Add control for choosing between AEC3 and AECM (#67)

This commit is contained in:
Peter Thatcher 2022-02-23 18:59:14 -07:00 committed by GitHub
parent c3195def8f
commit 54cfdf3754
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 21 deletions

View file

@ -435,10 +435,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
<< options_in.ToString(); << options_in.ToString();
AudioOptions options = options_in; // The options are modified below. AudioOptions options = options_in; // The options are modified below.
// Set and adjust echo canceller options.
// Use desktop AEC by default, when not using hardware AEC.
bool use_mobile_software_aec = false;
#if defined(WEBRTC_IOS) #if defined(WEBRTC_IOS)
if (options.ios_force_software_aec_HACK && if (options.ios_force_software_aec_HACK &&
*options.ios_force_software_aec_HACK) { *options.ios_force_software_aec_HACK) {
@ -452,8 +448,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
options.echo_cancellation = false; options.echo_cancellation = false;
RTC_LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead."; RTC_LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
} }
#elif defined(WEBRTC_ANDROID)
use_mobile_software_aec = true;
#endif #endif
// Override noise suppression options for Android. // Override noise suppression options for Android.
@ -592,7 +586,8 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
if (options.echo_cancellation) { if (options.echo_cancellation) {
apm_config.echo_canceller.enabled = *options.echo_cancellation; apm_config.echo_canceller.enabled = *options.echo_cancellation;
apm_config.echo_canceller.mobile_mode = use_mobile_software_aec; // RingRTC change to allow control of AEC3 vs AECM
apm_config.echo_canceller.mobile_mode = adm()->UseAecm();
} }
if (options.auto_gain_control) { if (options.auto_gain_control) {

View file

@ -140,6 +140,9 @@ class AudioDeviceModule : public rtc::RefCountInterface {
virtual bool BuiltInAECIsAvailable() const = 0; virtual bool BuiltInAECIsAvailable() const = 0;
virtual bool BuiltInAGCIsAvailable() const = 0; virtual bool BuiltInAGCIsAvailable() const = 0;
virtual bool BuiltInNSIsAvailable() const = 0; virtual bool BuiltInNSIsAvailable() const = 0;
// RingRTC change to allow control of AEC3 vs AECM
// When using software AEC, use AECM instead of AEC3.
virtual bool UseAecm() const { return false; }
// Enables the built-in audio effects. Only supported on Android. // Enables the built-in audio effects. Only supported on Android.
virtual int32_t EnableBuiltInAEC(bool enable) = 0; virtual int32_t EnableBuiltInAEC(bool enable) = 0;

View file

@ -50,6 +50,8 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
private boolean useStereoOutput; private boolean useStereoOutput;
private AudioAttributes audioAttributes; private AudioAttributes audioAttributes;
private boolean useLowLatency; private boolean useLowLatency;
// RingRTC change to allow control of AEC3 vs AECM
private boolean useAecm;
private Builder(Context context) { private Builder(Context context) {
this.context = context; this.context = context;
@ -57,6 +59,7 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
this.inputSampleRate = WebRtcAudioManager.getSampleRate(audioManager); this.inputSampleRate = WebRtcAudioManager.getSampleRate(audioManager);
this.outputSampleRate = WebRtcAudioManager.getSampleRate(audioManager); this.outputSampleRate = WebRtcAudioManager.getSampleRate(audioManager);
this.useLowLatency = false; this.useLowLatency = false;
this.useAecm = false;
} }
public Builder setScheduler(ScheduledExecutorService scheduler) { public Builder setScheduler(ScheduledExecutorService scheduler) {
@ -213,6 +216,15 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
return this; return this;
} }
// RingRTC change to allow control of AEC3 vs AECM
/**
* Control if AECM is used or AEC3. The default is AEC3.
*/
public Builder setUseAecm(boolean useAecm) {
this.useAecm = useAecm;
return this;
}
/** /**
* Construct an AudioDeviceModule based on the supplied arguments. The caller takes ownership * Construct an AudioDeviceModule based on the supplied arguments. The caller takes ownership
* and is responsible for calling release(). * and is responsible for calling release().
@ -251,7 +263,7 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
final WebRtcAudioTrack audioOutput = new WebRtcAudioTrack(context, audioManager, final WebRtcAudioTrack audioOutput = new WebRtcAudioTrack(context, audioManager,
audioAttributes, audioTrackErrorCallback, audioTrackStateCallback, useLowLatency); audioAttributes, audioTrackErrorCallback, audioTrackStateCallback, useLowLatency);
return new JavaAudioDeviceModule(context, audioManager, audioInput, audioOutput, return new JavaAudioDeviceModule(context, audioManager, audioInput, audioOutput,
inputSampleRate, outputSampleRate, useStereoInput, useStereoOutput); inputSampleRate, outputSampleRate, useStereoInput, useStereoOutput, useAecm);
} }
} }
@ -359,13 +371,15 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
private final int outputSampleRate; private final int outputSampleRate;
private final boolean useStereoInput; private final boolean useStereoInput;
private final boolean useStereoOutput; private final boolean useStereoOutput;
private final boolean useAecm;
private final Object nativeLock = new Object(); private final Object nativeLock = new Object();
private long nativeAudioDeviceModule; private long nativeAudioDeviceModule;
private JavaAudioDeviceModule(Context context, AudioManager audioManager, private JavaAudioDeviceModule(Context context, AudioManager audioManager,
WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput, int inputSampleRate, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput, int inputSampleRate,
int outputSampleRate, boolean useStereoInput, boolean useStereoOutput) { int outputSampleRate, boolean useStereoInput, boolean useStereoOutput,
boolean useAecm) {
this.context = context; this.context = context;
this.audioManager = audioManager; this.audioManager = audioManager;
this.audioInput = audioInput; this.audioInput = audioInput;
@ -374,6 +388,7 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
this.outputSampleRate = outputSampleRate; this.outputSampleRate = outputSampleRate;
this.useStereoInput = useStereoInput; this.useStereoInput = useStereoInput;
this.useStereoOutput = useStereoOutput; this.useStereoOutput = useStereoOutput;
this.useAecm = useAecm;
} }
@Override @Override
@ -381,7 +396,8 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
synchronized (nativeLock) { synchronized (nativeLock) {
if (nativeAudioDeviceModule == 0) { if (nativeAudioDeviceModule == 0) {
nativeAudioDeviceModule = nativeCreateAudioDeviceModule(context, audioManager, audioInput, nativeAudioDeviceModule = nativeCreateAudioDeviceModule(context, audioManager, audioInput,
audioOutput, inputSampleRate, outputSampleRate, useStereoInput, useStereoOutput); audioOutput, inputSampleRate, outputSampleRate, useStereoInput, useStereoOutput,
useAecm);
} }
return nativeAudioDeviceModule; return nativeAudioDeviceModule;
} }
@ -423,5 +439,6 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
private static native long nativeCreateAudioDeviceModule(Context context, private static native long nativeCreateAudioDeviceModule(Context context,
AudioManager audioManager, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput, AudioManager audioManager, WebRtcAudioRecord audioInput, WebRtcAudioTrack audioOutput,
int inputSampleRate, int outputSampleRate, boolean useStereoInput, boolean useStereoOutput); int inputSampleRate, int outputSampleRate, boolean useStereoInput, boolean useStereoOutput,
boolean useAecm);
} }

View file

@ -69,7 +69,8 @@ rtc::scoped_refptr<AudioDeviceModule> CreateAAudioAudioDeviceModule(
false /* use_stereo_output */, false /* use_stereo_output */,
jni::kLowLatencyModeDelayEstimateInMilliseconds, jni::kLowLatencyModeDelayEstimateInMilliseconds,
std::make_unique<jni::AAudioRecorder>(input_parameters), std::make_unique<jni::AAudioRecorder>(input_parameters),
std::make_unique<jni::AAudioPlayer>(output_parameters)); std::make_unique<jni::AAudioPlayer>(output_parameters),
false /* use_aecm */);
} }
#endif #endif
@ -98,7 +99,8 @@ rtc::scoped_refptr<AudioDeviceModule> CreateJavaAudioDeviceModule(
AudioDeviceModule::kAndroidJavaAudio, false /* use_stereo_input */, AudioDeviceModule::kAndroidJavaAudio, false /* use_stereo_input */,
false /* use_stereo_output */, false /* use_stereo_output */,
jni::kHighLatencyModeDelayEstimateInMilliseconds, std::move(audio_input), jni::kHighLatencyModeDelayEstimateInMilliseconds, std::move(audio_input),
std::move(audio_output)); std::move(audio_output)
false /* use_aecm */);
} }
rtc::scoped_refptr<AudioDeviceModule> CreateOpenSLESAudioDeviceModule( rtc::scoped_refptr<AudioDeviceModule> CreateOpenSLESAudioDeviceModule(
@ -121,7 +123,8 @@ rtc::scoped_refptr<AudioDeviceModule> CreateOpenSLESAudioDeviceModule(
AudioDeviceModule::kAndroidOpenSLESAudio, false /* use_stereo_input */, AudioDeviceModule::kAndroidOpenSLESAudio, false /* use_stereo_input */,
false /* use_stereo_output */, false /* use_stereo_output */,
jni::kLowLatencyModeDelayEstimateInMilliseconds, std::move(audio_input), jni::kLowLatencyModeDelayEstimateInMilliseconds, std::move(audio_input),
std::move(audio_output)); std::move(audio_output),
false /* use_aecm */);
} }
rtc::scoped_refptr<AudioDeviceModule> rtc::scoped_refptr<AudioDeviceModule>
@ -150,7 +153,8 @@ CreateJavaInputAndOpenSLESOutputAudioDeviceModule(JNIEnv* env,
AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio, AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio,
false /* use_stereo_input */, false /* use_stereo_output */, false /* use_stereo_input */, false /* use_stereo_output */,
jni::kLowLatencyModeDelayEstimateInMilliseconds, std::move(audio_input), jni::kLowLatencyModeDelayEstimateInMilliseconds, std::move(audio_input),
std::move(audio_output)); std::move(audio_output),
false /* use_aecm */);
} }
} // namespace webrtc } // namespace webrtc

