To control a Behringer X32 audio mixer, I have to send an OSC message like /ch/01/mix/fader ,f .3 to move a fader to 30%. The mixer, per the OSC protocol, is expecting the .3 to come in as a 4 character string - in hex it's 3E 99 99 9A. So special characters are involved.
TIdUDPClient is given the characters for 3E 99 99 9A, but it sends out 3E 3F 3F 3F. Likewise .4 wants to be 3E CC CC CD but 3E 3F 3F 3F is sent.
When you get up to .5 and greater, things work again as the characters are below 3F. For example, .6 should be 3F 19 99 9A and goes out as 3F 19 3F 3F.
Evidently the Behringer is only looking at the first two characters there.
I am using Delphi Rio with the Indy 10 version distributed with it. I can create a module in Lazarus with Lnet that works fine. But my main application is in Delphi where I need this ability. As you can see, I've tried several different ways with the same non-working result.
How do I send the proper characters?
procedure TCPForm1.OSCSendMsg;
var
OutValueStr: String;
I: Integer;
J: Tbytes;
B1: TIdbytes;
begin
If Length(CommandStr) > 0 then begin
OscCommandStr := PadStr(CommandStr); //convert CommandStr to OSC string
If TypeStr='' then OscCommandStr := OscCommandStr+','+#0+#0+#0;
If Length(TypeStr) = 1 then begin
If TypeStr='i' then Begin // Parameter is an integer
I := swapendian(IValue); //change to big endian
OscCommandStr := OscCommandStr+','+TypeStr+#0+#0+IntToCharStr(I);
OutValueStr := IntToStr(IValue);
end;
If TypeStr='f' then Begin // Parameter is a float (real)
I := swapendian(PInteger(@FValue)^); //typecast & change to big endian
//I := htonl(PInteger(@FValue)^); //typecast & change to big endian
//J := MakeOSCFloat(FValue);
OscCommandStr := OscCommandStr+','+TypeStr+#0+#0+IntToCharStr(I);
//OscCommandStr := OscCommandStr+','+TypeStr+#0+#0+char(J[0])+char(J[1])+char(J[2])+char(J[3]);
OutValueStr := FloatToStr(FValue);
end;
end;
//IdUDPClient2.Send(OSCCommandStr,IndyTextEncoding_UTF8);
//IdUDPClient2.Send(OSCCommandStr);
B1 := toBytes(OSCCommandStr);
IdUDPClient2.SendBuffer(B1);
if loglevel>0 then logwrite('OSC= '+ hexstr(OSCCommandStr));
Wait(UDPtime);
// if loglevel>0 then logwrite('OSC '+ OSCCommandStr);
end;
end;
function TCPForm1.IntToCharStr(I : Integer) : String;
var
CharStr : String;
MyArray: array [0..3] of Byte;
J: Integer;
begin
For J :=0 to 3 do MyArray[J] := 0;
Move(I, MyArray, 4); //typeset conversion from integer to array of byte
CharStr := '';
For J :=0 to 3 do //convert array of byte to string
CharStr := CharStr+char(MyArray[J]);
IntToCharStr := CharStr;
end;
UPDATE:
The system would not let me add this as an answer, so...
Thank you, Remy. At least as far as the X32 software simulator is concerned, adding the 8 bit text encoding gives the correct response. I'll have to wait until tomorrow to test on the actual mixer in the theater. A byte array might be better if we had control of both ends of the communication. As it is, I can't change the X32 and it wants to get a padded string (in Hex: 2F 63 68 2F 30 31 2F 6D 69 78 2F 66 61 64 65 72 00 00 00 00 2C 66 00 00 3E CC CC CD) for the text string "/ch/01/mix/fader ,f .4". The documentation of messages the X32 responds to is a long table of similar messages with different parameters. e.g. "/ch/01/mix/mute on", "/bus/1/dyn/ratio ,i 2", etc. This is all in accordance with the Open Sound Control protocol.
As always, you are the definitive source of Indy wisdom, so, thank you. I'll edit this note after my results with the actual device.
UPDATE:
Confirmed that the addition of 8 bit text encoding to the Send command works with the X32. Cheers! A couple questions as a result of this:
Is one send construct preferred over the other?
Where should I have read/learned more about these details of Indy?
ToBytes()example). I think you need to read up on the correlation between 8bit strings and 8bit bytes. They are the same data. You can use byte arrays to build up your OSC messages, especially for the portions that don't involve human-readable characters. Just something to consider... - Remy Lebeau