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
43 #include <xmmintrin.h>
44 #include <emmintrin.h>
49 #include <pulse/xmalloc.h>
50 #include <pulse/i18n.h>
51 #include <pulse/timeval.h>
53 #include <pulsecore/core-rtclock.h>
54 #include <pulsecore/aupdate.h>
55 #include <pulsecore/core-error.h>
56 #include <pulsecore/namereg.h>
57 #include <pulsecore/sink.h>
58 #include <pulsecore/module.h>
59 #include <pulsecore/core-util.h>
60 #include <pulsecore/modargs.h>
61 #include <pulsecore/log.h>
62 #include <pulsecore/thread.h>
63 #include <pulsecore/thread-mq.h>
64 #include <pulsecore/rtpoll.h>
65 #include <pulsecore/sample-util.h>
66 #include <pulsecore/shared.h>
67 #include <pulsecore/idxset.h>
68 #include <pulsecore/strlist.h>
69 #include <pulsecore/database.h>
70 #include <pulsecore/protocol-dbus.h>
71 #include <pulsecore/dbus-util.h>
73 #include "module-equalizer-sink-symdef.h"
75 PA_MODULE_AUTHOR("Jason Newton");
76 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
77 PA_MODULE_VERSION(PACKAGE_VERSION
);
78 PA_MODULE_LOAD_ONCE(FALSE
);
80 _("sink_name=<name of the sink> "
81 "sink_properties=<properties for the sink> "
82 "sink_master=<sink to connect to> "
83 "format=<sample format> "
85 "channels=<number of channels> "
86 "channel_map=<channel map>"));
88 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
93 pa_sink_input
*sink_input
;
96 size_t fft_size
;//length (res) of fft
99 *effectively chooses R
101 size_t R
;/* the hop size between overlapping windows
102 * the latency of the filter, calculated from window_size
103 * based on constraints of COLA and window function
105 //for twiddling with pulseaudio
106 size_t overlap_size
;//window_size-R
107 size_t samples_gathered
;
108 size_t input_buffer_max
;
110 float *W
;//windowing function (time domain)
111 float *work_buffer
, **input
, **overlap_accum
;
112 fftwf_complex
*output_window
;
113 fftwf_plan forward_plan
, inverse_plan
;
117 float ***Hs
;//thread updatable copies of the freq response filters (magintude based)
119 pa_memblockq
*input_q
;
121 size_t output_buffer_length
;
122 size_t output_buffer_max_length
;
123 pa_memblockq
*output_q
;
124 pa_bool_t first_iteration
;
126 pa_dbus_protocol
*dbus_protocol
;
129 pa_database
*database
;
130 char **base_profiles
;
133 static const char* const valid_modargs
[] = {
145 #define SINKLIST "equalized_sinklist"
146 #define EQDB "equalizer_db"
147 #define EQ_STATE_DB "equalizer-state"
148 #define FILTER_SIZE(u) ((u)->fft_size / 2 + 1)
149 #define CHANNEL_PROFILE_SIZE(u) (FILTER_SIZE(u) + 1)
150 #define FILTER_STATE_SIZE(u) (CHANNEL_PROFILE_SIZE(u) * (u)->channels)
152 static void dbus_init(struct userdata
*u
);
153 static void dbus_done(struct userdata
*u
);
155 static void hanning_window(float *W
, size_t window_size
){
156 /* h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2 */
157 for (size_t i
= 0; i
< window_size
; ++i
)
158 W
[i
] = (float).5 * (1 - cos(2*M_PI
*i
/ (window_size
+1)));
161 static void fix_filter(float *H
, size_t fft_size
){
162 /* divide out the fft gain */
163 for (size_t i
= 0; i
< fft_size
/ 2 + 1; ++i
)
167 static void interpolate(float *signal
, size_t length
, uint32_t *xs
, float *ys
, size_t n_points
){
168 /* Note that xs must be monotonically increasing! */
169 float x_range_lower
, x_range_upper
, c0
;
171 pa_assert(n_points
>= 2);
172 pa_assert(xs
[0] == 0);
173 pa_assert(xs
[n_points
- 1] == length
- 1);
175 for (size_t x
= 0, x_range_lower_i
= 0; x
< length
-1; ++x
) {
176 pa_assert(x_range_lower_i
< n_points
-1);
178 x_range_lower
= (float) xs
[x_range_lower_i
];
179 x_range_upper
= (float) xs
[x_range_lower_i
+1];
181 pa_assert_se(x_range_lower
< x_range_upper
);
182 pa_assert_se(x
>= x_range_lower
);
183 pa_assert_se(x
<= x_range_upper
);
185 /* bilinear-interpolation of coefficients specified */
186 c0
= (x
-x_range_lower
) / (x_range_upper
-x_range_lower
);
187 pa_assert(c0
>= 0 && c0
<= 1.0);
189 signal
[x
] = ((1.0f
- c0
) * ys
[x_range_lower_i
] + c0
* ys
[x_range_lower_i
+ 1]);
190 while(x
>= xs
[x_range_lower_i
+ 1])
194 signal
[length
-1] = ys
[n_points
-1];
197 static pa_bool_t
is_monotonic(const uint32_t *xs
, size_t length
) {
203 for(size_t i
= 1; i
< length
; ++i
)
204 if (xs
[i
] <= xs
[i
-1])
210 /* ensures memory allocated is a multiple of v_size and aligned */
211 static void * alloc(size_t x
, size_t s
){
215 f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
216 pa_assert_se(t
= fftwf_malloc(f
));
222 static void alloc_input_buffers(struct userdata
*u
, size_t min_buffer_length
){
223 if (min_buffer_length
<= u
->input_buffer_max
)
226 pa_assert(min_buffer_length
>= u
->window_size
);
227 for (size_t c
= 0; c
< u
->channels
; ++c
) {
228 float *tmp
= alloc(min_buffer_length
, sizeof(float));
230 if (!u
->first_iteration
)
231 memcpy(tmp
, u
->input
[c
], u
->overlap_size
* sizeof(float));
236 u
->input_buffer_max
= min_buffer_length
;
239 /* Called from I/O thread context */
240 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
241 struct userdata
*u
= PA_SINK(o
)->userdata
;
245 case PA_SINK_MESSAGE_GET_LATENCY
: {
246 //size_t fs=pa_frame_size(&u->sink->sample_spec);
248 /* The sink is _put() before the sink input is, so let's
249 * make sure we don't access it in that time. Also, the
250 * sink input is first shut down, the sink second. */
251 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
252 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
253 *((pa_usec_t
*) data
) = 0;
257 *((pa_usec_t
*) data
) =
258 /* Get the latency of the master sink */
259 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
261 /* Add the latency internal to our sink input on top */
262 pa_bytes_to_usec(pa_memblockq_get_length(u
->output_q
) +
263 pa_memblockq_get_length(u
->input_q
), &u
->sink_input
->sink
->sample_spec
) +
264 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
265 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
266 //+ pa_bytes_to_usec(u->latency * fs, ss)
271 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
275 /* Called from main context */
276 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
279 pa_sink_assert_ref(s
);
280 pa_assert_se(u
= s
->userdata
);
282 if (!PA_SINK_IS_LINKED(state
) ||
283 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
286 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
290 /* Called from I/O thread context */
291 static void sink_request_rewind_cb(pa_sink
*s
) {
294 pa_sink_assert_ref(s
);
295 pa_assert_se(u
= s
->userdata
);
297 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
298 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
301 /* Just hand this one over to the master sink */
302 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), TRUE
, FALSE
, FALSE
);
305 /* Called from I/O thread context */
306 static void sink_update_requested_latency_cb(pa_sink
*s
) {
309 pa_sink_assert_ref(s
);
310 pa_assert_se(u
= s
->userdata
);
312 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
313 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
316 /* Just hand this one over to the master sink */
317 pa_sink_input_set_requested_latency_within_thread(
319 pa_sink_get_requested_latency_within_thread(s
));
322 /* Called from main context */
323 static void sink_set_volume_cb(pa_sink
*s
) {
326 pa_sink_assert_ref(s
);
327 pa_assert_se(u
= s
->userdata
);
329 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
330 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
333 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
336 /* Called from main context */
337 static void sink_set_mute_cb(pa_sink
*s
) {
340 pa_sink_assert_ref(s
);
341 pa_assert_se(u
= s
->userdata
);
343 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
344 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
347 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
351 //reference implementation
352 static void dsp_logic(
353 float * restrict dst
,//used as a temp array too, needs to be fft_length!
354 float * restrict src
,/*input data w/ overlap at start,
355 *automatically cycled in routine
357 float * restrict overlap
,
358 const float X
,//multipliar
359 const float * restrict H
,//The freq. magnitude scalers filter
360 const float * restrict W
,//The windowing function
361 fftwf_complex
* restrict output_window
,//The transformed window'd src
364 //use a linear-phase sliding STFT and overlap-add method (for each channel)
366 for(size_t j
= 0; j
< u
->window_size
; ++j
){
367 dst
[j
] = X
* W
[j
] * src
[j
];
369 //zero padd the the remaining fft window
370 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
371 //Processing is done here!
373 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
375 for(size_t j
= 0; j
< FILTER_SIZE(u
); ++j
){
376 u
->output_window
[j
][0] *= H
[j
];
377 u
->output_window
[j
][1] *= H
[j
];
380 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
381 ////debug: tests overlaping add
382 ////and negates ALL PREVIOUS processing
383 ////yields a perfect reconstruction if COLA is held
384 //for(size_t j = 0; j < u->window_size; ++j){
385 // u->work_buffer[j] = u->W[j] * u->input[c][j];
388 //overlap add and preserve overlap component from this window (linear phase)
389 for(size_t j
= 0; j
< u
->overlap_size
; ++j
){
390 u
->work_buffer
[j
] += overlap
[j
];
391 overlap
[j
] = dst
[u
->R
+ j
];
393 ////debug: tests if basic buffering works
394 ////shouldn't modify the signal AT ALL (beyond roundoff)
395 //for(size_t j = 0; j < u->window_size;++j){
396 // u->work_buffer[j] = u->input[c][j];
399 //preseve the needed input for the next window's overlap
400 memmove(src
, src
+ u
->R
,
401 (u
->samples_gathered
- u
->R
) * sizeof(float)
405 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
406 typedef union float_vector
{
412 //regardless of sse enabled, the loops in here assume
413 //16 byte aligned addresses and memory allocations divisible by v_size
414 static void dsp_logic(
415 float * restrict dst
,//used as a temp array too, needs to be fft_length!
416 float * restrict src
,/*input data w/ overlap at start,
417 *automatically cycled in routine
419 float * restrict overlap
,//The size of the overlap
420 const float X
,//multipliar
421 const float * restrict H
,//The freq. magnitude scalers filter
422 const float * restrict W
,//The windowing function
423 fftwf_complex
* restrict output_window
,//The transformed window'd src
424 struct userdata
*u
){//Collection of constants
425 const size_t overlap_size
= PA_ROUND_UP(u
->overlap_size
, v_size
);
427 x
.f
[0] = x
.f
[1] = x
.f
[2] = x
.f
[3] = X
;
429 //assert(u->samples_gathered >= u->R);
430 //use a linear-phase sliding STFT and overlap-add method
431 for(size_t j
= 0; j
< u
->window_size
; j
+= v_size
){
432 //dst[j] = W[j] * src[j];
433 float_vector_t
*d
= (float_vector_t
*) (dst
+ j
);
434 float_vector_t
*w
= (float_vector_t
*) (W
+ j
);
435 float_vector_t
*s
= (float_vector_t
*) (src
+ j
);
437 d
->m
= _mm_mul_ps(x
.m
, _mm_mul_ps(w
->m
, s
->m
));
438 // d->v = x->v * w->v * s->v;
441 //zero padd the the remaining fft window
442 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
444 //Processing is done here!
446 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
447 //perform filtering - purely magnitude based
448 for(size_t j
= 0; j
< FILTER_SIZE
; j
+= v_size
/ 2){
449 //output_window[j][0]*=H[j];
450 //output_window[j][1]*=H[j];
451 float_vector_t
*d
= (float_vector_t
*)( ((float *) output_window
) + 2 * j
);
453 h
.f
[0] = h
.f
[1] = H
[j
];
454 h
.f
[2] = h
.f
[3] = H
[j
+ 1];
456 d
->m
= _mm_mul_ps(d
->m
, h
.m
);
458 // d->v = d->v * h.v;
463 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
465 ////debug: tests overlaping add
466 ////and negates ALL PREVIOUS processing
467 ////yields a perfect reconstruction if COLA is held
468 //for(size_t j = 0; j < u->window_size; ++j){
469 // dst[j] = W[j] * src[j];
472 //overlap add and preserve overlap component from this window (linear phase)
473 for(size_t j
= 0; j
< overlap_size
; j
+= v_size
){
474 //dst[j]+=overlap[j];
475 //overlap[j]+=dst[j+R];
476 float_vector_t
*d
= (float_vector_t
*)(dst
+ j
);
477 float_vector_t
*o
= (float_vector_t
*)(overlap
+ j
);
479 d
->m
= _mm_add_ps(d
->m
, o
->m
);
480 o
->m
= ((float_vector_t
*)(dst
+ u
->R
+ j
))->m
;
482 // d->v = d->v + o->v;
483 // o->v = ((float_vector_t*)(dst + u->R + j))->v;
486 //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
487 //zero out the bit beyond the real overlap so we don't add garbage next iteration
488 memset(overlap
+ u
->overlap_size
, 0, overlap_size
- u
->overlap_size
);
490 ////debug: tests if basic buffering works
491 ////shouldn't modify the signal AT ALL (beyond roundoff)
492 //for(size_t j = 0; j < u->window_size; ++j){
496 //preseve the needed input for the next window's overlap
497 memmove(src
, src
+ u
->R
,
498 (u
->samples_gathered
- u
->R
) * sizeof(float)
503 static void flatten_to_memblockq(struct userdata
*u
){
504 size_t mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
508 while(i
< u
->output_buffer_length
){
510 tchunk
.length
= PA_MIN((u
->output_buffer_length
- i
), mbs
);
511 tchunk
.memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
.length
);
512 //pa_log_debug("pushing %ld into the q", tchunk.length);
513 dst
= pa_memblock_acquire(tchunk
.memblock
);
514 memcpy(dst
, u
->output_buffer
+ i
, tchunk
.length
);
515 pa_memblock_release(tchunk
.memblock
);
516 pa_memblockq_push(u
->output_q
, &tchunk
);
517 pa_memblock_unref(tchunk
.memblock
);
522 static void process_samples(struct userdata
*u
){
523 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
526 size_t iterations
, offset
;
527 pa_assert(u
->samples_gathered
>= u
->window_size
);
528 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
529 //make sure there is enough buffer memory allocated
530 if(iterations
* u
->R
* fs
> u
->output_buffer_max_length
){
531 u
->output_buffer_max_length
= iterations
* u
->R
* fs
;
532 pa_xfree(u
->output_buffer
);
533 u
->output_buffer
= pa_xmalloc(u
->output_buffer_max_length
);
535 u
->output_buffer_length
= iterations
* u
->R
* fs
;
537 for(size_t iter
= 0; iter
< iterations
; ++iter
){
538 offset
= iter
* u
->R
* fs
;
539 for(size_t c
= 0;c
< u
->channels
; c
++) {
540 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
553 pa_aupdate_read_end(u
->a_H
[c
]);
554 if(u
->first_iteration
){
555 /* The windowing function will make the audio ramped in, as a cheap fix we can
556 * undo the windowing (for non-zero window values)
558 for(size_t i
= 0; i
< u
->overlap_size
; ++i
){
559 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
562 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (((float *)u
->output_buffer
) + c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
564 if(u
->first_iteration
){
565 u
->first_iteration
= FALSE
;
567 u
->samples_gathered
-= u
->R
;
569 flatten_to_memblockq(u
);
572 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
){
573 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
574 size_t samples
= in
->length
/fs
;
575 float *src
= (float*) ((uint8_t*) pa_memblock_acquire(in
->memblock
) + in
->index
);
576 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
577 for(size_t c
= 0; c
< u
->channels
; c
++) {
578 //buffer with an offset after the overlap from previous
581 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
583 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
585 u
->samples_gathered
+= samples
;
586 pa_memblock_release(in
->memblock
);
589 /* Called from I/O thread context */
590 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
592 size_t fs
, target_samples
;
594 //struct timeval start, end;
597 pa_sink_input_assert_ref(i
);
598 pa_assert_se(u
= i
->userdata
);
602 /* FIXME: Please clean this up. I see more commented code lines
603 * than uncommented code lines. I am sorry, but I am too dumb to
604 * understand this. */
606 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
607 mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
608 if(pa_memblockq_get_length(u
->output_q
) > 0){
609 //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
612 //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
613 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
614 ////pa_log_debug("vanilla mbs = %ld",mbs);
615 //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
616 //mbs = PA_MAX(mbs, u->R);
617 //target_samples = PA_MAX(target_samples, mbs);
618 //pa_log_debug("target samples: %ld", target_samples);
619 if(u
->first_iteration
){
620 //allocate request_size
621 target_samples
= PA_MAX(target_samples
, u
->window_size
);
623 //allocate request_size + overlap
624 target_samples
+= u
->overlap_size
;
626 alloc_input_buffers(u
, target_samples
);
627 //pa_log_debug("post target samples: %ld", target_samples);
628 chunk
->memblock
= NULL
;
630 /* Hmm, process any rewind request that might be queued up */
631 pa_sink_process_rewind(u
->sink
, 0);
633 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
634 //pa_rtclock_get(&start);
636 size_t input_remaining
= target_samples
- u
->samples_gathered
;
637 // pa_log_debug("input remaining %ld samples", input_remaining);
638 pa_assert(input_remaining
> 0);
639 while (pa_memblockq_peek(u
->input_q
, &tchunk
) < 0) {
640 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
641 pa_sink_render_full(u
->sink
, PA_MIN(input_remaining
* fs
, mbs
), &tchunk
);
642 pa_memblockq_push(u
->input_q
, &tchunk
);
643 pa_memblock_unref(tchunk
.memblock
);
645 pa_assert(tchunk
.memblock
);
647 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
649 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
650 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
652 //pa_rtclock_get(start);
653 // pa_log_debug("buffering %ld bytes", tchunk.length);
654 input_buffer(u
, &tchunk
);
655 //pa_rtclock_get(&end);
656 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
657 pa_memblock_unref(tchunk
.memblock
);
658 } while(u
->samples_gathered
< target_samples
);
660 //pa_rtclock_get(&end);
661 //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
663 pa_assert(u
->fft_size
>= u
->window_size
);
664 pa_assert(u
->R
< u
->window_size
);
665 //pa_rtclock_get(&start);
666 /* process a block */
668 //pa_rtclock_get(&end);
669 //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
671 pa_assert_se(pa_memblockq_peek(u
->output_q
, chunk
) >= 0);
672 pa_assert(chunk
->memblock
);
673 pa_memblockq_drop(u
->output_q
, chunk
->length
);
675 /** FIXME: Uh? you need to unref the chunk here! */
677 //pa_log_debug("gave %ld", chunk->length/fs);
678 //pa_log_debug("end pop");
682 /* Called from main context */
683 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
686 pa_sink_input_assert_ref(i
);
687 pa_assert_se(u
= i
->userdata
);
689 pa_sink_volume_changed(u
->sink
, &i
->volume
);
692 /* Called from main context */
693 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
696 pa_sink_input_assert_ref(i
);
697 pa_assert_se(u
= i
->userdata
);
699 pa_sink_mute_changed(u
->sink
, i
->muted
);
702 static void reset_filter(struct userdata
*u
){
703 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
706 u
->samples_gathered
= 0;
708 for(size_t i
= 0; i
< u
->channels
; ++i
)
709 pa_memzero(u
->overlap_accum
[i
], u
->overlap_size
* sizeof(float));
711 u
->first_iteration
= TRUE
;
712 //set buffer size to max request, no overlap copy
713 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
714 max_request
= PA_MAX(max_request
, u
->window_size
);
715 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
718 /* Called from I/O thread context */
719 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
723 pa_log_debug("Rewind callback!");
724 pa_sink_input_assert_ref(i
);
725 pa_assert_se(u
= i
->userdata
);
727 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
730 //max_rewrite = nbytes;
731 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
732 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
733 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
734 u
->sink
->thread_info
.rewind_nbytes
= 0;
737 //invalidate the output q
738 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
739 pa_log("Resetting filter");
740 //reset_filter(u); //this is the "proper" thing to do...
744 pa_sink_process_rewind(u
->sink
, amount
);
745 pa_memblockq_rewind(u
->input_q
, nbytes
);
748 /* Called from I/O thread context */
749 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
752 pa_sink_input_assert_ref(i
);
753 pa_assert_se(u
= i
->userdata
);
755 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
756 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
759 /* Called from I/O thread context */
760 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
764 pa_sink_input_assert_ref(i
);
765 pa_assert_se(u
= i
->userdata
);
767 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
768 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
771 /* Called from I/O thread context */
772 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
775 pa_sink_input_assert_ref(i
);
776 pa_assert_se(u
= i
->userdata
);
778 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
781 /* Called from I/O thread context */
782 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
785 pa_sink_input_assert_ref(i
);
786 pa_assert_se(u
= i
->userdata
);
788 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
791 /* Called from I/O thread context */
792 static void sink_input_detach_cb(pa_sink_input
*i
) {
795 pa_sink_input_assert_ref(i
);
796 pa_assert_se(u
= i
->userdata
);
798 pa_sink_detach_within_thread(u
->sink
);
800 pa_sink_set_rtpoll(u
->sink
, NULL
);
803 /* Called from I/O thread context */
804 static void sink_input_attach_cb(pa_sink_input
*i
) {
806 size_t fs
, max_request
;
808 pa_sink_input_assert_ref(i
);
809 pa_assert_se(u
= i
->userdata
);
811 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
812 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
813 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
815 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
816 /* set buffer size to max request, no overlap copy */
817 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
818 max_request
= PA_MAX(max_request
, u
->window_size
);
820 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
821 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
823 pa_sink_attach_within_thread(u
->sink
);
826 /* Called from main context */
827 static void sink_input_kill_cb(pa_sink_input
*i
) {
830 pa_sink_input_assert_ref(i
);
831 pa_assert_se(u
= i
->userdata
);
833 /* The order here matters! We first kill the sink input, followed
834 * by the sink. That means the sink callbacks must be protected
835 * against an unconnected sink input! */
836 pa_sink_input_unlink(u
->sink_input
);
837 pa_sink_unlink(u
->sink
);
839 pa_sink_input_unref(u
->sink_input
);
840 u
->sink_input
= NULL
;
842 pa_sink_unref(u
->sink
);
845 pa_module_unload_request(u
->module
, TRUE
);
848 /* Called from IO thread context */
849 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
852 pa_sink_input_assert_ref(i
);
853 pa_assert_se(u
= i
->userdata
);
855 /* If we are added for the first time, ask for a rewinding so that
856 * we are heard right-away. */
857 if (PA_SINK_INPUT_IS_LINKED(state
) &&
858 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
859 pa_log_debug("Requesting rewind due to state change.");
860 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
864 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
){
866 size_t headers
= (1+len
) * sizeof(uint16_t);
868 for(size_t i
= 0; i
< len
; ++i
){
869 t_len
+= strlen(strs
[i
]);
871 *length
= headers
+ t_len
;
872 p
= *packed
= pa_xmalloc0(*length
);
873 *((uint16_t *) p
) = (uint16_t) len
;
874 p
+= sizeof(uint16_t);
875 for(size_t i
= 0; i
< len
; ++i
){
876 uint16_t l
= strlen(strs
[i
]);
877 *((uint16_t *) p
) = (uint16_t) l
;
878 p
+= sizeof(uint16_t);
879 memcpy(p
, strs
[i
], l
);
883 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
){
885 *len
= *((uint16_t *) p
);
886 p
+= sizeof(uint16_t);
887 *strs
= pa_xnew(char *, *len
);
889 for(size_t i
= 0; i
< *len
; ++i
){
890 size_t l
= *((uint16_t *) p
);
891 p
+= sizeof(uint16_t);
892 (*strs
)[i
] = pa_xnew(char, l
+ 1);
893 memcpy((*strs
)[i
], p
, l
);
894 (*strs
)[i
][l
] = '\0';
898 static void save_profile(struct userdata
*u
, size_t channel
, char *name
){
900 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
901 float *H_n
, *profile
;
904 profile
= pa_xnew0(float, profile_size
);
905 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
906 profile
[0] = u
->Xs
[a_i
][channel
];
907 H
= u
->Hs
[channel
][a_i
];
909 for(size_t i
= 0 ; i
<= FILTER_SIZE(u
); ++i
){
910 H_n
[i
] = H
[i
] * u
->fft_size
;
913 pa_aupdate_read_end(u
->a_H
[channel
]);
915 key
.size
= strlen(key
.data
);
917 data
.size
= profile_size
;
918 pa_database_set(u
->database
, &key
, &data
, TRUE
);
919 pa_database_sync(u
->database
);
920 if(u
->base_profiles
[channel
]){
921 pa_xfree(u
->base_profiles
[channel
]);
923 u
->base_profiles
[channel
] = pa_xstrdup(name
);
926 static void save_state(struct userdata
*u
){
928 const size_t filter_state_size
= FILTER_STATE_SIZE(u
) * sizeof(float);
932 pa_database
*database
;
935 size_t packed_length
;
937 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
938 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
939 memcpy(state
+ FILTER_STATE_SIZE(u
), packed
, packed_length
);
942 for(size_t c
= 0; c
< u
->channels
; ++c
){
943 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
944 state
[c
* CHANNEL_PROFILE_SIZE(u
)] = u
->Xs
[c
][a_i
];
946 H_n
= &state
[c
* CHANNEL_PROFILE_SIZE(u
) + 1];
947 memcpy(H_n
, H
, FILTER_SIZE(u
) * sizeof(float));
948 pa_aupdate_read_end(u
->a_H
[c
]);
951 key
.data
= u
->sink
->name
;
952 key
.size
= strlen(key
.data
);
954 data
.size
= filter_state_size
+ packed_length
;
955 //thread safety for 0.9.17?
956 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
957 pa_assert_se(database
= pa_database_open(dbname
, TRUE
));
960 pa_database_set(database
, &key
, &data
, TRUE
);
961 pa_database_sync(database
);
962 pa_database_close(database
);
966 static void remove_profile(pa_core
*c
, char *name
){
968 pa_database
*database
;
970 key
.size
= strlen(key
.data
);
971 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
972 pa_database_unset(database
, &key
);
973 pa_database_sync(database
);
976 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
){
979 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
981 key
.size
= strlen(key
.data
);
982 if(pa_database_get(u
->database
, &key
, &value
) != NULL
){
983 if(value
.size
== profile_size
){
984 float *profile
= (float *) value
.data
;
985 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
986 u
->Xs
[channel
][a_i
] = profile
[0];
987 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE(u
) * sizeof(float));
988 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
989 pa_aupdate_write_end(u
->a_H
[channel
]);
990 pa_xfree(u
->base_profiles
[channel
]);
991 u
->base_profiles
[channel
] = pa_xstrdup(name
);
993 return "incompatible size";
995 pa_datum_free(&value
);
997 return "profile doesn't exist";
1002 static void load_state(struct userdata
*u
){
1005 pa_datum key
, value
;
1006 pa_database
*database
;
1008 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
1009 database
= pa_database_open(dbname
, FALSE
);
1012 pa_log("No resume state");
1016 key
.data
= u
->sink
->name
;
1017 key
.size
= strlen(key
.data
);
1019 if(pa_database_get(database
, &key
, &value
) != NULL
){
1020 if(value
.size
> FILTER_STATE_SIZE(u
) * sizeof(float) + sizeof(uint16_t)){
1021 float *state
= (float *) value
.data
;
1024 for(size_t c
= 0; c
< u
->channels
; ++c
){
1025 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1026 H
= state
+ c
* CHANNEL_PROFILE_SIZE(u
) + 1;
1027 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE(u
)];
1028 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE(u
) * sizeof(float));
1029 pa_aupdate_write_end(u
->a_H
[c
]);
1031 unpack(((char *)value
.data
) + FILTER_STATE_SIZE(u
) * sizeof(float), value
.size
- FILTER_STATE_SIZE(u
) * sizeof(float), &names
, &n_profs
);
1032 n_profs
= PA_MIN(n_profs
, u
->channels
);
1033 for(size_t c
= 0; c
< n_profs
; ++c
){
1034 pa_xfree(u
->base_profiles
[c
]);
1035 u
->base_profiles
[c
] = names
[c
];
1039 pa_datum_free(&value
);
1041 pa_log("resume state exists but is wrong size!");
1043 pa_database_close(database
);
1046 /* Called from main context */
1047 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1050 pa_sink_input_assert_ref(i
);
1051 pa_assert_se(u
= i
->userdata
);
1053 return u
->sink
!= dest
;
1056 /* Called from main context */
1057 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1060 pa_sink_input_assert_ref(i
);
1061 pa_assert_se(u
= i
->userdata
);
1064 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1065 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1067 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1070 int pa__init(pa_module
*m
) {
1077 pa_sink_input_new_data sink_input_data
;
1078 pa_sink_new_data sink_data
;
1086 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1087 pa_log("Failed to parse module arguments.");
1091 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "sink_master", NULL
), PA_NAMEREG_SINK
))) {
1092 pa_log("Master sink not found");
1096 ss
= master
->sample_spec
;
1097 ss
.format
= PA_SAMPLE_FLOAT32
;
1098 map
= master
->channel_map
;
1099 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1100 pa_log("Invalid sample format specification or channel map");
1104 fs
= pa_frame_size(&ss
);
1106 u
= pa_xnew0(struct userdata
, 1);
1110 u
->channels
= ss
.channels
;
1111 u
->fft_size
= pow(2, ceil(log(ss
.rate
) / log(2)));//probably unstable near corner cases of powers of 2
1112 pa_log_debug("fft size: %ld", u
->fft_size
);
1113 u
->window_size
= 15999;
1114 if (u
->window_size
% 2 == 0)
1116 u
->R
= (u
->window_size
+ 1) / 2;
1117 u
->overlap_size
= u
->window_size
- u
->R
;
1118 u
->samples_gathered
= 0;
1119 u
->input_buffer_max
= 0;
1121 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1122 u
->Xs
= pa_xnew0(float *, u
->channels
);
1123 u
->Hs
= pa_xnew0(float **, u
->channels
);
1125 for (c
= 0; c
< u
->channels
; ++c
) {
1126 u
->Xs
[c
] = pa_xnew0(float, 2);
1127 u
->Hs
[c
] = pa_xnew0(float *, 2);
1128 for (i
= 0; i
< 2; ++i
)
1129 u
->Hs
[c
][i
] = alloc(FILTER_SIZE(u
), sizeof(float));
1132 u
->W
= alloc(u
->window_size
, sizeof(float));
1133 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1134 u
->input
= pa_xnew0(float *, u
->channels
);
1135 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1136 for (c
= 0; c
< u
->channels
; ++c
) {
1137 u
->a_H
[c
] = pa_aupdate_new();
1139 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1141 u
->output_window
= alloc(FILTER_SIZE(u
), sizeof(fftwf_complex
));
1142 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1143 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1145 hanning_window(u
->W
, u
->window_size
);
1146 u
->first_iteration
= TRUE
;
1148 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1149 for (c
= 0; c
< u
->channels
; ++c
)
1150 u
->base_profiles
[c
] = pa_xstrdup("default");
1153 pa_sink_new_data_init(&sink_data
);
1154 sink_data
.driver
= __FILE__
;
1155 sink_data
.module
= m
;
1156 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1157 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1158 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1159 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1161 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1162 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s", z
? z
: master
->name
);
1164 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1165 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1167 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1168 pa_log("Invalid properties");
1169 pa_sink_new_data_done(&sink_data
);
1173 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1174 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1175 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1176 pa_sink_new_data_done(&sink_data
);
1179 pa_log("Failed to create sink.");
1183 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1184 u
->sink
->set_state
= sink_set_state_cb
;
1185 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1186 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1187 u
->sink
->set_volume
= sink_set_volume_cb
;
1188 u
->sink
->set_mute
= sink_set_mute_cb
;
1189 u
->sink
->userdata
= u
;
1191 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1192 u
->output_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, NULL
);
1193 u
->output_buffer
= NULL
;
1194 u
->output_buffer_length
= 0;
1195 u
->output_buffer_max_length
= 0;
1197 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1198 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1200 /* Create sink input */
1201 pa_sink_input_new_data_init(&sink_input_data
);
1202 sink_input_data
.driver
= __FILE__
;
1203 sink_input_data
.module
= m
;
1204 sink_input_data
.sink
= master
;
1205 sink_input_data
.origin_sink
= u
->sink
;
1206 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1207 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1208 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1209 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1211 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1212 pa_sink_input_new_data_done(&sink_input_data
);
1217 u
->sink_input
->pop
= sink_input_pop_cb
;
1218 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1219 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1220 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1221 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1222 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1223 u
->sink_input
->kill
= sink_input_kill_cb
;
1224 u
->sink_input
->attach
= sink_input_attach_cb
;
1225 u
->sink_input
->detach
= sink_input_detach_cb
;
1226 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1227 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1228 u
->sink_input
->moving
= sink_input_moving_cb
;
1229 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1230 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1231 u
->sink_input
->userdata
= u
;
1233 u
->sink
->input_to_master
= u
->sink_input
;
1237 /* default filter to these */
1238 for (c
= 0; c
< u
->channels
; ++c
) {
1239 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1241 u
->Xs
[c
][a_i
] = 1.0f
;
1243 for(i
= 0; i
< FILTER_SIZE(u
); ++i
)
1244 H
[i
] = 1.0 / sqrtf(2.0f
);
1246 fix_filter(H
, u
->fft_size
);
1247 pa_aupdate_write_end(u
->a_H
[c
]);
1250 /* load old parameters */
1253 pa_sink_put(u
->sink
);
1254 pa_sink_input_put(u
->sink_input
);
1256 pa_modargs_free(ma
);
1262 pa_modargs_free(ma
);
1269 int pa__get_n_used(pa_module
*m
) {
1273 pa_assert_se(u
= m
->userdata
);
1275 return pa_sink_linked_by(u
->sink
);
1278 void pa__done(pa_module
*m
) {
1284 if (!(u
= m
->userdata
))
1291 for(c
= 0; c
< u
->channels
; ++c
)
1292 pa_xfree(u
->base_profiles
[c
]);
1293 pa_xfree(u
->base_profiles
);
1295 /* See comments in sink_input_kill_cb() above regarding
1296 * destruction order! */
1299 pa_sink_input_unlink(u
->sink_input
);
1302 pa_sink_unlink(u
->sink
);
1305 pa_sink_input_unref(u
->sink_input
);
1308 pa_sink_unref(u
->sink
);
1310 pa_xfree(u
->output_buffer
);
1311 pa_memblockq_free(u
->output_q
);
1312 pa_memblockq_free(u
->input_q
);
1314 fftwf_destroy_plan(u
->inverse_plan
);
1315 fftwf_destroy_plan(u
->forward_plan
);
1316 pa_xfree(u
->output_window
);
1317 for (c
= 0; c
< u
->channels
; ++c
) {
1318 pa_aupdate_free(u
->a_H
[c
]);
1319 pa_xfree(u
->overlap_accum
[c
]);
1320 pa_xfree(u
->input
[c
]);
1323 pa_xfree(u
->overlap_accum
);
1325 pa_xfree(u
->work_buffer
);
1327 for (c
= 0; c
< u
->channels
; ++c
) {
1329 for (size_t i
= 0; i
< 2; ++i
)
1330 pa_xfree(u
->Hs
[c
][i
]);
1340 * DBus Routines and Callbacks
1342 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1343 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1344 #define MANAGER_IFACE EXTNAME ".Manager"
1345 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1346 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1347 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1348 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1349 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1350 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1351 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1352 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1353 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1354 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1355 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1356 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1357 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1358 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1359 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1360 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1361 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1362 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1363 static void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1364 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1365 enum manager_method_index
{
1366 MANAGER_METHOD_REMOVE_PROFILE
,
1370 pa_dbus_arg_info remove_profile_args
[]={
1374 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1375 [MANAGER_METHOD_REMOVE_PROFILE
]{
1376 .method_name
="RemoveProfile",
1377 .arguments
=remove_profile_args
,
1378 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1379 .receive_cb
=manager_handle_remove_profile
}
1382 enum manager_handler_index
{
1383 MANAGER_HANDLER_REVISION
,
1384 MANAGER_HANDLER_EQUALIZED_SINKS
,
1385 MANAGER_HANDLER_PROFILES
,
1389 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1390 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1391 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1392 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1395 pa_dbus_arg_info sink_args
[]={
1399 enum manager_signal_index
{
1400 MANAGER_SIGNAL_SINK_ADDED
,
1401 MANAGER_SIGNAL_SINK_REMOVED
,
1402 MANAGER_SIGNAL_PROFILES_CHANGED
,
1406 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1407 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1408 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1409 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1412 static pa_dbus_interface_info manager_info
={
1413 .name
=MANAGER_IFACE
,
1414 .method_handlers
=manager_methods
,
1415 .n_method_handlers
=MANAGER_METHOD_MAX
,
1416 .property_handlers
=manager_handlers
,
1417 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1418 .get_all_properties_cb
=manager_get_all
,
1419 .signals
=manager_signals
,
1420 .n_signals
=MANAGER_SIGNAL_MAX
1423 enum equalizer_method_index
{
1424 EQUALIZER_METHOD_FILTER_POINTS
,
1425 EQUALIZER_METHOD_SEED_FILTER
,
1426 EQUALIZER_METHOD_SAVE_PROFILE
,
1427 EQUALIZER_METHOD_LOAD_PROFILE
,
1428 EQUALIZER_METHOD_SET_FILTER
,
1429 EQUALIZER_METHOD_GET_FILTER
,
1430 EQUALIZER_METHOD_SAVE_STATE
,
1431 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1432 EQUALIZER_METHOD_MAX
1435 enum equalizer_handler_index
{
1436 EQUALIZER_HANDLER_REVISION
,
1437 EQUALIZER_HANDLER_SAMPLERATE
,
1438 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1439 EQUALIZER_HANDLER_N_COEFS
,
1440 EQUALIZER_HANDLER_N_CHANNELS
,
1441 EQUALIZER_HANDLER_MAX
1444 pa_dbus_arg_info filter_points_args
[]={
1445 {"channel", "u","in"},
1448 {"preamp", "d","out"}
1450 pa_dbus_arg_info seed_filter_args
[]={
1451 {"channel", "u","in"},
1454 {"preamp", "d","in"}
1457 pa_dbus_arg_info set_filter_args
[]={
1458 {"channel", "u","in"},
1460 {"preamp", "d","in"}
1462 pa_dbus_arg_info get_filter_args
[]={
1463 {"channel", "u","in"},
1465 {"preamp", "d","out"}
1468 pa_dbus_arg_info save_profile_args
[]={
1469 {"channel", "u","in"},
1472 pa_dbus_arg_info load_profile_args
[]={
1473 {"channel", "u","in"},
1476 pa_dbus_arg_info base_profile_name_args
[]={
1477 {"channel", "u","in"},
1481 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1482 [EQUALIZER_METHOD_SEED_FILTER
]{
1483 .method_name
="SeedFilter",
1484 .arguments
=seed_filter_args
,
1485 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1486 .receive_cb
=equalizer_handle_seed_filter
},
1487 [EQUALIZER_METHOD_FILTER_POINTS
]{
1488 .method_name
="FilterAtPoints",
1489 .arguments
=filter_points_args
,
1490 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1491 .receive_cb
=equalizer_handle_get_filter_points
},
1492 [EQUALIZER_METHOD_SET_FILTER
]{
1493 .method_name
="SetFilter",
1494 .arguments
=set_filter_args
,
1495 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1496 .receive_cb
=equalizer_handle_set_filter
},
1497 [EQUALIZER_METHOD_GET_FILTER
]{
1498 .method_name
="GetFilter",
1499 .arguments
=get_filter_args
,
1500 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1501 .receive_cb
=equalizer_handle_get_filter
},
1502 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1503 .method_name
="SaveProfile",
1504 .arguments
=save_profile_args
,
1505 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1506 .receive_cb
=equalizer_handle_save_profile
},
1507 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1508 .method_name
="LoadProfile",
1509 .arguments
=load_profile_args
,
1510 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1511 .receive_cb
=equalizer_handle_load_profile
},
1512 [EQUALIZER_METHOD_SAVE_STATE
]{
1513 .method_name
="SaveState",
1516 .receive_cb
=equalizer_handle_save_state
},
1517 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1518 .method_name
="BaseProfile",
1519 .arguments
=base_profile_name_args
,
1520 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1521 .receive_cb
=equalizer_handle_get_profile_name
}
1524 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1525 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1526 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1527 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1528 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1529 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1532 enum equalizer_signal_index
{
1533 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1534 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1535 EQUALIZER_SIGNAL_MAX
1538 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1539 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1540 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1543 static pa_dbus_interface_info equalizer_info
={
1544 .name
=EQUALIZER_IFACE
,
1545 .method_handlers
=equalizer_methods
,
1546 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1547 .property_handlers
=equalizer_handlers
,
1548 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1549 .get_all_properties_cb
=equalizer_get_all
,
1550 .signals
=equalizer_signals
,
1551 .n_signals
=EQUALIZER_SIGNAL_MAX
1554 void dbus_init(struct userdata
*u
){
1556 DBusMessage
*signal
= NULL
;
1557 pa_idxset
*sink_list
= NULL
;
1558 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1559 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1561 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1562 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1563 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1564 if(sink_list
== NULL
){
1566 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1567 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1568 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1569 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1571 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1572 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1573 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1575 pa_idxset_put(sink_list
, u
, &dummy
);
1577 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1578 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1579 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1580 dbus_message_unref(signal
);
1583 void dbus_done(struct userdata
*u
){
1584 pa_idxset
*sink_list
;
1587 DBusMessage
*signal
= NULL
;
1588 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1589 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1590 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1591 dbus_message_unref(signal
);
1593 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1594 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1595 if(pa_idxset_size(sink_list
)==0){
1596 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1597 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1598 pa_shared_remove(u
->sink
->core
, EQDB
);
1599 pa_database_close(u
->database
);
1600 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1601 pa_xfree(sink_list
);
1603 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1604 pa_xfree(u
->dbus_path
);
1605 pa_dbus_protocol_unref(u
->dbus_protocol
);
1608 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1610 pa_core
*c
= (pa_core
*)_u
;
1611 DBusMessage
*signal
= NULL
;
1612 pa_dbus_protocol
*dbus_protocol
;
1617 dbus_error_init(&error
);
1618 if(!dbus_message_get_args(msg
, &error
,
1619 DBUS_TYPE_STRING
, &name
,
1620 DBUS_TYPE_INVALID
)){
1621 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1622 dbus_error_free(&error
);
1625 remove_profile(c
,name
);
1626 pa_dbus_send_empty_reply(conn
, msg
);
1628 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1629 dbus_protocol
= pa_dbus_protocol_get(c
);
1630 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1631 pa_dbus_protocol_unref(dbus_protocol
);
1632 dbus_message_unref(signal
);
1635 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1637 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1640 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1642 struct userdata
*sink_u
= NULL
;
1644 pa_idxset
*sink_list
;
1649 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1650 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1651 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1652 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1653 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1654 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1658 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1660 char **names
= NULL
;
1665 get_sinks((pa_core
*) _u
, &names
, &n
);
1666 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1667 for(unsigned i
= 0; i
< n
; ++i
){
1673 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1675 pa_database
*database
;
1676 pa_datum key
, next_key
;
1677 pa_strlist
*head
=NULL
, *iter
;
1679 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1684 done
= !pa_database_first(database
, &key
, NULL
);
1687 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1688 name
=pa_xmalloc(key
.size
+ 1);
1689 memcpy(name
, key
.data
, key
.size
);
1690 name
[key
.size
] = '\0';
1691 pa_datum_free(&key
);
1692 head
= pa_strlist_prepend(head
, name
);
1697 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1699 for(unsigned i
= 0; i
< *n
; ++i
){
1700 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1701 iter
= pa_strlist_next(iter
);
1703 pa_strlist_free(head
);
1706 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1713 get_profiles((pa_core
*)_u
, &names
, &n
);
1714 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1715 for(unsigned i
= 0; i
< n
; ++i
){
1721 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1723 char **names
= NULL
;
1725 DBusMessage
*reply
= NULL
;
1726 DBusMessageIter msg_iter
, dict_iter
;
1730 pa_assert_se(c
= _u
);
1732 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1733 dbus_message_iter_init_append(reply
, &msg_iter
);
1734 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1737 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1739 get_sinks(c
, &names
, &n
);
1740 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1741 for(unsigned i
= 0; i
< n
; ++i
){
1746 get_profiles(c
, &names
, &n
);
1747 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1748 for(unsigned i
= 0; i
< n
; ++i
){
1752 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1753 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1754 dbus_message_unref(reply
);
1757 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1758 struct userdata
*u
= _u
;
1760 DBusMessage
*signal
= NULL
;
1762 uint32_t *xs
, channel
, r_channel
;
1763 double *_ys
, preamp
;
1764 unsigned x_npoints
, y_npoints
, a_i
;
1766 pa_bool_t points_good
= TRUE
;
1772 dbus_error_init(&error
);
1774 if(!dbus_message_get_args(msg
, &error
,
1775 DBUS_TYPE_UINT32
, &channel
,
1776 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1777 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1778 DBUS_TYPE_DOUBLE
, &preamp
,
1779 DBUS_TYPE_INVALID
)){
1780 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1781 dbus_error_free(&error
);
1784 if(channel
> u
->channels
){
1785 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1786 dbus_error_free(&error
);
1789 for(size_t i
= 0; i
< x_npoints
; ++i
){
1790 if(xs
[i
] >= FILTER_SIZE(u
)){
1791 points_good
= FALSE
;
1795 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1796 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1797 dbus_error_free(&error
);
1799 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE(u
)){
1800 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE(u
));
1801 dbus_error_free(&error
);
1803 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1804 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1805 dbus_error_free(&error
);
1809 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1810 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1811 ys
[i
] = (float) _ys
[i
];
1813 r_channel
= channel
== u
->channels
? 0 : channel
;
1814 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1815 H
= u
->Hs
[r_channel
][a_i
];
1816 u
->Xs
[r_channel
][a_i
] = preamp
;
1817 interpolate(H
, FILTER_SIZE(u
), xs
, ys
, x_npoints
);
1818 fix_filter(H
, u
->fft_size
);
1819 if(channel
== u
->channels
){
1820 for(size_t c
= 1; c
< u
->channels
; ++c
){
1821 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1822 float *H_p
= u
->Hs
[c
][b_i
];
1823 u
->Xs
[c
][b_i
] = preamp
;
1824 memcpy(H_p
, H
, FILTER_SIZE(u
) * sizeof(float));
1825 pa_aupdate_write_end(u
->a_H
[c
]);
1828 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1832 pa_dbus_send_empty_reply(conn
, msg
);
1834 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1835 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1836 dbus_message_unref(signal
);
1839 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1840 struct userdata
*u
= (struct userdata
*) _u
;
1841 uint32_t *xs
, channel
, r_channel
;
1843 unsigned x_npoints
, a_i
;
1845 pa_bool_t points_good
=TRUE
;
1846 DBusMessage
*reply
= NULL
;
1847 DBusMessageIter msg_iter
;
1854 dbus_error_init(&error
);
1855 if(!dbus_message_get_args(msg
, &error
,
1856 DBUS_TYPE_UINT32
, &channel
,
1857 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1858 DBUS_TYPE_INVALID
)){
1859 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1860 dbus_error_free(&error
);
1863 if(channel
> u
->channels
){
1864 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1865 dbus_error_free(&error
);
1869 for(size_t i
= 0; i
< x_npoints
; ++i
){
1870 if(xs
[i
] >= FILTER_SIZE(u
)){
1876 if(x_npoints
> FILTER_SIZE(u
) || !points_good
){
1877 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE(u
));
1878 dbus_error_free(&error
);
1882 r_channel
= channel
== u
->channels
? 0 : channel
;
1883 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1884 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1885 H
= u
->Hs
[r_channel
][a_i
];
1886 preamp
= u
->Xs
[r_channel
][a_i
];
1887 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1888 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1890 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1892 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1893 dbus_message_iter_init_append(reply
, &msg_iter
);
1895 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1896 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1898 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1899 dbus_message_unref(reply
);
1903 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1906 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1907 *H_
= pa_xnew0(double, FILTER_SIZE(u
));
1908 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1909 H
= u
->Hs
[r_channel
][a_i
];
1910 for(size_t i
= 0;i
< FILTER_SIZE(u
); ++i
){
1911 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1913 *preamp
= u
->Xs
[r_channel
][a_i
];
1915 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1918 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1923 DBusMessage
*reply
= NULL
;
1924 DBusMessageIter msg_iter
;
1926 pa_assert_se(u
= (struct userdata
*) _u
);
1930 dbus_error_init(&error
);
1931 if(!dbus_message_get_args(msg
, &error
,
1932 DBUS_TYPE_UINT32
, &channel
,
1933 DBUS_TYPE_INVALID
)){
1934 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1935 dbus_error_free(&error
);
1938 if(channel
> u
->channels
){
1939 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1940 dbus_error_free(&error
);
1944 n_coefs
= CHANNEL_PROFILE_SIZE(u
);
1947 get_filter(u
, channel
, &H_
, &preamp
);
1948 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1949 dbus_message_iter_init_append(reply
, &msg_iter
);
1951 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1952 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1954 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1955 dbus_message_unref(reply
);
1959 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1961 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1964 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1965 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1966 H
= u
->Hs
[r_channel
][a_i
];
1967 for(size_t i
= 0; i
< FILTER_SIZE(u
); ++i
){
1968 H
[i
] = (float) H_
[i
];
1970 fix_filter(H
, u
->fft_size
);
1971 if(channel
== u
->channels
){
1972 for(size_t c
= 1; c
< u
->channels
; ++c
){
1973 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1974 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1975 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE(u
) * sizeof(float));
1976 pa_aupdate_write_end(u
->a_H
[c
]);
1979 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1982 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1987 DBusMessage
*signal
= NULL
;
1989 pa_assert_se(u
= (struct userdata
*) _u
);
1993 dbus_error_init(&error
);
1994 if(!dbus_message_get_args(msg
, &error
,
1995 DBUS_TYPE_UINT32
, &channel
,
1996 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1997 DBUS_TYPE_DOUBLE
, &preamp
,
1998 DBUS_TYPE_INVALID
)){
1999 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2000 dbus_error_free(&error
);
2003 if(channel
> u
->channels
){
2004 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2005 dbus_error_free(&error
);
2008 if(_n_coefs
!= FILTER_SIZE(u
)){
2009 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE(u
), _n_coefs
);
2012 set_filter(u
, channel
, H
, preamp
);
2014 pa_dbus_send_empty_reply(conn
, msg
);
2016 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2017 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2018 dbus_message_unref(signal
);
2021 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2022 struct userdata
*u
= (struct userdata
*) _u
;
2024 uint32_t channel
, r_channel
;
2025 DBusMessage
*signal
= NULL
;
2030 dbus_error_init(&error
);
2032 if(!dbus_message_get_args(msg
, &error
,
2033 DBUS_TYPE_UINT32
, &channel
,
2034 DBUS_TYPE_STRING
, &name
,
2035 DBUS_TYPE_INVALID
)){
2036 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2037 dbus_error_free(&error
);
2040 if(channel
> u
->channels
){
2041 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2042 dbus_error_free(&error
);
2045 r_channel
= channel
== u
->channels
? 0 : channel
;
2046 save_profile(u
, r_channel
, name
);
2047 pa_dbus_send_empty_reply(conn
, msg
);
2049 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
2050 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2051 dbus_message_unref(signal
);
2054 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2055 struct userdata
*u
= (struct userdata
*) _u
;
2058 uint32_t channel
, r_channel
;
2059 const char *err_msg
= NULL
;
2060 DBusMessage
*signal
= NULL
;
2065 dbus_error_init(&error
);
2067 if(!dbus_message_get_args(msg
, &error
,
2068 DBUS_TYPE_UINT32
, &channel
,
2069 DBUS_TYPE_STRING
, &name
,
2070 DBUS_TYPE_INVALID
)){
2071 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2072 dbus_error_free(&error
);
2075 if(channel
> u
->channels
){
2076 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2077 dbus_error_free(&error
);
2080 r_channel
= channel
== u
->channels
? 0 : channel
;
2082 err_msg
= load_profile(u
, r_channel
, name
);
2083 if(err_msg
!= NULL
){
2084 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2085 dbus_error_free(&error
);
2088 if(channel
== u
->channels
){
2089 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2090 load_profile(u
, c
, name
);
2093 pa_dbus_send_empty_reply(conn
, msg
);
2095 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2096 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2097 dbus_message_unref(signal
);
2100 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2101 struct userdata
*u
= (struct userdata
*) _u
;
2107 pa_dbus_send_empty_reply(conn
, msg
);
2110 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2111 struct userdata
*u
= (struct userdata
*) _u
;
2113 uint32_t channel
, r_channel
;
2118 dbus_error_init(&error
);
2120 if(!dbus_message_get_args(msg
, &error
,
2121 DBUS_TYPE_UINT32
, &channel
,
2122 DBUS_TYPE_INVALID
)){
2123 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2124 dbus_error_free(&error
);
2127 if(channel
> u
->channels
){
2128 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2129 dbus_error_free(&error
);
2132 r_channel
= channel
== u
->channels
? 0 : channel
;
2133 pa_assert(u
->base_profiles
[r_channel
]);
2134 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2137 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2139 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2142 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2145 pa_assert_se(u
= (struct userdata
*) _u
);
2149 channels
= (uint32_t) u
->channels
;
2150 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2153 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2156 pa_assert_se(u
= (struct userdata
*) _u
);
2160 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2161 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2164 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2167 pa_assert_se(u
= (struct userdata
*) _u
);
2171 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2172 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2175 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2178 pa_assert_se(u
= (struct userdata
*) _u
);
2182 fft_size
= (uint32_t) u
->fft_size
;
2183 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2186 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2188 DBusMessage
*reply
= NULL
;
2189 DBusMessageIter msg_iter
, dict_iter
;
2190 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2192 pa_assert_se(u
= _u
);
2196 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2197 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2198 fft_size
= (uint32_t) u
->fft_size
;
2199 channels
= (uint32_t) u
->channels
;
2201 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2202 dbus_message_iter_init_append(reply
, &msg_iter
);
2203 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2205 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2206 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2207 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2208 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2209 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2211 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2212 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2213 dbus_message_unref(reply
);