FireMonkey конвертировать MP3 поток в шестнадцатеричный и обратный - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь сохранить звук с мобильного микрофона в поток Tmemorystream, а затем преобразовать его в шестнадцатеричный формат с помощью этой функции:

function StreamToHexStr(AStream: TStream): string;
const
 HexArr: array[0..15] of char =
 ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
var
 AByte: Byte;
 i: Integer;
begin
 SetLength(Result, AStream.Size * 2);
 AStream.Position := 0;
 for i := 0 to AStream.Size - 1 do
 begin
   AStream.ReadBuffer(AByte, SizeOf(AByte));
   Result[i * 2 + 1] := HexArr[AByte shr 4];
   Result[i * 2 + 2] := HexArr[AByte and $0F];
 end;
end;

на выходе получается шестнадцатеричная строка

после передачи аавторое устройство, мне нужно изменить шестнадцатеричный код на поток Tmemorystream и воспроизвести его с помощью этой функции:

Stream := TMemoryStream.Create;
try
  Writer := TBinaryWriter.Create(Stream);
  try
    Writer.Write(TEncoding.UTF8.GetBytes(ReciavedSTR));
  finally
    Writer.Free;
  end;
  Stream.SaveToFile( TPath.GetSharedMoviesPath()+'/record2.mp3' );

, но record2.mp3 не воспроизводится, и он просто содержит преобразованную шестнадцатеричную строку

что не так с моим кодом?

для простого теста, когда я сохраняю записанный поток в файл с этим кодом

FOutputStream.SaveToFile( TPath.GetSharedMoviesPath()+'/record.mp3' );

он работает хорошо.

updateКонцепция проекта:

enter image description here аппаратный передатчик получает 406 шестнадцатеричных символов с мобильного телефона через последовательный порт и передает их на второе устройство, затем получатель передает шестнадцатеричную строку на второй мобильный телефон,второй телефон должен соединить строки и преобразовать их в слышимый звук.

пример вывода base64 для потоковой передачи и сохранения в файл

образец mp3 файла

1 Ответ

0 голосов
/ 06 декабря 2018

Сначала позвольте мне ответить на ваш первоначальный вопрос

Как преобразовать поток в base16 и обратно (он же ASCII-HEX).

Ваш код для преобразования в base16 здесь правильныйявляется по существу равной версией:

function StreamToHexStr(const AStream: TStream): String;
const
  cMap : array[0..15] of Char = (
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
    'A', 'B', 'C', 'D', 'E', 'F');
var
  lData: Byte;
  lPos: Integer;
begin
  Setlength(Result, AStream.Size * 2);
  AStream.Position := 0; 
  lPos := Low(Result);
  while AStream.ReadData(lData) = sizeof(lData) do begin
    Result[lPos]     := cMap[lData shr 4];
    Result[lPos + 1] := cMap[lData and $0F];
    Inc(lPos, 2);
  end;
end;

Чтобы преобразовать строку обратно в поток, попробуйте следующее:

procedure HexStrToStream(const AString: String; AStream: TStream);
const
  // Mapping vom ASCII-Code to value
  cMap: array['0'..'F'] of Byte  = (
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,  // $30..$39 / '0'..'9'
    100, 100, 100, 100, 100, 100, 100, //  $3A..$40
    10, 11, 12, 13, 14, 15); // $41..$46 / 'A'..'F'
var
  lPos: Integer;
begin
  lPos := Low(AString);
  while lPos < High(AString) do begin
    AStream.WriteData(UInt8(cMap[AString[lPos]] shl 4 + cMap[AString[lPos + 1]]));
    Inc(lPos, 2);
  end;
end;

Чтобы использовать этот код, просто выполните:

Base16String := StreamToHexStr(MP3Stream);

на отправителе и на получателе выполните:

lRecvStream := TMemoryStream.Create();
try
  HexStrToStream(Base16RecvString, RecvStream);
  lRecvStream.SaveToFile('Record.mp3');
finally
  lRecvStream.Free();
end;

Как сделать то же самое для base64

С TMemoryStream на стороне отправителя вы просто делаете:

lString := TNetEncoding.Base64.EncodeBytesToString(lInStream.Memory, lInStream.Size);

и на принимающей стороне вы используете TBytesStream (который является потомком TMemoryStream):

lRecvStream := TBytesStream.Create(TNetEncoding.Base64.DecodeStringToBytes(lString));
try
  lRecvStream.SaveToFile('Record.mp3');
finally
  lRecvStream.Free();
end;

Вещи, которые вы можете учитывать

Во время передачи данных некоторые байтыможет быть изменен или потерятьсяИногда целые пакеты не будут получены.В зависимости от ваших требований вашему приложению может потребоваться защита от таких ошибок.

...