java - Convert audio stereo to audio byte -
i've trying audio processing, i'm stuck stereo mono conversion. looked in internet regarding stereo mono conversion.
as far know, can take left channel, right channel, sum them , divide 2. when dump result wav file again, got lot of foreground noise. know noise can caused when processing data, there overflow in byte variable.
this class retrieving byte[] data chunks mp3 file:
public class inputsounddecoder {
private int buffer_size = 128000; private string _inputfilename; private file _soundfile; private audioinputstream _audioinputstream; private audioformat _audioinputformat; private audioformat _decodedformat; private audioinputstream _audioinputdecodedstream; public inputsounddecoder(string filename) throws unsuportedsamplerateexception{ this._inputfilename = filename; this._soundfile = new file(this._inputfilename); try{ this._audioinputstream = audiosystem.getaudioinputstream(this._soundfile); } catch (exception e){ e.printstacktrace(); system.err.println("could not open file: " + this._inputfilename); system.exit(1); } this._audioinputformat = this._audioinputstream.getformat(); this._decodedformat = new audioformat(audioformat.encoding.pcm_signed, 44100, 16, 2, 1, 44100, false); this._audioinputdecodedstream = audiosystem.getaudioinputstream(this._decodedformat, this._audioinputstream); /** supported sample rates */ switch((int)this._audioinputformat.getsamplerate()){ case 22050: this.buffer_size = 2304; break; case 44100: this.buffer_size = 4608; break; default: throw new unsuportedsamplerateexception((int)this._audioinputformat.getsamplerate()); } system.out.println ("# channels: " + this._decodedformat.getchannels()); system.out.println ("sample size (bits): " + this._decodedformat.getsamplesizeinbits()); system.out.println ("frame size: " + this._decodedformat.getframesize()); system.out.println ("frame rate: " + this._decodedformat.getframerate()); } public byte[] getsamples(){ byte[] abdata = new byte[this.buffer_size]; int bytesread = 0; try{ bytesread = this._audioinputdecodedstream.read(abdata,0,abdata.length); } catch (exception e){ e.printstacktrace(); system.err.println("error getting samples file: " + this._inputfilename); system.exit(1); } if (bytesread > 0) return abdata; else return null; } }
this means, every time call getsamples, returns array like:
buff = {lchannel, rchannel, lchannel, rchannel,lchannel, rchannel,lchannel, rchannel...}
the processing routine conversion mono looks like:
byte[] buff = null; while( (buff = _input.getsamples()) != null ){ /** convert mono */ byte[] mono = new byte[buff.length/2]; (int = 0 ; < mono.length/2; ++i){ int left = (buff[i * 4] << 8) | (buff[i * 4 + 1] & 0xff); int right = (buff[i * 4 + 2] <<8) | (buff[i * 4 + 3] & 0xff); int avg = (left + right) / 2; short m = (short)avg; /*mono average between 2 channels (stereo)*/ mono[i * 2] = (byte)((short)(m >> 8)); mono[i * 2 + 1] = (byte)(m & 0xff); } }
and writing wav file using:
public static void writewav(byte [] theresult, int samplerate, file outfile) { // convert theresult wav file // should use file if samplecount big! int thesize = theresult.length; inputstream = new bytearrayinputstream(theresult); //short2inputstream sis = new short2inputstream(theresult); audioformat audiof = new audioformat( audioformat.encoding.pcm_signed, samplerate, 16, 1, // channels 2, // framesize samplerate, false ); audioinputstream ais = new audioinputstream(is, audiof, thesize); try { audiosystem.write(ais, audiofileformat.type.wave, outfile); } catch (ioexception ioe) { system.err.println("io exception; done file"); return; } } with 44100 sample rate.
take in mind byte[] array i've got it's pcm, mp3 -> pcm conversion it's done specifying
this._decodedformat = new audioformat(audioformat.encoding.pcm_signed, 44100, 16, 2, 1, 44100, false); this._audioinputdecodedstream = audiosystem.getaudioinputstream(this._decodedformat, this._audioinputstream);
as said, when writing wav file i've got lot of noise. pretend apply every chunk of byte fft, think because of noisy sound result it's not correct.
because i'm taking 2 songs, 1 of them 20 seconds crop another, , when comparing crop fft result original 20 seconds subset, doesn't match @ all.
i think reason it's incorrect conversion stereo->mono.
hope know this,
regards.
as pointed out in comments, endianness may wrong. also, converting signed short , shifting may cause first byte 0xff.
try:
int hi = 0; int lo = 1; int left = (buff[i * 4 + hi] << 8) | (buff[i * 4 + lo] & 0xff); int right = (buff[i * 4 + 2 + hi] << 8) | (buff[i * 4 + 2 + lo] & 0xff); int avg = (left + right) / 2; mono[i * 2 + hi] = (byte)((avg >> 8) & 0xff); mono[i * 2 + lo] = (byte)(avg & 0xff); then switch values of hi , lo see if gets better.
Comments
Post a Comment