2014-10-07 17 views
7

Sto registrando audio con AudioRecord in formato PCM16LE, 8000Hz, 1canale. Registra bene nelle versioni Android 2.3.3-4.4.4, ma registra strani suoni intermittenti in Android L (5.0) Developer Preview (su nexus 5, nexus 7 ed emulatore).AudioRecord registra audio intermittente in Android L Developer Preview

Ecco il campione del suono registrato (prima metà - la registrazione, la seconda metà - riproduzione): https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0

ho cercato di riprodurre l'audio registrato con tariffa diversa campione (4000, 16000) e come 8bit, ma il suono continua ad essere intermittente. Quale potrebbe essere il problema con questo suono?

Sto usando questo AudioRecordTask per registrare l'audio con getAudioRecord() per l'inizializzazione di ingresso (senza errori restituiti durante il funzionamento; la ricezione di blocchi audio di dimensioni anche per il valore internalBufferSize):

public final int SAMPLING_RATE = 8000; 

private AudioRecord getAudioRecord() { 
    int internalBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT); //returns 640 

    internalBufferSize = 8000; //also tried returned value (640) and values 2560, 30000 - no changes 

    final int SOURCE; 
    if (Build.VERSION.SDK_INT < 11) { 
     SOURCE = MediaRecorder.AudioSource.MIC; 
    } else { 
     SOURCE = MediaRecorder.AudioSource.VOICE_COMMUNICATION; 
    } 

    AudioRecord record = new AudioRecord(SOURCE, 
      SAMPLING_RATE, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT, 
      internalBufferSize); 

    int state = record.getState(); 
    if (state != AudioRecord.STATE_INITIALIZED) { 
     try { 
      record.release(); 
     } catch (Exception e) { 
     } 
     return null; 
    } 

    if (record.getState() == android.media.AudioRecord.STATE_INITIALIZED) { 
     record.startRecording(); 
    } else { 
     record.release(); 
     return null; 
    } 
    return record; 
} 

private class AudioRecordTask extends AsyncTask<Void, Void, Void> { 
    final int PARTIAL_BUFFER_SIZE = SAMPLING_RATE; 
    final int NECESSARY_BUFFER_SIZE = 15 * PARTIAL_BUFFER_SIZE * Short.SIZE/8; 
    final int FULL_BUFFER_SIZE = NECESSARY_BUFFER_SIZE * 2; //XXX: * 2 for the case when system returns more data than needed 
    short[] mBuffer; 
    int mTotalSize; 
    int mTotalSizeInBytes; 
    boolean mResult; 
    private Object mLock = new Object(); 

    @Override 
    protected void onPreExecute() 
    { 
     mIsRecording = true; 

     mBuffer = new short[FULL_BUFFER_SIZE]; 
     mTotalSize = 0; 
     mTotalSizeInBytes = 0; 
     mResult = false; 
    } 

    @Override 
    protected Void doInBackground(Void... arg0) { 
     synchronized (mLock) { 
      android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); 
      AudioRecord record = getAudioRecord(); 
      if (record == null) { 
       mResult = false; 
       return null; 
      } 

      for (int i = 0; i < 15 * 100; i++) { //XXX: * 100 to record enough data (system can return lesser than needed) 
       int datalen = record.read(mBuffer, mTotalSize, PARTIAL_BUFFER_SIZE); 
       if (datalen > 0) { 
        mTotalSize += datalen; 
        mTotalSizeInBytes = mTotalSize*2; 
       } else { 
        Log.w("", "error " + datalen + " in AudioRecord.read"); 
       } 
       if (isCancelled() || mTotalSizeInBytes > NECESSARY_BUFFER_SIZE) { 
        break; 
       } 
      } 
      if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { 
       record.stop(); 
      } 

      record.release(); 
      mResult = true; 
      return null; 
     } 
    } 

    @Override 
    protected void onPostExecute(Void r) { 
     synchronized (mLock) { 
      mIsRecording = false; 
      fin(); 
     } 
    } 

    @Override 
    protected void onCancelled() { 
     //XXX: on old Androids (e.g. 2.3.3) onCancelled being called while doInBackground is still running 
     synchronized (mLock) { 
      mIsRecording = false; 
      if (mAbort) { 
       return; 
      } 
      fin(); 
     } 
    } 

    private void fin() { 
     if (mResult && mTotalSizeInBytes > 0) { 
      sendRecordedAudioToServer(mBuffer, mTotalSize, mTotalSizeInBytes); 
     } else { 
      showError(null); 
     } 
    } 
} 

risposta

4

Si tratta di un bug in Android L Developer Preview: https://code.google.com/p/android-developer-preview/issues/detail?id=1492

AudioRecord.read per breve [] l'argomento del buffer restituisce il valore in byte anziché il valore in cortocircuito.

Come soluzione alternativa utilizzare AudioRecord.read con byte [] buffer.

+0

Questo problema sembra essere risolto nella versione 5.0, tuttavia esiste un problema correlato in cui il parametro di offset viene erroneamente raddoppiato. Vedere https://code.google.com/p/android/issues/detail?id=80866 quando si tenta di per inviare una patch mi è stato detto che è anche fissato internamente, anche se non ha idea di quando verrà visualizzato in una versione. –

+0

Mi sono appena schiantato in questo (credo) in 5.0.2. Questo significa che se il byte [] buffer read è usato tutto funziona bene, incluso il parametro offset, o è ancora doppio? – nmw01223

+0

quando si utilizza il buffer byte [] tutto è ok incluso offset (era così su 5.0 e 5.0.1, non ancora testato su 5.0.2 ancora) –

Problemi correlati