【问题标题】:MP3 Files get distorted during read processMP3 文件在读取过程中失真
【发布时间】:2019-05-12 18:19:04
【问题描述】:

我目前正在开发一个播放声音的应用程序。我使用 Java Sound API 实现了标准 WAV 文件的播放,没​​有问题,一切正常。现在我也想添加对 MP3 的支持,但我遇到了一个奇怪的问题:播放失真。我试图找出我做错了什么,我将不胜感激任何朝着正确方向发展的线索。 我正在使用 Mp3SPI (http://www.javazoom.net/mp3spi/documents.html) 播放 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 数据。

【问题讨论】:

  • 从您所展示的内容来看,您基本上是在遵循 Javazoom 文档。很多人使用浮点数而不是双精度数,浮点数被认为是足够的,但这不应该影响您的代码。作为故障排除的一种形式,可以尝试使用 Javazoom 中的代码进行简单的播放,将存储空间加倍。如果可行,请继续更仔细地查看您的转换过程。 IDK 任何其他库,Javazoom 代码多年来一直是中流砥柱。 Maven化版本:github.com/pdudits/soundlibs
  • 我没想到切换到浮点数来帮助解决这个问题,如果我的建议暗示了这一点,我很抱歉。一旦一切正常,就更适合下线了。但我确实认为最好看看 Javazoom 提供的示例代码是否适合您,作为调试的基线测试。
  • 好主意!事实证明,mp3(输入)中的AudioFormat 和输出的AudioFormat 不匹配,显然会导致失真。因此,与那些匹配的,播放是好的!
  • 恭喜您解决了这个问题!使用 Java 进行音频编码有一个显着的学习曲线,但一旦掌握了它就会非常强大。

标签: java audio mp3 decode


【解决方案1】:

事实证明,mp3(输入)的 AudioFormat 和输出的 AudioFormat 不匹配,显然会导致失真。所以有了匹配的,播放就好了!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    相关资源
    最近更新 更多