2015-10-20 114 views
1

在使用VoIP功能的Android Unity應用程序中,我們發現在某些設備(特別是Galaxy S6)上,麥克風會拾取由揚聲器,導致了很多靜態,失真和回聲。正因爲如此,我已經開始致力於本地解決方案,以利用Android的一些AEC和NS功能。Android的AEC和​​Noise Suppressor在某些設備上不工作

我已經寫了下面的測試牀,它可以在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爲AudioRecord,使用MIC和手動創建NoiseSuppressor和AcousticEchoCanceller,禁用/啓用NuPlayer/AwesomePlayer,等等。這些設備顯示AEC被支持和啓用,但它似乎並沒有發生。使用耳機或使用手機代替揚聲器電話時問題完全消失(因此麥克風無法拾取揚聲器聲音)。我在這裏忽略了一些巨大的東西,還是有可能會報告一個錯誤?

如果AEC和NS在其他設備上無法正常工作,我不會懷疑。

回答

0

這是Android中的一個已知問題。硬件AEC是不可靠的,即使他們報告了硬件AEC也不會被大量硬件實現/支持。 我會建議部署一個軟件AEC以及硬件AEC,以使您的軟件更穩定。唯一的問題是軟件AEC不太容易正確完成,所以要做好大量的測試準備。

相關問題