2 This file is part of PulseAudio.
4 This module is based off Lennart Poettering's LADSPA sink and swaps out
5 LADSPA functionality for a dbus-aware STFT OLA based digital equalizer.
6 All new work is published under PulseAudio's original license.
8 Copyright 2009 Jason Newton <nevion@gmail.com>
11 Copyright 2004-2008 Lennart Poettering
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
15 published by the Free Software Foundation; either version 2.1 of the
16 License, 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
24 License along with PulseAudio; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
42 #include <xmmintrin.h>
43 #include <emmintrin.h>
48 #include <pulse/xmalloc.h>
49 #include <pulse/timeval.h>
51 #include <pulsecore/core-rtclock.h>
52 #include <pulsecore/i18n.h>
53 #include <pulsecore/aupdate.h>
54 #include <pulsecore/namereg.h>
55 #include <pulsecore/sink.h>
56 #include <pulsecore/module.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/modargs.h>
59 #include <pulsecore/log.h>
60 #include <pulsecore/rtpoll.h>
61 #include <pulsecore/sample-util.h>
62 #include <pulsecore/shared.h>
63 #include <pulsecore/idxset.h>
64 #include <pulsecore/strlist.h>
65 #include <pulsecore/database.h>
66 #include <pulsecore/protocol-dbus.h>
67 #include <pulsecore/dbus-util.h>
69 #include "module-equalizer-sink-symdef.h"
71 PA_MODULE_AUTHOR("Jason Newton");
72 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
73 PA_MODULE_VERSION(PACKAGE_VERSION
);
74 PA_MODULE_LOAD_ONCE(false);
76 _("sink_name=<name of the sink> "
77 "sink_properties=<properties for the sink> "
78 "sink_master=<sink to connect to> "
79 "format=<sample format> "
81 "channels=<number of channels> "
82 "channel_map=<channel map> "
83 "autoloaded=<set if this module is being loaded automatically> "
84 "use_volume_sharing=<yes or no> "
87 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
88 #define DEFAULT_AUTOLOADED false
93 pa_sink_input
*sink_input
;
97 size_t fft_size
;//length (res) of fft
100 *effectively chooses R
102 size_t R
;/* the hop size between overlapping windows
103 * the latency of the filter, calculated from window_size
104 * based on constraints of COLA and window function
106 //for twiddling with pulseaudio
107 size_t overlap_size
;//window_size-R
108 size_t samples_gathered
;
109 size_t input_buffer_max
;
111 float *W
;//windowing function (time domain)
112 float *work_buffer
, **input
, **overlap_accum
;
113 fftwf_complex
*output_window
;
114 fftwf_plan forward_plan
, inverse_plan
;
118 float ***Hs
;//thread updatable copies of the freq response filters (magnitude based)
120 pa_memblockq
*input_q
;
122 size_t output_buffer_length
;
123 size_t output_buffer_max_length
;
124 pa_memblockq
*output_q
;
125 bool first_iteration
;
127 pa_dbus_protocol
*dbus_protocol
;
130 pa_database
*database
;
131 char **base_profiles
;
134 static const char* const valid_modargs
[] = {
143 "use_volume_sharing",
148 #define SINKLIST "equalized_sinklist"
149 #define EQDB "equalizer_db"
150 #define EQ_STATE_DB "equalizer-state"
151 #define FILTER_SIZE(u) ((u)->fft_size / 2 + 1)
152 #define CHANNEL_PROFILE_SIZE(u) (FILTER_SIZE(u) + 1)
153 #define FILTER_STATE_SIZE(u) (CHANNEL_PROFILE_SIZE(u) * (u)->channels)
155 static void dbus_init(struct userdata
*u
);
156 static void dbus_done(struct userdata
*u
);
158 static void hanning_window(float *W
, size_t window_size
) {
159 /* h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2 */
160 for (size_t i
= 0; i
< window_size
; ++i
)
161 W
[i
] = (float).5 * (1 - cos(2*M_PI
*i
/ (window_size
+1)));
164 static void fix_filter(float *H
, size_t fft_size
) {
165 /* divide out the fft gain */
166 for (size_t i
= 0; i
< fft_size
/ 2 + 1; ++i
)
170 static void interpolate(float *samples
, size_t length
, uint32_t *xs
, float *ys
, size_t n_points
) {
171 /* Note that xs must be monotonically increasing! */
172 float x_range_lower
, x_range_upper
, c0
;
174 pa_assert(n_points
>= 2);
175 pa_assert(xs
[0] == 0);
176 pa_assert(xs
[n_points
- 1] == length
- 1);
178 for (size_t x
= 0, x_range_lower_i
= 0; x
< length
-1; ++x
) {
179 pa_assert(x_range_lower_i
< n_points
-1);
181 x_range_lower
= (float) xs
[x_range_lower_i
];
182 x_range_upper
= (float) xs
[x_range_lower_i
+1];
184 pa_assert_se(x_range_lower
< x_range_upper
);
185 pa_assert_se(x
>= x_range_lower
);
186 pa_assert_se(x
<= x_range_upper
);
188 /* bilinear-interpolation of coefficients specified */
189 c0
= (x
-x_range_lower
) / (x_range_upper
-x_range_lower
);
190 pa_assert(c0
>= 0 && c0
<= 1.0);
192 samples
[x
] = ((1.0f
- c0
) * ys
[x_range_lower_i
] + c0
* ys
[x_range_lower_i
+ 1]);
193 while(x
>= xs
[x_range_lower_i
+ 1])
197 samples
[length
-1] = ys
[n_points
-1];
200 static bool is_monotonic(const uint32_t *xs
, size_t length
) {
206 for(size_t i
= 1; i
< length
; ++i
)
207 if (xs
[i
] <= xs
[i
-1])
213 /* ensures memory allocated is a multiple of v_size and aligned */
214 static void * alloc(size_t x
, size_t s
) {
218 f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
219 pa_assert_se(t
= fftwf_malloc(f
));
225 static void alloc_input_buffers(struct userdata
*u
, size_t min_buffer_length
) {
226 if (min_buffer_length
<= u
->input_buffer_max
)
229 pa_assert(min_buffer_length
>= u
->window_size
);
230 for (size_t c
= 0; c
< u
->channels
; ++c
) {
231 float *tmp
= alloc(min_buffer_length
, sizeof(float));
233 if (!u
->first_iteration
)
234 memcpy(tmp
, u
->input
[c
], u
->overlap_size
* sizeof(float));
239 u
->input_buffer_max
= min_buffer_length
;
242 /* Called from I/O thread context */
243 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
244 struct userdata
*u
= PA_SINK(o
)->userdata
;
248 case PA_SINK_MESSAGE_GET_LATENCY
: {
249 //size_t fs=pa_frame_size(&u->sink->sample_spec);
251 /* The sink is _put() before the sink input is, so let's
252 * make sure we don't access it in that time. Also, the
253 * sink input is first shut down, the sink second. */
254 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
255 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
256 *((pa_usec_t
*) data
) = 0;
260 *((pa_usec_t
*) data
) =
261 /* Get the latency of the master sink */
262 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
264 /* Add the latency internal to our sink input on top */
265 pa_bytes_to_usec(pa_memblockq_get_length(u
->output_q
) +
266 pa_memblockq_get_length(u
->input_q
), &u
->sink_input
->sink
->sample_spec
) +
267 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
268 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
269 //+ pa_bytes_to_usec(u->latency * fs, ss)
274 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
277 /* Called from main context */
278 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
281 pa_sink_assert_ref(s
);
282 pa_assert_se(u
= s
->userdata
);
284 if (!PA_SINK_IS_LINKED(state
) ||
285 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
288 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
292 /* Called from I/O thread context */
293 static void sink_request_rewind_cb(pa_sink
*s
) {
296 pa_sink_assert_ref(s
);
297 pa_assert_se(u
= s
->userdata
);
299 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
300 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
303 /* Just hand this one over to the master sink */
304 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), true, false, false);
307 /* Called from I/O thread context */
308 static void sink_update_requested_latency_cb(pa_sink
*s
) {
311 pa_sink_assert_ref(s
);
312 pa_assert_se(u
= s
->userdata
);
314 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
315 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
318 /* Just hand this one over to the master sink */
319 pa_sink_input_set_requested_latency_within_thread(
321 pa_sink_get_requested_latency_within_thread(s
));
324 /* Called from main context */
325 static void sink_set_volume_cb(pa_sink
*s
) {
328 pa_sink_assert_ref(s
);
329 pa_assert_se(u
= s
->userdata
);
331 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
332 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
335 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, true);
338 /* Called from main context */
339 static void sink_set_mute_cb(pa_sink
*s
) {
342 pa_sink_assert_ref(s
);
343 pa_assert_se(u
= s
->userdata
);
345 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
346 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
349 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
353 //reference implementation
354 static void dsp_logic(
355 float * restrict dst
,//used as a temp array too, needs to be fft_length!
356 float * restrict src
,/*input data w/ overlap at start,
357 *automatically cycled in routine
359 float * restrict overlap
,
360 const float X
,//multiplier
361 const float * restrict H
,//The freq. magnitude scalers filter
362 const float * restrict W
,//The windowing function
363 fftwf_complex
* restrict output_window
,//The transformed windowed src
364 struct userdata
*u
) {
366 //use a linear-phase sliding STFT and overlap-add method (for each channel)
368 for(size_t j
= 0; j
< u
->window_size
; ++j
) {
369 dst
[j
] = X
* W
[j
] * src
[j
];
371 //zero pad the remaining fft window
372 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
373 //Processing is done here!
375 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
377 for(size_t j
= 0; j
< FILTER_SIZE(u
); ++j
) {
378 u
->output_window
[j
][0] *= H
[j
];
379 u
->output_window
[j
][1] *= H
[j
];
382 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
383 ////debug: tests overlapping add
384 ////and negates ALL PREVIOUS processing
385 ////yields a perfect reconstruction if COLA is held
386 //for(size_t j = 0; j < u->window_size; ++j) {
387 // u->work_buffer[j] = u->W[j] * u->input[c][j];
390 //overlap add and preserve overlap component from this window (linear phase)
391 for(size_t j
= 0; j
< u
->overlap_size
; ++j
) {
392 u
->work_buffer
[j
] += overlap
[j
];
393 overlap
[j
] = dst
[u
->R
+ j
];
395 ////debug: tests if basic buffering works
396 ////shouldn't modify the signal AT ALL (beyond roundoff)
397 //for(size_t j = 0; j < u->window_size;++j) {
398 // u->work_buffer[j] = u->input[c][j];
401 //preserve the needed input for the next window's overlap
402 memmove(src
, src
+ u
->R
,
403 (u
->samples_gathered
- u
->R
) * sizeof(float)
407 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
408 typedef union float_vector
{
414 //regardless of sse enabled, the loops in here assume
415 //16 byte aligned addresses and memory allocations divisible by v_size
416 static void dsp_logic(
417 float * restrict dst
,//used as a temp array too, needs to be fft_length!
418 float * restrict src
,/*input data w/ overlap at start,
419 *automatically cycled in routine
421 float * restrict overlap
,//The size of the overlap
422 const float X
,//multiplier
423 const float * restrict H
,//The freq. magnitude scalers filter
424 const float * restrict W
,//The windowing function
425 fftwf_complex
* restrict output_window
,//The transformed windowed src
426 struct userdata
*u
) {//Collection of constants
427 const size_t overlap_size
= PA_ROUND_UP(u
->overlap_size
, v_size
);
429 x
.f
[0] = x
.f
[1] = x
.f
[2] = x
.f
[3] = X
;
431 //assert(u->samples_gathered >= u->R);
432 //use a linear-phase sliding STFT and overlap-add method
433 for(size_t j
= 0; j
< u
->window_size
; j
+= v_size
) {
434 //dst[j] = W[j] * src[j];
435 float_vector_t
*d
= (float_vector_t
*) (dst
+ j
);
436 float_vector_t
*w
= (float_vector_t
*) (W
+ j
);
437 float_vector_t
*s
= (float_vector_t
*) (src
+ j
);
439 d
->m
= _mm_mul_ps(x
.m
, _mm_mul_ps(w
->m
, s
->m
));
440 // d->v = x->v * w->v * s->v;
443 //zero pad the remaining fft window
444 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
446 //Processing is done here!
448 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
449 //perform filtering - purely magnitude based
450 for(size_t j
= 0; j
< FILTER_SIZE
; j
+= v_size
/ 2) {
451 //output_window[j][0]*=H[j];
452 //output_window[j][1]*=H[j];
453 float_vector_t
*d
= (float_vector_t
*)( ((float *) output_window
) + 2 * j
);
455 h
.f
[0] = h
.f
[1] = H
[j
];
456 h
.f
[2] = h
.f
[3] = H
[j
+ 1];
458 d
->m
= _mm_mul_ps(d
->m
, h
.m
);
460 // d->v = d->v * h.v;
465 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
467 ////debug: tests overlapping add
468 ////and negates ALL PREVIOUS processing
469 ////yields a perfect reconstruction if COLA is held
470 //for(size_t j = 0; j < u->window_size; ++j) {
471 // dst[j] = W[j] * src[j];
474 //overlap add and preserve overlap component from this window (linear phase)
475 for(size_t j
= 0; j
< overlap_size
; j
+= v_size
) {
476 //dst[j]+=overlap[j];
477 //overlap[j]+=dst[j+R];
478 float_vector_t
*d
= (float_vector_t
*)(dst
+ j
);
479 float_vector_t
*o
= (float_vector_t
*)(overlap
+ j
);
481 d
->m
= _mm_add_ps(d
->m
, o
->m
);
482 o
->m
= ((float_vector_t
*)(dst
+ u
->R
+ j
))->m
;
484 // d->v = d->v + o->v;
485 // o->v = ((float_vector_t*)(dst + u->R + j))->v;
488 //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
489 //zero out the bit beyond the real overlap so we don't add garbage next iteration
490 memset(overlap
+ u
->overlap_size
, 0, overlap_size
- u
->overlap_size
);
492 ////debug: tests if basic buffering works
493 ////shouldn't modify the signal AT ALL (beyond roundoff)
494 //for(size_t j = 0; j < u->window_size; ++j) {
498 //preserve the needed input for the next window's overlap
499 memmove(src
, src
+ u
->R
,
500 (u
->samples_gathered
- u
->R
) * sizeof(float)
505 static void flatten_to_memblockq(struct userdata
*u
) {
506 size_t mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
510 while(i
< u
->output_buffer_length
) {
512 tchunk
.length
= PA_MIN((u
->output_buffer_length
- i
), mbs
);
513 tchunk
.memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
.length
);
514 //pa_log_debug("pushing %ld into the q", tchunk.length);
515 dst
= pa_memblock_acquire(tchunk
.memblock
);
516 memcpy(dst
, u
->output_buffer
+ i
, tchunk
.length
);
517 pa_memblock_release(tchunk
.memblock
);
518 pa_memblockq_push(u
->output_q
, &tchunk
);
519 pa_memblock_unref(tchunk
.memblock
);
524 static void process_samples(struct userdata
*u
) {
525 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
528 size_t iterations
, offset
;
529 pa_assert(u
->samples_gathered
>= u
->window_size
);
530 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
531 //make sure there is enough buffer memory allocated
532 if (iterations
* u
->R
* fs
> u
->output_buffer_max_length
) {
533 u
->output_buffer_max_length
= iterations
* u
->R
* fs
;
534 pa_xfree(u
->output_buffer
);
535 u
->output_buffer
= pa_xmalloc(u
->output_buffer_max_length
);
537 u
->output_buffer_length
= iterations
* u
->R
* fs
;
539 for(size_t iter
= 0; iter
< iterations
; ++iter
) {
540 offset
= iter
* u
->R
* fs
;
541 for(size_t c
= 0;c
< u
->channels
; c
++) {
542 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
555 pa_aupdate_read_end(u
->a_H
[c
]);
556 if (u
->first_iteration
) {
557 /* The windowing function will make the audio ramped in, as a cheap fix we can
558 * undo the windowing (for non-zero window values)
560 for(size_t i
= 0; i
< u
->overlap_size
; ++i
) {
561 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
564 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (((float *)u
->output_buffer
) + c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
566 if (u
->first_iteration
) {
567 u
->first_iteration
= false;
569 u
->samples_gathered
-= u
->R
;
571 flatten_to_memblockq(u
);
574 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
) {
575 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
576 size_t samples
= in
->length
/fs
;
577 float *src
= pa_memblock_acquire_chunk(in
);
578 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
579 for(size_t c
= 0; c
< u
->channels
; c
++) {
580 //buffer with an offset after the overlap from previous
583 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
585 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
587 u
->samples_gathered
+= samples
;
588 pa_memblock_release(in
->memblock
);
591 /* Called from I/O thread context */
592 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
594 size_t fs
, target_samples
;
596 //struct timeval start, end;
599 pa_sink_input_assert_ref(i
);
600 pa_assert_se(u
= i
->userdata
);
604 /* FIXME: Please clean this up. I see more commented code lines
605 * than uncommented code lines. I am sorry, but I am too dumb to
606 * understand this. */
608 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
609 mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
610 if (pa_memblockq_get_length(u
->output_q
) > 0) {
611 //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
614 //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
615 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
616 ////pa_log_debug("vanilla mbs = %ld",mbs);
617 //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
618 //mbs = PA_MAX(mbs, u->R);
619 //target_samples = PA_MAX(target_samples, mbs);
620 //pa_log_debug("target samples: %ld", target_samples);
621 if (u
->first_iteration
) {
622 //allocate request_size
623 target_samples
= PA_MAX(target_samples
, u
->window_size
);
625 //allocate request_size + overlap
626 target_samples
+= u
->overlap_size
;
628 alloc_input_buffers(u
, target_samples
);
629 //pa_log_debug("post target samples: %ld", target_samples);
630 chunk
->memblock
= NULL
;
632 /* Hmm, process any rewind request that might be queued up */
633 pa_sink_process_rewind(u
->sink
, 0);
635 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
636 //pa_rtclock_get(&start);
638 size_t input_remaining
= target_samples
- u
->samples_gathered
;
639 // pa_log_debug("input remaining %ld samples", input_remaining);
640 pa_assert(input_remaining
> 0);
641 while (pa_memblockq_peek(u
->input_q
, &tchunk
) < 0) {
642 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
643 pa_sink_render_full(u
->sink
, PA_MIN(input_remaining
* fs
, mbs
), &tchunk
);
644 pa_memblockq_push(u
->input_q
, &tchunk
);
645 pa_memblock_unref(tchunk
.memblock
);
647 pa_assert(tchunk
.memblock
);
649 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
651 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
652 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
654 //pa_rtclock_get(start);
655 // pa_log_debug("buffering %ld bytes", tchunk.length);
656 input_buffer(u
, &tchunk
);
657 //pa_rtclock_get(&end);
658 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
659 pa_memblock_unref(tchunk
.memblock
);
660 } while(u
->samples_gathered
< target_samples
);
662 //pa_rtclock_get(&end);
663 //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
665 pa_assert(u
->fft_size
>= u
->window_size
);
666 pa_assert(u
->R
< u
->window_size
);
667 //pa_rtclock_get(&start);
668 /* process a block */
670 //pa_rtclock_get(&end);
671 //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
673 pa_assert_se(pa_memblockq_peek(u
->output_q
, chunk
) >= 0);
674 pa_assert(chunk
->memblock
);
675 pa_memblockq_drop(u
->output_q
, chunk
->length
);
677 /** FIXME: Uh? you need to unref the chunk here! */
679 //pa_log_debug("gave %ld", chunk->length/fs);
680 //pa_log_debug("end pop");
684 /* Called from main context */
685 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
688 pa_sink_input_assert_ref(i
);
689 pa_assert_se(u
= i
->userdata
);
691 pa_sink_volume_changed(u
->sink
, &i
->volume
);
694 /* Called from main context */
695 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
698 pa_sink_input_assert_ref(i
);
699 pa_assert_se(u
= i
->userdata
);
701 pa_sink_mute_changed(u
->sink
, i
->muted
);
705 static void reset_filter(struct userdata
*u
) {
706 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
709 u
->samples_gathered
= 0;
711 for(size_t i
= 0; i
< u
->channels
; ++i
)
712 pa_memzero(u
->overlap_accum
[i
], u
->overlap_size
* sizeof(float));
714 u
->first_iteration
= true;
715 //set buffer size to max request, no overlap copy
716 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
717 max_request
= PA_MAX(max_request
, u
->window_size
);
718 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
722 /* Called from I/O thread context */
723 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
727 pa_log_debug("Rewind callback!");
728 pa_sink_input_assert_ref(i
);
729 pa_assert_se(u
= i
->userdata
);
731 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
734 //max_rewrite = nbytes;
735 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
736 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
737 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
738 u
->sink
->thread_info
.rewind_nbytes
= 0;
741 //invalidate the output q
742 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, true);
743 pa_log("Resetting filter");
744 //reset_filter(u); //this is the "proper" thing to do...
748 pa_sink_process_rewind(u
->sink
, amount
);
749 pa_memblockq_rewind(u
->input_q
, nbytes
);
752 /* Called from I/O thread context */
753 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
756 pa_sink_input_assert_ref(i
);
757 pa_assert_se(u
= i
->userdata
);
759 /* FIXME: Too small max_rewind:
760 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
761 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
762 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
765 /* Called from I/O thread context */
766 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
770 pa_sink_input_assert_ref(i
);
771 pa_assert_se(u
= i
->userdata
);
773 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
774 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
777 /* Called from I/O thread context */
778 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
781 pa_sink_input_assert_ref(i
);
782 pa_assert_se(u
= i
->userdata
);
784 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
787 /* Called from I/O thread context */
788 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
791 pa_sink_input_assert_ref(i
);
792 pa_assert_se(u
= i
->userdata
);
794 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
797 /* Called from I/O thread context */
798 static void sink_input_detach_cb(pa_sink_input
*i
) {
801 pa_sink_input_assert_ref(i
);
802 pa_assert_se(u
= i
->userdata
);
804 pa_sink_detach_within_thread(u
->sink
);
806 pa_sink_set_rtpoll(u
->sink
, NULL
);
809 /* Called from I/O thread context */
810 static void sink_input_attach_cb(pa_sink_input
*i
) {
812 size_t fs
, max_request
;
814 pa_sink_input_assert_ref(i
);
815 pa_assert_se(u
= i
->userdata
);
817 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
818 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
819 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
821 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
822 /* set buffer size to max request, no overlap copy */
823 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
824 max_request
= PA_MAX(max_request
, u
->window_size
);
826 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
828 /* FIXME: Too small max_rewind:
829 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
830 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
832 pa_sink_attach_within_thread(u
->sink
);
835 /* Called from main context */
836 static void sink_input_kill_cb(pa_sink_input
*i
) {
839 pa_sink_input_assert_ref(i
);
840 pa_assert_se(u
= i
->userdata
);
842 /* The order here matters! We first kill the sink input, followed
843 * by the sink. That means the sink callbacks must be protected
844 * against an unconnected sink input! */
845 pa_sink_input_unlink(u
->sink_input
);
846 pa_sink_unlink(u
->sink
);
848 pa_sink_input_unref(u
->sink_input
);
849 u
->sink_input
= NULL
;
851 /* Leave u->sink alone for now, it will be cleaned up on module
852 * unload (and it is needed during unload as well). */
854 pa_module_unload_request(u
->module
, true);
857 /* Called from IO thread context */
858 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
861 pa_sink_input_assert_ref(i
);
862 pa_assert_se(u
= i
->userdata
);
864 /* If we are added for the first time, ask for a rewinding so that
865 * we are heard right-away. */
866 if (PA_SINK_INPUT_IS_LINKED(state
) &&
867 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
868 pa_log_debug("Requesting rewind due to state change.");
869 pa_sink_input_request_rewind(i
, 0, false, true, true);
873 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
) {
875 size_t headers
= (1+len
) * sizeof(uint16_t);
877 for(size_t i
= 0; i
< len
; ++i
) {
878 t_len
+= strlen(strs
[i
]);
880 *length
= headers
+ t_len
;
881 p
= *packed
= pa_xmalloc0(*length
);
882 *((uint16_t *) p
) = (uint16_t) len
;
883 p
+= sizeof(uint16_t);
884 for(size_t i
= 0; i
< len
; ++i
) {
885 uint16_t l
= strlen(strs
[i
]);
886 *((uint16_t *) p
) = (uint16_t) l
;
887 p
+= sizeof(uint16_t);
888 memcpy(p
, strs
[i
], l
);
892 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
) {
894 *len
= *((uint16_t *) p
);
895 p
+= sizeof(uint16_t);
896 *strs
= pa_xnew(char *, *len
);
898 for(size_t i
= 0; i
< *len
; ++i
) {
899 size_t l
= *((uint16_t *) p
);
900 p
+= sizeof(uint16_t);
901 (*strs
)[i
] = pa_xnew(char, l
+ 1);
902 memcpy((*strs
)[i
], p
, l
);
903 (*strs
)[i
][l
] = '\0';
907 static void save_profile(struct userdata
*u
, size_t channel
, char *name
) {
909 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
910 float *H_n
, *profile
;
913 profile
= pa_xnew0(float, profile_size
);
914 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
915 profile
[0] = u
->Xs
[a_i
][channel
];
916 H
= u
->Hs
[channel
][a_i
];
918 for(size_t i
= 0 ; i
< FILTER_SIZE(u
); ++i
) {
919 H_n
[i
] = H
[i
] * u
->fft_size
;
922 pa_aupdate_read_end(u
->a_H
[channel
]);
924 key
.size
= strlen(key
.data
);
926 data
.size
= profile_size
;
927 pa_database_set(u
->database
, &key
, &data
, true);
928 pa_database_sync(u
->database
);
929 if (u
->base_profiles
[channel
]) {
930 pa_xfree(u
->base_profiles
[channel
]);
932 u
->base_profiles
[channel
] = pa_xstrdup(name
);
935 static void save_state(struct userdata
*u
) {
937 const size_t filter_state_size
= FILTER_STATE_SIZE(u
) * sizeof(float);
941 pa_database
*database
;
944 size_t packed_length
;
946 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
947 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
948 memcpy(state
+ FILTER_STATE_SIZE(u
), packed
, packed_length
);
951 for(size_t c
= 0; c
< u
->channels
; ++c
) {
952 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
953 state
[c
* CHANNEL_PROFILE_SIZE(u
)] = u
->Xs
[c
][a_i
];
955 H_n
= &state
[c
* CHANNEL_PROFILE_SIZE(u
) + 1];
956 memcpy(H_n
, H
, FILTER_SIZE(u
) * sizeof(float));
957 pa_aupdate_read_end(u
->a_H
[c
]);
960 key
.data
= u
->sink
->name
;
961 key
.size
= strlen(key
.data
);
963 data
.size
= filter_state_size
+ packed_length
;
964 //thread safety for 0.9.17?
965 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, false));
966 pa_assert_se(database
= pa_database_open(dbname
, true));
969 pa_database_set(database
, &key
, &data
, true);
970 pa_database_sync(database
);
971 pa_database_close(database
);
975 static void remove_profile(pa_core
*c
, char *name
) {
977 pa_database
*database
;
979 key
.size
= strlen(key
.data
);
980 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
981 pa_database_unset(database
, &key
);
982 pa_database_sync(database
);
985 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
) {
988 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
990 key
.size
= strlen(key
.data
);
991 if (pa_database_get(u
->database
, &key
, &value
) != NULL
) {
992 if (value
.size
== profile_size
) {
993 float *profile
= (float *) value
.data
;
994 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
995 u
->Xs
[channel
][a_i
] = profile
[0];
996 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE(u
) * sizeof(float));
997 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
998 pa_aupdate_write_end(u
->a_H
[channel
]);
999 pa_xfree(u
->base_profiles
[channel
]);
1000 u
->base_profiles
[channel
] = pa_xstrdup(name
);
1002 return "incompatible size";
1004 pa_datum_free(&value
);
1006 return "profile doesn't exist";
1011 static void load_state(struct userdata
*u
) {
1014 pa_datum key
, value
;
1015 pa_database
*database
;
1017 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, false));
1018 database
= pa_database_open(dbname
, false);
1021 pa_log("No resume state");
1025 key
.data
= u
->sink
->name
;
1026 key
.size
= strlen(key
.data
);
1028 if (pa_database_get(database
, &key
, &value
) != NULL
) {
1029 if (value
.size
> FILTER_STATE_SIZE(u
) * sizeof(float) + sizeof(uint16_t)) {
1030 float *state
= (float *) value
.data
;
1033 for(size_t c
= 0; c
< u
->channels
; ++c
) {
1034 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1035 H
= state
+ c
* CHANNEL_PROFILE_SIZE(u
) + 1;
1036 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE(u
)];
1037 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE(u
) * sizeof(float));
1038 pa_aupdate_write_end(u
->a_H
[c
]);
1040 unpack(((char *)value
.data
) + FILTER_STATE_SIZE(u
) * sizeof(float), value
.size
- FILTER_STATE_SIZE(u
) * sizeof(float), &names
, &n_profs
);
1041 n_profs
= PA_MIN(n_profs
, u
->channels
);
1042 for(size_t c
= 0; c
< n_profs
; ++c
) {
1043 pa_xfree(u
->base_profiles
[c
]);
1044 u
->base_profiles
[c
] = names
[c
];
1048 pa_datum_free(&value
);
1050 pa_log("resume state exists but is wrong size!");
1052 pa_database_close(database
);
1055 /* Called from main context */
1056 static bool sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1059 pa_sink_input_assert_ref(i
);
1060 pa_assert_se(u
= i
->userdata
);
1065 return u
->sink
!= dest
;
1068 /* Called from main context */
1069 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1072 pa_sink_input_assert_ref(i
);
1073 pa_assert_se(u
= i
->userdata
);
1076 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1077 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1079 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1082 int pa__init(pa_module
*m
) {
1089 pa_sink_input_new_data sink_input_data
;
1090 pa_sink_new_data sink_data
;
1095 bool use_volume_sharing
= true;
1099 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1100 pa_log("Failed to parse module arguments.");
1104 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "sink_master", NULL
), PA_NAMEREG_SINK
))) {
1105 pa_log("Master sink not found");
1109 ss
= master
->sample_spec
;
1110 ss
.format
= PA_SAMPLE_FLOAT32
;
1111 map
= master
->channel_map
;
1112 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1113 pa_log("Invalid sample format specification or channel map");
1117 //fs = pa_frame_size(&ss);
1119 if (pa_modargs_get_value_boolean(ma
, "use_volume_sharing", &use_volume_sharing
) < 0) {
1120 pa_log("use_volume_sharing= expects a boolean argument");
1124 u
= pa_xnew0(struct userdata
, 1);
1128 u
->channels
= ss
.channels
;
1129 u
->fft_size
= pow(2, ceil(log(ss
.rate
) / log(2)));//probably unstable near corner cases of powers of 2
1130 pa_log_debug("fft size: %zd", u
->fft_size
);
1131 u
->window_size
= 15999;
1132 if (u
->window_size
% 2 == 0)
1134 u
->R
= (u
->window_size
+ 1) / 2;
1135 u
->overlap_size
= u
->window_size
- u
->R
;
1136 u
->samples_gathered
= 0;
1137 u
->input_buffer_max
= 0;
1139 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1140 u
->Xs
= pa_xnew0(float *, u
->channels
);
1141 u
->Hs
= pa_xnew0(float **, u
->channels
);
1143 for (c
= 0; c
< u
->channels
; ++c
) {
1144 u
->Xs
[c
] = pa_xnew0(float, 2);
1145 u
->Hs
[c
] = pa_xnew0(float *, 2);
1146 for (i
= 0; i
< 2; ++i
)
1147 u
->Hs
[c
][i
] = alloc(FILTER_SIZE(u
), sizeof(float));
1150 u
->W
= alloc(u
->window_size
, sizeof(float));
1151 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1152 u
->input
= pa_xnew0(float *, u
->channels
);
1153 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1154 for (c
= 0; c
< u
->channels
; ++c
) {
1155 u
->a_H
[c
] = pa_aupdate_new();
1157 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1159 u
->output_window
= alloc(FILTER_SIZE(u
), sizeof(fftwf_complex
));
1160 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1161 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1163 hanning_window(u
->W
, u
->window_size
);
1164 u
->first_iteration
= true;
1166 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1167 for (c
= 0; c
< u
->channels
; ++c
)
1168 u
->base_profiles
[c
] = pa_xstrdup("default");
1171 pa_sink_new_data_init(&sink_data
);
1172 sink_data
.driver
= __FILE__
;
1173 sink_data
.module
= m
;
1174 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1175 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1176 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1177 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1179 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1180 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s", z
? z
: master
->name
);
1182 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1183 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1185 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1186 pa_log("Invalid properties");
1187 pa_sink_new_data_done(&sink_data
);
1191 u
->autoloaded
= DEFAULT_AUTOLOADED
;
1192 if (pa_modargs_get_value_boolean(ma
, "autoloaded", &u
->autoloaded
) < 0) {
1193 pa_log("Failed to parse autoloaded value");
1197 u
->sink
= pa_sink_new(m
->core
, &sink_data
, (master
->flags
& (PA_SINK_LATENCY
| PA_SINK_DYNAMIC_LATENCY
))
1198 | (use_volume_sharing
? PA_SINK_SHARE_VOLUME_WITH_MASTER
: 0));
1199 pa_sink_new_data_done(&sink_data
);
1202 pa_log("Failed to create sink.");
1206 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1207 u
->sink
->set_state
= sink_set_state_cb
;
1208 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1209 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1210 pa_sink_set_set_mute_callback(u
->sink
, sink_set_mute_cb
);
1211 if (!use_volume_sharing
) {
1212 pa_sink_set_set_volume_callback(u
->sink
, sink_set_volume_cb
);
1213 pa_sink_enable_decibel_volume(u
->sink
, true);
1215 u
->sink
->userdata
= u
;
1217 u
->input_q
= pa_memblockq_new("module-equalizer-sink input_q", 0, MEMBLOCKQ_MAXLENGTH
, 0, &ss
, 1, 1, 0, &u
->sink
->silence
);
1218 u
->output_q
= pa_memblockq_new("module-equalizer-sink output_q", 0, MEMBLOCKQ_MAXLENGTH
, 0, &ss
, 1, 1, 0, NULL
);
1219 u
->output_buffer
= NULL
;
1220 u
->output_buffer_length
= 0;
1221 u
->output_buffer_max_length
= 0;
1223 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1224 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1226 /* Create sink input */
1227 pa_sink_input_new_data_init(&sink_input_data
);
1228 sink_input_data
.driver
= __FILE__
;
1229 sink_input_data
.module
= m
;
1230 pa_sink_input_new_data_set_sink(&sink_input_data
, master
, false);
1231 sink_input_data
.origin_sink
= u
->sink
;
1232 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1233 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1234 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1235 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1237 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1238 pa_sink_input_new_data_done(&sink_input_data
);
1243 u
->sink_input
->pop
= sink_input_pop_cb
;
1244 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1245 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1246 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1247 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1248 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1249 u
->sink_input
->kill
= sink_input_kill_cb
;
1250 u
->sink_input
->attach
= sink_input_attach_cb
;
1251 u
->sink_input
->detach
= sink_input_detach_cb
;
1252 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1253 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1254 u
->sink_input
->moving
= sink_input_moving_cb
;
1255 if (!use_volume_sharing
)
1256 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1257 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1258 u
->sink_input
->userdata
= u
;
1260 u
->sink
->input_to_master
= u
->sink_input
;
1264 /* default filter to these */
1265 for (c
= 0; c
< u
->channels
; ++c
) {
1266 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1268 u
->Xs
[c
][a_i
] = 1.0f
;
1270 for(i
= 0; i
< FILTER_SIZE(u
); ++i
)
1271 H
[i
] = 1.0 / sqrtf(2.0f
);
1273 fix_filter(H
, u
->fft_size
);
1274 pa_aupdate_write_end(u
->a_H
[c
]);
1277 /* load old parameters */
1280 pa_sink_put(u
->sink
);
1281 pa_sink_input_put(u
->sink_input
);
1283 pa_modargs_free(ma
);
1289 pa_modargs_free(ma
);
1296 int pa__get_n_used(pa_module
*m
) {
1300 pa_assert_se(u
= m
->userdata
);
1302 return pa_sink_linked_by(u
->sink
);
1305 void pa__done(pa_module
*m
) {
1311 if (!(u
= m
->userdata
))
1318 for(c
= 0; c
< u
->channels
; ++c
)
1319 pa_xfree(u
->base_profiles
[c
]);
1320 pa_xfree(u
->base_profiles
);
1322 /* See comments in sink_input_kill_cb() above regarding
1323 * destruction order! */
1326 pa_sink_input_unlink(u
->sink_input
);
1329 pa_sink_unlink(u
->sink
);
1332 pa_sink_input_unref(u
->sink_input
);
1335 pa_sink_unref(u
->sink
);
1337 pa_xfree(u
->output_buffer
);
1338 pa_memblockq_free(u
->output_q
);
1339 pa_memblockq_free(u
->input_q
);
1341 fftwf_destroy_plan(u
->inverse_plan
);
1342 fftwf_destroy_plan(u
->forward_plan
);
1343 pa_xfree(u
->output_window
);
1344 for (c
= 0; c
< u
->channels
; ++c
) {
1345 pa_aupdate_free(u
->a_H
[c
]);
1346 pa_xfree(u
->overlap_accum
[c
]);
1347 pa_xfree(u
->input
[c
]);
1350 pa_xfree(u
->overlap_accum
);
1352 pa_xfree(u
->work_buffer
);
1354 for (c
= 0; c
< u
->channels
; ++c
) {
1356 for (size_t i
= 0; i
< 2; ++i
)
1357 pa_xfree(u
->Hs
[c
][i
]);
1367 * DBus Routines and Callbacks
1369 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1370 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1371 #define MANAGER_IFACE EXTNAME ".Manager"
1372 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1373 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1374 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1375 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1376 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1377 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1378 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1379 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1380 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1381 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1382 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1383 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1384 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1385 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1386 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1387 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1388 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1389 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1390 static void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1391 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1392 enum manager_method_index
{
1393 MANAGER_METHOD_REMOVE_PROFILE
,
1397 pa_dbus_arg_info remove_profile_args
[]={
1401 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1402 [MANAGER_METHOD_REMOVE_PROFILE
]={
1403 .method_name
="RemoveProfile",
1404 .arguments
=remove_profile_args
,
1405 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1406 .receive_cb
=manager_handle_remove_profile
}
1409 enum manager_handler_index
{
1410 MANAGER_HANDLER_REVISION
,
1411 MANAGER_HANDLER_EQUALIZED_SINKS
,
1412 MANAGER_HANDLER_PROFILES
,
1416 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1417 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1418 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1419 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1422 pa_dbus_arg_info sink_args
[]={
1426 enum manager_signal_index
{
1427 MANAGER_SIGNAL_SINK_ADDED
,
1428 MANAGER_SIGNAL_SINK_REMOVED
,
1429 MANAGER_SIGNAL_PROFILES_CHANGED
,
1433 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1434 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1435 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1436 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1439 static pa_dbus_interface_info manager_info
={
1440 .name
=MANAGER_IFACE
,
1441 .method_handlers
=manager_methods
,
1442 .n_method_handlers
=MANAGER_METHOD_MAX
,
1443 .property_handlers
=manager_handlers
,
1444 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1445 .get_all_properties_cb
=manager_get_all
,
1446 .signals
=manager_signals
,
1447 .n_signals
=MANAGER_SIGNAL_MAX
1450 enum equalizer_method_index
{
1451 EQUALIZER_METHOD_FILTER_POINTS
,
1452 EQUALIZER_METHOD_SEED_FILTER
,
1453 EQUALIZER_METHOD_SAVE_PROFILE
,
1454 EQUALIZER_METHOD_LOAD_PROFILE
,
1455 EQUALIZER_METHOD_SET_FILTER
,
1456 EQUALIZER_METHOD_GET_FILTER
,
1457 EQUALIZER_METHOD_SAVE_STATE
,
1458 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1459 EQUALIZER_METHOD_MAX
1462 enum equalizer_handler_index
{
1463 EQUALIZER_HANDLER_REVISION
,
1464 EQUALIZER_HANDLER_SAMPLERATE
,
1465 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1466 EQUALIZER_HANDLER_N_COEFS
,
1467 EQUALIZER_HANDLER_N_CHANNELS
,
1468 EQUALIZER_HANDLER_MAX
1471 pa_dbus_arg_info filter_points_args
[]={
1472 {"channel", "u","in"},
1475 {"preamp", "d","out"}
1477 pa_dbus_arg_info seed_filter_args
[]={
1478 {"channel", "u","in"},
1481 {"preamp", "d","in"}
1484 pa_dbus_arg_info set_filter_args
[]={
1485 {"channel", "u","in"},
1487 {"preamp", "d","in"}
1489 pa_dbus_arg_info get_filter_args
[]={
1490 {"channel", "u","in"},
1492 {"preamp", "d","out"}
1495 pa_dbus_arg_info save_profile_args
[]={
1496 {"channel", "u","in"},
1499 pa_dbus_arg_info load_profile_args
[]={
1500 {"channel", "u","in"},
1503 pa_dbus_arg_info base_profile_name_args
[]={
1504 {"channel", "u","in"},
1508 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1509 [EQUALIZER_METHOD_SEED_FILTER
]={
1510 .method_name
="SeedFilter",
1511 .arguments
=seed_filter_args
,
1512 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1513 .receive_cb
=equalizer_handle_seed_filter
},
1514 [EQUALIZER_METHOD_FILTER_POINTS
]={
1515 .method_name
="FilterAtPoints",
1516 .arguments
=filter_points_args
,
1517 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1518 .receive_cb
=equalizer_handle_get_filter_points
},
1519 [EQUALIZER_METHOD_SET_FILTER
]={
1520 .method_name
="SetFilter",
1521 .arguments
=set_filter_args
,
1522 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1523 .receive_cb
=equalizer_handle_set_filter
},
1524 [EQUALIZER_METHOD_GET_FILTER
]={
1525 .method_name
="GetFilter",
1526 .arguments
=get_filter_args
,
1527 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1528 .receive_cb
=equalizer_handle_get_filter
},
1529 [EQUALIZER_METHOD_SAVE_PROFILE
]={
1530 .method_name
="SaveProfile",
1531 .arguments
=save_profile_args
,
1532 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1533 .receive_cb
=equalizer_handle_save_profile
},
1534 [EQUALIZER_METHOD_LOAD_PROFILE
]={
1535 .method_name
="LoadProfile",
1536 .arguments
=load_profile_args
,
1537 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1538 .receive_cb
=equalizer_handle_load_profile
},
1539 [EQUALIZER_METHOD_SAVE_STATE
]={
1540 .method_name
="SaveState",
1543 .receive_cb
=equalizer_handle_save_state
},
1544 [EQUALIZER_METHOD_GET_PROFILE_NAME
]={
1545 .method_name
="BaseProfile",
1546 .arguments
=base_profile_name_args
,
1547 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1548 .receive_cb
=equalizer_handle_get_profile_name
}
1551 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1552 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1553 [EQUALIZER_HANDLER_SAMPLERATE
]={.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1554 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]={.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1555 [EQUALIZER_HANDLER_N_COEFS
]={.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1556 [EQUALIZER_HANDLER_N_CHANNELS
]={.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1559 enum equalizer_signal_index
{
1560 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1561 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1562 EQUALIZER_SIGNAL_MAX
1565 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1566 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1567 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1570 static pa_dbus_interface_info equalizer_info
={
1571 .name
=EQUALIZER_IFACE
,
1572 .method_handlers
=equalizer_methods
,
1573 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1574 .property_handlers
=equalizer_handlers
,
1575 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1576 .get_all_properties_cb
=equalizer_get_all
,
1577 .signals
=equalizer_signals
,
1578 .n_signals
=EQUALIZER_SIGNAL_MAX
1581 void dbus_init(struct userdata
*u
) {
1583 DBusMessage
*message
= NULL
;
1584 pa_idxset
*sink_list
= NULL
;
1585 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1586 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1588 pa_assert_se(pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
) >= 0);
1589 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1590 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1591 if (sink_list
== NULL
) {
1593 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1594 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1595 pa_assert_se(dbname
= pa_state_path("equalizer-presets", false));
1596 pa_assert_se(u
->database
= pa_database_open(dbname
, true));
1598 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1599 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1600 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1602 pa_idxset_put(sink_list
, u
, &dummy
);
1604 pa_assert_se((message
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1605 dbus_message_append_args(message
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1606 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
1607 dbus_message_unref(message
);
1610 void dbus_done(struct userdata
*u
) {
1611 pa_idxset
*sink_list
;
1614 DBusMessage
*message
= NULL
;
1615 pa_assert_se((message
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1616 dbus_message_append_args(message
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1617 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
1618 dbus_message_unref(message
);
1620 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1621 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1622 if (pa_idxset_size(sink_list
)==0) {
1623 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1624 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1625 pa_shared_remove(u
->sink
->core
, EQDB
);
1626 pa_database_close(u
->database
);
1627 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1628 pa_xfree(sink_list
);
1630 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1631 pa_xfree(u
->dbus_path
);
1632 pa_dbus_protocol_unref(u
->dbus_protocol
);
1635 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1637 pa_core
*c
= (pa_core
*)_u
;
1638 DBusMessage
*message
= NULL
;
1639 pa_dbus_protocol
*dbus_protocol
;
1644 dbus_error_init(&error
);
1645 if (!dbus_message_get_args(msg
, &error
,
1646 DBUS_TYPE_STRING
, &name
,
1647 DBUS_TYPE_INVALID
)) {
1648 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1649 dbus_error_free(&error
);
1652 remove_profile(c
,name
);
1653 pa_dbus_send_empty_reply(conn
, msg
);
1655 pa_assert_se((message
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1656 dbus_protocol
= pa_dbus_protocol_get(c
);
1657 pa_dbus_protocol_send_signal(dbus_protocol
, message
);
1658 pa_dbus_protocol_unref(dbus_protocol
);
1659 dbus_message_unref(message
);
1662 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1664 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1667 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
) {
1669 struct userdata
*sink_u
= NULL
;
1671 pa_idxset
*sink_list
;
1676 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1677 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1678 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1679 for(uint32_t i
= 0; i
< *n_sinks
; ++i
) {
1680 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1681 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1685 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1687 char **names
= NULL
;
1692 get_sinks((pa_core
*) _u
, &names
, &n
);
1693 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1694 for(unsigned i
= 0; i
< n
; ++i
) {
1700 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
) {
1702 pa_database
*database
;
1703 pa_datum key
, next_key
;
1704 pa_strlist
*head
=NULL
, *iter
;
1706 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1711 done
= !pa_database_first(database
, &key
, NULL
);
1714 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1715 name
=pa_xmalloc(key
.size
+ 1);
1716 memcpy(name
, key
.data
, key
.size
);
1717 name
[key
.size
] = '\0';
1718 pa_datum_free(&key
);
1719 head
= pa_strlist_prepend(head
, name
);
1724 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1726 for(unsigned i
= 0; i
< *n
; ++i
) {
1727 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1728 iter
= pa_strlist_next(iter
);
1730 pa_strlist_free(head
);
1733 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1740 get_profiles((pa_core
*)_u
, &names
, &n
);
1741 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1742 for(unsigned i
= 0; i
< n
; ++i
) {
1748 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1750 char **names
= NULL
;
1752 DBusMessage
*reply
= NULL
;
1753 DBusMessageIter msg_iter
, dict_iter
;
1757 pa_assert_se(c
= _u
);
1759 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1760 dbus_message_iter_init_append(reply
, &msg_iter
);
1761 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1764 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1766 get_sinks(c
, &names
, &n
);
1767 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1768 for(unsigned i
= 0; i
< n
; ++i
) {
1773 get_profiles(c
, &names
, &n
);
1774 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1775 for(unsigned i
= 0; i
< n
; ++i
) {
1779 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1780 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1781 dbus_message_unref(reply
);
1784 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1785 struct userdata
*u
= _u
;
1787 DBusMessage
*message
= NULL
;
1789 uint32_t *xs
, channel
, r_channel
;
1790 double *_ys
, preamp
;
1791 unsigned x_npoints
, y_npoints
, a_i
;
1793 bool points_good
= true;
1799 dbus_error_init(&error
);
1801 if (!dbus_message_get_args(msg
, &error
,
1802 DBUS_TYPE_UINT32
, &channel
,
1803 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1804 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1805 DBUS_TYPE_DOUBLE
, &preamp
,
1806 DBUS_TYPE_INVALID
)) {
1807 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1808 dbus_error_free(&error
);
1811 if (channel
> u
->channels
) {
1812 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1813 dbus_error_free(&error
);
1816 for(size_t i
= 0; i
< x_npoints
; ++i
) {
1817 if (xs
[i
] >= FILTER_SIZE(u
)) {
1818 points_good
= false;
1822 if (!is_monotonic(xs
, x_npoints
) || !points_good
) {
1823 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%zd", u
->fft_size
/ 2);
1824 dbus_error_free(&error
);
1826 }else if (x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE(u
)) {
1827 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%zd!", FILTER_SIZE(u
));
1828 dbus_error_free(&error
);
1830 }else if (xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2) {
1831 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1832 dbus_error_free(&error
);
1836 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1837 for(uint32_t i
= 0; i
< x_npoints
; ++i
) {
1838 ys
[i
] = (float) _ys
[i
];
1840 r_channel
= channel
== u
->channels
? 0 : channel
;
1841 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1842 H
= u
->Hs
[r_channel
][a_i
];
1843 u
->Xs
[r_channel
][a_i
] = preamp
;
1844 interpolate(H
, FILTER_SIZE(u
), xs
, ys
, x_npoints
);
1845 fix_filter(H
, u
->fft_size
);
1846 if (channel
== u
->channels
) {
1847 for(size_t c
= 1; c
< u
->channels
; ++c
) {
1848 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1849 float *H_p
= u
->Hs
[c
][b_i
];
1850 u
->Xs
[c
][b_i
] = preamp
;
1851 memcpy(H_p
, H
, FILTER_SIZE(u
) * sizeof(float));
1852 pa_aupdate_write_end(u
->a_H
[c
]);
1855 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1858 pa_dbus_send_empty_reply(conn
, msg
);
1860 pa_assert_se((message
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1861 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
1862 dbus_message_unref(message
);
1865 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1866 struct userdata
*u
= (struct userdata
*) _u
;
1867 uint32_t *xs
, channel
, r_channel
;
1869 unsigned x_npoints
, a_i
;
1871 bool points_good
=true;
1872 DBusMessage
*reply
= NULL
;
1873 DBusMessageIter msg_iter
;
1880 dbus_error_init(&error
);
1881 if (!dbus_message_get_args(msg
, &error
,
1882 DBUS_TYPE_UINT32
, &channel
,
1883 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1884 DBUS_TYPE_INVALID
)) {
1885 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1886 dbus_error_free(&error
);
1889 if (channel
> u
->channels
) {
1890 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1891 dbus_error_free(&error
);
1895 for(size_t i
= 0; i
< x_npoints
; ++i
) {
1896 if (xs
[i
] >= FILTER_SIZE(u
)) {
1902 if (x_npoints
> FILTER_SIZE(u
) || !points_good
) {
1903 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %zd!", FILTER_SIZE(u
));
1904 dbus_error_free(&error
);
1908 r_channel
= channel
== u
->channels
? 0 : channel
;
1909 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1910 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1911 H
= u
->Hs
[r_channel
][a_i
];
1912 preamp
= u
->Xs
[r_channel
][a_i
];
1913 for(uint32_t i
= 0; i
< x_npoints
; ++i
) {
1914 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1916 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1918 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1919 dbus_message_iter_init_append(reply
, &msg_iter
);
1921 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1922 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1924 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1925 dbus_message_unref(reply
);
1929 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
) {
1932 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1933 *H_
= pa_xnew0(double, FILTER_SIZE(u
));
1934 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1935 H
= u
->Hs
[r_channel
][a_i
];
1936 for(size_t i
= 0;i
< FILTER_SIZE(u
); ++i
) {
1937 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1939 *preamp
= u
->Xs
[r_channel
][a_i
];
1941 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1944 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1949 DBusMessage
*reply
= NULL
;
1950 DBusMessageIter msg_iter
;
1952 pa_assert_se(u
= (struct userdata
*) _u
);
1956 dbus_error_init(&error
);
1957 if (!dbus_message_get_args(msg
, &error
,
1958 DBUS_TYPE_UINT32
, &channel
,
1959 DBUS_TYPE_INVALID
)) {
1960 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1961 dbus_error_free(&error
);
1964 if (channel
> u
->channels
) {
1965 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1966 dbus_error_free(&error
);
1970 n_coefs
= CHANNEL_PROFILE_SIZE(u
);
1973 get_filter(u
, channel
, &H_
, &preamp
);
1974 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1975 dbus_message_iter_init_append(reply
, &msg_iter
);
1977 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1978 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1980 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1981 dbus_message_unref(reply
);
1985 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
) {
1987 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1990 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1991 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1992 H
= u
->Hs
[r_channel
][a_i
];
1993 for(size_t i
= 0; i
< FILTER_SIZE(u
); ++i
) {
1994 H
[i
] = (float) H_
[i
];
1996 fix_filter(H
, u
->fft_size
);
1997 if (channel
== u
->channels
) {
1998 for(size_t c
= 1; c
< u
->channels
; ++c
) {
1999 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
2000 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
2001 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE(u
) * sizeof(float));
2002 pa_aupdate_write_end(u
->a_H
[c
]);
2005 pa_aupdate_write_end(u
->a_H
[r_channel
]);
2008 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2013 DBusMessage
*message
= NULL
;
2015 pa_assert_se(u
= (struct userdata
*) _u
);
2019 dbus_error_init(&error
);
2020 if (!dbus_message_get_args(msg
, &error
,
2021 DBUS_TYPE_UINT32
, &channel
,
2022 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
2023 DBUS_TYPE_DOUBLE
, &preamp
,
2024 DBUS_TYPE_INVALID
)) {
2025 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2026 dbus_error_free(&error
);
2029 if (channel
> u
->channels
) {
2030 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2031 dbus_error_free(&error
);
2034 if (_n_coefs
!= FILTER_SIZE(u
)) {
2035 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %zd coefficients, you gave %d", FILTER_SIZE(u
), _n_coefs
);
2038 set_filter(u
, channel
, H
, preamp
);
2040 pa_dbus_send_empty_reply(conn
, msg
);
2042 pa_assert_se((message
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2043 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
2044 dbus_message_unref(message
);
2047 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2048 struct userdata
*u
= (struct userdata
*) _u
;
2050 uint32_t channel
, r_channel
;
2051 DBusMessage
*message
= NULL
;
2056 dbus_error_init(&error
);
2058 if (!dbus_message_get_args(msg
, &error
,
2059 DBUS_TYPE_UINT32
, &channel
,
2060 DBUS_TYPE_STRING
, &name
,
2061 DBUS_TYPE_INVALID
)) {
2062 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2063 dbus_error_free(&error
);
2066 if (channel
> u
->channels
) {
2067 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2068 dbus_error_free(&error
);
2071 r_channel
= channel
== u
->channels
? 0 : channel
;
2072 save_profile(u
, r_channel
, name
);
2073 pa_dbus_send_empty_reply(conn
, msg
);
2075 pa_assert_se((message
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
2076 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
2077 dbus_message_unref(message
);
2080 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2081 struct userdata
*u
= (struct userdata
*) _u
;
2084 uint32_t channel
, r_channel
;
2085 const char *err_msg
= NULL
;
2086 DBusMessage
*message
= NULL
;
2091 dbus_error_init(&error
);
2093 if (!dbus_message_get_args(msg
, &error
,
2094 DBUS_TYPE_UINT32
, &channel
,
2095 DBUS_TYPE_STRING
, &name
,
2096 DBUS_TYPE_INVALID
)) {
2097 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2098 dbus_error_free(&error
);
2101 if (channel
> u
->channels
) {
2102 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2103 dbus_error_free(&error
);
2106 r_channel
= channel
== u
->channels
? 0 : channel
;
2108 err_msg
= load_profile(u
, r_channel
, name
);
2109 if (err_msg
!= NULL
) {
2110 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2111 dbus_error_free(&error
);
2114 if (channel
== u
->channels
) {
2115 for(uint32_t c
= 1; c
< u
->channels
; ++c
) {
2116 load_profile(u
, c
, name
);
2119 pa_dbus_send_empty_reply(conn
, msg
);
2121 pa_assert_se((message
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2122 pa_dbus_protocol_send_signal(u
->dbus_protocol
, message
);
2123 dbus_message_unref(message
);
2126 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2127 struct userdata
*u
= (struct userdata
*) _u
;
2133 pa_dbus_send_empty_reply(conn
, msg
);
2136 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2137 struct userdata
*u
= (struct userdata
*) _u
;
2139 uint32_t channel
, r_channel
;
2144 dbus_error_init(&error
);
2146 if (!dbus_message_get_args(msg
, &error
,
2147 DBUS_TYPE_UINT32
, &channel
,
2148 DBUS_TYPE_INVALID
)) {
2149 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2150 dbus_error_free(&error
);
2153 if (channel
> u
->channels
) {
2154 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2155 dbus_error_free(&error
);
2158 r_channel
= channel
== u
->channels
? 0 : channel
;
2159 pa_assert(u
->base_profiles
[r_channel
]);
2160 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2163 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2165 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2168 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2171 pa_assert_se(u
= (struct userdata
*) _u
);
2175 channels
= (uint32_t) u
->channels
;
2176 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2179 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2182 pa_assert_se(u
= (struct userdata
*) _u
);
2186 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2187 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2190 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2193 pa_assert_se(u
= (struct userdata
*) _u
);
2197 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2198 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2201 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2204 pa_assert_se(u
= (struct userdata
*) _u
);
2208 fft_size
= (uint32_t) u
->fft_size
;
2209 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2212 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2214 DBusMessage
*reply
= NULL
;
2215 DBusMessageIter msg_iter
, dict_iter
;
2216 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2218 pa_assert_se(u
= _u
);
2222 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2223 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2224 fft_size
= (uint32_t) u
->fft_size
;
2225 channels
= (uint32_t) u
->channels
;
2227 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2228 dbus_message_iter_init_append(reply
, &msg_iter
);
2229 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2231 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2232 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2233 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2234 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2235 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2237 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2238 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2239 dbus_message_unref(reply
);