PCM Wave file - stereo to mono

fredley picture fredley · Jan 17, 2011 · Viewed 16.2k times · Source

I have an audio file which is stereo. Is converting it to mono just a case of skipping every other byte (after the header)? It's encoded in 16bit signed PCM format. I've got javax.sound.sampled available.

Here's code I tried that didn't work:

WaveFileWriter wfw = new WaveFileWriter();
AudioFormat format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 2, 2, 44100, false);
AudioFormat monoFormat = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 1, 2, 44100, false);

byte[] audioData = dataout.toByteArray();
int length = audioData.length;
ByteArrayInputStream bais = new ByteArrayInputStream(audioData);

AudioInputStream stereoStream = new AudioInputStream(bais,format,length);
AudioInputStream monoStream = new AudioInputStream(stereoStream,format,length/2);

wfw.write(monoStream, Type.WAVE, new File(Environment.
                 getExternalStorageDirectory().getAbsolutePath()+"/stegDroid/un-ogged.wav"));

This code is used after reading a .ogg file using Jorbis to convert it to PCM data. The only problem is the result is stereo and I need it to be mono, so if there's another solution I'm happy to hear it!

Answer

BrokenGlass picture BrokenGlass · Jan 17, 2011

I have an audio file which is stereo. Is converting it to mono just a case of skipping every other byte (after the header)?

Almost - you want to skip every other sample, not byte. In your case it looks like each sample is of size 16 bits = 2 bytes. So you would want to take 2 bytes, skip 2 bytes, take 2 bytes and so on.

AudioInputStream monoStream = new AudioInputStream(stereoStream,format,length/2);

wfw.write(monoStream, Type.WAVE, new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/stegDroid/un-ogged.wav"));

This looks like you just write out the first half of the file instead of writing out every other sample. Also you have to fix the WAV header, to specify a single channel (see your monoFormat).