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 "master=<sink to connect to> "
82 "format=<sample format> "
84 "channels=<number of channels> "
85 "channel_map=<channel map>"));
87 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
92 pa_sink_input
*sink_input
;
95 size_t fft_size
;//length (res) of fft
98 *effectively chooses R
100 size_t R
;/* the hop size between overlapping windows
101 * the latency of the filter, calculated from window_size
102 * based on constraints of COLA and window function
104 //for twiddling with pulseaudio
105 size_t overlap_size
;//window_size-R
106 size_t samples_gathered
;
107 size_t input_buffer_max
;
109 float *W
;//windowing function (time domain)
110 float *work_buffer
, **input
, **overlap_accum
;
111 fftwf_complex
*output_window
;
112 fftwf_plan forward_plan
, inverse_plan
;
116 float ***Hs
;//thread updatable copies of the freq response filters (magintude based)
118 pa_memblockq
*input_q
;
120 size_t output_buffer_length
;
121 size_t output_buffer_max_length
;
122 pa_memblockq
*output_q
;
123 pa_bool_t first_iteration
;
125 pa_dbus_protocol
*dbus_protocol
;
128 pa_database
*database
;
129 char **base_profiles
;
132 static const char* const valid_modargs
[] = {
143 #define SINKLIST "equalized_sinklist"
144 #define EQDB "equalizer_db"
145 #define EQ_STATE_DB "equalizer-state"
146 #define FILTER_SIZE(u) ((u)->fft_size / 2 + 1)
147 #define CHANNEL_PROFILE_SIZE(u) (FILTER_SIZE(u) + 1)
148 #define FILTER_STATE_SIZE(u) (CHANNEL_PROFILE_SIZE(u) * (u)->channels)
150 static void dbus_init(struct userdata
*u
);
151 static void dbus_done(struct userdata
*u
);
153 static void hanning_window(float *W
, size_t window_size
){
154 /* h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2 */
155 for (size_t i
= 0; i
< window_size
; ++i
)
156 W
[i
] = (float).5 * (1 - cos(2*M_PI
*i
/ (window_size
+1)));
159 static void fix_filter(float *H
, size_t fft_size
){
160 /* divide out the fft gain */
161 for (size_t i
= 0; i
< fft_size
/ 2 + 1; ++i
)
165 static void interpolate(float *signal
, size_t length
, uint32_t *xs
, float *ys
, size_t n_points
){
166 /* Note that xs must be monotonically increasing! */
167 float x_range_lower
, x_range_upper
, c0
;
169 pa_assert(n_points
>= 2);
170 pa_assert(xs
[0] == 0);
171 pa_assert(xs
[n_points
- 1] == length
- 1);
173 for (size_t x
= 0, x_range_lower_i
= 0; x
< length
-1; ++x
) {
174 pa_assert(x_range_lower_i
< n_points
-1);
176 x_range_lower
= (float) xs
[x_range_lower_i
];
177 x_range_upper
= (float) xs
[x_range_lower_i
+1];
179 pa_assert_se(x_range_lower
< x_range_upper
);
180 pa_assert_se(x
>= x_range_lower
);
181 pa_assert_se(x
<= x_range_upper
);
183 /* bilinear-interpolation of coefficients specified */
184 c0
= (x
-x_range_lower
) / (x_range_upper
-x_range_lower
);
185 pa_assert(c0
>= 0 && c0
<= 1.0);
187 signal
[x
] = ((1.0f
- c0
) * ys
[x_range_lower_i
] + c0
* ys
[x_range_lower_i
+ 1]);
188 while(x
>= xs
[x_range_lower_i
+ 1])
192 signal
[length
-1] = ys
[n_points
-1];
195 static pa_bool_t
is_monotonic(const uint32_t *xs
, size_t length
) {
201 for(size_t i
= 1; i
< length
; ++i
)
202 if (xs
[i
] <= xs
[i
-1])
208 /* ensures memory allocated is a multiple of v_size and aligned */
209 static void * alloc(size_t x
, size_t s
){
213 f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
214 pa_assert_se(t
= fftwf_malloc(f
));
220 static void alloc_input_buffers(struct userdata
*u
, size_t min_buffer_length
){
221 if (min_buffer_length
<= u
->input_buffer_max
)
224 pa_assert(min_buffer_length
>= u
->window_size
);
225 for (size_t c
= 0; c
< u
->channels
; ++c
) {
226 float *tmp
= alloc(min_buffer_length
, sizeof(float));
228 if (!u
->first_iteration
)
229 memcpy(tmp
, u
->input
[c
], u
->overlap_size
* sizeof(float));
234 u
->input_buffer_max
= min_buffer_length
;
237 /* Called from I/O thread context */
238 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
239 struct userdata
*u
= PA_SINK(o
)->userdata
;
243 case PA_SINK_MESSAGE_GET_LATENCY
: {
244 //size_t fs=pa_frame_size(&u->sink->sample_spec);
246 /* The sink is _put() before the sink input is, so let's
247 * make sure we don't access it in that time. Also, the
248 * sink input is first shut down, the sink second. */
249 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
250 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
251 *((pa_usec_t
*) data
) = 0;
255 *((pa_usec_t
*) data
) =
256 /* Get the latency of the master sink */
257 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
259 /* Add the latency internal to our sink input on top */
260 pa_bytes_to_usec(pa_memblockq_get_length(u
->output_q
) +
261 pa_memblockq_get_length(u
->input_q
), &u
->sink_input
->sink
->sample_spec
) +
262 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
263 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
264 //+ pa_bytes_to_usec(u->latency * fs, ss)
269 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
273 /* Called from main context */
274 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
277 pa_sink_assert_ref(s
);
278 pa_assert_se(u
= s
->userdata
);
280 if (!PA_SINK_IS_LINKED(state
) ||
281 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
284 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
288 /* Called from I/O thread context */
289 static void sink_request_rewind_cb(pa_sink
*s
) {
292 pa_sink_assert_ref(s
);
293 pa_assert_se(u
= s
->userdata
);
295 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
296 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
299 /* Just hand this one over to the master sink */
300 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), TRUE
, FALSE
, FALSE
);
303 /* Called from I/O thread context */
304 static void sink_update_requested_latency_cb(pa_sink
*s
) {
307 pa_sink_assert_ref(s
);
308 pa_assert_se(u
= s
->userdata
);
310 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
311 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
314 /* Just hand this one over to the master sink */
315 pa_sink_input_set_requested_latency_within_thread(
317 pa_sink_get_requested_latency_within_thread(s
));
320 /* Called from main context */
321 static void sink_set_volume_cb(pa_sink
*s
) {
324 pa_sink_assert_ref(s
);
325 pa_assert_se(u
= s
->userdata
);
327 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
328 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
331 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
334 /* Called from main context */
335 static void sink_set_mute_cb(pa_sink
*s
) {
338 pa_sink_assert_ref(s
);
339 pa_assert_se(u
= s
->userdata
);
341 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
342 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
345 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
349 //reference implementation
350 static void dsp_logic(
351 float * restrict dst
,//used as a temp array too, needs to be fft_length!
352 float * restrict src
,/*input data w/ overlap at start,
353 *automatically cycled in routine
355 float * restrict overlap
,
356 const float X
,//multipliar
357 const float * restrict H
,//The freq. magnitude scalers filter
358 const float * restrict W
,//The windowing function
359 fftwf_complex
* restrict output_window
,//The transformed window'd src
362 //use a linear-phase sliding STFT and overlap-add method (for each channel)
364 for(size_t j
= 0; j
< u
->window_size
; ++j
){
365 dst
[j
] = X
* W
[j
] * src
[j
];
367 //zero padd the the remaining fft window
368 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
369 //Processing is done here!
371 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
373 for(size_t j
= 0; j
< FILTER_SIZE(u
); ++j
){
374 u
->output_window
[j
][0] *= H
[j
];
375 u
->output_window
[j
][1] *= H
[j
];
378 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
379 ////debug: tests overlaping add
380 ////and negates ALL PREVIOUS processing
381 ////yields a perfect reconstruction if COLA is held
382 //for(size_t j = 0; j < u->window_size; ++j){
383 // u->work_buffer[j] = u->W[j] * u->input[c][j];
386 //overlap add and preserve overlap component from this window (linear phase)
387 for(size_t j
= 0; j
< u
->overlap_size
; ++j
){
388 u
->work_buffer
[j
] += overlap
[j
];
389 overlap
[j
] = dst
[u
->R
+ j
];
391 ////debug: tests if basic buffering works
392 ////shouldn't modify the signal AT ALL (beyond roundoff)
393 //for(size_t j = 0; j < u->window_size;++j){
394 // u->work_buffer[j] = u->input[c][j];
397 //preseve the needed input for the next window's overlap
398 memmove(src
, src
+ u
->R
,
399 (u
->samples_gathered
- u
->R
) * sizeof(float)
403 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
404 typedef union float_vector
{
410 //regardless of sse enabled, the loops in here assume
411 //16 byte aligned addresses and memory allocations divisible by v_size
412 static void dsp_logic(
413 float * restrict dst
,//used as a temp array too, needs to be fft_length!
414 float * restrict src
,/*input data w/ overlap at start,
415 *automatically cycled in routine
417 float * restrict overlap
,//The size of the overlap
418 const float X
,//multipliar
419 const float * restrict H
,//The freq. magnitude scalers filter
420 const float * restrict W
,//The windowing function
421 fftwf_complex
* restrict output_window
,//The transformed window'd src
422 struct userdata
*u
){//Collection of constants
423 const size_t overlap_size
= PA_ROUND_UP(u
->overlap_size
, v_size
);
425 x
.f
[0] = x
.f
[1] = x
.f
[2] = x
.f
[3] = X
;
427 //assert(u->samples_gathered >= u->R);
428 //use a linear-phase sliding STFT and overlap-add method
429 for(size_t j
= 0; j
< u
->window_size
; j
+= v_size
){
430 //dst[j] = W[j] * src[j];
431 float_vector_t
*d
= (float_vector_t
*) (dst
+ j
);
432 float_vector_t
*w
= (float_vector_t
*) (W
+ j
);
433 float_vector_t
*s
= (float_vector_t
*) (src
+ j
);
435 d
->m
= _mm_mul_ps(x
.m
, _mm_mul_ps(w
->m
, s
->m
));
436 // d->v = x->v * w->v * s->v;
439 //zero padd the the remaining fft window
440 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
442 //Processing is done here!
444 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
445 //perform filtering - purely magnitude based
446 for(size_t j
= 0; j
< FILTER_SIZE
; j
+= v_size
/ 2){
447 //output_window[j][0]*=H[j];
448 //output_window[j][1]*=H[j];
449 float_vector_t
*d
= (float_vector_t
*)( ((float *) output_window
) + 2 * j
);
451 h
.f
[0] = h
.f
[1] = H
[j
];
452 h
.f
[2] = h
.f
[3] = H
[j
+ 1];
454 d
->m
= _mm_mul_ps(d
->m
, h
.m
);
456 // d->v = d->v * h.v;
461 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
463 ////debug: tests overlaping add
464 ////and negates ALL PREVIOUS processing
465 ////yields a perfect reconstruction if COLA is held
466 //for(size_t j = 0; j < u->window_size; ++j){
467 // dst[j] = W[j] * src[j];
470 //overlap add and preserve overlap component from this window (linear phase)
471 for(size_t j
= 0; j
< overlap_size
; j
+= v_size
){
472 //dst[j]+=overlap[j];
473 //overlap[j]+=dst[j+R];
474 float_vector_t
*d
= (float_vector_t
*)(dst
+ j
);
475 float_vector_t
*o
= (float_vector_t
*)(overlap
+ j
);
477 d
->m
= _mm_add_ps(d
->m
, o
->m
);
478 o
->m
= ((float_vector_t
*)(dst
+ u
->R
+ j
))->m
;
480 // d->v = d->v + o->v;
481 // o->v = ((float_vector_t*)(dst + u->R + j))->v;
484 //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
485 //zero out the bit beyond the real overlap so we don't add garbage next iteration
486 memset(overlap
+ u
->overlap_size
, 0, overlap_size
- u
->overlap_size
);
488 ////debug: tests if basic buffering works
489 ////shouldn't modify the signal AT ALL (beyond roundoff)
490 //for(size_t j = 0; j < u->window_size; ++j){
494 //preseve the needed input for the next window's overlap
495 memmove(src
, src
+ u
->R
,
496 (u
->samples_gathered
- u
->R
) * sizeof(float)
501 static void flatten_to_memblockq(struct userdata
*u
){
502 size_t mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
506 while(i
< u
->output_buffer_length
){
508 tchunk
.length
= PA_MIN((u
->output_buffer_length
- i
), mbs
);
509 tchunk
.memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
.length
);
510 //pa_log_debug("pushing %ld into the q", tchunk.length);
511 dst
= pa_memblock_acquire(tchunk
.memblock
);
512 memcpy(dst
, u
->output_buffer
+ i
, tchunk
.length
);
513 pa_memblock_release(tchunk
.memblock
);
514 pa_memblockq_push(u
->output_q
, &tchunk
);
515 pa_memblock_unref(tchunk
.memblock
);
520 static void process_samples(struct userdata
*u
){
521 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
524 size_t iterations
, offset
;
525 pa_assert(u
->samples_gathered
>= u
->window_size
);
526 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
527 //make sure there is enough buffer memory allocated
528 if(iterations
* u
->R
* fs
> u
->output_buffer_max_length
){
529 u
->output_buffer_max_length
= iterations
* u
->R
* fs
;
530 pa_xfree(u
->output_buffer
);
531 u
->output_buffer
= pa_xmalloc(u
->output_buffer_max_length
);
533 u
->output_buffer_length
= iterations
* u
->R
* fs
;
535 for(size_t iter
= 0; iter
< iterations
; ++iter
){
536 offset
= iter
* u
->R
* fs
;
537 for(size_t c
= 0;c
< u
->channels
; c
++) {
538 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
551 pa_aupdate_read_end(u
->a_H
[c
]);
552 if(u
->first_iteration
){
553 /* The windowing function will make the audio ramped in, as a cheap fix we can
554 * undo the windowing (for non-zero window values)
556 for(size_t i
= 0; i
< u
->overlap_size
; ++i
){
557 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
560 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (((float *)u
->output_buffer
) + c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
562 if(u
->first_iteration
){
563 u
->first_iteration
= FALSE
;
565 u
->samples_gathered
-= u
->R
;
567 flatten_to_memblockq(u
);
570 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
){
571 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
572 size_t samples
= in
->length
/fs
;
573 float *src
= (float*) ((uint8_t*) pa_memblock_acquire(in
->memblock
) + in
->index
);
574 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
575 for(size_t c
= 0; c
< u
->channels
; c
++) {
576 //buffer with an offset after the overlap from previous
579 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
581 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
583 u
->samples_gathered
+= samples
;
584 pa_memblock_release(in
->memblock
);
587 /* Called from I/O thread context */
588 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
590 size_t fs
, target_samples
;
592 //struct timeval start, end;
595 pa_sink_input_assert_ref(i
);
596 pa_assert_se(u
= i
->userdata
);
600 /* FIXME: Please clean this up. I see more commented code lines
601 * than uncommented code lines. I am sorry, but I am too dumb to
602 * understand this. */
604 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
605 mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
606 if(pa_memblockq_get_length(u
->output_q
) > 0){
607 //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
610 //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
611 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
612 ////pa_log_debug("vanilla mbs = %ld",mbs);
613 //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
614 //mbs = PA_MAX(mbs, u->R);
615 //target_samples = PA_MAX(target_samples, mbs);
616 //pa_log_debug("target samples: %ld", target_samples);
617 if(u
->first_iteration
){
618 //allocate request_size
619 target_samples
= PA_MAX(target_samples
, u
->window_size
);
621 //allocate request_size + overlap
622 target_samples
+= u
->overlap_size
;
624 alloc_input_buffers(u
, target_samples
);
625 //pa_log_debug("post target samples: %ld", target_samples);
626 chunk
->memblock
= NULL
;
628 /* Hmm, process any rewind request that might be queued up */
629 pa_sink_process_rewind(u
->sink
, 0);
631 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
632 //pa_rtclock_get(&start);
634 size_t input_remaining
= target_samples
- u
->samples_gathered
;
635 // pa_log_debug("input remaining %ld samples", input_remaining);
636 pa_assert(input_remaining
> 0);
637 while (pa_memblockq_peek(u
->input_q
, &tchunk
) < 0) {
638 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
639 pa_sink_render_full(u
->sink
, PA_MIN(input_remaining
* fs
, mbs
), &tchunk
);
640 pa_memblockq_push(u
->input_q
, &tchunk
);
641 pa_memblock_unref(tchunk
.memblock
);
643 pa_assert(tchunk
.memblock
);
645 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
647 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
648 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
650 //pa_rtclock_get(start);
651 // pa_log_debug("buffering %ld bytes", tchunk.length);
652 input_buffer(u
, &tchunk
);
653 //pa_rtclock_get(&end);
654 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
655 pa_memblock_unref(tchunk
.memblock
);
656 } while(u
->samples_gathered
< target_samples
);
658 //pa_rtclock_get(&end);
659 //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
661 pa_assert(u
->fft_size
>= u
->window_size
);
662 pa_assert(u
->R
< u
->window_size
);
663 //pa_rtclock_get(&start);
664 /* process a block */
666 //pa_rtclock_get(&end);
667 //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
669 pa_assert_se(pa_memblockq_peek(u
->output_q
, chunk
) >= 0);
670 pa_assert(chunk
->memblock
);
671 pa_memblockq_drop(u
->output_q
, chunk
->length
);
673 /** FIXME: Uh? you need to unref the chunk here! */
675 //pa_log_debug("gave %ld", chunk->length/fs);
676 //pa_log_debug("end pop");
680 /* Called from main context */
681 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
684 pa_sink_input_assert_ref(i
);
685 pa_assert_se(u
= i
->userdata
);
687 pa_sink_volume_changed(u
->sink
, &i
->volume
);
690 /* Called from main context */
691 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
694 pa_sink_input_assert_ref(i
);
695 pa_assert_se(u
= i
->userdata
);
697 pa_sink_mute_changed(u
->sink
, i
->muted
);
700 static void reset_filter(struct userdata
*u
){
701 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
704 u
->samples_gathered
= 0;
706 for(size_t i
= 0; i
< u
->channels
; ++i
)
707 pa_memzero(u
->overlap_accum
[i
], u
->overlap_size
* sizeof(float));
709 u
->first_iteration
= TRUE
;
710 //set buffer size to max request, no overlap copy
711 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
712 max_request
= PA_MAX(max_request
, u
->window_size
);
713 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
716 /* Called from I/O thread context */
717 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
721 pa_log_debug("Rewind callback!");
722 pa_sink_input_assert_ref(i
);
723 pa_assert_se(u
= i
->userdata
);
725 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
728 //max_rewrite = nbytes;
729 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
730 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
731 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
732 u
->sink
->thread_info
.rewind_nbytes
= 0;
735 //invalidate the output q
736 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
737 pa_log("Resetting filter");
738 //reset_filter(u); //this is the "proper" thing to do...
742 pa_sink_process_rewind(u
->sink
, amount
);
743 pa_memblockq_rewind(u
->input_q
, nbytes
);
746 /* Called from I/O thread context */
747 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
750 pa_sink_input_assert_ref(i
);
751 pa_assert_se(u
= i
->userdata
);
753 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
754 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
757 /* Called from I/O thread context */
758 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
762 pa_sink_input_assert_ref(i
);
763 pa_assert_se(u
= i
->userdata
);
765 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
766 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
769 /* Called from I/O thread context */
770 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
773 pa_sink_input_assert_ref(i
);
774 pa_assert_se(u
= i
->userdata
);
776 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
779 /* Called from I/O thread context */
780 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
783 pa_sink_input_assert_ref(i
);
784 pa_assert_se(u
= i
->userdata
);
786 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
789 /* Called from I/O thread context */
790 static void sink_input_detach_cb(pa_sink_input
*i
) {
793 pa_sink_input_assert_ref(i
);
794 pa_assert_se(u
= i
->userdata
);
796 pa_sink_detach_within_thread(u
->sink
);
798 pa_sink_set_rtpoll(u
->sink
, NULL
);
801 /* Called from I/O thread context */
802 static void sink_input_attach_cb(pa_sink_input
*i
) {
804 size_t fs
, max_request
;
806 pa_sink_input_assert_ref(i
);
807 pa_assert_se(u
= i
->userdata
);
809 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
810 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
811 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
813 fs
= pa_frame_size(&u
->sink_input
->sample_spec
);
814 /* set buffer size to max request, no overlap copy */
815 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
816 max_request
= PA_MAX(max_request
, u
->window_size
);
818 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
819 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
821 pa_sink_attach_within_thread(u
->sink
);
824 /* Called from main context */
825 static void sink_input_kill_cb(pa_sink_input
*i
) {
828 pa_sink_input_assert_ref(i
);
829 pa_assert_se(u
= i
->userdata
);
831 /* The order here matters! We first kill the sink input, followed
832 * by the sink. That means the sink callbacks must be protected
833 * against an unconnected sink input! */
834 pa_sink_input_unlink(u
->sink_input
);
835 pa_sink_unlink(u
->sink
);
837 pa_sink_input_unref(u
->sink_input
);
838 u
->sink_input
= NULL
;
840 pa_sink_unref(u
->sink
);
843 pa_module_unload_request(u
->module
, TRUE
);
846 /* Called from IO thread context */
847 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
850 pa_sink_input_assert_ref(i
);
851 pa_assert_se(u
= i
->userdata
);
853 /* If we are added for the first time, ask for a rewinding so that
854 * we are heard right-away. */
855 if (PA_SINK_INPUT_IS_LINKED(state
) &&
856 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
857 pa_log_debug("Requesting rewind due to state change.");
858 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
862 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
){
864 size_t headers
= (1+len
) * sizeof(uint16_t);
866 for(size_t i
= 0; i
< len
; ++i
){
867 t_len
+= strlen(strs
[i
]);
869 *length
= headers
+ t_len
;
870 p
= *packed
= pa_xmalloc0(*length
);
871 *((uint16_t *) p
) = (uint16_t) len
;
872 p
+= sizeof(uint16_t);
873 for(size_t i
= 0; i
< len
; ++i
){
874 uint16_t l
= strlen(strs
[i
]);
875 *((uint16_t *) p
) = (uint16_t) l
;
876 p
+= sizeof(uint16_t);
877 memcpy(p
, strs
[i
], l
);
881 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
){
883 *len
= *((uint16_t *) p
);
884 p
+= sizeof(uint16_t);
885 *strs
= pa_xnew(char *, *len
);
887 for(size_t i
= 0; i
< *len
; ++i
){
888 size_t l
= *((uint16_t *) p
);
889 p
+= sizeof(uint16_t);
890 (*strs
)[i
] = pa_xnew(char, l
+ 1);
891 memcpy((*strs
)[i
], p
, l
);
892 (*strs
)[i
][l
] = '\0';
896 static void save_profile(struct userdata
*u
, size_t channel
, char *name
){
898 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
899 float *H_n
, *profile
;
902 profile
= pa_xnew0(float, profile_size
);
903 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
904 profile
[0] = u
->Xs
[a_i
][channel
];
905 H
= u
->Hs
[channel
][a_i
];
907 for(size_t i
= 0 ; i
<= FILTER_SIZE(u
); ++i
){
908 H_n
[i
] = H
[i
] * u
->fft_size
;
911 pa_aupdate_read_end(u
->a_H
[channel
]);
913 key
.size
= strlen(key
.data
);
915 data
.size
= profile_size
;
916 pa_database_set(u
->database
, &key
, &data
, TRUE
);
917 pa_database_sync(u
->database
);
918 if(u
->base_profiles
[channel
]){
919 pa_xfree(u
->base_profiles
[channel
]);
921 u
->base_profiles
[channel
] = pa_xstrdup(name
);
924 static void save_state(struct userdata
*u
){
926 const size_t filter_state_size
= FILTER_STATE_SIZE(u
) * sizeof(float);
930 pa_database
*database
;
933 size_t packed_length
;
935 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
936 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
937 memcpy(state
+ FILTER_STATE_SIZE(u
), packed
, packed_length
);
940 for(size_t c
= 0; c
< u
->channels
; ++c
){
941 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
942 state
[c
* CHANNEL_PROFILE_SIZE(u
)] = u
->Xs
[c
][a_i
];
944 H_n
= &state
[c
* CHANNEL_PROFILE_SIZE(u
) + 1];
945 memcpy(H_n
, H
, FILTER_SIZE(u
) * sizeof(float));
946 pa_aupdate_read_end(u
->a_H
[c
]);
949 key
.data
= u
->sink
->name
;
950 key
.size
= strlen(key
.data
);
952 data
.size
= filter_state_size
+ packed_length
;
953 //thread safety for 0.9.17?
954 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
955 pa_assert_se(database
= pa_database_open(dbname
, TRUE
));
958 pa_database_set(database
, &key
, &data
, TRUE
);
959 pa_database_sync(database
);
960 pa_database_close(database
);
964 static void remove_profile(pa_core
*c
, char *name
){
966 pa_database
*database
;
968 key
.size
= strlen(key
.data
);
969 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
970 pa_database_unset(database
, &key
);
971 pa_database_sync(database
);
974 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
){
977 const size_t profile_size
= CHANNEL_PROFILE_SIZE(u
) * sizeof(float);
979 key
.size
= strlen(key
.data
);
980 if(pa_database_get(u
->database
, &key
, &value
) != NULL
){
981 if(value
.size
== profile_size
){
982 float *profile
= (float *) value
.data
;
983 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
984 u
->Xs
[channel
][a_i
] = profile
[0];
985 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE(u
) * sizeof(float));
986 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
987 pa_aupdate_write_end(u
->a_H
[channel
]);
988 pa_xfree(u
->base_profiles
[channel
]);
989 u
->base_profiles
[channel
] = pa_xstrdup(name
);
991 return "incompatible size";
993 pa_datum_free(&value
);
995 return "profile doesn't exist";
1000 static void load_state(struct userdata
*u
){
1003 pa_datum key
, value
;
1004 pa_database
*database
;
1006 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
1007 database
= pa_database_open(dbname
, FALSE
);
1010 pa_log("No resume state");
1014 key
.data
= u
->sink
->name
;
1015 key
.size
= strlen(key
.data
);
1017 if(pa_database_get(database
, &key
, &value
) != NULL
){
1018 if(value
.size
> FILTER_STATE_SIZE(u
) * sizeof(float) + sizeof(uint16_t)){
1019 float *state
= (float *) value
.data
;
1022 for(size_t c
= 0; c
< u
->channels
; ++c
){
1023 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1024 H
= state
+ c
* CHANNEL_PROFILE_SIZE(u
) + 1;
1025 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE(u
)];
1026 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE(u
) * sizeof(float));
1027 pa_aupdate_write_end(u
->a_H
[c
]);
1029 unpack(((char *)value
.data
) + FILTER_STATE_SIZE(u
) * sizeof(float), value
.size
- FILTER_STATE_SIZE(u
) * sizeof(float), &names
, &n_profs
);
1030 n_profs
= PA_MIN(n_profs
, u
->channels
);
1031 for(size_t c
= 0; c
< n_profs
; ++c
){
1032 pa_xfree(u
->base_profiles
[c
]);
1033 u
->base_profiles
[c
] = names
[c
];
1037 pa_datum_free(&value
);
1039 pa_log("resume state exists but is wrong size!");
1041 pa_database_close(database
);
1044 /* Called from main context */
1045 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1048 pa_sink_input_assert_ref(i
);
1049 pa_assert_se(u
= i
->userdata
);
1051 return u
->sink
!= dest
;
1054 /* Called from main context */
1055 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1058 pa_sink_input_assert_ref(i
);
1059 pa_assert_se(u
= i
->userdata
);
1062 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1063 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1065 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1068 int pa__init(pa_module
*m
) {
1075 pa_sink_input_new_data sink_input_data
;
1076 pa_sink_new_data sink_data
;
1084 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1085 pa_log("Failed to parse module arguments.");
1089 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
1090 pa_log("Master sink not found");
1094 ss
= master
->sample_spec
;
1095 ss
.format
= PA_SAMPLE_FLOAT32
;
1096 map
= master
->channel_map
;
1097 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1098 pa_log("Invalid sample format specification or channel map");
1102 fs
= pa_frame_size(&ss
);
1104 u
= pa_xnew0(struct userdata
, 1);
1108 u
->channels
= ss
.channels
;
1109 u
->fft_size
= pow(2, ceil(log(ss
.rate
) / log(2)));//probably unstable near corner cases of powers of 2
1110 pa_log_debug("fft size: %ld", u
->fft_size
);
1111 u
->window_size
= 15999;
1112 if (u
->window_size
% 2 == 0)
1114 u
->R
= (u
->window_size
+ 1) / 2;
1115 u
->overlap_size
= u
->window_size
- u
->R
;
1116 u
->samples_gathered
= 0;
1117 u
->input_buffer_max
= 0;
1119 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1120 u
->Xs
= pa_xnew0(float *, u
->channels
);
1121 u
->Hs
= pa_xnew0(float **, u
->channels
);
1123 for (c
= 0; c
< u
->channels
; ++c
) {
1124 u
->Xs
[c
] = pa_xnew0(float, 2);
1125 u
->Hs
[c
] = pa_xnew0(float *, 2);
1126 for (i
= 0; i
< 2; ++i
)
1127 u
->Hs
[c
][i
] = alloc(FILTER_SIZE(u
), sizeof(float));
1130 u
->W
= alloc(u
->window_size
, sizeof(float));
1131 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1132 u
->input
= pa_xnew0(float *, u
->channels
);
1133 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1134 for (c
= 0; c
< u
->channels
; ++c
) {
1135 u
->a_H
[c
] = pa_aupdate_new();
1137 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1139 u
->output_window
= alloc(FILTER_SIZE(u
), sizeof(fftwf_complex
));
1140 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1141 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1143 hanning_window(u
->W
, u
->window_size
);
1144 u
->first_iteration
= TRUE
;
1146 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1147 for (c
= 0; c
< u
->channels
; ++c
)
1148 u
->base_profiles
[c
] = pa_xstrdup("default");
1151 pa_sink_new_data_init(&sink_data
);
1152 sink_data
.driver
= __FILE__
;
1153 sink_data
.module
= m
;
1154 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1155 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1156 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1157 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1159 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1160 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s", z
? z
: master
->name
);
1162 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1163 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1165 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1166 pa_log("Invalid properties");
1167 pa_sink_new_data_done(&sink_data
);
1171 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1172 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1173 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1174 pa_sink_new_data_done(&sink_data
);
1177 pa_log("Failed to create sink.");
1181 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1182 u
->sink
->set_state
= sink_set_state_cb
;
1183 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1184 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1185 u
->sink
->set_volume
= sink_set_volume_cb
;
1186 u
->sink
->set_mute
= sink_set_mute_cb
;
1187 u
->sink
->userdata
= u
;
1189 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1190 u
->output_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, NULL
);
1191 u
->output_buffer
= NULL
;
1192 u
->output_buffer_length
= 0;
1193 u
->output_buffer_max_length
= 0;
1195 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1196 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1198 /* Create sink input */
1199 pa_sink_input_new_data_init(&sink_input_data
);
1200 sink_input_data
.driver
= __FILE__
;
1201 sink_input_data
.module
= m
;
1202 sink_input_data
.sink
= master
;
1203 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1204 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1205 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1206 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1208 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1209 pa_sink_input_new_data_done(&sink_input_data
);
1214 u
->sink_input
->pop
= sink_input_pop_cb
;
1215 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1216 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1217 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1218 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1219 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1220 u
->sink_input
->kill
= sink_input_kill_cb
;
1221 u
->sink_input
->attach
= sink_input_attach_cb
;
1222 u
->sink_input
->detach
= sink_input_detach_cb
;
1223 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1224 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1225 u
->sink_input
->moving
= sink_input_moving_cb
;
1226 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1227 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1229 u
->sink_input
->userdata
= u
;
1233 /* default filter to these */
1234 for (c
= 0; c
< u
->channels
; ++c
) {
1235 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1237 u
->Xs
[c
][a_i
] = 1.0f
;
1239 for(i
= 0; i
< FILTER_SIZE(u
); ++i
)
1240 H
[i
] = 1.0 / sqrtf(2.0f
);
1242 fix_filter(H
, u
->fft_size
);
1243 pa_aupdate_write_end(u
->a_H
[c
]);
1246 /* load old parameters */
1249 pa_sink_put(u
->sink
);
1250 pa_sink_input_put(u
->sink_input
);
1252 pa_modargs_free(ma
);
1258 pa_modargs_free(ma
);
1265 int pa__get_n_used(pa_module
*m
) {
1269 pa_assert_se(u
= m
->userdata
);
1271 return pa_sink_linked_by(u
->sink
);
1274 void pa__done(pa_module
*m
) {
1280 if (!(u
= m
->userdata
))
1287 for(c
= 0; c
< u
->channels
; ++c
)
1288 pa_xfree(u
->base_profiles
[c
]);
1289 pa_xfree(u
->base_profiles
);
1291 /* See comments in sink_input_kill_cb() above regarding
1292 * destruction order! */
1295 pa_sink_input_unlink(u
->sink_input
);
1298 pa_sink_unlink(u
->sink
);
1301 pa_sink_input_unref(u
->sink_input
);
1304 pa_sink_unref(u
->sink
);
1306 pa_xfree(u
->output_buffer
);
1307 pa_memblockq_free(u
->output_q
);
1308 pa_memblockq_free(u
->input_q
);
1310 fftwf_destroy_plan(u
->inverse_plan
);
1311 fftwf_destroy_plan(u
->forward_plan
);
1312 pa_xfree(u
->output_window
);
1313 for (c
= 0; c
< u
->channels
; ++c
) {
1314 pa_aupdate_free(u
->a_H
[c
]);
1315 pa_xfree(u
->overlap_accum
[c
]);
1316 pa_xfree(u
->input
[c
]);
1319 pa_xfree(u
->overlap_accum
);
1321 pa_xfree(u
->work_buffer
);
1323 for (c
= 0; c
< u
->channels
; ++c
) {
1325 for (size_t i
= 0; i
< 2; ++i
)
1326 pa_xfree(u
->Hs
[c
][i
]);
1336 * DBus Routines and Callbacks
1338 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1339 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1340 #define MANAGER_IFACE EXTNAME ".Manager"
1341 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1342 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1343 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1344 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1345 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1346 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1347 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1348 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1349 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1350 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1351 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1352 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1353 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1354 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1355 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1356 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1357 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1358 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1359 static void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1360 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1361 enum manager_method_index
{
1362 MANAGER_METHOD_REMOVE_PROFILE
,
1366 pa_dbus_arg_info remove_profile_args
[]={
1370 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1371 [MANAGER_METHOD_REMOVE_PROFILE
]{
1372 .method_name
="RemoveProfile",
1373 .arguments
=remove_profile_args
,
1374 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1375 .receive_cb
=manager_handle_remove_profile
}
1378 enum manager_handler_index
{
1379 MANAGER_HANDLER_REVISION
,
1380 MANAGER_HANDLER_EQUALIZED_SINKS
,
1381 MANAGER_HANDLER_PROFILES
,
1385 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1386 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1387 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1388 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1391 pa_dbus_arg_info sink_args
[]={
1395 enum manager_signal_index
{
1396 MANAGER_SIGNAL_SINK_ADDED
,
1397 MANAGER_SIGNAL_SINK_REMOVED
,
1398 MANAGER_SIGNAL_PROFILES_CHANGED
,
1402 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1403 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1404 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1405 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1408 static pa_dbus_interface_info manager_info
={
1409 .name
=MANAGER_IFACE
,
1410 .method_handlers
=manager_methods
,
1411 .n_method_handlers
=MANAGER_METHOD_MAX
,
1412 .property_handlers
=manager_handlers
,
1413 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1414 .get_all_properties_cb
=manager_get_all
,
1415 .signals
=manager_signals
,
1416 .n_signals
=MANAGER_SIGNAL_MAX
1419 enum equalizer_method_index
{
1420 EQUALIZER_METHOD_FILTER_POINTS
,
1421 EQUALIZER_METHOD_SEED_FILTER
,
1422 EQUALIZER_METHOD_SAVE_PROFILE
,
1423 EQUALIZER_METHOD_LOAD_PROFILE
,
1424 EQUALIZER_METHOD_SET_FILTER
,
1425 EQUALIZER_METHOD_GET_FILTER
,
1426 EQUALIZER_METHOD_SAVE_STATE
,
1427 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1428 EQUALIZER_METHOD_MAX
1431 enum equalizer_handler_index
{
1432 EQUALIZER_HANDLER_REVISION
,
1433 EQUALIZER_HANDLER_SAMPLERATE
,
1434 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1435 EQUALIZER_HANDLER_N_COEFS
,
1436 EQUALIZER_HANDLER_N_CHANNELS
,
1437 EQUALIZER_HANDLER_MAX
1440 pa_dbus_arg_info filter_points_args
[]={
1441 {"channel", "u","in"},
1444 {"preamp", "d","out"}
1446 pa_dbus_arg_info seed_filter_args
[]={
1447 {"channel", "u","in"},
1450 {"preamp", "d","in"}
1453 pa_dbus_arg_info set_filter_args
[]={
1454 {"channel", "u","in"},
1456 {"preamp", "d","in"}
1458 pa_dbus_arg_info get_filter_args
[]={
1459 {"channel", "u","in"},
1461 {"preamp", "d","out"}
1464 pa_dbus_arg_info save_profile_args
[]={
1465 {"channel", "u","in"},
1468 pa_dbus_arg_info load_profile_args
[]={
1469 {"channel", "u","in"},
1472 pa_dbus_arg_info base_profile_name_args
[]={
1473 {"channel", "u","in"},
1477 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1478 [EQUALIZER_METHOD_SEED_FILTER
]{
1479 .method_name
="SeedFilter",
1480 .arguments
=seed_filter_args
,
1481 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1482 .receive_cb
=equalizer_handle_seed_filter
},
1483 [EQUALIZER_METHOD_FILTER_POINTS
]{
1484 .method_name
="FilterAtPoints",
1485 .arguments
=filter_points_args
,
1486 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1487 .receive_cb
=equalizer_handle_get_filter_points
},
1488 [EQUALIZER_METHOD_SET_FILTER
]{
1489 .method_name
="SetFilter",
1490 .arguments
=set_filter_args
,
1491 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1492 .receive_cb
=equalizer_handle_set_filter
},
1493 [EQUALIZER_METHOD_GET_FILTER
]{
1494 .method_name
="GetFilter",
1495 .arguments
=get_filter_args
,
1496 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1497 .receive_cb
=equalizer_handle_get_filter
},
1498 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1499 .method_name
="SaveProfile",
1500 .arguments
=save_profile_args
,
1501 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1502 .receive_cb
=equalizer_handle_save_profile
},
1503 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1504 .method_name
="LoadProfile",
1505 .arguments
=load_profile_args
,
1506 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1507 .receive_cb
=equalizer_handle_load_profile
},
1508 [EQUALIZER_METHOD_SAVE_STATE
]{
1509 .method_name
="SaveState",
1512 .receive_cb
=equalizer_handle_save_state
},
1513 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1514 .method_name
="BaseProfile",
1515 .arguments
=base_profile_name_args
,
1516 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1517 .receive_cb
=equalizer_handle_get_profile_name
}
1520 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1521 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1522 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1523 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1524 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1525 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1528 enum equalizer_signal_index
{
1529 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1530 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1531 EQUALIZER_SIGNAL_MAX
1534 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1535 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1536 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1539 static pa_dbus_interface_info equalizer_info
={
1540 .name
=EQUALIZER_IFACE
,
1541 .method_handlers
=equalizer_methods
,
1542 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1543 .property_handlers
=equalizer_handlers
,
1544 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1545 .get_all_properties_cb
=equalizer_get_all
,
1546 .signals
=equalizer_signals
,
1547 .n_signals
=EQUALIZER_SIGNAL_MAX
1550 void dbus_init(struct userdata
*u
){
1552 DBusMessage
*signal
= NULL
;
1553 pa_idxset
*sink_list
= NULL
;
1554 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1555 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1557 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1558 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1559 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1560 if(sink_list
== NULL
){
1562 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1563 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1564 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1565 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1567 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1568 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1569 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1571 pa_idxset_put(sink_list
, u
, &dummy
);
1573 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1574 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1575 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1576 dbus_message_unref(signal
);
1579 void dbus_done(struct userdata
*u
){
1580 pa_idxset
*sink_list
;
1583 DBusMessage
*signal
= NULL
;
1584 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1585 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1586 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1587 dbus_message_unref(signal
);
1589 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1590 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1591 if(pa_idxset_size(sink_list
)==0){
1592 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1593 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1594 pa_shared_remove(u
->sink
->core
, EQDB
);
1595 pa_database_close(u
->database
);
1596 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1597 pa_xfree(sink_list
);
1599 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1600 pa_xfree(u
->dbus_path
);
1601 pa_dbus_protocol_unref(u
->dbus_protocol
);
1604 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1606 pa_core
*c
= (pa_core
*)_u
;
1607 DBusMessage
*signal
= NULL
;
1608 pa_dbus_protocol
*dbus_protocol
;
1613 dbus_error_init(&error
);
1614 if(!dbus_message_get_args(msg
, &error
,
1615 DBUS_TYPE_STRING
, &name
,
1616 DBUS_TYPE_INVALID
)){
1617 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1618 dbus_error_free(&error
);
1621 remove_profile(c
,name
);
1622 pa_dbus_send_empty_reply(conn
, msg
);
1624 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1625 dbus_protocol
= pa_dbus_protocol_get(c
);
1626 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1627 pa_dbus_protocol_unref(dbus_protocol
);
1628 dbus_message_unref(signal
);
1631 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1633 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1636 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1638 struct userdata
*sink_u
= NULL
;
1640 pa_idxset
*sink_list
;
1645 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1646 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1647 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1648 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1649 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1650 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1654 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1656 char **names
= NULL
;
1661 get_sinks((pa_core
*) _u
, &names
, &n
);
1662 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1663 for(unsigned i
= 0; i
< n
; ++i
){
1669 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1671 pa_database
*database
;
1672 pa_datum key
, next_key
;
1673 pa_strlist
*head
=NULL
, *iter
;
1675 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1680 done
= !pa_database_first(database
, &key
, NULL
);
1683 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1684 name
=pa_xmalloc(key
.size
+ 1);
1685 memcpy(name
, key
.data
, key
.size
);
1686 name
[key
.size
] = '\0';
1687 pa_datum_free(&key
);
1688 head
= pa_strlist_prepend(head
, name
);
1693 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1695 for(unsigned i
= 0; i
< *n
; ++i
){
1696 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1697 iter
= pa_strlist_next(iter
);
1699 pa_strlist_free(head
);
1702 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1709 get_profiles((pa_core
*)_u
, &names
, &n
);
1710 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1711 for(unsigned i
= 0; i
< n
; ++i
){
1717 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1719 char **names
= NULL
;
1721 DBusMessage
*reply
= NULL
;
1722 DBusMessageIter msg_iter
, dict_iter
;
1726 pa_assert_se(c
= _u
);
1728 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1729 dbus_message_iter_init_append(reply
, &msg_iter
);
1730 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1733 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1735 get_sinks(c
, &names
, &n
);
1736 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1737 for(unsigned i
= 0; i
< n
; ++i
){
1742 get_profiles(c
, &names
, &n
);
1743 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1744 for(unsigned i
= 0; i
< n
; ++i
){
1748 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1749 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1750 dbus_message_unref(reply
);
1753 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1754 struct userdata
*u
= _u
;
1756 DBusMessage
*signal
= NULL
;
1758 uint32_t *xs
, channel
, r_channel
;
1759 double *_ys
, preamp
;
1760 unsigned x_npoints
, y_npoints
, a_i
;
1762 pa_bool_t points_good
= TRUE
;
1768 dbus_error_init(&error
);
1770 if(!dbus_message_get_args(msg
, &error
,
1771 DBUS_TYPE_UINT32
, &channel
,
1772 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1773 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1774 DBUS_TYPE_DOUBLE
, &preamp
,
1775 DBUS_TYPE_INVALID
)){
1776 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1777 dbus_error_free(&error
);
1780 if(channel
> u
->channels
){
1781 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1782 dbus_error_free(&error
);
1785 for(size_t i
= 0; i
< x_npoints
; ++i
){
1786 if(xs
[i
] >= FILTER_SIZE(u
)){
1787 points_good
= FALSE
;
1791 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1792 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1793 dbus_error_free(&error
);
1795 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE(u
)){
1796 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
));
1797 dbus_error_free(&error
);
1799 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1800 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1801 dbus_error_free(&error
);
1805 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1806 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1807 ys
[i
] = (float) _ys
[i
];
1809 r_channel
= channel
== u
->channels
? 0 : channel
;
1810 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1811 H
= u
->Hs
[r_channel
][a_i
];
1812 u
->Xs
[r_channel
][a_i
] = preamp
;
1813 interpolate(H
, FILTER_SIZE(u
), xs
, ys
, x_npoints
);
1814 fix_filter(H
, u
->fft_size
);
1815 if(channel
== u
->channels
){
1816 for(size_t c
= 1; c
< u
->channels
; ++c
){
1817 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1818 float *H_p
= u
->Hs
[c
][b_i
];
1819 u
->Xs
[c
][b_i
] = preamp
;
1820 memcpy(H_p
, H
, FILTER_SIZE(u
) * sizeof(float));
1821 pa_aupdate_write_end(u
->a_H
[c
]);
1824 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1828 pa_dbus_send_empty_reply(conn
, msg
);
1830 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1831 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1832 dbus_message_unref(signal
);
1835 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1836 struct userdata
*u
= (struct userdata
*) _u
;
1837 uint32_t *xs
, channel
, r_channel
;
1839 unsigned x_npoints
, a_i
;
1841 pa_bool_t points_good
=TRUE
;
1842 DBusMessage
*reply
= NULL
;
1843 DBusMessageIter msg_iter
;
1850 dbus_error_init(&error
);
1851 if(!dbus_message_get_args(msg
, &error
,
1852 DBUS_TYPE_UINT32
, &channel
,
1853 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1854 DBUS_TYPE_INVALID
)){
1855 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1856 dbus_error_free(&error
);
1859 if(channel
> u
->channels
){
1860 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1861 dbus_error_free(&error
);
1865 for(size_t i
= 0; i
< x_npoints
; ++i
){
1866 if(xs
[i
] >= FILTER_SIZE(u
)){
1872 if(x_npoints
> FILTER_SIZE(u
) || !points_good
){
1873 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE(u
));
1874 dbus_error_free(&error
);
1878 r_channel
= channel
== u
->channels
? 0 : channel
;
1879 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1880 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1881 H
= u
->Hs
[r_channel
][a_i
];
1882 preamp
= u
->Xs
[r_channel
][a_i
];
1883 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1884 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1886 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1888 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1889 dbus_message_iter_init_append(reply
, &msg_iter
);
1891 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1892 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1894 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1895 dbus_message_unref(reply
);
1899 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1902 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1903 *H_
= pa_xnew0(double, FILTER_SIZE(u
));
1904 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1905 H
= u
->Hs
[r_channel
][a_i
];
1906 for(size_t i
= 0;i
< FILTER_SIZE(u
); ++i
){
1907 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1909 *preamp
= u
->Xs
[r_channel
][a_i
];
1911 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1914 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1919 DBusMessage
*reply
= NULL
;
1920 DBusMessageIter msg_iter
;
1922 pa_assert_se(u
= (struct userdata
*) _u
);
1926 dbus_error_init(&error
);
1927 if(!dbus_message_get_args(msg
, &error
,
1928 DBUS_TYPE_UINT32
, &channel
,
1929 DBUS_TYPE_INVALID
)){
1930 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1931 dbus_error_free(&error
);
1934 if(channel
> u
->channels
){
1935 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1936 dbus_error_free(&error
);
1940 n_coefs
= CHANNEL_PROFILE_SIZE(u
);
1943 get_filter(u
, channel
, &H_
, &preamp
);
1944 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1945 dbus_message_iter_init_append(reply
, &msg_iter
);
1947 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1948 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1950 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1951 dbus_message_unref(reply
);
1955 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1957 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1960 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1961 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1962 H
= u
->Hs
[r_channel
][a_i
];
1963 for(size_t i
= 0; i
< FILTER_SIZE(u
); ++i
){
1964 H
[i
] = (float) H_
[i
];
1966 fix_filter(H
, u
->fft_size
);
1967 if(channel
== u
->channels
){
1968 for(size_t c
= 1; c
< u
->channels
; ++c
){
1969 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1970 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1971 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE(u
) * sizeof(float));
1972 pa_aupdate_write_end(u
->a_H
[c
]);
1975 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1978 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1983 DBusMessage
*signal
= NULL
;
1985 pa_assert_se(u
= (struct userdata
*) _u
);
1989 dbus_error_init(&error
);
1990 if(!dbus_message_get_args(msg
, &error
,
1991 DBUS_TYPE_UINT32
, &channel
,
1992 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1993 DBUS_TYPE_DOUBLE
, &preamp
,
1994 DBUS_TYPE_INVALID
)){
1995 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1996 dbus_error_free(&error
);
1999 if(channel
> u
->channels
){
2000 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2001 dbus_error_free(&error
);
2004 if(_n_coefs
!= FILTER_SIZE(u
)){
2005 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE(u
), _n_coefs
);
2008 set_filter(u
, channel
, H
, preamp
);
2010 pa_dbus_send_empty_reply(conn
, msg
);
2012 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2013 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2014 dbus_message_unref(signal
);
2017 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2018 struct userdata
*u
= (struct userdata
*) _u
;
2020 uint32_t channel
, r_channel
;
2021 DBusMessage
*signal
= NULL
;
2026 dbus_error_init(&error
);
2028 if(!dbus_message_get_args(msg
, &error
,
2029 DBUS_TYPE_UINT32
, &channel
,
2030 DBUS_TYPE_STRING
, &name
,
2031 DBUS_TYPE_INVALID
)){
2032 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2033 dbus_error_free(&error
);
2036 if(channel
> u
->channels
){
2037 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2038 dbus_error_free(&error
);
2041 r_channel
= channel
== u
->channels
? 0 : channel
;
2042 save_profile(u
, r_channel
, name
);
2043 pa_dbus_send_empty_reply(conn
, msg
);
2045 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
2046 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2047 dbus_message_unref(signal
);
2050 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2051 struct userdata
*u
= (struct userdata
*) _u
;
2054 uint32_t channel
, r_channel
;
2055 const char *err_msg
= NULL
;
2056 DBusMessage
*signal
= NULL
;
2061 dbus_error_init(&error
);
2063 if(!dbus_message_get_args(msg
, &error
,
2064 DBUS_TYPE_UINT32
, &channel
,
2065 DBUS_TYPE_STRING
, &name
,
2066 DBUS_TYPE_INVALID
)){
2067 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2068 dbus_error_free(&error
);
2071 if(channel
> u
->channels
){
2072 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2073 dbus_error_free(&error
);
2076 r_channel
= channel
== u
->channels
? 0 : channel
;
2078 err_msg
= load_profile(u
, r_channel
, name
);
2079 if(err_msg
!= NULL
){
2080 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2081 dbus_error_free(&error
);
2084 if(channel
== u
->channels
){
2085 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2086 load_profile(u
, c
, name
);
2089 pa_dbus_send_empty_reply(conn
, msg
);
2091 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2092 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2093 dbus_message_unref(signal
);
2096 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2097 struct userdata
*u
= (struct userdata
*) _u
;
2103 pa_dbus_send_empty_reply(conn
, msg
);
2106 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2107 struct userdata
*u
= (struct userdata
*) _u
;
2109 uint32_t channel
, r_channel
;
2114 dbus_error_init(&error
);
2116 if(!dbus_message_get_args(msg
, &error
,
2117 DBUS_TYPE_UINT32
, &channel
,
2118 DBUS_TYPE_INVALID
)){
2119 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2120 dbus_error_free(&error
);
2123 if(channel
> u
->channels
){
2124 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2125 dbus_error_free(&error
);
2128 r_channel
= channel
== u
->channels
? 0 : channel
;
2129 pa_assert(u
->base_profiles
[r_channel
]);
2130 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2133 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2135 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2138 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2141 pa_assert_se(u
= (struct userdata
*) _u
);
2145 channels
= (uint32_t) u
->channels
;
2146 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2149 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2152 pa_assert_se(u
= (struct userdata
*) _u
);
2156 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2157 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2160 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2163 pa_assert_se(u
= (struct userdata
*) _u
);
2167 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2168 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2171 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2174 pa_assert_se(u
= (struct userdata
*) _u
);
2178 fft_size
= (uint32_t) u
->fft_size
;
2179 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2182 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2184 DBusMessage
*reply
= NULL
;
2185 DBusMessageIter msg_iter
, dict_iter
;
2186 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2188 pa_assert_se(u
= _u
);
2192 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE(u
);
2193 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2194 fft_size
= (uint32_t) u
->fft_size
;
2195 channels
= (uint32_t) u
->channels
;
2197 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2198 dbus_message_iter_init_append(reply
, &msg_iter
);
2199 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2201 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2202 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2203 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2204 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2205 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2207 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2208 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2209 dbus_message_unref(reply
);