#define DEFAULT_HIGH_PASS_FILTER TRUE
#define DEFAULT_NOISE_SUPPRESSION TRUE
-#define DEFAULT_ANALOG_GAIN_CONTROL FALSE
-#define DEFAULT_DIGITAL_GAIN_CONTROL TRUE
+#define DEFAULT_ANALOG_GAIN_CONTROL TRUE
+#define DEFAULT_DIGITAL_GAIN_CONTROL FALSE
#define DEFAULT_MOBILE FALSE
#define DEFAULT_ROUTING_MODE "speakerphone"
#define DEFAULT_COMFORT_NOISE TRUE
}
pa_bool_t pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
- pa_sample_spec *source_ss, pa_channel_map *source_map,
- pa_sample_spec *sink_ss, pa_channel_map *sink_map,
- uint32_t *blocksize, const char *args)
-{
+ pa_sample_spec *rec_ss, pa_channel_map *rec_map,
+ pa_sample_spec *play_ss, pa_channel_map *play_map,
+ pa_sample_spec *out_ss, pa_channel_map *out_map,
+ uint32_t *nframes, const char *args) {
webrtc::AudioProcessing *apm = NULL;
pa_bool_t hpf, ns, agc, dgc, mobile, cn;
- int rm;
+ int rm = -1;
pa_modargs *ma;
if (!(ma = pa_modargs_new(args, valid_modargs))) {
goto fail;
}
-
hpf = DEFAULT_HIGH_PASS_FILTER;
if (pa_modargs_get_value_boolean(ma, "high_pass_filter", &hpf) < 0) {
pa_log("Failed to parse high_pass_filter value");
goto fail;
}
- dgc = DEFAULT_DIGITAL_GAIN_CONTROL;
+ dgc = agc ? FALSE : DEFAULT_DIGITAL_GAIN_CONTROL;
if (pa_modargs_get_value_boolean(ma, "digital_gain_control", &dgc) < 0) {
pa_log("Failed to parse digital_gain_control value");
goto fail;
apm = webrtc::AudioProcessing::Create(0);
- source_ss->format = PA_SAMPLE_S16NE;
- *sink_ss = *source_ss;
+ out_ss->format = PA_SAMPLE_S16NE;
+ *play_ss = *out_ss;
/* FIXME: the implementation actually allows a different number of
* source/sink channels. Do we want to support that? */
- *sink_map = *source_map;
+ *play_map = *out_map;
+ *rec_ss = *out_ss;
+ *rec_map = *out_map;
- apm->set_sample_rate_hz(source_ss->rate);
+ apm->set_sample_rate_hz(out_ss->rate);
- apm->set_num_channels(source_ss->channels, source_ss->channels);
- apm->set_num_reverse_channels(sink_ss->channels);
+ apm->set_num_channels(out_ss->channels, out_ss->channels);
+ apm->set_num_reverse_channels(play_ss->channels);
if (hpf)
apm->high_pass_filter()->Enable(true);
if (!mobile) {
if (ec->params.drift_compensation) {
- apm->echo_cancellation()->set_device_sample_rate_hz(source_ss->rate);
+ apm->echo_cancellation()->set_device_sample_rate_hz(out_ss->rate);
apm->echo_cancellation()->enable_drift_compensation(true);
} else {
apm->echo_cancellation()->enable_drift_compensation(false);
}
if (agc || dgc) {
- if (mobile && rm <= webrtc::EchoControlMobile::kEarpiece)
+ if (mobile && rm <= webrtc::EchoControlMobile::kEarpiece) {
/* Maybe this should be a knob, but we've got a lot of knobs already */
apm->gain_control()->set_mode(webrtc::GainControl::kFixedDigital);
- else if (dgc)
- apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
- else {
- /* FIXME: Hook up for analog AGC */
- pa_log("Analog gain control isn't implemented yet -- using ditital gain control.");
+ ec->params.priv.webrtc.agc = FALSE;
+ } else if (dgc) {
apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital);
+ ec->params.priv.webrtc.agc = FALSE;
+ } else {
+ apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveAnalog);
+ if (apm->gain_control()->set_analog_level_limits(0, PA_VOLUME_NORM-1) != apm->kNoError) {
+ pa_log("Failed to initialise AGC");
+ goto fail;
+ }
+ ec->params.priv.webrtc.agc = TRUE;
}
apm->gain_control()->Enable(true);
apm->voice_detection()->Enable(true);
ec->params.priv.webrtc.apm = apm;
- ec->params.priv.webrtc.sample_spec = *source_ss;
- ec->params.priv.webrtc.blocksize = *blocksize = (uint64_t)pa_bytes_per_second(source_ss) * BLOCK_SIZE_US / PA_USEC_PER_SEC;
+ ec->params.priv.webrtc.sample_spec = *out_ss;
+ ec->params.priv.webrtc.blocksize = (uint64_t)pa_bytes_per_second(out_ss) * BLOCK_SIZE_US / PA_USEC_PER_SEC;
+ *nframes = ec->params.priv.webrtc.blocksize / pa_frame_size(out_ss);
pa_modargs_free(ma);
return TRUE;
webrtc::AudioProcessing *apm = (webrtc::AudioProcessing*)ec->params.priv.webrtc.apm;
webrtc::AudioFrame out_frame;
const pa_sample_spec *ss = &ec->params.priv.webrtc.sample_spec;
+ pa_cvolume v;
out_frame._audioChannel = ss->channels;
out_frame._frequencyInHz = ss->rate;
out_frame._payloadDataLengthInSamples = ec->params.priv.webrtc.blocksize / pa_frame_size(ss);
memcpy(out_frame._payloadData, rec, ec->params.priv.webrtc.blocksize);
+ if (ec->params.priv.webrtc.agc) {
+ pa_cvolume_init(&v);
+ pa_echo_canceller_get_capture_volume(ec, &v);
+ apm->gain_control()->set_stream_analog_level(pa_cvolume_avg(&v));
+ }
+
apm->set_stream_delay_ms(0);
apm->ProcessStream(&out_frame);
+ if (ec->params.priv.webrtc.agc) {
+ pa_cvolume_set(&v, ss->channels, apm->gain_control()->stream_analog_level());
+ pa_echo_canceller_set_capture_volume(ec, &v);
+ }
+
memcpy(out, out_frame._payloadData, ec->params.priv.webrtc.blocksize);
}