Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android AudioRecord class - process live mic audio quickly, set up callback function

I want to record audio from the mic and access it for possible playback in near real-time. I am unsure of how to use the Android AudioRecord class to record some mic audio and quickly access it.

For the AudioRecord class, the official site says 'the app polls the AudioRecord object in time', and 'the size of the buffer being filled determines the time-length of the recording before over-running unread data'. Later it's suggested that a larger buffer should be used when polling less frequently. They never actually show an example in code.

One example I've seen in a book uses the AudioRecord class to continuously read a buffer freshly populated with live mic audio, and then the app writes this data to an SD file. The pseudo-code looks something like -

set up AudioRecord object with buffer size and recording format info set up a file and an output stream myAudioRecord.startRecording(); while(isRecording) {     // myBuffer is being filled with fresh audio     read audio data into myBuffer     send contents of myBuffer to SD file } myAudioRecord.stop(); 

How this code synchronizes its reading with the rate of recording is unclear - is the boolean "isRecording" sequenced on and off properly elsewhere? It seems this code could either read too frequently or too infrequently, depending on how long the reading and writing takes.

The site doc also says the AudioRecord class has a nested class named OnRecordPositionUpdateListener which is defined as an interface. The information suggests that somehow, you specify the period you want for being notified of the progress of the recording, and the name of your event handler, and a call is automatically made to your event handler at the specified frequency. I think the structure, in pseudo-code would be something like -

set target of period update message = myListener set period to be about every 250 ms other code  myListener() {     if(record button was recently tapped)         handle message that another 250 ms of fresh audio is available         ie, read it and send it somewhere ) 

I need to find some specific code which allows me to capture and process mic audio with a delay of less than about 500 ms. Android offers another class called MediaRecorder, but it doesn't support streaming, and I may want to stream live mic audio over a Wi-Fi network in near real-time. Where can I find some specific examples?

like image 512
kenj Avatar asked Dec 24 '10 08:12

kenj


1 Answers

After experimenting lots with the notifications and a bunch of other techniques I settled on this code:

private class AudioIn extends Thread {       private boolean stopped    = false;       private AudioIn() {                start();           }       @Override      public void run() {              android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);             AudioRecord recorder = null;             short[][]   buffers  = new short[256][160];             int         ix       = 0;              try { // ... initialise                    int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);                     recorder = new AudioRecord(AudioSource.MIC,                                               8000,                                               AudioFormat.CHANNEL_IN_MONO,                                               AudioFormat.ENCODING_PCM_16BIT,                                               N*10);                     recorder.startRecording();                     // ... loop                     while(!stopped) {                        short[] buffer = buffers[ix++ % buffers.length];                        N = recorder.read(buffer,0,buffer.length);                       //process is what you will do with the data...not defined here                       process(buffer);                   }              } catch(Throwable x) {                 Log.w(TAG,"Error reading voice audio",x);              } finally {                 close();              }          }        private void close() {            stopped = true;         }      } 

So far it's working pretty robustly on the half a dozen Android phones I've tried it on.

like image 141
tonys Avatar answered Oct 12 '22 23:10

tonys