Необходимо закодировать аудио byte [] как строку для передачи через JSON. Будет закодирован и отправлен из C # и прочитан как аудио байты в Java - PullRequest
0 голосов
/ 23 мая 2019

Итак, я нашел много похожих вопросов, и, по-видимому, это сводится к разнице во мнениях относительно того, какой формат кодирования вы используете. Я пробовал как 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.

1 Ответ

0 голосов
/ 23 мая 2019

Base64 закодирует байты, которые вы дадите, напрямую и не вызовет проблем.Скорее всего, проблема заключается в порядке байтов, который отличается на каждом конце.Преобразование из и в байты должно быть одинаковым на обоих концах.Вы не показали, как вы получаете байтовый буфер из 16-битных аудиоданных, поэтому не можете предложить никаких исправлений к этой части.

По умолчанию Java имеет порядковый номер с прямым порядком байтов, тогда как .NET использует любую базовую архитектуру, как правило, с прямым порядком байтов, поэтому в какой-то момент требуется перестановка.ByteBuffer в Java поддерживает установку порядка байтов, чтобы это могло помочь.

...