summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Raghavan <git@arunraghavan.net>2016-02-17 19:47:12 +0530
committerArun Raghavan <git@arunraghavan.net>2016-02-25 09:17:10 +0530
commit07663b06b325eee5b434f15fe1cdde0e7dd7d02d (patch)
treea53ce6a84d9eab94b0bae66dc8047108b46d9c74
parent3133ff8e1110ae694070951fdfe37e63a58995cb (diff)
downloadpulseaudio-07663b06b325eee5b434f15fe1cdde0e7dd7d02d.tar.gz
echo-cancel: Use webrtc's deinterleaved API
This is required to have unequal channel counts on capture in and out streams, which is needed for beamforming to work. The deinterleaved API only works with floating point samples.
-rw-r--r--src/modules/echo-cancel/echo-cancel.h1
-rw-r--r--src/modules/echo-cancel/module-echo-cancel.c4
-rw-r--r--src/modules/echo-cancel/webrtc.cc50
3 files changed, 30 insertions, 25 deletions
diff --git a/src/modules/echo-cancel/echo-cancel.h b/src/modules/echo-cancel/echo-cancel.h
index ab0c5e91e..83f8b8534 100644
--- a/src/modules/echo-cancel/echo-cancel.h
+++ b/src/modules/echo-cancel/echo-cancel.h
@@ -66,6 +66,7 @@ struct pa_echo_canceller_params {
void *apm;
unsigned int blocksize; /* in frames */
pa_sample_spec rec_ss, play_ss, out_ss;
+ float *rec_buffer[PA_CHANNELS_MAX], *play_buffer[PA_CHANNELS_MAX]; /* for deinterleaved buffers */
void *trace_callback;
bool agc;
bool first;
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 484281f01..4e898d070 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -2158,12 +2158,12 @@ int main(int argc, char* argv[]) {
goto fail;
}
- source_ss.format = PA_SAMPLE_S16LE;
+ source_ss.format = PA_SAMPLE_FLOAT32LE;
source_ss.rate = DEFAULT_RATE;
source_ss.channels = DEFAULT_CHANNELS;
pa_channel_map_init_auto(&source_map, source_ss.channels, PA_CHANNEL_MAP_DEFAULT);
- sink_ss.format = PA_SAMPLE_S16LE;
+ sink_ss.format = PA_SAMPLE_FLOAT32LE;
sink_ss.rate = DEFAULT_RATE;
sink_ss.channels = DEFAULT_CHANNELS;
pa_channel_map_init_auto(&sink_map, sink_ss.channels, PA_CHANNEL_MAP_DEFAULT);
diff --git a/src/modules/echo-cancel/webrtc.cc b/src/modules/echo-cancel/webrtc.cc
index 6c2dd99f1..93af18f76 100644
--- a/src/modules/echo-cancel/webrtc.cc
+++ b/src/modules/echo-cancel/webrtc.cc
@@ -117,8 +117,8 @@ static void pa_webrtc_ec_fixate_spec(pa_sample_spec *rec_ss, pa_channel_map *rec
pa_sample_spec *play_ss, pa_channel_map *play_map,
pa_sample_spec *out_ss, pa_channel_map *out_map)
{
- rec_ss->format = PA_SAMPLE_S16NE;
- play_ss->format = PA_SAMPLE_S16NE;
+ rec_ss->format = PA_SAMPLE_FLOAT32NE;
+ play_ss->format = PA_SAMPLE_FLOAT32NE;
/* AudioProcessing expects one of the following rates */
if (rec_ss->rate >= 48000)
@@ -130,7 +130,6 @@ static void pa_webrtc_ec_fixate_spec(pa_sample_spec *rec_ss, pa_channel_map *rec
else
rec_ss->rate = 8000;
- /* In int16 mode, AudioProcessing will give us the same spec we give it */
*out_ss = *rec_ss;
*out_map = *rec_map;
@@ -147,7 +146,7 @@ bool pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
webrtc::ProcessingConfig pconfig;
webrtc::Config config;
bool hpf, ns, agc, dgc, mobile, cn, vad, ext_filter, intelligibility, experimental_agc;
- int rm = -1;
+ int rm = -1, i;
uint32_t agc_start_volume;
pa_modargs *ma;
bool trace = false;
@@ -340,6 +339,11 @@ bool pa_webrtc_ec_init(pa_core *c, pa_echo_canceller *ec,
*nframes = ec->params.webrtc.blocksize;
ec->params.webrtc.first = true;
+ for (i = 0; i < rec_ss->channels; i++)
+ ec->params.webrtc.rec_buffer[i] = pa_xnew(float, *nframes);
+ for (i = 0; i < play_ss->channels; i++)
+ ec->params.webrtc.play_buffer[i] = pa_xnew(float, *nframes);
+
pa_modargs_free(ma);
return true;
@@ -357,18 +361,14 @@ fail:
void pa_webrtc_ec_play(pa_echo_canceller *ec, const uint8_t *play) {
webrtc::AudioProcessing *apm = (webrtc::AudioProcessing*)ec->params.webrtc.apm;
- webrtc::AudioFrame play_frame;
const pa_sample_spec *ss = &ec->params.webrtc.play_ss;
+ int n = ec->params.webrtc.blocksize;
+ float **buf = ec->params.webrtc.play_buffer;
+ webrtc::StreamConfig config(ss->rate, ss->channels, false);
- play_frame.num_channels_ = ss->channels;
- play_frame.sample_rate_hz_ = ss->rate;
- play_frame.interleaved_ = true;
- play_frame.samples_per_channel_ = ec->params.webrtc.blocksize;
-
- pa_assert(play_frame.samples_per_channel_ <= webrtc::AudioFrame::kMaxDataSizeSamples);
- memcpy(play_frame.data_, play, ec->params.webrtc.blocksize * pa_frame_size(ss));
+ pa_deinterleave(play, (void **) buf, ss->channels, pa_sample_size(ss), n);
- pa_assert_se(apm->ProcessReverseStream(&play_frame) == webrtc::AudioProcessing::kNoError);
+ pa_assert_se(apm->ProcessReverseStream(buf, config, config, buf) == webrtc::AudioProcessing::kNoError);
/* FIXME: If ProcessReverseStream() makes any changes to the audio, such as
* applying intelligibility enhancement, those changes don't have any
@@ -379,19 +379,16 @@ void pa_webrtc_ec_play(pa_echo_canceller *ec, const uint8_t *play) {
void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out) {
webrtc::AudioProcessing *apm = (webrtc::AudioProcessing*)ec->params.webrtc.apm;
- webrtc::AudioFrame out_frame;
const pa_sample_spec *rec_ss = &ec->params.webrtc.rec_ss;
const pa_sample_spec *out_ss = &ec->params.webrtc.out_ss;
+ float **buf = ec->params.webrtc.rec_buffer;
+ int n = ec->params.webrtc.blocksize;
pa_cvolume v;
int old_volume, new_volume;
+ webrtc::StreamConfig rec_config(rec_ss->rate, rec_ss->channels, false);
+ webrtc::StreamConfig out_config(out_ss->rate, out_ss->channels, false);
- out_frame.num_channels_ = rec_ss->channels;
- out_frame.sample_rate_hz_ = rec_ss->rate;
- out_frame.interleaved_ = true;
- out_frame.samples_per_channel_ = ec->params.webrtc.blocksize;
-
- pa_assert(out_frame.samples_per_channel_ <= webrtc::AudioFrame::kMaxDataSizeSamples);
- memcpy(out_frame.data_, rec, ec->params.webrtc.blocksize * pa_frame_size(rec_ss));
+ pa_deinterleave(rec, (void **) buf, rec_ss->channels, pa_sample_size(rec_ss), n);
if (ec->params.webrtc.agc) {
pa_cvolume_init(&v);
@@ -401,7 +398,7 @@ void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out
}
apm->set_stream_delay_ms(0);
- pa_assert_se(apm->ProcessStream(&out_frame) == webrtc::AudioProcessing::kNoError);
+ pa_assert_se(apm->ProcessStream(buf, rec_config, out_config, buf) == webrtc::AudioProcessing::kNoError);
if (ec->params.webrtc.agc) {
if (PA_UNLIKELY(ec->params.webrtc.first)) {
@@ -421,7 +418,7 @@ void pa_webrtc_ec_record(pa_echo_canceller *ec, const uint8_t *rec, uint8_t *out
}
}
- memcpy(out, out_frame.data_, ec->params.webrtc.blocksize * pa_frame_size(out_ss));
+ pa_interleave((const void **) buf, out_ss->channels, out, pa_sample_size(out_ss), n);
}
void pa_webrtc_ec_set_drift(pa_echo_canceller *ec, float drift) {
@@ -436,6 +433,8 @@ void pa_webrtc_ec_run(pa_echo_canceller *ec, const uint8_t *rec, const uint8_t *
}
void pa_webrtc_ec_done(pa_echo_canceller *ec) {
+ int i;
+
if (ec->params.webrtc.trace_callback) {
webrtc::Trace::ReturnTrace();
delete ((PaWebrtcTraceCallback *) ec->params.webrtc.trace_callback);
@@ -445,4 +444,9 @@ void pa_webrtc_ec_done(pa_echo_canceller *ec) {
delete (webrtc::AudioProcessing*)ec->params.webrtc.apm;
ec->params.webrtc.apm = NULL;
}
+
+ for (i = 0; i < ec->params.webrtc.rec_ss.channels; i++)
+ pa_xfree(ec->params.webrtc.rec_buffer[i]);
+ for (i = 0; i < ec->params.webrtc.play_ss.channels; i++)
+ pa_xfree(ec->params.webrtc.play_buffer[i]);
}