Search code examples
androidaudiorecord

Android record and playback


I am currently trying to build an amplifier for the Android. The goal is to record and playback what is being recorded simultaneously. I created a thread that would take care of this. However, the sound comes out choppy. Here is what I tried.

private class RecordAndPlay extends Thread{
    int bufferSize;
    AudioRecord aRecord;
    short[] buffer;

    public RecordAndPlay() {
        bufferSize = AudioRecord.getMinBufferSize(22050, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        buffer = new short[bufferSize];

    }

    @Override
    public void run() {         
            aRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 22050, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

            try {
                aRecord.startRecording();
            } catch (Exception e) {

            }
            int bufferedResult = aRecord.read(buffer,0,bufferSize);
            final AudioTrack aTrack = new AudioTrack(AudioManager.STREAM_MUSIC, samplingRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferedResult, AudioTrack.MODE_STREAM);
            aTrack.setNotificationMarkerPosition(bufferedResult);
            aTrack.setPlaybackPositionUpdateListener(new OnPlaybackPositionUpdateListener() {

                @Override
                public void onPeriodicNotification(AudioTrack track) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onMarkerReached(AudioTrack track) {
                    Log.d("Marker reached", "...");
                    aTrack.release();                       
                    aRecord.release();
                    run();

                }
            });
            aTrack.play();
            aTrack.write(buffer, 0, buffer.length);     

    }

    public void cancel(){
        aRecord.stop();
        aRecord.release();

    }
}

Solution

  • Your playback is choppy because the AudioTrack is getting starved and not getting data smoothly. In your code you are recursively calling run and creating a new AudioTrack per marker. Instead, instantiate AudioRecord and AudioTrack only once and just handle their events. Also, to help smooth out playback you should probably start recording slightly before playback and maintain a queue of the recorded buffers. You can then manage passing these buffers to the AudioTrack and make sure there is always a new buffer to submit on each marker event.