我正在开展一项雄心勃勃的项目,通过耳机或耳机在Android上实现主动降噪。
我的目标是用Android手机麦克风记录环境噪音,反相(从音频记录中拉出的短值上的简单* -1),然后通过耳机播放倒置的波形。如果延迟和幅度接近正确,它应该使环境中的大量机械结构噪声无效。
这是我到目前为止所得到的:
@Override
public void run()
{
Log.i("Audio", "Running Audio Thread");
AudioRecord recorder = null;
AudioTrack track = null;
short[][] buffers = new short[256][160];
int ix = 0;
/*
* Initialize buffer to hold continuously recorded audio data, start recording, and start
* playback.
*/
try
{
int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
//NoiseSuppressor ns = NoiseSuppressor.create(recorder.getAudioSessionId());
//ns.setEnabled(true);
track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);
recorder.startRecording();
track.play();
/*
* Loops until something outside of this thread stops it.
* Reads the data from the recorder and writes it to the audio track for playback.
*/
while(!stopped)
{
short[] buffer = buffers[ix++ % buffers.length];
N = recorder.read(buffer,0,buffer.length);
for(int iii = 0;iii<buffer.length;iii++){
//Log.i("Data","Value: "+buffer[iii]);
buffer[iii] = buffer[iii] *= -1;
}
track.write(buffer, 0, buffer.length);
}
}
catch(Throwable x)
{
Log.w("Audio", "Error reading voice audio", x);
}
/*
* Frees the thread's resources after the loop completes so that it can be run again
*/
finally
{
recorder.stop();
recorder.release();
track.stop();
track.release();
}
}
我一时兴奋地发现Android API实际上已经有了一个NoiseSuppression算法(你会在上面看到它注释掉)。我用它进行了测试,发现NoiseSuppressor没有做太多的事情来消除恒定的音调,这使我相信它实际上只是在非人声频率下执行带通滤波器。
所以,我的问题:
1)上述代码从麦克风录制到耳机播放大约需要250-500毫秒。这种延迟很糟糕,减少它会很棒。任何建议都会受到赞赏。
2)无论延迟有多紧,我的理解是回放波形将与实际环境噪声波形相位偏移。这表明我需要执行某种波形匹配来计算此偏移并进行补偿。关于如何计算的想法?
3)在补偿延迟方面,这会是什么样子?我在每个周期都有一系列短路,那么30ms或250ms的延迟是什么样的呢?
我意识到这种方法存在的基本问题是手机的位置不在头部旁边可能会引入一些错误,但我对某些动态或固定延迟修正有希望也许有可能克服它。
感谢您的任何建议。
答案 0 :(得分:4)
即使你能够对延迟做些什么,这也是一个难题,因为你不知道手机距离耳朵的距离,而且还有一个事实是距离不固定(因为用户会移动电话),再加上你没有为每只耳朵配备一个麦克风这一事实(所以你不知道一只耳朵会在它到达之前是什么波,即使你有零延迟)
话虽如此,您可以做一些可以取消高周期性波形的事情。你所能做的只是允许用户手动调整每只耳朵的时间延迟 - 因为耳朵附近没有麦克风,你的代码中无法知道你是否是使问题更好或更糟。