Monday, May 7, 2018

How Does the LAME Android SDK work

How do we encode and store a file in mp3 format? There are two ways to do

1. use a wav recorder and convert the byte buffer from the wav recorder into mp3 buffer on the fly
2. Read a wav file and convert it into mp3

#2 has a huge disadvantage of the original wav file being taking at least 100 MB for a 1 hr long file with just 8Kbps sampling.
#1 is efficient, but on the fly encoder needs  to be much efficient and faster.

The LAME mp3 encoder help one to achieve both. Below is how we do for on the fly encoding

int inSamplerate = 8000;
//get the minimum buffer value. Here we are considering only 8K samples
minBuffer = AudioRecord.getMinBufferSize(inSamplerate, AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

//now create the AudioRecorder object.
  audioRecord = new AudioRecord(
                MediaRecorder.AudioSource.MIC, inSamplerate,
                AudioFormat.CHANNEL_IN_MONO,
                AudioFormat.ENCODING_PCM_16BIT, minBuffer * 2);


//now create a buffer to read in the bytes from recorder
short[] buffer = new short[inSamplerate * 2 * 5];

//now create the mp3 buffer.  'mp3buf' should be at least 7200 bytes long to hold all possible emitted data.
byte[] mp3buffer = new byte[(int) (7200 + buffer.length * 2 * 1.25)];

//create a file output stream for the path at which  the mp3 file should be written. 
 try {
            outputStream = new FileOutputStream(new File(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

//now create the AndroidLame object
androidLame = new LameBuilder()
                .setInSampleRate(inSamplerate)
                .setOutChannels(1)
                .setOutBitrate(32)
                .setOutSampleRate(inSamplerate)
                .build();

// now start the recording
 audioRecord.startRecording();

//now loop in and read the byte buffer.
while (isRecording) {
            bytesRead = audioRecord.read(buffer, 0, minBuffer);
            if (bytesRead > 0) {
                int bytesEncoded = androidLame.encode(buffer, buffer, bytesRead, mp3buffer);
                if (bytesEncoded > 0) {
                    try {
                        outputStream.write(mp3buffer, 0, bytesEncoded);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }


//now flush
int outputMp3buf = androidLame.flush(mp3buffer);

if (outputMp3buf > 0) {
         try {
                outputStream.write(mp3buffer, 0, outputMp3buf);
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
}

//now stop and release the recorder, and close the AndroidLame as well. 
 audioRecord.stop();
 audioRecord.release();
 androidLame.close();


references:
https://github.com/naman14/TAndroidLame 

No comments:

Post a Comment