Android – Recording with AudioRecord on Android speeds up the audio

androidaudiorecord

I am using AudioRecord to record raw audio for processing.
The audio records entirely without any noise but when the raw PCM data generated is played back, it plays as if it has been speeded up a lot (upto about twice as much).
I am viewing and playing the PCM data in Audacity. I am using actual phone (Samsung Galaxy S5670) for testing.
The recording is done at 44100 Hz, 16 bit. Any idea what might cause this?

Following is the recording code:

public class TestApp extends Activity
{   
File file;
OutputStream os;
BufferedOutputStream bos;       
AudioRecord recorder;   
int iAudioBufferSize;
boolean bRecording; 
int iBytesRead;

Thread recordThread = new Thread(){
    @Override
    public void run()
    {
        byte[] buffer = new byte[iAudioBufferSize];
        int iBufferReadResult;
        iBytesRead = 0;
        while(!interrupted())
        {
            iBufferReadResult = recorder.read(buffer, 0, iAudioBufferSize);
            // Android is reading less number of bytes than requested.
            if(iAudioBufferSize > iBufferReadResult)
            {
                iBufferReadResult = iBufferReadResult + 
                        recorder.read(buffer, iBufferReadResult - 1, iAudioBufferSize - iBufferReadResult);
            }               
            iBytesRead = iBytesRead + iBufferReadResult;
            for (int i = 0; i < iBufferReadResult; i++)
            {
                try
                {
                    bos.write(buffer[i]);
                } catch (IOException e)
                {                                               
                    e.printStackTrace();
                }
            }
        }
    }
};  

@Override
public void onCreate(Bundle savedInstanceState)
{
    // File Creation and UI init stuff etc.

    bRecording = false;
    bPlaying = false;

    int iSampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
    iAudioBufferSize = AudioRecord.getMinBufferSize(iSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); 
    recorder = new AudioRecord(AudioSource.MIC, iSampleRate, AudioFormat.CHANNEL_IN_MONO, 
        AudioFormat.ENCODING_PCM_16BIT, iAudioBufferSize);

    bt_Record.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            if (!bRecording)
            {
                try
                {                       
                    recorder.startRecording();
                    bRecording = true;
                    recordThread.start();                       
                }
                catch(Exception e)
                {
                    tv_Error.setText(e.getLocalizedMessage());
                }
            }
            else
            {
                recorder.stop();
                bRecording = false;
                recordThread.interrupt();
                try
                {
                    bos.close();
                }
                catch(IOException e)
                {

                }
                tv_Hello.setText("Recorded Sucessfully. Total " + iBytesRead + " bytes.");
            }
        }

    });
}
}

RESOLVED : I posted this after struggling with it for 1-2 days. But, ironically, I found the solution soon after posting. The buffered output stream write was taking too much time in the for loop, so the stream was skipping samples. changed it to block write, removing the for loop. Works perfectly.

Best Answer

The audio skipping was caused by the delay in writing to buffer. the solution is to just replace this FOR loop:

        for (int i = 0; i < iBufferReadResult; i++)
        {
            try
            {
                bos.write(buffer[i]);
            } catch (IOException e)
            {                                               
                e.printStackTrace();
            }
        }

by a single write, like so:

       bos.write(buffer, 0, iBufferReadResult);

I had used the code from a book which worked, I guess, for lower sample rates and buffer updates.

Related Topic