Android 回音消除(AcousticEchoCanceler)的使用

回音消除Google 开发文档原文:

/**
 * Acoustic Echo Canceler (AEC).
 * 

Acoustic Echo Canceler (AEC) is an audio pre-processor which removes the contribution of the * signal received from the remote party from the captured audio signal. *

AEC is used by voice communication applications (voice chat, video conferencing, SIP calls) * where the presence of echo with significant delay in the signal received from the remote party * is highly disturbing. AEC is often used in conjunction with noise suppression (NS). *

An application creates an AcousticEchoCanceler object to instantiate and control an AEC * engine in the audio capture path. *

To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord}, * specify the audio session ID of this AudioRecord when creating the AcousticEchoCanceler. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. *

On some devices, an AEC can be inserted by default in the capture path by the platform * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should * call AcousticEchoCanceler.getEnable() after creating the AEC to check the default AEC activation * state on a particular AudioRecord session. *

See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. */

场景就是在手机播放声音和声音录制同时进行,但是手机播放的声音不会被本机录制,达到了消除的效果。微信对讲的最适合不过了,但是微信的回音消除好像是不是自己弄的。

文档大致意思:创建android.media.AudioRecord 的对象的时候,可以通过这个对象获取到一个audio session 的ID(获取的方法:getAudioSessionId()),这个ID的话在创建AcousticEchoCanceler的时候用到(创建对象:AcousticEchoCanceler.create(audioSessionId)),最后播放音频的时候(这里是用AudioTrack播放)传入这个ID就行了。

首先创建AudioRecord。这里就不啰嗦里面的参数是干嘛的了,可以自己查资料知道什么是采样率,声道,位数。


    private AudioRecord mRecorder;
    private byte[] pcm;
    private int mRecorderBufferSize;


    /**
     * 初始化录音
     */
    public void initRecorder() {
        mRecorderBufferSize = AudioRecord.getMinBufferSize(8000,
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        pcm = new byte[320];
        mRecorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
                mRecorderBufferSize);
    }

初始化AudioTrack(注意下传入的audioSessionId)。

private AudioTrack mAudioTrack;
private int audioSessionId = -1;
private void initAudioTrack() {
        if (mAudioTrack == null) {
            if (audioSessionId == -1) {
                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mRecorderBufferSize * 2
                        , AudioTrack.MODE_STREAM);
            } else {
                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mRecorderBufferSize * 2
                        , AudioTrack.MODE_STREAM, audioSessionId);
            }
        }
}

最后创建AcousticEchoCanceler

    private AcousticEchoCanceler acousticEchoCanceler;

    private void initAEC() {
        if (AcousticEchoCanceler.isAvailable()) {
            if (acousticEchoCanceler == null) {
                acousticEchoCanceler = AcousticEchoCanceler.create(audioSessionId);
                Log.d(TAG, "initAEC: ---->" + acousticEchoCanceler + "\t" + audioSessionId);
                if (acousticEchoCanceler == null) {
                    Log.e(TAG, "initAEC: ----->AcousticEchoCanceler create fail.");
                } else {
                    acousticEchoCanceler.setEnabled(true);
                }
            }
        }
    }

最后播放的时候就可以了(验证是ok的)


    public void write(byte[] data) {
        if (mAudioTrack != null && mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
            mAudioTrack.write(data, 0, data.length);
        }
    }

你可能感兴趣的:(Android 回音消除(AcousticEchoCanceler)的使用)