Using MIDIPacketList in Fast

I am looking at some examples of midi output using core midi.

In particular, this question

and this

I have code that works based on these objects in objC, and now I want to try to translate this to fast.

the line that I least understand is this: MIDIPacketList* pktList = (MIDIPacketList*) pktBuffer;

I read this as a declaration of a pktlist pointer of type MIDIPacketList and assigned it a pktBuffer value other than a type of MIDIPacketList

I am new to C and objC, and that makes no sense to me.

MIDIPacketList is the structure defined here :

how does it make sense to use bytearray for the MIDIPacketList structure type and what is it trying to achieve? I assume that he is trying to determine the size of the package list, but why should we do this, and how is it anyway? why is this not enough to do this with MIDIPacketListAdd, how does this happen over several lines?

here is my attempt in the midi output class in swift - can anyone see what is going wrong? this code does not give errors in Xcode until it is launched. I have a working version of this in objC, but I cannot get the size of the package list defined in swift. (at least I think the problem)

 import Foundation import CoreMIDI class MidiOutClass { var midiClient = MIDIClientRef() var midiSource = MIDIEndpointRef() func openOutput() { MIDIClientCreate("MIDI client", nil, nil, &midiClient) MIDISourceCreate(midiClient, "MIDI Source",&midiSource) println("midi out opened")//should only do this if successful } func noteOn(channel: Int, note: Int, velocity:Int) { midisend((0x90+channel), note: note, value: velocity) } func polyAfter(channel: Int, note: Int, value:Int) { midisend((0xA0+channel), note: note, value: value) } func noteOff(channel: Int, note: Int) { midisend((0x90+channel), note: note, value: 0 ) } func midisend(status:Int, note: Int, value:Int) { var packet: UnsafeMutablePointer<MIDIPacket> = nil //var buffer = [Byte](count:1024, repeatedValue: 0) //this is the array I'm trying to use in a similar way to the obj C. var packetList: UnsafeMutablePointer<MIDIPacketList> = nil let midiDataToSend:[Byte] = [Byte(status), Byte(note), Byte(value)]; packet = MIDIPacketListInit(packetList); packet = MIDIPacketListAdd(packetList, 1024, packet, 0, 3, midiDataToSend); if (packet == nil ) { println("failed to send the midi.") } else { MIDIReceived(midiSource, packetList) println("sent some stuff") } } }//end MidiOutClass 
+5
source share
3 answers

I found an answer on this

the byte array in objC version is a nasty hack to allocate some memory for the package list

here is my revised code that now works.

  func midisend(status:Int, note: Int, value:Int) { var packet = UnsafeMutablePointer<MIDIPacket>.alloc(1) var packetList = UnsafeMutablePointer<MIDIPacketList>.alloc(1) let midiDataToSend:[Byte] = [Byte(status), Byte(note), Byte(value)]; packet = MIDIPacketListInit(packetList); packet = MIDIPacketListAdd(packetList, 1024, packet, 0, 3, midiDataToSend); if (packet == nil ) { println("failed to send the midi.") } else { MIDIReceived(midiSource, packetList) println("sent some stuff") } packet.destroy() //packet.dealloc(1) packetList.destroy() packetList.dealloc(1) } 

However, a commented dealloc seems unnecessary, I'm not quite sure why yet. Does MIDIReceived Help?

If anyone has a better solution - perhaps without using pointers, submit it!

+5
source

I also used the above procedure to send MIDI commands from my application to internal background synthesizers such as iMini, Z3TA +, Sunrizer, etc., but I could not get rid of memory leaks. There are no dangerous pointers and distributions in this version. It works without memory leaks.

 static var z: UInt8 = 0 // initalize tuple with 256 x this UInt8 value: // Silly: why not an array instead of this.. a tuple is needed.. length must be exact 256.. // Don't know no other way to create a tuple with 256 elements... var midiDataTuple = (z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z) // use the above tuple in MIDIPacket func midiSend(status: Int, val1: Int, val2 :Int) { var midipacket = MIDIPacket() midipacket.timeStamp = 0 midipacket.length = 3 midipacket.data = midiDataTuple //<-= midipacket.data.0 = UInt8(status) midipacket.data.1 = UInt8(val1 ) midipacket.data.2 = UInt8(val2 ) var midipacketlist = MIDIPacketList(numPackets: 1, packet: midipacket) MIDIReceived(midiSource, &midipacketlist) } ////////////////////////////////////////////////////////////// func noteOn(soundNr: Int, note: Int, velocity:Int) { let chan = midiChannelForSoundNr[soundNr] midiSend((0x90 + chan), val1: note, val2: velocity) notesPlaying[chan][note] = true } 

tested.

0
source

That's how I ended up. I used the byte buffer example that was found in various C / ObjC examples online, but I found that I needed to allocate a bit more space for the MIDIPacketList structure itself.

A MidiEvent is just an array of UInt8. For ordinary MIDI events, it has a length of 3 bytes: (status, data, data).

 /// A UInt8 array, usually 3 bytes long public typealias MidiEvent = [UInt8] extension MIDIPacketList { init(midiEvents: [MidiEvent]) { let timestamp = MIDITimeStamp(0) // do it now let totalBytesInAllEvents = midiEvents.reduce(0) { total, event in return total + event.count } // Without this, we'd run out of space for the last few MidiEvents let listSize = sizeof(MIDIPacketList) + totalBytesInAllEvents // CoreMIDI supports up to 65536 bytes, but in practical tests it seems // certain devices accept much less than that at a time. Unless you're // turning on / off ALL notes at once, 256 bytes should be plenty. assert(totalBytesInAllEvents < 256, "The packet list was too long! Split your data into multiple lists.") // Allocate space for a certain number of bytes let byteBuffer = UnsafeMutablePointer<UInt8>.alloc(listSize) // Use that space for our MIDIPacketList let packets = UnsafeMutablePointer<MIDIPacketList>(byteBuffer) var packet = MIDIPacketListInit(packets) midiEvents.forEach { event in packet = MIDIPacketListAdd(packets, listSize, packet, timestamp, event.count, event) } self = packets.memory // copy the MIDIPacketList data into self byteBuffer.dealloc(listSize) // release the manually managed memory } } 

So, if you just send one MIDI note, it will look something like this. This example will send a NoteOn message to middle C on channel 1 at a rate of 100. You should use helper functions to create these MidiEvents, not hard code them;)

 var packets = MIDIPacketList(midiEvents: [[0x90, 60, 100]]) MIDISend(clientOutputPort, destination, &packetList) 
0
source

Source: https://habr.com/ru/post/1205219/


All Articles