0

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

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

波形文件失真截图

原始波形文件可以在这里下载

问题绝对不是由于我的效果处理代码,因为我尝试将其注释掉并在两种情况下得到相同的结果。我在网上搜索了其他代码或可能遇到类似问题的人,但没有找到任何东西。

4

3 回答 3

2

我根本不知道 Android SDK,但getFloatingPointBufferFromPcmData看起来getShortPcmBufferFromFloatingPointData不像标准的 API 函数,尽管命名约定很好。:)

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

还有一种可能是您以错误的格式(位数,字节序)写出 PCM 数据,并且您的音频编辑器正在根据不同的格式解释数据,从而导致解码错误的音频数据看起来像有一些积累效应发生。

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

同样,我不是 Android SDK 专家,因此这些只是根据多年处理几乎所有类型的 API 及其实现细节的经验得出的一般建议。

希望这有助于诊断您的问题!

于 2010-10-14T15:08:50.407 回答
0

在静音的情况下,可能会有一个自动增益控制,它会超出合理地增加输入增益,试图找到“东西”让你记录(当然还有找到本底噪声)

如果您将 PC 扬声器设置为播放良好的音频正弦波会发生什么 - 噪音仍然出现还是您继续记录正弦波?

于 2010-10-14T15:52:06.047 回答
0

呸,实际上问题不是 Android 的错——它是由我用来将原始 PCM 数据转换为 WAV 格式的软件引起的。由于ARM芯片是大端,WAV是小端,字节序转换显然有一些错误。当我们尝试在 Audacity 中打开原始 PCM 文件时,它们看起来还不错。

于 2010-10-15T10:26:52.033 回答