Robert J. Walker
Robert J. Walker

Reputation: 10355

Convert audio stream to WAV byte array in Java without temp file

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?

Upvotes: 9

Views: 29454

Answers (5)

Kanaris007
Kanaris007

Reputation: 314

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.

Upvotes: -1

HolloW
HolloW

Reputation: 730

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

Upvotes: 2

Superziyi
Superziyi

Reputation: 619

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?

Upvotes: 2

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.

Upvotes: -2

Simon Lehmann
Simon Lehmann

Reputation: 10967

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

Upvotes: 7

Related Questions