我正在尝试在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
中的音频输入源之间究竟有什么区别?为什么他们的一些选择导致平板电脑和手机的不同行为?
---编辑---
另外我最近被告知,在手机中,执行该程序后,手机中的输出听起来很小,退出程序后,手机正常操作中的声音继续保持在那个小音量。程序终止后,如何确保所有与声音相关的声音(或任何其他电话资源)恢复原始设置?
---编辑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
---编辑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);
答案 0 :(得分:1)
如果您需要有关SDK API documentation中所提供内容的更多信息,那么我建议您推荐相应的source code吗?同样,您也可以为MediaRecorder类做同样的事情。
在您运行应用程序时,问题是您的问题已经改变,我建议您在启动应用程序时(首先使用硬件资源上的相应getMode()
方法)首先阅读模式并保存它们退出/进入后台应用程序时(使用硬件资源上的相应setMode()
方法)恢复相同的操作。这里的硬件资源是MediaRecorder和AudioManager。
HTH。