2

I installed the mp3spi to support reading mp3 files in my Java 8 project usng the javax.sound* libraries. My goal now is to write mp3 to a wav file. However, the result is incorrect. Here's the code in its simplest format:

public static void mp3ToWav(InputStream mp3Data) throws UnsupportedAudioFileException, IOException {
    AudioInputStream mp3Stream = AudioSystem.getAudioInputStream(mp3Data);
    AudioFormat format = mp3Stream.getFormat();
    AudioFormat convertFormat = new AudioSystem.write(mp3Stream, Type.WAVE, new File("C:\\temp\\out.wav"));
}

There's one other way as outlined here (mp3 to wav conversion in java):

File mp3 = new File("C:\\music\\greatest-songs-of-all-time\\RebeccaBlack-Friday.mp3");
if(!mp3.exists()) {
    throw new FileNotFoundException("couldn't find mp3");
}
FileInputStream fis = new FileInputStream(mp3);
BufferedInputStream bis = new BufferedInputStream(fis);

AudioInputStream mp3Stream = AudioSystem.getAudioInputStream(bis);
AudioFormat sourceFormat = mp3Stream.getFormat();
AudioFormat convertFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
        sourceFormat.getSampleRate(), 16, 
        sourceFormat.getChannels(), 
        sourceFormat.getChannels() * 2,
        sourceFormat.getSampleRate(),
        false);

try (final AudioInputStream convert1AIS = AudioSystem.getAudioInputStream(mp3Stream)) {
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final AudioInputStream convert2AIS = AudioSystem.getAudioInputStream(convertFormat, convert1AIS);
    System.out.println("Length is: " + mp3Stream.getFrameLength() + " div by " + mp3Stream.getFormat().getFrameRate());
    byte [] buffer = new byte[8192];
    int iteration = 0;
    while(true){
        int readCount = convert2AIS.read(buffer, 0, buffer.length);
        if(readCount == -1){
            break;
        }
        baos.write(buffer, 0, readCount);
        iteration++;
    }

    System.out.println("completed with iteration: " + iteration);

    FileOutputStream fw = new FileOutputStream("C:\\temp\\out-2.wav");
    fw.write(baos.toByteArray());
    fw.close();
}

bis.close();
fis.close();

This generates a file that's over 30 mb from a compressed mp3 of 4-5 mb, however it doesn't work as a valid WAV file.

The method that does work for me involves using JLayer Converter class, however, because I want to do some other processing like cutting out portions of audio, modifying the volume and playback speed, etc., I feel like I might be better off working with the native library.

Community
  • 1
  • 1
IcedDante
  • 6,145
  • 12
  • 57
  • 100
  • I challenge the existence of mp3Data; where do you get that from and what does it contain?? In any case You need to start with bytes - an array of bytes - as in the answer - do you have that array of bytes? – gpasch Jan 21 '17 at 22:07
  • 1
    `AudioFormat convertFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate(), 16, sourceFormat.getChannels(), sourceFormat.getChannels() * 2, sourceFormat.getSampleRate(), false);` Don't hard code these values. Use the same values as in the source format and it will likely work as advertised. – Andrew Thompson Jan 22 '17 at 18:13
  • gspasch you can challenge the existence of mp3 Data, but I guarantee it exists! I'll modify my question to include that part of the code – IcedDante Jan 22 '17 at 20:16
  • @AndrewThompson I left AudioFormat.Encoding.PCM_SIGNED as is (since I assume that gives it the WAV format) and used the sourceFormat for everything else and had the same error – IcedDante Jan 22 '17 at 20:25
  • The seconds code snippet does not create a valid wav file, but (probably) a raw audio file. I'd simply call `AudioSystem.write(convert2AIS, Type.WAVE, new File("C:\\temp\\out.wav"));` once I have that converted stream `convert2AIS` and let the `AudioSystem` do the writing for me. – Hendrik Jan 25 '17 at 11:43

1 Answers1

2

After you opened the mp3 stream, you typically have to convert it, before writing it to a file.

Like this (untested):

public static void mp3ToWav(File mp3Data) throws UnsupportedAudioFileException, IOException {
    // open stream
    AudioInputStream mp3Stream = AudioSystem.getAudioInputStream(mp3Data);
    AudioFormat sourceFormat = mp3Stream.getFormat();
    // create audio format object for the desired stream/audio format
    // this is *not* the same as the file format (wav)
    AudioFormat convertFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
        sourceFormat.getSampleRate(), 16, 
        sourceFormat.getChannels(), 
        sourceFormat.getChannels() * 2,
        sourceFormat.getSampleRate(),
        false);
    // create stream that delivers the desired format
    AudioInputStream converted = AudioSystem.getAudioInputStream(convertFormat, mp3Stream);
    // write stream into a file with file format wav
    AudioSystem.write(converted, Type.WAVE, new File("C:\\temp\\out.wav"));
}
Hendrik
  • 5,085
  • 24
  • 56
  • I ee you marked this as untested and I wanted to say that I did try it and it does not work. That's not to say it can't work without some adjustments, but as of now I haven't been able to make it happen – IcedDante Jan 30 '17 at 18:51
  • 2
    it worked to me, i just had to add some pluggin to have .mp3 services working (mp3spi) – vict Mar 09 '17 at 17:08
  • BTW: Instead of mp3spi you can also use one of the libs from [SampledSP](http://www.tagtraum.com/sampledsp.html) (disclosure: I'm the author) – Hendrik Apr 12 '18 at 14:07
  • By "untested" you mean you have tested it and then un-tested it? :)) (OK, it's **"not tested"**) And then, how can you post a not tested code? It's not OK! – Apostolos Mar 02 '22 at 10:55