View file

@ -59,7 +59,9 @@ class AndroidAudioDeviceModule : public AudioDeviceModule {
bool is_stereo_record_supported, bool is_stereo_record_supported,
uint16_t playout_delay_ms, uint16_t playout_delay_ms,
std::unique_ptr<AudioInput> audio_input, std::unique_ptr<AudioInput> audio_input,
std::unique_ptr<AudioOutput> audio_output) std::unique_ptr<AudioOutput> audio_output,
// RingRTC change to allow control of AEC3 vs AEC3
bool use_aecm)
: audio_layer_(audio_layer), : audio_layer_(audio_layer),
is_stereo_playout_supported_(is_stereo_playout_supported), is_stereo_playout_supported_(is_stereo_playout_supported),
is_stereo_record_supported_(is_stereo_record_supported), is_stereo_record_supported_(is_stereo_record_supported),
@ -67,6 +69,7 @@ class AndroidAudioDeviceModule : public AudioDeviceModule {
task_queue_factory_(CreateDefaultTaskQueueFactory()), task_queue_factory_(CreateDefaultTaskQueueFactory()),
input_(std::move(audio_input)), input_(std::move(audio_input)),
output_(std::move(audio_output)), output_(std::move(audio_output)),
use_aecm_(use_aecm),
initialized_(false) { initialized_(false) {
RTC_CHECK(input_); RTC_CHECK(input_);
RTC_CHECK(output_); RTC_CHECK(output_);
@ -542,6 +545,13 @@ class AndroidAudioDeviceModule : public AudioDeviceModule {
return isAvailable; return isAvailable;
} }
// RingRTC change to allow control of AEC3 vs AECM
bool UseAecm() const override {
RTC_DLOG(INFO) << __FUNCTION__;
RTC_DLOG(INFO) << "output: " << use_aecm_;
return use_aecm_;
}
// TODO(henrika): add implementation for OpenSL ES based audio as well. // TODO(henrika): add implementation for OpenSL ES based audio as well.
int32_t EnableBuiltInAEC(bool enable) override { int32_t EnableBuiltInAEC(bool enable) override {
RTC_DLOG(INFO) << __FUNCTION__ << "(" << enable << ")"; RTC_DLOG(INFO) << __FUNCTION__ << "(" << enable << ")";
@ -593,6 +603,7 @@ class AndroidAudioDeviceModule : public AudioDeviceModule {
const std::unique_ptr<AudioInput> input_; const std::unique_ptr<AudioInput> input_;
const std::unique_ptr<AudioOutput> output_; const std::unique_ptr<AudioOutput> output_;
std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_; std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_;
const bool use_aecm_ = false;
bool initialized_; bool initialized_;
}; };
@ -639,11 +650,13 @@ rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModuleFromInputAndOutput(
bool is_stereo_record_supported, bool is_stereo_record_supported,
uint16_t playout_delay_ms, uint16_t playout_delay_ms,
std::unique_ptr<AudioInput> audio_input, std::unique_ptr<AudioInput> audio_input,
std::unique_ptr<AudioOutput> audio_output) { std::unique_ptr<AudioOutput> audio_output,
// RingRTC change to allow control of AEC3 vs AECM
bool use_aecm) {
RTC_DLOG(INFO) << __FUNCTION__; RTC_DLOG(INFO) << __FUNCTION__;
return rtc::make_ref_counted<AndroidAudioDeviceModule>( return rtc::make_ref_counted<AndroidAudioDeviceModule>(
audio_layer, is_stereo_playout_supported, is_stereo_record_supported, audio_layer, is_stereo_playout_supported, is_stereo_record_supported,
playout_delay_ms, std::move(audio_input), std::move(audio_output)); playout_delay_ms, std::move(audio_input), std::move(audio_output), use_aecm);
} }
} // namespace jni } // namespace jni

View file

@ -93,7 +93,9 @@ rtc::scoped_refptr<AudioDeviceModule> CreateAudioDeviceModuleFromInputAndOutput(
bool is_stereo_record_supported, bool is_stereo_record_supported,
uint16_t playout_delay_ms, uint16_t playout_delay_ms,
std::unique_ptr<AudioInput> audio_input, std::unique_ptr<AudioInput> audio_input,
std::unique_ptr<AudioOutput> audio_output); std::unique_ptr<AudioOutput> audio_output,
// RingRTC change to allow control of AEC3 vs AECM
bool use_aecm);
} // namespace jni } // namespace jni

