]> code.delx.au - pulseaudio/blob - src/modules/echo-cancel/module-echo-cancel.c
echo-cancel: Close debug files on module unload
[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, to_skip;
649 pa_memchunk rchunk, pchunk;
650
651 pa_source_output_assert_ref(o);
652 pa_source_output_assert_io_context(o);
653 pa_assert_se(u = o->userdata);
654
655 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output))) {
656 pa_log("push when no link?");
657 return;
658 }
659
660 if (PA_UNLIKELY(u->source->thread_info.state != PA_SOURCE_RUNNING)) {
661 pa_source_post(u->source, chunk);
662 return;
663 }
664
665 /* handle queued messages, do any message sending of our own */
666 while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
667 ;
668
669 pa_memblockq_push_align(u->source_memblockq, chunk);
670
671 rlen = pa_memblockq_get_length(u->source_memblockq);
672 plen = pa_memblockq_get_length(u->sink_memblockq);
673
674 /* Let's not do anything else till we have enough data to process */
675 if (rlen < u->blocksize)
676 return;
677
678 /* See if we need to drop samples in order to sync */
679 if (pa_atomic_cmpxchg (&u->request_resync, 1, 0)) {
680 do_resync(u);
681 }
682
683 /* Okay, skip cancellation for skipped source samples if needed. */
684 if (PA_UNLIKELY(u->source_skip)) {
685 /* The slightly tricky bit here is that we drop all but modulo
686 * blocksize bytes and then adjust for that last bit on the sink side.
687 * We do this because the source data is coming at a fixed rate, which
688 * means the only way to try to catch up is drop sink samples and let
689 * the canceller cope up with this. */
690 to_skip = rlen >= u->source_skip ? u->source_skip : rlen;
691 to_skip -= to_skip % u->blocksize;
692
693 if (to_skip) {
694 pa_memblockq_peek_fixed_size(u->source_memblockq, to_skip, &rchunk);
695 pa_source_post(u->source, &rchunk);
696
697 pa_memblock_unref(rchunk.memblock);
698 pa_memblockq_drop(u->source_memblockq, u->blocksize);
699
700 rlen -= to_skip;
701 u->source_skip -= to_skip;
702 }
703
704 if (rlen && u->source_skip % u->blocksize) {
705 u->sink_skip += u->blocksize - (u->source_skip % u->blocksize);
706 u->source_skip -= (u->source_skip % u->blocksize);
707 }
708 }
709
710 /* And for the sink, these samples have been played back already, so we can
711 * just drop them and get on with it. */
712 if (PA_UNLIKELY(u->sink_skip)) {
713 to_skip = plen >= u->sink_skip ? u->sink_skip : plen;
714
715 pa_memblockq_drop(u->sink_memblockq, to_skip);
716
717 plen -= to_skip;
718 u->sink_skip -= to_skip;
719 }
720
721 while (rlen >= u->blocksize) {
722 /* take fixed block from recorded samples */
723 pa_memblockq_peek_fixed_size(u->source_memblockq, u->blocksize, &rchunk);
724
725 if (plen > u->blocksize) {
726 uint8_t *rdata, *pdata, *cdata;
727 pa_memchunk cchunk;
728 int unused;
729
730 if (plen > u->blocksize) {
731 /* take fixed block from played samples */
732 pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
733
734 rdata = pa_memblock_acquire(rchunk.memblock);
735 rdata += rchunk.index;
736 pdata = pa_memblock_acquire(pchunk.memblock);
737 pdata += pchunk.index;
738
739 cchunk.index = 0;
740 cchunk.length = u->blocksize;
741 cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
742 cdata = pa_memblock_acquire(cchunk.memblock);
743
744 if (u->save_aec) {
745 if (u->captured_file)
746 unused = fwrite(rdata, 1, u->blocksize, u->captured_file);
747 if (u->played_file)
748 unused = fwrite(pdata, 1, u->blocksize, u->played_file);
749 }
750
751 /* perform echo cancellation */
752 u->ec->run(u->ec, rdata, pdata, cdata);
753
754 if (u->save_aec) {
755 if (u->canceled_file)
756 unused = fwrite(cdata, 1, u->blocksize, u->canceled_file);
757 }
758
759 pa_memblock_release(cchunk.memblock);
760 pa_memblock_release(pchunk.memblock);
761 pa_memblock_release(rchunk.memblock);
762
763 /* drop consumed sink samples */
764 pa_memblockq_drop(u->sink_memblockq, u->blocksize);
765 pa_memblock_unref(pchunk.memblock);
766
767 pa_memblock_unref(rchunk.memblock);
768 /* the filtered samples now become the samples from our
769 * source */
770 rchunk = cchunk;
771
772 plen -= u->blocksize;
773 }
774 }
775
776 /* forward the (echo-canceled) data to the virtual source */
777 pa_source_post(u->source, &rchunk);
778 pa_memblock_unref(rchunk.memblock);
779
780 pa_memblockq_drop(u->source_memblockq, u->blocksize);
781 rlen -= u->blocksize;
782 }
783 }
784
785 /* Called from I/O thread context */
786 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
787 struct userdata *u;
788
789 pa_sink_input_assert_ref(i);
790 pa_assert(chunk);
791 pa_assert_se(u = i->userdata);
792
793 if (u->sink->thread_info.rewind_requested)
794 pa_sink_process_rewind(u->sink, 0);
795
796 pa_sink_render_full(u->sink, nbytes, chunk);
797
798 if (i->thread_info.underrun_for > 0) {
799 pa_log_debug("Handling end of underrun.");
800 pa_atomic_store(&u->request_resync, 1);
801 }
802
803 /* let source thread handle the chunk. pass the sample count as well so that
804 * the source IO thread can update the right variables. */
805 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_POST,
806 NULL, 0, chunk, NULL);
807 u->send_counter += chunk->length;
808
809 return 0;
810 }
811
812 /* Called from input thread context */
813 static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) {
814 struct userdata *u;
815
816 pa_source_output_assert_ref(o);
817 pa_source_output_assert_io_context(o);
818 pa_assert_se(u = o->userdata);
819
820 pa_source_process_rewind(u->source, nbytes);
821
822 /* go back on read side, we need to use older sink data for this */
823 pa_memblockq_rewind(u->sink_memblockq, nbytes);
824
825 /* manipulate write index */
826 pa_memblockq_seek(u->source_memblockq, -nbytes, PA_SEEK_RELATIVE, TRUE);
827
828 pa_log_debug("Source rewind (%lld) %lld", (long long) nbytes,
829 (long long) pa_memblockq_get_length (u->source_memblockq));
830 }
831
832 /* Called from I/O thread context */
833 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
834 struct userdata *u;
835
836 pa_sink_input_assert_ref(i);
837 pa_assert_se(u = i->userdata);
838
839 pa_log_debug("Sink process rewind %lld", (long long) nbytes);
840
841 pa_sink_process_rewind(u->sink, nbytes);
842
843 pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
844 u->send_counter -= nbytes;
845 }
846
847 static void source_output_snapshot_within_thread(struct userdata *u, struct snapshot *snapshot) {
848 size_t delay, rlen, plen;
849 pa_usec_t now, latency;
850
851 now = pa_rtclock_now();
852 latency = pa_source_get_latency_within_thread(u->source_output->source);
853 delay = pa_memblockq_get_length(u->source_output->thread_info.delay_memblockq);
854
855 delay = (u->source_output->thread_info.resampler ? pa_resampler_request(u->source_output->thread_info.resampler, delay) : delay);
856 rlen = pa_memblockq_get_length(u->source_memblockq);
857 plen = pa_memblockq_get_length(u->sink_memblockq);
858
859 snapshot->source_now = now;
860 snapshot->source_latency = latency;
861 snapshot->source_delay = delay;
862 snapshot->recv_counter = u->recv_counter;
863 snapshot->rlen = rlen + u->sink_skip;
864 snapshot->plen = plen + u->source_skip;
865 }
866
867
868 /* Called from output thread context */
869 static int source_output_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
870 struct userdata *u = PA_SOURCE_OUTPUT(obj)->userdata;
871
872 switch (code) {
873
874 case SOURCE_OUTPUT_MESSAGE_POST:
875
876 pa_source_output_assert_io_context(u->source_output);
877
878 if (u->source_output->source->thread_info.state == PA_SOURCE_RUNNING)
879 pa_memblockq_push_align(u->sink_memblockq, chunk);
880 else
881 pa_memblockq_flush_write(u->sink_memblockq, TRUE);
882
883 u->recv_counter += (int64_t) chunk->length;
884
885 return 0;
886
887 case SOURCE_OUTPUT_MESSAGE_REWIND:
888 pa_source_output_assert_io_context(u->source_output);
889
890 /* manipulate write index, never go past what we have */
891 if (PA_SOURCE_IS_OPENED(u->source_output->source->thread_info.state))
892 pa_memblockq_seek(u->sink_memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
893 else
894 pa_memblockq_flush_write(u->sink_memblockq, TRUE);
895
896 pa_log_debug("Sink rewind (%lld)", (long long) offset);
897
898 u->recv_counter -= offset;
899
900 return 0;
901
902 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT: {
903 struct snapshot *snapshot = (struct snapshot *) data;
904
905 source_output_snapshot_within_thread(u, snapshot);
906 return 0;
907 }
908
909 case SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME:
910 apply_diff_time(u, offset);
911 return 0;
912
913 }
914
915 return pa_source_output_process_msg(obj, code, data, offset, chunk);
916 }
917
918 static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
919 struct userdata *u = PA_SINK_INPUT(obj)->userdata;
920
921 switch (code) {
922
923 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT: {
924 size_t delay;
925 pa_usec_t now, latency;
926 struct snapshot *snapshot = (struct snapshot *) data;
927
928 pa_sink_input_assert_io_context(u->sink_input);
929
930 now = pa_rtclock_now();
931 latency = pa_sink_get_latency_within_thread(u->sink_input->sink);
932 delay = pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq);
933
934 delay = (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, delay) : delay);
935
936 snapshot->sink_now = now;
937 snapshot->sink_latency = latency;
938 snapshot->sink_delay = delay;
939 snapshot->send_counter = u->send_counter;
940 return 0;
941 }
942 }
943
944 return pa_sink_input_process_msg(obj, code, data, offset, chunk);
945 }
946
947 /* Called from I/O thread context */
948 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
949 struct userdata *u;
950
951 pa_sink_input_assert_ref(i);
952 pa_assert_se(u = i->userdata);
953
954 pa_log_debug("Sink input update max rewind %lld", (long long) nbytes);
955
956 pa_memblockq_set_maxrewind(u->sink_memblockq, nbytes);
957 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
958 }
959
960 /* Called from I/O thread context */
961 static void source_output_update_max_rewind_cb(pa_source_output *o, size_t nbytes) {
962 struct userdata *u;
963
964 pa_source_output_assert_ref(o);
965 pa_assert_se(u = o->userdata);
966
967 pa_log_debug("Source output update max rewind %lld", (long long) nbytes);
968
969 pa_source_set_max_rewind_within_thread(u->source, nbytes);
970 }
971
972 /* Called from I/O thread context */
973 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
974 struct userdata *u;
975
976 pa_sink_input_assert_ref(i);
977 pa_assert_se(u = i->userdata);
978
979 pa_log_debug("Sink input update max request %lld", (long long) nbytes);
980
981 pa_sink_set_max_request_within_thread(u->sink, nbytes);
982 }
983
984 /* Called from I/O thread context */
985 static void sink_input_update_sink_requested_latency_cb(pa_sink_input *i) {
986 struct userdata *u;
987 pa_usec_t latency;
988
989 pa_sink_input_assert_ref(i);
990 pa_assert_se(u = i->userdata);
991
992 latency = pa_sink_get_requested_latency_within_thread(i->sink);
993
994 pa_log_debug("Sink input update requested latency %lld", (long long) latency);
995 }
996
997 /* Called from I/O thread context */
998 static void source_output_update_source_requested_latency_cb(pa_source_output *o) {
999 struct userdata *u;
1000 pa_usec_t latency;
1001
1002 pa_source_output_assert_ref(o);
1003 pa_assert_se(u = o->userdata);
1004
1005 latency = pa_source_get_requested_latency_within_thread(o->source);
1006
1007 pa_log_debug("source output update requested latency %lld", (long long) latency);
1008 }
1009
1010 /* Called from I/O thread context */
1011 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
1012 struct userdata *u;
1013
1014 pa_sink_input_assert_ref(i);
1015 pa_assert_se(u = i->userdata);
1016
1017 pa_log_debug("Sink input update latency range %lld %lld",
1018 (long long) i->sink->thread_info.min_latency,
1019 (long long) i->sink->thread_info.max_latency);
1020
1021 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1022 }
1023
1024 /* Called from I/O thread context */
1025 static void source_output_update_source_latency_range_cb(pa_source_output *o) {
1026 struct userdata *u;
1027
1028 pa_source_output_assert_ref(o);
1029 pa_assert_se(u = o->userdata);
1030
1031 pa_log_debug("Source output update latency range %lld %lld",
1032 (long long) o->source->thread_info.min_latency,
1033 (long long) o->source->thread_info.max_latency);
1034
1035 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
1036 }
1037
1038 /* Called from I/O thread context */
1039 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
1040 struct userdata *u;
1041
1042 pa_sink_input_assert_ref(i);
1043 pa_assert_se(u = i->userdata);
1044
1045 pa_log_debug("Sink input update fixed latency %lld",
1046 (long long) i->sink->thread_info.fixed_latency);
1047
1048 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
1049 }
1050
1051 /* Called from I/O thread context */
1052 static void source_output_update_source_fixed_latency_cb(pa_source_output *o) {
1053 struct userdata *u;
1054
1055 pa_source_output_assert_ref(o);
1056 pa_assert_se(u = o->userdata);
1057
1058 pa_log_debug("Source output update fixed latency %lld",
1059 (long long) o->source->thread_info.fixed_latency);
1060
1061 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
1062 }
1063
1064 /* Called from output thread context */
1065 static void source_output_attach_cb(pa_source_output *o) {
1066 struct userdata *u;
1067
1068 pa_source_output_assert_ref(o);
1069 pa_source_output_assert_io_context(o);
1070 pa_assert_se(u = o->userdata);
1071
1072 pa_source_set_rtpoll(u->source, o->source->thread_info.rtpoll);
1073 pa_source_set_latency_range_within_thread(u->source, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
1074 pa_source_set_fixed_latency_within_thread(u->source, o->source->thread_info.fixed_latency);
1075 pa_source_set_max_rewind_within_thread(u->source, pa_source_output_get_max_rewind(o));
1076
1077 pa_log_debug("Source output %d attach", o->index);
1078
1079 pa_source_attach_within_thread(u->source);
1080
1081 u->rtpoll_item_read = pa_rtpoll_item_new_asyncmsgq_read(
1082 o->source->thread_info.rtpoll,
1083 PA_RTPOLL_LATE,
1084 u->asyncmsgq);
1085 }
1086
1087 /* Called from I/O thread context */
1088 static void sink_input_attach_cb(pa_sink_input *i) {
1089 struct userdata *u;
1090
1091 pa_sink_input_assert_ref(i);
1092 pa_assert_se(u = i->userdata);
1093
1094 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
1095 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
1096
1097 /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
1098 * BLOCK MINUS ONE SAMPLE HERE. SEE (7) */
1099 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
1100
1101 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
1102 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
1103 * HERE. SEE (6) */
1104 pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
1105 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
1106
1107 pa_log_debug("Sink input %d attach", i->index);
1108
1109 u->rtpoll_item_write = pa_rtpoll_item_new_asyncmsgq_write(
1110 i->sink->thread_info.rtpoll,
1111 PA_RTPOLL_LATE,
1112 u->asyncmsgq);
1113
1114 pa_sink_attach_within_thread(u->sink);
1115 }
1116
1117
1118 /* Called from output thread context */
1119 static void source_output_detach_cb(pa_source_output *o) {
1120 struct userdata *u;
1121
1122 pa_source_output_assert_ref(o);
1123 pa_source_output_assert_io_context(o);
1124 pa_assert_se(u = o->userdata);
1125
1126 pa_source_detach_within_thread(u->source);
1127 pa_source_set_rtpoll(u->source, NULL);
1128
1129 pa_log_debug("Source output %d detach", o->index);
1130
1131 if (u->rtpoll_item_read) {
1132 pa_rtpoll_item_free(u->rtpoll_item_read);
1133 u->rtpoll_item_read = NULL;
1134 }
1135 }
1136
1137 /* Called from I/O thread context */
1138 static void sink_input_detach_cb(pa_sink_input *i) {
1139 struct userdata *u;
1140
1141 pa_sink_input_assert_ref(i);
1142 pa_assert_se(u = i->userdata);
1143
1144 pa_sink_detach_within_thread(u->sink);
1145
1146 pa_sink_set_rtpoll(u->sink, NULL);
1147
1148 pa_log_debug("Sink input %d detach", i->index);
1149
1150 if (u->rtpoll_item_write) {
1151 pa_rtpoll_item_free(u->rtpoll_item_write);
1152 u->rtpoll_item_write = NULL;
1153 }
1154 }
1155
1156 /* Called from output thread context */
1157 static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) {
1158 struct userdata *u;
1159
1160 pa_source_output_assert_ref(o);
1161 pa_source_output_assert_io_context(o);
1162 pa_assert_se(u = o->userdata);
1163
1164 pa_log_debug("Source output %d state %d", o->index, state);
1165 }
1166
1167 /* Called from IO thread context */
1168 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
1169 struct userdata *u;
1170
1171 pa_sink_input_assert_ref(i);
1172 pa_assert_se(u = i->userdata);
1173
1174 pa_log_debug("Sink input %d state %d", i->index, state);
1175
1176 /* If we are added for the first time, ask for a rewinding so that
1177 * we are heard right-away. */
1178 if (PA_SINK_INPUT_IS_LINKED(state) &&
1179 i->thread_info.state == PA_SINK_INPUT_INIT) {
1180 pa_log_debug("Requesting rewind due to state change.");
1181 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
1182 }
1183 }
1184
1185 /* Called from main thread */
1186 static void source_output_kill_cb(pa_source_output *o) {
1187 struct userdata *u;
1188
1189 pa_source_output_assert_ref(o);
1190 pa_assert_ctl_context();
1191 pa_assert_se(u = o->userdata);
1192
1193 u->dead = TRUE;
1194
1195 /* The order here matters! We first kill the source output, followed
1196 * by the source. That means the source callbacks must be protected
1197 * against an unconnected source output! */
1198 pa_source_output_unlink(u->source_output);
1199 pa_source_unlink(u->source);
1200
1201 pa_source_output_unref(u->source_output);
1202 u->source_output = NULL;
1203
1204 pa_source_unref(u->source);
1205 u->source = NULL;
1206
1207 pa_log_debug("Source output kill %d", o->index);
1208
1209 pa_module_unload_request(u->module, TRUE);
1210 }
1211
1212 /* Called from main context */
1213 static void sink_input_kill_cb(pa_sink_input *i) {
1214 struct userdata *u;
1215
1216 pa_sink_input_assert_ref(i);
1217 pa_assert_se(u = i->userdata);
1218
1219 u->dead = TRUE;
1220
1221 /* The order here matters! We first kill the sink input, followed
1222 * by the sink. That means the sink callbacks must be protected
1223 * against an unconnected sink input! */
1224 pa_sink_input_unlink(u->sink_input);
1225 pa_sink_unlink(u->sink);
1226
1227 pa_sink_input_unref(u->sink_input);
1228 u->sink_input = NULL;
1229
1230 pa_sink_unref(u->sink);
1231 u->sink = NULL;
1232
1233 pa_log_debug("Sink input kill %d", i->index);
1234
1235 pa_module_unload_request(u->module, TRUE);
1236 }
1237
1238 /* Called from main thread */
1239 static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) {
1240 struct userdata *u;
1241
1242 pa_source_output_assert_ref(o);
1243 pa_assert_ctl_context();
1244 pa_assert_se(u = o->userdata);
1245
1246 if (u->dead)
1247 return FALSE;
1248
1249 return (u->source != dest) && (u->sink != dest->monitor_of);
1250 }
1251
1252 /* Called from main context */
1253 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
1254 struct userdata *u;
1255
1256 pa_sink_input_assert_ref(i);
1257 pa_assert_se(u = i->userdata);
1258
1259 if (u->dead)
1260 return FALSE;
1261
1262 return u->sink != dest;
1263 }
1264
1265 /* Called from main thread */
1266 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1267 struct userdata *u;
1268
1269 pa_source_output_assert_ref(o);
1270 pa_assert_ctl_context();
1271 pa_assert_se(u = o->userdata);
1272
1273 if (dest) {
1274 pa_source_set_asyncmsgq(u->source, dest->asyncmsgq);
1275 pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags);
1276 } else
1277 pa_source_set_asyncmsgq(u->source, NULL);
1278
1279 if (u->source_auto_desc && dest) {
1280 const char *z;
1281 pa_proplist *pl;
1282
1283 pl = pa_proplist_new();
1284 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
1285 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s",
1286 pa_proplist_gets(u->source->proplist, "device.echo-cancel.name"), z ? z : dest->name);
1287
1288 pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
1289 pa_proplist_free(pl);
1290 }
1291 }
1292
1293 /* Called from main context */
1294 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1295 struct userdata *u;
1296
1297 pa_sink_input_assert_ref(i);
1298 pa_assert_se(u = i->userdata);
1299
1300 if (dest) {
1301 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
1302 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
1303 } else
1304 pa_sink_set_asyncmsgq(u->sink, NULL);
1305
1306 if (u->sink_auto_desc && dest) {
1307 const char *z;
1308 pa_proplist *pl;
1309
1310 pl = pa_proplist_new();
1311 z = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
1312 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s",
1313 pa_proplist_gets(u->sink->proplist, "device.echo-cancel.name"), z ? z : dest->name);
1314
1315 pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
1316 pa_proplist_free(pl);
1317 }
1318 }
1319
1320 /* Called from main context */
1321 static void sink_input_volume_changed_cb(pa_sink_input *i) {
1322 struct userdata *u;
1323
1324 pa_sink_input_assert_ref(i);
1325 pa_assert_se(u = i->userdata);
1326
1327 pa_sink_volume_changed(u->sink, &i->volume);
1328 }
1329
1330 /* Called from main context */
1331 static void sink_input_mute_changed_cb(pa_sink_input *i) {
1332 struct userdata *u;
1333
1334 pa_sink_input_assert_ref(i);
1335 pa_assert_se(u = i->userdata);
1336
1337 pa_sink_mute_changed(u->sink, i->muted);
1338 }
1339
1340 static pa_echo_canceller_method_t get_ec_method_from_string(const char *method) {
1341 if (pa_streq(method, "speex"))
1342 return PA_ECHO_CANCELLER_SPEEX;
1343 else if (pa_streq(method, "adrian"))
1344 return PA_ECHO_CANCELLER_ADRIAN;
1345 else
1346 return PA_ECHO_CANCELLER_INVALID;
1347 }
1348
1349 /* Common initialisation bits between module-echo-cancel and the standalone test program */
1350 static int init_common(pa_modargs *ma, struct userdata *u, pa_sample_spec *source_ss, pa_channel_map *source_map) {
1351 pa_echo_canceller_method_t ec_method;
1352
1353 if (pa_modargs_get_sample_spec_and_channel_map(ma, source_ss, source_map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1354 pa_log("Invalid sample format specification or channel map");
1355 goto fail;
1356 }
1357
1358 u->ec = pa_xnew0(pa_echo_canceller, 1);
1359 if (!u->ec) {
1360 pa_log("Failed to alloc echo canceller");
1361 goto fail;
1362 }
1363
1364 if ((ec_method = get_ec_method_from_string(pa_modargs_get_value(ma, "aec_method", DEFAULT_ECHO_CANCELLER))) < 0) {
1365 pa_log("Invalid echo canceller implementation");
1366 goto fail;
1367 }
1368
1369 u->ec->init = ec_table[ec_method].init;
1370 u->ec->run = ec_table[ec_method].run;
1371 u->ec->done = ec_table[ec_method].done;
1372
1373 return 0;
1374
1375 fail:
1376 return -1;
1377 }
1378
1379
1380 int pa__init(pa_module*m) {
1381 struct userdata *u;
1382 pa_sample_spec source_ss, sink_ss;
1383 pa_channel_map source_map, sink_map;
1384 pa_modargs *ma;
1385 pa_source *source_master=NULL;
1386 pa_sink *sink_master=NULL;
1387 pa_source_output_new_data source_output_data;
1388 pa_sink_input_new_data sink_input_data;
1389 pa_source_new_data source_data;
1390 pa_sink_new_data sink_data;
1391 pa_memchunk silence;
1392 uint32_t temp;
1393 pa_bool_t use_volume_sharing = TRUE;
1394
1395 pa_assert(m);
1396
1397 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1398 pa_log("Failed to parse module arguments.");
1399 goto fail;
1400 }
1401
1402 if (!(source_master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source_master", NULL), PA_NAMEREG_SOURCE))) {
1403 pa_log("Master source not found");
1404 goto fail;
1405 }
1406 pa_assert(source_master);
1407
1408 if (!(sink_master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) {
1409 pa_log("Master sink not found");
1410 goto fail;
1411 }
1412 pa_assert(sink_master);
1413
1414 if (source_master->monitor_of == sink_master) {
1415 pa_log("Can't cancel echo between a sink and its monitor");
1416 goto fail;
1417 }
1418
1419 source_ss = source_master->sample_spec;
1420 source_ss.rate = DEFAULT_RATE;
1421 source_ss.channels = DEFAULT_CHANNELS;
1422 pa_channel_map_init_auto(&source_map, source_ss.channels, PA_CHANNEL_MAP_DEFAULT);
1423
1424 sink_ss = sink_master->sample_spec;
1425 sink_map = sink_master->channel_map;
1426
1427 if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
1428 pa_log("use_volume_sharing= expects a boolean argument");
1429 goto fail;
1430 }
1431
1432 u = pa_xnew0(struct userdata, 1);
1433 if (!u) {
1434 pa_log("Failed to alloc userdata");
1435 goto fail;
1436 }
1437 u->core = m->core;
1438 u->module = m;
1439 m->userdata = u;
1440 u->dead = FALSE;
1441
1442 temp = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
1443 if (pa_modargs_get_value_u32(ma, "adjust_time", &temp) < 0) {
1444 pa_log("Failed to parse adjust_time value");
1445 goto fail;
1446 }
1447
1448 if (temp != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC)
1449 u->adjust_time = temp * PA_USEC_PER_SEC;
1450 else
1451 u->adjust_time = DEFAULT_ADJUST_TIME_USEC;
1452
1453 temp = DEFAULT_ADJUST_TOLERANCE / PA_USEC_PER_MSEC;
1454 if (pa_modargs_get_value_u32(ma, "adjust_threshold", &temp) < 0) {
1455 pa_log("Failed to parse adjust_threshold value");
1456 goto fail;
1457 }
1458
1459 if (temp != DEFAULT_ADJUST_TOLERANCE / PA_USEC_PER_MSEC)
1460 u->adjust_threshold = temp * PA_USEC_PER_MSEC;
1461 else
1462 u->adjust_threshold = DEFAULT_ADJUST_TOLERANCE;
1463
1464 u->save_aec = DEFAULT_SAVE_AEC;
1465 if (pa_modargs_get_value_boolean(ma, "save_aec", &u->save_aec) < 0) {
1466 pa_log("Failed to parse save_aec value");
1467 goto fail;
1468 }
1469
1470 u->autoloaded = DEFAULT_AUTOLOADED;
1471 if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) {
1472 pa_log("Failed to parse autoloaded value");
1473 goto fail;
1474 }
1475
1476 if (init_common(ma, u, &source_ss, &source_map))
1477 goto fail;
1478
1479 u->asyncmsgq = pa_asyncmsgq_new(0);
1480 u->need_realign = TRUE;
1481
1482 if (u->ec->init) {
1483 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))) {
1484 pa_log("Failed to init AEC engine");
1485 goto fail;
1486 }
1487 }
1488
1489 /* Create source */
1490 pa_source_new_data_init(&source_data);
1491 source_data.driver = __FILE__;
1492 source_data.module = m;
1493 if (!(source_data.name = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
1494 source_data.name = pa_sprintf_malloc("%s.echo-cancel", source_master->name);
1495 pa_source_new_data_set_sample_spec(&source_data, &source_ss);
1496 pa_source_new_data_set_channel_map(&source_data, &source_map);
1497 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, source_master->name);
1498 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1499 if (!u->autoloaded)
1500 pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
1501 pa_proplist_sets(source_data.proplist, "device.echo-cancel.name", source_data.name);
1502
1503 if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
1504 pa_log("Invalid properties");
1505 pa_source_new_data_done(&source_data);
1506 goto fail;
1507 }
1508
1509 if ((u->source_auto_desc = !pa_proplist_contains(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
1510 const char *z;
1511
1512 z = pa_proplist_gets(source_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1513 pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Source %s on %s", source_data.name, z ? z : source_master->name);
1514 }
1515
1516 u->source = pa_source_new(m->core, &source_data, (source_master->flags & (PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY))
1517 | (use_volume_sharing ? PA_SOURCE_SHARE_VOLUME_WITH_MASTER : 0));
1518 pa_source_new_data_done(&source_data);
1519
1520 if (!u->source) {
1521 pa_log("Failed to create source.");
1522 goto fail;
1523 }
1524
1525 u->source->parent.process_msg = source_process_msg_cb;
1526 u->source->set_state = source_set_state_cb;
1527 u->source->update_requested_latency = source_update_requested_latency_cb;
1528 pa_source_set_get_mute_callback(u->source, source_get_mute_cb);
1529 pa_source_set_set_mute_callback(u->source, source_set_mute_cb);
1530 if (!use_volume_sharing) {
1531 pa_source_set_get_volume_callback(u->source, source_get_volume_cb);
1532 pa_source_set_set_volume_callback(u->source, source_set_volume_cb);
1533 pa_source_enable_decibel_volume(u->source, TRUE);
1534 }
1535 u->source->userdata = u;
1536
1537 pa_source_set_asyncmsgq(u->source, source_master->asyncmsgq);
1538
1539 /* Create sink */
1540 pa_sink_new_data_init(&sink_data);
1541 sink_data.driver = __FILE__;
1542 sink_data.module = m;
1543 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
1544 sink_data.name = pa_sprintf_malloc("%s.echo-cancel", sink_master->name);
1545 pa_sink_new_data_set_sample_spec(&sink_data, &sink_ss);
1546 pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
1547 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, sink_master->name);
1548 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1549 if (!u->autoloaded)
1550 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone");
1551 pa_proplist_sets(sink_data.proplist, "device.echo-cancel.name", sink_data.name);
1552
1553 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
1554 pa_log("Invalid properties");
1555 pa_sink_new_data_done(&sink_data);
1556 goto fail;
1557 }
1558
1559 if ((u->sink_auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
1560 const char *z;
1561
1562 z = pa_proplist_gets(sink_master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1563 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Echo-Cancel Sink %s on %s", sink_data.name, z ? z : sink_master->name);
1564 }
1565
1566 u->sink = pa_sink_new(m->core, &sink_data, (sink_master->flags & (PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY))
1567 | (use_volume_sharing ? PA_SINK_SHARE_VOLUME_WITH_MASTER : 0));
1568 pa_sink_new_data_done(&sink_data);
1569
1570 if (!u->sink) {
1571 pa_log("Failed to create sink.");
1572 goto fail;
1573 }
1574
1575 u->sink->parent.process_msg = sink_process_msg_cb;
1576 u->sink->set_state = sink_set_state_cb;
1577 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1578 u->sink->request_rewind = sink_request_rewind_cb;
1579 pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
1580 if (!use_volume_sharing) {
1581 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
1582 pa_sink_enable_decibel_volume(u->sink, TRUE);
1583 }
1584 u->sink->userdata = u;
1585
1586 pa_sink_set_asyncmsgq(u->sink, sink_master->asyncmsgq);
1587
1588 /* Create source output */
1589 pa_source_output_new_data_init(&source_output_data);
1590 source_output_data.driver = __FILE__;
1591 source_output_data.module = m;
1592 pa_source_output_new_data_set_source(&source_output_data, source_master, FALSE);
1593 source_output_data.destination_source = u->source;
1594 /* FIXME
1595 source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
1596
1597 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Source Stream");
1598 pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1599 pa_source_output_new_data_set_sample_spec(&source_output_data, &source_ss);
1600 pa_source_output_new_data_set_channel_map(&source_output_data, &source_map);
1601
1602 pa_source_output_new(&u->source_output, m->core, &source_output_data);
1603 pa_source_output_new_data_done(&source_output_data);
1604
1605 if (!u->source_output)
1606 goto fail;
1607
1608 u->source_output->parent.process_msg = source_output_process_msg_cb;
1609 u->source_output->push = source_output_push_cb;
1610 u->source_output->process_rewind = source_output_process_rewind_cb;
1611 u->source_output->update_max_rewind = source_output_update_max_rewind_cb;
1612 u->source_output->update_source_requested_latency = source_output_update_source_requested_latency_cb;
1613 u->source_output->update_source_latency_range = source_output_update_source_latency_range_cb;
1614 u->source_output->update_source_fixed_latency = source_output_update_source_fixed_latency_cb;
1615 u->source_output->kill = source_output_kill_cb;
1616 u->source_output->attach = source_output_attach_cb;
1617 u->source_output->detach = source_output_detach_cb;
1618 u->source_output->state_change = source_output_state_change_cb;
1619 u->source_output->may_move_to = source_output_may_move_to_cb;
1620 u->source_output->moving = source_output_moving_cb;
1621 u->source_output->userdata = u;
1622
1623 u->source->output_from_master = u->source_output;
1624
1625 /* Create sink input */
1626 pa_sink_input_new_data_init(&sink_input_data);
1627 sink_input_data.driver = __FILE__;
1628 sink_input_data.module = m;
1629 pa_sink_input_new_data_set_sink(&sink_input_data, sink_master, FALSE);
1630 sink_input_data.origin_sink = u->sink;
1631 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Sink Stream");
1632 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1633 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &sink_ss);
1634 pa_sink_input_new_data_set_channel_map(&sink_input_data, &sink_map);
1635 sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
1636
1637 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
1638 pa_sink_input_new_data_done(&sink_input_data);
1639
1640 if (!u->sink_input)
1641 goto fail;
1642
1643 u->sink_input->parent.process_msg = sink_input_process_msg_cb;
1644 u->sink_input->pop = sink_input_pop_cb;
1645 u->sink_input->process_rewind = sink_input_process_rewind_cb;
1646 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1647 u->sink_input->update_max_request = sink_input_update_max_request_cb;
1648 u->sink_input->update_sink_requested_latency = sink_input_update_sink_requested_latency_cb;
1649 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1650 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1651 u->sink_input->kill = sink_input_kill_cb;
1652 u->sink_input->attach = sink_input_attach_cb;
1653 u->sink_input->detach = sink_input_detach_cb;
1654 u->sink_input->state_change = sink_input_state_change_cb;
1655 u->sink_input->may_move_to = sink_input_may_move_to_cb;
1656 u->sink_input->moving = sink_input_moving_cb;
1657 if (!use_volume_sharing)
1658 u->sink_input->volume_changed = sink_input_volume_changed_cb;
1659 u->sink_input->mute_changed = sink_input_mute_changed_cb;
1660 u->sink_input->userdata = u;
1661
1662 u->sink->input_to_master = u->sink_input;
1663
1664 pa_sink_input_get_silence(u->sink_input, &silence);
1665
1666 u->source_memblockq = pa_memblockq_new("module-echo-cancel source_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0,
1667 &source_ss, 1, 1, 0, &silence);
1668 u->sink_memblockq = pa_memblockq_new("module-echo-cancel sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH, 0,
1669 &sink_ss, 1, 1, 0, &silence);
1670
1671 pa_memblock_unref(silence.memblock);
1672
1673 if (!u->source_memblockq || !u->sink_memblockq) {
1674 pa_log("Failed to create memblockq.");
1675 goto fail;
1676 }
1677
1678 /* our source and sink are not suspended when we create them */
1679 u->active_mask = 3;
1680
1681 if (u->adjust_time > 0)
1682 u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
1683
1684 if (u->save_aec) {
1685 pa_log("Creating AEC files in /tmp");
1686 u->captured_file = fopen("/tmp/aec_rec.sw", "wb");
1687 if (u->captured_file == NULL)
1688 perror ("fopen failed");
1689 u->played_file = fopen("/tmp/aec_play.sw", "wb");
1690 if (u->played_file == NULL)
1691 perror ("fopen failed");
1692 u->canceled_file = fopen("/tmp/aec_out.sw", "wb");
1693 if (u->canceled_file == NULL)
1694 perror ("fopen failed");
1695 }
1696
1697 pa_sink_put(u->sink);
1698 pa_source_put(u->source);
1699
1700 pa_sink_input_put(u->sink_input);
1701 pa_source_output_put(u->source_output);
1702
1703 pa_modargs_free(ma);
1704
1705 return 0;
1706
1707 fail:
1708 if (ma)
1709 pa_modargs_free(ma);
1710
1711 pa__done(m);
1712
1713 return -1;
1714 }
1715
1716 int pa__get_n_used(pa_module *m) {
1717 struct userdata *u;
1718
1719 pa_assert(m);
1720 pa_assert_se(u = m->userdata);
1721
1722 return pa_sink_linked_by(u->sink) + pa_source_linked_by(u->source);
1723 }
1724
1725 void pa__done(pa_module*m) {
1726 struct userdata *u;
1727
1728 pa_assert(m);
1729
1730 if (!(u = m->userdata))
1731 return;
1732
1733 u->dead = TRUE;
1734
1735 /* See comments in source_output_kill_cb() above regarding
1736 * destruction order! */
1737
1738 if (u->time_event)
1739 u->core->mainloop->time_free(u->time_event);
1740
1741 if (u->source_output)
1742 pa_source_output_unlink(u->source_output);
1743 if (u->sink_input)
1744 pa_sink_input_unlink(u->sink_input);
1745
1746 if (u->source)
1747 pa_source_unlink(u->source);
1748 if (u->sink)
1749 pa_sink_unlink(u->sink);
1750
1751 if (u->source_output)
1752 pa_source_output_unref(u->source_output);
1753 if (u->sink_input)
1754 pa_sink_input_unref(u->sink_input);
1755
1756 if (u->source)
1757 pa_source_unref(u->source);
1758 if (u->sink)
1759 pa_sink_unref(u->sink);
1760
1761 if (u->source_memblockq)
1762 pa_memblockq_free(u->source_memblockq);
1763 if (u->sink_memblockq)
1764 pa_memblockq_free(u->sink_memblockq);
1765
1766 if (u->ec) {
1767 if (u->ec->done)
1768 u->ec->done(u->ec);
1769
1770 pa_xfree(u->ec);
1771 }
1772
1773 if (u->asyncmsgq)
1774 pa_asyncmsgq_unref(u->asyncmsgq);
1775
1776 if (u->save_aec) {
1777 if (u->played_file)
1778 fclose(u->played_file);
1779 if (u->captured_file)
1780 fclose(u->captured_file);
1781 if (u->canceled_file)
1782 fclose(u->canceled_file);
1783 }
1784
1785 pa_xfree(u);
1786 }
1787
1788 #ifdef ECHO_CANCEL_TEST
1789 /*
1790 * Stand-alone test program for running in the canceller on pre-recorded files.
1791 */
1792 int main(int argc, char* argv[]) {
1793 struct userdata u;
1794 pa_sample_spec source_ss, sink_ss;
1795 pa_channel_map source_map, sink_map;
1796 pa_modargs *ma = NULL;
1797 uint8_t *rdata = NULL, *pdata = NULL, *cdata = NULL;
1798 int ret = 0, unused;
1799
1800 pa_memzero(&u, sizeof(u));
1801
1802 if (argc < 4 || argc > 6) {
1803 goto usage;
1804 }
1805
1806 u.ec = pa_xnew0(pa_echo_canceller, 1);
1807 if (!u.ec) {
1808 pa_log("Failed to alloc echo canceller");
1809 goto fail;
1810 }
1811
1812 u.captured_file = fopen(argv[2], "r");
1813 if (u.captured_file == NULL) {
1814 perror ("fopen failed");
1815 goto fail;
1816 }
1817 u.played_file = fopen(argv[1], "r");
1818 if (u.played_file == NULL) {
1819 perror ("fopen failed");
1820 goto fail;
1821 }
1822 u.canceled_file = fopen(argv[3], "wb");
1823 if (u.canceled_file == NULL) {
1824 perror ("fopen failed");
1825 goto fail;
1826 }
1827
1828 u.core = pa_xnew0(pa_core, 1);
1829 u.core->cpu_info.cpu_type = PA_CPU_X86;
1830 u.core->cpu_info.flags.x86 |= PA_CPU_X86_SSE;
1831
1832 if (!(ma = pa_modargs_new(argc > 4 ? argv[4] : NULL, valid_modargs))) {
1833 pa_log("Failed to parse module arguments.");
1834 goto fail;
1835 }
1836
1837 source_ss.format = PA_SAMPLE_S16LE;
1838 source_ss.rate = DEFAULT_RATE;
1839 source_ss.channels = DEFAULT_CHANNELS;
1840 pa_channel_map_init_auto(&source_map, source_ss.channels, PA_CHANNEL_MAP_DEFAULT);
1841
1842 init_common(ma, &u, &source_ss, &source_map);
1843
1844 if (!u.ec->init(u.core, u.ec, &source_ss, &source_map, &sink_ss, &sink_map, &u.blocksize,
1845 (argc > 4) ? argv[5] : NULL )) {
1846 pa_log("Failed to init AEC engine");
1847 goto fail;
1848 }
1849
1850 rdata = pa_xmalloc(u.blocksize);
1851 pdata = pa_xmalloc(u.blocksize);
1852 cdata = pa_xmalloc(u.blocksize);
1853
1854 while (fread(rdata, u.blocksize, 1, u.captured_file) > 0) {
1855 if (fread(pdata, u.blocksize, 1, u.played_file) == 0) {
1856 perror("played file ended before captured file");
1857 break;
1858 }
1859
1860 u.ec->run(u.ec, rdata, pdata, cdata);
1861
1862 unused = fwrite(cdata, u.blocksize, 1, u.canceled_file);
1863 }
1864
1865 u.ec->done(u.ec);
1866
1867 fclose(u.captured_file);
1868 fclose(u.played_file);
1869 fclose(u.canceled_file);
1870
1871 out:
1872 pa_xfree(rdata);
1873 pa_xfree(pdata);
1874 pa_xfree(cdata);
1875
1876 pa_xfree(u.ec);
1877 pa_xfree(u.core);
1878
1879 if (ma)
1880 pa_modargs_free(ma);
1881
1882 return ret;
1883
1884 usage:
1885 pa_log("Usage: %s play_file rec_file out_file [module args] [aec_args]",argv[0]);
1886
1887 fail:
1888 ret = -1;
1889 goto out;
1890 }
1891 #endif /* ECHO_CANCEL_TEST */