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.
7 Copyright 2009 Jason Newton <nevion@gmail.com>
10 Copyright 2004-2008 Lennart Poettering
12 PulseAudio is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published
14 by the Free Software Foundation; either version 2.1 of the License,
15 or (at your option) any later version.
17 PulseAudio is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with PulseAudio; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <pulse/xmalloc.h>
40 #include <pulse/i18n.h>
41 #include <pulse/timeval.h>
43 #include <pulsecore/core-rtclock.h>
44 #include <pulsecore/aupdate.h>
45 #include <pulsecore/core-error.h>
46 #include <pulsecore/namereg.h>
47 #include <pulsecore/sink.h>
48 #include <pulsecore/module.h>
49 #include <pulsecore/core-util.h>
50 #include <pulsecore/modargs.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/thread.h>
53 #include <pulsecore/thread-mq.h>
54 #include <pulsecore/rtpoll.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/shared.h>
57 #include <pulsecore/idxset.h>
58 #include <pulsecore/strlist.h>
59 #include <pulsecore/database.h>
60 #include <pulsecore/protocol-dbus.h>
61 #include <pulsecore/dbus-util.h>
69 #include <xmmintrin.h>
70 #include <emmintrin.h>
75 #include "module-equalizer-sink-symdef.h"
77 PA_MODULE_AUTHOR("Jason Newton");
78 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
79 PA_MODULE_VERSION(PACKAGE_VERSION
);
80 PA_MODULE_LOAD_ONCE(FALSE
);
81 PA_MODULE_USAGE(_("sink=<sink to connect to> "));
83 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
89 pa_sink_input
*sink_input
;
93 size_t fft_size
;//length (res) of fft
96 *effectively chooses R
98 size_t R
;/* the hop size between overlapping windows
99 * the latency of the filter, calculated from window_size
100 * based on constraints of COLA and window function
102 //for twiddling with pulseaudio
103 size_t overlap_size
;//window_size-R
104 size_t samples_gathered
;
105 size_t input_buffer_max
;
107 float *W
;//windowing function (time domain)
108 float *work_buffer
, **input
, **overlap_accum
;
109 fftwf_complex
*output_window
;
110 fftwf_plan forward_plan
, inverse_plan
;
114 float ***Hs
;//thread updatable copies of the freq response filters (magintude based)
116 pa_memblockq
*input_q
;
118 size_t output_buffer_length
;
119 size_t output_buffer_max_length
;
120 pa_memblockq
*output_q
;
121 pa_bool_t first_iteration
;
123 pa_dbus_protocol
*dbus_protocol
;
125 pa_bool_t set_default
;
127 pa_database
*database
;
128 char **base_profiles
;
131 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->fft_size / 2 + 1)
149 #define CHANNEL_PROFILE_SIZE (FILTER_SIZE + 1)
150 #define FILTER_STATE_SIZE (CHANNEL_PROFILE_SIZE * u->channels)
151 static void dbus_init(struct userdata
*u
);
152 static void dbus_done(struct userdata
*u
);
154 static void hanning_window(float *W
, size_t window_size
){
155 //h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2
156 for(size_t i
=0; i
< window_size
;++i
){
157 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
){
168 static void interpolate(float *signal
, size_t length
, uint32_t *xs
, float *ys
, size_t n_points
){
169 //Note that xs must be monotonically increasing!
170 float x_range_lower
, x_range_upper
, c0
;
171 pa_assert_se(n_points
>=2);
172 pa_assert_se(xs
[0] == 0);
173 pa_assert_se(xs
[n_points
- 1] == length
- 1);
174 for(size_t x
= 0, x_range_lower_i
= 0; x
< length
-1; ++x
){
175 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]);
178 pa_assert_se(x_range_lower
< x_range_upper
);
179 pa_assert_se(x
>= x_range_lower
);
180 pa_assert_se(x
<= x_range_upper
);
181 //bilinear-interpolation of coefficients specified
182 c0
= (x
-x_range_lower
)/(x_range_upper
-x_range_lower
);
183 pa_assert_se(c0
>= 0&&c0
<= 1.0);
184 signal
[x
] = ((1.0f
- c0
) * ys
[x_range_lower_i
] + c0
* ys
[x_range_lower_i
+ 1]);
185 while(x
>= xs
[x_range_lower_i
+ 1]){
189 signal
[length
-1]=ys
[n_points
-1];
192 static int is_monotonic(const uint32_t *xs
,size_t length
){
196 for(size_t i
= 1; i
< length
; ++i
){
204 //ensure's memory allocated is a multiple of v_size
206 static void * alloc(size_t x
,size_t s
){
207 size_t f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
215 static void alloc_input_buffers(struct userdata
*u
, size_t min_buffer_length
){
216 if(min_buffer_length
<= u
->input_buffer_max
){
219 pa_assert(min_buffer_length
>= u
->window_size
);
220 for(size_t c
= 0; c
< u
->channels
; ++c
){
221 float *tmp
= alloc(min_buffer_length
, sizeof(float));
223 if(!u
->first_iteration
){
224 memcpy(tmp
, u
->input
[c
], u
->overlap_size
* sizeof(float));
230 u
->input_buffer_max
= min_buffer_length
;
233 /* Called from I/O thread context */
234 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
235 struct userdata
*u
= PA_SINK(o
)->userdata
;
239 case PA_SINK_MESSAGE_GET_LATENCY
: {
240 //size_t fs=pa_frame_size(&u->sink->sample_spec);
242 /* The sink is _put() before the sink input is, so let's
243 * make sure we don't access it in that time. Also, the
244 * sink input is first shut down, the sink second. */
245 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
246 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
247 *((pa_usec_t
*) data
) = 0;
251 *((pa_usec_t
*) data
) =
252 /* Get the latency of the master sink */
253 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
255 /* Add the latency internal to our sink input on top */
256 pa_bytes_to_usec(pa_memblockq_get_length(u
->output_q
), &u
->sink_input
->sink
->sample_spec
) +
257 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
) +
258 pa_bytes_to_usec(pa_memblockq_get_length(u
->input_q
), &u
->sink_input
->sink
->sample_spec
);
259 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
260 //+ pa_bytes_to_usec(u->latency * fs, ss)
265 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
269 /* Called from main context */
270 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
273 pa_sink_assert_ref(s
);
274 pa_assert_se(u
= s
->userdata
);
276 if (!PA_SINK_IS_LINKED(state
) ||
277 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
280 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
284 /* Called from I/O thread context */
285 static void sink_request_rewind_cb(pa_sink
*s
) {
288 pa_sink_assert_ref(s
);
289 pa_assert_se(u
= s
->userdata
);
291 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
292 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
295 /* Just hand this one over to the master sink */
296 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), TRUE
, FALSE
, FALSE
);
299 /* Called from I/O thread context */
300 static void sink_update_requested_latency_cb(pa_sink
*s
) {
303 pa_sink_assert_ref(s
);
304 pa_assert_se(u
= s
->userdata
);
306 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
307 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
310 /* Just hand this one over to the master sink */
311 pa_sink_input_set_requested_latency_within_thread(
313 pa_sink_get_requested_latency_within_thread(s
));
316 /* Called from main context */
317 static void sink_set_volume_cb(pa_sink
*s
) {
320 pa_sink_assert_ref(s
);
321 pa_assert_se(u
= s
->userdata
);
323 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
324 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
327 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
330 /* Called from main context */
331 static void sink_set_mute_cb(pa_sink
*s
) {
334 pa_sink_assert_ref(s
);
335 pa_assert_se(u
= s
->userdata
);
337 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
338 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
341 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
345 //reference implementation
346 static void dsp_logic(
347 float * restrict dst
,//used as a temp array too, needs to be fft_length!
348 float * restrict src
,/*input data w/ overlap at start,
349 *automatically cycled in routine
351 float * restrict overlap
,
352 const float X
,//multipliar
353 const float * restrict H
,//The freq. magnitude scalers filter
354 const float * restrict W
,//The windowing function
355 fftwf_complex
* restrict output_window
,//The transformed window'd src
357 //use a linear-phase sliding STFT and overlap-add method (for each channel)
359 for(size_t j
= 0; j
< u
->window_size
; ++j
){
360 dst
[j
] = X
* W
[j
] * src
[j
];
362 //zero padd the the remaining fft window
363 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
364 //Processing is done here!
366 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
368 for(size_t j
= 0; j
< FILTER_SIZE
; ++j
){
369 u
->output_window
[j
][0] *= H
[j
];
370 u
->output_window
[j
][1] *= H
[j
];
373 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
374 ////debug: tests overlaping add
375 ////and negates ALL PREVIOUS processing
376 ////yields a perfect reconstruction if COLA is held
377 //for(size_t j = 0; j < u->window_size; ++j){
378 // u->work_buffer[j] = u->W[j] * u->input[c][j];
381 //overlap add and preserve overlap component from this window (linear phase)
382 for(size_t j
= 0; j
< u
->overlap_size
; ++j
){
383 u
->work_buffer
[j
] += overlap
[j
];
384 overlap
[j
] = dst
[u
->R
+ j
];
386 ////debug: tests if basic buffering works
387 ////shouldn't modify the signal AT ALL (beyond roundoff)
388 //for(size_t j = 0; j < u->window_size;++j){
389 // u->work_buffer[j] = u->input[c][j];
392 //preseve the needed input for the next window's overlap
393 memmove(src
, src
+ u
->R
,
394 (u
->samples_gathered
- u
->R
) * sizeof(float)
398 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
399 typedef union float_vector
{
405 //regardless of sse enabled, the loops in here assume
406 //16 byte aligned addresses and memory allocations divisible by v_size
407 static void dsp_logic(
408 float * restrict dst
,//used as a temp array too, needs to be fft_length!
409 float * restrict src
,/*input data w/ overlap at start,
410 *automatically cycled in routine
412 float * restrict overlap
,//The size of the overlap
413 const float X
,//multipliar
414 const float * restrict H
,//The freq. magnitude scalers filter
415 const float * restrict W
,//The windowing function
416 fftwf_complex
* restrict output_window
,//The transformed window'd src
417 struct userdata
*u
){//Collection of constants
418 const size_t overlap_size
= PA_ROUND_UP(u
->overlap_size
, v_size
);
420 x
.f
[0] = x
.f
[1] = x
.f
[2] = x
.f
[3] = X
;
422 //assert(u->samples_gathered >= u->R);
423 //use a linear-phase sliding STFT and overlap-add method
424 for(size_t j
= 0; j
< u
->window_size
; j
+= v_size
){
425 //dst[j] = W[j] * src[j];
426 float_vector_t
*d
= (float_vector_t
*) (dst
+ j
);
427 float_vector_t
*w
= (float_vector_t
*) (W
+ j
);
428 float_vector_t
*s
= (float_vector_t
*) (src
+ j
);
430 d
->m
= _mm_mul_ps(x
.m
, _mm_mul_ps(w
->m
, s
->m
));
431 // d->v = x->v * w->v * s->v;
434 //zero padd the the remaining fft window
435 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
437 //Processing is done here!
439 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
440 //perform filtering - purely magnitude based
441 for(size_t j
= 0; j
< FILTER_SIZE
; j
+= v_size
/ 2){
442 //output_window[j][0]*=H[j];
443 //output_window[j][1]*=H[j];
444 float_vector_t
*d
= (float_vector_t
*)( ((float *) output_window
) + 2 * j
);
446 h
.f
[0] = h
.f
[1] = H
[j
];
447 h
.f
[2] = h
.f
[3] = H
[j
+ 1];
449 d
->m
= _mm_mul_ps(d
->m
, h
.m
);
451 // d->v = d->v * h.v;
456 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
458 ////debug: tests overlaping add
459 ////and negates ALL PREVIOUS processing
460 ////yields a perfect reconstruction if COLA is held
461 //for(size_t j = 0; j < u->window_size; ++j){
462 // dst[j] = W[j] * src[j];
465 //overlap add and preserve overlap component from this window (linear phase)
466 for(size_t j
= 0; j
< overlap_size
; j
+= v_size
){
467 //dst[j]+=overlap[j];
468 //overlap[j]+=dst[j+R];
469 float_vector_t
*d
= (float_vector_t
*)(dst
+ j
);
470 float_vector_t
*o
= (float_vector_t
*)(overlap
+ j
);
472 d
->m
= _mm_add_ps(d
->m
, o
->m
);
473 o
->m
= ((float_vector_t
*)(dst
+ u
->R
+ j
))->m
;
475 // d->v = d->v + o->v;
476 // o->v = ((float_vector_t*)(dst + u->R + j))->v;
479 //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
480 //zero out the bit beyond the real overlap so we don't add garbage next iteration
481 memset(overlap
+ u
->overlap_size
, 0, overlap_size
- u
->overlap_size
);
483 ////debug: tests if basic buffering works
484 ////shouldn't modify the signal AT ALL (beyond roundoff)
485 //for(size_t j = 0; j < u->window_size; ++j){
489 //preseve the needed input for the next window's overlap
490 memmove(src
, src
+ u
->R
,
491 (u
->samples_gathered
- u
->R
) * sizeof(float)
496 static void flatten_to_memblockq(struct userdata
*u
){
497 size_t mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
501 while(i
< u
->output_buffer_length
){
503 tchunk
.length
= PA_MIN((u
->output_buffer_length
- i
), mbs
);
504 tchunk
.memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
.length
);
505 //pa_log_debug("pushing %ld into the q", tchunk.length);
506 dst
= pa_memblock_acquire(tchunk
.memblock
);
507 memcpy(dst
, u
->output_buffer
+ i
, tchunk
.length
);
508 pa_memblock_release(tchunk
.memblock
);
509 pa_memblockq_push(u
->output_q
, &tchunk
);
510 pa_memblock_unref(tchunk
.memblock
);
515 static void process_samples(struct userdata
*u
){
516 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
519 size_t iterations
, offset
;
520 pa_assert(u
->samples_gathered
>= u
->window_size
);
521 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
522 //make sure there is enough buffer memory allocated
523 if(iterations
* u
->R
* fs
> u
->output_buffer_max_length
){
524 u
->output_buffer_max_length
= iterations
* u
->R
* fs
;
525 if(u
->output_buffer
){
526 pa_xfree(u
->output_buffer
);
528 u
->output_buffer
= pa_xmalloc(u
->output_buffer_max_length
);
530 u
->output_buffer_length
= iterations
* u
->R
* fs
;
532 for(size_t iter
= 0; iter
< iterations
; ++iter
){
533 offset
= iter
* u
->R
* fs
;
534 for(size_t c
= 0;c
< u
->channels
; c
++) {
535 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
548 pa_aupdate_read_end(u
->a_H
[c
]);
549 if(u
->first_iteration
){
550 /* The windowing function will make the audio ramped in, as a cheap fix we can
551 * undo the windowing (for non-zero window values)
553 for(size_t i
= 0; i
< u
->overlap_size
; ++i
){
554 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
557 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (((float *)u
->output_buffer
) + c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
559 if(u
->first_iteration
){
560 u
->first_iteration
= FALSE
;
562 u
->samples_gathered
-= u
->R
;
564 flatten_to_memblockq(u
);
567 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
){
568 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
569 size_t samples
= in
->length
/fs
;
570 float *src
= (float*) ((uint8_t*) pa_memblock_acquire(in
->memblock
) + in
->index
);
571 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
572 for(size_t c
= 0; c
< u
->channels
; c
++) {
573 //buffer with an offset after the overlap from previous
576 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
578 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
580 u
->samples_gathered
+= samples
;
581 pa_memblock_release(in
->memblock
);
584 /* Called from I/O thread context */
585 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
587 size_t fs
, target_samples
;
589 //struct timeval start, end;
591 pa_sink_input_assert_ref(i
);
592 pa_assert_se(u
= i
->userdata
);
595 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
596 mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
597 if(pa_memblockq_get_length(u
->output_q
) > 0){
598 //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
601 //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
602 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
603 ////pa_log_debug("vanilla mbs = %ld",mbs);
604 //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
605 //mbs = PA_MAX(mbs, u->R);
606 //target_samples = PA_MAX(target_samples, mbs);
607 //pa_log_debug("target samples: %ld", target_samples);
608 if(u
->first_iteration
){
609 //allocate request_size
610 target_samples
= PA_MAX(target_samples
, u
->window_size
);
612 //allocate request_size + overlap
613 target_samples
+= u
->overlap_size
;
615 alloc_input_buffers(u
, target_samples
);
616 //pa_log_debug("post target samples: %ld", target_samples);
617 chunk
->memblock
= NULL
;
619 /* Hmm, process any rewind request that might be queued up */
620 pa_sink_process_rewind(u
->sink
, 0);
622 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
623 //pa_rtclock_get(&start);
625 size_t input_remaining
= target_samples
- u
->samples_gathered
;
626 // pa_log_debug("input remaining %ld samples", input_remaining);
627 pa_assert(input_remaining
> 0);
628 while(pa_memblockq_peek(u
->input_q
, &tchunk
) < 0){
629 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
630 pa_sink_render_full(u
->sink
, PA_MIN(input_remaining
* fs
, mbs
), &tchunk
);
631 pa_assert(tchunk
.memblock
);
632 pa_memblockq_push(u
->input_q
, &tchunk
);
633 pa_memblock_unref(tchunk
.memblock
);
635 pa_assert(tchunk
.memblock
);
636 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
637 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
638 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
640 //pa_rtclock_get(start);
641 // pa_log_debug("buffering %ld bytes", tchunk.length);
642 input_buffer(u
, &tchunk
);
643 //pa_rtclock_get(&end);
644 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
645 pa_memblock_unref(tchunk
.memblock
);
646 }while(u
->samples_gathered
< target_samples
);
648 //pa_rtclock_get(&end);
649 //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
651 pa_assert(u
->fft_size
>= u
->window_size
);
652 pa_assert(u
->R
< u
->window_size
);
653 //pa_rtclock_get(&start);
654 /* process a block */
656 //pa_rtclock_get(&end);
657 //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
659 pa_assert_se(pa_memblockq_peek(u
->output_q
, chunk
) >= 0);
660 pa_assert(chunk
->memblock
);
661 pa_memblockq_drop(u
->output_q
, chunk
->length
);
662 //pa_log_debug("gave %ld", chunk->length/fs);
663 //pa_log_debug("end pop");
667 /* Called from main context */
668 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
671 pa_sink_input_assert_ref(i
);
672 pa_assert_se(u
= i
->userdata
);
674 pa_sink_volume_changed(u
->sink
, &i
->volume
);
677 /* Called from main context */
678 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
681 pa_sink_input_assert_ref(i
);
682 pa_assert_se(u
= i
->userdata
);
684 pa_sink_mute_changed(u
->sink
, i
->muted
);
687 static void reset_filter(struct userdata
*u
){
688 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
690 u
->samples_gathered
= 0;
691 for(size_t i
= 0; i
< u
->channels
; ++i
){
692 memset(u
->overlap_accum
[i
], 0, u
->overlap_size
* sizeof(float));
694 u
->first_iteration
= TRUE
;
695 //set buffer size to max request, no overlap copy
696 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
697 max_request
= PA_MAX(max_request
, u
->window_size
);
698 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
701 /* Called from I/O thread context */
702 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
706 pa_log_debug("Rewind callback!");
707 pa_sink_input_assert_ref(i
);
708 pa_assert_se(u
= i
->userdata
);
710 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
713 //max_rewrite = nbytes;
714 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
715 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
716 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
717 u
->sink
->thread_info
.rewind_nbytes
= 0;
720 //invalidate the output q
721 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
722 pa_log("Resetting filter");
723 //reset_filter(u); //this is the "proper" thing to do...
727 pa_sink_process_rewind(u
->sink
, amount
);
728 pa_memblockq_rewind(u
->input_q
, nbytes
);
731 /* Called from I/O thread context */
732 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
735 pa_sink_input_assert_ref(i
);
736 pa_assert_se(u
= i
->userdata
);
738 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
739 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
742 /* Called from I/O thread context */
743 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
746 pa_sink_input_assert_ref(i
);
747 pa_assert_se(u
= i
->userdata
);
748 //if(u->first_iteration){
751 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
752 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
755 /* Called from I/O thread context */
756 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
759 pa_sink_input_assert_ref(i
);
760 pa_assert_se(u
= i
->userdata
);
762 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
765 /* Called from I/O thread context */
766 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
769 pa_sink_input_assert_ref(i
);
770 pa_assert_se(u
= i
->userdata
);
772 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
775 /* Called from I/O thread context */
776 static void sink_input_detach_cb(pa_sink_input
*i
) {
779 pa_sink_input_assert_ref(i
);
780 pa_assert_se(u
= i
->userdata
);
782 pa_sink_detach_within_thread(u
->sink
);
784 pa_sink_set_rtpoll(u
->sink
, NULL
);
787 /* Called from I/O thread context */
788 static void sink_input_attach_cb(pa_sink_input
*i
) {
790 size_t fs
, max_request
;
791 pa_sink_input_assert_ref(i
);
792 pa_assert_se(u
= i
->userdata
);
794 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
795 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
797 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
798 fs
= pa_frame_size(&u
->sink
->sample_spec
);
799 //set buffer size to max request, no overlap copy
800 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
801 max_request
= PA_MAX(max_request
, u
->window_size
);
802 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
803 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
804 pa_sink_attach_within_thread(u
->sink
);
806 pa_log_debug("Setting default sink to %s", u
->sink
->name
);
807 pa_namereg_set_default_sink(u
->module
->core
, u
->sink
);
811 /* Called from main context */
812 static void sink_input_kill_cb(pa_sink_input
*i
) {
815 pa_sink_input_assert_ref(i
);
816 pa_assert_se(u
= i
->userdata
);
818 /* The order here matters! We first kill the sink input, followed
819 * by the sink. That means the sink callbacks must be protected
820 * against an unconnected sink input! */
821 pa_sink_input_unlink(u
->sink_input
);
822 pa_sink_unlink(u
->sink
);
824 pa_sink_input_unref(u
->sink_input
);
825 u
->sink_input
= NULL
;
827 pa_sink_unref(u
->sink
);
830 pa_module_unload_request(u
->module
, TRUE
);
833 /* Called from IO thread context */
834 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
837 pa_sink_input_assert_ref(i
);
838 pa_assert_se(u
= i
->userdata
);
840 /* If we are added for the first time, ask for a rewinding so that
841 * we are heard right-away. */
842 if (PA_SINK_INPUT_IS_LINKED(state
) &&
843 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
844 pa_log_debug("Requesting rewind due to state change.");
845 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
849 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
){
851 size_t headers
= (1+len
) * sizeof(uint16_t);
853 for(size_t i
= 0; i
< len
; ++i
){
854 t_len
+= strlen(strs
[i
]);
856 *length
= headers
+ t_len
;
857 p
= *packed
= pa_xmalloc0(*length
);
858 *((uint16_t *) p
) = (uint16_t) len
;
859 p
+= sizeof(uint16_t);
860 for(size_t i
= 0; i
< len
; ++i
){
861 uint16_t l
= strlen(strs
[i
]);
862 *((uint16_t *) p
) = (uint16_t) l
;
863 p
+= sizeof(uint16_t);
864 memcpy(p
, strs
[i
], l
);
868 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
){
870 *len
= *((uint16_t *) p
);
871 p
+= sizeof(uint16_t);
872 *strs
= pa_xnew(char *, *len
);
874 for(size_t i
= 0; i
< *len
; ++i
){
875 size_t l
= *((uint16_t *) p
);
876 p
+= sizeof(uint16_t);
877 (*strs
)[i
] = pa_xnew(char, l
+ 1);
878 memcpy((*strs
)[i
], p
, l
);
879 (*strs
)[i
][l
] = '\0';
883 static void save_profile(struct userdata
*u
, size_t channel
, char *name
){
885 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
886 float *H_n
, *profile
;
889 profile
= pa_xnew0(float, profile_size
);
890 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
891 profile
[0] = u
->Xs
[a_i
][channel
];
892 H
= u
->Hs
[channel
][a_i
];
894 for(size_t i
= 0 ; i
<= FILTER_SIZE
; ++i
){
895 H_n
[i
] = H
[i
] * u
->fft_size
;
898 pa_aupdate_read_end(u
->a_H
[channel
]);
900 key
.size
= strlen(key
.data
);
902 data
.size
= profile_size
;
903 pa_database_set(u
->database
, &key
, &data
, TRUE
);
904 pa_database_sync(u
->database
);
905 if(u
->base_profiles
[channel
]){
906 pa_xfree(u
->base_profiles
[channel
]);
908 u
->base_profiles
[channel
] = pa_xstrdup(name
);
911 static void save_state(struct userdata
*u
){
913 const size_t filter_state_size
= FILTER_STATE_SIZE
* sizeof(float);
917 pa_database
*database
;
919 char *state_name
= u
->name
;
921 size_t packed_length
;
923 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
924 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
925 memcpy(state
+ FILTER_STATE_SIZE
, packed
, packed_length
);
928 for(size_t c
= 0; c
< u
->channels
; ++c
){
929 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
930 state
[c
* CHANNEL_PROFILE_SIZE
] = u
->Xs
[c
][a_i
];
932 H_n
= &state
[c
* CHANNEL_PROFILE_SIZE
+ 1];
933 memcpy(H_n
, H
, FILTER_SIZE
* sizeof(float));
934 pa_aupdate_read_end(u
->a_H
[c
]);
937 key
.data
= state_name
;
938 key
.size
= strlen(key
.data
);
940 data
.size
= filter_state_size
+ packed_length
;
941 //thread safety for 0.9.17?
942 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
943 pa_assert_se(database
= pa_database_open(dbname
, TRUE
));
946 pa_database_set(database
, &key
, &data
, TRUE
);
947 pa_database_sync(database
);
948 pa_database_close(database
);
952 static void remove_profile(pa_core
*c
, char *name
){
954 pa_database
*database
;
956 key
.size
= strlen(key
.data
);
957 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
958 pa_database_unset(database
, &key
);
959 pa_database_sync(database
);
962 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
){
965 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
967 key
.size
= strlen(key
.data
);
968 if(pa_database_get(u
->database
, &key
, &value
) != NULL
){
969 if(value
.size
== profile_size
){
970 float *profile
= (float *) value
.data
;
971 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
972 u
->Xs
[channel
][a_i
] = profile
[0];
973 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE
* sizeof(float));
974 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
975 pa_aupdate_write_end(u
->a_H
[channel
]);
976 pa_xfree(u
->base_profiles
[channel
]);
977 u
->base_profiles
[channel
] = pa_xstrdup(name
);
979 return "incompatible size";
981 pa_datum_free(&value
);
983 return "profile doesn't exist";
988 static void load_state(struct userdata
*u
){
992 pa_database
*database
;
994 char *state_name
= u
->name
;
995 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
996 database
= pa_database_open(dbname
, FALSE
);
999 pa_log("No resume state");
1003 key
.data
= state_name
;
1004 key
.size
= strlen(key
.data
);
1006 if(pa_database_get(database
, &key
, &value
) != NULL
){
1007 if(value
.size
> FILTER_STATE_SIZE
* sizeof(float) + sizeof(uint16_t)){
1008 float *state
= (float *) value
.data
;
1011 for(size_t c
= 0; c
< u
->channels
; ++c
){
1012 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1013 H
= state
+ c
* CHANNEL_PROFILE_SIZE
+ 1;
1014 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE
];
1015 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE
* sizeof(float));
1016 pa_aupdate_write_end(u
->a_H
[c
]);
1018 unpack(((char *)value
.data
) + FILTER_STATE_SIZE
* sizeof(float), value
.size
- FILTER_STATE_SIZE
* sizeof(float), &names
, &n_profs
);
1019 n_profs
= PA_MIN(n_profs
, u
->channels
);
1020 for(size_t c
= 0; c
< n_profs
; ++c
){
1021 pa_xfree(u
->base_profiles
[c
]);
1022 u
->base_profiles
[c
] = names
[c
];
1026 pa_datum_free(&value
);
1028 pa_log("resume state exists but is wrong size!");
1030 pa_database_close(database
);
1033 /* Called from main context */
1034 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1037 pa_sink_input_assert_ref(i
);
1038 pa_assert_se(u
= i
->userdata
);
1040 return u
->sink
!= dest
;
1043 /* Called from main context */
1044 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1047 pa_sink_input_assert_ref(i
);
1048 pa_assert_se(u
= i
->userdata
);
1050 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1051 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1053 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1056 int pa__init(pa_module
*m
) {
1063 pa_sink_input_new_data sink_input_data
;
1064 pa_sink_new_data sink_data
;
1071 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1072 pa_log("Failed to parse module arguments.");
1076 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
1077 pa_log("Master sink not found, trying default");
1078 master
= pa_namereg_get_default_sink(m
->core
);
1080 pa_log("no default sink found!");
1085 ss
= master
->sample_spec
;
1086 ss
.format
= PA_SAMPLE_FLOAT32
;
1087 map
= master
->channel_map
;
1088 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1089 pa_log("Invalid sample format specification or channel map");
1092 fs
= pa_frame_size(&ss
);
1094 u
= pa_xnew0(struct userdata
, 1);
1098 u
->set_default
= TRUE
;
1099 pa_modargs_get_value_boolean(ma
, "set_default", &u
->set_default
);
1101 u
->channels
= ss
.channels
;
1102 u
->fft_size
= pow(2, ceil(log(ss
.rate
) / log(2)));//probably unstable near corner cases of powers of 2
1103 pa_log_debug("fft size: %ld", u
->fft_size
);
1104 u
->window_size
= 15999;
1105 if(u
->window_size
% 2 == 0){
1108 u
->R
= (u
->window_size
+ 1) / 2;
1109 u
->overlap_size
= u
->window_size
- u
->R
;
1110 u
->samples_gathered
= 0;
1111 u
->input_buffer_max
= 0;
1112 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1113 u
->Xs
= pa_xnew0(float *, u
->channels
);
1114 u
->Hs
= pa_xnew0(float **, u
->channels
);
1115 for(size_t c
= 0; c
< u
->channels
; ++c
){
1116 u
->Xs
[c
] = pa_xnew0(float, 2);
1117 u
->Hs
[c
] = pa_xnew0(float *, 2);
1118 for(size_t i
= 0; i
< 2; ++i
){
1119 u
->Hs
[c
][i
] = alloc(FILTER_SIZE
, sizeof(float));
1122 u
->W
= alloc(u
->window_size
, sizeof(float));
1123 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1124 memset(u
->work_buffer
, 0, u
->fft_size
*sizeof(float));
1125 u
->input
= pa_xnew0(float *, u
->channels
);
1126 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1127 for(size_t c
= 0; c
< u
->channels
; ++c
){
1128 u
->a_H
[c
] = pa_aupdate_new();
1130 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1132 u
->output_window
= alloc((FILTER_SIZE
), sizeof(fftwf_complex
));
1133 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1134 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1136 hanning_window(u
->W
, u
->window_size
);
1137 u
->first_iteration
= TRUE
;
1139 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1140 for(size_t c
= 0; c
< u
->channels
; ++c
){
1141 u
->base_profiles
[c
] = pa_xstrdup("default");
1145 pa_sink_new_data_init(&sink_data
);
1146 sink_data
.driver
= __FILE__
;
1147 sink_data
.module
= m
;
1148 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1149 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1150 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1151 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1152 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1153 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s",z
? z
: master
->name
);
1154 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1155 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1157 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1158 pa_log("Invalid properties");
1159 pa_sink_new_data_done(&sink_data
);
1163 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1164 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1165 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1166 pa_sink_new_data_done(&sink_data
);
1169 pa_log("Failed to create sink.");
1172 u
->name
=pa_xstrdup(u
->sink
->name
);
1173 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1174 u
->sink
->set_state
= sink_set_state_cb
;
1175 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1176 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1177 u
->sink
->set_volume
= sink_set_volume_cb
;
1178 u
->sink
->set_mute
= sink_set_mute_cb
;
1179 u
->sink
->userdata
= u
;
1180 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1181 u
->output_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, NULL
);
1182 u
->output_buffer
= NULL
;
1183 u
->output_buffer_length
= 0;
1184 u
->output_buffer_max_length
= 0;
1186 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1187 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1189 /* Create sink input */
1190 pa_sink_input_new_data_init(&sink_input_data
);
1191 sink_input_data
.driver
= __FILE__
;
1192 sink_input_data
.module
= m
;
1193 sink_input_data
.sink
= master
;
1194 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1195 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1196 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1197 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1199 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1200 pa_sink_input_new_data_done(&sink_input_data
);
1205 u
->sink_input
->pop
= sink_input_pop_cb
;
1206 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1207 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1208 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1209 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1210 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1211 u
->sink_input
->kill
= sink_input_kill_cb
;
1212 u
->sink_input
->attach
= sink_input_attach_cb
;
1213 u
->sink_input
->detach
= sink_input_detach_cb
;
1214 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1215 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1216 u
->sink_input
->moving
= sink_input_moving_cb
;
1217 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1218 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1220 u
->sink_input
->userdata
= u
;
1222 pa_sink_put(u
->sink
);
1223 pa_sink_input_put(u
->sink_input
);
1225 pa_modargs_free(ma
);
1230 //default filter to these
1231 for(size_t c
= 0; c
< u
->channels
; ++c
){
1232 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1234 u
->Xs
[c
][a_i
] = 1.0f
;
1235 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1236 H
[i
] = 1.0 / sqrtf(2.0f
);
1238 fix_filter(H
, u
->fft_size
);
1239 pa_aupdate_write_end(u
->a_H
[c
]);
1241 //load old parameters
1248 pa_modargs_free(ma
);
1256 int pa__get_n_used(pa_module
*m
) {
1260 pa_assert_se(u
= m
->userdata
);
1262 return pa_sink_linked_by(u
->sink
);
1265 void pa__done(pa_module
*m
) {
1270 if (!(u
= m
->userdata
))
1277 for(size_t c
= 0; c
< u
->channels
; ++c
){
1278 pa_xfree(u
->base_profiles
[c
]);
1280 pa_xfree(u
->base_profiles
);
1282 /* See comments in sink_input_kill_cb() above regarding
1283 * destruction order! */
1286 pa_sink_input_unlink(u
->sink_input
);
1289 pa_sink_unlink(u
->sink
);
1292 pa_sink_input_unref(u
->sink_input
);
1295 pa_sink_unref(u
->sink
);
1297 if(u
->output_buffer
){
1298 pa_xfree(u
->output_buffer
);
1300 pa_memblockq_free(u
->output_q
);
1301 pa_memblockq_free(u
->input_q
);
1303 fftwf_destroy_plan(u
->inverse_plan
);
1304 fftwf_destroy_plan(u
->forward_plan
);
1305 pa_xfree(u
->output_window
);
1306 for(size_t c
=0; c
< u
->channels
; ++c
){
1307 pa_aupdate_free(u
->a_H
[c
]);
1308 pa_xfree(u
->overlap_accum
[c
]);
1309 pa_xfree(u
->input
[c
]);
1312 pa_xfree(u
->overlap_accum
);
1314 pa_xfree(u
->work_buffer
);
1316 for(size_t c
= 0; c
< u
->channels
; ++c
){
1318 for(size_t i
= 0; i
< 2; ++i
){
1319 pa_xfree(u
->Hs
[c
][i
]);
1332 * DBus Routines and Callbacks
1334 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1335 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1336 #define MANAGER_IFACE EXTNAME ".Manager"
1337 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1338 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1339 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1340 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1341 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1342 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1343 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1344 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1345 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1346 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1347 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1348 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1349 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1350 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1351 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1352 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1353 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1354 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1355 static void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1356 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1357 enum manager_method_index
{
1358 MANAGER_METHOD_REMOVE_PROFILE
,
1362 pa_dbus_arg_info remove_profile_args
[]={
1366 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1367 [MANAGER_METHOD_REMOVE_PROFILE
]{
1368 .method_name
="RemoveProfile",
1369 .arguments
=remove_profile_args
,
1370 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1371 .receive_cb
=manager_handle_remove_profile
}
1374 enum manager_handler_index
{
1375 MANAGER_HANDLER_REVISION
,
1376 MANAGER_HANDLER_EQUALIZED_SINKS
,
1377 MANAGER_HANDLER_PROFILES
,
1381 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1382 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1383 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1384 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1387 pa_dbus_arg_info sink_args
[]={
1391 enum manager_signal_index
{
1392 MANAGER_SIGNAL_SINK_ADDED
,
1393 MANAGER_SIGNAL_SINK_REMOVED
,
1394 MANAGER_SIGNAL_PROFILES_CHANGED
,
1398 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1399 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1400 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1401 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1404 static pa_dbus_interface_info manager_info
={
1405 .name
=MANAGER_IFACE
,
1406 .method_handlers
=manager_methods
,
1407 .n_method_handlers
=MANAGER_METHOD_MAX
,
1408 .property_handlers
=manager_handlers
,
1409 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1410 .get_all_properties_cb
=manager_get_all
,
1411 .signals
=manager_signals
,
1412 .n_signals
=MANAGER_SIGNAL_MAX
1415 enum equalizer_method_index
{
1416 EQUALIZER_METHOD_FILTER_POINTS
,
1417 EQUALIZER_METHOD_SEED_FILTER
,
1418 EQUALIZER_METHOD_SAVE_PROFILE
,
1419 EQUALIZER_METHOD_LOAD_PROFILE
,
1420 EQUALIZER_METHOD_SET_FILTER
,
1421 EQUALIZER_METHOD_GET_FILTER
,
1422 EQUALIZER_METHOD_SAVE_STATE
,
1423 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1424 EQUALIZER_METHOD_MAX
1427 enum equalizer_handler_index
{
1428 EQUALIZER_HANDLER_REVISION
,
1429 EQUALIZER_HANDLER_SAMPLERATE
,
1430 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1431 EQUALIZER_HANDLER_N_COEFS
,
1432 EQUALIZER_HANDLER_N_CHANNELS
,
1433 EQUALIZER_HANDLER_MAX
1436 pa_dbus_arg_info filter_points_args
[]={
1437 {"channel", "u","in"},
1440 {"preamp", "d","out"}
1442 pa_dbus_arg_info seed_filter_args
[]={
1443 {"channel", "u","in"},
1446 {"preamp", "d","in"}
1449 pa_dbus_arg_info set_filter_args
[]={
1450 {"channel", "u","in"},
1452 {"preamp", "d","in"}
1454 pa_dbus_arg_info get_filter_args
[]={
1455 {"channel", "u","in"},
1457 {"preamp", "d","out"}
1460 pa_dbus_arg_info save_profile_args
[]={
1461 {"channel", "u","in"},
1464 pa_dbus_arg_info load_profile_args
[]={
1465 {"channel", "u","in"},
1468 pa_dbus_arg_info base_profile_name_args
[]={
1469 {"channel", "u","in"},
1473 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1474 [EQUALIZER_METHOD_SEED_FILTER
]{
1475 .method_name
="SeedFilter",
1476 .arguments
=seed_filter_args
,
1477 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1478 .receive_cb
=equalizer_handle_seed_filter
},
1479 [EQUALIZER_METHOD_FILTER_POINTS
]{
1480 .method_name
="FilterAtPoints",
1481 .arguments
=filter_points_args
,
1482 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1483 .receive_cb
=equalizer_handle_get_filter_points
},
1484 [EQUALIZER_METHOD_SET_FILTER
]{
1485 .method_name
="SetFilter",
1486 .arguments
=set_filter_args
,
1487 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1488 .receive_cb
=equalizer_handle_set_filter
},
1489 [EQUALIZER_METHOD_GET_FILTER
]{
1490 .method_name
="GetFilter",
1491 .arguments
=get_filter_args
,
1492 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1493 .receive_cb
=equalizer_handle_get_filter
},
1494 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1495 .method_name
="SaveProfile",
1496 .arguments
=save_profile_args
,
1497 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1498 .receive_cb
=equalizer_handle_save_profile
},
1499 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1500 .method_name
="LoadProfile",
1501 .arguments
=load_profile_args
,
1502 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1503 .receive_cb
=equalizer_handle_load_profile
},
1504 [EQUALIZER_METHOD_SAVE_STATE
]{
1505 .method_name
="SaveState",
1508 .receive_cb
=equalizer_handle_save_state
},
1509 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1510 .method_name
="BaseProfile",
1511 .arguments
=base_profile_name_args
,
1512 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1513 .receive_cb
=equalizer_handle_get_profile_name
}
1516 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1517 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1518 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1519 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1520 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1521 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1524 enum equalizer_signal_index
{
1525 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1526 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1527 EQUALIZER_SIGNAL_MAX
1530 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1531 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1532 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1535 static pa_dbus_interface_info equalizer_info
={
1536 .name
=EQUALIZER_IFACE
,
1537 .method_handlers
=equalizer_methods
,
1538 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1539 .property_handlers
=equalizer_handlers
,
1540 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1541 .get_all_properties_cb
=equalizer_get_all
,
1542 .signals
=equalizer_signals
,
1543 .n_signals
=EQUALIZER_SIGNAL_MAX
1546 void dbus_init(struct userdata
*u
){
1548 DBusMessage
*signal
= NULL
;
1549 pa_idxset
*sink_list
= NULL
;
1550 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1551 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1553 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1554 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1555 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1556 if(sink_list
== NULL
){
1558 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1559 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1560 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1561 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1563 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1564 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1565 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1567 pa_idxset_put(sink_list
, u
, &dummy
);
1569 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1570 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1571 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1572 dbus_message_unref(signal
);
1575 void dbus_done(struct userdata
*u
){
1576 pa_idxset
*sink_list
;
1579 DBusMessage
*signal
= NULL
;
1580 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1581 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1582 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1583 dbus_message_unref(signal
);
1585 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1586 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1587 if(pa_idxset_size(sink_list
)==0){
1588 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1589 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1590 pa_shared_remove(u
->sink
->core
, EQDB
);
1591 pa_database_close(u
->database
);
1592 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1593 pa_xfree(sink_list
);
1595 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1596 pa_xfree(u
->dbus_path
);
1597 pa_dbus_protocol_unref(u
->dbus_protocol
);
1600 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1602 pa_core
*c
= (pa_core
*)_u
;
1603 DBusMessage
*signal
= NULL
;
1604 pa_dbus_protocol
*dbus_protocol
;
1609 dbus_error_init(&error
);
1610 if(!dbus_message_get_args(msg
, &error
,
1611 DBUS_TYPE_STRING
, &name
,
1612 DBUS_TYPE_INVALID
)){
1613 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1614 dbus_error_free(&error
);
1617 remove_profile(c
,name
);
1618 pa_dbus_send_empty_reply(conn
, msg
);
1620 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1621 dbus_protocol
= pa_dbus_protocol_get(c
);
1622 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1623 pa_dbus_protocol_unref(dbus_protocol
);
1624 dbus_message_unref(signal
);
1627 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1629 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1632 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1634 struct userdata
*sink_u
= NULL
;
1636 pa_idxset
*sink_list
;
1641 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1642 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1643 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1644 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1645 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1646 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1650 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1652 char **names
= NULL
;
1657 get_sinks((pa_core
*) _u
, &names
, &n
);
1658 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1659 for(unsigned i
= 0; i
< n
; ++i
){
1665 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1667 pa_database
*database
;
1668 pa_datum key
, next_key
;
1669 pa_strlist
*head
=NULL
, *iter
;
1671 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1676 done
= !pa_database_first(database
, &key
, NULL
);
1679 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1680 name
=pa_xmalloc(key
.size
+ 1);
1681 memcpy(name
, key
.data
, key
.size
);
1682 name
[key
.size
] = '\0';
1683 pa_datum_free(&key
);
1684 head
= pa_strlist_prepend(head
, name
);
1689 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1691 for(unsigned i
= 0; i
< *n
; ++i
){
1692 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1693 iter
= pa_strlist_next(iter
);
1695 pa_strlist_free(head
);
1698 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1705 get_profiles((pa_core
*)_u
, &names
, &n
);
1706 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1707 for(unsigned i
= 0; i
< n
; ++i
){
1713 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1715 char **names
= NULL
;
1717 DBusMessage
*reply
= NULL
;
1718 DBusMessageIter msg_iter
, dict_iter
;
1722 pa_assert_se(c
= _u
);
1724 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1725 dbus_message_iter_init_append(reply
, &msg_iter
);
1726 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1729 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1731 get_sinks(c
, &names
, &n
);
1732 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1733 for(unsigned i
= 0; i
< n
; ++i
){
1738 get_profiles(c
, &names
, &n
);
1739 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1740 for(unsigned i
= 0; i
< n
; ++i
){
1744 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1745 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1746 dbus_message_unref(reply
);
1749 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1750 struct userdata
*u
=(struct userdata
*) _u
;
1752 DBusMessage
*signal
= NULL
;
1754 uint32_t *xs
, channel
, r_channel
;
1755 double *_ys
, preamp
;
1756 unsigned x_npoints
, y_npoints
, a_i
;
1758 pa_bool_t points_good
= TRUE
;
1763 dbus_error_init(&error
);
1765 if(!dbus_message_get_args(msg
, &error
,
1766 DBUS_TYPE_UINT32
, &channel
,
1767 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1768 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1769 DBUS_TYPE_DOUBLE
, &preamp
,
1770 DBUS_TYPE_INVALID
)){
1771 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1772 dbus_error_free(&error
);
1775 if(channel
> u
->channels
){
1776 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1777 dbus_error_free(&error
);
1780 for(size_t i
= 0; i
< x_npoints
; ++i
){
1781 if(xs
[i
] >= FILTER_SIZE
){
1782 points_good
= FALSE
;
1786 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1787 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1788 dbus_error_free(&error
);
1790 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE
){
1791 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE
);
1792 dbus_error_free(&error
);
1794 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1795 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1796 dbus_error_free(&error
);
1800 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1801 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1802 ys
[i
] = (float) _ys
[i
];
1804 r_channel
= channel
== u
->channels
? 0 : channel
;
1805 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1806 H
= u
->Hs
[r_channel
][a_i
];
1807 u
->Xs
[r_channel
][a_i
] = preamp
;
1808 interpolate(H
, FILTER_SIZE
, xs
, ys
, x_npoints
);
1809 fix_filter(H
, u
->fft_size
);
1810 if(channel
== u
->channels
){
1811 for(size_t c
= 1; c
< u
->channels
; ++c
){
1812 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1813 float *H_p
= u
->Hs
[c
][b_i
];
1814 u
->Xs
[c
][b_i
] = preamp
;
1815 memcpy(H_p
, H
, FILTER_SIZE
* sizeof(float));
1816 pa_aupdate_write_end(u
->a_H
[c
]);
1819 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1823 pa_dbus_send_empty_reply(conn
, msg
);
1825 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1826 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1827 dbus_message_unref(signal
);
1830 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1831 struct userdata
*u
= (struct userdata
*) _u
;
1832 uint32_t *xs
, channel
, r_channel
;
1834 unsigned x_npoints
, a_i
;
1836 pa_bool_t points_good
=TRUE
;
1837 DBusMessage
*reply
= NULL
;
1838 DBusMessageIter msg_iter
;
1845 dbus_error_init(&error
);
1846 if(!dbus_message_get_args(msg
, &error
,
1847 DBUS_TYPE_UINT32
, &channel
,
1848 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1849 DBUS_TYPE_INVALID
)){
1850 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1851 dbus_error_free(&error
);
1854 if(channel
> u
->channels
){
1855 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1856 dbus_error_free(&error
);
1860 for(size_t i
= 0; i
< x_npoints
; ++i
){
1861 if(xs
[i
] >= FILTER_SIZE
){
1867 if(x_npoints
> FILTER_SIZE
|| !points_good
){
1868 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE
);
1869 dbus_error_free(&error
);
1873 r_channel
= channel
== u
->channels
? 0 : channel
;
1874 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1875 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1876 H
= u
->Hs
[r_channel
][a_i
];
1877 preamp
= u
->Xs
[r_channel
][a_i
];
1878 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1879 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1881 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1883 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1884 dbus_message_iter_init_append(reply
, &msg_iter
);
1886 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1887 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1889 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1890 dbus_message_unref(reply
);
1894 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1897 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1898 *H_
= pa_xnew0(double, FILTER_SIZE
);
1899 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1900 H
= u
->Hs
[r_channel
][a_i
];
1901 for(size_t i
= 0;i
< FILTER_SIZE
; ++i
){
1902 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1904 *preamp
= u
->Xs
[r_channel
][a_i
];
1906 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1909 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1914 DBusMessage
*reply
= NULL
;
1915 DBusMessageIter msg_iter
;
1917 pa_assert_se(u
= (struct userdata
*) _u
);
1921 dbus_error_init(&error
);
1922 if(!dbus_message_get_args(msg
, &error
,
1923 DBUS_TYPE_UINT32
, &channel
,
1924 DBUS_TYPE_INVALID
)){
1925 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1926 dbus_error_free(&error
);
1929 if(channel
> u
->channels
){
1930 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1931 dbus_error_free(&error
);
1935 n_coefs
= CHANNEL_PROFILE_SIZE
;
1938 get_filter(u
, channel
, &H_
, &preamp
);
1939 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1940 dbus_message_iter_init_append(reply
, &msg_iter
);
1942 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1943 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1945 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1946 dbus_message_unref(reply
);
1950 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1952 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1955 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1956 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1957 H
= u
->Hs
[r_channel
][a_i
];
1958 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1959 H
[i
] = (float) H_
[i
];
1961 fix_filter(H
, u
->fft_size
);
1962 if(channel
== u
->channels
){
1963 for(size_t c
= 1; c
< u
->channels
; ++c
){
1964 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1965 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1966 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE
* sizeof(float));
1967 pa_aupdate_write_end(u
->a_H
[c
]);
1970 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1973 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1978 DBusMessage
*signal
= NULL
;
1980 pa_assert_se(u
= (struct userdata
*) _u
);
1984 dbus_error_init(&error
);
1985 if(!dbus_message_get_args(msg
, &error
,
1986 DBUS_TYPE_UINT32
, &channel
,
1987 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1988 DBUS_TYPE_DOUBLE
, &preamp
,
1989 DBUS_TYPE_INVALID
)){
1990 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1991 dbus_error_free(&error
);
1994 if(channel
> u
->channels
){
1995 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1996 dbus_error_free(&error
);
1999 if(_n_coefs
!= FILTER_SIZE
){
2000 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE
, _n_coefs
);
2003 set_filter(u
, channel
, H
, preamp
);
2005 pa_dbus_send_empty_reply(conn
, msg
);
2007 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2008 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2009 dbus_message_unref(signal
);
2012 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2013 struct userdata
*u
= (struct userdata
*) _u
;
2015 uint32_t channel
, r_channel
;
2016 DBusMessage
*signal
= NULL
;
2021 dbus_error_init(&error
);
2023 if(!dbus_message_get_args(msg
, &error
,
2024 DBUS_TYPE_UINT32
, &channel
,
2025 DBUS_TYPE_STRING
, &name
,
2026 DBUS_TYPE_INVALID
)){
2027 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2028 dbus_error_free(&error
);
2031 if(channel
> u
->channels
){
2032 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2033 dbus_error_free(&error
);
2036 r_channel
= channel
== u
->channels
? 0 : channel
;
2037 save_profile(u
, r_channel
, name
);
2038 pa_dbus_send_empty_reply(conn
, msg
);
2040 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
2041 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2042 dbus_message_unref(signal
);
2045 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2046 struct userdata
*u
= (struct userdata
*) _u
;
2049 uint32_t channel
, r_channel
;
2050 const char *err_msg
= NULL
;
2051 DBusMessage
*signal
= NULL
;
2056 dbus_error_init(&error
);
2058 if(!dbus_message_get_args(msg
, &error
,
2059 DBUS_TYPE_UINT32
, &channel
,
2060 DBUS_TYPE_STRING
, &name
,
2061 DBUS_TYPE_INVALID
)){
2062 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2063 dbus_error_free(&error
);
2066 if(channel
> u
->channels
){
2067 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2068 dbus_error_free(&error
);
2071 r_channel
= channel
== u
->channels
? 0 : channel
;
2073 err_msg
= load_profile(u
, r_channel
, name
);
2074 if(err_msg
!= NULL
){
2075 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2076 dbus_error_free(&error
);
2079 if(channel
== u
->channels
){
2080 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2081 load_profile(u
, c
, name
);
2084 pa_dbus_send_empty_reply(conn
, msg
);
2086 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2087 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2088 dbus_message_unref(signal
);
2091 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2092 struct userdata
*u
= (struct userdata
*) _u
;
2098 pa_dbus_send_empty_reply(conn
, msg
);
2101 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2102 struct userdata
*u
= (struct userdata
*) _u
;
2104 uint32_t channel
, r_channel
;
2109 dbus_error_init(&error
);
2111 if(!dbus_message_get_args(msg
, &error
,
2112 DBUS_TYPE_UINT32
, &channel
,
2113 DBUS_TYPE_INVALID
)){
2114 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2115 dbus_error_free(&error
);
2118 if(channel
> u
->channels
){
2119 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2120 dbus_error_free(&error
);
2123 r_channel
= channel
== u
->channels
? 0 : channel
;
2124 pa_assert(u
->base_profiles
[r_channel
]);
2125 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2128 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2130 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2133 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2136 pa_assert_se(u
= (struct userdata
*) _u
);
2140 channels
= (uint32_t) u
->channels
;
2141 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2144 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2147 pa_assert_se(u
= (struct userdata
*) _u
);
2151 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2152 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2155 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2158 pa_assert_se(u
= (struct userdata
*) _u
);
2162 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2163 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2166 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2169 pa_assert_se(u
= (struct userdata
*) _u
);
2173 fft_size
= (uint32_t) u
->fft_size
;
2174 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2177 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2179 DBusMessage
*reply
= NULL
;
2180 DBusMessageIter msg_iter
, dict_iter
;
2181 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2182 pa_assert_se(u
= (struct userdata
*) _u
);
2186 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2187 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2188 fft_size
= (uint32_t) u
->fft_size
;
2189 channels
= (uint32_t) u
->channels
;
2191 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2192 dbus_message_iter_init_append(reply
, &msg_iter
);
2193 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2195 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2196 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2197 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2198 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2199 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2201 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2202 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2203 dbus_message_unref(reply
);