MP3文件在读取过程中变形

时间:2019-05-12 18:19:04

标签: java audio mp3 decode

我目前正在开发一个播放声音的应用程序。我使用Java Sound API实现了标准WAV文件的播放,没​​有问题,一切正常。现在,我也想添加对MP3的支持,但是我遇到了一个奇怪的问题:播放失真。我试图弄清楚自己在做错什么,如果能为您提供正确的指导,我将不胜感激。 我正在使用Mp3SPI(3)播放Mp3文件。

我已经尝试查看输出,并用从mp3中获得的输出记录了一个wav文件,然后比较了原始文件和记录文件的波形。事实证明,在记录的文件中,有许多采样为0或非常接近于0。较长的音调被打断,波形一直都返回零,然后跳回到波形在原始位置。

我这样打开文件:


private AudioInputStream mp3;
private AudioInputStream rawMp3;

private void openMP3(File file) {

// open the Audio INput Stream
    try {
    rawMp3 = AudioSystem.getAudioInputStream(file);
    AudioFormat baseFormat = rawMp3.getFormat();
    AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
              baseFormat.getSampleRate(),
              16,
              baseFormat.getChannels(),
              baseFormat.getChannels() * 2,
              baseFormat.getSampleRate(),
              false);
        mp3 = AudioSystem.getAudioInputStream(decodedFormat, rawMp3);
    } catch (UnsupportedAudioFileException | IOException ex) {
        Logger.getLogger(SoundFile.class.getName()).log(Level.SEVERE, null, ex);
    }
}

我读取Mp3文件的部分:

byte[] data = new byte[length];    
// read the data into the buffer
int nBytesRead = 0;
while (nBytesRead != - 1 && nBytesRead < length) {
    nBytesRead = mp3.read(data, 0, data.length - nBytesRead);
}

我也将字节数组转换为双精度,也许我在这里做错了(我对使用按位运算符还很陌生,所以也许存在问题

double[][] frameBuffer = new double[2][1024]; // 2 channel stereo buffer
int nFramesRead = 0;
int byteIndex = 0;
// convert the data into double and write it to frameBuffer
for (int i = 0; i < length; ++i) {
    for (int c = 0; c < 2; ++c) {
        byte a = data[byteIndex++];
        byte b = data[byteIndex++];
        int val = a | b << 8; // a is the least significant byte. | functions as a + here. b << 8 moves 8 zeroes to the end of b.
        frameBuffer[c][i] = (double) val / (double) Short.MAX_VALUE;
        nFramesRead++;
    }
}

然后使用双阵列播放声音。播放wav文件时,我会对缓冲区执行完全相同的操作,因此我很确定它在读取过程中一定是某些东西,而不是我向输出发送错误的字节。

我希望它可以与Mp3SPI一起使用,但是在某种程度上会破坏音频。 如果您有任何建议,我也愿意尝试其他库来播放MP3。只需一个用于原始MP3数据的解码器就足够了。

1 个答案:

答案 0 :(得分:0)

事实证明,来自mp3(输入)的AudioFormat与输出的AudioFormat不匹配,显然导致失真。因此,将它们配对后,回放就可以了!