Преобразование частоты дискретизации на лету при чтении файла WAV в массив образцов с помощью Java - PullRequest
8 голосов
/ 16 февраля 2010

У меня есть коллекция коротких WAV-файлов, которые я хотел бы обработать на Java, используя различные алгоритмы цифровой обработки сигналов. Для этого мне нужно получить массив значений типа int, закодированных с частотой кадров 11025 Гц.

Исходные файлы имеют несколько разных частот дискретизации, включая 11025 Гц и 44100 Гц. Вот код, который я пытаюсь использовать, чтобы прочитать их:

// read the WAV file
FileInputStream fileInputStream = new FileInputStream(new File("test.wav"));
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileInputStream );

// copy the AudioInputStream to a byte array called buffer
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] data = new byte[4096];
int tempBytesRead = 0;
int byteCounter = 0;
while ((tempBytesRead = audioInputStream.read(data, 0, data.length)) != -1) {
  bos.write(data, 0, tempBytesRead);
            byteCounter += tempBytesRead;
}
bos.close();
byte[] buffer = bos.toByteArray();

AudioFileFormat audioFileFormat = new AudioFileFormat(AudioFileFormat.Type.WAVE, audioInputStream.getFormat(), (int)audioInputStream.getFrameLength());

// get the resulting sample array
int[] samples = new int[audioFileFormat.getFrameLength()];
for (int i = 0; i < samples.length; i++) {
  samples[i] = getSampleValue(i); // the getSampleValue method reads the sample values from the "buffer" array, handling different encoding types like PCM unsigned/signed, mono/stereo, 8 bit/16 bit
}

// RESULT: the "samples" array

Проблема в том, что код неправильно обрабатывает разные частоты дискретизации. Таким образом, для частоты кадров 44100 Гц я получаю в четыре раза больше выборок, чем для частоты кадров 11025 Гц. Я хотел бы, чтобы полученный массив образцов использовал частоту кадров 11025 Гц, независимо от частоты кадров исходного файла. Я пытался заставить Java преобразовать частоту кадров для меня при чтении AudioInputStream, но я получаю исключение, подобное следующему:

java.lang.IllegalArgumentException: Unsupported conversion: PCM_SIGNED 11025.0 Hz, 16 bit, mono, 2 bytes/frame, 44100.0 frames/second, little-endian from PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian
    at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:955)

Я прочитал учебник по API Java Sound: http://java.sun.com/docs/books/tutorial/sound/converters.html. Кажется, что API Java Sound не поддерживает такого рода преобразование моей операционной системы (Windows 7). И я хотел бы избежать зависимости от любых внешних библиотек. Есть ли способ сделать преобразование частоты дискретизации самостоятельно?

Ответы [ 2 ]

7 голосов
/ 17 февраля 2010

Для частот дискретизации> 11025 Гц вам необходимо уменьшить частоту дискретизации, что является двухэтапным процессом. Сначала нужно выполнить фильтр нижних частот, чтобы удовлетворить критерию Найквиста, а затем вы можете уничтожить, например, для данных с частотой дискретизации 44,1 кГц вам потребуется фильтр нижних частот с частотой среза 5,5 кГц, а затем вы можете выбросить 3 из каждых 4 выборок для коэффициента понижающей дискретизации 4: 1. Вам потребуется отдельный фильтр для каждого коэффициента понижающей дискретизации, который вы хотите поддерживать.

6 голосов
/ 13 февраля 2012

Я полагаю, что принятый ответ отвечает на другой вопрос - он решает ту же проблему (понижающую дискретизацию аудио), но другим способом (вручную вместо использования java sound API). У меня было то же самое, и я закопался в него.

Правильный способ (или способ Java-звука) сделать это действительно (как предложено в http://docs.oracle.com/javase/tutorial/sound/converters.html)

AudioFormat outDataFormat = new AudioFormat((float) 8000.0, (int) 8, (int) 1, true, false);
AudioInputStream lowResAIS = AudioSystem.getAudioInputStream(outDataFormat, inFileAIS);

Проблема в том, что стандартный java не поставляется с кодом ресэмплирования (или даже стерео-моно) (или, по крайней мере, не в этой части кода - см. http://www.jsresources.org/faq_audio.html#convert_sample_rate).

Страницы jsresources также указывают на ответы: простая установка 2 плагинов делает свое дело. Проще всего установить эти плагины в каталоге Extensions, в OSX Lion это поможет (если у вас есть wget):

wget http://www.tritonus.org/tritonus_share-0.3.6.jar -O /Library/Java/Extensions/tritonus_share-0.3.6.jar
wget http://www.tritonus.org/tritonus_remaining-0.3.6.jar -O /Library/Java/Extensions/tritonus_remaining-0.3.6.jar

После добавления этих 2-х jar-файлов все заработало (только одно дополнительное предупреждение: если вы хотите изменить и количество каналов, и частоту дискретизации, это все равно не поддерживается как один шаг).

...