title: Processing of Microphone Input
body: <p>I am trying to get audio data from the microphone. I have achieved this by using the <code>AudioRecord</code> class which fills a buffer with type shorts. </p>
  
  <p>Eventually I would like to graph this buffer so that I get an oscilloscope like display (realtime information). The problem is that if I want to display a value (say in text) then I need a different thread to update the UI. Currently I'm doing this by using an <code>AsyncTask</code> and updating the UI with <code>AsyncTasks.publishProgress()</code>. So far I haven't been very successful and would like to know if I'm on the right track? Are handles a better way to go? Is there anyone out there who has done something similar before, and if so what method worked for you? Also, is it at all possible to simply poll the microphone? </p>
  
  <hr>
  
  <p>Here is my code. It is meant to output every read sample from the MIC. It appears to do this at an acceptable rate but occasionally displays a zero. Why?</p>
  
  <pre><code>package com.ss.audioacquireapp3;
  
  import android.app.Activity;
  import android.content.Context;
  import android.media.AudioFormat;
  import android.media.AudioRecord;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.util.Log;
  import android.widget.TextView;
  
  
  public class AudioAcquireApp3Activity extends Activity 
  {
          //Properties (AsyncTask)
          protected TextView _percentField;
          protected InitTask _initTask;
  
          //Properties (MIC)
          public AudioRecord audioRecord; 
          public int mSamplesRead; //how many samples read 
          public int recordingState;
          public int buffersizebytes; 
          public int channelConfiguration = AudioFormat.CHANNEL_IN_MONO; 
          public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 
          public static short[] buffer; //+-32767 
          public static final int SAMPPERSEC = 44100; //samp per sec 8000, 11025, 22050 44100 or 48000
  
      @Override
      public void onCreate( Bundle savedInstanceState ) 
      {
          super.onCreate(savedInstanceState);
          setContentView( R.layout.main );
  
          _percentField = ( TextView ) findViewById( R.id.percent_field );
  
          buffersizebytes = AudioRecord.getMinBufferSize(SAMPPERSEC,channelConfiguration,audioEncoding); //4096 on ion 
          buffer = new short[buffersizebytes]; 
          audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,SAMPPERSEC,channelConfiguration,audioEncoding,buffersizebytes); //constructor 
  
          _initTask = new InitTask();
          _initTask.execute( this );
      }
  
      /**
       * sub-class of AsyncTask
       */
      protected class InitTask extends AsyncTask&lt;Context, Integer, String&gt;
      {
          // -- run intensive processes here
          // -- notice that the datatype of the first param in the class definition matches the param passed to this method 
          // -- and that the datatype of the last param in the class definition matches the return type of this method
                  @Override
                  protected String doInBackground( Context... params ) 
                  {
                          //-- on every iteration
                          //-- runs a while loop that causes the thread to sleep for 50 milliseconds 
                          //-- publishes the progress - calls the onProgressUpdate handler defined below
                          //-- and increments the counter variable i by one
                          //int i = 0;
  
                      audioRecord.startRecording();
  
                          while( true ) 
                          {
                                  try{
                                          mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes);
  
                                          int amp;
  
                                          for(int i = 0; i &lt; buffersizebytes - 1; i++){
                                              amp = (int)buffer[i];
                                              publishProgress( amp );
                                          }
  
                                  } catch( Exception e ){                        
                                  }
                          }
                  }
  
                  // -- gets called just before thread begins
                  @Override
                  protected void onPreExecute() 
                  {
                          //Log.i( "makemachine", "onPreExecute()" );
                          super.onPreExecute();
  
                  }
  
                  // -- called from the publish progress 
                  // -- notice that the datatype of the second param gets passed to this method
                  @Override
                  protected void onProgressUpdate(Integer... values) 
                  {
                          super.onProgressUpdate(values);
                          //Log.i( "makemachine", "onProgressUpdate(): " +  String.valueOf( values[0] ) );
                          _percentField.setText( String.valueOf(values[0]) );
                  }
  
                  // -- called as soon as doInBackground method completes
                  // -- notice that the third param gets passed to this method
                  @Override
                  protected void onPostExecute( String result ) 
                  {
                          super.onPostExecute(result);
                          //Log.i( "makemachine", "onPostExecute(): " + result );
                  }   
  
  
       } 
  }
  </code></pre>
  
  <p>And here is main.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:gravity="center_vertical|center_horizontal"
      &gt;
  
  &lt;TextView android:id="@+id/percent_field"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"/&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>Note that you need to add this to AndroidManifest.xml</p>
  
  <pre><code>&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
  </code></pre>
  
  <p>I am running this on a LG Optimus Black. Please help me make this code as efficient as possible.</p>