| Index: webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
|
| diff --git a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
|
| index 21e43c86f33e714f29c8afb2265d2e51daab3ce8..a55966d1397aaf022af8a1c9bfbe36ff60e0fe06 100644
|
| --- a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
|
| +++ b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
|
| @@ -16,9 +16,6 @@ import java.util.concurrent.TimeUnit;
|
|
|
| import android.content.Context;
|
| import android.media.AudioFormat;
|
| -import android.media.audiofx.AcousticEchoCanceler;
|
| -import android.media.audiofx.AudioEffect;
|
| -import android.media.audiofx.AudioEffect.Descriptor;
|
| import android.media.AudioRecord;
|
| import android.media.MediaRecorder.AudioSource;
|
| import android.os.Build;
|
| @@ -45,14 +42,13 @@ class WebRtcAudioRecord {
|
| private final long nativeAudioRecord;
|
| private final Context context;
|
|
|
| + private WebRtcAudioEffects effects = null;
|
| +
|
| private ByteBuffer byteBuffer;
|
|
|
| private AudioRecord audioRecord = null;
|
| private AudioRecordThread audioThread = null;
|
|
|
| - private AcousticEchoCanceler aec = null;
|
| - private boolean useBuiltInAEC = false;
|
| -
|
| /**
|
| * Audio thread which keeps calling ByteBuffer.read() waiting for audio
|
| * to be recorded. Feeds recorded data to the native counterpart as a
|
| @@ -69,7 +65,7 @@ class WebRtcAudioRecord {
|
| @Override
|
| public void run() {
|
| Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
|
| - Logd("AudioRecordThread" + WebRtcAudioUtils.getThreadInfo());
|
| + Logging.w(TAG, "AudioRecordThread" + WebRtcAudioUtils.getThreadInfo());
|
| assertTrue(audioRecord.getRecordingState()
|
| == AudioRecord.RECORDSTATE_RECORDING);
|
|
|
| @@ -79,7 +75,7 @@ class WebRtcAudioRecord {
|
| if (bytesRead == byteBuffer.capacity()) {
|
| nativeDataIsRecorded(bytesRead, nativeAudioRecord);
|
| } else {
|
| - Loge("AudioRecord.read failed: " + bytesRead);
|
| + Logging.e(TAG,"AudioRecord.read failed: " + bytesRead);
|
| if (bytesRead == AudioRecord.ERROR_INVALID_OPERATION) {
|
| keepAlive = false;
|
| }
|
| @@ -89,14 +85,14 @@ class WebRtcAudioRecord {
|
| long durationInMs =
|
| TimeUnit.NANOSECONDS.toMillis((nowTime - lastTime));
|
| lastTime = nowTime;
|
| - Logd("bytesRead[" + durationInMs + "] " + bytesRead);
|
| + Logging.w(TAG, "bytesRead[" + durationInMs + "] " + bytesRead);
|
| }
|
| }
|
|
|
| try {
|
| audioRecord.stop();
|
| } catch (IllegalStateException e) {
|
| - Loge("AudioRecord.stop failed: " + e.getMessage());
|
| + Logging.e(TAG,"AudioRecord.stop failed: " + e.getMessage());
|
| }
|
| }
|
|
|
| @@ -113,47 +109,58 @@ class WebRtcAudioRecord {
|
| }
|
|
|
| WebRtcAudioRecord(Context context, long nativeAudioRecord) {
|
| - Logd("ctor" + WebRtcAudioUtils.getThreadInfo());
|
| + Logging.w(TAG, "ctor" + WebRtcAudioUtils.getThreadInfo());
|
| this.context = context;
|
| this.nativeAudioRecord = nativeAudioRecord;
|
| if (DEBUG) {
|
| WebRtcAudioUtils.logDeviceInfo(TAG);
|
| }
|
| + effects = WebRtcAudioEffects.create();
|
| }
|
|
|
| - private boolean EnableBuiltInAEC(boolean enable) {
|
| - Logd("EnableBuiltInAEC(" + enable + ')');
|
| - assertTrue(WebRtcAudioUtils.isAcousticEchoCancelerApproved());
|
| - // Store the AEC state.
|
| - useBuiltInAEC = enable;
|
| - // Set AEC state if AEC has already been created.
|
| - if (aec != null) {
|
| - int ret = aec.setEnabled(enable);
|
| - if (ret != AudioEffect.SUCCESS) {
|
| - Loge("AcousticEchoCanceler.setEnabled failed");
|
| - return false;
|
| - }
|
| - Logd("AcousticEchoCanceler.getEnabled: " + aec.getEnabled());
|
| + private boolean enableBuiltInAEC(boolean enable) {
|
| + Logging.w(TAG, "enableBuiltInAEC(" + enable + ')');
|
| + if (effects == null) {
|
| + Logging.e(TAG,"Built-in AEC is not supported on this platform");
|
| + return false;
|
| }
|
| - return true;
|
| + return effects.setAEC(enable);
|
| + }
|
| +
|
| + private boolean enableBuiltInAGC(boolean enable) {
|
| + Logging.w(TAG, "enableBuiltInAGC(" + enable + ')');
|
| + if (effects == null) {
|
| + Logging.e(TAG,"Built-in AGC is not supported on this platform");
|
| + return false;
|
| + }
|
| + return effects.setAGC(enable);
|
| + }
|
| +
|
| + private boolean enableBuiltInNS(boolean enable) {
|
| + Logging.w(TAG, "enableBuiltInNS(" + enable + ')');
|
| + if (effects == null) {
|
| + Logging.e(TAG,"Built-in NS is not supported on this platform");
|
| + return false;
|
| + }
|
| + return effects.setNS(enable);
|
| }
|
|
|
| - private int InitRecording(int sampleRate, int channels) {
|
| - Logd("InitRecording(sampleRate=" + sampleRate + ", channels=" +
|
| + private int initRecording(int sampleRate, int channels) {
|
| + Logging.w(TAG, "initRecording(sampleRate=" + sampleRate + ", channels=" +
|
| channels + ")");
|
| if (!WebRtcAudioUtils.hasPermission(
|
| context, android.Manifest.permission.RECORD_AUDIO)) {
|
| - Loge("RECORD_AUDIO permission is missing");
|
| + Logging.e(TAG,"RECORD_AUDIO permission is missing");
|
| return -1;
|
| }
|
| if (audioRecord != null) {
|
| - Loge("InitRecording() called twice without StopRecording()");
|
| + Logging.e(TAG,"InitRecording() called twice without StopRecording()");
|
| return -1;
|
| }
|
| final int bytesPerFrame = channels * (BITS_PER_SAMPLE / 8);
|
| final int framesPerBuffer = sampleRate / BUFFERS_PER_SECOND;
|
| byteBuffer = ByteBuffer.allocateDirect(bytesPerFrame * framesPerBuffer);
|
| - Logd("byteBuffer.capacity: " + byteBuffer.capacity());
|
| + Logging.w(TAG, "byteBuffer.capacity: " + byteBuffer.capacity());
|
| // Rather than passing the ByteBuffer with every callback (requiring
|
| // the potentially expensive GetDirectBufferAddress) we simply have the
|
| // the native class cache the address to the memory once.
|
| @@ -167,11 +174,11 @@ class WebRtcAudioRecord {
|
| sampleRate,
|
| AudioFormat.CHANNEL_IN_MONO,
|
| AudioFormat.ENCODING_PCM_16BIT);
|
| - Logd("AudioRecord.getMinBufferSize: " + minBufferSize);
|
| + Logging.w(TAG, "AudioRecord.getMinBufferSize: " + minBufferSize);
|
|
|
|
|
| int bufferSizeInBytes = Math.max(byteBuffer.capacity(), minBufferSize);
|
| - Logd("bufferSizeInBytes: " + bufferSizeInBytes);
|
| + Logging.w(TAG, "bufferSizeInBytes: " + bufferSizeInBytes);
|
| try {
|
| audioRecord = new AudioRecord(AudioSource.VOICE_COMMUNICATION,
|
| sampleRate,
|
| @@ -180,63 +187,37 @@ class WebRtcAudioRecord {
|
| bufferSizeInBytes);
|
|
|
| } catch (IllegalArgumentException e) {
|
| - Loge(e.getMessage());
|
| + Logging.e(TAG,e.getMessage());
|
| return -1;
|
| }
|
| if (audioRecord == null ||
|
| audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
|
| - Loge("Failed to create a new AudioRecord instance");
|
| + Logging.e(TAG,"Failed to create a new AudioRecord instance");
|
| return -1;
|
| }
|
| -
|
| - Logd("AudioRecord " +
|
| - "session ID: " + audioRecord.getAudioSessionId() + ", " +
|
| - "audio format: " + audioRecord.getAudioFormat() + ", " +
|
| - "channels: " + audioRecord.getChannelCount() + ", " +
|
| - "sample rate: " + audioRecord.getSampleRate());
|
| - Logd("AcousticEchoCanceler.isAvailable: " + builtInAECIsAvailable());
|
| - if (!builtInAECIsAvailable()) {
|
| - return framesPerBuffer;
|
| - }
|
| - if (WebRtcAudioUtils.deviceIsBlacklistedForHwAecUsage()) {
|
| - // Just in case, ensure that no attempt has been done to enable the
|
| - // HW AEC on a blacklisted device.
|
| - assertTrue(!useBuiltInAEC);
|
| - }
|
| - // We create an AEC also for blacklisted devices since it is possible that
|
| - // HW EAC is enabled by default. Hence, the AEC object is needed to be
|
| - // able to check the current state and to disable the AEC if enabled.
|
| - aec = AcousticEchoCanceler.create(audioRecord.getAudioSessionId());
|
| - if (aec == null) {
|
| - Loge("AcousticEchoCanceler.create failed");
|
| - return -1;
|
| - }
|
| - int ret = aec.setEnabled(useBuiltInAEC);
|
| - if (ret != AudioEffect.SUCCESS) {
|
| - Loge("AcousticEchoCanceler.setEnabled failed");
|
| - return -1;
|
| + Logging.w(TAG, "AudioRecord "
|
| + + "session ID: " + audioRecord.getAudioSessionId() + ", "
|
| + + "audio format: " + audioRecord.getAudioFormat() + ", "
|
| + + "channels: " + audioRecord.getChannelCount() + ", "
|
| + + "sample rate: " + audioRecord.getSampleRate());
|
| + if (effects != null) {
|
| + effects.enable(audioRecord.getAudioSessionId());
|
| }
|
| - Descriptor descriptor = aec.getDescriptor();
|
| - Logd("AcousticEchoCanceler " +
|
| - "name: " + descriptor.name + ", " +
|
| - "implementor: " + descriptor.implementor + ", " +
|
| - "uuid: " + descriptor.uuid);
|
| - Logd("AcousticEchoCanceler.getEnabled: " + aec.getEnabled());
|
| return framesPerBuffer;
|
| }
|
|
|
| - private boolean StartRecording() {
|
| - Logd("StartRecording");
|
| + private boolean startRecording() {
|
| + Logging.w(TAG, "startRecording");
|
| assertTrue(audioRecord != null);
|
| assertTrue(audioThread == null);
|
| try {
|
| audioRecord.startRecording();
|
| } catch (IllegalStateException e) {
|
| - Loge("AudioRecord.startRecording failed: " + e.getMessage());
|
| + Logging.e(TAG,"AudioRecord.startRecording failed: " + e.getMessage());
|
| return false;
|
| }
|
| if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
|
| - Loge("AudioRecord.startRecording failed");
|
| + Logging.e(TAG,"AudioRecord.startRecording failed");
|
| return false;
|
| }
|
| audioThread = new AudioRecordThread("AudioRecordJavaThread");
|
| @@ -244,26 +225,19 @@ class WebRtcAudioRecord {
|
| return true;
|
| }
|
|
|
| - private boolean StopRecording() {
|
| - Logd("StopRecording");
|
| + private boolean stopRecording() {
|
| + Logging.w(TAG, "stopRecording");
|
| assertTrue(audioThread != null);
|
| audioThread.joinThread();
|
| audioThread = null;
|
| - if (aec != null) {
|
| - aec.release();
|
| - aec = null;
|
| + if (effects != null) {
|
| + effects.release();
|
| }
|
| audioRecord.release();
|
| audioRecord = null;
|
| return true;
|
| }
|
|
|
| - // Returns true if built-in AEC is available. Does not take blacklisting
|
| - // into account.
|
| - private static boolean builtInAECIsAvailable() {
|
| - return WebRtcAudioUtils.isAcousticEchoCancelerSupported();
|
| - }
|
| -
|
| // Helper method which throws an exception when an assertion has failed.
|
| private static void assertTrue(boolean condition) {
|
| if (!condition) {
|
| @@ -271,14 +245,6 @@ class WebRtcAudioRecord {
|
| }
|
| }
|
|
|
| - private static void Logd(String msg) {
|
| - Logging.d(TAG, msg);
|
| - }
|
| -
|
| - private static void Loge(String msg) {
|
| - Logging.e(TAG, msg);
|
| - }
|
| -
|
| private native void nativeCacheDirectBufferAddress(
|
| ByteBuffer byteBuffer, long nativeAudioRecord);
|
|
|
|
|