]> code.delx.au - pulseaudio/blob - src/modules/echo-cancel/module-echo-cancel.c
a3e7e0d59507b54af04b48b5663b010e71104647
[pulseaudio] / src / modules / echo-cancel / module-echo-cancel.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2010 Wim Taymans <wim.taymans@gmail.com>
5
6 Based on module-virtual-sink.c
7 module-virtual-source.c
8 module-loopback.c
9
10 Copyright 2010 Intel Corporation
11 Contributor: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
12
13 PulseAudio is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published
15 by the Free Software Foundation; either version 2.1 of the License,
16 or (at your option) any later version.
17
18 PulseAudio is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License
24 along with PulseAudio; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 USA.
27 ***/
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include <stdio.h>
34
35 #include "echo-cancel.h"
36
37 #include <pulse/xmalloc.h>
38 #include <pulse/timeval.h>
39 #include <pulse/rtclock.h>
40
41 #include <pulsecore/i18n.h>
42 #include <pulsecore/atomic.h>
43 #include <pulsecore/macro.h>
44 #include <pulsecore/namereg.h>
45 #include <pulsecore/sink.h>
46 #include <pulsecore/module.h>
47 #include <pulsecore/core-rtclock.h>
48 #include <pulsecore/core-util.h>
49 #include <pulsecore/modargs.h>
50 #include <pulsecore/log.h>
51 #include <pulsecore/rtpoll.h>
52 #include <pulsecore/sample-util.h>
53 #include <pulsecore/ltdl-helper.h>
54
55 #include "module-echo-cancel-symdef.h"
56
57 PA_MODULE_AUTHOR("Wim Taymans");
58 PA_MODULE_DESCRIPTION("Echo Cancellation");
59 PA_MODULE_VERSION(PACKAGE_VERSION);
60 PA_MODULE_LOAD_ONCE(FALSE);
61 PA_MODULE_USAGE(
62 _("source_name=<name for the source> "
63 "source_properties=<properties for the source> "
64 "source_master=<name of source to filter> "
65 "sink_name=<name for the sink> "
66 "sink_properties=<properties for the sink> "
67 "sink_master=<name of sink to filter> "
68 "adjust_time=<how often to readjust rates in s> "
69 "adjust_threshold=<how much drift to readjust after in ms> "
70 "format=<sample format> "
71 "rate=<sample rate> "
72 "channels=<number of channels> "
73 "channel_map=<channel map> "
74 "aec_method=<implementation to use> "
75 "aec_args=<parameters for the AEC engine> "
76 "save_aec=<save AEC data in /tmp> "
77 "autoloaded=<set if this module is being loaded automatically> "
78 "use_volume_sharing=<yes or no> "
79 ));
80
81 /* NOTE: Make sure the enum and ec_table are maintained in the correct order */
82 typedef enum {
83 PA_ECHO_CANCELLER_INVALID = -1,
84 PA_ECHO_CANCELLER_SPEEX = 0,
85 PA_ECHO_CANCELLER_ADRIAN,
86 } pa_echo_canceller_method_t;
87
88 #define DEFAULT_ECHO_CANCELLER "speex"
89
90 static const pa_echo_canceller ec_table[] = {
91 {
92 /* Speex */
93 .init = pa_speex_ec_init,
94 .run = pa_speex_ec_run,
95 .done = pa_speex_ec_done,
96 },
97 {
98 /* Adrian Andre's NLMS implementation */
99 .init = pa_adrian_ec_init,
100 .run = pa_adrian_ec_run,
101 .done = pa_adrian_ec_done,
102 },
103 };
104
105 #define DEFAULT_RATE 32000
106 #define DEFAULT_CHANNELS 1
107 #define DEFAULT_ADJUST_TIME_USEC (1*PA_USEC_PER_SEC)
108 #define DEFAULT_ADJUST_TOLERANCE (5*PA_USEC_PER_MSEC)
109 #define DEFAULT_SAVE_AEC FALSE
110 #define DEFAULT_AUTOLOADED FALSE
111
112 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
113
114 /* This module creates a new (virtual) source and sink.
115 *
116 * The data sent to the new sink is kept in a memblockq before being
117 * forwarded to the real sink_master.
118 *
119 * Data read from source_master is matched against the saved sink data and
120 * echo canceled data is then pushed onto the new source.
121 *
122 * Both source and sink masters have their own threads to push/pull data
123 * respectively. We however perform all our actions in the source IO thread.
124 * To do this we send all played samples to the source IO thread where they
125 * are then pushed into the memblockq.
126 *
127 * Alignment is performed in two steps:
128 *
129 * 1) when something happens that requires quick adjustment of the alignment of
130 * capture and playback samples, we perform a resync. This adjusts the
131 * position in the playback memblock to the requested sample. Quick
132 * adjustments include moving the playback samples before the capture
133 * samples (because else the echo canceler does not work) or when the
134 * playback pointer drifts too far away.
135 *
136 * 2) periodically check the difference between capture and playback. we use a
137 * low and high watermark for adjusting the alignment. playback should always
138 * be before capture and the difference should not be bigger than one frame
139 * size. We would ideally like to resample the sink_input but most driver
140 * don't give enough accuracy to be able to do that right now.
141 */
142
143 struct snapshot {
144 pa_usec_t sink_now;
145 pa_usec_t sink_latency;
146 size_t sink_delay;
147 int64_t send_counter;
148
149 pa_usec_t source_now;
150 pa_usec_t source_latency;
151 size_t source_delay;
152 int64_t recv_counter;
153 size_t rlen;
154 size_t plen;
155 };
156
157 struct userdata {
158 pa_core *core;
159 pa_module *module;
160
161 pa_bool_t autoloaded;
162 pa_bool_t dead;
163 pa_bool_t save_aec;
164
165 pa_echo_canceller *ec;
166 uint32_t blocksize;
167
168 pa_bool_t need_realign;
169
170 /* to wakeup the source I/O thread */
171 pa_asyncmsgq *asyncmsgq;
172 pa_rtpoll_item *rtpoll_item_read, *rtpoll_item_write;
173
174 pa_source *source;
175 pa_bool_t source_auto_desc;
176 pa_source_output *source_output;
177 pa_memblockq *source_memblockq; /* echo canceler needs fixed sized chunks */
178 size_t source_skip;
179
180 pa_sink *sink;
181 pa_bool_t sink_auto_desc;
182 pa_sink_input *sink_input;
183 pa_memblockq *sink_memblockq;
184 int64_t send_counter; /* updated in sink IO thread */
185 int64_t recv_counter;
186 size_t sink_skip;
187
188 pa_atomic_t request_resync;
189
190 int active_mask;
191 pa_time_event *time_event;
192 pa_usec_t adjust_time;
193 int adjust_threshold;
194
195 FILE *captured_file;
196 FILE *played_file;
197 FILE *canceled_file;
198 };
199
200 static void source_output_snapshot_within_thread(struct userdata *u, struct snapshot *snapshot);
201
202 static const char* const valid_modargs[] = {
203 "source_name",
204 "source_properties",
205 "source_master",
206 "sink_name",
207 "sink_properties",
208 "sink_master",
209 "adjust_time",
210 "adjust_threshold",
211 "format",
212 "rate",
213 "channels",
214 "channel_map",
215 "aec_method",
216 "aec_args",
217 "save_aec",
218 "autoloaded",
219 "use_volume_sharing",
220 NULL
221 };
222
223 enum {
224 SOURCE_OUTPUT_MESSAGE_POST = PA_SOURCE_OUTPUT_MESSAGE_MAX,
225 SOURCE_OUTPUT_MESSAGE_REWIND,
226 SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT,
227 SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME
228 };
229
230 enum {
231 SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
232 };
233
234 static int64_t calc_diff(struct userdata *u, struct snapshot *snapshot) {
235 int64_t buffer, diff_time, buffer_latency;
236
237 /* get the number of samples between capture and playback */
238 if (snapshot->plen > snapshot->rlen)
239 buffer = snapshot->plen - snapshot->rlen;
240 else
241 buffer = 0;
242
243 buffer += snapshot->source_delay + snapshot->sink_delay;
244
245 /* add the amount of samples not yet transferred to the source context */
246 if (snapshot->recv_counter <= snapshot->send_counter)
247 buffer += (int64_t) (snapshot->send_counter - snapshot->recv_counter);
248 else
249 buffer += PA_CLIP_SUB(buffer, (int64_t) (snapshot->recv_counter - snapshot->send_counter));
250
251 /* convert to time */
252 buffer_latency = pa_bytes_to_usec(buffer, &u->source_output->sample_spec);
253
254 /* capture and playback samples are perfectly aligned when diff_time is 0 */
255 diff_time = (snapshot->sink_now + snapshot->sink_latency - buffer_latency) -
256 (snapshot->source_now - snapshot->source_latency);
257
258 pa_log_debug("diff %lld (%lld - %lld + %lld) %lld %lld %lld %lld", (long long) diff_time,
259 (long long) snapshot->sink_latency,
260 (long long) buffer_latency, (long long) snapshot->source_latency,
261 (long long) snapshot->source_delay, (long long) snapshot->sink_delay,
262 (long long) (snapshot->send_counter - snapshot->recv_counter),
263 (long long) (snapshot->sink_now - snapshot->source_now));
264
265 return diff_time;
266 }
267
268 /* Called from main context */
269 static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
270 struct userdata *u = userdata;
271 uint32_t old_rate, base_rate, new_rate;
272 int64_t diff_time;
273 /*size_t fs*/
274 struct snapshot latency_snapshot;
275
276 pa_assert(u);
277 pa_assert(a);
278 pa_assert(u->time_event == e);
279 pa_assert_ctl_context();
280
281 if (u->active_mask != 3)
282 return;
283
284 /* update our snapshots */
285 pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, &latency_snapshot, 0, NULL);
286 pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, &latency_snapshot, 0, NULL);
287
288 /* calculate drift between capture and playback */
289 diff_time = calc_diff(u, &latency_snapshot);
290
291 /*fs = pa_frame_size(&u->source_output->sample_spec);*/
292 old_rate = u->sink_input->sample_spec.rate;
293 base_rate = u->source_output->sample_spec.rate;
294
295 if (diff_time < 0) {
296 /* recording before playback, we need to adjust quickly. The echo
297 * canceler does not work in this case. */
298 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME,
299 NULL, diff_time, NULL, NULL);
300 /*new_rate = base_rate - ((pa_usec_to_bytes(-diff_time, &u->source_output->sample_spec) / fs) * PA_USEC_PER_SEC) / u->adjust_time;*/
301 new_rate = base_rate;
302 }
303 else {
304 if (diff_time > u->adjust_threshold) {
305 /* diff too big, quickly adjust */
306 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME,
307 NULL, diff_time, NULL, NULL);
308 }
309
310 /* recording behind playback, we need to slowly adjust the rate to match */
311 /*new_rate = base_rate + ((pa_usec_to_bytes(diff_time, &u->source_output->sample_spec) / fs) * PA_USEC_PER_SEC) / u->adjust_time;*/
312
313 /* assume equal samplerates for now */
314 new_rate = base_rate;
315 }
316
317 /* make sure we don't make too big adjustments because that sounds horrible */
318 if (new_rate > base_rate * 1.1 || new_rate < base_rate * 0.9)
319 new_rate = base_rate;
320
321 if (new_rate != old_rate) {
322 pa_log_info("Old rate %lu Hz, new rate %lu Hz", (unsigned long) old_rate, (unsigned long) new_rate);
323
324 pa_sink_input_set_rate(u->sink_input, new_rate);
325 }
326
327 pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
328 }
329
330 /* Called from source I/O thread context */
331 static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
332 struct userdata *u = PA_SOURCE(o)->userdata;
333
334 switch (code) {
335
336 case PA_SOURCE_MESSAGE_GET_LATENCY:
337
338 /* The source is _put() before the source output is, so let's
339 * make sure we don't access it in that time. Also, the
340 * source output is first shut down, the source second. */
341 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
342 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state)) {
343 *((pa_usec_t*) data) = 0;
344 return 0;
345 }
346
347 *((pa_usec_t*) data) =
348
349 /* Get the latency of the master source */
350 pa_source_get_latency_within_thread(u->source_output->source) +
351 /* Add the latency internal to our source output on top */
352 pa_bytes_to_usec(pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq), &u->source_output->source->sample_spec) +
353 /* and the buffering we do on the source */
354 pa_bytes_to_usec(u->blocksize, &u->source_output->source->sample_spec);
355
356 return 0;
357
358 }
359
360 return pa_source_process_msg(o, code, data, offset, chunk);
361 }
362
363 /* Called from sink I/O thread context */
364 static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
365 struct userdata *u = PA_SINK(o)->userdata;
366
367 switch (code) {
368
369 case PA_SINK_MESSAGE_GET_LATENCY:
370
371 /* The sink is _put() before the sink input is, so let's
372 * make sure we don't access it in that time. Also, the
373 * sink input is first shut down, the sink second. */
374 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
375 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
376 *((pa_usec_t*) data) = 0;
377 return 0;
378 }
379
380 *((pa_usec_t*) data) =
381
382 /* Get the latency of the master sink */
383 pa_sink_get_latency_within_thread(u->sink_input->sink) +
384
385 /* Add the latency internal to our sink input on top */
386 pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);
387
388 return 0;
389 }
390
391 return pa_sink_process_msg(o, code, data, offset, chunk);
392 }
393
394
395 /* Called from main context */
396 static int source_set_state_cb(pa_source *s, pa_source_state_t state) {
397 struct userdata *u;
398
399 pa_source_assert_ref(s);
400 pa_assert_se(u = s->userdata);
401
402 if (!PA_SOURCE_IS_LINKED(state) ||
403 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
404 return 0;
405
406 pa_log_debug("Source state %d %d", state, u->active_mask);
407
408 if (state == PA_SOURCE_RUNNING) {
409 /* restart timer when both sink and source are active */
410 u->active_mask |= 1;
411 if (u->active_mask == 3 && u->adjust_time)
412 pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
413
414 pa_atomic_store(&u->request_resync, 1);
415 pa_source_output_cork(u->source_output, FALSE);
416 } else if (state == PA_SOURCE_SUSPENDED) {
417 u->active_mask &= ~1;
418 pa_source_output_cork(u->source_output, TRUE);
419 }
420 return 0;
421 }
422
423 /* Called from main context */
424 static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
425 struct userdata *u;
426
427 pa_sink_assert_ref(s);
428 pa_assert_se(u = s->userdata);
429
430 if (!PA_SINK_IS_LINKED(state) ||
431 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
432 return 0;
433
434 pa_log_debug("Sink state %d %d", state, u->active_mask);
435
436 if (state == PA_SINK_RUNNING) {
437 /* restart timer when both sink and source are active */
438 u->active_mask |= 2;
439 if (u->active_mask == 3 && u->adjust_time)
440 pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
441
442 pa_atomic_store(&u->request_resync, 1);
443 pa_sink_input_cork(u->sink_input, FALSE);
444 } else if (state == PA_SINK_SUSPENDED) {
445 u->active_mask &= ~2;
446 pa_sink_input_cork(u->sink_input, TRUE);
447 }
448 return 0;
449 }
450
451 /* Called from I/O thread context */
452 static void source_update_requested_latency_cb(pa_source *s) {
453 struct userdata *u;
454
455 pa_source_assert_ref(s);
456 pa_assert_se(u = s->userdata);
457
458 if (!PA_SOURCE_IS_LINKED(u->source->thread_info.state) ||
459 !PA_SOURCE_OUTPUT_IS_LINKED(u->source_output->thread_info.state))
460 return;
461
462 pa_log_debug("Source update requested latency");
463
464 /* Just hand this one over to the master source */
465 pa_source_output_set_requested_latency_within_thread(
466 u->source_output,
467 pa_source_get_requested_latency_within_thread(s));
468 }
469
470 /* Called from I/O thread context */
471 static void sink_update_requested_latency_cb(pa_sink *s) {
472 struct userdata *u;
473
474 pa_sink_assert_ref(s);
475 pa_assert_se(u = s->userdata);
476
477 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
478 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
479 return;
480
481 pa_log_debug("Sink update requested latency");
482
483 /* Just hand this one over to the master sink */
484 pa_sink_input_set_requested_latency_within_thread(
485 u->sink_input,
486 pa_sink_get_requested_latency_within_thread(s));
487 }
488
489 /* Called from I/O thread context */
490 static void sink_request_rewind_cb(pa_sink *s) {
491 struct userdata *u;
492
493 pa_sink_assert_ref(s);
494 pa_assert_se(u = s->userdata);
495
496 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
497 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
498 return;
499
500 pa_log_debug("Sink request rewind %lld", (long long) s->thread_info.rewind_nbytes);
501
502 /* Just hand this one over to the master sink */
503 pa_sink_input_request_rewind(u->sink_input,
504 s->thread_info.rewind_nbytes, TRUE, FALSE, FALSE);
505 }
506
507 /* Called from main context */
508 static void source_set_volume_cb(pa_source *s) {
509 struct userdata *u;
510
511 pa_source_assert_ref(s);
512 pa_assert_se(u = s->userdata);
513
514 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
515 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
516 return;
517
518 pa_source_output_set_volume(u->source_output, &s->real_volume, s->save_volume, TRUE);
519 }
520
521 /* Called from main context */
522 static void sink_set_volume_cb(pa_sink *s) {
523 struct userdata *u;
524
525 pa_sink_assert_ref(s);
526 pa_assert_se(u = s->userdata);
527
528 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
529 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
530 return;
531
532 pa_sink_input_set_volume(u->sink_input, &s->real_volume, s->save_volume, TRUE);
533 }
534
535 static void source_get_volume_cb(pa_source *s) {
536 struct userdata *u;
537 pa_cvolume v;
538
539 pa_source_assert_ref(s);
540 pa_assert_se(u = s->userdata);
541
542 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
543 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
544 return;
545
546 pa_source_output_get_volume(u->source_output, &v, TRUE);
547
548 if (pa_cvolume_equal(&s->real_volume, &v))
549 /* no change */
550 return;
551
552 s->real_volume = v;
553 pa_source_set_soft_volume(s, NULL);
554 }
555
556 /* Called from main context */
557 static void source_set_mute_cb(pa_source *s) {
558 struct userdata *u;
559
560 pa_source_assert_ref(s);
561 pa_assert_se(u = s->userdata);
562
563 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
564 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
565 return;
566
567 pa_source_output_set_mute(u->source_output, s->muted, s->save_muted);
568 }
569
570 /* Called from main context */
571 static void sink_set_mute_cb(pa_sink *s) {
572 struct userdata *u;
573
574 pa_sink_assert_ref(s);
575 pa_assert_se(u = s->userdata);
576
577 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
578 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
579 return;
580
581 pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
582 }
583
584 /* Called from main context */
585 static void source_get_mute_cb(pa_source *s) {
586 struct userdata *u;
587
588 pa_source_assert_ref(s);
589 pa_assert_se(u = s->userdata);
590
591 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s)) ||
592 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
593 return;
594
595 pa_source_output_get_mute(u->source_output);
596 }
597
598 /* must be called from the input thread context */
599 static void apply_diff_time(struct userdata *u, int64_t diff_time) {
600 int64_t diff;
601
602 if (diff_time < 0) {
603 diff = pa_usec_to_bytes(-diff_time, &u->source_output->sample_spec);
604
605 if (diff > 0) {
606 /* add some extra safety samples to compensate for jitter in the
607 * timings */
608 diff += 10 * pa_frame_size (&u->source_output->sample_spec);
609
610 pa_log("Playback after capture (%lld), drop sink %lld", (long long) diff_time, (long long) diff);
611
612 u->sink_skip = diff;
613 u->source_skip = 0;
614 }
615 } else if (diff_time > 0) {
616 diff = pa_usec_to_bytes(diff_time, &u->source_output->sample_spec);
617
618 if (diff > 0) {
619 pa_log("playback too far ahead (%lld), drop source %lld", (long long) diff_time, (long long) diff);
620
621 u->source_skip = diff;
622 u->sink_skip = 0;
623 }
624 }
625 }
626
627 /* must be called from the input thread */
628 static void do_resync(struct userdata *u) {
629 int64_t diff_time;
630 struct snapshot latency_snapshot;
631
632 pa_log("Doing resync");
633
634 /* update our snapshot */
635 source_output_snapshot_within_thread(u, &latency_snapshot);
636 pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, &latency_snapshot, 0, NULL);
637
638 /* calculate drift between capture and playback */
639 diff_time = calc_diff(u, &latency_snapshot);
640
641 /* and adjust for the drift */
642 apply_diff_time(u, diff_time);
643 }
644
645 /* Called from input thread context */
646 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
647 struct userdata *u;
648 size_t rlen, plen;
649
650 pa_source_output_assert_ref(o);
651 pa_source_output_assert_io_context(o);
652 pa_assert_se(u = o->userdata);
653
654 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output))) {
655 pa_log("push when no link?");
656 return;
657 }
658
659 /* handle queued messages, do any message sending of our own */
660 while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
661 ;
662
663 if (pa_atomic_cmpxchg (&u->request_resync, 1, 0)) {
664 do_resync(u);
665 }
666
667 pa_memblockq_push_align(u->source_memblockq, chunk);
668
669 rlen = pa_memblockq_get_length(u->source_memblockq);
670 plen = pa_memblockq_get_length(u->sink_memblockq);
671
672 while (rlen >= u->blocksize) {
673 pa_memchunk rchunk, pchunk;
674
675 /* take fixed block from recorded samples */
676 pa_memblockq_peek_fixed_size(u->source_memblockq, u->blocksize, &rchunk);
677
678 if (plen > u->blocksize && u->source_skip == 0) {
679 uint8_t *rdata, *pdata, *cdata;
680 pa_memchunk cchunk;
681 int unused;
682
683 if (u->sink_skip) {
684 size_t to_skip;
685
686 if (u->sink_skip > plen)
687 to_skip = plen;
688 else
689 to_skip = u->sink_skip;
690
691 pa_memblockq_drop(u->sink_memblockq, to_skip);
692 plen -= to_skip;
693
694 u->sink_skip -= to_skip;
695 }
696
697 if (plen > u->blocksize && u->sink_skip == 0) {
698 /* take fixed block from played samples */
699 pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
700
701 rdata = pa_memblock_acquire(rchunk.memblock);
702 rdata += rchunk.index;
703 pdata = pa_memblock_acquire(pchunk.memblock);
704 pdata += pchunk.index;
705
706 cchunk.index = 0;
707 cchunk.length = u->blocksize;
708 cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
709 cdata = pa_memblock_acquire(cchunk.memblock);
710
711 if (u->save_aec) {
712 if (u->captured_file)
713 unused = fwrite(rdata, 1, u->blocksize, u->captured_file);
714 if (u->played_file)
715 unused = fwrite(pdata, 1, u->blocksize, u->played_file);
716 }
717
718 /* perform echo cancellation */
719 u->ec->run(u->ec, rdata, pdata, cdata);
720
721 if (u->save_aec) {
722 if (u->canceled_file)
723 unused = fwrite(cdata, 1, u->blocksize, u->canceled_file);
724 }
725
726 pa_memblock_release(cchunk.memblock);
727 pa_memblock_release(pchunk.memblock);
728 pa_memblock_release(rchunk.memblock);
729
730 /* drop consumed sink samples */
731 pa_memblockq_drop(u->sink_memblockq, u->blocksize);
732 pa_memblock_unref(pchunk.memblock);
733
734 pa_memblock_unref(rchunk.memblock);
735 /* the filtered samples now become the samples from our
736 * source */
737 rchunk = cchunk;
738
739 plen -= u->blocksize;
740 }
741 }
742
743 /* forward the (echo-canceled) data to the virtual source */
744 pa_source_post(u->source, &rchunk);
745 pa_memblock_unref(rchunk.memblock);
746
747 pa_memblockq_drop(u->source_memblockq, u->blocksize);
748 rlen -= u->blocksize;
749
750 if (u->source_skip) {
751 if (u->source_skip > u->blocksize) {
752 u->source_skip -= u->blocksize;
753 }
754 else {
755 u->sink_skip += (u->blocksize - u->source_skip);
756 u->source_skip = 0;
757 }
758 }
759 }
760 }
761
762 /* Called from I/O thread context */
763 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
764 struct userdata *u;
765
766 pa_sink_input_assert_ref(i);
767 pa_assert(chunk);
768 pa_assert_se(u = i->userdata);
769
770 if (u->sink->thread_info.rewind_requested)
771 pa_sink_process_rewind(u->sink, 0);
772
773 pa_sink_render_full(u->sink, nbytes, chunk);
774
775 if (i->thread_info.underrun_for > 0) {
776 pa_log_debug("Handling end of underrun.");
777 pa_atomic_store(&u->request_resync, 1);
778 }
779
780 /* let source thread handle the chunk. pass the sample count as well so that
781 * the source IO thread can update the right variables. */
782 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_POST,
783 NULL, 0, chunk, NULL);
784 u->send_counter += chunk->length;
785
786 return 0;
787 }
788
789 /* Called from input thread context */
790 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
791 struct userdata *u;
792
793 pa_source_output_assert_ref(o);
794 pa_source_output_assert_io_context(o);
795 pa_assert_se(u = o->userdata);
796
797 pa_source_process_rewind(u->source, nbytes);
798
799 /* go back on read side, we need to use older sink data for this */
800 pa_memblockq_rewind(u->sink_memblockq, nbytes);
801
802 /* manipulate write index */
803 pa_memblockq_seek(u->source_memblockq, -nbytes, PA_SEEK_RELATIVE, TRUE);
804
805 pa_log_debug("Source rewind (%lld) %lld", (long long) nbytes,
806 (long long) pa_memblockq_get_length (u->source_memblockq));
807 }
808
809 /* Called from I/O thread context */
810 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
811 struct userdata *u;
812
813 pa_sink_input_assert_ref(i);
814 pa_assert_se(u = i->userdata);
815
816 pa_log_debug("Sink process rewind %lld", (long long) nbytes);
817
818 pa_sink_process_rewind(u->sink, nbytes);
819
820 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
821 u->send_counter -= nbytes;
822 }
823
824 static void source_output_snapshot_within_thread(struct userdata *u, struct snapshot *snapshot) {
825 size_t delay, rlen, plen;
826 pa_usec_t now, latency;
827
828 now = pa_rtclock_now();
829 latency = pa_source_get_latency_within_thread(u->source_output->source);
830 delay = pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq);
831
832 delay = (u->source_output->thread_info.resampler ? pa_resampler_request(u->source_output->thread_info.resampler, delay) : delay);
833 rlen = pa_memblockq_get_length(u->source_memblockq);
834 plen = pa_memblockq_get_length(u->sink_memblockq);
835
836 snapshot->source_now = now;
837 snapshot->source_latency = latency;
838 snapshot->source_delay = delay;
839 snapshot->recv_counter = u->recv_counter;
840 snapshot->rlen = rlen + u->sink_skip;
841 snapshot->plen = plen + u->source_skip;
842 }
843
844
845 /* Called from output thread context */
846 static int source_output_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
847 struct userdata *u = PA_SOURCE_OUTPUT(obj)->userdata;
848
849 switch (code) {
850
851 case SOURCE_OUTPUT_MESSAGE_POST:
852
853 pa_source_output_assert_io_context(u->source_output);
854
855 if (PA_SOURCE_IS_OPENED(u->source_output->source->thread_info.state))
856 pa_memblockq_push_align(u->sink_memblockq, chunk);
857 else
858 pa_memblockq_flush_write(u->sink_memblockq, TRUE);
859
860 u->recv_counter += (int64_t) chunk->length;
861
862 return 0;
863
864 case SOURCE_OUTPUT_MESSAGE_REWIND:
865 pa_source_output_assert_io_context(u->source_output);
866
867 /* manipulate write index, never go past what we have */
868 if (PA_SOURCE_IS_OPENED(u->source_output->source->thread_info.state))
869 pa_memblockq_seek(u->sink_memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
870 else
871 pa_memblockq_flush_write(u->sink_memblockq, TRUE);
872
873 pa_log_debug("Sink rewind (%lld)", (long long) offset);
874
875 u->recv_counter -= offset;
876
877 return 0;
878
879 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT: {
880 struct snapshot *snapshot = (struct snapshot *) data;
881
882 source_output_snapshot_within_thread(u, snapshot);
883 return 0;
884 }
885
886 case SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME:
887 apply_diff_time(u, offset);
888 return 0;
889
890 }
891
892 return pa_source_output_process_msg(obj, code, data, offset, chunk);
893 }
894
895 static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
896 struct userdata *u = PA_SINK_INPUT(obj)->userdata;
897
898 switch (code) {
899
900 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT: {
901 size_t delay;
902 pa_usec_t now, latency;
903 struct snapshot *snapshot = (struct snapshot *) data;
904
905 pa_sink_input_assert_io_context(u->sink_input);
906
907 now = pa_rtclock_now();
908 latency = pa_sink_get_latency_within_thread(u->sink_input->sink);
909 delay = pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq);
910
911 delay = (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, delay) : delay);
912
913 snapshot->sink_now = now;
914 snapshot->sink_latency = latency;
915 snapshot->sink_delay = delay;
916 snapshot->send_counter = u->send_counter;
917 return 0;
918 }
919 }
920
921 return pa_sink_input_process_msg(obj, code, data, offset, chunk);
922 }
923
924 /* Called from I/O thread context */
925 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
926 struct userdata *u;
927
928 pa_sink_input_assert_ref(i);
929 pa_assert_se(u = i->userdata);
930
931 pa_log_debug("Sink input update max rewind %lld", (long long) nbytes);
932
933 pa_memblockq_set_maxrewind(u->sink_memblockq, nbytes);
934 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
935 }
936
937 /* Called from I/O thread context */
938 static void source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes) {
939 struct userdata *u;
940
941 pa_source_output_assert_ref(o);
942 pa_assert_se(u = o->userdata);
943
944 pa_log_debug("Source output update max rewind %lld", (long long) nbytes);
945
946 pa_source_set_max_rewind_within_thread(u->source, nbytes);
947 }
948
949 /* Called from I/O thread context */
950 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
951 struct userdata *u;
952
953 pa_sink_input_assert_ref(i);
954 pa_assert_se(u = i->userdata);
955
956 pa_log_debug("Sink input update max request %lld", (long long) nbytes);
957
958 pa_sink_set_max_request_within_thread(u->sink, nbytes);
959 }
960
961 /* Called from I/O thread context */
962 static void sink_input_update_sink_requested_latency_cb(pa_sink_input *i) {
963 struct userdata *u;
964 pa_usec_t latency;
965
966 pa_sink_input_assert_ref(i);
967 pa_assert_se(u = i->userdata);
968
969 latency = pa_sink_get_requested_latency_within_thread(i->sink);
970
971 pa_log_debug("Sink input update requested latency %lld", (long long) latency);
972 }
973
974 /* Called from I/O thread context */
975 static void source_output_update_source_requested_latency_cb(pa_source_output *o) {
976 struct userdata *u;
977 pa_usec_t latency;
978
979 pa_source_output_assert_ref(o);
980 pa_assert_se(u = o->userdata);
981
982 latency = pa_source_get_requested_latency_within_thread(o->source);
983
984 pa_log_debug("source output update requested latency %lld", (long long) latency);
985 }
986
987 /* Called from I/O thread context */
988 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
989 struct userdata *u;
990
991 pa_sink_input_assert_ref(i);
992 pa_assert_se(u = i->userdata);
993
994 pa_log_debug("Sink input update latency range %lld %lld",
995 (long long) i->sink->thread_info.min_latency,
996 (long long) i->sink->thread_info.max_latency);
997
998 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
999 }
1000
1001 /* Called from I/O thread context */
1002 static void source_output_update_source_latency_range_cb(pa_source_output *o) {
1003 struct userdata *u;
1004
1005 pa_source_output_assert_ref(o);
1006 pa_assert_se(u = o->userdata);
1007
1008 pa_log_debug("Source output update latency range %lld %lld",
1009 (long long) o->source->thread_info.min_latency,
1010 (long long) o->source->thread_info.max_latency);
1011
1012 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
1013 }
1014
1015 /* Called from I/O thread context */
1016 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
1017 struct userdata *u;
1018
1019 pa_sink_input_assert_ref(i);
1020 pa_assert_se(u = i->userdata);
1021
1022 pa_log_debug("Sink input update fixed latency %lld",
1023 (long long) i->sink->thread_info.fixed_latency);
1024
1025 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
1026 }
1027
1028 /* Called from I/O thread context */
1029 static void source_output_update_source_fixed_latency_cb(pa_source_output *o) {
1030 struct userdata *u;
1031
1032 pa_source_output_assert_ref(o);
1033 pa_assert_se(u = o->userdata);
1034
1035 pa_log_debug("Source output update fixed latency %lld",
1036 (long long) o->source->thread_info.fixed_latency);
1037
1038 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
1039 }
1040
1041 /* Called from output thread context */
1042 static void source_output_attach_cb(pa_source_output *o) {
1043 struct userdata *u;
1044
1045 pa_source_output_assert_ref(o);
1046 pa_source_output_assert_io_context(o);
1047 pa_assert_se(u = o->userdata);
1048
1049 pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
1050 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
1051 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
1052 pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
1053
1054 pa_log_debug("Source output %d attach", o->index);
1055
1056 pa_source_attach_within_thread(u->source);
1057
1058 u->rtpoll_item_read = pa_rtpoll_item_new_asyncmsgq_read(
1059 o->source->thread_info.rtpoll,
1060 PA_RTPOLL_LATE,
1061 u->asyncmsgq);
1062 }
1063
1064 /* Called from I/O thread context */
1065 static void sink_input_attach_cb(pa_sink_input *i) {
1066 struct userdata *u;
1067
1068 pa_sink_input_assert_ref(i);
1069 pa_assert_se(u = i->userdata);
1070
1071 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
1072 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1073
1074 /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
1075 * BLOCK MINUS ONE SAMPLE HERE. SEE (7) */
1076 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
1077
1078 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
1079 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
1080 * HERE. SEE (6) */
1081 pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
1082 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
1083
1084 pa_log_debug("Sink input %d attach", i->index);
1085
1086 u->rtpoll_item_write = pa_rtpoll_item_new_asyncmsgq_write(
1087 i->sink->thread_info.rtpoll,
1088 PA_RTPOLL_LATE,
1089 u->asyncmsgq);
1090
1091 pa_sink_attach_within_thread(u->sink);
1092 }
1093
1094
1095 /* Called from output thread context */
1096 static void source_output_detach_cb(pa_source_output *o) {
1097 struct userdata *u;
1098
1099 pa_source_output_assert_ref(o);
1100 pa_source_output_assert_io_context(o);
1101 pa_assert_se(u = o->userdata);
1102
1103 pa_source_detach_within_thread(u->source);
1104 pa_source_set_rtpoll(u->source, NULL);
1105
1106 pa_log_debug("Source output %d detach", o->index);
1107
1108 if (u->rtpoll_item_read) {
1109 pa_rtpoll_item_free(u->rtpoll_item_read);
1110 u->rtpoll_item_read = NULL;
1111 }
1112 }
1113
1114 /* Called from I/O thread context */
1115 static void sink_input_detach_cb(pa_sink_input *i) {
1116 struct userdata *u;
1117
1118 pa_sink_input_assert_ref(i);
1119 pa_assert_se(u = i->userdata);
1120
1121 pa_sink_detach_within_thread(u->sink);
1122
1123 pa_sink_set_rtpoll(u->sink, NULL);
1124
1125 pa_log_debug("Sink input %d detach", i->index);
1126
1127 if (u->rtpoll_item_write) {
1128 pa_rtpoll_item_free(u->rtpoll_item_write);
1129 u->rtpoll_item_write = NULL;
1130 }
1131 }
1132
1133 /* Called from output thread context */
1134 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
1135 struct userdata *u;
1136
1137 pa_source_output_assert_ref(o);
1138 pa_source_output_assert_io_context(o);
1139 pa_assert_se(u = o->userdata);
1140
1141 pa_log_debug("Source output %d state %d", o->index, state);
1142 }
1143
1144 /* Called from IO thread context */
1145 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
1146 struct userdata *u;
1147
1148 pa_sink_input_assert_ref(i);
1149 pa_assert_se(u = i->userdata);
1150
1151 pa_log_debug("Sink input %d state %d", i->index, state);
1152
1153 /* If we are added for the first time, ask for a rewinding so that
1154 * we are heard right-away. */
1155 if (PA_SINK_INPUT_IS_LINKED(state) &&
1156 i->thread_info.state == PA_SINK_INPUT_INIT) {
1157 pa_log_debug("Requesting rewind due to state change.");
1158 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1159 }
1160 }
1161
1162 /* Called from main thread */
1163 static void source_output_kill_cb(pa_source_output *o) {
1164 struct userdata *u;
1165
1166 pa_source_output_assert_ref(o);
1167 pa_assert_ctl_context();
1168 pa_assert_se(u = o->userdata);
1169
1170 u->dead = TRUE;
1171
1172 /* The order here matters! We first kill the source output, followed
1173 * by the source. That means the source callbacks must be protected
1174 * against an unconnected source output! */
1175 pa_source_output_unlink(u->source_output);
1176 pa_source_unlink(u->source);
1177
1178 pa_source_output_unref(u->source_output);
1179 u->source_output = NULL;
1180
1181 pa_source_unref(u->source);
1182 u->source = NULL;
1183
1184 pa_log_debug("Source output kill %d", o->index);
1185
1186 pa_module_unload_request(u->module, TRUE);
1187 }
1188
1189 /* Called from main context */
1190 static void sink_input_kill_cb(pa_sink_input *i) {
1191 struct userdata *u;
1192
1193 pa_sink_input_assert_ref(i);
1194 pa_assert_se(u = i->userdata);
1195
1196 u->dead = TRUE;
1197
1198 /* The order here matters! We first kill the sink input, followed
1199 * by the sink. That means the sink callbacks must be protected
1200 * against an unconnected sink input! */
1201 pa_sink_input_unlink(u->sink_input);
1202 pa_sink_unlink(u->sink);
1203
1204 pa_sink_input_unref(u->sink_input);
1205 u->sink_input = NULL;
1206
1207 pa_sink_unref(u->sink);
1208 u->sink = NULL;
1209
1210 pa_log_debug("Sink input kill %d", i->index);
1211
1212 pa_module_unload_request(u->module, TRUE);
1213 }
1214
1215 /* Called from main thread */
1216 static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
1217 struct userdata *u;
1218
1219 pa_source_output_assert_ref(o);
1220 pa_assert_ctl_context();
1221 pa_assert_se(u = o->userdata);
1222
1223 if (u->dead)
1224 return FALSE;
1225
1226 return (u->source != dest) && (u->sink != dest->monitor_of);
1227 }
1228
1229 /* Called from main context */
1230 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
1231 struct userdata *u;
1232
1233 pa_sink_input_assert_ref(i);
1234 pa_assert_se(u = i->userdata);
1235
1236 if (u->dead)
1237 return FALSE;
1238
1239 return u->sink != dest;
1240 }
1241
1242 /* Called from main thread */
1243 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1244 struct userdata *u;
1245
1246 pa_source_output_assert_ref(o);
1247 pa_assert_ctl_context();
1248 pa_assert_se(u = o->userdata);
1249
1250 if (dest) {
1251 pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
1252 pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
1253 } else
1254 pa_source_set_asyncmsgq(u->source, NULL);
1255
1256 if (u->source_auto_desc && dest) {
1257 const char *z;
1258 pa_proplist *pl;
1259
1260 pl = pa_proplist_new();
1261 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
1262 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s",
1263 pa_proplist_gets(u->source->proplist, "device.echo-cancel.name"), z ? z : dest->name);
1264
1265 pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
1266 pa_proplist_free(pl);
1267 }
1268 }
1269
1270 /* Called from main context */
1271 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1272 struct userdata *u;
1273
1274 pa_sink_input_assert_ref(i);
1275 pa_assert_se(u = i->userdata);
1276
1277 if (dest) {
1278 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
1279 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
1280 } else
1281 pa_sink_set_asyncmsgq(u->sink, NULL);
1282
1283 if (u->sink_auto_desc && dest) {
1284 const char *z;
1285 pa_proplist *pl;
1286
1287 pl = pa_proplist_new();
1288 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
1289 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s",
1290 pa_proplist_gets(u->sink->proplist, "device.echo-cancel.name"), z ? z : dest->name);
1291
1292 pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
1293 pa_proplist_free(pl);
1294 }
1295 }
1296
1297 /* Called from main context */
1298 static void sink_input_volume_changed_cb(pa_sink_input *i) {
1299 struct userdata *u;
1300
1301 pa_sink_input_assert_ref(i);
1302 pa_assert_se(u = i->userdata);
1303
1304 pa_sink_volume_changed(u->sink, &i->volume);
1305 }
1306
1307 /* Called from main context */
1308 static void sink_input_mute_changed_cb(pa_sink_input *i) {
1309 struct userdata *u;
1310
1311 pa_sink_input_assert_ref(i);
1312 pa_assert_se(u = i->userdata);
1313
1314 pa_sink_mute_changed(u->sink, i->muted);
1315 }
1316
1317 static pa_echo_canceller_method_t get_ec_method_from_string(const char *method) {
1318 if (pa_streq(method, "speex"))
1319 return PA_ECHO_CANCELLER_SPEEX;
1320 else if (pa_streq(method, "adrian"))
1321 return PA_ECHO_CANCELLER_ADRIAN;
1322 else
1323 return PA_ECHO_CANCELLER_INVALID;
1324 }
1325
1326 /* Common initialisation bits between module-echo-cancel and the standalone test program */
1327 static int init_common(pa_modargs *ma, struct userdata *u, pa_sample_spec *source_ss, pa_channel_map *source_map) {
1328 pa_echo_canceller_method_t ec_method;
1329
1330 if (pa_modargs_get_sample_spec_and_channel_map(ma, source_ss, source_map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1331 pa_log("Invalid sample format specification or channel map");
1332 goto fail;
1333 }
1334
1335 u->ec = pa_xnew0(pa_echo_canceller, 1);
1336 if (!u->ec) {
1337 pa_log("Failed to alloc echo canceller");
1338 goto fail;
1339 }
1340
1341 if ((ec_method = get_ec_method_from_string(pa_modargs_get_value(ma, "aec_method", DEFAULT_ECHO_CANCELLER))) < 0) {
1342 pa_log("Invalid echo canceller implementation");
1343 goto fail;
1344 }
1345
1346 u->ec->init = ec_table[ec_method].init;
1347 u->ec->run = ec_table[ec_method].run;
1348 u->ec->done = ec_table[ec_method].done;
1349
1350 return 0;
1351
1352 fail:
1353 return -1;
1354 }
1355
1356
1357 int pa__init(pa_module*m) {
1358 struct userdata *u;
1359 pa_sample_spec source_ss, sink_ss;
1360 pa_channel_map source_map, sink_map;
1361 pa_modargs *ma;
1362 pa_source *source_master=NULL;
1363 pa_sink *sink_master=NULL;
1364 pa_source_output_new_data source_output_data;
1365 pa_sink_input_new_data sink_input_data;
1366 pa_source_new_data source_data;
1367 pa_sink_new_data sink_data;
1368 pa_memchunk silence;
1369 uint32_t temp;
1370 pa_bool_t use_volume_sharing = TRUE;
1371
1372 pa_assert(m);
1373
1374 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1375 pa_log("Failed to parse module arguments.");
1376 goto fail;
1377 }
1378
1379 if (!(source_master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source_master", NULL), PA_NAMEREG_SOURCE))) {
1380 pa_log("Master source not found");
1381 goto fail;
1382 }
1383 pa_assert(source_master);
1384
1385 if (!(sink_master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) {
1386 pa_log("Master sink not found");
1387 goto fail;
1388 }
1389 pa_assert(sink_master);
1390
1391 if (source_master->monitor_of == sink_master) {
1392 pa_log("Can't cancel echo between a sink and its monitor");
1393 goto fail;
1394 }
1395
1396 source_ss = source_master->sample_spec;
1397 source_ss.rate = DEFAULT_RATE;
1398 source_ss.channels = DEFAULT_CHANNELS;
1399 pa_channel_map_init_auto(&source_map, source_ss.channels, PA_CHANNEL_MAP_DEFAULT);
1400
1401 sink_ss = sink_master->sample_spec;
1402 sink_map = sink_master->channel_map;
1403
1404 if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
1405 pa_log("use_volume_sharing= expects a boolean argument");
1406 goto fail;
1407 }
1408
1409 u = pa_xnew0(struct userdata, 1);
1410 if (!u) {
1411 pa_log("Failed to alloc userdata");
1412 goto fail;
1413 }
1414 u->core = m->core;
1415 u->module = m;
1416 m->userdata = u;
1417 u->dead = FALSE;
1418
1419 temp = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
1420 if (pa_modargs_get_value_u32(ma, "adjust_time", &temp) < 0) {
1421 pa_log("Failed to parse adjust_time value");
1422 goto fail;
1423 }
1424
1425 if (temp != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC)
1426 u->adjust_time = temp * PA_USEC_PER_SEC;
1427 else
1428 u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
1429
1430 temp = DEFAULT_ADJUST_TOLERANCE / PA_USEC_PER_MSEC;
1431 if (pa_modargs_get_value_u32(ma, "adjust_threshold", &temp) < 0) {
1432 pa_log("Failed to parse adjust_threshold value");
1433 goto fail;
1434 }
1435
1436 if (temp != DEFAULT_ADJUST_TOLERANCE / PA_USEC_PER_MSEC)
1437 u->adjust_threshold = temp * PA_USEC_PER_MSEC;
1438 else
1439 u->adjust_threshold = DEFAULT_ADJUST_TOLERANCE;
1440
1441 u->save_aec = DEFAULT_SAVE_AEC;
1442 if (pa_modargs_get_value_boolean(ma, "save_aec", &u->save_aec) < 0) {
1443 pa_log("Failed to parse save_aec value");
1444 goto fail;
1445 }
1446
1447 u->autoloaded = DEFAULT_AUTOLOADED;
1448 if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) {
1449 pa_log("Failed to parse autoloaded value");
1450 goto fail;
1451 }
1452
1453 if (init_common(ma, u, &source_ss, &source_map))
1454 goto fail;
1455
1456 u->asyncmsgq = pa_asyncmsgq_new(0);
1457 u->need_realign = TRUE;
1458
1459 if (u->ec->init) {
1460 if (!u->ec->init(u->core, u->ec, &source_ss, &source_map, &sink_ss, &sink_map, &u->blocksize, pa_modargs_get_value(ma, "aec_args", NULL))) {
1461 pa_log("Failed to init AEC engine");
1462 goto fail;
1463 }
1464 }
1465
1466 /* Create source */
1467 pa_source_new_data_init(&source_data);
1468 source_data.driver = __FILE__;
1469 source_data.module = m;
1470 if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
1471 source_data.name = pa_sprintf_malloc("%s.echo-cancel", source_master->name);
1472 pa_source_new_data_set_sample_spec(&source_data, &source_ss);
1473 pa_source_new_data_set_channel_map(&source_data, &source_map);
1474 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, source_master->name);
1475 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1476 if (!u->autoloaded)
1477 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
1478 pa_proplist_sets(source_data.proplist, "device.echo-cancel.name", source_data.name);
1479
1480 if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
1481 pa_log("Invalid properties");
1482 pa_source_new_data_done(&source_data);
1483 goto fail;
1484 }
1485
1486 if ((u->source_auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
1487 const char *z;
1488
1489 z = pa_proplist_gets(source_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1490 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s", source_data.name, z ? z : source_master->name);
1491 }
1492
1493 u->source = pa_source_new(m->core, &source_data, (source_master->flags & (PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY))
1494 | (use_volume_sharing ? PA_SOURCE_SHARE_VOLUME_WITH_MASTER : 0));
1495 pa_source_new_data_done(&source_data);
1496
1497 if (!u->source) {
1498 pa_log("Failed to create source.");
1499 goto fail;
1500 }
1501
1502 u->source->parent.process_msg = source_process_msg_cb;
1503 u->source->set_state = source_set_state_cb;
1504 u->source->update_requested_latency = source_update_requested_latency_cb;
1505 pa_source_set_get_mute_callback(u->source, source_get_mute_cb);
1506 pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
1507 if (!use_volume_sharing) {
1508 pa_source_set_get_volume_callback(u->source, source_get_volume_cb);
1509 pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
1510 pa_source_enable_decibel_volume(u->source, TRUE);
1511 }
1512 u->source->userdata = u;
1513
1514 pa_source_set_asyncmsgq(u->source, source_master->asyncmsgq);
1515
1516 /* Create sink */
1517 pa_sink_new_data_init(&sink_data);
1518 sink_data.driver = __FILE__;
1519 sink_data.module = m;
1520 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
1521 sink_data.name = pa_sprintf_malloc("%s.echo-cancel", sink_master->name);
1522 pa_sink_new_data_set_sample_spec(&sink_data, &sink_ss);
1523 pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
1524 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, sink_master->name);
1525 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1526 if (!u->autoloaded)
1527 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
1528 pa_proplist_sets(sink_data.proplist, "device.echo-cancel.name", sink_data.name);
1529
1530 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
1531 pa_log("Invalid properties");
1532 pa_sink_new_data_done(&sink_data);
1533 goto fail;
1534 }
1535
1536 if ((u->sink_auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
1537 const char *z;
1538
1539 z = pa_proplist_gets(sink_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1540 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s", sink_data.name, z ? z : sink_master->name);
1541 }
1542
1543 u->sink = pa_sink_new(m->core, &sink_data, (sink_master->flags & (PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY))
1544 | (use_volume_sharing ? PA_SINK_SHARE_VOLUME_WITH_MASTER : 0));
1545 pa_sink_new_data_done(&sink_data);
1546
1547 if (!u->sink) {
1548 pa_log("Failed to create sink.");
1549 goto fail;
1550 }
1551
1552 u->sink->parent.process_msg = sink_process_msg_cb;
1553 u->sink->set_state = sink_set_state_cb;
1554 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1555 u->sink->request_rewind = sink_request_rewind_cb;
1556 pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
1557 if (!use_volume_sharing) {
1558 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
1559 pa_sink_enable_decibel_volume(u->sink, TRUE);
1560 }
1561 u->sink->userdata = u;
1562
1563 pa_sink_set_asyncmsgq(u->sink, sink_master->asyncmsgq);
1564
1565 /* Create source output */
1566 pa_source_output_new_data_init(&source_output_data);
1567 source_output_data.driver = __FILE__;
1568 source_output_data.module = m;
1569 pa_source_output_new_data_set_source(&source_output_data, source_master, FALSE);
1570 source_output_data.destination_source = u->source;
1571 /* FIXME
1572 source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
1573
1574 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Source Stream");
1575 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1576 pa_source_output_new_data_set_sample_spec(&source_output_data, &source_ss);
1577 pa_source_output_new_data_set_channel_map(&source_output_data, &source_map);
1578
1579 pa_source_output_new(&u->source_output, m->core, &source_output_data);
1580 pa_source_output_new_data_done(&source_output_data);
1581
1582 if (!u->source_output)
1583 goto fail;
1584
1585 u->source_output->parent.process_msg = source_output_process_msg_cb;
1586 u->source_output->push = source_output_push_cb;
1587 u->source_output->process_rewind = source_output_process_rewind_cb;
1588 u->source_output->update_max_rewind = source_output_update_max_rewind_cb;
1589 u->source_output->update_source_requested_latency = source_output_update_source_requested_latency_cb;
1590 u->source_output->update_source_latency_range = source_output_update_source_latency_range_cb;
1591 u->source_output->update_source_fixed_latency = source_output_update_source_fixed_latency_cb;
1592 u->source_output->kill = source_output_kill_cb;
1593 u->source_output->attach = source_output_attach_cb;
1594 u->source_output->detach = source_output_detach_cb;
1595 u->source_output->state_change = source_output_state_change_cb;
1596 u->source_output->may_move_to = source_output_may_move_to_cb;
1597 u->source_output->moving = source_output_moving_cb;
1598 u->source_output->userdata = u;
1599
1600 u->source->output_from_master = u->source_output;
1601
1602 /* Create sink input */
1603 pa_sink_input_new_data_init(&sink_input_data);
1604 sink_input_data.driver = __FILE__;
1605 sink_input_data.module = m;
1606 pa_sink_input_new_data_set_sink(&sink_input_data, sink_master, FALSE);
1607 sink_input_data.origin_sink = u->sink;
1608 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Sink Stream");
1609 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1610 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &sink_ss);
1611 pa_sink_input_new_data_set_channel_map(&sink_input_data, &sink_map);
1612 sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
1613
1614 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
1615 pa_sink_input_new_data_done(&sink_input_data);
1616
1617 if (!u->sink_input)
1618 goto fail;
1619
1620 u->sink_input->parent.process_msg = sink_input_process_msg_cb;
1621 u->sink_input->pop = sink_input_pop_cb;
1622 u->sink_input->process_rewind = sink_input_process_rewind_cb;
1623 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1624 u->sink_input->update_max_request = sink_input_update_max_request_cb;
1625 u->sink_input->update_sink_requested_latency = sink_input_update_sink_requested_latency_cb;
1626 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1627 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1628 u->sink_input->kill = sink_input_kill_cb;
1629 u->sink_input->attach = sink_input_attach_cb;
1630 u->sink_input->detach = sink_input_detach_cb;
1631 u->sink_input->state_change = sink_input_state_change_cb;
1632 u->sink_input->may_move_to = sink_input_may_move_to_cb;
1633 u->sink_input->moving = sink_input_moving_cb;
1634 if (!use_volume_sharing)
1635 u->sink_input->volume_changed = sink_input_volume_changed_cb;
1636 u->sink_input->mute_changed = sink_input_mute_changed_cb;
1637 u->sink_input->userdata = u;
1638
1639 u->sink->input_to_master = u->sink_input;
1640
1641 pa_sink_input_get_silence(u->sink_input, &silence);
1642
1643 u->source_memblockq = pa_memblockq_new("module-echo-cancel source_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0,
1644 &source_ss, 1, 1, 0, &silence);
1645 u->sink_memblockq = pa_memblockq_new("module-echo-cancel sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0,
1646 &sink_ss, 1, 1, 0, &silence);
1647
1648 pa_memblock_unref(silence.memblock);
1649
1650 if (!u->source_memblockq || !u->sink_memblockq) {
1651 pa_log("Failed to create memblockq.");
1652 goto fail;
1653 }
1654
1655 /* our source and sink are not suspended when we create them */
1656 u->active_mask = 3;
1657
1658 if (u->adjust_time > 0)
1659 u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
1660
1661 if (u->save_aec) {
1662 pa_log("Creating AEC files in /tmp");
1663 u->captured_file = fopen("/tmp/aec_rec.sw", "wb");
1664 if (u->captured_file == NULL)
1665 perror ("fopen failed");
1666 u->played_file = fopen("/tmp/aec_play.sw", "wb");
1667 if (u->played_file == NULL)
1668 perror ("fopen failed");
1669 u->canceled_file = fopen("/tmp/aec_out.sw", "wb");
1670 if (u->canceled_file == NULL)
1671 perror ("fopen failed");
1672 }
1673
1674 pa_sink_put(u->sink);
1675 pa_source_put(u->source);
1676
1677 pa_sink_input_put(u->sink_input);
1678 pa_source_output_put(u->source_output);
1679
1680 pa_modargs_free(ma);
1681
1682 return 0;
1683
1684 fail:
1685 if (ma)
1686 pa_modargs_free(ma);
1687
1688 pa__done(m);
1689
1690 return -1;
1691 }
1692
1693 int pa__get_n_used(pa_module *m) {
1694 struct userdata *u;
1695
1696 pa_assert(m);
1697 pa_assert_se(u = m->userdata);
1698
1699 return pa_sink_linked_by(u->sink) + pa_source_linked_by(u->source);
1700 }
1701
1702 void pa__done(pa_module*m) {
1703 struct userdata *u;
1704
1705 pa_assert(m);
1706
1707 if (!(u = m->userdata))
1708 return;
1709
1710 u->dead = TRUE;
1711
1712 /* See comments in source_output_kill_cb() above regarding
1713 * destruction order! */
1714
1715 if (u->time_event)
1716 u->core->mainloop->time_free(u->time_event);
1717
1718 if (u->source_output)
1719 pa_source_output_unlink(u->source_output);
1720 if (u->sink_input)
1721 pa_sink_input_unlink(u->sink_input);
1722
1723 if (u->source)
1724 pa_source_unlink(u->source);
1725 if (u->sink)
1726 pa_sink_unlink(u->sink);
1727
1728 if (u->source_output)
1729 pa_source_output_unref(u->source_output);
1730 if (u->sink_input)
1731 pa_sink_input_unref(u->sink_input);
1732
1733 if (u->source)
1734 pa_source_unref(u->source);
1735 if (u->sink)
1736 pa_sink_unref(u->sink);
1737
1738 if (u->source_memblockq)
1739 pa_memblockq_free(u->source_memblockq);
1740 if (u->sink_memblockq)
1741 pa_memblockq_free(u->sink_memblockq);
1742
1743 if (u->ec) {
1744 if (u->ec->done)
1745 u->ec->done(u->ec);
1746
1747 pa_xfree(u->ec);
1748 }
1749
1750 if (u->asyncmsgq)
1751 pa_asyncmsgq_unref(u->asyncmsgq);
1752
1753 pa_xfree(u);
1754 }
1755
1756 #ifdef ECHO_CANCEL_TEST
1757 /*
1758 * Stand-alone test program for running in the canceller on pre-recorded files.
1759 */
1760 int main(int argc, char* argv[]) {
1761 struct userdata u;
1762 pa_sample_spec source_ss, sink_ss;
1763 pa_channel_map source_map, sink_map;
1764 pa_modargs *ma = NULL;
1765 uint8_t *rdata = NULL, *pdata = NULL, *cdata = NULL;
1766 int ret = 0, unused;
1767
1768 pa_memzero(&u, sizeof(u));
1769
1770 if (argc < 4 || argc > 6) {
1771 goto usage;
1772 }
1773
1774 u.ec = pa_xnew0(pa_echo_canceller, 1);
1775 if (!u.ec) {
1776 pa_log("Failed to alloc echo canceller");
1777 goto fail;
1778 }
1779
1780 u.captured_file = fopen(argv[2], "r");
1781 if (u.captured_file == NULL) {
1782 perror ("fopen failed");
1783 goto fail;
1784 }
1785 u.played_file = fopen(argv[1], "r");
1786 if (u.played_file == NULL) {
1787 perror ("fopen failed");
1788 goto fail;
1789 }
1790 u.canceled_file = fopen(argv[3], "wb");
1791 if (u.canceled_file == NULL) {
1792 perror ("fopen failed");
1793 goto fail;
1794 }
1795
1796 u.core = pa_xnew0(pa_core, 1);
1797 u.core->cpu_info.cpu_type = PA_CPU_X86;
1798 u.core->cpu_info.flags.x86 |= PA_CPU_X86_SSE;
1799
1800 if (!(ma = pa_modargs_new(argc > 4 ? argv[4] : NULL, valid_modargs))) {
1801 pa_log("Failed to parse module arguments.");
1802 goto fail;
1803 }
1804
1805 source_ss.format = PA_SAMPLE_S16LE;
1806 source_ss.rate = DEFAULT_RATE;
1807 source_ss.channels = DEFAULT_CHANNELS;
1808 pa_channel_map_init_auto(&source_map, source_ss.channels, PA_CHANNEL_MAP_DEFAULT);
1809
1810 init_common(ma, &u, &source_ss, &source_map);
1811
1812 if (!u.ec->init(u.core, u.ec, &source_ss, &source_map, &sink_ss, &sink_map, &u.blocksize,
1813 (argc > 4) ? argv[5] : NULL )) {
1814 pa_log("Failed to init AEC engine");
1815 goto fail;
1816 }
1817
1818 rdata = pa_xmalloc(u.blocksize);
1819 pdata = pa_xmalloc(u.blocksize);
1820 cdata = pa_xmalloc(u.blocksize);
1821
1822 while (fread(rdata, u.blocksize, 1, u.captured_file) > 0) {
1823 if (fread(pdata, u.blocksize, 1, u.played_file) == 0) {
1824 perror("played file ended before captured file");
1825 break;
1826 }
1827
1828 u.ec->run(u.ec, rdata, pdata, cdata);
1829
1830 unused = fwrite(cdata, u.blocksize, 1, u.canceled_file);
1831 }
1832
1833 u.ec->done(u.ec);
1834
1835 fclose(u.captured_file);
1836 fclose(u.played_file);
1837 fclose(u.canceled_file);
1838
1839 out:
1840 pa_xfree(rdata);
1841 pa_xfree(pdata);
1842 pa_xfree(cdata);
1843
1844 pa_xfree(u.ec);
1845 pa_xfree(u.core);
1846
1847 if (ma)
1848 pa_modargs_free(ma);
1849
1850 return ret;
1851
1852 usage:
1853 pa_log("Usage: %s play_file rec_file out_file [module args] [aec_args]",argv[0]);
1854
1855 fail:
1856 ret = -1;
1857 goto out;
1858 }
1859 #endif /* ECHO_CANCEL_TEST */