]> code.delx.au - pulseaudio/blob - src/modules/module-equalizer-sink.c
module-equalizer-sink: added more assertions to aid in debugging
[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 <stdio.h>
33 #include <math.h>
34 #include <fftw3.h>
35 #include <float.h>
36
37
38 #include <pulse/xmalloc.h>
39 #include <pulse/i18n.h>
40
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/namereg.h>
43 #include <pulsecore/sink.h>
44 #include <pulsecore/module.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/modargs.h>
47 #include <pulsecore/log.h>
48 #include <pulsecore/thread.h>
49 #include <pulsecore/thread-mq.h>
50 #include <pulsecore/rtpoll.h>
51 #include <pulsecore/sample-util.h>
52 #include <pulsecore/ltdl-helper.h>
53
54 #include <stdint.h>
55 #include <time.h>
56
57
58 #include "module-equalizer-sink-symdef.h"
59
60 PA_MODULE_AUTHOR("Jason Newton");
61 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
62 PA_MODULE_VERSION(PACKAGE_VERSION);
63 PA_MODULE_LOAD_ONCE(FALSE);
64 PA_MODULE_USAGE(_("sink=<sink to connect to> "));
65
66 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
67
68 struct userdata {
69 pa_core *core;
70 pa_module *module;
71 pa_sink *sink, *master;
72 pa_sink_input *sink_input;
73
74 size_t channels;
75 size_t fft_size;//length (res) of fft
76 size_t window_size;/*
77 *sliding window size
78 *effectively chooses R
79 */
80 size_t R;/* the hop size between overlapping windows
81 * the latency of the filter, calculated from window_size
82 * based on constraints of COLA and window function
83 */
84 size_t samples_gathered;
85 size_t n_buffered_output;
86 size_t max_output;
87 float *H;//frequency response filter (magnitude based)
88 float *W;//windowing function (time domain)
89 float *work_buffer,**input,**overlap_accum,**output_buffer;
90 fftwf_complex *output_window;
91 fftwf_plan forward_plan,inverse_plan;
92 //size_t samplings;
93
94 pa_memblockq *memblockq;
95 };
96
97 static const char* const valid_modargs[] = {
98 "sink_name",
99 "sink_properties",
100 "master",
101 "format",
102 "rate",
103 "channels",
104 "channel_map",
105 NULL
106 };
107
108 uint64_t time_diff(struct timespec *timeA_p, struct timespec *timeB_p)
109 {
110 return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
111 ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
112 }
113
114 void hanning_normalized_window(float *W,size_t window_size){
115 //h = sqrt(2)/2 * (1+cos(t*pi)) ./ sqrt( 1+cos(t*pi).^2 )
116 float c;
117 for(size_t i=0;i<window_size;++i){
118 c=cos(M_PI*i/(window_size-1));
119 W[i]=sqrt(2.0)/2.0*(1.0+c) / sqrt(1.0+c*c);
120 }
121 }
122 void hanning_window(float *W,size_t window_size){
123 //h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2
124 for(size_t i=0;i<window_size;++i){
125 W[i]=.5*(1-cos(2*M_PI*i/(window_size+1)));
126 }
127 }
128 void hamming_window(float *W,size_t window_size){
129 //h=.54-.46*cos(2*pi*j/(window_size-1))
130 //COLA for R=(M-1)/2,(M-1)/4 etc when endpoints are divided by 2
131 //or one endpoint is zeroed
132 float m;
133 for(size_t i=0;i<window_size;++i){
134 m=i;
135 m/=(window_size-1);
136 W[i]=.54-.46*cos(2*M_PI*m);
137 }
138 W[window_size-1]=0;
139 //W[0]/=2;
140 //W[window_size-1]/=2;
141 }
142 void blackman_window(float *W,size_t window_size){
143 //h=.42-.5*cos(2*pi*m)+.08*cos(4*pi*m), m=(0:W-1)/(W-1)
144 //COLA for R=(M-1)/3 when M is odd and R is an integer
145 //R=M/3 when M is even and R is an integer
146 float m;
147 for(size_t i=0;i<window_size;++i){
148 m=i;
149 m/=(window_size-1);
150 W[i]=.42-.5*cos(2*M_PI*m)+.08*cos(4*M_PI*m);
151 }
152 }
153
154
155 void sin_window(float *W,size_t window_size){
156 //h = (cos(t*pi)+1)/2 .* float(abs(t)<1);
157 for(size_t i=0;i<window_size;++i){
158 W[i]=sin(M_PI*i/(window_size-1));
159 }
160 }
161
162
163 void array_out(const char *name,float *a,size_t length){
164 FILE *p=fopen(name,"w");
165 if(!p){
166 pa_log("opening %s failed!",name);
167 return;
168 }
169 for(size_t i=0;i<length;++i){
170 fprintf(p,"%e,",a[i]);
171 //if(i%1000==0){
172 // fprintf(p,"\n");
173 //}
174 }
175 fprintf(p,"\n");
176 fclose(p);
177 }
178
179
180 /* Called from I/O thread context */
181 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
182 struct userdata *u = PA_SINK(o)->userdata;
183
184 switch (code) {
185
186 case PA_SINK_MESSAGE_GET_LATENCY: {
187 pa_usec_t usec = 0;
188 pa_sample_spec *ss=&u->sink->sample_spec;
189
190 /* Get the latency of the master sink */
191 if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
192 usec = 0;
193
194 usec+=pa_bytes_to_usec(u->n_buffered_output*pa_frame_size(ss),ss);
195 /* Add the latency internal to our sink input on top */
196 usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
197 *((pa_usec_t*) data) = usec;
198 return 0;
199 }
200 }
201
202 return pa_sink_process_msg(o, code, data, offset, chunk);
203 }
204
205
206 /* Called from main context */
207 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
208 struct userdata *u;
209
210 pa_sink_assert_ref(s);
211 pa_assert_se(u = s->userdata);
212
213 if (PA_SINK_IS_LINKED(state) &&
214 u->sink_input &&
215 PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
216
217 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
218
219 return 0;
220 }
221
222 /* Called from I/O thread context */
223 static void sink_request_rewind(pa_sink *s) {
224 struct userdata *u;
225
226 pa_sink_assert_ref(s);
227 pa_assert_se(u = s->userdata);
228
229 /* Just hand this one over to the master sink */
230 pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq), TRUE, FALSE, FALSE);
231 }
232
233 /* Called from I/O thread context */
234 static void sink_update_requested_latency(pa_sink *s) {
235 struct userdata *u;
236
237 pa_sink_assert_ref(s);
238 pa_assert_se(u = s->userdata);
239
240 /* Just hand this one over to the master sink */
241 pa_sink_input_set_requested_latency_within_thread(
242 u->sink_input,
243 pa_sink_get_requested_latency_within_thread(s));
244 }
245
246 /* Called from I/O thread context */
247 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
248 struct userdata *u;
249 float *src, *dst;
250 pa_memchunk tchunk;
251 pa_sink_input_assert_ref(i);
252 pa_assert(chunk);
253 pa_assert_se(u = i->userdata);
254 pa_assert_se(u->sink);
255 size_t fs = pa_frame_size(&(u->sink->sample_spec));
256 size_t ss=pa_sample_size(&(u->sink->sample_spec));
257 size_t fe = fs/ss;
258
259 if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
260 return -1;
261
262 //output any buffered outputs first
263 if(u->n_buffered_output>0){
264 //pa_log("outputing %ld buffered samples",u->n_buffered_output);
265 chunk->index = 0;
266 size_t n_outputable=PA_MIN(u->n_buffered_output,u->max_output);
267 chunk->length = n_outputable*fs;
268 chunk->memblock = pa_memblock_new(i->sink->core->mempool, chunk->length);
269 pa_memblockq_drop(u->memblockq, chunk->length);
270 dst = (float*) pa_memblock_acquire(chunk->memblock);
271 for(size_t j=0;j<u->channels;++j){
272 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst+j, fs, u->output_buffer[j], sizeof(float),n_outputable);
273 memmove(u->output_buffer[j],u->output_buffer[j]+n_outputable,(u->n_buffered_output-n_outputable)*sizeof(float));
274 }
275 u->n_buffered_output-=n_outputable;
276 pa_memblock_release(chunk->memblock);
277 return 0;
278 }
279 pa_assert_se(u->n_buffered_output==0);
280
281 //collect the minimum number of samples
282 //TODO figure out a better way of buffering the needed
283 //number of samples, this doesn't seem to work correctly
284 while(u->samples_gathered < u->R){
285 //render some new fragments to our memblockq
286 size_t desired_samples=PA_MIN(u->R-u->samples_gathered,u->max_output);
287 while (pa_memblockq_peek(u->memblockq, &tchunk) < 0) {
288 pa_memchunk nchunk;
289
290 pa_sink_render(u->sink, desired_samples*fs, &nchunk);
291 pa_memblockq_push(u->memblockq, &nchunk);
292 pa_memblock_unref(nchunk.memblock);
293 }
294 if(tchunk.length/fs!=desired_samples){
295 pa_log("got %ld samples, asked for %ld",tchunk.length/fs,desired_samples);
296 }
297 size_t n_samples=PA_MIN(tchunk.length/fs,u->R-u->samples_gathered);
298 //TODO: figure out what to do with rest of the samples when there's too many (rare?)
299 src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index);
300 for (size_t c=0;c<u->channels;c++) {
301 pa_sample_clamp(PA_SAMPLE_FLOAT32NE,u->input[c]+(u->window_size-u->R)+u->samples_gathered,sizeof(float), src+c, fs, n_samples);
302 }
303 u->samples_gathered+=n_samples;
304 pa_memblock_release(tchunk.memblock);
305 pa_memblock_unref(tchunk.memblock);
306 }
307 //IT should be this guy if we're buffering like how its supposed to
308 //size_t n_outputable=PA_MIN(u->window_size-u->R,u->max_output);
309 //This one takes into account the actual data gathered but then the dsp
310 //stuff is wrong when the buffer "underruns"
311 size_t n_outputable=PA_MIN(u->R,u->max_output);
312
313
314 chunk->index=0;
315 chunk->length=n_outputable*fs;
316 chunk->memblock = pa_memblock_new(i->sink->core->mempool, chunk->length);
317 pa_memblockq_drop(u->memblockq, chunk->length);
318 dst = (float*) pa_memblock_acquire(chunk->memblock);
319
320 pa_assert_se(u->fft_size>=u->window_size);
321 pa_assert_se(u->R<u->window_size);
322 pa_assert_se(u->samples_gathered>=u->R);
323 size_t sample_rem=u->R-n_outputable;
324 //use a linear-phase sliding STFT and overlap-add method (for each channel)
325 for (size_t c=0;c<u->channels;c++) {
326 ////zero padd the data
327 //memset(u->work_buffer,0,u->fft_size*sizeof(float));
328 memset(u->work_buffer+u->window_size,0,(u->fft_size-u->window_size)*sizeof(float));
329 ////window the data
330 for(size_t j=0;j<u->window_size;++j){
331 u->work_buffer[j]=u->W[j]*u->input[c][j];
332 }
333 //Processing is done here!
334 //do fft
335 //char fname[1024];
336 //if(u->samplings==200){
337 // pa_assert_se(0);
338 //}
339
340 //this iterations input
341 //sprintf(fname,"/home/jason/input%ld-%ld.txt",u->samplings+1,c);
342 //array_out(fname,u->input[c]+(u->window_size-u->R),u->R);
343
344 fftwf_execute_dft_r2c(u->forward_plan,u->work_buffer,u->output_window);
345 //perform filtering
346 for(size_t j=0;j<u->fft_size/2+1;++j){
347 u->output_window[j][0]*=u->H[j];
348 u->output_window[j][1]*=u->H[j];
349 }
350 ////inverse fft
351 fftwf_execute_dft_c2r(u->inverse_plan,u->output_window,u->work_buffer);
352 //the output for the previous iteration's input
353 //sprintf(fname,"/home/jason/output%ld-%ld.txt",u->samplings,c);
354 //array_out(fname,u->work_buffer,u->window_size);
355
356
357 ////debug: tests overlaping add
358 ////and negates ALL PREVIOUS processing
359 ////yields a perfect reconstruction if COLA is held
360 //for(size_t j=0;j<u->window_size;++j){
361 // u->work_buffer[j]=u->W[j]*u->input[c][j];
362 //}
363
364 //overlap add and preserve overlap component from this window (linear phase)
365 for(size_t j=0;j<u->R;++j){
366 u->work_buffer[j]+=u->overlap_accum[c][j];
367 u->overlap_accum[c][j]=u->work_buffer[u->window_size-u->R+j];
368 }
369
370
371 /*
372 //debug: tests if basic buffering works
373 //shouldn't modify the signal AT ALL
374 for(size_t j=0;j<u->window_size;++j){
375 u->work_buffer[j]=u->input[c][j];
376 }
377 */
378
379 //preseve the needed input for the next windows overlap
380 memmove(u->input[c],u->input[c]+u->R,
381 (u->window_size-u->R)*sizeof(float)
382 );
383 //output the samples that are outputable now
384 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst+c, fs, u->work_buffer, sizeof(float),n_outputable);
385 //buffer the rest of them
386 memcpy(u->output_buffer[c]+u->n_buffered_output,u->work_buffer+n_outputable,sample_rem*sizeof(float));
387
388 }
389 //u->samplings++;
390 u->n_buffered_output+=sample_rem;
391 u->samples_gathered=0;
392 pa_memblock_release(chunk->memblock);
393 return 0;
394 }
395
396 /* Called from I/O thread context */
397 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
398 struct userdata *u;
399 size_t amount = 0;
400
401 pa_sink_input_assert_ref(i);
402 pa_assert_se(u = i->userdata);
403
404 if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
405 return;
406
407 if (u->sink->thread_info.rewind_nbytes > 0) {
408 size_t max_rewrite;
409
410 max_rewrite = nbytes + pa_memblockq_get_length(u->memblockq);
411 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
412 u->sink->thread_info.rewind_nbytes = 0;
413
414 if (amount > 0) {
415 pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
416 pa_log_debug("Resetting equalizer");
417 u->n_buffered_output=0;
418 u->samples_gathered=0;
419 }
420 }
421
422 pa_sink_process_rewind(u->sink, amount);
423 pa_memblockq_rewind(u->memblockq, nbytes);
424 }
425
426 /* Called from I/O thread context */
427 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
428 struct userdata *u;
429
430 pa_sink_input_assert_ref(i);
431 pa_assert_se(u = i->userdata);
432
433 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
434 return;
435
436 pa_memblockq_set_maxrewind(u->memblockq, nbytes);
437 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
438 }
439
440 /* Called from I/O thread context */
441 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
442 struct userdata *u;
443
444 pa_sink_input_assert_ref(i);
445 pa_assert_se(u = i->userdata);
446
447 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
448 return;
449
450 pa_sink_set_max_request_within_thread(u->sink, nbytes);
451 }
452
453 /* Called from I/O thread context */
454 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
455 struct userdata *u;
456
457 pa_sink_input_assert_ref(i);
458 pa_assert_se(u = i->userdata);
459
460 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
461 return;
462
463 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
464 }
465
466 /* Called from I/O thread context */
467 static void sink_input_detach_cb(pa_sink_input *i) {
468 struct userdata *u;
469
470 pa_sink_input_assert_ref(i);
471 pa_assert_se(u = i->userdata);
472
473 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
474 return;
475
476 pa_sink_detach_within_thread(u->sink);
477 pa_sink_set_asyncmsgq(u->sink, NULL);
478 pa_sink_set_rtpoll(u->sink, NULL);
479 }
480
481 /* Called from I/O thread context */
482 static void sink_input_attach_cb(pa_sink_input *i) {
483 struct userdata *u;
484
485 pa_sink_input_assert_ref(i);
486 pa_assert_se(u = i->userdata);
487
488 if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
489 return;
490
491 pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
492 pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
493 pa_sink_attach_within_thread(u->sink);
494
495 pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
496 }
497
498 /* Called from main context */
499 static void sink_input_kill_cb(pa_sink_input *i) {
500 struct userdata *u;
501
502 pa_sink_input_assert_ref(i);
503 pa_assert_se(u = i->userdata);
504
505 pa_sink_unlink(u->sink);
506 pa_sink_input_unlink(u->sink_input);
507
508 pa_sink_unref(u->sink);
509 u->sink = NULL;
510 pa_sink_input_unref(u->sink_input);
511 u->sink_input = NULL;
512
513 pa_module_unload_request(u->module, TRUE);
514 }
515
516 /* Called from IO thread context */
517 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
518 struct userdata *u;
519
520 pa_sink_input_assert_ref(i);
521 pa_assert_se(u = i->userdata);
522
523 /* If we are added for the first time, ask for a rewinding so that
524 * we are heard right-away. */
525 if (PA_SINK_INPUT_IS_LINKED(state) &&
526 i->thread_info.state == PA_SINK_INPUT_INIT) {
527 pa_log_debug("Requesting rewind due to state change.");
528 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
529 }
530 }
531
532 /* Called from main context */
533 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
534 struct userdata *u;
535
536 pa_sink_input_assert_ref(i);
537 pa_assert_se(u = i->userdata);
538
539 return u->sink != dest;
540 }
541
542 int pa__init(pa_module*m) {
543 struct userdata *u;
544 pa_sample_spec ss;
545 pa_channel_map map;
546 pa_modargs *ma;
547 const char *z;
548 pa_sink *master;
549 pa_sink_input_new_data sink_input_data;
550 pa_sink_new_data sink_data;
551 pa_bool_t *use_default = NULL;
552 size_t fs;
553
554 pa_assert(m);
555
556 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
557 pa_log("Failed to parse module arguments.");
558 goto fail;
559 }
560
561 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
562 pa_log("Master sink not found");
563 goto fail;
564 }
565
566 ss = master->sample_spec;
567 ss.format = PA_SAMPLE_FLOAT32;
568 map = master->channel_map;
569 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
570 pa_log("Invalid sample format specification or channel map");
571 goto fail;
572 }
573 fs=pa_frame_size(&ss);
574
575 u = pa_xnew0(struct userdata, 1);
576 u->core = m->core;
577 u->module = m;
578 m->userdata = u;
579 u->master = master;
580 u->sink = NULL;
581 u->sink_input = NULL;
582 u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, NULL);
583
584 //u->samplings=0;
585 u->channels=ss.channels;
586 u->fft_size=pow(2,ceil(log(ss.rate)/log(2)));
587 pa_log("fft size: %ld",u->fft_size);
588 u->window_size=7999;
589 u->R=(u->window_size+1)/2;
590 u->samples_gathered=0;
591 u->n_buffered_output=0;
592 u->max_output=pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss)/pa_frame_size(&ss);
593 u->H=(float*) fftwf_malloc((u->fft_size/2+1)*sizeof(float));
594 u->W=(float*) fftwf_malloc((u->window_size)*sizeof(float));
595 u->work_buffer=(float*) fftwf_malloc(u->fft_size*sizeof(float));
596 u->input=(float **)malloc(sizeof(float *)*u->channels);
597 u->overlap_accum=(float **)malloc(sizeof(float *)*u->channels);
598 u->output_buffer=(float **)malloc(sizeof(float *)*u->channels);
599 for(size_t c=0;c<u->channels;++c){
600 u->input[c]=(float*) fftwf_malloc(u->window_size*sizeof(float));
601 pa_assert_se(u->input[c]);
602 memset(u->input[c],0,u->window_size*sizeof(float));
603 pa_assert_se(u->input[c]);
604 u->overlap_accum[c]=(float*) fftwf_malloc(u->R*sizeof(float));
605 pa_assert_se(u->overlap_accum[c]);
606 memset(u->overlap_accum[c],0,u->R*sizeof(float));
607 u->output_buffer[c]=(float*) fftwf_malloc(u->window_size*sizeof(float));
608 pa_assert_se(u->output_buffer[c]);
609 }
610 u->output_window = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * (u->fft_size/2+1));
611 u->forward_plan=fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
612 u->inverse_plan=fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE);
613 /*
614 for(size_t j=0;j<u->window_size;++j){
615 u->W[j]=.5;
616 }
617 */
618 hanning_window(u->W,u->window_size);
619
620 const int freqs[]={0,25,50,100,200,300,400,800,1500,
621 2000,3000,4000,5000,6000,7000,8000,9000,10000,11000,12000,
622 13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23000,24000,INT_MAX};
623 const float coefficients[]={1,1,1,1,1,1,1,1,1,1,
624 1,1,1,1,1,1,1,1,
625 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
626 const size_t ncoefficients=sizeof(coefficients)/sizeof(float);
627 pa_assert_se(sizeof(freqs)/sizeof(int)==sizeof(coefficients)/sizeof(float));
628 float *freq_translated=(float *) malloc(sizeof(float)*(ncoefficients));
629 freq_translated[0]=1;
630 //Translate the frequencies in their natural sampling rate to the new sampling rate frequencies
631 for(size_t i=1;i<ncoefficients-1;++i){
632 freq_translated[i]=((float)freqs[i]*u->fft_size)/ss.rate;
633 //pa_log("i: %ld: %d , %g",i,freqs[i],freq_translated[i]);
634 pa_assert_se(freq_translated[i]>=freq_translated[i-1]);
635 }
636 freq_translated[ncoefficients-1]=FLT_MAX;
637 //Interpolate the specified frequency band values
638 u->H[0]=1;
639 for(size_t i=1,j=0;i<(u->fft_size/2+1);++i){
640 pa_assert_se(j<ncoefficients);
641 //max frequency range passed, consider the rest as one band
642 if(freq_translated[j+1]>=FLT_MAX){
643 for(;i<(u->fft_size/2+1);++i){
644 u->H[i]=coefficients[j];
645 }
646 break;
647 }
648 //pa_log("i: %d, j: %d, freq: %f",i,j,freq_translated[j]);
649 //pa_log("interp: %0.4f %0.4f",freq_translated[j],freq_translated[j+1]);
650 pa_assert_se(freq_translated[j]<freq_translated[j+1]);
651 pa_assert_se(i>=freq_translated[j]);
652 pa_assert_se(i<=freq_translated[j+1]);
653 //bilinear-inerpolation of coefficients specified
654 float c0=(i-freq_translated[j])/(freq_translated[j+1]-freq_translated[j]);
655 pa_assert_se(c0>=0&&c0<=1.0);
656 u->H[i]=((1.0f-c0)*coefficients[j]+c0*coefficients[j+1]);
657 pa_assert_se(u->H[i]>0);
658 while(i>=floor(freq_translated[j+1])){
659 j++;
660 }
661 }
662 //divide out the fft gain
663 for(size_t i=0;i<(u->fft_size/2+1);++i){
664 u->H[i]/=u->fft_size;
665 }
666 free(freq_translated);
667
668 /* Create sink */
669 pa_sink_new_data_init(&sink_data);
670 sink_data.driver = __FILE__;
671 sink_data.module = m;
672 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
673 sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name);
674 sink_data.namereg_fail = FALSE;
675 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
676 pa_sink_new_data_set_channel_map(&sink_data, &map);
677 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
678 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "FFT based equalizer");
679 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
680 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
681
682 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
683 pa_log("Invalid properties");
684 pa_sink_new_data_done(&sink_data);
685 goto fail;
686 }
687
688 u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY);
689 pa_sink_new_data_done(&sink_data);
690
691 if (!u->sink) {
692 pa_log("Failed to create sink.");
693 goto fail;
694 }
695
696 u->sink->parent.process_msg = sink_process_msg;
697 u->sink->set_state = sink_set_state;
698 u->sink->update_requested_latency = sink_update_requested_latency;
699 u->sink->request_rewind = sink_request_rewind;
700 u->sink->userdata = u;
701
702 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
703 pa_sink_set_rtpoll(u->sink, master->rtpoll);
704
705 /* Create sink input */
706 pa_sink_input_new_data_init(&sink_input_data);
707 sink_input_data.driver = __FILE__;
708 sink_input_data.module = m;
709 sink_input_data.sink = u->master;
710 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
711 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
712 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
713 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
714
715 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, PA_SINK_INPUT_DONT_MOVE);
716 pa_sink_input_new_data_done(&sink_input_data);
717
718 if (!u->sink_input)
719 goto fail;
720
721 u->sink_input->pop = sink_input_pop_cb;
722 u->sink_input->process_rewind = sink_input_process_rewind_cb;
723 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
724 u->sink_input->update_max_request = sink_input_update_max_request_cb;
725 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
726 u->sink_input->kill = sink_input_kill_cb;
727 u->sink_input->attach = sink_input_attach_cb;
728 u->sink_input->detach = sink_input_detach_cb;
729 u->sink_input->state_change = sink_input_state_change_cb;
730 u->sink_input->may_move_to = sink_input_may_move_to_cb;
731 u->sink_input->userdata = u;
732
733 pa_sink_put(u->sink);
734 pa_sink_input_put(u->sink_input);
735
736 pa_modargs_free(ma);
737
738 pa_xfree(use_default);
739
740 return 0;
741
742 fail:
743 if (ma)
744 pa_modargs_free(ma);
745
746 pa_xfree(use_default);
747
748 pa__done(m);
749
750 return -1;
751 }
752
753 int pa__get_n_used(pa_module *m) {
754 struct userdata *u;
755
756 pa_assert(m);
757 pa_assert_se(u = m->userdata);
758
759 return pa_sink_linked_by(u->sink);
760 }
761
762 void pa__done(pa_module*m) {
763 struct userdata *u;
764
765 pa_assert(m);
766
767 if (!(u = m->userdata))
768 return;
769
770 if (u->sink) {
771 pa_sink_unlink(u->sink);
772 pa_sink_unref(u->sink);
773 }
774
775 if (u->sink_input) {
776 pa_sink_input_unlink(u->sink_input);
777 pa_sink_input_unref(u->sink_input);
778 }
779
780 if (u->memblockq)
781 pa_memblockq_free(u->memblockq);
782
783 fftwf_destroy_plan(u->inverse_plan);
784 fftwf_destroy_plan(u->forward_plan);
785 fftwf_free(u->output_window);
786 for(size_t c=0;c<u->channels;++c){
787 fftwf_free(u->output_buffer[c]);
788 fftwf_free(u->overlap_accum[c]);
789 fftwf_free(u->input[c]);
790 }
791 free(u->output_buffer);
792 free(u->overlap_accum);
793 free(u->input);
794 fftwf_free(u->work_buffer);
795 fftwf_free(u->W);
796 fftwf_free(u->H);
797
798 pa_xfree(u);
799 }