我有一个应用程序,它可以记录来自麦克风的音频,然后实时对音频进行一些后处理,因此我必须使用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,尽管命名约定很可爱,但getFloatingPointBufferFromPcmData
和getShortPcmBufferFromFloatingPointData
看起来并不像标准API函数。 :)
你自己写这些吗?也许他们使用共享状态并在循环迭代中累积结果?如果这些是您的实现,请共享这些代码,以便我们可以帮助您确定实际问题。
还有可能是您以错误的格式(位数,字节序)写出了PCM数据,并且音频编辑器根据另一种格式解释了该数据,从而导致音频数据解码不正确,从而似乎在欺骗性地出现有一些积累效应正在发生。
如果这些查询都不能解决您的问题,那么我的下一个建议是为每个循环迭代创建一个新的MikeBuffer实例,而不是在while循环中使用单个实例。
再说一次,我不是Android SDK专家,所以这些只是一般性的建议,这些建议是由多年处理几乎所有API及其实现细节的经验所得出的。
希望能帮助您诊断问题!
关于android - 从Android 2.2中的麦克风录制时出现奇怪的失真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3934502/