我有一个应用程序从麦克风录制音频,然后实时对音频进行一些后处理,因此我必须使用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。
由于我的效果处理代码,问题肯定是不,因为我已尝试将其评论出来并在两种情况下获得相同的结果。我已经在网上搜索了其他代码或可能遇到类似问题的人,但没有找到任何内容。
答案 0 :(得分:1)
我根本不了解Android SDK,但getFloatingPointBufferFromPcmData
和getShortPcmBufferFromFloatingPointData
看起来不像标准API函数,尽管有可爱的命名约定。 :)
你自己写过这些吗?也许他们使用共享状态并在循环迭代中累积结果?如果这些是您的实施,请分享这些代码,以便我们帮助您确定实际问题。
您也有可能以错误的格式(比特数,字节顺序)写出PCM数据,并且您的音频编辑器正在根据不同的格式解释数据,导致出现错误解码的音频数据看起来好像有一些积累效应正在发生。
如果这些查询都没有引导您解决问题,那么我的下一个建议是为每个循环迭代创建一个新的microphoneBuffer实例,而不是在while循环中使用单个实例。
同样,我不是Android SDK专家,所以这些只是处理几乎所有API及其实现细节的多年经验所产生的一般建议。
希望有助于诊断您的问题!
答案 1 :(得分:0)
有了沉默,可能会有一个自动增益控制,增加输入增益超出理由,试图找到“某些东西”供你录制(当然还能找到本底噪声)
如果您将PC扬声器设置为播放一个好的音频正弦波会发生什么 - 噪音是否仍然存在或者您是否继续记录正弦波?
答案 2 :(得分:0)
Bah,实际上问题不是Android的问题 - 它是由我用来将原始PCM数据转换为WAV格式的软件引起的。在端序转换中显然存在一些错误,因为ARM芯片是大端,WAV是小端。当我们尝试在Audacity中打开原始PCM文件时,它们看起来很好。