echo-cancel: Convert AGC API to deal with pa_volume_t

It is expected that the underlying AGC mechanism will likely provide a
single volume for the source rather than a per-channel volume. Dealing
with per-channel volumes just adds complexity with regards to the
actual volume setting (depending on whether volume sharing is enabled or
not, we would set the volume on the source output of the virtual source,
and their sample specs may be different).

Using a single volume allows us to sidestep this problem entirely.
This commit is contained in:
Arun Raghavan 2016-02-25 17:58:38 +05:30
parent 05a6af744b
commit fa2b0b4aad
3 changed files with 22 additions and 24 deletions

View file

@ -132,8 +132,8 @@ struct pa_echo_canceller {
}; };
/* Functions to be used by the canceller analog gain control routines */ /* Functions to be used by the canceller analog gain control routines */
void pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec, pa_cvolume *v); pa_volume_t pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec);
void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_cvolume *v); void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_volume_t volume);
/* Computes EC block size in frames (rounded down to nearest power-of-2) based /* Computes EC block size in frames (rounded down to nearest power-of-2) based
* on sample rate and milliseconds. */ * on sample rate and milliseconds. */

View file

@ -1535,12 +1535,16 @@ static int canceller_process_msg_cb(pa_msgobject *o, int code, void *userdata, i
switch (code) { switch (code) {
case ECHO_CANCELLER_MESSAGE_SET_VOLUME: { case ECHO_CANCELLER_MESSAGE_SET_VOLUME: {
pa_cvolume *v = (pa_cvolume *) userdata; pa_volume_t v = PA_PTR_TO_UINT(userdata);
pa_cvolume vol;
if (u->use_volume_sharing) if (u->use_volume_sharing) {
pa_source_set_volume(u->source, v, true, false); pa_cvolume_set(&vol, u->source->sample_spec.channels, v);
else pa_source_set_volume(u->source, &vol, true, false);
pa_source_output_set_volume(u->source_output, v, false, true); } else {
pa_cvolume_set(&vol, u->source_output->sample_spec.channels, v);
pa_source_output_set_volume(u->source_output, &vol, false, true);
}
break; break;
} }
@ -1554,22 +1558,20 @@ static int canceller_process_msg_cb(pa_msgobject *o, int code, void *userdata, i
} }
/* Called by the canceller, so source I/O thread context. */ /* Called by the canceller, so source I/O thread context. */
void pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec, pa_cvolume *v) { pa_volume_t pa_echo_canceller_get_capture_volume(pa_echo_canceller *ec) {
#ifndef ECHO_CANCEL_TEST #ifndef ECHO_CANCEL_TEST
*v = ec->msg->userdata->thread_info.current_volume; return pa_cvolume_avg(&ec->msg->userdata->thread_info.current_volume);
#else #else
pa_cvolume_set(v, 1, PA_VOLUME_NORM); return PA_VOLUME_NORM;
#endif #endif
} }
/* Called by the canceller, so source I/O thread context. */ /* Called by the canceller, so source I/O thread context. */
void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_cvolume *v) { void pa_echo_canceller_set_capture_volume(pa_echo_canceller *ec, pa_volume_t v) {
#ifndef ECHO_CANCEL_TEST #ifndef ECHO_CANCEL_TEST
if (!pa_cvolume_equal(&ec->msg->userdata->thread_info.current_volume, v)) { if (pa_cvolume_avg(&ec->msg->userdata->thread_info.current_volume) != v) {
pa_cvolume *vol = pa_xnewdup(pa_cvolume, v, 1); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(ec->msg), ECHO_CANCELLER_MESSAGE_SET_VOLUME, PA_UINT_TO_PTR(v),
0, NULL, NULL);
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(ec->msg), ECHO_CANCELLER_MESSAGE_SET_VOLUME, vol, 0, NULL,
pa_xfree);
} }
#endif #endif
} }

View file

@ -529,7 +529,6 @@ void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out
const pa_sample_spec *out_ss = &ec->params.webrtc.out_ss; const pa_sample_spec *out_ss = &ec->params.webrtc.out_ss;
float **buf = ec->params.webrtc.rec_buffer; float **buf = ec->params.webrtc.rec_buffer;
int n = ec->params.webrtc.blocksize; int n = ec->params.webrtc.blocksize;
pa_cvolume v;
int old_volume, new_volume; int old_volume, new_volume;
webrtc::StreamConfig rec_config(rec_ss->rate, rec_ss->channels, false); webrtc::StreamConfig rec_config(rec_ss->rate, rec_ss->channels, false);
webrtc::StreamConfig out_config(out_ss->rate, out_ss->channels, false); webrtc::StreamConfig out_config(out_ss->rate, out_ss->channels, false);
@ -537,9 +536,8 @@ void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out
pa_deinterleave(rec, (void **) buf, rec_ss->channels, pa_sample_size(rec_ss), n); pa_deinterleave(rec, (void **) buf, rec_ss->channels, pa_sample_size(rec_ss), n);
if (ec->params.webrtc.agc) { if (ec->params.webrtc.agc) {
pa_cvolume_init(&v); pa_volume_t v = pa_echo_canceller_get_capture_volume(ec);
pa_echo_canceller_get_capture_volume(ec, &v); old_volume = webrtc_volume_from_pa(v);
old_volume = webrtc_volume_from_pa(pa_cvolume_avg(&v));
apm->gain_control()->set_stream_analog_level(old_volume); apm->gain_control()->set_stream_analog_level(old_volume);
} }
@ -558,10 +556,8 @@ void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out
new_volume = apm->gain_control()->stream_analog_level(); new_volume = apm->gain_control()->stream_analog_level();
} }
if (old_volume != new_volume) { if (old_volume != new_volume)
pa_cvolume_set(&v, rec_ss->channels, webrtc_volume_to_pa(new_volume)); pa_echo_canceller_set_capture_volume(ec, webrtc_volume_to_pa(new_volume));
pa_echo_canceller_set_capture_volume(ec, &v);
}
} }
pa_interleave((const void **) buf, out_ss->channels, out, pa_sample_size(out_ss), n); pa_interleave((const void **) buf, out_ss->channels, out, pa_sample_size(out_ss), n);