2 This file is part of PulseAudio.
4 Copyright 2010 Wim Taymans <wim.taymans@gmail.com>
6 Based on module-virtual-sink.c
7 module-virtual-source.c
10 Copyright 2010 Intel Corporation
11 Contributor: Pierre-Louis Bossart <pierre-louis.bossart@intel.com>
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.
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.
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
36 #include "echo-cancel.h"
38 #include <pulse/xmalloc.h>
39 #include <pulse/timeval.h>
40 #include <pulse/rtclock.h>
42 #include <pulsecore/i18n.h>
43 #include <pulsecore/atomic.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/namereg.h>
46 #include <pulsecore/sink.h>
47 #include <pulsecore/module.h>
48 #include <pulsecore/core-rtclock.h>
49 #include <pulsecore/core-util.h>
50 #include <pulsecore/modargs.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/rtpoll.h>
53 #include <pulsecore/sample-util.h>
54 #include <pulsecore/ltdl-helper.h>
56 #include "module-echo-cancel-symdef.h"
58 PA_MODULE_AUTHOR("Wim Taymans");
59 PA_MODULE_DESCRIPTION("Echo Cancellation");
60 PA_MODULE_VERSION(PACKAGE_VERSION
);
61 PA_MODULE_LOAD_ONCE(FALSE
);
63 _("source_name=<name for the source> "
64 "source_properties=<properties for the source> "
65 "source_master=<name of source to filter> "
66 "sink_name=<name for the sink> "
67 "sink_properties=<properties for the sink> "
68 "sink_master=<name of sink to filter> "
69 "adjust_time=<how often to readjust rates in s> "
70 "adjust_threshold=<how much drift to readjust after in ms> "
71 "format=<sample format> "
73 "channels=<number of channels> "
74 "channel_map=<channel map> "
75 "aec_method=<implementation to use> "
76 "aec_args=<parameters for the AEC engine> "
77 "save_aec=<save AEC data in /tmp> "
78 "autoloaded=<set if this module is being loaded automatically> "
79 "use_volume_sharing=<yes or no> "
82 /* NOTE: Make sure the enum and ec_table are maintained in the correct order */
84 PA_ECHO_CANCELLER_INVALID
= -1,
86 PA_ECHO_CANCELLER_SPEEX
,
89 PA_ECHO_CANCELLER_ADRIAN
,
92 PA_ECHO_CANCELLER_WEBRTC
,
94 } pa_echo_canceller_method_t
;
97 #define DEFAULT_ECHO_CANCELLER "webrtc"
99 #define DEFAULT_ECHO_CANCELLER "speex"
102 static const pa_echo_canceller ec_table
[] = {
106 .init
= pa_speex_ec_init
,
107 .run
= pa_speex_ec_run
,
108 .done
= pa_speex_ec_done
,
111 #ifdef HAVE_ADRIAN_EC
113 /* Adrian Andre's NLMS implementation */
114 .init
= pa_adrian_ec_init
,
115 .run
= pa_adrian_ec_run
,
116 .done
= pa_adrian_ec_done
,
121 /* WebRTC's audio processing engine */
122 .init
= pa_webrtc_ec_init
,
123 .play
= pa_webrtc_ec_play
,
124 .record
= pa_webrtc_ec_record
,
125 .set_drift
= pa_webrtc_ec_set_drift
,
126 .run
= pa_webrtc_ec_run
,
127 .done
= pa_webrtc_ec_done
,
132 #define DEFAULT_RATE 32000
133 #define DEFAULT_CHANNELS 1
134 #define DEFAULT_ADJUST_TIME_USEC (1*PA_USEC_PER_SEC)
135 #define DEFAULT_ADJUST_TOLERANCE (5*PA_USEC_PER_MSEC)
136 #define DEFAULT_SAVE_AEC FALSE
137 #define DEFAULT_AUTOLOADED FALSE
139 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
141 /* Can only be used in main context */
142 #define IS_ACTIVE(u) ((pa_source_get_state((u)->source) == PA_SOURCE_RUNNING) && \
143 (pa_sink_get_state((u)->sink) == PA_SINK_RUNNING))
145 /* This module creates a new (virtual) source and sink.
147 * The data sent to the new sink is kept in a memblockq before being
148 * forwarded to the real sink_master.
150 * Data read from source_master is matched against the saved sink data and
151 * echo canceled data is then pushed onto the new source.
153 * Both source and sink masters have their own threads to push/pull data
154 * respectively. We however perform all our actions in the source IO thread.
155 * To do this we send all played samples to the source IO thread where they
156 * are then pushed into the memblockq.
158 * Alignment is performed in two steps:
160 * 1) when something happens that requires quick adjustment of the alignment of
161 * capture and playback samples, we perform a resync. This adjusts the
162 * position in the playback memblock to the requested sample. Quick
163 * adjustments include moving the playback samples before the capture
164 * samples (because else the echo canceler does not work) or when the
165 * playback pointer drifts too far away.
167 * 2) periodically check the difference between capture and playback. We use a
168 * low and high watermark for adjusting the alignment. Playback should always
169 * be before capture and the difference should not be bigger than one frame
170 * size. We would ideally like to resample the sink_input but most driver
171 * don't give enough accuracy to be able to do that right now.
176 struct pa_echo_canceller_msg
{
178 struct userdata
*userdata
;
181 PA_DEFINE_PRIVATE_CLASS(pa_echo_canceller_msg
, pa_msgobject
);
182 #define PA_ECHO_CANCELLER_MSG(o) (pa_echo_canceller_msg_cast(o))
186 pa_usec_t sink_latency
;
188 int64_t send_counter
;
190 pa_usec_t source_now
;
191 pa_usec_t source_latency
;
193 int64_t recv_counter
;
202 pa_bool_t autoloaded
;
206 pa_echo_canceller
*ec
;
209 pa_bool_t need_realign
;
211 /* to wakeup the source I/O thread */
212 pa_asyncmsgq
*asyncmsgq
;
213 pa_rtpoll_item
*rtpoll_item_read
, *rtpoll_item_write
;
216 pa_bool_t source_auto_desc
;
217 pa_source_output
*source_output
;
218 pa_memblockq
*source_memblockq
; /* echo canceler needs fixed sized chunks */
222 pa_bool_t sink_auto_desc
;
223 pa_sink_input
*sink_input
;
224 pa_memblockq
*sink_memblockq
;
225 int64_t send_counter
; /* updated in sink IO thread */
226 int64_t recv_counter
;
229 /* Bytes left over from previous iteration */
233 pa_atomic_t request_resync
;
235 pa_time_event
*time_event
;
236 pa_usec_t adjust_time
;
237 int adjust_threshold
;
244 pa_bool_t use_volume_sharing
;
247 pa_cvolume current_volume
;
251 static void source_output_snapshot_within_thread(struct userdata
*u
, struct snapshot
*snapshot
);
253 static const char* const valid_modargs
[] = {
270 "use_volume_sharing",
275 SOURCE_OUTPUT_MESSAGE_POST
= PA_SOURCE_OUTPUT_MESSAGE_MAX
,
276 SOURCE_OUTPUT_MESSAGE_REWIND
,
277 SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
,
278 SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME
282 SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
286 ECHO_CANCELLER_MESSAGE_SET_VOLUME
,
289 static int64_t calc_diff(struct userdata
*u
, struct snapshot
*snapshot
) {
290 int64_t buffer
, diff_time
, buffer_latency
;
292 /* get the number of samples between capture and playback */
293 if (snapshot
->plen
> snapshot
->rlen
)
294 buffer
= snapshot
->plen
- snapshot
->rlen
;
298 buffer
+= snapshot
->source_delay
+ snapshot
->sink_delay
;
300 /* add the amount of samples not yet transferred to the source context */
301 if (snapshot
->recv_counter
<= snapshot
->send_counter
)
302 buffer
+= (int64_t) (snapshot
->send_counter
- snapshot
->recv_counter
);
304 buffer
+= PA_CLIP_SUB(buffer
, (int64_t) (snapshot
->recv_counter
- snapshot
->send_counter
));
306 /* convert to time */
307 buffer_latency
= pa_bytes_to_usec(buffer
, &u
->source_output
->sample_spec
);
309 /* capture and playback samples are perfectly aligned when diff_time is 0 */
310 diff_time
= (snapshot
->sink_now
+ snapshot
->sink_latency
- buffer_latency
) -
311 (snapshot
->source_now
- snapshot
->source_latency
);
313 pa_log_debug("Diff %lld (%lld - %lld + %lld) %lld %lld %lld %lld", (long long) diff_time
,
314 (long long) snapshot
->sink_latency
,
315 (long long) buffer_latency
, (long long) snapshot
->source_latency
,
316 (long long) snapshot
->source_delay
, (long long) snapshot
->sink_delay
,
317 (long long) (snapshot
->send_counter
- snapshot
->recv_counter
),
318 (long long) (snapshot
->sink_now
- snapshot
->source_now
));
323 /* Called from main context */
324 static void time_callback(pa_mainloop_api
*a
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
325 struct userdata
*u
= userdata
;
326 uint32_t old_rate
, base_rate
, new_rate
;
329 struct snapshot latency_snapshot
;
333 pa_assert(u
->time_event
== e
);
334 pa_assert_ctl_context();
339 /* update our snapshots */
340 pa_asyncmsgq_send(u
->source_output
->source
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
, &latency_snapshot
, 0, NULL
);
341 pa_asyncmsgq_send(u
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
, &latency_snapshot
, 0, NULL
);
343 /* calculate drift between capture and playback */
344 diff_time
= calc_diff(u
, &latency_snapshot
);
346 /*fs = pa_frame_size(&u->source_output->sample_spec);*/
347 old_rate
= u
->sink_input
->sample_spec
.rate
;
348 base_rate
= u
->source_output
->sample_spec
.rate
;
351 /* recording before playback, we need to adjust quickly. The echo
352 * canceler does not work in this case. */
353 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME
,
354 NULL
, diff_time
, NULL
, NULL
);
355 /*new_rate = base_rate - ((pa_usec_to_bytes(-diff_time, &u->source_output->sample_spec) / fs) * PA_USEC_PER_SEC) / u->adjust_time;*/
356 new_rate
= base_rate
;
359 if (diff_time
> u
->adjust_threshold
) {
360 /* diff too big, quickly adjust */
361 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME
,
362 NULL
, diff_time
, NULL
, NULL
);
365 /* recording behind playback, we need to slowly adjust the rate to match */
366 /*new_rate = base_rate + ((pa_usec_to_bytes(diff_time, &u->source_output->sample_spec) / fs) * PA_USEC_PER_SEC) / u->adjust_time;*/
368 /* assume equal samplerates for now */
369 new_rate
= base_rate
;
372 /* make sure we don't make too big adjustments because that sounds horrible */
373 if (new_rate
> base_rate
* 1.1 || new_rate
< base_rate
* 0.9)
374 new_rate
= base_rate
;
376 if (new_rate
!= old_rate
) {
377 pa_log_info("Old rate %lu Hz, new rate %lu Hz", (unsigned long) old_rate
, (unsigned long) new_rate
);
379 pa_sink_input_set_rate(u
->sink_input
, new_rate
);
382 pa_core_rttime_restart(u
->core
, u
->time_event
, pa_rtclock_now() + u
->adjust_time
);
385 /* Called from source I/O thread context */
386 static int source_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
387 struct userdata
*u
= PA_SOURCE(o
)->userdata
;
391 case PA_SOURCE_MESSAGE_GET_LATENCY
:
393 /* The source is _put() before the source output is, so let's
394 * make sure we don't access it in that time. Also, the
395 * source output is first shut down, the source second. */
396 if (!PA_SOURCE_IS_LINKED(u
->source
->thread_info
.state
) ||
397 !PA_SOURCE_OUTPUT_IS_LINKED(u
->source_output
->thread_info
.state
)) {
398 *((pa_usec_t
*) data
) = 0;
402 *((pa_usec_t
*) data
) =
404 /* Get the latency of the master source */
405 pa_source_get_latency_within_thread(u
->source_output
->source
) +
406 /* Add the latency internal to our source output on top */
407 pa_bytes_to_usec(pa_memblockq_get_length(u
->source_output
->thread_info
.delay_memblockq
), &u
->source_output
->source
->sample_spec
) +
408 /* and the buffering we do on the source */
409 pa_bytes_to_usec(u
->blocksize
, &u
->source_output
->source
->sample_spec
);
413 case PA_SOURCE_MESSAGE_SET_VOLUME_SYNCED
:
414 u
->thread_info
.current_volume
= u
->source
->reference_volume
;
418 return pa_source_process_msg(o
, code
, data
, offset
, chunk
);
421 /* Called from sink I/O thread context */
422 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
423 struct userdata
*u
= PA_SINK(o
)->userdata
;
427 case PA_SINK_MESSAGE_GET_LATENCY
:
429 /* The sink is _put() before the sink input is, so let's
430 * make sure we don't access it in that time. Also, the
431 * sink input is first shut down, the sink second. */
432 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
433 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
434 *((pa_usec_t
*) data
) = 0;
438 *((pa_usec_t
*) data
) =
440 /* Get the latency of the master sink */
441 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
443 /* Add the latency internal to our sink input on top */
444 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
449 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
453 /* Called from main context */
454 static int source_set_state_cb(pa_source
*s
, pa_source_state_t state
) {
457 pa_source_assert_ref(s
);
458 pa_assert_se(u
= s
->userdata
);
460 if (!PA_SOURCE_IS_LINKED(state
) ||
461 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
)))
464 if (state
== PA_SOURCE_RUNNING
) {
465 /* restart timer when both sink and source are active */
466 if (IS_ACTIVE(u
) && u
->adjust_time
)
467 pa_core_rttime_restart(u
->core
, u
->time_event
, pa_rtclock_now() + u
->adjust_time
);
469 pa_atomic_store(&u
->request_resync
, 1);
470 pa_source_output_cork(u
->source_output
, FALSE
);
471 } else if (state
== PA_SOURCE_SUSPENDED
) {
472 pa_source_output_cork(u
->source_output
, TRUE
);
478 /* Called from main context */
479 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
482 pa_sink_assert_ref(s
);
483 pa_assert_se(u
= s
->userdata
);
485 if (!PA_SINK_IS_LINKED(state
) ||
486 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
489 if (state
== PA_SINK_RUNNING
) {
490 /* restart timer when both sink and source are active */
491 if (IS_ACTIVE(u
) && u
->adjust_time
)
492 pa_core_rttime_restart(u
->core
, u
->time_event
, pa_rtclock_now() + u
->adjust_time
);
494 pa_atomic_store(&u
->request_resync
, 1);
495 pa_sink_input_cork(u
->sink_input
, FALSE
);
496 } else if (state
== PA_SINK_SUSPENDED
) {
497 pa_sink_input_cork(u
->sink_input
, TRUE
);
503 /* Called from source I/O thread context */
504 static void source_update_requested_latency_cb(pa_source
*s
) {
507 pa_source_assert_ref(s
);
508 pa_assert_se(u
= s
->userdata
);
510 if (!PA_SOURCE_IS_LINKED(u
->source
->thread_info
.state
) ||
511 !PA_SOURCE_OUTPUT_IS_LINKED(u
->source_output
->thread_info
.state
))
514 pa_log_debug("Source update requested latency");
516 /* Just hand this one over to the master source */
517 pa_source_output_set_requested_latency_within_thread(
519 pa_source_get_requested_latency_within_thread(s
));
522 /* Called from sink I/O thread context */
523 static void sink_update_requested_latency_cb(pa_sink
*s
) {
526 pa_sink_assert_ref(s
);
527 pa_assert_se(u
= s
->userdata
);
529 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
530 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
533 pa_log_debug("Sink update requested latency");
535 /* Just hand this one over to the master sink */
536 pa_sink_input_set_requested_latency_within_thread(
538 pa_sink_get_requested_latency_within_thread(s
));
541 /* Called from sink I/O thread context */
542 static void sink_request_rewind_cb(pa_sink
*s
) {
545 pa_sink_assert_ref(s
);
546 pa_assert_se(u
= s
->userdata
);
548 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
549 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
552 pa_log_debug("Sink request rewind %lld", (long long) s
->thread_info
.rewind_nbytes
);
554 /* Just hand this one over to the master sink */
555 pa_sink_input_request_rewind(u
->sink_input
,
556 s
->thread_info
.rewind_nbytes
, TRUE
, FALSE
, FALSE
);
559 /* Called from main context */
560 static void source_set_volume_cb(pa_source
*s
) {
563 pa_source_assert_ref(s
);
564 pa_assert_se(u
= s
->userdata
);
566 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s
)) ||
567 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
)))
570 pa_source_output_set_volume(u
->source_output
, &s
->real_volume
, s
->save_volume
, TRUE
);
573 /* Called from main context */
574 static void sink_set_volume_cb(pa_sink
*s
) {
577 pa_sink_assert_ref(s
);
578 pa_assert_se(u
= s
->userdata
);
580 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
581 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
584 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
587 /* Called from main context. */
588 static void source_get_volume_cb(pa_source
*s
) {
592 pa_source_assert_ref(s
);
593 pa_assert_se(u
= s
->userdata
);
595 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s
)) ||
596 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
)))
599 pa_source_output_get_volume(u
->source_output
, &v
, TRUE
);
601 if (pa_cvolume_equal(&s
->real_volume
, &v
))
606 pa_source_set_soft_volume(s
, NULL
);
609 /* Called from main context */
610 static void source_set_mute_cb(pa_source
*s
) {
613 pa_source_assert_ref(s
);
614 pa_assert_se(u
= s
->userdata
);
616 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s
)) ||
617 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
)))
620 pa_source_output_set_mute(u
->source_output
, s
->muted
, s
->save_muted
);
623 /* Called from main context */
624 static void sink_set_mute_cb(pa_sink
*s
) {
627 pa_sink_assert_ref(s
);
628 pa_assert_se(u
= s
->userdata
);
630 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
631 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
634 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
637 /* Called from main context */
638 static void source_get_mute_cb(pa_source
*s
) {
641 pa_source_assert_ref(s
);
642 pa_assert_se(u
= s
->userdata
);
644 if (!PA_SOURCE_IS_LINKED(pa_source_get_state(s
)) ||
645 !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
)))
648 pa_source_output_get_mute(u
->source_output
);
651 /* Called from source I/O thread context. */
652 static void apply_diff_time(struct userdata
*u
, int64_t diff_time
) {
656 diff
= pa_usec_to_bytes(-diff_time
, &u
->source_output
->sample_spec
);
659 /* add some extra safety samples to compensate for jitter in the
661 diff
+= 10 * pa_frame_size (&u
->source_output
->sample_spec
);
663 pa_log("Playback after capture (%lld), drop sink %lld", (long long) diff_time
, (long long) diff
);
668 } else if (diff_time
> 0) {
669 diff
= pa_usec_to_bytes(diff_time
, &u
->source_output
->sample_spec
);
672 pa_log("Playback too far ahead (%lld), drop source %lld", (long long) diff_time
, (long long) diff
);
674 u
->source_skip
= diff
;
680 /* Called from source I/O thread context. */
681 static void do_resync(struct userdata
*u
) {
683 struct snapshot latency_snapshot
;
685 pa_log("Doing resync");
687 /* update our snapshot */
688 source_output_snapshot_within_thread(u
, &latency_snapshot
);
689 pa_asyncmsgq_send(u
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(u
->sink_input
), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
, &latency_snapshot
, 0, NULL
);
691 /* calculate drift between capture and playback */
692 diff_time
= calc_diff(u
, &latency_snapshot
);
694 /* and adjust for the drift */
695 apply_diff_time(u
, diff_time
);
698 /* 1. Calculate drift at this point, pass to canceller
699 * 2. Push out playback samples in blocksize chunks
700 * 3. Push out capture samples in blocksize chunks
704 * Called from source I/O thread context.
706 static void do_push_drift_comp(struct userdata
*u
) {
708 pa_memchunk rchunk
, pchunk
, cchunk
;
709 uint8_t *rdata
, *pdata
, *cdata
;
711 int unused PA_GCC_UNUSED
;
713 rlen
= pa_memblockq_get_length(u
->source_memblockq
);
714 plen
= pa_memblockq_get_length(u
->sink_memblockq
);
716 /* Estimate snapshot drift as follows:
717 * pd: amount of data consumed since last time
718 * rd: amount of data consumed since last time
720 * drift = (pd - rd) / rd;
722 * We calculate pd and rd as the memblockq length less the number of
723 * samples left from the last iteration (to avoid double counting
724 * those remainder samples.
726 drift
= ((float)(plen
- u
->sink_rem
) - (rlen
- u
->source_rem
)) / ((float)(rlen
- u
->source_rem
));
727 u
->sink_rem
= plen
% u
->blocksize
;
728 u
->source_rem
= rlen
% u
->blocksize
;
730 /* Now let the canceller work its drift compensation magic */
731 u
->ec
->set_drift(u
->ec
, drift
);
735 fprintf(u
->drift_file
, "d %a\n", drift
);
738 /* Send in the playback samples first */
739 while (plen
>= u
->blocksize
) {
740 pa_memblockq_peek_fixed_size(u
->sink_memblockq
, u
->blocksize
, &pchunk
);
741 pdata
= pa_memblock_acquire(pchunk
.memblock
);
742 pdata
+= pchunk
.index
;
744 u
->ec
->play(u
->ec
, pdata
);
748 fprintf(u
->drift_file
, "p %d\n", u
->blocksize
);
750 unused
= fwrite(pdata
, 1, u
->blocksize
, u
->played_file
);
753 pa_memblock_release(pchunk
.memblock
);
754 pa_memblockq_drop(u
->sink_memblockq
, u
->blocksize
);
755 pa_memblock_unref(pchunk
.memblock
);
757 plen
-= u
->blocksize
;
760 /* And now the capture samples */
761 while (rlen
>= u
->blocksize
) {
762 pa_memblockq_peek_fixed_size(u
->source_memblockq
, u
->blocksize
, &rchunk
);
764 rdata
= pa_memblock_acquire(rchunk
.memblock
);
765 rdata
+= rchunk
.index
;
768 cchunk
.length
= u
->blocksize
;
769 cchunk
.memblock
= pa_memblock_new(u
->source
->core
->mempool
, cchunk
.length
);
770 cdata
= pa_memblock_acquire(cchunk
.memblock
);
772 u
->ec
->record(u
->ec
, rdata
, cdata
);
776 fprintf(u
->drift_file
, "c %d\n", u
->blocksize
);
777 if (u
->captured_file
)
778 unused
= fwrite(rdata
, 1, u
->blocksize
, u
->captured_file
);
779 if (u
->canceled_file
)
780 unused
= fwrite(cdata
, 1, u
->blocksize
, u
->canceled_file
);
783 pa_memblock_release(cchunk
.memblock
);
784 pa_memblock_release(rchunk
.memblock
);
786 pa_memblock_unref(rchunk
.memblock
);
788 pa_source_post(u
->source
, &cchunk
);
789 pa_memblock_unref(cchunk
.memblock
);
791 pa_memblockq_drop(u
->source_memblockq
, u
->blocksize
);
792 rlen
-= u
->blocksize
;
796 /* This one's simpler than the drift compensation case -- we just iterate over
797 * the capture buffer, and pass the canceller blocksize bytes of playback and
800 * Called from source I/O thread context. */
801 static void do_push(struct userdata
*u
) {
803 pa_memchunk rchunk
, pchunk
, cchunk
;
804 uint8_t *rdata
, *pdata
, *cdata
;
805 int unused PA_GCC_UNUSED
;
807 rlen
= pa_memblockq_get_length(u
->source_memblockq
);
808 plen
= pa_memblockq_get_length(u
->sink_memblockq
);
810 while (rlen
>= u
->blocksize
) {
811 /* take fixed block from recorded samples */
812 pa_memblockq_peek_fixed_size(u
->source_memblockq
, u
->blocksize
, &rchunk
);
814 if (plen
>= u
->blocksize
) {
815 /* take fixed block from played samples */
816 pa_memblockq_peek_fixed_size(u
->sink_memblockq
, u
->blocksize
, &pchunk
);
818 rdata
= pa_memblock_acquire(rchunk
.memblock
);
819 rdata
+= rchunk
.index
;
820 pdata
= pa_memblock_acquire(pchunk
.memblock
);
821 pdata
+= pchunk
.index
;
824 cchunk
.length
= u
->blocksize
;
825 cchunk
.memblock
= pa_memblock_new(u
->source
->core
->mempool
, cchunk
.length
);
826 cdata
= pa_memblock_acquire(cchunk
.memblock
);
829 if (u
->captured_file
)
830 unused
= fwrite(rdata
, 1, u
->blocksize
, u
->captured_file
);
832 unused
= fwrite(pdata
, 1, u
->blocksize
, u
->played_file
);
835 /* perform echo cancellation */
836 u
->ec
->run(u
->ec
, rdata
, pdata
, cdata
);
839 if (u
->canceled_file
)
840 unused
= fwrite(cdata
, 1, u
->blocksize
, u
->canceled_file
);
843 pa_memblock_release(cchunk
.memblock
);
844 pa_memblock_release(pchunk
.memblock
);
845 pa_memblock_release(rchunk
.memblock
);
847 /* drop consumed sink samples */
848 pa_memblockq_drop(u
->sink_memblockq
, u
->blocksize
);
849 pa_memblock_unref(pchunk
.memblock
);
851 pa_memblock_unref(rchunk
.memblock
);
852 /* the filtered samples now become the samples from our
856 plen
-= u
->blocksize
;
859 /* forward the (echo-canceled) data to the virtual source */
860 pa_source_post(u
->source
, &rchunk
);
861 pa_memblock_unref(rchunk
.memblock
);
863 pa_memblockq_drop(u
->source_memblockq
, u
->blocksize
);
864 rlen
-= u
->blocksize
;
868 /* Called from source I/O thread context. */
869 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
871 size_t rlen
, plen
, to_skip
;
874 pa_source_output_assert_ref(o
);
875 pa_source_output_assert_io_context(o
);
876 pa_assert_se(u
= o
->userdata
);
878 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u
->source_output
))) {
879 pa_log("Push when no link?");
883 if (PA_UNLIKELY(u
->source
->thread_info
.state
!= PA_SOURCE_RUNNING
||
884 u
->sink
->thread_info
.state
!= PA_SINK_RUNNING
)) {
885 pa_source_post(u
->source
, chunk
);
889 /* handle queued messages, do any message sending of our own */
890 while (pa_asyncmsgq_process_one(u
->asyncmsgq
) > 0)
893 pa_memblockq_push_align(u
->source_memblockq
, chunk
);
895 rlen
= pa_memblockq_get_length(u
->source_memblockq
);
896 plen
= pa_memblockq_get_length(u
->sink_memblockq
);
898 /* Let's not do anything else till we have enough data to process */
899 if (rlen
< u
->blocksize
)
902 /* See if we need to drop samples in order to sync */
903 if (pa_atomic_cmpxchg (&u
->request_resync
, 1, 0)) {
907 /* Okay, skip cancellation for skipped source samples if needed. */
908 if (PA_UNLIKELY(u
->source_skip
)) {
909 /* The slightly tricky bit here is that we drop all but modulo
910 * blocksize bytes and then adjust for that last bit on the sink side.
911 * We do this because the source data is coming at a fixed rate, which
912 * means the only way to try to catch up is drop sink samples and let
913 * the canceller cope up with this. */
914 to_skip
= rlen
>= u
->source_skip
? u
->source_skip
: rlen
;
915 to_skip
-= to_skip
% u
->blocksize
;
918 pa_memblockq_peek_fixed_size(u
->source_memblockq
, to_skip
, &rchunk
);
919 pa_source_post(u
->source
, &rchunk
);
921 pa_memblock_unref(rchunk
.memblock
);
922 pa_memblockq_drop(u
->source_memblockq
, to_skip
);
925 u
->source_skip
-= to_skip
;
928 if (rlen
&& u
->source_skip
% u
->blocksize
) {
929 u
->sink_skip
+= u
->blocksize
- (u
->source_skip
% u
->blocksize
);
930 u
->source_skip
-= (u
->source_skip
% u
->blocksize
);
934 /* And for the sink, these samples have been played back already, so we can
935 * just drop them and get on with it. */
936 if (PA_UNLIKELY(u
->sink_skip
)) {
937 to_skip
= plen
>= u
->sink_skip
? u
->sink_skip
: plen
;
939 pa_memblockq_drop(u
->sink_memblockq
, to_skip
);
942 u
->sink_skip
-= to_skip
;
945 /* process and push out samples */
946 if (u
->ec
->params
.drift_compensation
)
947 do_push_drift_comp(u
);
952 /* Called from sink I/O thread context. */
953 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
956 pa_sink_input_assert_ref(i
);
958 pa_assert_se(u
= i
->userdata
);
960 if (u
->sink
->thread_info
.rewind_requested
)
961 pa_sink_process_rewind(u
->sink
, 0);
963 pa_sink_render_full(u
->sink
, nbytes
, chunk
);
965 if (i
->thread_info
.underrun_for
> 0) {
966 pa_log_debug("Handling end of underrun.");
967 pa_atomic_store(&u
->request_resync
, 1);
970 /* let source thread handle the chunk. pass the sample count as well so that
971 * the source IO thread can update the right variables. */
972 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_POST
,
973 NULL
, 0, chunk
, NULL
);
974 u
->send_counter
+= chunk
->length
;
979 /* Called from source I/O thread context. */
980 static void source_output_process_rewind_cb(pa_source_output
*o
, size_t nbytes
) {
983 pa_source_output_assert_ref(o
);
984 pa_source_output_assert_io_context(o
);
985 pa_assert_se(u
= o
->userdata
);
987 pa_source_process_rewind(u
->source
, nbytes
);
989 /* go back on read side, we need to use older sink data for this */
990 pa_memblockq_rewind(u
->sink_memblockq
, nbytes
);
992 /* manipulate write index */
993 pa_memblockq_seek(u
->source_memblockq
, -nbytes
, PA_SEEK_RELATIVE
, TRUE
);
995 pa_log_debug("Source rewind (%lld) %lld", (long long) nbytes
,
996 (long long) pa_memblockq_get_length (u
->source_memblockq
));
999 /* Called from sink I/O thread context. */
1000 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1003 pa_sink_input_assert_ref(i
);
1004 pa_assert_se(u
= i
->userdata
);
1006 pa_log_debug("Sink process rewind %lld", (long long) nbytes
);
1008 pa_sink_process_rewind(u
->sink
, nbytes
);
1010 pa_asyncmsgq_post(u
->asyncmsgq
, PA_MSGOBJECT(u
->source_output
), SOURCE_OUTPUT_MESSAGE_REWIND
, NULL
, (int64_t) nbytes
, NULL
, NULL
);
1011 u
->send_counter
-= nbytes
;
1014 /* Called from source I/O thread context. */
1015 static void source_output_snapshot_within_thread(struct userdata
*u
, struct snapshot
*snapshot
) {
1016 size_t delay
, rlen
, plen
;
1017 pa_usec_t now
, latency
;
1019 now
= pa_rtclock_now();
1020 latency
= pa_source_get_latency_within_thread(u
->source_output
->source
);
1021 delay
= pa_memblockq_get_length(u
->source_output
->thread_info
.delay_memblockq
);
1023 delay
= (u
->source_output
->thread_info
.resampler
? pa_resampler_request(u
->source_output
->thread_info
.resampler
, delay
) : delay
);
1024 rlen
= pa_memblockq_get_length(u
->source_memblockq
);
1025 plen
= pa_memblockq_get_length(u
->sink_memblockq
);
1027 snapshot
->source_now
= now
;
1028 snapshot
->source_latency
= latency
;
1029 snapshot
->source_delay
= delay
;
1030 snapshot
->recv_counter
= u
->recv_counter
;
1031 snapshot
->rlen
= rlen
+ u
->sink_skip
;
1032 snapshot
->plen
= plen
+ u
->source_skip
;
1035 /* Called from source I/O thread context. */
1036 static int source_output_process_msg_cb(pa_msgobject
*obj
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
1037 struct userdata
*u
= PA_SOURCE_OUTPUT(obj
)->userdata
;
1041 case SOURCE_OUTPUT_MESSAGE_POST
:
1043 pa_source_output_assert_io_context(u
->source_output
);
1045 if (u
->source_output
->source
->thread_info
.state
== PA_SOURCE_RUNNING
)
1046 pa_memblockq_push_align(u
->sink_memblockq
, chunk
);
1048 pa_memblockq_flush_write(u
->sink_memblockq
, TRUE
);
1050 u
->recv_counter
+= (int64_t) chunk
->length
;
1054 case SOURCE_OUTPUT_MESSAGE_REWIND
:
1055 pa_source_output_assert_io_context(u
->source_output
);
1057 /* manipulate write index, never go past what we have */
1058 if (PA_SOURCE_IS_OPENED(u
->source_output
->source
->thread_info
.state
))
1059 pa_memblockq_seek(u
->sink_memblockq
, -offset
, PA_SEEK_RELATIVE
, TRUE
);
1061 pa_memblockq_flush_write(u
->sink_memblockq
, TRUE
);
1063 pa_log_debug("Sink rewind (%lld)", (long long) offset
);
1065 u
->recv_counter
-= offset
;
1069 case SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT
: {
1070 struct snapshot
*snapshot
= (struct snapshot
*) data
;
1072 source_output_snapshot_within_thread(u
, snapshot
);
1076 case SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME
:
1077 apply_diff_time(u
, offset
);
1082 return pa_source_output_process_msg(obj
, code
, data
, offset
, chunk
);
1085 /* Called from sink I/O thread context. */
1086 static int sink_input_process_msg_cb(pa_msgobject
*obj
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
1087 struct userdata
*u
= PA_SINK_INPUT(obj
)->userdata
;
1091 case SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT
: {
1093 pa_usec_t now
, latency
;
1094 struct snapshot
*snapshot
= (struct snapshot
*) data
;
1096 pa_sink_input_assert_io_context(u
->sink_input
);
1098 now
= pa_rtclock_now();
1099 latency
= pa_sink_get_latency_within_thread(u
->sink_input
->sink
);
1100 delay
= pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
);
1102 delay
= (u
->sink_input
->thread_info
.resampler
? pa_resampler_request(u
->sink_input
->thread_info
.resampler
, delay
) : delay
);
1104 snapshot
->sink_now
= now
;
1105 snapshot
->sink_latency
= latency
;
1106 snapshot
->sink_delay
= delay
;
1107 snapshot
->send_counter
= u
->send_counter
;
1112 return pa_sink_input_process_msg(obj
, code
, data
, offset
, chunk
);
1115 /* Called from sink I/O thread context. */
1116 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1119 pa_sink_input_assert_ref(i
);
1120 pa_assert_se(u
= i
->userdata
);
1122 pa_log_debug("Sink input update max rewind %lld", (long long) nbytes
);
1124 pa_memblockq_set_maxrewind(u
->sink_memblockq
, nbytes
);
1125 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
1128 /* Called from source I/O thread context. */
1129 static void source_output_update_max_rewind_cb(pa_source_output
*o
, size_t nbytes
) {
1132 pa_source_output_assert_ref(o
);
1133 pa_assert_se(u
= o
->userdata
);
1135 pa_log_debug("Source output update max rewind %lld", (long long) nbytes
);
1137 pa_source_set_max_rewind_within_thread(u
->source
, nbytes
);
1140 /* Called from sink I/O thread context. */
1141 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1144 pa_sink_input_assert_ref(i
);
1145 pa_assert_se(u
= i
->userdata
);
1147 pa_log_debug("Sink input update max request %lld", (long long) nbytes
);
1149 pa_sink_set_max_request_within_thread(u
->sink
, nbytes
);
1152 /* Called from sink I/O thread context. */
1153 static void sink_input_update_sink_requested_latency_cb(pa_sink_input
*i
) {
1157 pa_sink_input_assert_ref(i
);
1158 pa_assert_se(u
= i
->userdata
);
1160 latency
= pa_sink_get_requested_latency_within_thread(i
->sink
);
1162 pa_log_debug("Sink input update requested latency %lld", (long long) latency
);
1165 /* Called from source I/O thread context. */
1166 static void source_output_update_source_requested_latency_cb(pa_source_output
*o
) {
1170 pa_source_output_assert_ref(o
);
1171 pa_assert_se(u
= o
->userdata
);
1173 latency
= pa_source_get_requested_latency_within_thread(o
->source
);
1175 pa_log_debug("Source output update requested latency %lld", (long long) latency
);
1178 /* Called from sink I/O thread context. */
1179 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
1182 pa_sink_input_assert_ref(i
);
1183 pa_assert_se(u
= i
->userdata
);
1185 pa_log_debug("Sink input update latency range %lld %lld",
1186 (long long) i
->sink
->thread_info
.min_latency
,
1187 (long long) i
->sink
->thread_info
.max_latency
);
1189 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
1192 /* Called from source I/O thread context. */
1193 static void source_output_update_source_latency_range_cb(pa_source_output
*o
) {
1196 pa_source_output_assert_ref(o
);
1197 pa_assert_se(u
= o
->userdata
);
1199 pa_log_debug("Source output update latency range %lld %lld",
1200 (long long) o
->source
->thread_info
.min_latency
,
1201 (long long) o
->source
->thread_info
.max_latency
);
1203 pa_source_set_latency_range_within_thread(u
->source
, o
->source
->thread_info
.min_latency
, o
->source
->thread_info
.max_latency
);
1206 /* Called from sink I/O thread context. */
1207 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
1210 pa_sink_input_assert_ref(i
);
1211 pa_assert_se(u
= i
->userdata
);
1213 pa_log_debug("Sink input update fixed latency %lld",
1214 (long long) i
->sink
->thread_info
.fixed_latency
);
1216 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
1219 /* Called from source I/O thread context. */
1220 static void source_output_update_source_fixed_latency_cb(pa_source_output
*o
) {
1223 pa_source_output_assert_ref(o
);
1224 pa_assert_se(u
= o
->userdata
);
1226 pa_log_debug("Source output update fixed latency %lld",
1227 (long long) o
->source
->thread_info
.fixed_latency
);
1229 pa_source_set_fixed_latency_within_thread(u
->source
, o
->source
->thread_info
.fixed_latency
);
1232 /* Called from source I/O thread context. */
1233 static void source_output_attach_cb(pa_source_output
*o
) {
1236 pa_source_output_assert_ref(o
);
1237 pa_source_output_assert_io_context(o
);
1238 pa_assert_se(u
= o
->userdata
);
1240 pa_source_set_rtpoll(u
->source
, o
->source
->thread_info
.rtpoll
);
1241 pa_source_set_latency_range_within_thread(u
->source
, o
->source
->thread_info
.min_latency
, o
->source
->thread_info
.max_latency
);
1242 pa_source_set_fixed_latency_within_thread(u
->source
, o
->source
->thread_info
.fixed_latency
);
1243 pa_source_set_max_rewind_within_thread(u
->source
, pa_source_output_get_max_rewind(o
));
1245 pa_log_debug("Source output %d attach", o
->index
);
1247 pa_source_attach_within_thread(u
->source
);
1249 u
->rtpoll_item_read
= pa_rtpoll_item_new_asyncmsgq_read(
1250 o
->source
->thread_info
.rtpoll
,
1255 /* Called from sink I/O thread context. */
1256 static void sink_input_attach_cb(pa_sink_input
*i
) {
1259 pa_sink_input_assert_ref(i
);
1260 pa_assert_se(u
= i
->userdata
);
1262 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
1263 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
1265 /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
1266 * BLOCK MINUS ONE SAMPLE HERE. SEE (7) */
1267 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
1269 /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
1270 * pa_sink_input_get_max_request(i) UP TO MULTIPLES OF IT
1272 pa_sink_set_max_request_within_thread(u
->sink
, pa_sink_input_get_max_request(i
));
1273 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
1275 pa_log_debug("Sink input %d attach", i
->index
);
1277 u
->rtpoll_item_write
= pa_rtpoll_item_new_asyncmsgq_write(
1278 i
->sink
->thread_info
.rtpoll
,
1282 pa_sink_attach_within_thread(u
->sink
);
1286 /* Called from source I/O thread context. */
1287 static void source_output_detach_cb(pa_source_output
*o
) {
1290 pa_source_output_assert_ref(o
);
1291 pa_source_output_assert_io_context(o
);
1292 pa_assert_se(u
= o
->userdata
);
1294 pa_source_detach_within_thread(u
->source
);
1295 pa_source_set_rtpoll(u
->source
, NULL
);
1297 pa_log_debug("Source output %d detach", o
->index
);
1299 if (u
->rtpoll_item_read
) {
1300 pa_rtpoll_item_free(u
->rtpoll_item_read
);
1301 u
->rtpoll_item_read
= NULL
;
1305 /* Called from sink I/O thread context. */
1306 static void sink_input_detach_cb(pa_sink_input
*i
) {
1309 pa_sink_input_assert_ref(i
);
1310 pa_assert_se(u
= i
->userdata
);
1312 pa_sink_detach_within_thread(u
->sink
);
1314 pa_sink_set_rtpoll(u
->sink
, NULL
);
1316 pa_log_debug("Sink input %d detach", i
->index
);
1318 if (u
->rtpoll_item_write
) {
1319 pa_rtpoll_item_free(u
->rtpoll_item_write
);
1320 u
->rtpoll_item_write
= NULL
;
1324 /* Called from source I/O thread context. */
1325 static void source_output_state_change_cb(pa_source_output
*o
, pa_source_output_state_t state
) {
1328 pa_source_output_assert_ref(o
);
1329 pa_source_output_assert_io_context(o
);
1330 pa_assert_se(u
= o
->userdata
);
1332 pa_log_debug("Source output %d state %d", o
->index
, state
);
1335 /* Called from sink I/O thread context. */
1336 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
1339 pa_sink_input_assert_ref(i
);
1340 pa_assert_se(u
= i
->userdata
);
1342 pa_log_debug("Sink input %d state %d", i
->index
, state
);
1344 /* If we are added for the first time, ask for a rewinding so that
1345 * we are heard right-away. */
1346 if (PA_SINK_INPUT_IS_LINKED(state
) &&
1347 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
1348 pa_log_debug("Requesting rewind due to state change.");
1349 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
1353 /* Called from main context. */
1354 static void source_output_kill_cb(pa_source_output
*o
) {
1357 pa_source_output_assert_ref(o
);
1358 pa_assert_ctl_context();
1359 pa_assert_se(u
= o
->userdata
);
1363 /* The order here matters! We first kill the source output, followed
1364 * by the source. That means the source callbacks must be protected
1365 * against an unconnected source output! */
1366 pa_source_output_unlink(u
->source_output
);
1367 pa_source_unlink(u
->source
);
1369 pa_source_output_unref(u
->source_output
);
1370 u
->source_output
= NULL
;
1372 pa_source_unref(u
->source
);
1375 pa_log_debug("Source output kill %d", o
->index
);
1377 pa_module_unload_request(u
->module
, TRUE
);
1380 /* Called from main context */
1381 static void sink_input_kill_cb(pa_sink_input
*i
) {
1384 pa_sink_input_assert_ref(i
);
1385 pa_assert_se(u
= i
->userdata
);
1389 /* The order here matters! We first kill the sink input, followed
1390 * by the sink. That means the sink callbacks must be protected
1391 * against an unconnected sink input! */
1392 pa_sink_input_unlink(u
->sink_input
);
1393 pa_sink_unlink(u
->sink
);
1395 pa_sink_input_unref(u
->sink_input
);
1396 u
->sink_input
= NULL
;
1398 pa_sink_unref(u
->sink
);
1401 pa_log_debug("Sink input kill %d", i
->index
);
1403 pa_module_unload_request(u
->module
, TRUE
);
1406 /* Called from main context. */
1407 static pa_bool_t
source_output_may_move_to_cb(pa_source_output
*o
, pa_source
*dest
) {
1410 pa_source_output_assert_ref(o
);
1411 pa_assert_ctl_context();
1412 pa_assert_se(u
= o
->userdata
);
1414 if (u
->dead
|| u
->autoloaded
)
1417 return (u
->source
!= dest
) && (u
->sink
!= dest
->monitor_of
);
1420 /* Called from main context */
1421 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1424 pa_sink_input_assert_ref(i
);
1425 pa_assert_se(u
= i
->userdata
);
1427 if (u
->dead
|| u
->autoloaded
)
1430 return u
->sink
!= dest
;
1433 /* Called from main context. */
1434 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1437 pa_source_output_assert_ref(o
);
1438 pa_assert_ctl_context();
1439 pa_assert_se(u
= o
->userdata
);
1442 pa_source_set_asyncmsgq(u
->source
, dest
->asyncmsgq
);
1443 pa_source_update_flags(u
->source
, PA_SOURCE_LATENCY
|PA_SOURCE_DYNAMIC_LATENCY
, dest
->flags
);
1445 pa_source_set_asyncmsgq(u
->source
, NULL
);
1447 if (u
->source_auto_desc
&& dest
) {
1451 pl
= pa_proplist_new();
1452 y
= pa_proplist_gets(u
->sink_input
->sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1453 z
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1454 pa_proplist_setf(pl
, PA_PROP_DEVICE_DESCRIPTION
, "%s (echo cancelled with %s)", z
? z
: dest
->name
,
1455 y
? y
: u
->sink_input
->sink
->name
);
1457 pa_source_update_proplist(u
->source
, PA_UPDATE_REPLACE
, pl
);
1458 pa_proplist_free(pl
);
1462 /* Called from main context */
1463 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1466 pa_sink_input_assert_ref(i
);
1467 pa_assert_se(u
= i
->userdata
);
1470 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1471 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1473 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1475 if (u
->sink_auto_desc
&& dest
) {
1479 pl
= pa_proplist_new();
1480 y
= pa_proplist_gets(u
->source_output
->source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1481 z
= pa_proplist_gets(dest
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1482 pa_proplist_setf(pl
, PA_PROP_DEVICE_DESCRIPTION
, "%s (echo cancelled with %s)", z
? z
: dest
->name
,
1483 y
? y
: u
->source_output
->source
->name
);
1485 pa_sink_update_proplist(u
->sink
, PA_UPDATE_REPLACE
, pl
);
1486 pa_proplist_free(pl
);
1490 /* Called from main context */
1491 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
1494 pa_sink_input_assert_ref(i
);
1495 pa_assert_se(u
= i
->userdata
);
1497 pa_sink_volume_changed(u
->sink
, &i
->volume
);
1500 /* Called from main context */
1501 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
1504 pa_sink_input_assert_ref(i
);
1505 pa_assert_se(u
= i
->userdata
);
1507 pa_sink_mute_changed(u
->sink
, i
->muted
);
1510 /* Called from main context */
1511 static int canceller_process_msg_cb(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1512 struct pa_echo_canceller_msg
*msg
;
1517 msg
= PA_ECHO_CANCELLER_MSG(o
);
1521 case ECHO_CANCELLER_MESSAGE_SET_VOLUME
: {
1522 pa_cvolume
*v
= (pa_cvolume
*) userdata
;
1524 if (u
->use_volume_sharing
)
1525 pa_source_set_volume(u
->source
, v
, TRUE
, FALSE
);
1527 pa_source_output_set_volume(u
->source_output
, v
, FALSE
, TRUE
);
1533 pa_assert_not_reached();
1540 /* Called by the canceller, so source I/O thread context. */
1541 void pa_echo_canceller_get_capture_volume(pa_echo_canceller
*ec
, pa_cvolume
*v
) {
1542 *v
= ec
->msg
->userdata
->thread_info
.current_volume
;
1545 /* Called by the canceller, so source I/O thread context. */
1546 void pa_echo_canceller_set_capture_volume(pa_echo_canceller
*ec
, pa_cvolume
*v
) {
1547 if (!pa_cvolume_equal(&ec
->msg
->userdata
->thread_info
.current_volume
, v
)) {
1548 pa_cvolume
*vol
= pa_xnewdup(pa_cvolume
, v
, 1);
1550 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(ec
->msg
), ECHO_CANCELLER_MESSAGE_SET_VOLUME
, vol
, 0, NULL
,
1555 static pa_echo_canceller_method_t
get_ec_method_from_string(const char *method
) {
1557 if (pa_streq(method
, "speex"))
1558 return PA_ECHO_CANCELLER_SPEEX
;
1560 #ifdef HAVE_ADRIAN_EC
1561 if (pa_streq(method
, "adrian"))
1562 return PA_ECHO_CANCELLER_ADRIAN
;
1565 if (pa_streq(method
, "webrtc"))
1566 return PA_ECHO_CANCELLER_WEBRTC
;
1568 return PA_ECHO_CANCELLER_INVALID
;
1571 /* Common initialisation bits between module-echo-cancel and the standalone
1574 * Called from main context. */
1575 static int init_common(pa_modargs
*ma
, struct userdata
*u
, pa_sample_spec
*source_ss
, pa_channel_map
*source_map
) {
1576 pa_echo_canceller_method_t ec_method
;
1578 if (pa_modargs_get_sample_spec_and_channel_map(ma
, source_ss
, source_map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1579 pa_log("Invalid sample format specification or channel map");
1583 u
->ec
= pa_xnew0(pa_echo_canceller
, 1);
1585 pa_log("Failed to alloc echo canceller");
1589 if ((ec_method
= get_ec_method_from_string(pa_modargs_get_value(ma
, "aec_method", DEFAULT_ECHO_CANCELLER
))) < 0) {
1590 pa_log("Invalid echo canceller implementation");
1594 u
->ec
->init
= ec_table
[ec_method
].init
;
1595 u
->ec
->play
= ec_table
[ec_method
].play
;
1596 u
->ec
->record
= ec_table
[ec_method
].record
;
1597 u
->ec
->set_drift
= ec_table
[ec_method
].set_drift
;
1598 u
->ec
->run
= ec_table
[ec_method
].run
;
1599 u
->ec
->done
= ec_table
[ec_method
].done
;
1607 /* Called from main context. */
1608 int pa__init(pa_module
*m
) {
1610 pa_sample_spec source_ss
, sink_ss
;
1611 pa_channel_map source_map
, sink_map
;
1613 pa_source
*source_master
=NULL
;
1614 pa_sink
*sink_master
=NULL
;
1615 pa_source_output_new_data source_output_data
;
1616 pa_sink_input_new_data sink_input_data
;
1617 pa_source_new_data source_data
;
1618 pa_sink_new_data sink_data
;
1619 pa_memchunk silence
;
1624 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1625 pa_log("Failed to parse module arguments.");
1629 if (!(source_master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "source_master", NULL
), PA_NAMEREG_SOURCE
))) {
1630 pa_log("Master source not found");
1633 pa_assert(source_master
);
1635 if (!(sink_master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "sink_master", NULL
), PA_NAMEREG_SINK
))) {
1636 pa_log("Master sink not found");
1639 pa_assert(sink_master
);
1641 if (source_master
->monitor_of
== sink_master
) {
1642 pa_log("Can't cancel echo between a sink and its monitor");
1646 source_ss
= source_master
->sample_spec
;
1647 source_ss
.rate
= DEFAULT_RATE
;
1648 source_ss
.channels
= DEFAULT_CHANNELS
;
1649 pa_channel_map_init_auto(&source_map
, source_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
);
1651 sink_ss
= sink_master
->sample_spec
;
1652 sink_map
= sink_master
->channel_map
;
1654 u
= pa_xnew0(struct userdata
, 1);
1656 pa_log("Failed to alloc userdata");
1664 u
->use_volume_sharing
= TRUE
;
1665 if (pa_modargs_get_value_boolean(ma
, "use_volume_sharing", &u
->use_volume_sharing
) < 0) {
1666 pa_log("use_volume_sharing= expects a boolean argument");
1670 temp
= DEFAULT_ADJUST_TIME_USEC
/ PA_USEC_PER_SEC
;
1671 if (pa_modargs_get_value_u32(ma
, "adjust_time", &temp
) < 0) {
1672 pa_log("Failed to parse adjust_time value");
1676 if (temp
!= DEFAULT_ADJUST_TIME_USEC
/ PA_USEC_PER_SEC
)
1677 u
->adjust_time
= temp
* PA_USEC_PER_SEC
;
1679 u
->adjust_time
= DEFAULT_ADJUST_TIME_USEC
;
1681 temp
= DEFAULT_ADJUST_TOLERANCE
/ PA_USEC_PER_MSEC
;
1682 if (pa_modargs_get_value_u32(ma
, "adjust_threshold", &temp
) < 0) {
1683 pa_log("Failed to parse adjust_threshold value");
1687 if (temp
!= DEFAULT_ADJUST_TOLERANCE
/ PA_USEC_PER_MSEC
)
1688 u
->adjust_threshold
= temp
* PA_USEC_PER_MSEC
;
1690 u
->adjust_threshold
= DEFAULT_ADJUST_TOLERANCE
;
1692 u
->save_aec
= DEFAULT_SAVE_AEC
;
1693 if (pa_modargs_get_value_boolean(ma
, "save_aec", &u
->save_aec
) < 0) {
1694 pa_log("Failed to parse save_aec value");
1698 u
->autoloaded
= DEFAULT_AUTOLOADED
;
1699 if (pa_modargs_get_value_boolean(ma
, "autoloaded", &u
->autoloaded
) < 0) {
1700 pa_log("Failed to parse autoloaded value");
1704 if (init_common(ma
, u
, &source_ss
, &source_map
) < 0)
1707 u
->asyncmsgq
= pa_asyncmsgq_new(0);
1708 u
->need_realign
= TRUE
;
1711 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
))) {
1712 pa_log("Failed to init AEC engine");
1717 if (u
->ec
->params
.drift_compensation
)
1718 pa_assert(u
->ec
->set_drift
);
1721 pa_source_new_data_init(&source_data
);
1722 source_data
.driver
= __FILE__
;
1723 source_data
.module
= m
;
1724 if (!(source_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "source_name", NULL
))))
1725 source_data
.name
= pa_sprintf_malloc("%s.echo-cancel", source_master
->name
);
1726 pa_source_new_data_set_sample_spec(&source_data
, &source_ss
);
1727 pa_source_new_data_set_channel_map(&source_data
, &source_map
);
1728 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, source_master
->name
);
1729 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1731 pa_proplist_sets(source_data
.proplist
, PA_PROP_DEVICE_INTENDED_ROLES
, "phone");
1733 if (pa_modargs_get_proplist(ma
, "source_properties", source_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1734 pa_log("Invalid properties");
1735 pa_source_new_data_done(&source_data
);
1739 if ((u
->source_auto_desc
= !pa_proplist_contains(source_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
))) {
1742 y
= pa_proplist_gets(sink_master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1743 z
= pa_proplist_gets(source_master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1744 pa_proplist_setf(source_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "%s (echo cancelled with %s)",
1745 z
? z
: source_master
->name
, y
? y
: sink_master
->name
);
1748 u
->source
= pa_source_new(m
->core
, &source_data
, (source_master
->flags
& (PA_SOURCE_LATENCY
| PA_SOURCE_DYNAMIC_LATENCY
))
1749 | (u
->use_volume_sharing
? PA_SOURCE_SHARE_VOLUME_WITH_MASTER
: 0));
1750 pa_source_new_data_done(&source_data
);
1753 pa_log("Failed to create source.");
1757 u
->source
->parent
.process_msg
= source_process_msg_cb
;
1758 u
->source
->set_state
= source_set_state_cb
;
1759 u
->source
->update_requested_latency
= source_update_requested_latency_cb
;
1760 pa_source_set_get_mute_callback(u
->source
, source_get_mute_cb
);
1761 pa_source_set_set_mute_callback(u
->source
, source_set_mute_cb
);
1762 if (!u
->use_volume_sharing
) {
1763 pa_source_set_get_volume_callback(u
->source
, source_get_volume_cb
);
1764 pa_source_set_set_volume_callback(u
->source
, source_set_volume_cb
);
1765 pa_source_enable_decibel_volume(u
->source
, TRUE
);
1767 u
->source
->userdata
= u
;
1769 pa_source_set_asyncmsgq(u
->source
, source_master
->asyncmsgq
);
1772 pa_sink_new_data_init(&sink_data
);
1773 sink_data
.driver
= __FILE__
;
1774 sink_data
.module
= m
;
1775 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1776 sink_data
.name
= pa_sprintf_malloc("%s.echo-cancel", sink_master
->name
);
1777 pa_sink_new_data_set_sample_spec(&sink_data
, &sink_ss
);
1778 pa_sink_new_data_set_channel_map(&sink_data
, &sink_map
);
1779 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, sink_master
->name
);
1780 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1782 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_INTENDED_ROLES
, "phone");
1784 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1785 pa_log("Invalid properties");
1786 pa_sink_new_data_done(&sink_data
);
1790 if ((u
->sink_auto_desc
= !pa_proplist_contains(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
))) {
1793 y
= pa_proplist_gets(source_master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1794 z
= pa_proplist_gets(sink_master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1795 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "%s (echo cancelled with %s)",
1796 z
? z
: sink_master
->name
, y
? y
: source_master
->name
);
1799 u
->sink
= pa_sink_new(m
->core
, &sink_data
, (sink_master
->flags
& (PA_SINK_LATENCY
| PA_SINK_DYNAMIC_LATENCY
))
1800 | (u
->use_volume_sharing
? PA_SINK_SHARE_VOLUME_WITH_MASTER
: 0));
1801 pa_sink_new_data_done(&sink_data
);
1804 pa_log("Failed to create sink.");
1808 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1809 u
->sink
->set_state
= sink_set_state_cb
;
1810 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1811 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1812 pa_sink_set_set_mute_callback(u
->sink
, sink_set_mute_cb
);
1813 if (!u
->use_volume_sharing
) {
1814 pa_sink_set_set_volume_callback(u
->sink
, sink_set_volume_cb
);
1815 pa_sink_enable_decibel_volume(u
->sink
, TRUE
);
1817 u
->sink
->userdata
= u
;
1819 pa_sink_set_asyncmsgq(u
->sink
, sink_master
->asyncmsgq
);
1821 /* Create source output */
1822 pa_source_output_new_data_init(&source_output_data
);
1823 source_output_data
.driver
= __FILE__
;
1824 source_output_data
.module
= m
;
1825 pa_source_output_new_data_set_source(&source_output_data
, source_master
, FALSE
);
1826 source_output_data
.destination_source
= u
->source
;
1828 source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
1830 pa_proplist_sets(source_output_data
.proplist
, PA_PROP_MEDIA_NAME
, "Echo-Cancel Source Stream");
1831 pa_proplist_sets(source_output_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1832 pa_source_output_new_data_set_sample_spec(&source_output_data
, &source_ss
);
1833 pa_source_output_new_data_set_channel_map(&source_output_data
, &source_map
);
1835 pa_source_output_new(&u
->source_output
, m
->core
, &source_output_data
);
1836 pa_source_output_new_data_done(&source_output_data
);
1838 if (!u
->source_output
)
1841 u
->source_output
->parent
.process_msg
= source_output_process_msg_cb
;
1842 u
->source_output
->push
= source_output_push_cb
;
1843 u
->source_output
->process_rewind
= source_output_process_rewind_cb
;
1844 u
->source_output
->update_max_rewind
= source_output_update_max_rewind_cb
;
1845 u
->source_output
->update_source_requested_latency
= source_output_update_source_requested_latency_cb
;
1846 u
->source_output
->update_source_latency_range
= source_output_update_source_latency_range_cb
;
1847 u
->source_output
->update_source_fixed_latency
= source_output_update_source_fixed_latency_cb
;
1848 u
->source_output
->kill
= source_output_kill_cb
;
1849 u
->source_output
->attach
= source_output_attach_cb
;
1850 u
->source_output
->detach
= source_output_detach_cb
;
1851 u
->source_output
->state_change
= source_output_state_change_cb
;
1852 u
->source_output
->may_move_to
= source_output_may_move_to_cb
;
1853 u
->source_output
->moving
= source_output_moving_cb
;
1854 u
->source_output
->userdata
= u
;
1856 u
->source
->output_from_master
= u
->source_output
;
1858 /* Create sink input */
1859 pa_sink_input_new_data_init(&sink_input_data
);
1860 sink_input_data
.driver
= __FILE__
;
1861 sink_input_data
.module
= m
;
1862 pa_sink_input_new_data_set_sink(&sink_input_data
, sink_master
, FALSE
);
1863 sink_input_data
.origin_sink
= u
->sink
;
1864 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Echo-Cancel Sink Stream");
1865 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1866 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &sink_ss
);
1867 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &sink_map
);
1868 sink_input_data
.flags
= PA_SINK_INPUT_VARIABLE_RATE
;
1870 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1871 pa_sink_input_new_data_done(&sink_input_data
);
1876 u
->sink_input
->parent
.process_msg
= sink_input_process_msg_cb
;
1877 u
->sink_input
->pop
= sink_input_pop_cb
;
1878 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1879 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1880 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1881 u
->sink_input
->update_sink_requested_latency
= sink_input_update_sink_requested_latency_cb
;
1882 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1883 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1884 u
->sink_input
->kill
= sink_input_kill_cb
;
1885 u
->sink_input
->attach
= sink_input_attach_cb
;
1886 u
->sink_input
->detach
= sink_input_detach_cb
;
1887 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1888 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1889 u
->sink_input
->moving
= sink_input_moving_cb
;
1890 if (!u
->use_volume_sharing
)
1891 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1892 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1893 u
->sink_input
->userdata
= u
;
1895 u
->sink
->input_to_master
= u
->sink_input
;
1897 pa_sink_input_get_silence(u
->sink_input
, &silence
);
1899 u
->source_memblockq
= pa_memblockq_new("module-echo-cancel source_memblockq", 0, MEMBLOCKQ_MAXLENGTH
, 0,
1900 &source_ss
, 1, 1, 0, &silence
);
1901 u
->sink_memblockq
= pa_memblockq_new("module-echo-cancel sink_memblockq", 0, MEMBLOCKQ_MAXLENGTH
, 0,
1902 &sink_ss
, 1, 1, 0, &silence
);
1904 pa_memblock_unref(silence
.memblock
);
1906 if (!u
->source_memblockq
|| !u
->sink_memblockq
) {
1907 pa_log("Failed to create memblockq.");
1911 if (u
->adjust_time
> 0 && !u
->ec
->params
.drift_compensation
)
1912 u
->time_event
= pa_core_rttime_new(m
->core
, pa_rtclock_now() + u
->adjust_time
, time_callback
, u
);
1913 else if (u
->ec
->params
.drift_compensation
) {
1914 pa_log_info("Canceller does drift compensation -- built-in compensation will be disabled");
1916 /* Perform resync just once to give the canceller a leg up */
1917 pa_atomic_store(&u
->request_resync
, 1);
1921 pa_log("Creating AEC files in /tmp");
1922 u
->captured_file
= fopen("/tmp/aec_rec.sw", "wb");
1923 if (u
->captured_file
== NULL
)
1924 perror ("fopen failed");
1925 u
->played_file
= fopen("/tmp/aec_play.sw", "wb");
1926 if (u
->played_file
== NULL
)
1927 perror ("fopen failed");
1928 u
->canceled_file
= fopen("/tmp/aec_out.sw", "wb");
1929 if (u
->canceled_file
== NULL
)
1930 perror ("fopen failed");
1931 if (u
->ec
->params
.drift_compensation
) {
1932 u
->drift_file
= fopen("/tmp/aec_drift.txt", "w");
1933 if (u
->drift_file
== NULL
)
1934 perror ("fopen failed");
1938 u
->ec
->msg
= pa_msgobject_new(pa_echo_canceller_msg
);
1939 u
->ec
->msg
->parent
.process_msg
= canceller_process_msg_cb
;
1940 u
->ec
->msg
->userdata
= u
;
1942 u
->thread_info
.current_volume
= u
->source
->reference_volume
;
1944 pa_sink_put(u
->sink
);
1945 pa_source_put(u
->source
);
1947 pa_sink_input_put(u
->sink_input
);
1948 pa_source_output_put(u
->source_output
);
1949 pa_modargs_free(ma
);
1955 pa_modargs_free(ma
);
1962 /* Called from main context. */
1963 int pa__get_n_used(pa_module
*m
) {
1967 pa_assert_se(u
= m
->userdata
);
1969 return pa_sink_linked_by(u
->sink
) + pa_source_linked_by(u
->source
);
1972 /* Called from main context. */
1973 void pa__done(pa_module
*m
) {
1978 if (!(u
= m
->userdata
))
1983 /* See comments in source_output_kill_cb() above regarding
1984 * destruction order! */
1987 u
->core
->mainloop
->time_free(u
->time_event
);
1989 if (u
->source_output
)
1990 pa_source_output_unlink(u
->source_output
);
1992 pa_sink_input_unlink(u
->sink_input
);
1995 pa_source_unlink(u
->source
);
1997 pa_sink_unlink(u
->sink
);
1999 if (u
->source_output
)
2000 pa_source_output_unref(u
->source_output
);
2002 pa_sink_input_unref(u
->sink_input
);
2005 pa_source_unref(u
->source
);
2007 pa_sink_unref(u
->sink
);
2009 if (u
->source_memblockq
)
2010 pa_memblockq_free(u
->source_memblockq
);
2011 if (u
->sink_memblockq
)
2012 pa_memblockq_free(u
->sink_memblockq
);
2022 pa_asyncmsgq_unref(u
->asyncmsgq
);
2026 fclose(u
->played_file
);
2027 if (u
->captured_file
)
2028 fclose(u
->captured_file
);
2029 if (u
->canceled_file
)
2030 fclose(u
->canceled_file
);
2032 fclose(u
->drift_file
);
2038 #ifdef ECHO_CANCEL_TEST
2040 * Stand-alone test program for running in the canceller on pre-recorded files.
2042 int main(int argc
, char* argv
[]) {
2044 pa_sample_spec source_ss
, sink_ss
;
2045 pa_channel_map source_map
, sink_map
;
2046 pa_modargs
*ma
= NULL
;
2047 uint8_t *rdata
= NULL
, *pdata
= NULL
, *cdata
= NULL
;
2048 int unused PA_GCC_UNUSED
;
2053 pa_memzero(&u
, sizeof(u
));
2055 if (argc
< 4 || argc
> 7) {
2059 u
.captured_file
= fopen(argv
[2], "rb");
2060 if (u
.captured_file
== NULL
) {
2061 perror ("fopen failed");
2064 u
.played_file
= fopen(argv
[1], "rb");
2065 if (u
.played_file
== NULL
) {
2066 perror ("fopen failed");
2069 u
.canceled_file
= fopen(argv
[3], "wb");
2070 if (u
.canceled_file
== NULL
) {
2071 perror ("fopen failed");
2075 u
.core
= pa_xnew0(pa_core
, 1);
2076 u
.core
->cpu_info
.cpu_type
= PA_CPU_X86
;
2077 u
.core
->cpu_info
.flags
.x86
|= PA_CPU_X86_SSE
;
2079 if (!(ma
= pa_modargs_new(argc
> 4 ? argv
[4] : NULL
, valid_modargs
))) {
2080 pa_log("Failed to parse module arguments.");
2084 source_ss
.format
= PA_SAMPLE_S16LE
;
2085 source_ss
.rate
= DEFAULT_RATE
;
2086 source_ss
.channels
= DEFAULT_CHANNELS
;
2087 pa_channel_map_init_auto(&source_map
, source_ss
.channels
, PA_CHANNEL_MAP_DEFAULT
);
2089 if (init_common(ma
, &u
, &source_ss
, &source_map
) < 0)
2092 if (!u
.ec
->init(u
.core
, u
.ec
, &source_ss
, &source_map
, &sink_ss
, &sink_map
, &u
.blocksize
,
2093 (argc
> 4) ? argv
[5] : NULL
)) {
2094 pa_log("Failed to init AEC engine");
2098 if (u
.ec
->params
.drift_compensation
) {
2100 pa_log("Drift compensation enabled but drift file not specified");
2104 u
.drift_file
= fopen(argv
[6], "rt");
2106 if (u
.drift_file
== NULL
) {
2107 perror ("fopen failed");
2112 rdata
= pa_xmalloc(u
.blocksize
);
2113 pdata
= pa_xmalloc(u
.blocksize
);
2114 cdata
= pa_xmalloc(u
.blocksize
);
2116 if (!u
.ec
->params
.drift_compensation
) {
2117 while (fread(rdata
, u
.blocksize
, 1, u
.captured_file
) > 0) {
2118 if (fread(pdata
, u
.blocksize
, 1, u
.played_file
) == 0) {
2119 perror("Played file ended before captured file");
2123 u
.ec
->run(u
.ec
, rdata
, pdata
, cdata
);
2125 unused
= fwrite(cdata
, u
.blocksize
, 1, u
.canceled_file
);
2128 while (fscanf(u
.drift_file
, "%c", &c
) > 0) {
2131 if (!fscanf(u
.drift_file
, "%a", &drift
)) {
2132 perror("Drift file incomplete");
2136 u
.ec
->set_drift(u
.ec
, drift
);
2141 if (!fscanf(u
.drift_file
, "%d", &i
)) {
2142 perror("Drift file incomplete");
2146 if (fread(rdata
, i
, 1, u
.captured_file
) <= 0) {
2147 perror("Captured file ended prematurely");
2151 u
.ec
->record(u
.ec
, rdata
, cdata
);
2153 unused
= fwrite(cdata
, i
, 1, u
.canceled_file
);
2158 if (!fscanf(u
.drift_file
, "%d", &i
)) {
2159 perror("Drift file incomplete");
2163 if (fread(pdata
, i
, 1, u
.played_file
) <= 0) {
2164 perror("Played file ended prematurely");
2168 u
.ec
->play(u
.ec
, pdata
);
2174 if (fread(rdata
, i
, 1, u
.captured_file
) > 0)
2175 pa_log("All capture data was not consumed");
2176 if (fread(pdata
, i
, 1, u
.played_file
) > 0)
2177 pa_log("All playback data was not consumed");
2183 if (u
.captured_file
)
2184 fclose(u
.captured_file
);
2186 fclose(u
.played_file
);
2187 if (u
.canceled_file
)
2188 fclose(u
.canceled_file
);
2190 fclose(u
.drift_file
);
2200 pa_modargs_free(ma
);
2205 pa_log("Usage: %s play_file rec_file out_file [module args] [aec_args] [drift_file]", argv
[0]);
2211 #endif /* ECHO_CANCEL_TEST */