I’m just implementing support for the MIDI keyboard under iOS – mean you can connect MIDI keyboards (I’m using MIDITECH GARAGEKEY Mini) connected via the Apple iPad Camera Connection Kit.
The keyboard works perfect, you just plug it into the iPhone or iPad and it works. As the keyboard doesn’t have any additional led diode it has really low power consumption.
From the free software I found only GarageBand from Apple to be working with the keys.
At my application the keyboards can be easily implemented via the CoreMIDI (here is link to download my implementation for Delphi).
The code to read is very simple (it’s based on this code).
var aresult:OSStatus; inputMIDIClient:MIDIClientRef; inputSrc,source:MIDIEndpointRef; inputPort:MIDIPortRef; lastError:string; i,ci:Integer; begin aresult:= MIDIClientCreate(CFSTR('MIDI client'), nil, nil, inputMIDIClient); //note the use of "self" to send the reference to this document object aresult:= MIDIDestinationCreate(inputMIDIClient, CFSTR('Virtual port'), MyMIDIReadProcInput, nil, inputSrc); //and again here aresult:= MIDIInputPortCreate(inputMIDIClient, CFSTR('Input'), MyMIDIReadProcInput, nil, inputPort); if aresult<>0 then lastError:=lastError+'Cant create Input '+IntToStr(aresult); i := MIDIGetNumberOfSources(); if (inputPort<>nil) and (i>0) then for ci := 0 to i-1 do begin source:= MIDIGetSource(ci); if (source<>nil) then begin // inputPort aresult:=MIDIPortConnectSource(inputPort, source, nil); if aresult<>0 then lastError:=lastError+'Cant link the device '+IntToStr(aresult); end; end; end;
Then the keys are read at function MyMIDIReadProcInput.
procedure MyMIDIReadProcInput(pktlist: MIDIPacketListRef; readProcRefCon: pointer; srcConnRefCon: pointer); cdecl; var packet:MIDIPacketRef; ci,c2:integer; note:integer; midiStatus,midiCommand:Byte; begin packet:=@pktList.packet; for ci := 0 to pktlist.numPackets-1 do begin c2:=0; while c2<packet.length-2 do begin midiStatus:= packet.data[c2]; midiCommand:= midiStatus shr 4; note:= packet.data[c2+1] and $7F; if (midiCommand = $09) then begin //Key DOWN end else if (midiCommand = $08) then begin // Key UP end; c2:=c2+3; end; {$IF defined(CPUARM) or defined(CPUARM64)} packet:=@packet.data[packet.length]; packet:=pointer((UIntPtr(packet)+3) and not 3); {$ELSE} packet:=@packet.data[packet.length]; {$ENDIF} end; end;
Please note the while cycle when reading data from packet.data. This is something I has figured out my self and the other resources have here a mistake.
The data.length is usually 3 bytes. But if you manage to press more than one key at the moment (it’s more hard than it’s sounds) you will not get more messages or more MIDIPackets. You will get more data at the packet.data and the packet.length will be multiplied by 3.
Also note that the function MyMIDIReadProcInput is called at separated thread. So for example you can’t write data to a string that is readed by other part of the application – the application will then freeze.
Leave a Reply