2

我正在尝试在 Android 中构建一个实时降噪程序,
我使用 AudioRecord 获取原始输入声音数据并使用 AudioTrack 来播放它。
在初始化 Audiorecord 时,我使用了代码

record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, min);  

回放时我使用代码

track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);   

这些设置非常适合我的 Nexus 7 平板电脑(不是手机),但是当我尝试在 LG Optimus(或任何其他手机)上运行它时,输出音量非常低,即使在硬件最大时也是如此。如果我将 AudioManager.MODE_IN_COMMUNICATION 更改为其他一些值,有时根本没有输出,或者有时在第一次执行程序时输出很大,然后在后续运行中没有输出。这个问题在 Nexus 7 中没有出现(虽然某些选项确实会导致 Nexus 7 中没有声音输出)

(我对原始音频数据执行 FFT,然后通过降噪算法函数运行它以计算 FFT 后每个频率分量的增益值,并将最终输出乘以 thsi 增益值。我已经能够弄清楚,只要有是扬声器没有输出,这通常是由于这些增益值获得了 NaN 值,但这是一个不同的问题)。

Audiomanager我想知道的是,中定义的各种类型的音频输出源,比如AudioManager.MODE_IN_COMMUNICATION和中的音频输入源到底有什么区别MediaRecorder.AudioSource?为什么他们的某些选项会导致平板电脑和手机出现不同的行为?

--- EDIT ---
另外我最近被告知,在手机中,执行此程序后,手机中的输出声音很小,退出程序后,手机正常运行中的声音继续停留在那个小音量。一旦程序终止,如何确保所有与声音相关的(或任何其他手机资源)恢复到原来的设置?

--- 编辑 2 ---
旧的初始化代码:

int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, min);
int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_COMMUNICATION); // ORIGINAL   AudioManager.MODE_IN_COMMUNICATION  

--- EDIT 3 ---
当前初始化方案

am.setMode(AudioManager.MODE_IN_COMMUNICATION); // ADDED LATER: DELETE THIS LINE IF IT CAUSES PROBLEMS
int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, min);
int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);

--- 编辑 4 ---
onResume() 中的代码

am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
currentAudioManagerMode = am.getMode();  
... // (function with initialization code from EDIT 3)  

onPause() 中的代码

am.setMode(currentAudioManagerMode);  
4

1 回答 1

1

如果您需要SDK API 文档中提供的更多信息,那么我可以建议您参考相应的源代码吗?同样,您可以对 MediaRecorder 类执行相同的操作。

WRT 对于您在运行应用程序后更改音频设置的问题,我建议您在启动应用程序时首先阅读模式(使用getMode()硬件资源上的相应方法)并保存它们并在退出/离开时恢复相同-进入您的应用程序的后台(使用setMode()硬件资源上的相应方法)。这里的硬件资源是 MediaRecorder 和 AudioManager。

HTH。

于 2013-10-17T05:16:01.307 回答