Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving audio byte[] to a wav file

Tags:

java

audio

Been having a bit of trouble over the last few days trying to get this to work. But what I want is we have an application that sends raw data over the network. I then read this binary data in and want to save it to a wav(any audio) file. Might look at compression later.

So the problematic code:

byte[] allBytes = ...
InputStream b_in = new ByteArrayInputStream(allBytes);

try
{
     AudioFormat format = new AudioFormat(8000f, 16, 1, true, true);
     AudioInputStream stream = new AudioInputStream(b_in, format, allBytes.length);
     //AudioInputStream stream = AudioSystem.getAudioInputStream(b_in);                

Have tried to use the above statement as well but i get the exception: javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from stream. So what I think is happening is that because my stream is raw audio data and does not have a wave header this is throwing an exception?

File newPath = new File(SystemConfiguration.getLatest().voiceNetworkPathDirectory + currentPhoneCall.fileName);
if (!AudioSystem.isFileTypeSupported(Type.WAVE, stream))
{
    Logger.error("Audio System file type not supported");
}

AudioSystem.write(stream, Type.WAVE, newPath);

The file does successfully write but it is all static, Do I need to create a wave header on the output using the something like this. When I look at the outputted wav file in notepad and it does seem to have a header as it starts with 'RIFF'.

Do I need to add a fake header into my input stream? Should i just create my own output header and just save it with a binary writer?

like image 574
user1434177 Avatar asked Jun 12 '12 06:06

user1434177


People also ask

How many bytes is a WAV file?

The WAV format is by definition, the highest quality 16-bit audio format. It is also the largest at about 10 MB per minute of CD quality audio. The quality can be sacrificed for file size by adjusting the sampling rate, data width (i.e. 8-bits), and number of channels (up to 2 for stereo).

How is audio stored in WAV?

What is a WAV file? WAV, known for WAVE (Waveform Audio File Format), is a subset of Microsoft's Resource Interchange File Format (RIFF) specification for storing digital audio files. The format doesn't apply any compression to the bitstream and stores the audio recordings with different sampling rates and bitrates.

What encoding is a WAV file?

A WAV file encoder uses a technique called pulse code modulation (PCM), which samples analog sound waves at regular intervals. (Some computer systems call this linear pulse code modulation, or LPCM.)


2 Answers

So I ended up getting it working, not really sure why but this is the code that is working:

InputStream b_in = new ByteArrayInputStream(resultArray);
try {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(
                "C:\\filename.bin"));
        dos.write(resultArray);
        AudioFormat format = new AudioFormat(8000f, 16, 1, true, false);
        AudioInputStream stream = new AudioInputStream(b_in, format,
                resultArray.length);
        File file = new File("C:\\file.wav");
        AudioSystem.write(stream, Type.WAVE, file);
        Logger.info("File saved: " + file.getName() + ", bytes: "
                + resultArray.length)

So it must have been my signed/unsigned/ little endian settings. What I ended up doing was saving the data to a binary file. Then importing that file as raw data in audacity. This told me everything except the rate which I already new. The only issue I have now is to do with the header calculation. I save the binary data which generates a 4 second wav but it only ever has 2 seconds of sound. Its as if it is calculating my header wrong. I'm not sure if it is to do with the frame-length that LiuYan mentioned.

If I have an array length of 160. Does this mean I have a framelength of 10? 160 / 1 / 16. If I do this then I only store 10 bytes of data into my binary file.

like image 116
user1434177 Avatar answered Oct 20 '22 00:10

user1434177


It's hard to know from your description where the error is, but to answer your questions, when you see 'RIFF' when you open the file that does mean it has a header. Trying to build you own header is possible but a bit time consuming (and unnecessary since you've got one).

Now, when reading, it is safest to get the format from the file itself, rather than trying to specify it manually -- that will be less error prone. There is sample code for that here:

http://www.jsresources.org/examples/SimpleAudioPlayer.java.html

When writing, you say "The file does successfully write but it is all static" -- have you confirmed that with something other than your own java code? Maybe I am not understanding correctly, but it sounds like you are trying to record and playback WAV files with fresh java code, and if that's the case, it's hard to tell if something is going wrong with the recording or the playback.

You should start with a vanilla format (16 bits, stereo, uncompressed, 44,100 kHz) so you can open the file in media player or quicktime or something and verify that the recording worked. Once that works, you can try to change the SR and so on. Here is some sample code for recording. Start with that, verify that it works, and then move on to something more complex:

http://www.jsresources.org/examples/SimpleAudioRecorder.java.html

like image 40
Bjorn Roche Avatar answered Oct 20 '22 01:10

Bjorn Roche