Итак, я нашел много похожих вопросов, и, по-видимому, это сводится к разнице во мнениях относительно того, какой формат кодирования вы используете. Я пробовал как 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");
Я использую ресурс под названием «NatMic» в Unity для получения живого микрофона. Это дает мне 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 кодируется, как указано выше, и отправляется на сервер. Если я отправляю байты без кодирования и воспроизводю их напрямую в формате LittleDian SourceDataLine в Java, это звучит идеально, но после кодирования в base64 я должен изменить формат SourceDataLine, чтобы ожидать, что Big Endian будет воспроизводиться правильно. По другим причинам я должен поддерживать порядок Little Endian.