如何避免使用AudioRecord进行自动增益控制?

问题描述 投票:13回答:4

如何使用android.media.AudioRecord进行录音,而无需任何智能手机制造商相关的花式信号处理,如自动增益控制(AGC)和/或均衡,噪声抑制,回声消除,......只是纯麦克风信号?

Background

MediaRecorder.AudioSource提供九个常数,

  • DEFAULTMIC最初在那里,
  • API API 4中添加了VOICE_UPLINKVOICE_DOWNLINKVOICE_CALL
  • API 7中添加了CAMCORDERVOICE_RECOGNITION
  • VOICE_COMMUNICATION在API 11中添加,
  • REMOTE_SUBMIX在API 19中添加但不适用于第三方应用程序。

但是他们都没有在所有智能手机上做得干净。相反,我必须找出自己似乎,哪个设备使用MediaRecorder.AudioSource恒定的信号处理块的哪种组合。

很高兴在API级别20中添加像PURE_MIC这样的第十个常量。

但只要没有,我可以做些什么呢?

android api audio-recording
4个回答
6
投票

简短的回答是“没什么”。

AudioSources对应于各种逻辑音频输入设备,具体取决于您连接到手机的附件和当前用例,而后者又与物理设备(主要内置麦克风,辅助麦克风,有线耳机麦克风等)相对应用不同的调音。

物流设备和调谐的每个这样的组合由OEM修整,以满足外部要求(例如CTS,操作员要求等)和OEM本身设定的内部声学要求。此过程可能会导致各种滤波器(如AGC,噪声抑制,均衡等)进入硬件编解码器或多媒体DSP级别的音频输入路径。

虽然PURE_MIC源可能对某些应用程序有用,但它不是今天可用的东西。 在许多设备上,您可以使用amixer写入硬件编解码器的ALSA控件来控制麦克风增益,甚至可能是滤波器链。但是,这显然是一种非常特定于平台的方法,我还怀疑你必须以root用户或音频用户身份运行才能执行此操作。


2
投票

默认情况下,某些设备会将AGC效果添加到声音输入区域。因此,您需要获取对相应AudioEffect对象的引用并强制它禁用。

首先,获取链接到AudioRecord音频会话的AutomaticGainControl对象,然后将其设置为禁用:

if (AutomaticGainControl.isAvailable()) {
    AutomaticGainControl agc = AutomaticGainControl.create(
            myAudioRecord.getAudioSessionId()
        );
    agc.setEnabled(false);
}

1
投票

注意:大多数音频源(包括DEFAULT)将处理应用于音频信号。要录制原始音频,请选择UNPROCESSED。某些设备不支持未处理的输入。首先调用AudioManager.getProperty(“PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED”)以验证它是否可用。如果不是,请尝试使用VOICE_RECOGNITION,而不使用AGC或噪声抑制。即使不支持该属性,也可以将UNPROCESSED用作音频源,但在这种情况下无法保证信号是否未被处理。

Android文档链接https://developer.android.com/guide/topics/media/mediarecorder.html#example

    AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
    if(audioManager.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED) !=null)
        mRecorder.setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
    else
        mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);

0
投票

MIC应该没问题,其余的你需要知道它们是否得到支持。

我为此做了一堂课:

enum class AudioSource(val audioSourceValue: Int, val minApi: Int) {
    VOICE_CALL(MediaRecorder.AudioSource.VOICE_CALL, 4), DEFAULT(MediaRecorder.AudioSource.DEFAULT, 1), MIC(MediaRecorder.AudioSource.MIC, 1),
    VOICE_COMMUNICATION(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 11), CAMCORDER(MediaRecorder.AudioSource.CAMCORDER, 7),
    VOICE_RECOGNITION(MediaRecorder.AudioSource.VOICE_RECOGNITION, 7),
    VOICE_UPLINK(MediaRecorder.AudioSource.VOICE_UPLINK, 4), VOICE_DOWNLINK(MediaRecorder.AudioSource.VOICE_DOWNLINK, 4),
    @TargetApi(Build.VERSION_CODES.KITKAT)
    REMOTE_SUBMIX(MediaRecorder.AudioSource.REMOTE_SUBMIX, 19),
    @TargetApi(Build.VERSION_CODES.N)
    UNPROCESSED(MediaRecorder.AudioSource.UNPROCESSED, 24);

    fun isSupported(context: Context): Boolean =
            when {
                Build.VERSION.SDK_INT < minApi -> false
                this != UNPROCESSED -> true
                else -> {
                    val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
                    Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && "true" == audioManager.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED)
                }
            }

    companion object {
        fun getAllSupportedValues(context: Context): ArrayList<AudioSource> {
            val values = AudioSource.values()
            val result = ArrayList<AudioSource>(values.size)
            for (value in values)
                if (value.isSupported(context))
                    result.add(value)
            return result
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.