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
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
257 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
258 //+ pa_bytes_to_usec(u->latency * fs, ss)
259 //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);
264 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
268 /* Called from main context */
269 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
272 pa_sink_assert_ref(s
);
273 pa_assert_se(u
= s
->userdata
);
275 if (!PA_SINK_IS_LINKED(state
) ||
276 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
279 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
283 /* Called from I/O thread context */
284 static void sink_request_rewind_cb(pa_sink
*s
) {
287 pa_sink_assert_ref(s
);
288 pa_assert_se(u
= s
->userdata
);
290 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
291 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
294 /* Just hand this one over to the master sink */
295 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), TRUE
, FALSE
, FALSE
);
298 /* Called from I/O thread context */
299 static void sink_update_requested_latency_cb(pa_sink
*s
) {
302 pa_sink_assert_ref(s
);
303 pa_assert_se(u
= s
->userdata
);
305 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
306 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
309 /* Just hand this one over to the master sink */
310 pa_sink_input_set_requested_latency_within_thread(
312 pa_sink_get_requested_latency_within_thread(s
));
315 /* Called from main context */
316 static void sink_set_volume_cb(pa_sink
*s
) {
319 pa_sink_assert_ref(s
);
320 pa_assert_se(u
= s
->userdata
);
322 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
323 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
326 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
329 /* Called from main context */
330 static void sink_set_mute_cb(pa_sink
*s
) {
333 pa_sink_assert_ref(s
);
334 pa_assert_se(u
= s
->userdata
);
336 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
337 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
340 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
344 //reference implementation
345 static void dsp_logic(
346 float * restrict dst
,//used as a temp array too, needs to be fft_length!
347 float * restrict src
,/*input data w/ overlap at start,
348 *automatically cycled in routine
350 float * restrict overlap
,
351 const float X
,//multipliar
352 const float * restrict H
,//The freq. magnitude scalers filter
353 const float * restrict W
,//The windowing function
354 fftwf_complex
* restrict output_window
,//The transformed window'd src
356 //use a linear-phase sliding STFT and overlap-add method (for each channel)
358 for(size_t j
= 0; j
< u
->window_size
; ++j
){
359 dst
[j
] = X
* W
[j
] * src
[j
];
361 //zero padd the the remaining fft window
362 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
363 //Processing is done here!
365 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
367 for(size_t j
= 0; j
< FILTER_SIZE
; ++j
){
368 u
->output_window
[j
][0] *= H
[j
];
369 u
->output_window
[j
][1] *= H
[j
];
372 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
373 ////debug: tests overlaping add
374 ////and negates ALL PREVIOUS processing
375 ////yields a perfect reconstruction if COLA is held
376 //for(size_t j = 0; j < u->window_size; ++j){
377 // u->work_buffer[j] = u->W[j] * u->input[c][j];
380 //overlap add and preserve overlap component from this window (linear phase)
381 for(size_t j
= 0; j
< u
->overlap_size
; ++j
){
382 u
->work_buffer
[j
] += overlap
[j
];
383 overlap
[j
] = dst
[u
->R
+ j
];
385 ////debug: tests if basic buffering works
386 ////shouldn't modify the signal AT ALL (beyond roundoff)
387 //for(size_t j = 0; j < u->window_size;++j){
388 // u->work_buffer[j] = u->input[c][j];
391 //preseve the needed input for the next window's overlap
392 memmove(src
, src
+ u
->R
,
393 (u
->samples_gathered
- u
->R
) * sizeof(float)
397 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
398 typedef union float_vector
{
404 //regardless of sse enabled, the loops in here assume
405 //16 byte aligned addresses and memory allocations divisible by v_size
406 static void dsp_logic(
407 float * restrict dst
,//used as a temp array too, needs to be fft_length!
408 float * restrict src
,/*input data w/ overlap at start,
409 *automatically cycled in routine
411 float * restrict overlap
,//The size of the overlap
412 const float X
,//multipliar
413 const float * restrict H
,//The freq. magnitude scalers filter
414 const float * restrict W
,//The windowing function
415 fftwf_complex
* restrict output_window
,//The transformed window'd src
416 struct userdata
*u
){//Collection of constants
417 const size_t overlap_size
= PA_ROUND_UP(u
->overlap_size
, v_size
);
419 x
.f
[0] = x
.f
[1] = x
.f
[2] = x
.f
[3] = X
;
421 //assert(u->samples_gathered >= u->R);
422 //use a linear-phase sliding STFT and overlap-add method
423 for(size_t j
= 0; j
< u
->window_size
; j
+= v_size
){
424 //dst[j] = W[j] * src[j];
425 float_vector_t
*d
= (float_vector_t
*) (dst
+ j
);
426 float_vector_t
*w
= (float_vector_t
*) (W
+ j
);
427 float_vector_t
*s
= (float_vector_t
*) (src
+ j
);
429 d
->m
= _mm_mul_ps(x
.m
, _mm_mul_ps(w
->m
, s
->m
));
430 // d->v = x->v * w->v * s->v;
433 //zero padd the the remaining fft window
434 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
436 //Processing is done here!
438 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
439 //perform filtering - purely magnitude based
440 for(size_t j
= 0; j
< FILTER_SIZE
; j
+= v_size
/ 2){
441 //output_window[j][0]*=H[j];
442 //output_window[j][1]*=H[j];
443 float_vector_t
*d
= (float_vector_t
*)( ((float *) output_window
) + 2 * j
);
445 h
.f
[0] = h
.f
[1] = H
[j
];
446 h
.f
[2] = h
.f
[3] = H
[j
+ 1];
448 d
->m
= _mm_mul_ps(d
->m
, h
.m
);
450 // d->v = d->v * h.v;
455 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
457 ////debug: tests overlaping add
458 ////and negates ALL PREVIOUS processing
459 ////yields a perfect reconstruction if COLA is held
460 //for(size_t j = 0; j < u->window_size; ++j){
461 // dst[j] = W[j] * src[j];
464 //overlap add and preserve overlap component from this window (linear phase)
465 for(size_t j
= 0; j
< overlap_size
; j
+= v_size
){
466 //dst[j]+=overlap[j];
467 //overlap[j]+=dst[j+R];
468 float_vector_t
*d
= (float_vector_t
*)(dst
+ j
);
469 float_vector_t
*o
= (float_vector_t
*)(overlap
+ j
);
471 d
->m
= _mm_add_ps(d
->m
, o
->m
);
472 o
->m
= ((float_vector_t
*)(dst
+ u
->R
+ j
))->m
;
474 // d->v = d->v + o->v;
475 // o->v = ((float_vector_t*)(dst + u->R + j))->v;
478 //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
479 //zero out the bit beyond the real overlap so we don't add garbage next iteration
480 memset(overlap
+ u
->overlap_size
, 0, overlap_size
- u
->overlap_size
);
482 ////debug: tests if basic buffering works
483 ////shouldn't modify the signal AT ALL (beyond roundoff)
484 //for(size_t j = 0; j < u->window_size; ++j){
488 //preseve the needed input for the next window's overlap
489 memmove(src
, src
+ u
->R
,
490 (u
->samples_gathered
- u
->R
) * sizeof(float)
495 static void flatten_to_memblockq(struct userdata
*u
){
496 size_t mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
500 while(i
< u
->output_buffer_length
){
502 tchunk
.length
= PA_MIN((u
->output_buffer_length
- i
), mbs
);
503 tchunk
.memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
.length
);
504 //pa_log_debug("pushing %ld into the q", tchunk.length);
505 dst
= pa_memblock_acquire(tchunk
.memblock
);
506 memcpy(dst
, u
->output_buffer
+ i
, tchunk
.length
);
507 pa_memblock_release(tchunk
.memblock
);
508 pa_memblockq_push(u
->output_q
, &tchunk
);
509 pa_memblock_unref(tchunk
.memblock
);
514 static void process_samples(struct userdata
*u
){
515 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
518 size_t iterations
, offset
;
519 pa_assert(u
->samples_gathered
>= u
->window_size
);
520 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
521 //make sure there is enough buffer memory allocated
522 if(iterations
* u
->R
* fs
> u
->output_buffer_max_length
){
523 u
->output_buffer_max_length
= iterations
* u
->R
* fs
;
524 if(u
->output_buffer
){
525 pa_xfree(u
->output_buffer
);
527 u
->output_buffer
= pa_xmalloc(u
->output_buffer_max_length
);
529 u
->output_buffer_length
= iterations
* u
->R
* fs
;
531 for(size_t iter
= 0; iter
< iterations
; ++iter
){
532 offset
= iter
* u
->R
* fs
;
533 for(size_t c
= 0;c
< u
->channels
; c
++) {
534 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
547 pa_aupdate_read_end(u
->a_H
[c
]);
548 if(u
->first_iteration
){
549 /* The windowing function will make the audio ramped in, as a cheap fix we can
550 * undo the windowing (for non-zero window values)
552 for(size_t i
= 0; i
< u
->overlap_size
; ++i
){
553 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
556 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (((float *)u
->output_buffer
) + c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
558 if(u
->first_iteration
){
559 u
->first_iteration
= FALSE
;
561 u
->samples_gathered
-= u
->R
;
563 flatten_to_memblockq(u
);
566 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
){
567 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
568 size_t samples
= in
->length
/fs
;
569 float *src
= (float*) ((uint8_t*) pa_memblock_acquire(in
->memblock
) + in
->index
);
570 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
571 for(size_t c
= 0; c
< u
->channels
; c
++) {
572 //buffer with an offset after the overlap from previous
575 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
577 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
579 u
->samples_gathered
+= samples
;
580 pa_memblock_release(in
->memblock
);
583 /* Called from I/O thread context */
584 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
586 size_t fs
, target_samples
;
588 //struct timeval start, end;
590 pa_sink_input_assert_ref(i
);
591 pa_assert_se(u
= i
->userdata
);
594 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
595 mbs
= pa_mempool_block_size_max(u
->sink
->core
->mempool
);
596 if(pa_memblockq_get_length(u
->output_q
) > 0){
597 //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
600 //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
601 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
602 ////pa_log_debug("vanilla mbs = %ld",mbs);
603 //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
604 //mbs = PA_MAX(mbs, u->R);
605 //target_samples = PA_MAX(target_samples, mbs);
606 //pa_log_debug("target samples: %ld", target_samples);
607 if(u
->first_iteration
){
608 //allocate request_size
609 target_samples
= PA_MAX(target_samples
, u
->window_size
);
611 //allocate request_size + overlap
612 target_samples
+= u
->overlap_size
;
614 alloc_input_buffers(u
, target_samples
);
615 //pa_log_debug("post target samples: %ld", target_samples);
616 chunk
->memblock
= NULL
;
618 /* Hmm, process any rewind request that might be queued up */
619 pa_sink_process_rewind(u
->sink
, 0);
621 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
622 //pa_rtclock_get(&start);
624 size_t input_remaining
= target_samples
- u
->samples_gathered
;
625 // pa_log_debug("input remaining %ld samples", input_remaining);
626 pa_assert(input_remaining
> 0);
627 while(pa_memblockq_peek(u
->input_q
, &tchunk
) < 0){
628 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
629 pa_sink_render_full(u
->sink
, PA_MIN(input_remaining
* fs
, mbs
), &tchunk
);
630 pa_assert(tchunk
.memblock
);
631 pa_memblockq_push(u
->input_q
, &tchunk
);
632 pa_memblock_unref(tchunk
.memblock
);
634 pa_assert(tchunk
.memblock
);
635 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
636 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
637 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
639 //pa_rtclock_get(start);
640 // pa_log_debug("buffering %ld bytes", tchunk.length);
641 input_buffer(u
, &tchunk
);
642 //pa_rtclock_get(&end);
643 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
644 pa_memblock_unref(tchunk
.memblock
);
645 }while(u
->samples_gathered
< target_samples
);
647 //pa_rtclock_get(&end);
648 //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
650 pa_assert(u
->fft_size
>= u
->window_size
);
651 pa_assert(u
->R
< u
->window_size
);
652 //pa_rtclock_get(&start);
653 /* process a block */
655 //pa_rtclock_get(&end);
656 //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
658 pa_assert_se(pa_memblockq_peek(u
->output_q
, chunk
) >= 0);
659 pa_assert(chunk
->memblock
);
660 pa_memblockq_drop(u
->output_q
, chunk
->length
);
661 //pa_log_debug("gave %ld", chunk->length/fs);
662 //pa_log_debug("end pop");
666 /* Called from main context */
667 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
670 pa_sink_input_assert_ref(i
);
671 pa_assert_se(u
= i
->userdata
);
673 pa_sink_volume_changed(u
->sink
, &i
->volume
);
676 /* Called from main context */
677 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
680 pa_sink_input_assert_ref(i
);
681 pa_assert_se(u
= i
->userdata
);
683 pa_sink_mute_changed(u
->sink
, i
->muted
);
686 static void reset_filter(struct userdata
*u
){
687 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
689 u
->samples_gathered
= 0;
690 for(size_t i
= 0; i
< u
->channels
; ++i
){
691 memset(u
->overlap_accum
[i
], 0, u
->overlap_size
* sizeof(float));
693 u
->first_iteration
= TRUE
;
694 //set buffer size to max request, no overlap copy
695 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
696 max_request
= PA_MAX(max_request
, u
->window_size
);
697 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
700 /* Called from I/O thread context */
701 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
705 pa_log_debug("Rewind callback!");
706 pa_sink_input_assert_ref(i
);
707 pa_assert_se(u
= i
->userdata
);
709 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
712 //max_rewrite = nbytes;
713 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
714 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
715 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
716 u
->sink
->thread_info
.rewind_nbytes
= 0;
719 //invalidate the output q
720 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
721 pa_log("Resetting filter");
722 //reset_filter(u); //this is the "proper" thing to do...
726 pa_sink_process_rewind(u
->sink
, amount
);
727 pa_memblockq_rewind(u
->input_q
, nbytes
);
730 /* Called from I/O thread context */
731 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
734 pa_sink_input_assert_ref(i
);
735 pa_assert_se(u
= i
->userdata
);
737 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
738 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
741 /* Called from I/O thread context */
742 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
745 pa_sink_input_assert_ref(i
);
746 pa_assert_se(u
= i
->userdata
);
747 //if(u->first_iteration){
750 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
751 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
754 /* Called from I/O thread context */
755 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
758 pa_sink_input_assert_ref(i
);
759 pa_assert_se(u
= i
->userdata
);
761 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
764 /* Called from I/O thread context */
765 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
768 pa_sink_input_assert_ref(i
);
769 pa_assert_se(u
= i
->userdata
);
771 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
774 /* Called from I/O thread context */
775 static void sink_input_detach_cb(pa_sink_input
*i
) {
778 pa_sink_input_assert_ref(i
);
779 pa_assert_se(u
= i
->userdata
);
781 pa_sink_detach_within_thread(u
->sink
);
783 pa_sink_set_rtpoll(u
->sink
, NULL
);
786 /* Called from I/O thread context */
787 static void sink_input_attach_cb(pa_sink_input
*i
) {
789 size_t fs
, max_request
;
790 pa_sink_input_assert_ref(i
);
791 pa_assert_se(u
= i
->userdata
);
793 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
794 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
796 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
797 fs
= pa_frame_size(&u
->sink
->sample_spec
);
798 //set buffer size to max request, no overlap copy
799 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
800 max_request
= PA_MAX(max_request
, u
->window_size
);
801 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
802 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
803 pa_sink_attach_within_thread(u
->sink
);
805 pa_log_debug("Setting default sink to %s", u
->sink
->name
);
806 pa_namereg_set_default_sink(u
->module
->core
, u
->sink
);
810 /* Called from main context */
811 static void sink_input_kill_cb(pa_sink_input
*i
) {
814 pa_sink_input_assert_ref(i
);
815 pa_assert_se(u
= i
->userdata
);
817 /* The order here matters! We first kill the sink input, followed
818 * by the sink. That means the sink callbacks must be protected
819 * against an unconnected sink input! */
820 pa_sink_input_unlink(u
->sink_input
);
821 pa_sink_unlink(u
->sink
);
823 pa_sink_input_unref(u
->sink_input
);
824 u
->sink_input
= NULL
;
826 pa_sink_unref(u
->sink
);
829 pa_module_unload_request(u
->module
, TRUE
);
832 /* Called from IO thread context */
833 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
836 pa_sink_input_assert_ref(i
);
837 pa_assert_se(u
= i
->userdata
);
839 /* If we are added for the first time, ask for a rewinding so that
840 * we are heard right-away. */
841 if (PA_SINK_INPUT_IS_LINKED(state
) &&
842 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
843 pa_log_debug("Requesting rewind due to state change.");
844 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
848 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
){
850 size_t headers
= (1+len
) * sizeof(uint16_t);
852 for(size_t i
= 0; i
< len
; ++i
){
853 t_len
+= strlen(strs
[i
]);
855 *length
= headers
+ t_len
;
856 p
= *packed
= pa_xmalloc0(*length
);
857 *((uint16_t *) p
) = (uint16_t) len
;
858 p
+= sizeof(uint16_t);
859 for(size_t i
= 0; i
< len
; ++i
){
860 uint16_t l
= strlen(strs
[i
]);
861 *((uint16_t *) p
) = (uint16_t) l
;
862 p
+= sizeof(uint16_t);
863 memcpy(p
, strs
[i
], l
);
867 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
){
869 *len
= *((uint16_t *) p
);
870 p
+= sizeof(uint16_t);
871 *strs
= pa_xnew(char *, *len
);
873 for(size_t i
= 0; i
< *len
; ++i
){
874 size_t l
= *((uint16_t *) p
);
875 p
+= sizeof(uint16_t);
876 (*strs
)[i
] = pa_xnew(char, l
+ 1);
877 memcpy((*strs
)[i
], p
, l
);
878 (*strs
)[i
][l
] = '\0';
882 static void save_profile(struct userdata
*u
, size_t channel
, char *name
){
884 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
885 float *H_n
, *profile
;
888 profile
= pa_xnew0(float, profile_size
);
889 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
890 profile
[0] = u
->Xs
[a_i
][channel
];
891 H
= u
->Hs
[channel
][a_i
];
893 for(size_t i
= 0 ; i
<= FILTER_SIZE
; ++i
){
894 H_n
[i
] = H
[i
] * u
->fft_size
;
897 pa_aupdate_read_end(u
->a_H
[channel
]);
899 key
.size
= strlen(key
.data
);
901 data
.size
= profile_size
;
902 pa_database_set(u
->database
, &key
, &data
, TRUE
);
903 pa_database_sync(u
->database
);
904 if(u
->base_profiles
[channel
]){
905 pa_xfree(u
->base_profiles
[channel
]);
907 u
->base_profiles
[channel
] = pa_xstrdup(name
);
910 static void save_state(struct userdata
*u
){
912 const size_t filter_state_size
= FILTER_STATE_SIZE
* sizeof(float);
916 pa_database
*database
;
918 char *state_name
= u
->name
;
920 size_t packed_length
;
922 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
923 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
924 memcpy(state
+ FILTER_STATE_SIZE
, packed
, packed_length
);
927 for(size_t c
= 0; c
< u
->channels
; ++c
){
928 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
929 state
[c
* CHANNEL_PROFILE_SIZE
] = u
->Xs
[c
][a_i
];
931 H_n
= &state
[c
* CHANNEL_PROFILE_SIZE
+ 1];
932 memcpy(H_n
, H
, FILTER_SIZE
* sizeof(float));
933 pa_aupdate_read_end(u
->a_H
[c
]);
936 key
.data
= state_name
;
937 key
.size
= strlen(key
.data
);
939 data
.size
= filter_state_size
+ packed_length
;
940 //thread safety for 0.9.17?
941 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
942 pa_assert_se(database
= pa_database_open(dbname
, TRUE
));
945 pa_database_set(database
, &key
, &data
, TRUE
);
946 pa_database_sync(database
);
947 pa_database_close(database
);
951 static void remove_profile(pa_core
*c
, char *name
){
953 pa_database
*database
;
955 key
.size
= strlen(key
.data
);
956 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
957 pa_database_unset(database
, &key
);
958 pa_database_sync(database
);
961 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
){
964 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
966 key
.size
= strlen(key
.data
);
967 if(pa_database_get(u
->database
, &key
, &value
) != NULL
){
968 if(value
.size
== profile_size
){
969 float *profile
= (float *) value
.data
;
970 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
971 u
->Xs
[channel
][a_i
] = profile
[0];
972 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE
* sizeof(float));
973 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
974 pa_aupdate_write_end(u
->a_H
[channel
]);
975 pa_xfree(u
->base_profiles
[channel
]);
976 u
->base_profiles
[channel
] = pa_xstrdup(name
);
978 return "incompatible size";
980 pa_datum_free(&value
);
982 return "profile doesn't exist";
987 static void load_state(struct userdata
*u
){
991 pa_database
*database
;
993 char *state_name
= u
->name
;
994 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
995 database
= pa_database_open(dbname
, FALSE
);
998 pa_log("No resume state");
1002 key
.data
= state_name
;
1003 key
.size
= strlen(key
.data
);
1005 if(pa_database_get(database
, &key
, &value
) != NULL
){
1006 if(value
.size
> FILTER_STATE_SIZE
* sizeof(float) + sizeof(uint16_t)){
1007 float *state
= (float *) value
.data
;
1010 for(size_t c
= 0; c
< u
->channels
; ++c
){
1011 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1012 H
= state
+ c
* CHANNEL_PROFILE_SIZE
+ 1;
1013 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE
];
1014 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE
* sizeof(float));
1015 pa_aupdate_write_end(u
->a_H
[c
]);
1017 unpack(((char *)value
.data
) + FILTER_STATE_SIZE
* sizeof(float), value
.size
- FILTER_STATE_SIZE
* sizeof(float), &names
, &n_profs
);
1018 n_profs
= PA_MIN(n_profs
, u
->channels
);
1019 for(size_t c
= 0; c
< n_profs
; ++c
){
1020 pa_xfree(u
->base_profiles
[c
]);
1021 u
->base_profiles
[c
] = names
[c
];
1025 pa_datum_free(&value
);
1027 pa_log("resume state exists but is wrong size!");
1029 pa_database_close(database
);
1032 /* Called from main context */
1033 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1036 pa_sink_input_assert_ref(i
);
1037 pa_assert_se(u
= i
->userdata
);
1039 return u
->sink
!= dest
;
1042 /* Called from main context */
1043 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1046 pa_sink_input_assert_ref(i
);
1047 pa_assert_se(u
= i
->userdata
);
1049 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1050 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1052 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
1055 int pa__init(pa_module
*m
) {
1062 pa_sink_input_new_data sink_input_data
;
1063 pa_sink_new_data sink_data
;
1070 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1071 pa_log("Failed to parse module arguments.");
1075 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
1076 pa_log("Master sink not found, trying default");
1077 master
= pa_namereg_get_default_sink(m
->core
);
1079 pa_log("no default sink found!");
1084 ss
= master
->sample_spec
;
1085 ss
.format
= PA_SAMPLE_FLOAT32
;
1086 map
= master
->channel_map
;
1087 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1088 pa_log("Invalid sample format specification or channel map");
1091 fs
= pa_frame_size(&ss
);
1093 u
= pa_xnew0(struct userdata
, 1);
1097 u
->set_default
= TRUE
;
1098 pa_modargs_get_value_boolean(ma
, "set_default", &u
->set_default
);
1100 u
->channels
= ss
.channels
;
1101 u
->fft_size
= pow(2, ceil(log(ss
.rate
) / log(2)));//probably unstable near corner cases of powers of 2
1102 pa_log_debug("fft size: %ld", u
->fft_size
);
1103 u
->window_size
= 15999;
1104 if(u
->window_size
% 2 == 0){
1107 u
->R
= (u
->window_size
+ 1) / 2;
1108 u
->overlap_size
= u
->window_size
- u
->R
;
1109 u
->samples_gathered
= 0;
1110 u
->input_buffer_max
= 0;
1111 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1112 u
->Xs
= pa_xnew0(float *, u
->channels
);
1113 u
->Hs
= pa_xnew0(float **, u
->channels
);
1114 for(size_t c
= 0; c
< u
->channels
; ++c
){
1115 u
->Xs
[c
] = pa_xnew0(float, 2);
1116 u
->Hs
[c
] = pa_xnew0(float *, 2);
1117 for(size_t i
= 0; i
< 2; ++i
){
1118 u
->Hs
[c
][i
] = alloc(FILTER_SIZE
, sizeof(float));
1121 u
->W
= alloc(u
->window_size
, sizeof(float));
1122 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1123 memset(u
->work_buffer
, 0, u
->fft_size
*sizeof(float));
1124 u
->input
= pa_xnew0(float *, u
->channels
);
1125 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1126 for(size_t c
= 0; c
< u
->channels
; ++c
){
1127 u
->a_H
[c
] = pa_aupdate_new();
1129 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1131 u
->output_window
= alloc((FILTER_SIZE
), sizeof(fftwf_complex
));
1132 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1133 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1135 hanning_window(u
->W
, u
->window_size
);
1136 u
->first_iteration
= TRUE
;
1138 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1139 for(size_t c
= 0; c
< u
->channels
; ++c
){
1140 u
->base_profiles
[c
] = pa_xstrdup("default");
1144 pa_sink_new_data_init(&sink_data
);
1145 sink_data
.driver
= __FILE__
;
1146 sink_data
.module
= m
;
1147 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1148 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1149 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1150 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1151 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1152 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s",z
? z
: master
->name
);
1153 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1154 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1156 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1157 pa_log("Invalid properties");
1158 pa_sink_new_data_done(&sink_data
);
1162 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1163 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1164 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1165 pa_sink_new_data_done(&sink_data
);
1168 pa_log("Failed to create sink.");
1171 u
->name
=pa_xstrdup(u
->sink
->name
);
1172 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1173 u
->sink
->set_state
= sink_set_state_cb
;
1174 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1175 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1176 u
->sink
->set_volume
= sink_set_volume_cb
;
1177 u
->sink
->set_mute
= sink_set_mute_cb
;
1178 u
->sink
->userdata
= u
;
1179 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1180 u
->output_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, NULL
);
1181 u
->output_buffer
= NULL
;
1182 u
->output_buffer_length
= 0;
1183 u
->output_buffer_max_length
= 0;
1185 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1186 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1188 /* Create sink input */
1189 pa_sink_input_new_data_init(&sink_input_data
);
1190 sink_input_data
.driver
= __FILE__
;
1191 sink_input_data
.module
= m
;
1192 sink_input_data
.sink
= master
;
1193 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1194 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1195 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1196 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1198 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1199 pa_sink_input_new_data_done(&sink_input_data
);
1204 u
->sink_input
->pop
= sink_input_pop_cb
;
1205 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1206 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1207 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1208 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1209 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1210 u
->sink_input
->kill
= sink_input_kill_cb
;
1211 u
->sink_input
->attach
= sink_input_attach_cb
;
1212 u
->sink_input
->detach
= sink_input_detach_cb
;
1213 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1214 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1215 u
->sink_input
->moving
= sink_input_moving_cb
;
1216 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1217 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1219 u
->sink_input
->userdata
= u
;
1221 pa_sink_put(u
->sink
);
1222 pa_sink_input_put(u
->sink_input
);
1224 pa_modargs_free(ma
);
1229 //default filter to these
1230 for(size_t c
= 0; c
< u
->channels
; ++c
){
1231 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1233 u
->Xs
[c
][a_i
] = 1.0f
;
1234 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1235 H
[i
] = 1.0 / sqrtf(2.0f
);
1237 fix_filter(H
, u
->fft_size
);
1238 pa_aupdate_write_end(u
->a_H
[c
]);
1240 //load old parameters
1247 pa_modargs_free(ma
);
1255 int pa__get_n_used(pa_module
*m
) {
1259 pa_assert_se(u
= m
->userdata
);
1261 return pa_sink_linked_by(u
->sink
);
1264 void pa__done(pa_module
*m
) {
1269 if (!(u
= m
->userdata
))
1276 for(size_t c
= 0; c
< u
->channels
; ++c
){
1277 pa_xfree(u
->base_profiles
[c
]);
1279 pa_xfree(u
->base_profiles
);
1281 /* See comments in sink_input_kill_cb() above regarding
1282 * destruction order! */
1285 pa_sink_input_unlink(u
->sink_input
);
1288 pa_sink_unlink(u
->sink
);
1291 pa_sink_input_unref(u
->sink_input
);
1294 pa_sink_unref(u
->sink
);
1296 if(u
->output_buffer
){
1297 pa_xfree(u
->output_buffer
);
1299 pa_memblockq_free(u
->output_q
);
1300 pa_memblockq_free(u
->input_q
);
1302 fftwf_destroy_plan(u
->inverse_plan
);
1303 fftwf_destroy_plan(u
->forward_plan
);
1304 pa_xfree(u
->output_window
);
1305 for(size_t c
=0; c
< u
->channels
; ++c
){
1306 pa_aupdate_free(u
->a_H
[c
]);
1307 pa_xfree(u
->overlap_accum
[c
]);
1308 pa_xfree(u
->input
[c
]);
1311 pa_xfree(u
->overlap_accum
);
1313 pa_xfree(u
->work_buffer
);
1315 for(size_t c
= 0; c
< u
->channels
; ++c
){
1317 for(size_t i
= 0; i
< 2; ++i
){
1318 pa_xfree(u
->Hs
[c
][i
]);
1331 * DBus Routines and Callbacks
1333 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1334 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1335 #define MANAGER_IFACE EXTNAME ".Manager"
1336 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1337 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1338 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1339 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1340 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1341 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1342 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1343 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1344 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1345 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1346 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1347 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1348 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1349 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1350 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1351 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1352 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1353 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1354 static void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1355 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1356 enum manager_method_index
{
1357 MANAGER_METHOD_REMOVE_PROFILE
,
1361 pa_dbus_arg_info remove_profile_args
[]={
1365 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1366 [MANAGER_METHOD_REMOVE_PROFILE
]{
1367 .method_name
="RemoveProfile",
1368 .arguments
=remove_profile_args
,
1369 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1370 .receive_cb
=manager_handle_remove_profile
}
1373 enum manager_handler_index
{
1374 MANAGER_HANDLER_REVISION
,
1375 MANAGER_HANDLER_EQUALIZED_SINKS
,
1376 MANAGER_HANDLER_PROFILES
,
1380 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1381 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1382 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1383 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1386 pa_dbus_arg_info sink_args
[]={
1390 enum manager_signal_index
{
1391 MANAGER_SIGNAL_SINK_ADDED
,
1392 MANAGER_SIGNAL_SINK_REMOVED
,
1393 MANAGER_SIGNAL_PROFILES_CHANGED
,
1397 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1398 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1399 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1400 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1403 static pa_dbus_interface_info manager_info
={
1404 .name
=MANAGER_IFACE
,
1405 .method_handlers
=manager_methods
,
1406 .n_method_handlers
=MANAGER_METHOD_MAX
,
1407 .property_handlers
=manager_handlers
,
1408 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1409 .get_all_properties_cb
=manager_get_all
,
1410 .signals
=manager_signals
,
1411 .n_signals
=MANAGER_SIGNAL_MAX
1414 enum equalizer_method_index
{
1415 EQUALIZER_METHOD_FILTER_POINTS
,
1416 EQUALIZER_METHOD_SEED_FILTER
,
1417 EQUALIZER_METHOD_SAVE_PROFILE
,
1418 EQUALIZER_METHOD_LOAD_PROFILE
,
1419 EQUALIZER_METHOD_SET_FILTER
,
1420 EQUALIZER_METHOD_GET_FILTER
,
1421 EQUALIZER_METHOD_SAVE_STATE
,
1422 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1423 EQUALIZER_METHOD_MAX
1426 enum equalizer_handler_index
{
1427 EQUALIZER_HANDLER_REVISION
,
1428 EQUALIZER_HANDLER_SAMPLERATE
,
1429 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1430 EQUALIZER_HANDLER_N_COEFS
,
1431 EQUALIZER_HANDLER_N_CHANNELS
,
1432 EQUALIZER_HANDLER_MAX
1435 pa_dbus_arg_info filter_points_args
[]={
1436 {"channel", "u","in"},
1439 {"preamp", "d","out"}
1441 pa_dbus_arg_info seed_filter_args
[]={
1442 {"channel", "u","in"},
1445 {"preamp", "d","in"}
1448 pa_dbus_arg_info set_filter_args
[]={
1449 {"channel", "u","in"},
1451 {"preamp", "d","in"}
1453 pa_dbus_arg_info get_filter_args
[]={
1454 {"channel", "u","in"},
1456 {"preamp", "d","out"}
1459 pa_dbus_arg_info save_profile_args
[]={
1460 {"channel", "u","in"},
1463 pa_dbus_arg_info load_profile_args
[]={
1464 {"channel", "u","in"},
1467 pa_dbus_arg_info base_profile_name_args
[]={
1468 {"channel", "u","in"},
1472 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1473 [EQUALIZER_METHOD_SEED_FILTER
]{
1474 .method_name
="SeedFilter",
1475 .arguments
=seed_filter_args
,
1476 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1477 .receive_cb
=equalizer_handle_seed_filter
},
1478 [EQUALIZER_METHOD_FILTER_POINTS
]{
1479 .method_name
="FilterAtPoints",
1480 .arguments
=filter_points_args
,
1481 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1482 .receive_cb
=equalizer_handle_get_filter_points
},
1483 [EQUALIZER_METHOD_SET_FILTER
]{
1484 .method_name
="SetFilter",
1485 .arguments
=set_filter_args
,
1486 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1487 .receive_cb
=equalizer_handle_set_filter
},
1488 [EQUALIZER_METHOD_GET_FILTER
]{
1489 .method_name
="GetFilter",
1490 .arguments
=get_filter_args
,
1491 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1492 .receive_cb
=equalizer_handle_get_filter
},
1493 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1494 .method_name
="SaveProfile",
1495 .arguments
=save_profile_args
,
1496 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1497 .receive_cb
=equalizer_handle_save_profile
},
1498 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1499 .method_name
="LoadProfile",
1500 .arguments
=load_profile_args
,
1501 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1502 .receive_cb
=equalizer_handle_load_profile
},
1503 [EQUALIZER_METHOD_SAVE_STATE
]{
1504 .method_name
="SaveState",
1507 .receive_cb
=equalizer_handle_save_state
},
1508 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1509 .method_name
="BaseProfile",
1510 .arguments
=base_profile_name_args
,
1511 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1512 .receive_cb
=equalizer_handle_get_profile_name
}
1515 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1516 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1517 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1518 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1519 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1520 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1523 enum equalizer_signal_index
{
1524 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1525 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1526 EQUALIZER_SIGNAL_MAX
1529 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1530 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1531 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1534 static pa_dbus_interface_info equalizer_info
={
1535 .name
=EQUALIZER_IFACE
,
1536 .method_handlers
=equalizer_methods
,
1537 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1538 .property_handlers
=equalizer_handlers
,
1539 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1540 .get_all_properties_cb
=equalizer_get_all
,
1541 .signals
=equalizer_signals
,
1542 .n_signals
=EQUALIZER_SIGNAL_MAX
1545 void dbus_init(struct userdata
*u
){
1547 DBusMessage
*signal
= NULL
;
1548 pa_idxset
*sink_list
= NULL
;
1549 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1550 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1552 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1553 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1554 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1555 if(sink_list
== NULL
){
1557 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1558 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1559 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1560 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1562 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1563 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1564 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1566 pa_idxset_put(sink_list
, u
, &dummy
);
1568 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1569 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1570 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1571 dbus_message_unref(signal
);
1574 void dbus_done(struct userdata
*u
){
1575 pa_idxset
*sink_list
;
1578 DBusMessage
*signal
= NULL
;
1579 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1580 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1581 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1582 dbus_message_unref(signal
);
1584 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1585 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1586 if(pa_idxset_size(sink_list
)==0){
1587 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1588 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1589 pa_shared_remove(u
->sink
->core
, EQDB
);
1590 pa_database_close(u
->database
);
1591 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1592 pa_xfree(sink_list
);
1594 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1595 pa_xfree(u
->dbus_path
);
1596 pa_dbus_protocol_unref(u
->dbus_protocol
);
1599 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1601 pa_core
*c
= (pa_core
*)_u
;
1602 DBusMessage
*signal
= NULL
;
1603 pa_dbus_protocol
*dbus_protocol
;
1608 dbus_error_init(&error
);
1609 if(!dbus_message_get_args(msg
, &error
,
1610 DBUS_TYPE_STRING
, &name
,
1611 DBUS_TYPE_INVALID
)){
1612 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1613 dbus_error_free(&error
);
1616 remove_profile(c
,name
);
1617 pa_dbus_send_empty_reply(conn
, msg
);
1619 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1620 dbus_protocol
= pa_dbus_protocol_get(c
);
1621 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1622 pa_dbus_protocol_unref(dbus_protocol
);
1623 dbus_message_unref(signal
);
1626 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1628 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1631 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1633 struct userdata
*sink_u
= NULL
;
1635 pa_idxset
*sink_list
;
1640 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1641 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1642 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1643 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1644 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1645 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1649 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1651 char **names
= NULL
;
1656 get_sinks((pa_core
*) _u
, &names
, &n
);
1657 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1658 for(unsigned i
= 0; i
< n
; ++i
){
1664 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1666 pa_database
*database
;
1667 pa_datum key
, next_key
;
1668 pa_strlist
*head
=NULL
, *iter
;
1670 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1675 done
= !pa_database_first(database
, &key
, NULL
);
1678 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1679 name
=pa_xmalloc(key
.size
+ 1);
1680 memcpy(name
, key
.data
, key
.size
);
1681 name
[key
.size
] = '\0';
1682 pa_datum_free(&key
);
1683 head
= pa_strlist_prepend(head
, name
);
1688 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1690 for(unsigned i
= 0; i
< *n
; ++i
){
1691 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1692 iter
= pa_strlist_next(iter
);
1694 pa_strlist_free(head
);
1697 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1704 get_profiles((pa_core
*)_u
, &names
, &n
);
1705 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1706 for(unsigned i
= 0; i
< n
; ++i
){
1712 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1714 char **names
= NULL
;
1716 DBusMessage
*reply
= NULL
;
1717 DBusMessageIter msg_iter
, dict_iter
;
1721 pa_assert_se(c
= _u
);
1723 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1724 dbus_message_iter_init_append(reply
, &msg_iter
);
1725 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1728 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1730 get_sinks(c
, &names
, &n
);
1731 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1732 for(unsigned i
= 0; i
< n
; ++i
){
1737 get_profiles(c
, &names
, &n
);
1738 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1739 for(unsigned i
= 0; i
< n
; ++i
){
1743 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1744 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1745 dbus_message_unref(reply
);
1748 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1749 struct userdata
*u
=(struct userdata
*) _u
;
1751 DBusMessage
*signal
= NULL
;
1753 uint32_t *xs
, channel
, r_channel
;
1754 double *_ys
, preamp
;
1755 unsigned x_npoints
, y_npoints
, a_i
;
1757 pa_bool_t points_good
= TRUE
;
1762 dbus_error_init(&error
);
1764 if(!dbus_message_get_args(msg
, &error
,
1765 DBUS_TYPE_UINT32
, &channel
,
1766 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1767 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1768 DBUS_TYPE_DOUBLE
, &preamp
,
1769 DBUS_TYPE_INVALID
)){
1770 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1771 dbus_error_free(&error
);
1774 if(channel
> u
->channels
){
1775 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1776 dbus_error_free(&error
);
1779 for(size_t i
= 0; i
< x_npoints
; ++i
){
1780 if(xs
[i
] >= FILTER_SIZE
){
1781 points_good
= FALSE
;
1785 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1786 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1787 dbus_error_free(&error
);
1789 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE
){
1790 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE
);
1791 dbus_error_free(&error
);
1793 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1794 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1795 dbus_error_free(&error
);
1799 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1800 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1801 ys
[i
] = (float) _ys
[i
];
1803 r_channel
= channel
== u
->channels
? 0 : channel
;
1804 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1805 H
= u
->Hs
[r_channel
][a_i
];
1806 u
->Xs
[r_channel
][a_i
] = preamp
;
1807 interpolate(H
, FILTER_SIZE
, xs
, ys
, x_npoints
);
1808 fix_filter(H
, u
->fft_size
);
1809 if(channel
== u
->channels
){
1810 for(size_t c
= 1; c
< u
->channels
; ++c
){
1811 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1812 float *H_p
= u
->Hs
[c
][b_i
];
1813 u
->Xs
[c
][b_i
] = preamp
;
1814 memcpy(H_p
, H
, FILTER_SIZE
* sizeof(float));
1815 pa_aupdate_write_end(u
->a_H
[c
]);
1818 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1822 pa_dbus_send_empty_reply(conn
, msg
);
1824 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1825 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1826 dbus_message_unref(signal
);
1829 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1830 struct userdata
*u
= (struct userdata
*) _u
;
1831 uint32_t *xs
, channel
, r_channel
;
1833 unsigned x_npoints
, a_i
;
1835 pa_bool_t points_good
=TRUE
;
1836 DBusMessage
*reply
= NULL
;
1837 DBusMessageIter msg_iter
;
1844 dbus_error_init(&error
);
1845 if(!dbus_message_get_args(msg
, &error
,
1846 DBUS_TYPE_UINT32
, &channel
,
1847 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1848 DBUS_TYPE_INVALID
)){
1849 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1850 dbus_error_free(&error
);
1853 if(channel
> u
->channels
){
1854 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1855 dbus_error_free(&error
);
1859 for(size_t i
= 0; i
< x_npoints
; ++i
){
1860 if(xs
[i
] >= FILTER_SIZE
){
1866 if(x_npoints
> FILTER_SIZE
|| !points_good
){
1867 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE
);
1868 dbus_error_free(&error
);
1872 r_channel
= channel
== u
->channels
? 0 : channel
;
1873 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1874 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1875 H
= u
->Hs
[r_channel
][a_i
];
1876 preamp
= u
->Xs
[r_channel
][a_i
];
1877 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1878 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1880 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1882 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1883 dbus_message_iter_init_append(reply
, &msg_iter
);
1885 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1886 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1888 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1889 dbus_message_unref(reply
);
1893 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1896 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1897 *H_
= pa_xnew0(double, FILTER_SIZE
);
1898 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1899 H
= u
->Hs
[r_channel
][a_i
];
1900 for(size_t i
= 0;i
< FILTER_SIZE
; ++i
){
1901 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1903 *preamp
= u
->Xs
[r_channel
][a_i
];
1905 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1908 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1913 DBusMessage
*reply
= NULL
;
1914 DBusMessageIter msg_iter
;
1916 pa_assert_se(u
= (struct userdata
*) _u
);
1920 dbus_error_init(&error
);
1921 if(!dbus_message_get_args(msg
, &error
,
1922 DBUS_TYPE_UINT32
, &channel
,
1923 DBUS_TYPE_INVALID
)){
1924 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1925 dbus_error_free(&error
);
1928 if(channel
> u
->channels
){
1929 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1930 dbus_error_free(&error
);
1934 n_coefs
= CHANNEL_PROFILE_SIZE
;
1937 get_filter(u
, channel
, &H_
, &preamp
);
1938 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1939 dbus_message_iter_init_append(reply
, &msg_iter
);
1941 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1942 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1944 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1945 dbus_message_unref(reply
);
1949 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1951 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1954 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1955 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1956 H
= u
->Hs
[r_channel
][a_i
];
1957 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1958 H
[i
] = (float) H_
[i
];
1960 fix_filter(H
, u
->fft_size
);
1961 if(channel
== u
->channels
){
1962 for(size_t c
= 1; c
< u
->channels
; ++c
){
1963 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1964 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1965 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE
* sizeof(float));
1966 pa_aupdate_write_end(u
->a_H
[c
]);
1969 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1972 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1977 DBusMessage
*signal
= NULL
;
1979 pa_assert_se(u
= (struct userdata
*) _u
);
1983 dbus_error_init(&error
);
1984 if(!dbus_message_get_args(msg
, &error
,
1985 DBUS_TYPE_UINT32
, &channel
,
1986 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1987 DBUS_TYPE_DOUBLE
, &preamp
,
1988 DBUS_TYPE_INVALID
)){
1989 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1990 dbus_error_free(&error
);
1993 if(channel
> u
->channels
){
1994 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1995 dbus_error_free(&error
);
1998 if(_n_coefs
!= FILTER_SIZE
){
1999 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE
, _n_coefs
);
2002 set_filter(u
, channel
, H
, preamp
);
2004 pa_dbus_send_empty_reply(conn
, msg
);
2006 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2007 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2008 dbus_message_unref(signal
);
2011 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2012 struct userdata
*u
= (struct userdata
*) _u
;
2014 uint32_t channel
, r_channel
;
2015 DBusMessage
*signal
= NULL
;
2020 dbus_error_init(&error
);
2022 if(!dbus_message_get_args(msg
, &error
,
2023 DBUS_TYPE_UINT32
, &channel
,
2024 DBUS_TYPE_STRING
, &name
,
2025 DBUS_TYPE_INVALID
)){
2026 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2027 dbus_error_free(&error
);
2030 if(channel
> u
->channels
){
2031 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2032 dbus_error_free(&error
);
2035 r_channel
= channel
== u
->channels
? 0 : channel
;
2036 save_profile(u
, r_channel
, name
);
2037 pa_dbus_send_empty_reply(conn
, msg
);
2039 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
2040 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2041 dbus_message_unref(signal
);
2044 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2045 struct userdata
*u
= (struct userdata
*) _u
;
2048 uint32_t channel
, r_channel
;
2049 const char *err_msg
= NULL
;
2050 DBusMessage
*signal
= NULL
;
2055 dbus_error_init(&error
);
2057 if(!dbus_message_get_args(msg
, &error
,
2058 DBUS_TYPE_UINT32
, &channel
,
2059 DBUS_TYPE_STRING
, &name
,
2060 DBUS_TYPE_INVALID
)){
2061 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2062 dbus_error_free(&error
);
2065 if(channel
> u
->channels
){
2066 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2067 dbus_error_free(&error
);
2070 r_channel
= channel
== u
->channels
? 0 : channel
;
2072 err_msg
= load_profile(u
, r_channel
, name
);
2073 if(err_msg
!= NULL
){
2074 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2075 dbus_error_free(&error
);
2078 if(channel
== u
->channels
){
2079 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2080 load_profile(u
, c
, name
);
2083 pa_dbus_send_empty_reply(conn
, msg
);
2085 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2086 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2087 dbus_message_unref(signal
);
2090 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2091 struct userdata
*u
= (struct userdata
*) _u
;
2097 pa_dbus_send_empty_reply(conn
, msg
);
2100 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2101 struct userdata
*u
= (struct userdata
*) _u
;
2103 uint32_t channel
, r_channel
;
2108 dbus_error_init(&error
);
2110 if(!dbus_message_get_args(msg
, &error
,
2111 DBUS_TYPE_UINT32
, &channel
,
2112 DBUS_TYPE_INVALID
)){
2113 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2114 dbus_error_free(&error
);
2117 if(channel
> u
->channels
){
2118 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2119 dbus_error_free(&error
);
2122 r_channel
= channel
== u
->channels
? 0 : channel
;
2123 pa_assert(u
->base_profiles
[r_channel
]);
2124 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2127 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2129 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2132 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2135 pa_assert_se(u
= (struct userdata
*) _u
);
2139 channels
= (uint32_t) u
->channels
;
2140 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2143 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2146 pa_assert_se(u
= (struct userdata
*) _u
);
2150 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2151 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2154 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2157 pa_assert_se(u
= (struct userdata
*) _u
);
2161 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2162 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2165 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2168 pa_assert_se(u
= (struct userdata
*) _u
);
2172 fft_size
= (uint32_t) u
->fft_size
;
2173 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2176 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2178 DBusMessage
*reply
= NULL
;
2179 DBusMessageIter msg_iter
, dict_iter
;
2180 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2181 pa_assert_se(u
= (struct userdata
*) _u
);
2185 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2186 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2187 fft_size
= (uint32_t) u
->fft_size
;
2188 channels
= (uint32_t) u
->channels
;
2190 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2191 dbus_message_iter_init_append(reply
, &msg_iter
);
2192 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2194 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2195 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2196 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2197 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2198 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2200 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2201 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2202 dbus_message_unref(reply
);