【问题标题】:what is the difference between various sound sources in android system?android系统中各种声源有什么区别?
【发布时间】:2013-10-17 03:04:57
【问题描述】:

我正在尝试在 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_COMMUNICATIONMediaRecorder.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);  

【问题讨论】:

  • AudioTrack 构造函数的第一个参数是流类型,而不是音频模式。你很幸运,MODE_IN_COMMUNICATION 与 STREAM_MUSIC 具有相同的值。
  • 是的,我意识到,我已经在我的代码中更改了它,但我仍然不明白为什么程序在平板电脑和手机中的行为不同
  • 您是否在应用中的任何位置使用setMode?另外,你正在制作什么类型的录音?您是在录制电话附近的声音(例如录音机)还是远处(例如几米)的声音?
  • 请看我的更新。以前我习惯如上所示进行初始化。但显然当时没有看到这个问题(或者可能是,但他们只是没有注意到)所以我删除了setMode() 部分。其他人正在手机上对此进行测试,我根据他们的反馈在这里发布。目前我如编辑 3 所示进行初始化。
  • 请看我更新的帖子

标签: android audio audiorecord audiotrack


【解决方案1】:

如果您需要SDK API documentation 中给出的更多信息,那么我可以建议您参考相应的source code 吗?同样,您可以对 MediaRecorder 类执行相同的操作。

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

HTH。

【讨论】:

  • 很抱歉,但是查看源代码并不能确切地知道AudioManager.MODE_IN_COMMUNICATION 是什么。源代码只是显示 MODE_IN_COMMUNICATION 是一个public static int,这也是 android 开发者网站中给出的所有内容。是否有任何其他来源提供有关 android 中低级音频任务的更多详细信息?
  • 另外,我可以找到 AudioManager(音频输出)的 getMode() 函数,但我找不到 AudioSource(input) 的等效 getMode()。我发现的唯一东西是MediaRecorder 类中的getAudioSourceMax(),它似乎也总是返回一个常量值 6(源代码:grepcode.com/file/repository.grepcode.com/java/ext/…
  • @user13267 你试过查看内核源代码吗?我建议你从谷歌下载源代码 - source.android.com/source/downloading.html。其他可能的模块可能位于“硬件”或“框架”文件夹下。
  • This document describes how to download the source tree for a specific Android code-line. 这是否意味着我只能下载特定课程的代码?此下载的代码与您在答案中链接的网页中显示的源代码有什么不同?此外,看起来下载说明适用于 linux 计算机,而我只有 windows XP
  • 我相信“master”分支包含所有 API 级别的代码行。如果您需要特定的 API 级别,请使用带有“-b”选项的“repo init”命令。此处提供了有关 google 通过代码行表示的更多信息:source.android.com/source/code-lines.html。您可以在 Windows XP 上安装 cygwin 并签出源代码。在你这样做之前,你必须先做这个设置:source.android.com/source/initializing.html。 Windows XP 上可能有我可能不知道的更简单的方法。检查代码行与网站(grepcode 等)的优点是存在内核 src。
猜你喜欢
  • 1970-01-01
  • 2015-10-18
  • 1970-01-01
  • 2015-03-25
  • 2011-05-06
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 2010-11-04
相关资源
最近更新 更多