在使用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在其他設備上無法正常工作,我不會懷疑。