title: Audio Record and Playback Failing - Android AudioRecord & AudioTrack
body: <p>I am writing an Android Application for Recording and playing back audio in a loop.
  Like an echo (Record, Play, run in a loop).</p>
  
  <p>I have successfully written the application for Recording and playing using a temp file, (write into file, read from the same file).<br>
  Doing the same using a intermediate buffer is failing.</p>
  
  <p>Here is my code:   </p>
  
  <pre><code>public class BufferMain extends ActionBarActivity {
  private String TAG = "AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER";
  
  private boolean isRunning = false;
  
  private AudioRecord recorder = null;
  private AudioTrack track = null;
  
  /* Buffer used to record and Playback Audio */
  byte buffer[] = new byte[640];
  int bufferSize;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_buffer_main);
  
      enableButton(R.id.StartButton,true);
      enableButton(R.id.StopButton,false);
  
      /* Assign Button Click Handlers */
      ((Button)findViewById(R.id.StartButton)).setOnClickListener(btnClick);
      ((Button)findViewById(R.id.StopButton)).setOnClickListener(btnClick);
  
      Log.d(TAG, "\n ==Starting Application.. ==");
  }
  
  /* Method for Recording and Playing in a loop */
  public void run_loop (boolean isRunning)
  {
      int readbytes, writebytes, state;
      Log.d(TAG, "===== Entering Loop ===== ");
  
      if (isRunning == true) {
          do {
              bufferSize = 640; /* since configuration would return 640 size in buffer */
              recorder = findAudioRecord(recorder);
              if (recorder == null) {
                  Log.e(TAG, "====== findAudioRecord : Returned Error! =======");
                  return;
              }
  
              if (recorder.STATE_INITIALIZED == recorder.getState())
              {
                  recorder.startRecording();
  
                  readbytes = 0;              /* Reset read for next Iteration */
                  readbytes = recorder.read(buffer, 0, bufferSize);
  
                  /* Error Checking Code for AudioRecord */
                  if(-1 == checkAudioRecordforError(readbytes)) 
                  {
                      Log.d(TAG, "========= Read Error =========");
                      return;
                  }
  
                  Log.d(TAG, "\n\n===== Read : Sizeof Buffer:"+buffer.length+"=== readbytes: ["+readbytes+"]=====");
                  recorder.stop();
                  recorder.release();
  
              }else {
                  state = recorder.getState();
                  Log.d(TAG, "========= Else Part : state : "+state+"=========");
              }
  
              Log.d(TAG, "========= Reading Completed =========");
  
  
              /** ======== API for Playing ===========  **/
  
              track = findAudioTrack(track);
              if (track == null) {
                  Log.e(TAG, "========= findAudioTrack : Returned Error! ========== ");
                  return;
              }
  
              if (track.STATE_INITIALIZED == track.getState()) 
              {
                  writebytes = 0;                             /* Reset write bytes for next Iteration */
                  track.play();
  
                  writebytes = track.write(buffer, 0, bufferSize);
                  Log.d(TAG, "\n\n===== Write : Sizeof Buffer:"+ bufferSize +"==== writebytes: ["+writebytes+"]======== ");
  
                  /* Error Checking Code for AudioRecord */
                  if (-1 == checkAudioTrackforError(writebytes)) 
                  {
                      Log.d(TAG, "========= Write Error =========");
                      return;
                  }
  
                  track.stop();
                  track.release();
              }
              else {
                  state = track.getState();
                  Log.d(TAG, "========= Else Part : state : "+state+"=========");
              }
  
          } while(true);
      }
      return;
  }
  /* Method for Initializing   AudioTrack for Playing Purpose */
  public AudioTrack findAudioTrack (AudioTrack track)
  {
      Log.d(TAG, "========== Initialising Playing API ============");
  
      bufferSize = AudioTrack.getMinBufferSize(8000, 
              AudioFormat.CHANNEL_OUT_MONO, 
              AudioFormat.ENCODING_PCM_16BIT);        /* Return 640 */
  
      Log.d(TAG, "========= AudioTrack ==&gt; bufferSize : "+bufferSize+"=========");
  
      if (bufferSize != AudioTrack.ERROR_BAD_VALUE) 
      {
          track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
                  AudioFormat.CHANNEL_OUT_MONO, 
                  AudioFormat.ENCODING_PCM_16BIT, bufferSize, 
                  AudioTrack.MODE_STREAM);
  
          if (track.getState() == AudioTrack.STATE_UNINITIALIZED) {
              Log.e(TAG, "=========== AudioTrack UnInitilaised ===========");
              return null;
          }
      }
      return track;
  }
  
  /* Method for Initializing AudioRecord for Recording Purpose */
  public AudioRecord findAudioRecord (AudioRecord recorder)
  {
      Log.d(TAG, "======== Initializing Record API ==========");
  
      bufferSize = AudioRecord.getMinBufferSize(8000,
              AudioFormat.CHANNEL_IN_MONO,
              AudioFormat.ENCODING_PCM_16BIT);
  
  
      if (bufferSize != AudioRecord.ERROR_BAD_VALUE) 
      {
          recorder = new AudioRecord(AudioSource.DEFAULT, 8000, 
                  AudioFormat.CHANNEL_IN_MONO,
                  AudioFormat.ENCODING_PCM_16BIT, bufferSize);
  
          if (recorder.getState() == AudioRecord.STATE_UNINITIALIZED) {
              Log.e(TAG, "========= AudioRecord UnInitilaised ============= ");
              return null;
          }
      }
      return recorder;
  }
  
  /* Method for Error Checking - AudioRecord */
  public int checkAudioRecordforError(int readbytes)
  {
      if (readbytes ==  recorder.ERROR_INVALID_OPERATION || readbytes ==  recorder.ERROR_BAD_VALUE) 
      {
          if(readbytes == AudioRecord.ERROR_INVALID_OPERATION)
              Log.d(TAG, "========= read Error : ERROR_INVALID_OPERATION ===========");
          else if (readbytes == AudioRecord.ERROR_BAD_VALUE)
              Log.d(TAG, "========= read Error : ERROR_BAD_VALUE ===========");
          else if (readbytes == AudioRecord.ERROR)
              Log.d(TAG, "========= read Error : ERROR Unknown ===========");
          return -1;
      }
      return readbytes;
  }
  
  /* Method for Error Checking - AudioTrack */
  public int checkAudioTrackforError(int writebytes)
  {
      if (writebytes ==  track.ERROR_INVALID_OPERATION || writebytes ==  track.ERROR_BAD_VALUE)
      {
          if(writebytes == track.ERROR_INVALID_OPERATION)
              Log.d(TAG, "========= read Error : ERROR_INVALID_OPERATION ===========");
          else if (writebytes == track.ERROR_BAD_VALUE)
              Log.d(TAG, "========= read Error : ERROR_BAD_VALUE ===========");
          else if (writebytes == track.ERROR)
              Log.d(TAG, "========= read Error : ERROR Unknown ===========");
          return -1;
      }
      return writebytes;
  }
  
  /* Method for Mapping Button Click */
  private View.OnClickListener btnClick = new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          switch(v.getId()){
          case R.id.StartButton:
          {
              Log.d(TAG, "======= Start Recording =======");
              isRunning = true;
              Log.d(TAG, "========== isRunning = true =============");
              run_loop (isRunning);
              enableButton(R.id.StartButton,false);
              enableButton(R.id.StopButton,true);
              break;
          }
          case R.id.StopButton:
          {
              Log.d(TAG, "======== Stop Recording =========");
              isRunning = false;
              Log.d(TAG, "========== isRunning = false =============");
              run_loop (isRunning);
              enableButton(R.id.StopButton,false);
              enableButton(R.id.StartButton,true);
              break;
          }
          }
      }
  }; 
  /* Function to Enable/Disable Buttons */
  private void enableButton(int id,boolean isEnable){
      ((Button)findViewById(id)).setEnabled(isEnable);
  }
  }
  </code></pre>
  
  <p>There is no read write failure anywhere.</p>
  
  <p>Logcat Output:</p>
  
  <pre><code>D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ==Starting Application.. ==
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========Start Recording========
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========== isRunning = true =============
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Entering Loop ===== 
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): =========== Initializing Record API =======
  E/ACDB-LOADER(  213): Error: ACDB AudProc vol returned = -19
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Read : Sizeof Buffer:640=== readbytes: [640]=====
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========= Reading Completed =========
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========== Initializing Playing API     ========
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========= AudioTrack ==&gt; bufferSize : 640=========
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Write : Sizeof Buffer:640==== writebytes: [640]======== 
  D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): =========Initialising Record API =========
  E/ACDB-LOADER(  213): Error: ACDB AudProc vol returned = -19
  </code></pre>
  
  <p>I need to verify if <code>E/ACDB-LOADER(  213): Error: ACDB AudProc vol returned = -19</code> is responsible for the same.<br>
  The above Audio Configuration is for <code>Google Nexus 5</code>. Might fails to initialize on other devices.    </p>
  
  <p>The Android GUI contains two buttons <code>Start</code> and <code>Stop</code>.</p>
  
  <p>Please help me resolve the above Issue.</p>