Question

Given an InputStream called in which contains audio data in a compressed format (such as MP3 or OGG), I wish to create a byte array containing a WAV conversion of the input data. Unfortunately, if you try to do this, JavaSound hands you the following error:

java.io.IOException: stream length not specified

I managed to get it to work by writing the wav to a temporary file, then reading it back in, as shown below:

AudioInputStream source = AudioSystem.getAudioInputStream(new BufferedInputStream(in, 1024));
AudioInputStream pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
AudioInputStream ulaw = AudioSystem.getAudioInputStream(AudioFormat.Encoding.ULAW, pcm);
File tempFile = File.createTempFile("wav", "tmp");
AudioSystem.write(ulaw, AudioFileFormat.Type.WAVE, tempFile);
// The fileToByteArray() method reads the file
// into a byte array; omitted for brevity
byte[] bytes = fileToByteArray(tempFile);
tempFile.delete();
return bytes;

This is obviously less desirable. Is there a better way?

Was it helpful?

Solution

The problem is that the most AudioFileWriters need to know the file size in advance if writing to an OutputStream. Because you can't provide this, it always fails. Unfortunatly, the default Java sound API implementation doesn't have any alternatives.

But you can try using the AudioOutputStream architecture from the Tritonus plugins (Tritonus is an open source implementation of the Java sound API): http://tritonus.org/plugins.html

OTHER TIPS

I notice this one was asked very long time ago. In case any new person (using Java 7 and above) found this thread, note there is a better new way doing it via Files.readAllBytes API. See: How to convert .wav file into byte array?

Too late, I know, but I was needed this, so this is my two cents on the topic.

public void UploadFiles(String fileName, byte[] bFile)
{
    String uploadedFileLocation = "c:\\";

    AudioInputStream source;
    AudioInputStream pcm;
    InputStream b_in = new ByteArrayInputStream(bFile);
    source = AudioSystem.getAudioInputStream(new BufferedInputStream(b_in));
    pcm = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, source);
    File newFile = new File(uploadedFileLocation + fileName);
    AudioSystem.write(pcm, Type.WAVE, newFile);

    source.close();
    pcm.close();
}

The issue is easy to solve if you prepare class which will create correct header for you. In my example Example how to read audio input in wav buffer data goes in some buffer, after that I create header and have wav file in the buffer. No need in additional libraries. Just copy the code from my example.

Example how to use class which creates correct header in the buffer array:

public void run() {    
    try {    
        writer = new NewWaveWriter(44100);  

        byte[]buffer = new byte[256];  
        int res = 0;  
        while((res = m_audioInputStream.read(buffer)) > 0) {  
            writer.write(buffer, 0, res);  
        }  
    } catch (IOException e) {  
        System.out.println("Error: " + e.getMessage());  
    }    
}    

public byte[]getResult() throws IOException {  
    return writer.getByteBuffer();  
}  

And class NewWaveWriter you can find under my link.

This is very simple...

File f = new File(exportFileName+".tmp");
File f2 = new File(exportFileName);
long l = f.length();
FileInputStream fi = new FileInputStream(f);
AudioInputStream ai = new AudioInputStream(fi,mainFormat,l/4);
AudioSystem.write(ai, Type.WAVE, f2);
fi.close();
f.delete();

The .tmp file is a RAW audio file, the result is a WAV file with header.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top