首页 > 解决方案 > 需要将音频字节 [] 编码为要通过 JSON 传输的字符串。将从 C# 编码和发送,并在 Java 中读取为音频字节

问题描述

因此,我发现了许多类似的问题,并且似乎归结为对您使用的编码格式的看法不同。我已经尝试过 Base64 和 UTF-8。当我使用 Base64 时,当我解码它们时,Java 端的字节似乎完全改变了,声音基本上只是静态噪声。然而,当我使用 UTF-8 时,我仍然可以听到其中的原始声音,但它非常失真和嘈杂,几乎听不见,但肯定仍然存在。我认为这是因为 UTF-8 没有许多音频字节的字符,所以在编码和解码过程中丢失了很多字符,这就是我尝试 base64 的原因,但这会导致音频更差。我正在流式传输实时麦克风音频,所以我没有一个音频文件,我可以在它到达 Java 后将其与编码类型的字节进行比较。

整个想法是我想将音频字节打包在 JSON 字符串中以从 C# 发送到 Java,而不是单独流式传输原始音频字节(效果很好)。我想这样做的原因是因为我也希望能够传达其他非音频内容,并且也计划为此使用 JSON。

有没有更好的方法将音频编码为可以在 JSON 中使用的字符串?或者,无论您尝试将它们编码为字符串,音频字节基本上都会导致数据丢失?

对于我的 base64 尝试,在 C# 中我使用:

Convert.ToBase64String(byteBuffer);

在Java方面,我尝试使用解码

DatatypeConverter.parseBase64Binary(audioBufferData);

BASE64Decoder decoder = new BASE64Decoder();                            
byte[] bufferBytes = decoder.decodeBuffer(audioBufferData);

对于 UTF-8,在 C# 中我使用了

Encoding.UTF8.GetString(byteBuffer);

在Java中

audioBufferData.getBytes("UTF-8");

我在 Unity 中使用名为“NatMic”的资产来获取实时麦克风输入。它给了我一个 float[] sampleBuffer,它被转换为字节,如下所示:

    var shortBuffer = new short[sampleBuffer.Length];
    var byteBuffer = new byte[Buffer.ByteLength(shortBuffer)];
    for (int i = 0; i < sampleBuffer.Length; i++)
        shortBuffer[i] = (short)(sampleBuffer[i] * short.MaxValue);
    Buffer.BlockCopy(shortBuffer, 0, byteBuffer, 0, byteBuffer.Length);

然后 byteBuffer 如上所述被编码并发送到服务器。如果我在不编码的情况下发送字节并在 Java 中使用 Little Endian 格式 SourceDataLine 直接播放它们,这听起来很完美,但是在编码为 base64 之后,我必须更改 SourceDataLine 的格式以期望 Big Endian 能够正确播放。由于其他原因,我必须保持 Little Endian 顺序。

标签: javac#jsonaudioencode

解决方案


Base64 将对您直接提供的字节进行编码,不会引起问题。最有可能的问题是字节顺序,每一端都不同。从和到字节的转换需要在两端相同。您还没有展示如何从 16 位音频数据中获取字节缓冲区,因此无法建议对该部分进行任何更正。

默认情况下,Java 是大端,而 .NET 采用任何底层架构,通常是小端,因此在某些时候需要进行交换。JavaByteBuffer确实支持设置字节顺序,所以这可能会有所帮助。


推荐阅读