Menu

#3 MIDI Sysex bug

open
nobody
None
5
2015-01-29
2010-07-22
Petrus
No

Hi,

today I saw that You have the Adrian Meyers SourceCode in use,
renamed to "DAV_MidiIO.pas". I found bugs some time ago:

1) length of Sysex String must be even.
Otherwise the String makes no sense.
=> throw exception

2) "aStream.Size-1" is wrong (I tested both issues and the following implementation works : )

procedure StrToSysExStream(const aString: string; const aStream: TMemoryStream);
const
cHex = '123456789ABCDEF';
var
i: integer;
lStr: string;
L: integer;
begin
// check on errors - added by BREAKOUTBOX 2009-07-30
L := length( aString);
if not (L mod 2 = 0) // as HEX every byte must be two chars long, for example '0F'
then raise EMidiDevices.Create( 'SysEx string corrupted')
else if l < 10 // shortest System Exclusive Message = 5 bytes = 10 hex chars
then raise EMidiDevices.Create( 'SysEx string too short');

lStr := StringReplace(AnsiUpperCase(aString), ' ', '', [rfReplaceAll]);
aStream.Size := Length(lStr) div 2; // ' - 1' removed by BREAKOUTBOX 2009-07-15
aStream.Position := 0;

for i:=1 to aStream.Size do
pchar(aStream.Memory)[i-1] :=
char(AnsiPos(lStr[ i*2 - 1], cHex) shl 4 + AnsiPos(lStr[i*2], cHex));
end;

On my system it didn't make sense to try to open a unassigned device.
The following code works:

procedure TMidiOutput.Send(const aDeviceINdex: integer; const aStatus,
aData1, aData2: byte);
var
lMsg: cardinal;
begin
// (do NOT) open if the device if not open

if not assigned(fDevices.Objects[ aDeviceIndex ])
then exit; // Open( aDeviceIndex); // Breakoutbox changed 2008-07-01

//lMsg := aStatus + (aData1 * $100) + (aData2 * $10000);
lMsg:= aStatus or (aData1 shl 8) or (aData2 shl 16); // better ?
MidiResult := midiOutShortMsg(GetHandle(aDeviceIndex), lMSG);
end;

Cheers,
Peter

Discussion


Log in to post a comment.