Java - 将 16 位有符号 pcm 音频数据数组转换为双数组

Dan*_*elY 5 java audio bytebuffer bytearray

我正在做一个涉及音频处理的项目。

我正在从文件中提取一段音频,然后想对其进行一些处理。问题是我将音频数据作为字节数组获取,而我的处理是在双数组上(以及后来在复杂数组上......)。

我的问题是如何将收到的字节数组正确转换为双数组继续?

这是我的输入代码:

AudioFormat format = new AudioFormat(8000, 16, 1, true, true);
AudioInputStream in = AudioSystem.getAudioInputStream(WAVfile);
AudioInputStream din = null;
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
                        8000,
                        16,
                        1,
                        2,
                        8000,
                        true);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
TargetDataLine fileLine = AudioSystem.getTargetDataLine(decodedFormat);
fileLine .open(format);
fileLine .start();

int numBytesRead;
byte[] targetData = new byte[256]; // (samplingRate / 1000) * 32ms

while (true) {
    numBytesRead = din.read(targetData, 0, targetData.length);

    if (numBytesRead == -1) {
        break;
    }

    double[] convertedData;
    // Conversion code goes here...

    processAudio(convertedData);
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经研究了围绕本网站和其他网站的不同问题的不同答案。我尝试使用 ByteBuffer 和位转换,但它们都没有给我看起来正确的结果(我的另一个成员在 Python 中的同一个文件上做了同样的事情,所以我有一个参考结果应该是什么大约是……

我错过了什么?如何正确地将字节转换为双精度数?如果我想在targetData中只捕获文件的32ms,targerData的长度应该是多少?那么convertedData 的长度是多少?

提前致谢。

Krz*_*cki 0

首先,了解示例所使用的格式AudioFormat.Encoding.PCM_SIGNEDBigEndian然后了解 java int(该数字的格式)。然后使用二进制移位运算符正确移动字节>>,并且<<(将其中一个字节向左移动 8 位 - 以便它将表示整数的高位字节 - 需要移动的字节取决于这是小端还是大端,Big Endian 意味着包含更重要部分的字节位于字节数组 array 的末尾 - 因此您应该将数组中的第二个字节向左移动 8 位),然后使用+or|运算符将结果求和到一个int变量中,然后您需要除以 int 以获得您想要的双精度范围。假设您想要范围 -1...+1 那么您应该将整数除以等于 32768 的双精度数。

我想在这里发布代码,但我现在没有。这是我遵循的指示。

例如,我已经使用以下方法成功获取了立体声音频数据:

AudioFormat format = new AudioFormat(8000, 16, 2, true, false);
Run Code Online (Sandbox Code Playgroud)

然后通过以下方式转换它们:

   int l = (short) ((readedData[i*4+1]<<8)|readedData[i*4+0]);
   int r = (short) ((readedData[i*4+3]<<8)|readedData[i*4+2]);
Run Code Online (Sandbox Code Playgroud)

所以你的缩放比例应该是:

   double scaledL = l/32768d;
   double scaledR = r/32768d;
Run Code Online (Sandbox Code Playgroud)