В Java принимайте потоковую передачу аудиоданных из приложения C # через сокеты TCP и воспроизводите потоковую передачу по мере ее поступления - PullRequest
0 голосов
/ 02 мая 2019

У меня есть некоторые необработанные данные PCM для аудио в приложении C #.Мне нужно получить его в приложение Java и играть как аудио.

В качестве первого шага я хочу, чтобы приложение Java немедленно воспроизводило аудио во время его потоковой передачи (не сохраняя временный файл и не воспроизводя его, воспроизводя его по мере его получения).

У меня проблемы с форматированием аудиоданных PCM в C # и отправкой их в приложение Java.В настоящее время я использую для этого простую систему сокетов TCP, называя приложение C # (созданное в Unity) «клиентом», а приложение Java «сервером».

На клиенте Unity C # я использую NatMic для получения необработанных данных PCM для микрофона.Эта функция вызывается много раз в секунду при поступлении данных:

void IAudioProcessor.OnSampleBuffer(float[] sampleBuffer, int sampleRate, int channelCount, long timestamp)

У меня есть массив с плавающей запятой и два целых числа для описания аудиоданных.

Как упаковать эти данные какбайты для отправки на Java?

У меня настроен протокол TCP, в котором я могу отправлять байты в Java, и кажется, что он работает нормально, когда я тестирую простую отправку простых строк сообщений между клиентом и сервером.

Но когда я пытаюсь упаковать аудио и отправить его, он никогда не работает.Я всегда получаю сообщение об ошибке, подобное этому:

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream

Вот фрагмент кода на стороне Java о том, как я пытался воспроизвести звук на стороне Java в качестве теста (когда клиент подключается, я запускаю его один раз):

    inputStream = client.getInputStream();
    bInputStream = new BufferedInputStream(inputStream);
    Clip clip = AudioSystem.getClip();
    audioStream = AudioSystem.getAudioInputStream(bInputStream);
    clip.open(audioStream);
    clip.start();

Как мне упаковать float [], int и int для отправки на сервер Java, чтобы он распознал его как аудиопоток?

1 Ответ

1 голос
/ 02 мая 2019

Прежде всего, вам нужно будет выводить данные как SourceDataLine, а не Clip.Clip не может воспроизводиться, пока не получит весь звуковой файл.

Обычный план - прочитать строку ввода любым способом и преобразовать ее в нужный формат в цикле, вызывающем sdl.write.() метод.

Что-то в следующих строках должно работать, для входящих данных

while(playerRunning)
{
    readBuffer = getInputPCM();
    audioBytes = convertToFollowAudioFormat(readBuffer);
    sourceDataLine.write(audioBytes, 0, sdlBufferSize);
}

Если ваши входящие данные являются плавающими, в диапазоне от -1 до 1, и вы выводите вБазовый формат «Качество CD» Java (44100 fps, 16-битный, стерео, little-endian), тогда преобразование может выглядеть следующим образом:

for (int i = 0, n = buffer.length; i < n; i++)
{
    buffer[i] *= 32767;
    audioBytes[i*2] = (byte) buffer[i];
    audioBytes[i*2 + 1] = (byte)((int)buffer[i] >> 8 );
}
return audioBytes;

В зависимости от формы вашего PCM, вы можете иметьсделать немного больше или меньше.Например, если вы читаете целые или краткие значения в диапазоне от -32767 до 32767, то шаг умножения не требуется.

Чтобы получить SourceDataLine, выводящий аудиоформат "CD Quality" на аудио линию по умолчанию:

AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
                44100, 16, 2, 4, 44100, false);
Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
SourceDataLine sdl = (SourceDataLine)AudioSystem.getLine(info);

Что касается вашего метода getInputPCM, я предполагаю, что вы можете представлять только данные PCM в потоке, и нет необходимости в дальнейшем разборе.Если вы хотите выполнить задачу преобразования PCM в байты в C # перед отправкой, это также вполне допустимо.

Более подробно о различных выходных форматах написано в семпловом пакете учебника Java . AudioCue , который является своего рода суперподобным Clip.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...