0
votes

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.

1
It looks like you are basically following the Javazoom documentation, from what you show. Lots of people use floats instead of doubles, floats being considered quite sufficient, but that shouldn't affect your code. As a form of trouble-shooting, maybe try using the code from Javazoom to do a simple playback, foregoing the storage to doubles portion. If that works, then proceed to look more closely at your conversion process. IDK any other libraries, the Javazoom code has been a mainstay for many years. Mavenized version: github.com/pdudits/soundlibsPhil Freihofner
I wasn't expecting switching to floats to help with this problem, sorry if my suggestion implied that. It's more for down the line once everything is working. But I do think it would be good to see if the example code given by Javazoom works for you, as a baseline test for debugging.Phil Freihofner
Great Idea! 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!MusicIsLife
Congratulations figuring this out! Audio coding with Java has a significant learning curve, but it is quite powerful once you get the hang of it.Phil Freihofner

1 Answers

0
votes

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!