Как объединить два AudioInputStream?

Формат файла «PCM_SIGNED 44100,0 Гц, 16 бит, стерео, 4 байта/кадр, обратный порядок байтов», и я хочу добавить их вместе, усиливая один из двух файлов. Я планирую прочитать два wav-файла, поместить их в два экземпляра audioinputstream, затем сохранить экземпляры в два массива byte[], манипулировать массивами и получить возврат в виде другого экземпляра audioinputstream.

Я провел много исследований, но не получил хороших результатов. Я знаю, что это класс с сайта www.jsresources.org, смешивающий два аудиовходных потока, но он не позволяет мне изменять ни один из двух потоков перед микшированием, в то время как я хочу уменьшить один из потоков перед их микшированием. Что ты думаешь я должен сделать?


person Zhu Li    schedule 21.09.2015    source источник
comment
Я знаю, что это класс с сайта www.jsresources.org, смешивающий два аудиовходных потока, но он не позволяет мне изменить ни один из двух потоков перед микшированием, в то время как я хочу уменьшить один из потоков перед их микшированием. Объедините этот источник с AmplitudeConverter для одного из потоков.   -  person Andrew Thompson    schedule 21.09.2015


Ответы (1)


Для этого вы можете преобразовать потоки в данные PCM, умножить канал, громкость которого вы хотите изменить, на желаемый коэффициент, сложить данные PCM из результатов вместе, а затем преобразовать обратно в байты.

Чтобы получить доступ к AudioStreams побайтно, ознакомьтесь с первым фрагментом расширенного кода в разделе «Учебники по Java» на Использование файлов и преобразователей форматов. Это показывает, как получить массив звуковых байтовых данных. Есть комментарий следующего содержания:

  // Here, do something useful with the audio data that's 
  // now in the audioBytes array...

На этом этапе переберите байты, конвертируя в PCM. Должен работать набор команд, основанный на следующем:

for (int i = 0; i < numBytes; i += 2)
{
    pcmA[i/2] = audioBytesA[i] & 0xff ) | ( audioBytesA[i + 1] << 8 );
    pcmB[i/2] = audioBytesB[i] & 0xff ) | ( audioBytesB[i + 1] << 8 );
}

В приведенном выше примере audioBytesA и audioBytesB — это два входных потока (имена основаны на коде из примера), а pcmA и pcmB может быть либо массивом int, либо массивом short, содержащим значения, попадающие в диапазон short. Возможно, лучше всего сделать массивы pcm числом с плавающей запятой, так как вы будете выполнять некоторые математические операции, которые приведут к дробям. Использование float, как в приведенном ниже примере, увеличивает точность только на один разряд (округление лучше, чем при использовании int), и int будет работать быстрее. Я думаю, что использование поплавков чаще используется, если аудиоданные нормализуются для использования с дополнительной обработкой.

Оттуда лучший способ изменить громкость — умножить каждое значение PCM на одну и ту же сумму. Например, чтобы увеличить громкость на 25%,

pcmA[i] = pcmA[i] * 1.25f; 

Затем добавьте pcmA и pcmB и снова преобразуйте их в байты. Вы также можете добавить минимальные или максимальные функции, чтобы объем и слияние не превышали значений, которые могут поместиться в 16-битном формате.

Я использую следующее для преобразования обратно в байты:

for (int i = 0; i < numBytes; i++)
{
   outBuffer[i*2] = (byte) pcmCombined[i];
   outBuffer[(i*2) + 1] = (byte)((int)pcmCombined[i] >> 8 );            
}

Выше предполагается, что pcmCombined[] является массивом с плавающей запятой. Код преобразования может быть немного проще, если это массив short[] или int[].

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

person Phil Freihofner    schedule 21.09.2015