firemonkey将mp3流转换为十六进制并反向

时间:2018-12-06 16:35:27

标签: delphi firemonkey delphi-10.2-tokyo

我尝试将音频从移动麦克风保存到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' );

运作良好。

更新项目概念:

enter image description here 硬件发送器在串行端口上从手机获取406十六进制字符并将其传输到第二个设备,然后接收器将十六进制字符串传递到第二个手机,第二个电话必须加入字符串并将其转换为可听见的声音。 / p>

base64的示例输出,用于流传输并将流保存到文件

sample mp3 file

1 个答案:

答案 0 :(得分:3)

首先,让我回答您的第一个问题

如何在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;

您可能会考虑的事情

在数据传输期间,某些字节可能会更改或丢失。有时将不会接收到整个数据包。根据您的要求,您的应用程序可能需要一些保护以防止此类错误。