8

我有一组简短的 WAV 文件,我想使用各种数字信号处理算法在 Java 中处理这些文件。为此,我需要获取一个 int 值样本数组,以 11025 Hz 帧速率编码。

源文件有几种不同的采样率,包括 11025 Hz 和 44100 Hz。这是我试图用来阅读它们的代码:

// 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 Hz 帧速率,我得到的样本数量是 11025 Hz 帧速率的四倍。我希望生成的样本数组使用 11025 Hz 帧速率,而不考虑源文件的帧速率。在读取 AudioInputStream 时,我尝试强制 Java 为我转换帧速率,但出现类似于以下异常的异常:

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)

我阅读了 Java Sound API 教程:http: //java.sun.com/docs/books/tutorial/sound/converters.html。Java Sound API 似乎不支持我的操作系统(Windows 7)的这种转换。而且我想避免对任何外部库的依赖。有什么办法可以自己进行采样率转换吗?

4

2 回答 2

7

对于 > 11025 Hz 的采样率,您需要进行下采样,这是一个两阶段的过程。首先,您需要低通滤波器以满足 Nyquist 标准,然后您可以抽取,例如对于 44.1 kHz 采样率数据,您需要使用截止频率为 5.5 kHz 的低通滤波器,然后您可以丢弃 3 个4:1 下采样率的每 4 个样本。对于要支持的每个下采样率,您都需要一个不同的过滤器。

于 2010-02-16T23:33:50.410 回答
6

我相信接受的答案回答了另一个问题——它解决了同样的问题(对音频进行下采样),但以另一种方式(手动而不是使用 java 声音 API)。我有同样的事情并深入研究它。

这样做的正确方法(或 java 声音 API 方法)确实是(如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 文件后,一切正常(只是一个额外的警告:如果您想同时更改通道数和采样率,仍然不支持一步)。

于 2012-02-13T18:55:07.547 回答