Indy 10 UdpClient и Open Sound Control - PullRequest
       146

Indy 10 UdpClient и Open Sound Control

0 голосов
/ 01 ноября 2019

Чтобы управлять звуковым микшером Behringer X32 , мне нужно отправить сообщение OSC, например /ch/01/mix/fader ,f .3, чтобы переместить фейдер на 30%. Микшер, согласно протоколу OSC, ожидает, что .3 появится как строка из 4 символов - в шестнадцатеричном формате это 3E 99 99 9A. Поэтому задействованы специальные символы.

TIdUDPClient задается символами для 3E 99 99 9A, но отправляет 3E 3F 3F 3F. Точно так же .4 хочет быть 3E CC CC CD, но отправляется 3E 3F 3F 3F.

Когда вы набираете .5 и выше, все снова работает, так как символы ниже 3F. Например, .6 должно быть 3F 19 99 9A и выглядит как 3F 19 3F 3F.

Очевидно, что Берингер просматривает только первые два символа.

Я использую Delphi Rio с распространяемой версией Indy 10 . Я могу создать модуль в Lazarus с Lnet , который работает отлично. Но мое основное приложение в Delphi, где мне нужна эта способность. Как видите, я пробовал несколько разных способов с одним и тем же нерабочим результатом.

Как отправить правильные символы?

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;

ОБНОВЛЕНИЕ :

Система не позволила бы мне добавить это как ответ, так что ...

Спасибо, Реми. По крайней мере, что касается программного симулятора X32, добавление 8-битной кодировки текста дает правильный ответ. Мне придется подождать до завтра, чтобы проверить настоящий микшер в театре. Массив байтов мог бы быть лучше, если бы мы контролировали оба конца связи. Как это, я не могу изменить X32, и он хочет получить дополненную строку (в шестнадцатеричном формате: 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 CCCD) для текстовой строки "/ ch / 01 / mix / fader, f .4". Документация сообщений, на которые отвечает X32, представляет собой длинную таблицу похожих сообщений с различными параметрами. например, "/ ch / 01 / mix / mute on", "/ bus / 1 / dyn / ratio, i 2" и т. д. Это все в соответствии с протоколом Open Sound Control.

Как всегда,Вы - окончательный источник мудрости Инди, так что, спасибо. Я отредактирую это примечание после моих результатов с фактическим устройством.

ОБНОВЛЕНИЕ :

Подтверждено, что добавление 8-битной кодировки текста в команду Send работает с X32. Ура! В результате этого возникает пара вопросов:

  1. Является ли одна отправляющая конструкция предпочтительнее другой?

  2. Где я должен был прочитать / узнать большеоб этих деталях Indy?

1 Ответ

0 голосов
/ 02 ноября 2019

3F является символом ASCII '?'. Вы видите, что этот символ отправляется, когда символ Unicode кодируется в байтовую кодировку, которая не поддерживает этот символ Unicode. Например, кодировка текста Indy по умолчанию US-ASCII , если не указано иное (через переменную GIdDefaultTextEncoding в блоке IdGlobal.pas или через различные свойства класса или параметры метода), а US-ASCII делаетне поддерживает символы Unicode> U + 007F.

Кажется, что вы имеете дело с двоичным протоколом, а не с текстовым протоколом, так почему вы используете строки для создания его сообщений? Я думаю, что байтовые массивы будут иметь больше смысла.

По крайней мере, попробуйте использовать 8-битное кодирование текста Indy (через функцию IndyTextEncoding_8Bit() в модуле IdGlobal.pas) для преобразования символов Unicode U + 0000..U + 00FF до байтов 0x00..0xFF без потери данных, например:

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