View file

@ -27,7 +27,9 @@ static jlong JNI_JavaAudioDeviceModule_CreateAudioDeviceModule(
int input_sample_rate, int input_sample_rate,
int output_sample_rate, int output_sample_rate,
jboolean j_use_stereo_input, jboolean j_use_stereo_input,
jboolean j_use_stereo_output) { jboolean j_use_stereo_output,
// RingRTC change to allow control of AEC3 vs AECM
jboolean j_use_aecm) {
AudioParameters input_parameters; AudioParameters input_parameters;
AudioParameters output_parameters; AudioParameters output_parameters;
GetAudioParameters(env, j_context, j_audio_manager, input_sample_rate, GetAudioParameters(env, j_context, j_audio_manager, input_sample_rate,
@ -43,7 +45,8 @@ static jlong JNI_JavaAudioDeviceModule_CreateAudioDeviceModule(
AudioDeviceModule::kAndroidJavaAudio, AudioDeviceModule::kAndroidJavaAudio,
j_use_stereo_input, j_use_stereo_output, j_use_stereo_input, j_use_stereo_output,
kHighLatencyModeDelayEstimateInMilliseconds, kHighLatencyModeDelayEstimateInMilliseconds,
std::move(audio_input), std::move(audio_output)) std::move(audio_input), std::move(audio_output),
j_use_aecm)
.release()); .release());
} }