Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
OSC commands with numbers
#1
Trying to use Indy to send OSC (open sound control) messages to a Behringer X32 mixer. If the message is just text, it works fine. The issue is a message of the format "/ch/01/mix/fader ,f .3". The .3 needs to be sent as 4 bytes. What needs to go out is "3E 99 99 9A". What the idudpclient sends is "3E 3F 3F 3F". The same problem exists for .4 (3E CC CC CD vs. 3E 3F 3F 3F). Once you get to .5 and greater, things work again because the second byte is smaller. e.g. .5 = 3F 00 00 00 > 3F 00 00 00, .6 = 3F 19 99 9A > 3F 19 3F 3F).

I'm using Indy 10 and Delphi Rio. Here is the sending subroutine. I've commented out several different approaches, all of which give the same result.

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;


Any insight you can share would be welcome. Thank you.
..Dave
Reply
#2
(11-01-2019, 03:04 PM)davidbaxter Wrote: What the idudpclient sends is "3E 3F 3F 3F".

"3F" is the ASCII "?" character. That happens when a Unicode character is encoded to a byte encoding that doesn't support that Unicode character. For example, Indy's default text encoding is US-ASCII unless you specify otherwise (via the GIdDefaultTextEncoding variable in the IdGlobal.pas unit, or via various class properties or method parameters). US-ASCII does not support Unicode characters > U+007F.

It seems like you are dealing with a binary protocol, not a text protocol, so why are you using strings to create its messages? I would think byte arrays would make more sense.

At the very least, try using Indy's 8-bit text encoding (via the IndyTextEncoding_8Bit() function in the IdGlobal.pas unit) to convert Unicode characters <= U+00FF to bytes without data loss, eg:

Code:
B1 := ToBytes(OSCCommandStr, IndyTextEncoding_8Bit); // not ASCII or UTF8!
IdUDPClient2.SendBuffer(B1);

Code:
IdUDPClient2.Send(OSCCommandStr, IndyTextEncoding_8Bit); // not ASCII or UTF8!

Reply
#3
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.
Edit: 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: 1) Is one send construct preferred over the other? 2) Where should I have read/learned more about these details of Indy?
Thanks again.
Reply
#4
(11-02-2019, 02:39 AM)davidbaxter Wrote: 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.

UDP operates on bytes only, not on strings. Strings are transmitted as bytes. You don't need to change anything on the X32 to use byte arrays in your own code (case in point, your 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.

(11-02-2019, 02:39 AM)davidbaxter Wrote: 1) Is one send construct preferred over the other?

Not really. It just really depends on what you are sending - strings, or byte arrays.

(11-02-2019, 02:39 AM)davidbaxter Wrote: 2) Where should I have read/learned more about these details of Indy?

Experience, online tutorials that are floating around, maybe documentation too (though the docs are quite old - for instance, it predates the introduction of the IIdTextEncoding interface).

Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)