1 /*
2 SuperEQ DSP plugin for DeaDBeeF Player
3 Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include "../../deadbeef.h"
24 #include "Equ.h"
25
26 static DB_functions_t *deadbeef;
27 static DB_dsp_t plugin;
28
29 typedef struct {
30 ddb_dsp_context_t ctx;
31 float last_srate;
32 int last_nch;
33 float bands[18];
34 float preamp;
35 void *paramsroot;
36 int params_changed;
37 uintptr_t mutex;
38 SuperEqState state;
39 int enabled;
40 } ddb_supereq_ctx_t;
41
42 void supereq_reset (ddb_dsp_context_t *ctx);
43
44 void
recalc_table(ddb_supereq_ctx_t * eq)45 recalc_table (ddb_supereq_ctx_t *eq) {
46 void *params = paramlist_alloc ();
47
48 deadbeef->mutex_lock (eq->mutex);
49 float bands_copy[18];
50 float srate = eq->last_srate;
51 memcpy (bands_copy, eq->bands, sizeof (eq->bands));
52 for (int i = 0; i < 18; i++) {
53 bands_copy[i] *= eq->preamp;
54 }
55 deadbeef->mutex_unlock (eq->mutex);
56
57 equ_makeTable (&eq->state, bands_copy, params, srate);
58
59 deadbeef->mutex_lock (eq->mutex);
60 paramlist_free (eq->paramsroot);
61 eq->paramsroot = params;
62 deadbeef->mutex_unlock (eq->mutex);
63 }
64
65 int
supereq_plugin_start(void)66 supereq_plugin_start (void) {
67 return 0;
68 }
69
70 int
supereq_plugin_stop(void)71 supereq_plugin_stop (void) {
72 return 0;
73 }
74
75 int
supereq_process(ddb_dsp_context_t * ctx,float * samples,int frames,int maxframes,ddb_waveformat_t * fmt,float * r)76 supereq_process (ddb_dsp_context_t *ctx, float *samples, int frames, int maxframes, ddb_waveformat_t *fmt, float *r) {
77 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
78 if (supereq->enabled != ctx->enabled) {
79 if (ctx->enabled && !supereq->enabled) {
80 supereq_reset (ctx);
81 }
82 supereq->enabled = ctx->enabled;
83
84 // this causes a glitch on 1st track
85 // DB_playItem_t *it = deadbeef->streamer_get_playing_track ();
86 // if (it) {
87 // float playpos = deadbeef->streamer_get_playpos ();
88 // deadbeef->streamer_seek (playpos);
89 // deadbeef->pl_item_unref (it);
90 // }
91 }
92 if (supereq->params_changed) {
93 recalc_table (supereq);
94 supereq->params_changed = 0;
95 }
96 if (supereq->last_srate != fmt->samplerate || supereq->last_nch != fmt->channels) {
97 deadbeef->mutex_lock (supereq->mutex);
98 supereq->last_srate = fmt->samplerate;
99 supereq->last_nch = fmt->channels;
100 equ_init (&supereq->state, 10, fmt->channels);
101 recalc_table (supereq);
102 equ_clearbuf(&supereq->state);
103 deadbeef->mutex_unlock (supereq->mutex);
104 }
105 equ_modifySamples_float(&supereq->state, (char *)samples,frames,fmt->channels);
106 return frames;
107 }
108
109 float
supereq_get_band(ddb_dsp_context_t * ctx,int band)110 supereq_get_band (ddb_dsp_context_t *ctx, int band) {
111 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
112 return supereq->bands[band];
113 }
114
115 void
supereq_set_band(ddb_dsp_context_t * ctx,int band,float value)116 supereq_set_band (ddb_dsp_context_t *ctx, int band, float value) {
117 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
118 deadbeef->mutex_lock (supereq->mutex);
119 supereq->bands[band] = value;
120 deadbeef->mutex_unlock (supereq->mutex);
121 supereq->params_changed = 1;
122 }
123
124 float
supereq_get_preamp(ddb_dsp_context_t * ctx)125 supereq_get_preamp (ddb_dsp_context_t *ctx) {
126 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
127 return supereq->preamp;
128 }
129
130 void
supereq_set_preamp(ddb_dsp_context_t * ctx,float value)131 supereq_set_preamp (ddb_dsp_context_t *ctx, float value) {
132 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
133 deadbeef->mutex_lock (supereq->mutex);
134 supereq->preamp = value;
135 deadbeef->mutex_unlock (supereq->mutex);
136 supereq->params_changed = 1;
137 }
138
139 void
supereq_reset(ddb_dsp_context_t * ctx)140 supereq_reset (ddb_dsp_context_t *ctx) {
141 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
142 deadbeef->mutex_lock (supereq->mutex);
143 equ_clearbuf(&supereq->state);
144 deadbeef->mutex_unlock (supereq->mutex);
145 }
146
147 int
supereq_num_params(void)148 supereq_num_params (void) {
149 return 19;
150 }
151
152 static const char *bandnames[] = {
153 "Preamp",
154 "55 Hz",
155 "77 Hz",
156 "110 Hz",
157 "156 Hz",
158 "220 Hz",
159 "311 Hz",
160 "440 Hz",
161 "622 Hz",
162 "880 Hz",
163 "1.2 kHz",
164 "1.8 kHz",
165 "2.5 kHz",
166 "3.5 kHz",
167 "5 kHz",
168 "7 kHz",
169 "10 kHz",
170 "14 kHz",
171 "20 kHz"
172 };
173
174 const char *
supereq_get_param_name(int p)175 supereq_get_param_name (int p) {
176 return bandnames[p];
177 }
178
179
180 static inline float
db_to_amp(float dB)181 db_to_amp (float dB) {
182 const float ln10=2.3025850929940002f;
183 return exp(ln10*dB/20.f);
184 }
185
186 static inline float
amp_to_db(float amp)187 amp_to_db (float amp) {
188 return 20*log10 (amp);
189 }
190
191 void
supereq_set_param(ddb_dsp_context_t * ctx,int p,const char * val)192 supereq_set_param (ddb_dsp_context_t *ctx, int p, const char *val) {
193 switch (p) {
194 case 0:
195 supereq_set_preamp (ctx, db_to_amp (atof (val)));
196 break;
197 case 1 ... 18:
198 supereq_set_band (ctx, p-1, db_to_amp (atof (val)));
199 break;
200 default:
201 fprintf (stderr, "supereq_set_param: invalid param index (%d)\n", p);
202 }
203 }
204
205 void
supereq_get_param(ddb_dsp_context_t * ctx,int p,char * v,int sz)206 supereq_get_param (ddb_dsp_context_t *ctx, int p, char *v, int sz) {
207 switch (p) {
208 case 0:
209 snprintf (v, sz, "%f", amp_to_db (supereq_get_preamp (ctx)));
210 break;
211 case 1 ... 18:
212 snprintf (v, sz, "%f", amp_to_db (supereq_get_band (ctx, p-1)));
213 break;
214 default:
215 fprintf (stderr, "supereq_get_param: invalid param index (%d)\n", p);
216 }
217 }
218
219
220 ddb_dsp_context_t*
supereq_open(void)221 supereq_open (void) {
222 ddb_supereq_ctx_t *supereq = malloc (sizeof (ddb_supereq_ctx_t));
223 DDB_INIT_DSP_CONTEXT (supereq,ddb_supereq_ctx_t,&plugin);
224
225 equ_init (&supereq->state, 10, 2);
226 supereq->paramsroot = paramlist_alloc ();
227 supereq->last_srate = 44100;
228 supereq->last_nch = 2;
229 supereq->mutex = deadbeef->mutex_create ();
230 supereq->preamp = 1;
231 for (int i = 0; i < 18; i++) {
232 supereq->bands[i] = 1;
233 }
234 recalc_table (supereq);
235 equ_clearbuf (&supereq->state);
236
237 return (ddb_dsp_context_t*)supereq;
238 }
239
240 void
supereq_close(ddb_dsp_context_t * ctx)241 supereq_close (ddb_dsp_context_t *ctx) {
242 ddb_supereq_ctx_t *supereq = (ddb_supereq_ctx_t *)ctx;
243 if (supereq->mutex) {
244 deadbeef->mutex_free (supereq->mutex);
245 supereq->mutex = 0;
246 }
247 equ_quit (&supereq->state);
248 paramlist_free (supereq->paramsroot);
249 free (ctx);
250 }
251
252 static const char settings_dlg[] =
253 "property \"\" hbox[19] hmg fill expand border=0 spacing=8 height=200;\n"
254 "property \"Preamp\" vscale[20,-20,1] vert 0 0;\n"
255 "property \"55 Hz\" vscale[20,-20,1] vert 1 0;\n"
256 "property \"77 Hz\" vscale[20,-20,1] vert 2 0;\n"
257 "property \"110 Hz\" vscale[20,-20,1] vert 3 0;\n"
258 "property \"156 Hz\" vscale[20,-20,1] vert 4 0;\n"
259 "property \"220 Hz\" vscale[20,-20,1] vert 5 0;\n"
260 "property \"311 Hz\" vscale[20,-20,1] vert 6 0;\n"
261 "property \"440 Hz\" vscale[20,-20,1] vert 7 0;\n"
262 "property \"622 Hz\" vscale[20,-20,1] vert 8 0;\n"
263 "property \"880 Hz\" vscale[20,-20,1] vert 9 0;\n"
264 "property \"1.2 kHz\" vscale[20,-20,1] vert 10 0;\n"
265 "property \"1.8 kHz\" vscale[20,-20,1] vert 11 0;\n"
266 "property \"2.5 kHz\" vscale[20,-20,1] vert 12 0;\n"
267 "property \"3.5 kHz\" vscale[20,-20,1] vert 13 0;\n"
268 "property \"5 kHz\" vscale[20,-20,1] vert 14 0;\n"
269 "property \"7 kHz\" vscale[20,-20,1] vert 15 0;\n"
270 "property \"10 kHz\" vscale[20,-20,1] vert 16 0;\n"
271 "property \"14 kHz\" vscale[20,-20,1] vert 17 0;\n"
272 "property \"20 kHz\" vscale[20,-20,1] vert 18 0;\n"
273 ;
274
275 static DB_dsp_t plugin = {
276 .plugin.api_vmajor = 1,
277 .plugin.api_vminor = 0,
278 .plugin.version_major = 1,
279 .plugin.version_minor = 0,
280 .plugin.type = DB_PLUGIN_DSP,
281 .plugin.id = "supereq",
282 .plugin.name = "SuperEQ",
283 .plugin.descr = "equalizer plugin using SuperEQ library",
284 .plugin.copyright =
285 "SuperEQ DSP plugin for DeaDBeeF Player\n"
286 "Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>\n"
287 "\n"
288 "Uses supereq library by Naoki Shibata, http://shibatch.sourceforge.net\n"
289 "Uses FFT library by Takuya Ooura, http://www.kurims.kyoto-u.ac.jp/~ooura/\n"
290 "\n"
291 "This program is free software; you can redistribute it and/or\n"
292 "modify it under the terms of the GNU General Public License\n"
293 "as published by the Free Software Foundation; either version 2\n"
294 "of the License, or (at your option) any later version.\n"
295 "\n"
296 "This program is distributed in the hope that it will be useful,\n"
297 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
298 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
299 "GNU General Public License for more details.\n"
300 "\n"
301 "You should have received a copy of the GNU General Public License\n"
302 "along with this program; if not, write to the Free Software\n"
303 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
304 "\n"
305 "\n"
306 "\n"
307 "Based on:\n"
308 "Shibatch Super Equalizer ver 0.03 for winamp\n"
309 "written by Naoki Shibata shibatch@users.sourceforge.net\n"
310 "\n"
311 "Shibatch Super Equalizer is a graphic and parametric equalizer plugin\n"
312 "for winamp. This plugin uses 16383th order FIR filter with FFT algorithm.\n"
313 "It's equalization is very precise. Equalization setting can be done\n"
314 "for each channel separately.\n"
315 "\n"
316 "Processes of internal equalizer in winamp are actually done by each\n"
317 "input plugin, so the results may differ for each input plugin.\n"
318 "With this plugin, this problem can be avoided.\n"
319 "\n"
320 "This plugin is optimized for processors which have cache equal to or\n"
321 "greater than 128k bytes(16383*2*sizeof(float) = 128k). This plugin\n"
322 "won't work efficiently with K6 series processors(buy Athlon!!!).\n"
323 "\n"
324 "Do not forget pressing \"preview\" button after changing setting.\n"
325 "\n"
326 "http://shibatch.sourceforge.net/\n"
327 "\n"
328 "***\n"
329 "\n"
330 " This program(except FFT part) is distributed under LGPL. See LGPL.txt for\n"
331 "details.\n"
332 "\n"
333 " FFT part is a routine made by Mr.Ooura. This routine is a freeware. Contact\n"
334 "Mr.Ooura for details of distributing licenses.\n"
335 "\n"
336 "http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html\n"
337 ,
338 .plugin.website = "http://deadbeef.sf.net",
339 .plugin.start = supereq_plugin_start,
340 .plugin.stop = supereq_plugin_stop,
341 .open = supereq_open,
342 .close = supereq_close,
343 .process = supereq_process,
344 .reset = supereq_reset,
345 .num_params = supereq_num_params,
346 .get_param_name = supereq_get_param_name,
347 .set_param = supereq_set_param,
348 .get_param = supereq_get_param,
349 .configdialog = settings_dlg,
350 };
351
352 DB_plugin_t *
supereq_load(DB_functions_t * api)353 supereq_load (DB_functions_t *api) {
354 deadbeef = api;
355 return DB_PLUGIN (&plugin);
356 }
357