Search code examples
javaaudiomp3decode

MP3 Files get distorted during read process


I'm currently working on an application that plays back sound. I implemented playback for standard WAV File with the Java Sound API, no problems there, everything working fine. Now I want to add support for MP3 as well, but I'm having a strange problem: the playback gets distorted. I'm trying to figure out what I'm doing wrong, I would appreciate any leads in the right direction. I'm using the Mp3SPI (http://www.javazoom.net/mp3spi/documents.html) for playing back the Mp3 Files.

I have already tried to take a look at the output and recorded a wav-file with the output I get from the mp3, then I compared the waveforms of the original and the recorded file. As it turns out, in the recorded file there are a lot of samples that are 0, or very close to it. Longer tones get broken up and the waveform returns to 0 all the time, then jumping back to the place the waveform is in the original.

I open the file like this:


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);
    }
}

The part where I read the Mp3 File:

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);
}

Also I convert the byte-array to doubles, perhaps I do something wrong here (I'm fairly new to using bitwise operators, so maybe there is the problem

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++;
    }
}

The double-array is then later used to play back the sound. When playing a wav file, I do the exact same thing to the buffer, so I'm pretty sure it has to be something during the read process, not me sending faulty bytes to the ouput.

I would expect this to work out of the box with Mp3SPI, but somehow something breaks the audio along the way. I am also open to trying other libraries to play back the MP3, if you have any recommendations. Just a Decoder for the raw MP3 Data would actually be enough.


Solution

  • As it turns out, the AudioFormat from the mp3 (input) and the AudioFormat of the output didnt match, obviously resulting in distortion. So with those matched up, playback is fine!