]> code.delx.au - pulseaudio/blob - src/modules/module-equalizer-sink.c
module-equalizer-sink: reverted buffering logic back to how the ladspa sink did it
[pulseaudio] / src / modules / module-equalizer-sink.c
1 /***
2 This file is part of PulseAudio.
3
4 This module is based off Lennart Poettering's LADSPA sink and swaps out
5 LADSPA functionality for a STFT OLA based digital equalizer. All new work
6 is published under Pulseaudio's original license.
7 Copyright 2009 Jason Newton <nevion@gmail.com>
8
9 Original Author:
10 Copyright 2004-2008 Lennart Poettering
11
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.
16
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.
21
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
25 USA.
26 ***/
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <float.h>
35 #include <math.h>
36 #include <fftw3.h>
37 #include <string.h>
38
39 #include <pulse/xmalloc.h>
40 #include <pulse/i18n.h>
41
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/namereg.h>
44 #include <pulsecore/sink.h>
45 #include <pulsecore/module.h>
46 #include <pulsecore/core-util.h>
47 #include <pulsecore/modargs.h>
48 #include <pulsecore/log.h>
49 #include <pulsecore/thread.h>
50 #include <pulsecore/thread-mq.h>
51 #include <pulsecore/rtpoll.h>
52 #include <pulsecore/sample-util.h>
53 #include <pulsecore/shared.h>
54 #include <pulsecore/idxset.h>
55 #include <pulsecore/database.h>
56 #include <pulsecore/protocol-dbus.h>
57 #include <pulsecore/dbus-util.h>
58
59 #include <stdint.h>
60 #include <time.h>
61
62
63 //#undef __SSE2__
64 #ifdef __SSE2__
65 #include <xmmintrin.h>
66 #include <emmintrin.h>
67 #endif
68
69
70
71 #include "module-equalizer-sink-symdef.h"
72
73 PA_MODULE_AUTHOR("Jason Newton");
74 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
75 PA_MODULE_VERSION(PACKAGE_VERSION);
76 PA_MODULE_LOAD_ONCE(FALSE);
77 PA_MODULE_USAGE(_("sink=<sink to connect to> "));
78
79 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
80
81
82 struct userdata {
83 pa_core *core;
84 pa_module *module;
85 pa_sink *sink, *master;
86 pa_sink_input *sink_input;
87 char *name;
88
89 size_t channels;
90 size_t fft_size;//length (res) of fft
91 size_t window_size;/*
92 *sliding window size
93 *effectively chooses R
94 */
95 size_t R;/* the hop size between overlapping windows
96 * the latency of the filter, calculated from window_size
97 * based on constraints of COLA and window function
98 */
99 size_t latency;//Really just R but made into it's own variable
100 //for twiddling with pulseaudio
101 size_t overlap_size;//window_size-R
102 size_t samples_gathered;
103 size_t max_output;//max amount of samples outputable in a single
104 //message
105 size_t target_samples;
106 float *H;//frequency response filter (magnitude based)
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;
111 //size_t samplings;
112
113 float *Hs[2];//thread updatable copies
114 pa_aupdate *a_H;
115 pa_memchunk conv_buffer;
116 pa_memblockq *input_q;
117
118 pa_dbus_protocol *dbus_protocol;
119 char *dbus_path;
120
121 pa_database *database;
122 };
123
124 static const char* const valid_modargs[] = {
125 "sink_name",
126 "sink_properties",
127 "master",
128 "format",
129 "rate",
130 "channels",
131 "channel_map",
132 NULL
133 };
134
135 static uint64_t time_diff(struct timespec *timeA_p, struct timespec *timeB_p);
136 static void hanning_window(float *W, size_t window_size);
137 void fix_filter(float *H, size_t fft_size);
138 void interpolate(float *signal, size_t length, uint32_t *xs, float *ys, size_t n_points);
139 static void array_out(const char *name, float *a, size_t length);
140 static int is_monotonic(uint32_t *xs, size_t length);
141 static void process_samples(struct userdata *u, pa_memchunk *tchunk);
142 static void input_buffer(struct userdata *u, pa_memchunk *in);
143 static void save_profile(struct userdata *u,char *name);
144 static void save_state(struct userdata *u);
145 static void remove_profile(pa_core *u,char *name);
146 static const char * load_profile(struct userdata *u,char *name);
147 static void load_state(struct userdata *u);
148
149 void dsp_logic(
150 float * __restrict__ dst,
151 float * __restrict__ src,
152 float * __restrict__ overlap,
153 const float * __restrict__ H,
154 const float * __restrict__ W,
155 fftwf_complex * __restrict__ output_window,
156 struct userdata *u);
157
158
159 /*
160 * DBus Routines and Callbacks
161 */
162 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
163 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
164 static void dbus_init(struct userdata *u);
165 static void dbus_done(struct userdata *u);
166 static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
167 static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u);
168 static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u);
169 static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
170 static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
171 static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
172 static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
173 static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
174 static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u);
175 static void equalizer_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
176 static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
177 static void equalizer_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
178 static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
179 static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u);
180 static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
181 static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
182
183 #define v_size 4
184 #define gettime(x) clock_gettime(CLOCK_MONOTONIC, &x)
185 #define tdiff(x, y) time_diff(&x, &y)
186 #define mround(x, y) (x % y == 0 ? x : ( x / y + 1) * y)
187 #define SINKLIST "equalized_sinklist"
188 #define EQDB "equalizer_db"
189
190 uint64_t time_diff(struct timespec *timeA_p, struct timespec *timeB_p)
191 {
192 return ((timeA_p->tv_sec * 1000000000ULL) + timeA_p->tv_nsec) -
193 ((timeB_p->tv_sec * 1000000000ULL) + timeB_p->tv_nsec);
194 }
195
196 void hanning_window(float *W, size_t window_size){
197 //h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2
198 for(size_t i=0; i < window_size;++i){
199 W[i] = (float).5*(1-cos(2*M_PI*i/(window_size+1)));
200 }
201 }
202
203 void fix_filter(float *H, size_t fft_size){
204 //divide out the fft gain
205 for(size_t i = 0; i < fft_size / 2 + 1; ++i){
206 H[i] /= fft_size;
207 }
208 }
209
210 void interpolate(float *signal, size_t length, uint32_t *xs, float *ys, size_t n_points){
211 //Note that xs must be monotonically increasing!
212 pa_assert_se(n_points>=2);
213 pa_assert_se(xs[0] == 0);
214 pa_assert_se(xs[n_points - 1] == length - 1);
215 for(size_t x = 0, x_range_lower_i = 0; x < length-1; ++x){
216 pa_assert(x_range_lower_i < n_points-1);
217 float x_range_lower = (float) (xs[x_range_lower_i]);
218 float x_range_upper = (float) (xs[x_range_lower_i+1]);
219 pa_assert_se(x_range_lower < x_range_upper);
220 pa_assert_se(x >= x_range_lower);
221 pa_assert_se(x <= x_range_upper);
222 //bilinear-interpolation of coefficients specified
223 float c0 = (x-x_range_lower)/(x_range_upper-x_range_lower);
224 pa_assert_se(c0 >= 0&&c0 <= 1.0);
225 signal[x] = ((1.0f - c0) * ys[x_range_lower_i] + c0 * ys[x_range_lower_i + 1]);
226 while(x >= xs[x_range_lower_i + 1]){
227 x_range_lower_i++;
228 }
229 }
230 signal[length-1]=ys[n_points-1];
231 }
232
233 void array_out(const char *name, float *a, size_t length){
234 FILE *p=fopen(name, "w");
235 if(!p){
236 pa_log("opening %s failed!", name);
237 return;
238 }
239 for(size_t i = 0; i < length; ++i){
240 fprintf(p, "%e,", a[i]);
241 //if(i%1000==0){
242 // fprintf(p, "\n");
243 //}
244 }
245 fprintf(p, "\n");
246 fclose(p);
247 }
248 static int is_monotonic(uint32_t *xs,size_t length){
249 if(length<2){
250 return 1;
251 }
252 for(size_t i = 1; i < length; ++i){
253 if(xs[i]<=xs[i-1]){
254 return 0;
255 }
256 }
257 return 1;
258 }
259
260
261 /* Called from I/O thread context */
262 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
263 struct userdata *u = PA_SINK(o)->userdata;
264
265 switch (code) {
266
267 case PA_SINK_MESSAGE_GET_LATENCY: {
268 pa_usec_t usec = 0;
269 pa_sample_spec *ss=&u->sink->sample_spec;
270 //size_t fs=pa_frame_size(&(u->sink->sample_spec));
271
272 /* Get the latency of the master sink */
273 if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
274 usec = 0;
275
276 //usec += pa_bytes_to_usec(u->latency * fs, ss);
277 //usec += pa_bytes_to_usec(u->samples_gathered * fs, ss);
278 usec += pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);
279 /* Add the latency internal to our sink input on top */
280 usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
281 *((pa_usec_t*) data) = usec;
282 return 0;
283 }
284 }
285
286 return pa_sink_process_msg(o, code, data, offset, chunk);
287 }
288
289
290 /* Called from main context */
291 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
292 struct userdata *u;
293
294 pa_sink_assert_ref(s);
295 pa_assert_se(u = s->userdata);
296
297 if (PA_SINK_IS_LINKED(state) &&
298 u->sink_input &&
299 PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
300
301 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
302
303 return 0;
304 }
305
306 /* Called from I/O thread context */
307 static void sink_request_rewind(pa_sink *s) {
308 struct userdata *u;
309
310 pa_sink_assert_ref(s);
311 pa_assert_se(u = s->userdata);
312
313 //pa_memblockq_drop(u->input_q,pa_memblockq_get_length(u->input_q));
314
315 /* Just hand this one over to the master sink */
316 pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes+pa_memblockq_get_length(u->input_q), TRUE, FALSE, FALSE);
317 }
318
319 /* Called from I/O thread context */
320 static void sink_update_requested_latency(pa_sink *s) {
321 struct userdata *u;
322
323 pa_sink_assert_ref(s);
324 pa_assert_se(u = s->userdata);
325
326 /* Just hand this one over to the master sink */
327 pa_sink_input_set_requested_latency_within_thread(
328 u->sink_input,
329 pa_sink_get_requested_latency_within_thread(s));
330 }
331
332 static void process_samples(struct userdata *u, pa_memchunk *tchunk){
333 size_t fs=pa_frame_size(&(u->sink->sample_spec));
334 pa_assert(u->samples_gathered >= u->R);
335 float *dst;
336 tchunk->index=0;
337 tchunk->length=u->R*fs;
338 tchunk->memblock=pa_memblock_new(u->core->mempool, tchunk->length);
339 dst=((float*)pa_memblock_acquire(tchunk->memblock));
340 for(size_t c=0;c < u->channels; c++) {
341 dsp_logic(
342 u->work_buffer,
343 u->input[c],
344 u->overlap_accum[c],
345 u->H,
346 u->W,
347 u->output_window,
348 u
349 );
350 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst + c, fs, u->work_buffer, sizeof(float), u->R);
351 }
352 pa_memblock_release(tchunk->memblock);
353 u->samples_gathered-=u->R;
354 }
355
356 typedef float v4sf __attribute__ ((__aligned__(v_size*sizeof(float))));
357 typedef union float_vector {
358 float f[v_size];
359 v4sf v;
360 #ifdef __SSE2__
361 __m128 m;
362 #endif
363 } float_vector_t;
364
365 //reference implementation
366 void dsp_logic(
367 float * __restrict__ dst,//used as a temp array too, needs to be fft_length!
368 float * __restrict__ src,/*input data w/ overlap at start,
369 *automatically cycled in routine
370 */
371 float * __restrict__ overlap,//The size of the overlap
372 const float * __restrict__ H,//The freq. magnitude scalers filter
373 const float * __restrict__ W,//The windowing function
374 fftwf_complex * __restrict__ output_window,//The transformed window'd src
375 struct userdata *u){
376 //use a linear-phase sliding STFT and overlap-add method (for each channel)
377 //zero padd the data
378 memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
379 //window the data
380 for(size_t j = 0;j < u->window_size; ++j){
381 dst[j] = W[j] * src[j];
382 }
383 //Processing is done here!
384 //do fft
385 fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
386 //perform filtering
387 for(size_t j = 0; j < u->fft_size / 2 + 1; ++j){
388 u->output_window[j][0] *= u->H[j];
389 u->output_window[j][1] *= u->H[j];
390 }
391 //inverse fft
392 fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
393 ////debug: tests overlaping add
394 ////and negates ALL PREVIOUS processing
395 ////yields a perfect reconstruction if COLA is held
396 //for(size_t j = 0; j < u->window_size; ++j){
397 // u->work_buffer[j] = u->W[j] * u->input[c][j];
398 //}
399
400 //overlap add and preserve overlap component from this window (linear phase)
401 for(size_t j = 0;j < u->overlap_size; ++j){
402 u->work_buffer[j] += overlap[j];
403 overlap[j] = dst[u->R+j];
404 }
405 ////debug: tests if basic buffering works
406 ////shouldn't modify the signal AT ALL (beyond roundoff)
407 //for(size_t j = 0; j < u->window_size;++j){
408 // u->work_buffer[j] = u->input[c][j];
409 //}
410
411 //preseve the needed input for the next window's overlap
412 memmove(src, src+u->R,
413 ((u->overlap_size + u->samples_gathered) - u->R)*sizeof(float)
414 );
415 }
416
417 ////regardless of sse enabled, the loops in here assume
418 ////16 byte aligned addresses and memory allocations divisible by v_size
419 //void dsp_logic(
420 // float * __restrict__ dst,//used as a temp array too, needs to be fft_length!
421 // float * __restrict__ src,/*input data w/ overlap at start,
422 // *automatically cycled in routine
423 // */
424 // float * __restrict__ overlap,//The size of the overlap
425 // const float * __restrict__ H,//The freq. magnitude scalers filter
426 // const float * __restrict__ W,//The windowing function
427 // fftwf_complex * __restrict__ output_window,//The transformed window'd src
428 // struct userdata *u){//Collection of constants
429 //
430 // const size_t window_size = mround(u->window_size,v_size);
431 // const size_t fft_h = mround(u->fft_size / 2 + 1, v_size / 2);
432 // //const size_t R = mround(u->R, v_size);
433 // const size_t overlap_size = mround(u->overlap_size, v_size);
434 //
435 // //assert(u->samples_gathered >= u->R);
436 // //zero out the bit beyond the real overlap so we don't add garbage
437 // for(size_t j = overlap_size; j > u->overlap_size; --j){
438 // overlap[j-1] = 0;
439 // }
440 // //use a linear-phase sliding STFT and overlap-add method
441 // //zero padd the data
442 // memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float));
443 // //window the data
444 // for(size_t j = 0; j < window_size; j += v_size){
445 // //dst[j] = W[j]*src[j];
446 // float_vector_t *d = (float_vector_t*) (dst+j);
447 // float_vector_t *w = (float_vector_t*) (W+j);
448 // float_vector_t *s = (float_vector_t*) (src+j);
449 //#if __SSE2__
450 // d->m = _mm_mul_ps(w->m, s->m);
451 //#else
452 // d->v = w->v * s->v;
453 //#endif
454 // }
455 // //Processing is done here!
456 // //do fft
457 // fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
458 //
459 //
460 // //perform filtering - purely magnitude based
461 // for(size_t j = 0;j < fft_h; j+=v_size/2){
462 // //output_window[j][0]*=H[j];
463 // //output_window[j][1]*=H[j];
464 // float_vector_t *d = (float_vector_t*)(output_window+j);
465 // float_vector_t h;
466 // h.f[0] = h.f[1] = H[j];
467 // h.f[2] = h.f[3] = H[j+1];
468 //#if __SSE2__
469 // d->m = _mm_mul_ps(d->m, h.m);
470 //#else
471 // d->v = d->v*h->v;
472 //#endif
473 // }
474 //
475 //
476 // //inverse fft
477 // fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
478 //
479 // ////debug: tests overlaping add
480 // ////and negates ALL PREVIOUS processing
481 // ////yields a perfect reconstruction if COLA is held
482 // //for(size_t j = 0; j < u->window_size; ++j){
483 // // dst[j] = W[j]*src[j];
484 // //}
485 //
486 // //overlap add and preserve overlap component from this window (linear phase)
487 // for(size_t j = 0; j < overlap_size; j+=v_size){
488 // //dst[j]+=overlap[j];
489 // //overlap[j]+=dst[j+R];
490 // float_vector_t *d = (float_vector_t*)(dst+j);
491 // float_vector_t *o = (float_vector_t*)(overlap+j);
492 //#if __SSE2__
493 // d->m = _mm_add_ps(d->m, o->m);
494 // o->m = ((float_vector_t*)(dst+u->R+j))->m;
495 //#else
496 // d->v = d->v+o->v;
497 // o->v = ((float_vector_t*)(dst+u->R+j))->v;
498 //#endif
499 // }
500 // //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float));
501 //
502 // //////debug: tests if basic buffering works
503 // //////shouldn't modify the signal AT ALL (beyond roundoff)
504 // //for(size_t j = 0; j < u->window_size; ++j){
505 // // dst[j] = src[j];
506 // //}
507 //
508 // //preseve the needed input for the next window's overlap
509 // memmove(src, src+u->R,
510 // ((u->overlap_size+u->samples_gathered)+-u->R)*sizeof(float)
511 // );
512 //}
513
514
515
516 void input_buffer(struct userdata *u, pa_memchunk *in){
517 size_t fs = pa_frame_size(&(u->sink->sample_spec));
518 size_t samples = in->length/fs;
519 pa_assert_se(samples <= u->target_samples-u->samples_gathered);
520 float *src = (float*) ((uint8_t*) pa_memblock_acquire(in->memblock) + in->index);
521 for(size_t c = 0; c < u->channels; c++) {
522 //buffer with an offset after the overlap from previous
523 //iterations
524 pa_assert_se(
525 u->input[c]+u->overlap_size+u->samples_gathered+samples <= u->input[c]+u->overlap_size+u->target_samples
526 );
527 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c]+u->overlap_size+u->samples_gathered, sizeof(float), src + c, fs, samples);
528 }
529 u->samples_gathered+=samples;
530 pa_memblock_release(in->memblock);
531 }
532
533 /* Called from I/O thread context */
534 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
535 struct userdata *u;
536 pa_sink_input_assert_ref(i);
537 pa_assert(chunk);
538 pa_assert(u = i->userdata);
539 pa_assert(u->sink);
540 size_t fs = pa_frame_size(&(u->sink->sample_spec));
541 pa_memchunk tchunk;
542 chunk->memblock = NULL;
543 if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
544 return -1;
545
546 /* Hmm, process any rewind request that might be queued up */
547 pa_sink_process_rewind(u->sink, 0);
548
549 //pa_log("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
550 struct timespec start, end;
551
552 do{
553 size_t input_remaining = u->target_samples-u->samples_gathered;
554 pa_assert(input_remaining>0);
555 //collect samples
556
557 //buffer = &u->conv_buffer;
558 //buffer->length = input_remaining*fs;
559 //buffer->index = 0;
560 //pa_memblock_ref(buffer->memblock);
561 //pa_sink_render_into(u->sink, buffer);
562 while(pa_memblockq_peek(u->input_q, &tchunk) < 0){
563 pa_sink_render(u->sink, input_remaining*fs, &tchunk);
564 pa_memblockq_push(u->input_q, &tchunk);
565 pa_memblock_unref(tchunk.memblock);
566 }
567 tchunk.length = PA_MIN(input_remaining*fs, tchunk.length);
568 pa_memblockq_drop(u->input_q,tchunk.length);
569 //pa_log("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
570 /* copy new input */
571 gettime(start);
572 input_buffer(u, &tchunk);
573 gettime(end);
574 //pa_log("Took %0.5f seconds to setup", tdiff(end, start)*1e-9);
575 pa_memblock_unref(tchunk.memblock);
576 }while(u->samples_gathered < u->R);
577
578 pa_assert(u->fft_size >= u->window_size);
579 pa_assert(u->R < u->window_size);
580 /* set the H filter */
581 unsigned H_i = pa_aupdate_read_begin(u->a_H);
582 u->H = u->Hs[H_i];
583 gettime(start);
584 /* process a block */
585 process_samples(u,chunk);
586 gettime(end);
587 //pa_log("Took %0.5f seconds to process", tdiff(end, start)*1e-9);
588 pa_aupdate_read_end(u->a_H);
589
590 pa_assert(chunk->memblock);
591 //pa_log("gave %ld", chunk->length/fs);
592 //pa_log("end pop");
593 return 0;
594 }
595
596 /* Called from I/O thread context */
597 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
598 struct userdata *u;
599 size_t amount = 0;
600
601 pa_log_debug("Rewind callback!");
602 pa_sink_input_assert_ref(i);
603 pa_assert_se(u = i->userdata);
604
605 if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
606 return;
607
608 if (u->sink->thread_info.rewind_nbytes > 0) {
609 size_t max_rewrite;
610
611 //max_rewrite = nbytes;
612 max_rewrite = nbytes + pa_memblockq_get_length(u->input_q);
613 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
614 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
615 u->sink->thread_info.rewind_nbytes = 0;
616
617 if (amount > 0) {
618 //pa_sample_spec *ss = &u->sink->sample_spec;
619 //invalidate the output q
620 pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
621 //pa_memblockq_drop(u->input_q, pa_memblockq_get_length(u->input_q));
622 //pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
623 pa_log_debug("Resetting equalizer");
624 u->samples_gathered = 0;
625 }
626 }
627
628 pa_sink_process_rewind(u->sink, amount);
629 pa_memblockq_rewind(u->input_q, nbytes);
630 }
631
632 /* Called from I/O thread context */
633 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
634 struct userdata *u;
635
636 pa_sink_input_assert_ref(i);
637 pa_assert_se(u = i->userdata);
638
639 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
640 return;
641
642 pa_memblockq_set_maxrewind(u->input_q, nbytes);
643 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
644 }
645
646 /* Called from I/O thread context */
647 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
648 struct userdata *u;
649
650 pa_sink_input_assert_ref(i);
651 pa_assert_se(u = i->userdata);
652
653 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
654 return;
655
656 size_t fs = pa_frame_size(&(u->sink->sample_spec));
657 //pa_sink_set_max_request_within_thread(u->sink, nbytes);
658 //pa_sink_set_max_request_within_thread(u->sink, u->R*fs);
659 pa_sink_set_max_request_within_thread(u->sink, ((nbytes+u->R*fs-1)/(u->R*fs))*(u->R*fs));
660 }
661
662 /* Called from I/O thread context */
663 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
664 struct userdata *u;
665
666 pa_sink_input_assert_ref(i);
667 pa_assert_se(u = i->userdata);
668
669 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
670 return;
671
672 //pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->latency*fs);
673 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->latency*fs );
674 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
675 }
676
677 /* Called from I/O thread context */
678 static void sink_input_detach_cb(pa_sink_input *i) {
679 struct userdata *u;
680
681 pa_sink_input_assert_ref(i);
682 pa_assert_se(u = i->userdata);
683
684 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
685 return;
686
687 pa_sink_detach_within_thread(u->sink);
688 pa_sink_set_asyncmsgq(u->sink, NULL);
689 pa_sink_set_rtpoll(u->sink, NULL);
690 }
691
692 /* Called from I/O thread context */
693 static void sink_input_attach_cb(pa_sink_input *i) {
694 struct userdata *u;
695
696 pa_sink_input_assert_ref(i);
697 pa_assert_se(u = i->userdata);
698
699 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
700 return;
701
702 pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
703 pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
704 pa_sink_attach_within_thread(u->sink);
705
706 //size_t fs = pa_frame_size(&(u->sink->sample_spec));
707 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->latency*fs);
708 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->master->thread_info.max_latency);
709 //TODO: setting this guy minimizes drop outs but doesn't get rid
710 //of them completely, figure out why
711 //pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->latency*fs);
712 //TODO: this guy causes dropouts constantly+rewinds, it's unusable
713 pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
714 }
715
716 /* Called from main context */
717 static void sink_input_kill_cb(pa_sink_input *i) {
718 struct userdata *u;
719
720 pa_sink_input_assert_ref(i);
721 pa_assert_se(u = i->userdata);
722
723 pa_sink_unlink(u->sink);
724 pa_sink_input_unlink(u->sink_input);
725
726 pa_sink_unref(u->sink);
727 u->sink = NULL;
728 pa_sink_input_unref(u->sink_input);
729 u->sink_input = NULL;
730
731 pa_module_unload_request(u->module, TRUE);
732 }
733
734 /* Called from IO thread context */
735 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
736 struct userdata *u;
737
738 pa_sink_input_assert_ref(i);
739 pa_assert_se(u = i->userdata);
740
741 /* If we are added for the first time, ask for a rewinding so that
742 * we are heard right-away. */
743 if (PA_SINK_INPUT_IS_LINKED(state) &&
744 i->thread_info.state == PA_SINK_INPUT_INIT) {
745 pa_log_debug("Requesting rewind due to state change.");
746 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
747 }
748 }
749
750 void save_profile(struct userdata *u, char *name){
751 float *H_n = pa_xmalloc((u->fft_size / 2 + 1) * sizeof(float));
752 const float *H = u->Hs[pa_aupdate_read_begin(u->a_H)];
753 for(size_t i = 0 ; i <= u->fft_size / 2 + 1; ++i){
754 //H_n[i] = H[i] * u->fft_size;
755 H_n[i] = H[i];
756 }
757 pa_aupdate_read_end(u->a_H);
758 pa_datum key, data;
759 key.data=name;
760 key.size = strlen(key.data);
761 data.data = H_n;
762 data.size = (u->fft_size / 2 + 1) * sizeof(float);
763 pa_database_set(u->database, &key, &data, TRUE);
764 pa_database_sync(u->database);
765 }
766
767 void save_state(struct userdata *u){
768 char *state_name = pa_sprintf_malloc("%s-previous-state", u->name);
769 save_profile(u, state_name);
770 pa_xfree(state_name);
771 }
772
773 void remove_profile(pa_core *c,char *name){
774 pa_datum key;
775 key.data = name;
776 key.size = strlen(key.data);
777 pa_database *database;
778 pa_assert_se(database = pa_shared_get(c,EQDB));
779 pa_database_unset(database,&key);
780 pa_database_sync(database);
781 }
782
783 const char* load_profile(struct userdata *u,char *name){
784 pa_datum key,value;
785 key.data = name;
786 key.size = strlen(key.data);
787 if(pa_database_get(u->database, &key, &value) != NULL){
788 if(value.size == (u->fft_size / 2 + 1) * sizeof(float)){
789 float *H=u->Hs[pa_aupdate_write_begin(u->a_H)];
790 memcpy(H, value.data, value.size);
791 pa_aupdate_write_swap(u->a_H);
792 pa_aupdate_write_end(u->a_H);
793 }else{
794 return "incompatible size";
795 }
796 pa_datum_free(&value);
797 }else{
798 return "profile doesn't exist";
799 }
800 return NULL;
801 //fix_filter(u->H, u->fft_size);
802 }
803 void load_state(struct userdata *u){
804 char *state_name=pa_sprintf_malloc("%s-previous-state", u->name);
805 load_profile(u,state_name);
806 pa_xfree(state_name);
807 }
808
809
810 /* Called from main context */
811 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
812 struct userdata *u;
813
814 pa_sink_input_assert_ref(i);
815 pa_assert_se(u = i->userdata);
816
817 return u->sink != dest;
818 }
819
820
821 //ensure's memory allocated is a multiple of v_size
822 //and aligned
823 static void * alloc(size_t x,size_t s){
824 size_t f = mround(x*s, sizeof(float)*v_size);
825 pa_assert_se(f >= x*s);
826 //printf("requested %ld floats=%ld bytes, rem=%ld\n", x, x*sizeof(float), x*sizeof(float)%16);
827 //printf("giving %ld floats=%ld bytes, rem=%ld\n", f, f*sizeof(float), f*sizeof(float)%16);
828 float *t = fftwf_malloc(f);
829 memset(t, 0, f);
830 return t;
831 }
832
833 int pa__init(pa_module*m) {
834 struct userdata *u;
835 pa_sample_spec ss;
836 pa_channel_map map;
837 pa_modargs *ma;
838 const char *z;
839 pa_sink *master;
840 pa_sink_input_new_data sink_input_data;
841 pa_sink_new_data sink_data;
842 pa_bool_t *use_default = NULL;
843 size_t fs;
844
845 pa_assert(m);
846
847 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
848 pa_log("Failed to parse module arguments.");
849 goto fail;
850 }
851
852 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
853 pa_log("Master sink not found");
854 goto fail;
855 }
856
857 ss = master->sample_spec;
858 ss.format = PA_SAMPLE_FLOAT32;
859 map = master->channel_map;
860 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
861 pa_log("Invalid sample format specification or channel map");
862 goto fail;
863 }
864 fs = pa_frame_size(&ss);
865
866 u = pa_xnew0(struct userdata, 1);
867 u->core = m->core;
868 u->module = m;
869 m->userdata = u;
870 u->master = master;
871 u->sink = NULL;
872 u->sink_input = NULL;
873
874 u->channels = ss.channels;
875 u->fft_size = pow(2, ceil(log(ss.rate)/log(2)));
876 pa_log("fft size: %ld", u->fft_size);
877 u->window_size = 15999;
878 u->R = (u->window_size+1)/2;
879 u->overlap_size = u->window_size-u->R;
880 u->target_samples = 1*u->R;
881 u->samples_gathered = 0;
882 u->max_output = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss)/pa_frame_size(&ss);
883 u->input_q = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, NULL);
884 u->a_H = pa_aupdate_new();
885 u->conv_buffer.memblock = pa_memblock_new(u->core->mempool, u->target_samples*fs);
886 u->latency = u->R;
887 for(size_t i = 0; i < 2; ++i){
888 u->Hs[i] = alloc((u->fft_size / 2 + 1), sizeof(float));
889 }
890 u->W = alloc(u->window_size, sizeof(float));
891 u->work_buffer = alloc(u->fft_size, sizeof(float));
892 memset(u->work_buffer, 0, u->fft_size*sizeof(float));
893 u->input = (float **)pa_xmalloc0(sizeof(float *)*u->channels);
894 u->overlap_accum = (float **)pa_xmalloc0(sizeof(float *)*u->channels);
895 for(size_t c = 0; c < u->channels; ++c){
896 u->input[c] = alloc(u->overlap_size+u->target_samples, sizeof(float));
897 pa_assert_se(u->input[c]);
898 memset(u->input[c], 0, (u->overlap_size+u->target_samples)*sizeof(float));
899 pa_assert_se(u->input[c]);
900 u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
901 pa_assert_se(u->overlap_accum[c]);
902 memset(u->overlap_accum[c], 0, u->overlap_size*sizeof(float));
903 }
904 u->output_window = alloc((u->fft_size / 2 + 1), sizeof(fftwf_complex));
905 u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
906 u->inverse_plan = fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE);
907
908 hanning_window(u->W, u->window_size);
909
910 /* Create sink */
911 pa_sink_new_data_init(&sink_data);
912 sink_data.driver = __FILE__;
913 sink_data.module = m;
914 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
915 sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name);
916 sink_data.namereg_fail = FALSE;
917 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
918 pa_sink_new_data_set_channel_map(&sink_data, &map);
919 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
920 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "FFT based equalizer");
921 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
922 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
923
924 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
925 pa_log("Invalid properties");
926 pa_sink_new_data_done(&sink_data);
927 goto fail;
928 }
929
930 u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY);
931 pa_sink_new_data_done(&sink_data);
932
933 if (!u->sink) {
934 pa_log("Failed to create sink.");
935 goto fail;
936 }
937 u->name=pa_xstrdup(u->sink->name);
938 u->sink->parent.process_msg = sink_process_msg;
939 u->sink->set_state = sink_set_state;
940 u->sink->update_requested_latency = sink_update_requested_latency;
941 u->sink->request_rewind = sink_request_rewind;
942 u->sink->userdata = u;
943
944 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
945 pa_sink_set_rtpoll(u->sink, master->rtpoll);
946 pa_sink_set_max_request(u->sink,
947 ((pa_sink_get_max_request(u->sink)+u->R*fs-1)/(u->R*fs))*(u->R*fs)
948 );
949 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
950
951 /* Create sink input */
952 pa_sink_input_new_data_init(&sink_input_data);
953 sink_input_data.driver = __FILE__;
954 sink_input_data.module = m;
955 sink_input_data.sink = u->master;
956 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
957 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
958 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
959 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
960
961 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, PA_SINK_INPUT_DONT_MOVE);
962 pa_sink_input_new_data_done(&sink_input_data);
963
964 if (!u->sink_input)
965 goto fail;
966
967 u->sink_input->pop = sink_input_pop_cb;
968 u->sink_input->process_rewind = sink_input_process_rewind_cb;
969 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
970 u->sink_input->update_max_request = sink_input_update_max_request_cb;
971 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
972 u->sink_input->kill = sink_input_kill_cb;
973 u->sink_input->attach = sink_input_attach_cb;
974 u->sink_input->detach = sink_input_detach_cb;
975 u->sink_input->state_change = sink_input_state_change_cb;
976 u->sink_input->may_move_to = sink_input_may_move_to_cb;
977 u->sink_input->userdata = u;
978
979 pa_sink_put(u->sink);
980 pa_sink_input_put(u->sink_input);
981
982 pa_modargs_free(ma);
983
984 pa_xfree(use_default);
985
986 dbus_init(u);
987
988 //default filter to these
989 for(size_t i = 0; i < u->fft_size / 2 + 1; ++i){
990 u->Hs[1][i]=u->Hs[0][i] = 1.0;
991 }
992 //load old parameters
993 load_state(u);
994
995 return 0;
996
997 fail:
998 if (ma)
999 pa_modargs_free(ma);
1000
1001 pa_xfree(use_default);
1002
1003 pa__done(m);
1004
1005 return -1;
1006 }
1007
1008 int pa__get_n_used(pa_module *m) {
1009 struct userdata *u;
1010
1011 pa_assert(m);
1012 pa_assert_se(u = m->userdata);
1013
1014 return pa_sink_linked_by(u->sink);
1015 }
1016
1017 void pa__done(pa_module*m) {
1018 struct userdata *u;
1019
1020 pa_assert(m);
1021
1022 if (!(u = m->userdata))
1023 return;
1024
1025 save_state(u);
1026
1027 dbus_done(u);
1028
1029 if (u->sink) {
1030 pa_sink_unlink(u->sink);
1031 pa_sink_unref(u->sink);
1032 }
1033
1034 if (u->sink_input) {
1035 pa_sink_input_unlink(u->sink_input);
1036 pa_sink_input_unref(u->sink_input);
1037 }
1038
1039 pa_aupdate_free(u->a_H);
1040 pa_memblock_unref(u->conv_buffer.memblock);
1041 pa_memblockq_free(u->input_q);
1042
1043 fftwf_destroy_plan(u->inverse_plan);
1044 fftwf_destroy_plan(u->forward_plan);
1045 pa_xfree(u->output_window);
1046 for(size_t c=0; c < u->channels; ++c){
1047 pa_xfree(u->overlap_accum[c]);
1048 pa_xfree(u->input[c]);
1049 }
1050 pa_xfree(u->overlap_accum);
1051 pa_xfree(u->input);
1052 pa_xfree(u->work_buffer);
1053 pa_xfree(u->W);
1054 for(size_t i = 0; i < 2; ++i){
1055 pa_xfree(u->Hs[i]);
1056 }
1057
1058 pa_xfree(u->name);
1059
1060 pa_xfree(u);
1061 }
1062
1063 enum manager_method_index {
1064 MANAGER_METHOD_REMOVE_PROFILE,
1065 MANAGER_METHOD_MAX
1066 };
1067
1068 pa_dbus_arg_info remove_profile_args[]={
1069 {"name", "s","in"},
1070 };
1071
1072 static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={
1073 [MANAGER_METHOD_REMOVE_PROFILE]{
1074 .method_name="RemoveProfile",
1075 .arguments=remove_profile_args,
1076 .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info),
1077 .receive_cb=manager_handle_remove_profile}
1078 };
1079
1080 enum manager_handler_index {
1081 MANAGER_HANDLER_REVISION,
1082 MANAGER_HANDLER_EQUALIZED_SINKS,
1083 MANAGER_HANDLER_PROFILES,
1084 MANAGER_HANDLER_MAX
1085 };
1086
1087 static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={
1088 [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL},
1089 [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL},
1090 [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL}
1091 };
1092
1093 static pa_dbus_interface_info manager_info={
1094 .name=EXTNAME ".Manager",
1095 .method_handlers=manager_methods,
1096 .n_method_handlers=MANAGER_METHOD_MAX,
1097 .property_handlers=manager_handlers,
1098 .n_property_handlers=MANAGER_HANDLER_MAX,
1099 .get_all_properties_cb=manager_get_all,
1100 .signals=NULL,
1101 .n_signals=0
1102 };
1103
1104
1105 enum equalizer_method_index {
1106 EQUALIZER_METHOD_FILTER_POINTS,
1107 EQUALIZER_METHOD_SEED_FILTER,
1108 EQUALIZER_METHOD_SAVE_PROFILE,
1109 EQUALIZER_METHOD_LOAD_PROFILE,
1110 EQUALIZER_METHOD_SET_FILTER,
1111 EQUALIZER_METHOD_GET_FILTER,
1112 EQUALIZER_METHOD_MAX
1113 };
1114
1115 enum equalizer_handler_index {
1116 EQUALIZER_HANDLER_REVISION,
1117 EQUALIZER_HANDLER_SAMPLERATE,
1118 EQUALIZER_HANDLER_FILTERSAMPLERATE,
1119 EQUALIZER_HANDLER_N_COEFS,
1120 EQUALIZER_HANDLER_MAX
1121 };
1122
1123 pa_dbus_arg_info filter_points_args[]={
1124 {"xs", "au","in"},
1125 {"ys", "ad","out"},
1126 };
1127 pa_dbus_arg_info seed_filter_args[]={
1128 {"xs", "au","in"},
1129 {"ys", "ad","in"},
1130 };
1131 pa_dbus_arg_info save_profile_args[]={
1132 {"name", "s","in"},
1133 };
1134 pa_dbus_arg_info load_profile_args[]={
1135 {"name", "s","in"},
1136 };
1137 pa_dbus_arg_info set_filter_args[]={
1138 {"coefficients", "ad","in"},
1139 };
1140 pa_dbus_arg_info get_filter_args[]={
1141 {"coefficients", "ad","out"},
1142 };
1143
1144 static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={
1145 [EQUALIZER_METHOD_SEED_FILTER]{
1146 .method_name="SeedFilter",
1147 .arguments=seed_filter_args,
1148 .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info),
1149 .receive_cb=equalizer_handle_seed_filter},
1150 [EQUALIZER_METHOD_FILTER_POINTS]{
1151 .method_name="FilterAtPoints",
1152 .arguments=filter_points_args,
1153 .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info),
1154 .receive_cb=equalizer_handle_get_filter_points},
1155 [EQUALIZER_METHOD_SAVE_PROFILE]{
1156 .method_name="SaveProfile",
1157 .arguments=save_profile_args,
1158 .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info),
1159 .receive_cb=equalizer_handle_save_profile},
1160 [EQUALIZER_METHOD_LOAD_PROFILE]{
1161 .method_name="LoadProfile",
1162 .arguments=load_profile_args,
1163 .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info),
1164 .receive_cb=equalizer_handle_load_profile},
1165 [EQUALIZER_METHOD_SET_FILTER]{
1166 .method_name="SetFilterCoefficients",
1167 .arguments=set_filter_args,
1168 .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info),
1169 .receive_cb=equalizer_set_filter},
1170 [EQUALIZER_METHOD_GET_FILTER]{
1171 .method_name="GetFilterCoefficients",
1172 .arguments=get_filter_args,
1173 .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info),
1174 .receive_cb=equalizer_get_filter}
1175 };
1176
1177 static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={
1178 [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL},
1179 [EQUALIZER_HANDLER_SAMPLERATE]{.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL},
1180 [EQUALIZER_HANDLER_FILTERSAMPLERATE]{.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL},
1181 [EQUALIZER_HANDLER_N_COEFS]{.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL},
1182 };
1183
1184 //static pa_dbus_arg_info new_equalizer_args[] = { { "path","o",NULL} };
1185 //static pa_dbus_signal_info signals[SIGNAL_MAX] = {
1186 // [SIGNAL_NEW_EQUALIZER]={.name="NewEqualizer",.arguments=new_equalizer_args,.n_arguments=1}
1187 //};
1188
1189 static pa_dbus_interface_info equalizer_info={
1190 .name=EXTNAME ".Equalizer",
1191 .method_handlers=equalizer_methods,
1192 .n_method_handlers=EQUALIZER_METHOD_MAX,
1193 .property_handlers=equalizer_handlers,
1194 .n_property_handlers=EQUALIZER_HANDLER_MAX,
1195 .get_all_properties_cb=equalizer_get_all,
1196 .signals=NULL,
1197 .n_signals=0
1198 };
1199
1200 void dbus_init(struct userdata *u){
1201 u->dbus_protocol=pa_dbus_protocol_get(u->core);
1202 u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
1203
1204 pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u);
1205 pa_idxset *sink_list=pa_shared_get(u->core,SINKLIST);
1206 u->database=pa_shared_get(u->core,EQDB);
1207 if(sink_list==NULL){
1208 sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
1209 pa_shared_set(u->core, SINKLIST, sink_list);
1210 char *dbname;
1211 pa_assert_se(dbname = pa_state_path("equalizers", TRUE));
1212 pa_assert_se(u->database = pa_database_open(dbname, TRUE));
1213 pa_xfree(dbname);
1214 pa_shared_set(u->core,EQDB,u->database);
1215 pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->core);
1216 pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
1217 }
1218 uint32_t dummy;
1219 pa_idxset_put(sink_list,u,&dummy);
1220 }
1221
1222 void dbus_done(struct userdata *u){
1223 pa_idxset *sink_list;
1224 uint32_t dummy;
1225
1226 pa_assert_se(sink_list=pa_shared_get(u->core,SINKLIST));
1227 pa_idxset_remove_by_data(sink_list,u,&dummy);
1228 if(pa_idxset_size(sink_list)==0){
1229 pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
1230 pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name);
1231 pa_shared_remove(u->core, EQDB);
1232 pa_database_close(u->database);
1233 pa_shared_remove(u->core, SINKLIST);
1234 pa_xfree(sink_list);
1235 }
1236 pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name);
1237 pa_xfree(u->dbus_path);
1238 pa_dbus_protocol_unref(u->dbus_protocol);
1239 }
1240
1241 void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1242 DBusError error;
1243 pa_core *c = (pa_core *)_u;
1244 pa_assert(conn);
1245 pa_assert(msg);
1246 pa_assert(c);
1247 dbus_error_init(&error);
1248 char *name;
1249 if(!dbus_message_get_args(msg, &error,
1250 DBUS_TYPE_STRING, &name,
1251 DBUS_TYPE_INVALID)){
1252 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1253 dbus_error_free(&error);
1254 return;
1255 }
1256 remove_profile(c,name);
1257 pa_dbus_send_empty_reply(conn, msg);
1258 }
1259
1260 void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
1261 uint32_t rev=1;
1262 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1263 }
1264
1265 void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u){
1266 pa_assert(conn);
1267 pa_assert(msg);
1268 pa_assert(_u);
1269
1270 pa_core *c = (pa_core *)_u;
1271 pa_idxset *sink_list;
1272 uint32_t dummy;
1273
1274 pa_assert_se(sink_list = pa_shared_get(c, SINKLIST));
1275 unsigned n_sinks = (unsigned) pa_idxset_size(sink_list);
1276 char **names = NULL;
1277 void *iter = NULL;
1278 struct userdata *sink_u = NULL;
1279 pa_assert_se(names = pa_xnew0(char *,n_sinks));
1280 for(uint32_t i = 0; i < n_sinks; ++i){
1281 sink_u=(struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1282 names[i] = sink_u->dbus_path;
1283 }
1284 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n_sinks);
1285 pa_xfree(names);
1286 }
1287
1288 void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u){
1289 pa_assert(conn);
1290 pa_assert(msg);
1291 pa_assert(_u);
1292
1293 pa_core *core=_u;
1294 DBusMessage *reply = NULL;
1295 DBusMessageIter msg_iter, array_iter;
1296
1297 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1298 dbus_message_iter_init_append(reply, &msg_iter);
1299 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "s", &array_iter));
1300
1301 char *name;
1302 pa_datum key,next_key;
1303 int done;
1304 pa_database *database;
1305 pa_assert_se(database=pa_shared_get(core, EQDB));
1306 done = !pa_database_first(database, &key, NULL);
1307
1308 while(!done){
1309 done = !pa_database_next(database, &key, &next_key, NULL);
1310 name=pa_xmalloc(key.size + 1);
1311 memcpy(name, key.data, key.size);
1312 name[key.size] = '\0';
1313 pa_datum_free(&key);
1314 dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &name);
1315 pa_xfree(name);
1316 key = next_key;
1317 }
1318 dbus_message_iter_close_container(&msg_iter, &array_iter);
1319 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1320 dbus_message_unref(reply);
1321 }
1322
1323 void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
1324 pa_assert(conn);
1325 pa_assert(msg);
1326 pa_assert(_u);
1327
1328 pa_core *u=(pa_core *) _u;
1329 DBusMessage *reply = NULL;
1330 DBusMessageIter msg_iter, dict_iter, sub_iter, array_iter;
1331 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1332 dbus_message_iter_init_append(reply, &msg_iter);
1333 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1334
1335 uint32_t rev=1;
1336 pa_idxset *sink_list;
1337 pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1338
1339 pa_assert_se(sink_list = pa_shared_get(u, SINKLIST));
1340 unsigned n_sinks = (unsigned) pa_idxset_size(sink_list);
1341 char **names = NULL;
1342 void *iter = NULL;
1343 struct userdata *sink_u = NULL;
1344 pa_assert_se(names = pa_xnew0(char *,n_sinks));
1345 for(uint32_t i = 0; i < n_sinks; ++i){
1346 unsigned dummy;
1347 sink_u=(struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1348 names[i] = sink_u->dbus_path;
1349 }
1350 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n_sinks);
1351 pa_xfree(names);
1352
1353 pa_database *database;
1354 pa_assert_se(database=pa_shared_get(u, EQDB));
1355
1356 pa_datum key,next_key;
1357 char *profile_name;
1358 int done;
1359 done = !pa_database_first(database, &key, NULL);
1360 dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub_iter);
1361 dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, &manager_handlers[MANAGER_HANDLER_PROFILES].property_name);
1362
1363 dbus_message_iter_open_container(&sub_iter, DBUS_TYPE_ARRAY, "s", &array_iter);
1364 while(!done){
1365 done = !pa_database_next(database, &key, &next_key, NULL);
1366 profile_name=pa_xmalloc(key.size + 1);
1367 memcpy(profile_name, key.data, key.size);
1368 profile_name[key.size] = '\0';
1369 pa_datum_free(&key);
1370 dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &profile_name);
1371 pa_xfree(profile_name);
1372 key = next_key;
1373 }
1374 pa_assert_se(dbus_message_iter_close_container(&sub_iter, &array_iter));
1375 pa_assert_se(dbus_message_iter_close_container(&dict_iter, &sub_iter));
1376 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1377 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1378 dbus_message_unref(reply);
1379 }
1380
1381 void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1382 struct userdata *u=(struct userdata *) _u;
1383 DBusError error;
1384
1385 pa_assert(conn);
1386 pa_assert(msg);
1387 pa_assert(u);
1388 float *ys;
1389 uint32_t *xs;
1390 double *_ys;
1391 unsigned x_npoints,y_npoints;
1392
1393 dbus_error_init(&error);
1394
1395 if(!dbus_message_get_args(msg, &error,
1396 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1397 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints,
1398 DBUS_TYPE_INVALID)){
1399 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1400 dbus_error_free(&error);
1401 return;
1402 }
1403 int points_good=1;
1404 for(size_t i = 0; i < x_npoints; ++i){
1405 if(xs[i] >= u->fft_size / 2 + 1){
1406 points_good=0;
1407 break;
1408 }
1409 }
1410 if(!is_monotonic(xs,x_npoints) || !points_good){
1411 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<x<%ld", u->fft_size / 2);
1412 dbus_error_free(&error);
1413 return;
1414
1415 }
1416 else if(x_npoints != y_npoints || x_npoints < 2 || x_npoints > u->fft_size / 2 +1 ){
1417 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs and ys must be the same length and 2<=l<=%ld!", u->fft_size / 2 + 1);
1418 dbus_error_free(&error);
1419 return;
1420 }
1421
1422 ys = pa_xmalloc(x_npoints * sizeof(float));
1423 for(uint32_t i = 0; i < x_npoints; ++i){
1424 ys[i] = (float) _ys[i];
1425 }
1426
1427 float *H = u->Hs[pa_aupdate_write_begin(u->a_H)];
1428 interpolate(H, u->fft_size / 2 + 1, xs, ys, x_npoints);
1429 fix_filter(H, u->fft_size);
1430 pa_aupdate_write_swap(u->a_H);
1431 pa_aupdate_write_end(u->a_H);
1432 pa_xfree(ys);
1433
1434 //Stupid for IO reasons? Add a save signal to dbus instead
1435 //save_state(u);
1436
1437 pa_dbus_send_empty_reply(conn, msg);
1438 }
1439
1440 void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) {
1441 struct userdata *u=(struct userdata *) _u;
1442 DBusError error;
1443
1444 pa_assert(conn);
1445 pa_assert(msg);
1446 pa_assert(u);
1447 uint32_t *xs;
1448 double *ys;
1449 unsigned x_npoints;
1450
1451 dbus_error_init(&error);
1452
1453 if(!dbus_message_get_args(msg, &error,
1454 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1455 DBUS_TYPE_INVALID)){
1456 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1457 dbus_error_free(&error);
1458 return;
1459 }
1460 int points_good=1;
1461 for(size_t i = 0; i < x_npoints; ++i){
1462 if(xs[i] >= u->fft_size / 2 + 1){
1463 points_good=0;
1464 break;
1465 }
1466 }
1467
1468 if(x_npoints > u->fft_size / 2 +1 || !points_good){
1469 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %ld!", u->fft_size / 2 + 1);
1470 dbus_error_free(&error);
1471 return;
1472 }
1473
1474 ys = pa_xmalloc(x_npoints * sizeof(double));
1475 float *H = u->Hs[pa_aupdate_read_begin(u->a_H)];
1476 for(uint32_t i = 0; i < x_npoints; ++i){
1477 ys[i] = H[xs[i]] * u->fft_size;
1478 }
1479 pa_aupdate_read_end(u->a_H);
1480
1481 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_DOUBLE, ys, x_npoints);
1482 pa_xfree(ys);
1483 }
1484
1485 void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1486 struct userdata *u=(struct userdata *) _u;
1487 DBusError error;
1488 pa_assert(conn);
1489 pa_assert(msg);
1490 pa_assert(u);
1491 dbus_error_init(&error);
1492 char *name;
1493
1494 if(!dbus_message_get_args(msg, &error,
1495 DBUS_TYPE_STRING, &name,
1496 DBUS_TYPE_INVALID)){
1497 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1498 dbus_error_free(&error);
1499 return;
1500 }
1501 save_profile(u,name);
1502 pa_dbus_send_empty_reply(conn, msg);
1503 }
1504
1505 void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1506 struct userdata *u=(struct userdata *) _u;
1507 DBusError error;
1508
1509 pa_assert(conn);
1510 pa_assert(msg);
1511 pa_assert(u);
1512 dbus_error_init(&error);
1513 char *name;
1514
1515 if(!dbus_message_get_args(msg, &error,
1516 DBUS_TYPE_STRING, &name,
1517 DBUS_TYPE_INVALID)){
1518 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1519 dbus_error_free(&error);
1520 return;
1521 }
1522 const char *err_msg=load_profile(u,name);
1523 if(err_msg!=NULL){
1524 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name,err_msg);
1525 dbus_error_free(&error);
1526 return;
1527 }
1528 pa_dbus_send_empty_reply(conn, msg);
1529 }
1530
1531 void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
1532 uint32_t rev=1;
1533 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1534 }
1535
1536 void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){
1537 pa_assert(conn);
1538 pa_assert(msg);
1539 pa_assert(_u);
1540
1541 struct userdata *u=(struct userdata *)_u;
1542
1543 uint32_t n_coefs=(uint32_t)(u->fft_size / 2 + 1);
1544 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
1545 }
1546
1547 void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
1548 pa_assert(conn);
1549 pa_assert(msg);
1550 pa_assert(_u);
1551
1552 struct userdata *u=(struct userdata *) _u;
1553 uint32_t rate=(uint32_t) u->sink->sample_spec.rate;
1554 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate);
1555 }
1556
1557 void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
1558 pa_assert(conn);
1559 pa_assert(msg);
1560 pa_assert(_u);
1561
1562 struct userdata *u=(struct userdata *) _u;
1563 uint32_t fft_size=(uint32_t) u->fft_size;
1564 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size);
1565 }
1566
1567 void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
1568 pa_assert(conn);
1569 pa_assert(msg);
1570 pa_assert(_u);
1571
1572 struct userdata *u=(struct userdata *) _u;
1573 DBusMessage *reply = NULL;
1574 DBusMessageIter msg_iter, dict_iter;
1575 uint32_t rev=1;
1576 uint32_t n_coefs=(uint32_t)(u->fft_size / 2 + 1);
1577 uint32_t rate=(uint32_t) u->sink->sample_spec.rate;
1578 uint32_t fft_size=(uint32_t) u->fft_size;
1579
1580 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1581 dbus_message_iter_init_append(reply, &msg_iter);
1582 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1583
1584 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1585 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate);
1586 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size);
1587 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
1588
1589 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1590 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1591 dbus_message_unref(reply);
1592 }
1593
1594 void equalizer_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1595 pa_assert(conn);
1596 pa_assert(msg);
1597 pa_assert(_u);
1598
1599 struct userdata *u = (struct userdata *)_u;
1600
1601 unsigned n_coefs = (unsigned) (u->fft_size / 2 + 1);
1602 double *H_ = (double *) pa_xmalloc0(n_coefs * sizeof(double));
1603
1604 float *H=u->Hs[pa_aupdate_read_begin(u->a_H)];
1605 for(size_t i = 0;i < u->fft_size / 2 + 1; ++i){
1606 H_[i] = H[i] * u->fft_size;
1607 }
1608 pa_aupdate_read_end(u->a_H);
1609 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_DOUBLE, H_, n_coefs);
1610 pa_xfree(H_);
1611 }
1612
1613 void equalizer_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1614 pa_assert(conn);
1615 pa_assert(msg);
1616 pa_assert(_u);
1617
1618 struct userdata *u=(struct userdata *)_u;
1619 double *H_;
1620 unsigned _n_coefs;
1621 if(pa_dbus_get_fixed_array_set_property_arg(conn, msg, DBUS_TYPE_DOUBLE, &H_, &_n_coefs)){
1622 return;
1623 }
1624 if(_n_coefs!=u->fft_size / 2 + 1){
1625 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", u->fft_size / 2 + 1, _n_coefs);
1626 return;
1627 }
1628 float *H = u->Hs[pa_aupdate_write_begin(u->a_H)];
1629 for(size_t i = 0; i < u->fft_size / 2 + 1; ++i){
1630 H[i] = (float) H_[i];
1631 }
1632 fix_filter(H, u->fft_size);
1633 pa_aupdate_write_swap(u->a_H);
1634 pa_aupdate_write_end(u->a_H);
1635
1636 //Stupid for IO reasons? Add a save signal to dbus instead
1637 //save_state(u);
1638
1639 pa_dbus_send_empty_reply(conn, msg);
1640 }