簡體   English   中英

Android的AEC和​​Noise Suppressor在某些設備上不起作用

[英]Android's AEC and Noise Suppressor aren't working on some devices

在使用具有VoIP功能的Android Unity應用程序時,我們發現在某些設備(特別是Galaxy S6)上,麥克風會拾取揚聲器輸出的聲音,從而導致大量的靜態,失真和回聲。 因此,我開始研究本機解決方案,以利用Android的某些AEC和NS功能。

我編寫了以下測試平台,該測試平台在Note 4等某些設備上運行良好。當同一個應用程序在Galaxy S6上運行時,就好像ARC和NS沒有很好地應用或根本沒有應用。

public class MainActivity extends Activity
{
    private AudioRecord mAudioRecorder = null;
    private AudioTrack mStreamingPlayer = null;

    private Thread playbackThread = null;

    private boolean useVoip = true;

    int bufferSize;
    int chunkSize;

    private AutomaticGainControl agc;
    private NoiseSuppressor suppressor;
    private  AcousticEchoCanceler aec;

    private boolean manuallyAttachEffects = false;

    private void StartRecordingAudio()
    {
        int sampleRate = 44100;
        int channelConfig = AudioFormat.CHANNEL_IN_MONO;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

        chunkSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
        bufferSize = chunkSize * 10;

        int audioSource = MediaRecorder.AudioSource.MIC;

        if ( useVoip && !manuallyAttachEffects )
        {
            audioSource = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
        }

        mAudioRecorder = new AudioRecord( audioSource, 
                                        sampleRate,
                                        channelConfig,
                                        audioFormat,
                                        bufferSize );

        if ( useVoip && manuallyAttachEffects )
        {
            SetupVoipEffects( mAudioRecorder.getAudioSessionId() );
        }

        mAudioRecorder.startRecording();

        mStreamingPlayer = new AudioTrack(  AudioManager.STREAM_MUSIC,
                                            sampleRate,
                                            AudioFormat.CHANNEL_OUT_MONO,
                                            audioFormat,
                                            bufferSize,
                                            AudioTrack.MODE_STREAM );

        mStreamingPlayer.play();

        playbackThread = new Thread(new Runnable()
        {
            @Override
            public void run() {
                readAudioData();
            }

        });

        playbackThread.start();
    }

    private void readAudioData()
    {
        Thread thisThread = Thread.currentThread();

        byte[] buffer = new byte[chunkSize];

        while ( !thisThread.isInterrupted() )
        {
            if ( mAudioRecorder == null )
                break;

            int bytesRead = mAudioRecorder.read(buffer, 0, chunkSize);
            if ( bytesRead > 0 )
            {
                if ( mStreamingPlayer == null )
                    break;

                mStreamingPlayer.write(buffer, 0, chunkSize);   
            }
        }
    }

    private void SetupVoipEffects( int sessionId )
    {
        if(AutomaticGainControl.isAvailable())
        {
            agc = AutomaticGainControl.create( sessionId );
            Log.d(LOG_TAG, "AGC is " + (agc.getEnabled()?"enabled":"disabled"));

            if ( !agc.getEnabled() )
            {
                agc.setEnabled(true);
                Log.d(LOG_TAG, "AGC is " + (agc.getEnabled()?"enabled":"disabled" +" after trying to enable"));
            }
        }

        if(NoiseSuppressor.isAvailable())
        {
            suppressor = NoiseSuppressor.create( sessionId );
            Log.d(LOG_TAG, "NS is " + (suppressor.getEnabled()?"enabled":"disabled"));

            if ( !suppressor.getEnabled() )
            {
                suppressor.setEnabled(true);
                Log.d(LOG_TAG, "NS is " + (suppressor.getEnabled()?"enabled":"disabled" +" after trying to disable"));  
            }

        }
        if(AcousticEchoCanceler.isAvailable())
        {
            aec = AcousticEchoCanceler.create( sessionId );
            Log.d(LOG_TAG, "AEC is " + (aec.getEnabled()?"enabled":"disabled"));

            if ( !aec.getEnabled() )
            {
                aec.setEnabled(true);
                Log.d(LOG_TAG, "AEC is " + (aec.getEnabled()?"enabled":"disabled" +" after trying to disable"));
            }
        }
    }
}

我嘗試了很多事情,例如對音頻記錄使用VOICE_COMMUNICATION,使用MIC以及手動創建NoiseSuppressor和AcousticEchoCanceller,禁用/啟用NuPlayer / AwesomePlayer等。 這些設備表明已支持並啟用了AEC,但似乎並沒有發生。 使用耳機或使用聽筒而不是揚聲器電話時,問題完全消失了(因此麥克風無法拾取揚聲器的聲音)。 我是在這里俯瞰巨大的東西,還是有可能報告一個錯誤?

如果AEC和NS在其他設備上運行不正常,我不會懷疑。

這是Android中的已知問題。 硬件AEC不可靠,即使有其他硬件報告,它也不受許多硬件的實施/支持。 我建議同時部署軟件AEC和硬件AEC,以使此功能在軟件中更穩定。 唯一的問題是軟件AEC很難正確完成,因此要准備進行大量測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM