Domanda

devo un'applicazione che registra l'audio dal microfono e poi esegue alcune di post-elaborazione in audio in tempo reale, quindi devo usare la classe AudioRecord al posto del MediaRecorder standard. Il mio codice per la registrazione è in quanto tale:

DataOutputStream dataOutputStreamInstance = new DataOutputStream(bufferedStreamInstance);
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

int bufferSize = AudioRecord.getMinBufferSize((int)sampleRate, channelConfiguration, DEFAULT_AUDIO_ENCODING) * 2;
short[] microphoneBuffer = new short[bufferSize];
float[] processingBuffer = new float[bufferSize];
short[] outputBuffer = new short[bufferSize];

AudioRecord microphoneRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

microphoneRecorder.startRecording();
while(isRecording) {
  synchronized(mutex) { ... check for pause condition, wait, etc. ... }
  int numSamplesRead = microphoneRecorder.read(microphoneBuffer, 0, bufferSize);

  // Convert 16-bit short data to floating point
  getFloatingPointBufferFromPcmData(microphoneBuffer, processingBuffer, bufferSize);

  doProcessingStuff(processingBuffer, bufferSize);

  if(numSamplesRead == AudioRecord.ERROR_INVALID_OPERATION) {
    throw new IllegalStateException("read() returned AudioRecord.ERROR_INVALID_OPERATION");
  }
  else if(numSamplesRead == AudioRecord.ERROR_BAD_VALUE) {
    throw new IllegalStateException("read() returned AudioRecord.ERROR_BAD_VALUE");
  }

  try {
    // Dump the output to the target file in 16-bit short format
    getShortPcmBufferFromFloatingPointData(processingBuffer, outputBuffer, bufferSize);
    for(int bufferIndex = 0; bufferIndex < numSamplesRead; bufferIndex++) {
      dataOutputStreamInstance.writeShort(outputBuffer[bufferIndex]);
    }
  }
  catch(Exception e) {
    Log.e("MyApp", "Error while writing audio data to file: " + e.getMessage());
    e.getStackTrace();
  }
}

microphoneRecorder.stop();

Il codice sopra funziona bene, e posso realmente registrare audio dal dispositivo, e sento la mia voce e così via. Il problema è che dopo alcuni secondi, una strana modello di distorsione inizia ad emergere finché l'intero segnale è soffocata. Ecco uno screenshot di una registrazione di silenzio che ho fatto mettendo un po 'di nastro sopra il microfono e lasciare che il record di app per un minuto o giù di lì:

Schermata di distorsione nel file wave

Il file onda originale può essere scaricato qui .

Il problema è sicuramente non a causa del mio codice di elaborazione effetto, come ho cercato di commentare fuori e ottenere gli stessi risultati in entrambi i casi. Ho perlustrato il web per altro codice o le persone che si sono verificate problemi simili, ma non ho trovato nulla.

È stato utile?

Soluzione 3

Bah, in realtà il problema era non per colpa di Android - è stato causato dal software che stavo usando per convertire i dati grezzi PCM in formato WAV. C'è evidentemente un errore nella conversione endian, dal momento che i chip ARM sono big endian e WAV è little endian. Quando abbiamo provato ad aprire i file RAW PCM in Audacity, sembravano bene.

Altri suggerimenti

Non so Android SDK a tutti, ma getFloatingPointBufferFromPcmData e getShortPcmBufferFromFloatingPointData non assomigliano funzioni API standard, nonostante la bella convenzione di denominazione. :)

Hai scritto questi te stesso? Forse stanno usando stato condiviso e accumulando risultati attraverso iterazioni del ciclo? Se questi sono l'implementazione, si prega di condividere il codice di questi in modo che possiamo aiutarvi a identificare il problema reale.

C'è anche la possibilità che si sta scrivendo i dati PCM nel formato sbagliato (numero di bit, endianness) e che il vostro editor audio sta interpretando i dati secondo un formato diverso con conseguente dati audio in modo non corretto decodificati che appare ingannevolmente come se ci fosse qualche effetto accumulo accada.

Se nessuna di queste indagini porta a risolvere il problema, allora il mio prossimo consiglio sarebbe quello di creare una nuova istanza microphoneBuffer per ogni iterazione del ciclo, invece di utilizzare una singola istanza in tutto il ciclo while.

Anche in questo caso, io non sono un esperto di Android SDK, quindi queste sono pezzi solo generali di consulenza derivanti da anni di esperienza nel trattare con praticamente tutti i tipi di API e dettagli di implementazione dello stesso.

La speranza che aiuta a diagnosticare il problema!

Con il silenzio ci potrebbe essere un controllo automatico di guadagno che sta aumentando il guadagno di ingresso oltre la ragione, cercando di trovare "qualcosa" per voi per registrare (e, naturalmente, trovare il rumore di fondo)

Che cosa accade se si imposta gli altoparlanti del PC per giocare un bel sinusoide frequenza audio -? Non il rumore ancora venire o si continua a registrare l'onda sinusoidale

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top