Странные искажения при записи с микрофона на Android 2.2

StackOverflow https://stackoverflow.com/questions/3934502

  •  30-09-2019
  •  | 
  •  

Вопрос

У меня есть приложение, которое записывает звук с микрофона, а затем выполняет некоторую постобработку звука в реальном времени, поэтому я должен использовать AudioRecord класс вместо стандартного MediaRecorder.Мой код для записи такой:

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();

Приведенный выше код работает нормально, и я действительно могу записывать звук с устройства, слышу свой голос и все такое.Проблема в том, что через несколько секунд начинает проявляться очень странная картина искажений, пока весь сигнал не заглушается.Вот скриншот записи тишины, которую я сделал, наложив ленту на микрофон и позволив приложению записывать в течение минуты или около того:

Screenshot of distortion in wave file

Исходный волновой файл может быть скачал здесь.

Проблема определенно нет из-за моего кода обработки эффектов, поскольку я пытался его закомментировать и получил одинаковые результаты в обоих случаях.Я поискал в Интернете другой код или людей, у которых могут возникнуть подобные проблемы, но ничего не нашел.

Это было полезно?

Решение 3

Ба, на самом деле проблема возникла не по вине Android — она была вызвана программным обеспечением, которое я использовал для преобразования необработанных данных PCM в формат WAV.Очевидно, существует некоторая ошибка при преобразовании байтов с порядком байтов, поскольку чипы ARM имеют обратный порядок байтов, а WAV — прямой порядок байтов.Когда мы попытались открыть необработанные файлы PCM в Audacity, они выглядели нормально.

Другие советы

Я не знаю Android SDK вообще, но getFloatingPointBufferFromPcmData а также getShortPcmBufferFromFloatingPointData Не похоже на стандартные функции API, несмотря на прекрасную конвенцию именования. :)

Ты написал их сами? Возможно, они используют общие состояния и накапливания результатов по итерациям петли? Если это ваша реализация, пожалуйста, поделитесь этим кодом, чтобы мы могли помочь вам определить фактическую проблему.

Существует также вероятность того, что вы выписываете данные PCM в неправильном формате (количество битов, эндин), и что ваш аудиоредактор интерпретирует данные в соответствии с другим форматом, что приводит к неправильному декодированию аудиоданных, что происходит обманчиво Существует некоторое влияние накапливания.

Если ни одно из этих запросов не приведет вас к решению вашей проблемы, то моя следующая рекомендация будет создание нового экземпляра микрофонбуфера для каждой итерации цикла, а не используя один экземпляр по всему циклу.

Опять же, я не Android SDK Expert, так что это просто общие рекомендации, связанные с учетом лет опыта, посвященных практически во всем видах API и деталей реализации.

Надеюсь, что помогает диагностировать вашу проблему!

Благодаря тишине может быть автоматический контроль усиления, который повышает входное усиление по сравнению с разумом, пытаясь найти «что-то» для записи (и, конечно, нахождение уровня шума)

Что произойдет, если вы устанавливаете свои компьютерные колонки для воспроизведения симпатичной звуковой частоты синусоида.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top