javaaudiowavoggvorbis

Converting ogg to wav doesn't work although listed as available format


What I'm trying to do is generate 10 second snippets from audio files and convert them to WAV in the process. I'm using the javazoom vorbisspi and mp3spi libraries. It's working for mp3 and WAV files, but not for .ogg files.

I tried listing the available target formats for the encoding I want (PCM signed) and weirdly, for mp3 files the list of available formats is empty (although it works) and the list for ogg files diplays the PCM encoding I want (although it doesn't work). Playing back .ogg files works, though. Here is my code:

        AudioInputStream in = null;
        AudioInputStream din = null;
        AudioFileFormat fileFormat = null;
        AudioFormat format = null;

        fileFormat = AudioSystem.getAudioFileFormat(input);
        in = AudioSystem.getAudioInputStream(input);

        format = in.getFormat();
        float frameRate = 44100;
        int channels = format.getChannels();
        AudioFormat targetFormat = new AudioFormat(
            AudioFormat.Encoding.PCM_SIGNED,
            frameRate,
            16,
            channels,
            channels*2,
            frameRate,
            false
        );

        AudioFormat[] available = AudioSystem.getTargetFormats(
            AudioFormat.Encoding.PCM_SIGNED, format);
        System.out.println("------------------------------------");
        System.out.println("Available for: " + format.toString());
        for (AudioFormat e : available) {
            System.out.println(e.toString());
        }

        if (AudioSystem.isConversionSupported(targetFormat, format)) {

            din = AudioSystem.getAudioInputStream(targetFormat, in);

            long frames = this.thumbNailLength * (long)frameRate;
            AudioInputStream shortenedStream = new AudioInputStream(
                din, targetFormat, frames);
            AudioSystem.write(shortenedStream, 
                new AudioFileFormat.Type("WAVE", "wav"), outputFile);
        }
        else {
            throw new IllegalArgumentException(
                "Conversion to WAV from this format is not supported by the System.");
        }

The output for an .ogg file:

 [java] Available for: VORBISENC 44100.0 Hz, unknown bits per sample, stereo, unknown frame size, unknown frame rate, 
 [java] PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian
 [java] PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian

Why doesn't this work as expected? I don't even get an exception, a .wav file is generated but can't be played by any player.


Solution

  • I found a solution: temporarily write to a pcm file, then read the file into a new AudioInputStream. I don't really know why, but it works:

            if (format.getEncoding().equals(new AudioFormat.Encoding("VORBISENC"))) {
                byte [] buffer = new byte[4096];
                int n;
                FileOutputStream fos = new FileOutputStream(outputFile + ".pcm");    
                while(-1 != (n = din.read(buffer))) {
                    fos.write(buffer, 0, n); 
                }    
                fos.close();
    
                AudioInputStream pcmIn = new AudioInputStream(new FileInputStream(outputFile + ".pcm"), targetFormat, frames);
                AudioSystem.write(pcmIn, AudioFileFormat.Type.WAVE, new FileOutputStream(outputFile));
                File f = new File(outputFile + ".pcm");
                f.delete();
            } else {
                AudioInputStream shortenedStream = new AudioInputStream(din, targetFormat, frames);
                AudioSystem.write(shortenedStream, new AudioFileFormat.Type("WAVE", "wav"), outputFile);
            }