android - 从Android 2.2中的麦克风录制时出现奇怪的失真

标签 android audio audiorecord

我有一个应用程序,它可以记录来自麦克风的音频,然后实时对音频进行一些后处理,因此我必须使用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();

上面的代码工作正常,我实际上可以录制设备中的音频,并且听到声音等。问题是几秒钟后,一个非常奇怪的失真模式开始出现,直到整个信号被淹没为止。这是静音录音的屏幕截图,我是通过将一些录音带放在麦克风上并让该应用录制一分钟左右来制作的:

原始wave文件可以是downloaded here

由于我的效果处理代码,问题肯定是而不是,因为我尝试将其注释掉并在两种情况下均获得相同的结果。我在网上搜寻了其他代码或可能遇到类似问题但未发现任何问题的人员。

最佳答案

我一点也不了解Android SDK,尽管命名约定很可爱,但getFloatingPointBufferFromPcmDatagetShortPcmBufferFromFloatingPointData看起来并不像标准API函数。 :)

你自己写这些吗?也许他们使用共享状态并在循环迭代中累积结果?如果这些是您的实现,请共享这些代码,以便我们可以帮助您确定实际问题。

还有可能是您以错误的格式(位数,字节序)写出了PCM数据,并且音频编辑器根据另一种格式解释了该数据,从而导致音频数据解码不正确,从而似乎在欺骗性地出现有一些积累效应正在发生。

如果这些查询都不能解决您的问题,那么我的下一个建议是为每个循环迭代创建一个新的MikeBuffer实例,而不是在while循环中使用单个实例。

再说一次,我不是Android SDK专家,所以这些只是一般性的建议,这些建议是由多年处理几乎所有API及其实现细节的经验所得出的。

希望能帮助您诊断问题!

关于android - 从Android 2.2中的麦克风录制时出现奇怪的失真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3934502/

相关文章:

android - MediaCodec 没有任何可用的输入缓冲区

android - 如何正确设置 Android 的行高?

android - 从 MergeAdapter 中删除 View

haskell - 使用 Haskell 绑定(bind)保存脉冲音频流

audio - FMOD 如何在一些自定义 channel 组中设置一组事件?

php - ActionScript从php加载外部声音文件,并从php响应中找出实际的文件名?

android - 将原始 PCM 位保存到压缩音频 AAC/AMR 文件中

android - 在调试期间防止 ApplicationNotResponding

android - Travis CI apk 路径

Android 模拟器似乎以 96khz 的频率录制音频