Java – convert audio stereo to audio bytes
I'm trying to do some audio processing. I'm really stuck in stereo to mono conversion I checked the stereo to mono conversion on the Internet
As far as I know, I can take the left channel and the right channel, add them and divide them by 2 But when I convert the result to WAV file again, I get a lot of foreground noise I know that there may be noise when processing data, and there will be some overflow of byte variables
This is the class to retrieve byte [] data block from my 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,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,abData.length);
    }
    catch (Exception e){
        e.printStackTrace();
        System.err.println("Error getting samples from file: " + this._inputFileName);
        System.exit(1);
    }
    if (bytesRead > 0)
        return abData;
    else
        return null;
}
}
This means that every time getsamples is called, it returns an array, such as:
buff = {Lchannel,Rchannel,Lchannel,Rchannel ……}
The processing procedure for converting to mono is as follows:
byte[] buff = null;
        while( (buff = _input.getSamples()) != null ){
            /** Convert to mono */
            byte[] mono = new byte[buff.length/2];
            for (int i = 0 ; i < 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 is an average between 2 channels (stereo)*/
                mono[i * 2] = (byte)((short)(m >> 8));
                mono[i * 2 + 1] = (byte)(m & 0xff);
            }
}
And write the wav file using the following methods:
public static void writeWav(byte [] theResult,int samplerate,File outfile) {
        // Now convert theResult into a wav file
        // probably should use a file if samplecount is too big!
        int theSize = theResult.length;
        InputStream is = new ByteArrayInputStream(theResult);
        //Short2InputStream sis = new Short2InputStream(theResult);
        AudioFormat audioF = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,samplerate,// 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; probably just done with file");
            return;
        }
    }
Take 44100 as the sampling rate
Remember, in fact, I have obtained that the byte [] array is PCM, so the MP3 – > PCM conversion is completed by specifying
Solution
As pointed out in the comments, the byte order may be wrong In addition, converting to a signed short circuit and shifting it may result in the first byte being 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 the values of hi and lo to see if it gets better
