How avoid automatic gain control with AudioRecord?

前端 未结 4 920
我在风中等你
我在风中等你 2020-12-05 01:48

How can I do audio recordings using android.media.AudioRecord without any smartphone-manufacturer-dependent fancy signal processing like automatic gain control

相关标签:
4条回答
  • 2020-12-05 01:54

    Short answer is "Nothing".

    The AudioSources correspond to various logical audio input devices depending on the accessories that you have connected to the phone and the current use-case, which in turn corresponds to physical devices (primary built-in mic, secondary mic, wired headset mic, etc) with different tunings.

    Each such combination of physical device and tuning is trimmed by the OEM to meet both external requirements (e.g. CTS, operator requirements, etc) and internal acoustic requirements set by the OEM itself. This process may cause the introduction of various filters - such as AGC, noise suppression, equalization, etc - into the audio input path at the hardware codec or multimedia DSP level.

    While a PURE_MIC source might be useful in for some applications, it's not something that's available today.
    On many devices you can control things like microphone gain, and possibly even the filter chain, by using amixer to write to the hardware codec's ALSA controls. However, this would obviously be a very platform-specific approach, and I also suspect that you have to be running as either the root or audio user to be allowed to do this.

    0 讨论(0)
  • 2020-12-05 01:56

    Some devices add AGC effect to the sound input tract by default. Therefore, you need to obtain reference to corresponding AudioEffect object and force it to disable.

    First, obtain AutomaticGainControl object linked to the AudioRecord audio session, and then just set it disabled:

    if (AutomaticGainControl.isAvailable()) {
        AutomaticGainControl agc = AutomaticGainControl.create(
                myAudioRecord.getAudioSessionId()
            );
        agc.setEnabled(false);
    }
    
    0 讨论(0)
  • 2020-12-05 01:56

    MIC should be fine, and for the rest you need to know if they are supported.

    I've made a class for this:

    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
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-05 01:59

    Note: Most of the audio sources (including DEFAULT) apply processing to the audio signal. To record raw audio select UNPROCESSED. Some devices do not support unprocessed input. Call AudioManager.getProperty("PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED") first to verify it's available. If it is not, try using VOICE_RECOGNITION instead, which does not employ AGC or noise suppression. You can use UNPROCESSED as an audio source even when the property is not supported, but there is no guarantee whether the signal will be unprocessed or not in that case.

    Android documentation Link 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 讨论(0)
提交回复
热议问题