firemonkey 将 mp3 流转换为十六进制和反向
firemonkey convert mp3 stream to hex and reverse
我尝试将音频从 mobile microphone 保存到 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 [=10=]F];
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' );
效果很好。
更新项目概念:
硬件发送器从串口上的手机phone获取406个十六进制字符并将其传输到第二个设备,然后接收器将十六进制字符串传递给第二个手机phone,第二个phone必须加入字符串并将它们转换为可听到的声音。
base64 的示例输出流和流保存到文件
首先,让我回答你最初的问题
如何将流与 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 [=10=]F];
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, // .. / '0'..'9'
100, 100, 100, 100, 100, 100, 100, // A..
10, 11, 12, 13, 14, 15); // .. / '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;
您可能会考虑的事项
在数据传输过程中,一些字节可能会被更改或丢失。有时不会收到整个数据包。根据您的要求,您的应用程序可能需要针对此类错误采取一些保护措施。
我尝试将音频从 mobile microphone 保存到 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 [=10=]F];
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' );
效果很好。
更新项目概念:
base64 的示例输出流和流保存到文件
首先,让我回答你最初的问题
如何将流与 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 [=10=]F];
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, // .. / '0'..'9'
100, 100, 100, 100, 100, 100, 100, // A..
10, 11, 12, 13, 14, 15); // .. / '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;
您可能会考虑的事项
在数据传输过程中,一些字节可能会被更改或丢失。有时不会收到整个数据包。根据您的要求,您的应用程序可能需要针对此类错误采取一些保护措施。