pg: Add missing dummy stack frames for mcount for x86_64.
[dragonfly.git] / sys / tools / sound / feeder_eq_mkfilter.awk
blobf9a52e1243f9483ae1f9bca5a5f8aae479345f25
1 #!/usr/bin/awk -f
3 # Copyright (c) 2008-2009 Ariff Abdullah <ariff@FreeBSD.org>
4 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
27 # $FreeBSD: head/sys/tools/sound/feeder_eq_mkfilter.awk 193889 2009-06-10 06:49:45Z ariff $
31 # Biquad coefficients generator for Parametric Software Equalizer. Not as ugly
32 # as 'feeder_rate_mkfilter.awk'
34 # Based on:
36 # "Cookbook formulae for audio EQ biquad filter coefficients"
37 # by Robert Bristow-Johnson <rbj@audioimagination.com>
39 # - http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
45 # Some basic Math functions.
47 function abs(x)
49 return (((x < 0) ? -x : x) + 0);
52 function fabs(x)
54 return (((x < 0.0) ? -x : x) + 0.0);
57 function floor(x, r)
59 r = int(x);
60 if (r > x)
61 r--;
62 return (r + 0);
65 function pow(x, y)
67 return (exp(1.0 * y * log(1.0 * x)));
71 # What the hell...
73 function shl(x, y)
75 while (y > 0) {
76 x *= 2;
77 y--;
79 return (x);
82 function feedeq_w0(fc, rate)
84 return ((2.0 * M_PI * fc) / (1.0 * rate));
87 function feedeq_A(gain, A)
89 if (FEEDEQ_TYPE == FEEDEQ_TYPE_PEQ || FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF)
90 A = pow(10, gain / 40.0);
91 else
92 A = sqrt(pow(10, gain / 20.0));
94 return (A);
97 function feedeq_alpha(w0, A, QS)
99 if (FEEDEQ_TYPE == FEEDEQ_TYPE_PEQ)
100 alpha = sin(w0) / (2.0 * QS);
101 else if (FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF)
102 alpha = sin(w0) * 0.5 * sqrt(A + ((1.0 / A) * \
103 ((1.0 / QS) - 1.0)) + 2.0);
104 else
105 alpha = 0.0;
107 return (alpha);
110 function feedeq_fx_floor(v, r)
112 if (fabs(v) < fabs(smallest))
113 smallest = v;
114 if (fabs(v) > fabs(largest))
115 largest = v;
117 r = floor((v * FEEDEQ_COEFF_ONE) + 0.5);
119 if (r < INT32_MIN || r > INT32_MAX)
120 printf("\n#error overflow v=%f, " \
121 "please reduce FEEDEQ_COEFF_SHIFT\n", v);
123 return (r);
126 function feedeq_gen_biquad_coeffs(coeffs, rate, gain, \
127 w0, A, alpha, a0, a1, a2, b0, b1, b2)
129 w0 = feedeq_w0(FEEDEQ_TREBLE_SFREQ, 1.0 * rate);
130 A = feedeq_A(1.0 * gain);
131 alpha = feedeq_alpha(w0, A, FEEDEQ_TREBLE_SLOPE);
133 if (FEEDEQ_TYPE == FEEDEQ_TYPE_PEQ) {
134 b0 = 1.0 + (alpha * A);
135 b1 = -2.0 * cos(w0);
136 b2 = 1.0 - (alpha * A);
137 a0 = 1.0 + (alpha / A);
138 a1 = -2.0 * cos(w0);
139 a2 = 1.0 - (alpha / A);
140 } else if (FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF) {
141 b0 = A*((A+1.0)+((A-1.0)*cos(w0))+(2.0*sqrt(A)*alpha));
142 b1 = -2.0*A*((A-1.0)+((A+1.0)*cos(w0)) );
143 b2 = A*((A+1.0)+((A-1.0)*cos(w0))-(2.0*sqrt(A)*alpha));
144 a0 = (A+1.0)-((A-1.0)*cos(w0))+(2.0*sqrt(A)*alpha );
145 a1 = 2.0 * ((A-1.0)-((A+1.0)*cos(w0)) );
146 a2 = (A+1.0)-((A-1.0)*cos(w0))-(2.0*sqrt(A)*alpha );
147 } else
148 b0 = b1 = b2 = a0 = a1 = a2 = 0.0;
150 b0 /= a0;
151 b1 /= a0;
152 b2 /= a0;
153 a1 /= a0;
154 a2 /= a0;
156 coeffs["treble", gain, 0] = feedeq_fx_floor(a0);
157 coeffs["treble", gain, 1] = feedeq_fx_floor(a1);
158 coeffs["treble", gain, 2] = feedeq_fx_floor(a2);
159 coeffs["treble", gain, 3] = feedeq_fx_floor(b0);
160 coeffs["treble", gain, 4] = feedeq_fx_floor(b1);
161 coeffs["treble", gain, 5] = feedeq_fx_floor(b2);
163 w0 = feedeq_w0(FEEDEQ_BASS_SFREQ, 1.0 * rate);
164 A = feedeq_A(1.0 * gain);
165 alpha = feedeq_alpha(w0, A, FEEDEQ_BASS_SLOPE);
167 if (FEEDEQ_TYPE == FEEDEQ_TYPE_PEQ) {
168 b0 = 1.0 + (alpha * A);
169 b1 = -2.0 * cos(w0);
170 b2 = 1.0 - (alpha * A);
171 a0 = 1.0 + (alpha / A);
172 a1 = -2.0 * cos(w0);
173 a2 = 1.0 - (alpha / A);
174 } else if (FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF) {
175 b0 = A*((A+1.0)-((A-1.0)*cos(w0))+(2.0*sqrt(A)*alpha));
176 b1 = 2.0*A*((A-1.0)-((A+1.0)*cos(w0)) );
177 b2 = A*((A+1.0)-((A-1.0)*cos(w0))-(2.0*sqrt(A)*alpha));
178 a0 = (A+1.0)+((A-1.0)*cos(w0))+(2.0*sqrt(A)*alpha );
179 a1 = -2.0 * ((A-1.0)+((A+1.0)*cos(w0)) );
180 a2 = (A+1.0)+((A-1.0)*cos(w0))-(2.0*sqrt(A)*alpha );
181 } else
182 b0 = b1 = b2 = a0 = a1 = a2 = 0.0;
184 b0 /= a0;
185 b1 /= a0;
186 b2 /= a0;
187 a1 /= a0;
188 a2 /= a0;
190 coeffs["bass", gain, 0] = feedeq_fx_floor(a0);
191 coeffs["bass", gain, 1] = feedeq_fx_floor(a1);
192 coeffs["bass", gain, 2] = feedeq_fx_floor(a2);
193 coeffs["bass", gain, 3] = feedeq_fx_floor(b0);
194 coeffs["bass", gain, 4] = feedeq_fx_floor(b1);
195 coeffs["bass", gain, 5] = feedeq_fx_floor(b2);
198 function feedeq_gen_freq_coeffs(frq, g, i, v)
200 coeffs[0] = 0;
202 for (g = (FEEDEQ_GAIN_MIN * FEEDEQ_GAIN_DIV); \
203 g <= (FEEDEQ_GAIN_MAX * FEEDEQ_GAIN_DIV); \
204 g += FEEDEQ_GAIN_STEP) {
205 feedeq_gen_biquad_coeffs(coeffs, frq, \
206 g * FEEDEQ_GAIN_RECIPROCAL);
209 printf("\nstatic struct feed_eq_coeff eq_%d[%d] " \
210 "= {\n", frq, FEEDEQ_LEVELS);
211 for (g = (FEEDEQ_GAIN_MIN * FEEDEQ_GAIN_DIV); \
212 g <= (FEEDEQ_GAIN_MAX * FEEDEQ_GAIN_DIV); \
213 g += FEEDEQ_GAIN_STEP) {
214 printf(" {{ ");
215 for (i = 1; i < 6; i++) {
216 v = coeffs["treble", g * FEEDEQ_GAIN_RECIPROCAL, i];
217 printf("%s0x%08x%s", \
218 (v < 0) ? "-" : " ", abs(v), \
219 (i == 5) ? " " : ", ");
221 printf("},\n { ");
222 for (i = 1; i < 6; i++) {
223 v = coeffs["bass", g * FEEDEQ_GAIN_RECIPROCAL, i];
224 printf("%s0x%08x%s", \
225 (v < 0) ? "-" : " ", abs(v), \
226 (i == 5) ? " " : ", ");
228 printf("}}%s\n", \
229 (g < (FEEDEQ_GAIN_MAX * FEEDEQ_GAIN_DIV)) ? "," : "");
231 printf("};\n");
234 function feedeq_calc_preamp(norm, gain, shift, mul, bit, attn)
236 shift = FEEDEQ_PREAMP_SHIFT;
238 if (floor(FEEDEQ_PREAMP_BITDB) == 6 && \
239 (1.0 * floor(gain)) == gain && (floor(gain) % 6) == 0) {
240 mul = 1;
241 shift = floor(floor(gain) / 6);
242 } else {
243 bit = 32.0 - ((1.0 * gain) / (1.0 * FEEDEQ_PREAMP_BITDB));
244 attn = pow(2.0, bit) / pow(2.0, 32.0);
245 mul = floor((attn * FEEDEQ_PREAMP_ONE) + 0.5);
248 while ((mul % 2) == 0 && shift > 0) {
249 mul = floor(mul / 2);
250 shift--;
253 norm["mul"] = mul;
254 norm["shift"] = shift;
257 BEGIN {
258 M_PI = atan2(0.0, -1.0);
260 INT32_MAX = 1 + ((shl(1, 30) - 1) * 2);
261 INT32_MIN = -1 - INT32_MAX;
263 FEEDEQ_TYPE_PEQ = 0;
264 FEEDEQ_TYPE_SHELF = 1;
266 FEEDEQ_TYPE = FEEDEQ_TYPE_PEQ;
268 FEEDEQ_COEFF_SHIFT = 24;
269 FEEDEQ_COEFF_ONE = shl(1, FEEDEQ_COEFF_SHIFT);
271 FEEDEQ_PREAMP_SHIFT = 31;
272 FEEDEQ_PREAMP_ONE = shl(1, FEEDEQ_PREAMP_SHIFT);
273 FEEDEQ_PREAMP_BITDB = 6; # 20.0 * (log(2.0) / log(10.0));
275 FEEDEQ_GAIN_DIV = 10;
276 i = 0;
277 j = 1;
278 while (j < FEEDEQ_GAIN_DIV) {
279 j *= 2;
280 i++;
282 FEEDEQ_GAIN_SHIFT = i;
283 FEEDEQ_GAIN_FMASK = shl(1, FEEDEQ_GAIN_SHIFT) - 1;
285 FEEDEQ_GAIN_RECIPROCAL = 1.0 / FEEDEQ_GAIN_DIV;
287 if (ARGC == 2) {
288 i = 1;
289 split(ARGV[1], arg, ":");
290 while (match(arg[i], "^[^0-9]*$")) {
291 if (arg[i] == "PEQ") {
292 FEEDEQ_TYPE = FEEDEQ_TYPE_PEQ;
293 } else if (arg[i] == "SHELF") {
294 FEEDEQ_TYPE = FEEDEQ_TYPE_SHELF;
296 i++;
298 split(arg[i++], subarg, ",");
299 FEEDEQ_TREBLE_SFREQ = 1.0 * subarg[1];
300 FEEDEQ_TREBLE_SLOPE = 1.0 * subarg[2];
301 split(arg[i++], subarg, ",");
302 FEEDEQ_BASS_SFREQ = 1.0 * subarg[1];
303 FEEDEQ_BASS_SLOPE = 1.0 * subarg[2];
304 split(arg[i++], subarg, ",");
305 FEEDEQ_GAIN_MIN = floor(1.0 * subarg[1]);
306 FEEDEQ_GAIN_MAX = floor(1.0 * subarg[2]);
307 if (length(subarg) > 2) {
308 j = floor(1.0 * FEEDEQ_GAIN_DIV * subarg[3]);
309 if (j < 2)
310 j = 1;
311 else if (j < 5)
312 j = 2;
313 else if (j < 10)
314 j = 5;
315 else
316 j = 10;
317 if (j > FEEDEQ_GAIN_DIV || (FEEDEQ_GAIN_DIV % j) != 0)
318 j = FEEDEQ_GAIN_DIV;
319 FEEDEQ_GAIN_STEP = j;
320 } else
321 FEEDEQ_GAIN_STEP = FEEDEQ_GAIN_DIV;
322 split(arg[i], subarg, ",");
323 for (i = 1; i <= length(subarg); i++)
324 allfreq[i - 1] = floor(1.0 * subarg[i]);
325 } else {
326 FEEDEQ_TREBLE_SFREQ = 16000.0;
327 FEEDEQ_TREBLE_SLOPE = 0.25;
328 FEEDEQ_BASS_SFREQ = 62.0;
329 FEEDEQ_BASS_SLOPE = 0.25;
331 FEEDEQ_GAIN_MIN = -9;
332 FEEDEQ_GAIN_MAX = 9;
334 FEEDEQ_GAIN_STEP = FEEDEQ_GAIN_DIV;
337 allfreq[0] = 44100;
338 allfreq[1] = 48000;
339 allfreq[2] = 88200;
340 allfreq[3] = 96000;
341 allfreq[4] = 176400;
342 allfreq[5] = 192000;
345 FEEDEQ_LEVELS = ((FEEDEQ_GAIN_MAX - FEEDEQ_GAIN_MIN) * \
346 floor(FEEDEQ_GAIN_DIV / FEEDEQ_GAIN_STEP)) + 1;
348 FEEDEQ_ERR_CLIP = 0;
350 smallest = 10.000000;
351 largest = 0.000010;
353 printf("#ifndef _FEEDER_EQ_GEN_H_\n");
354 printf("#define _FEEDER_EQ_GEN_H_\n\n");
355 printf("/*\n");
356 printf(" * Generated using feeder_eq_mkfilter.awk, heaven, wind and awesome.\n");
357 printf(" *\n");
358 printf(" * DO NOT EDIT!\n");
359 printf(" */\n\n");
360 printf("/*\n");
361 printf(" * EQ: %s\n", (FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF) ? \
362 "Shelving" : "Peaking EQ");
363 printf(" */\n");
364 printf("#define FEEDER_EQ_PRESETS\t\"");
365 printf("%s:%d,%.4f,%d,%.4f:%d,%d,%.1f:", \
366 (FEEDEQ_TYPE == FEEDEQ_TYPE_SHELF) ? "SHELF" : "PEQ", \
367 FEEDEQ_TREBLE_SFREQ, FEEDEQ_TREBLE_SLOPE, \
368 FEEDEQ_BASS_SFREQ, FEEDEQ_BASS_SLOPE, \
369 FEEDEQ_GAIN_MIN, FEEDEQ_GAIN_MAX, \
370 FEEDEQ_GAIN_STEP * FEEDEQ_GAIN_RECIPROCAL);
371 for (i = 0; i < length(allfreq); i++) {
372 if (i != 0)
373 printf(",");
374 printf("%d", allfreq[i]);
376 printf("\"\n\n");
377 printf("struct feed_eq_coeff_tone {\n");
378 printf("\tint32_t a1, a2;\n");
379 printf("\tint32_t b0, b1, b2;\n");
380 printf("};\n\n");
381 printf("struct feed_eq_coeff {\n");
382 #printf("\tstruct {\n");
383 #printf("\t\tint32_t a1, a2;\n");
384 #printf("\t\tint32_t b0, b1, b2;\n");
385 #printf("\t} treble, bass;\n");
386 printf("\tstruct feed_eq_coeff_tone treble;\n");
387 printf("\tstruct feed_eq_coeff_tone bass;\n");
388 #printf("\tstruct {\n");
389 #printf("\t\tint32_t a1, a2;\n");
390 #printf("\t\tint32_t b0, b1, b2;\n");
391 #printf("\t} bass;\n");
392 printf("};\n");
393 for (i = 0; i < length(allfreq); i++)
394 feedeq_gen_freq_coeffs(allfreq[i]);
395 printf("\n");
396 printf("static const struct {\n");
397 printf("\tuint32_t rate;\n");
398 printf("\tstruct feed_eq_coeff *coeff;\n");
399 printf("} feed_eq_tab[] = {\n");
400 for (i = 0; i < length(allfreq); i++) {
401 printf("\t{ %6d, eq_%-6d },\n", allfreq[i], allfreq[i]);
403 printf("};\n");
405 printf("\n#define FEEDEQ_RATE_MIN\t\t%d\n", allfreq[0]);
406 printf("#define FEEDEQ_RATE_MAX\t\t%d\n", allfreq[length(allfreq) - 1]);
407 printf("\n#define FEEDEQ_TAB_SIZE\t\t\t\t\t\t\t\\\n");
408 printf("\t((int32_t)(sizeof(feed_eq_tab) / sizeof(feed_eq_tab[0])))\n");
410 printf("\nstatic const struct {\n");
411 printf("\tint32_t mul, shift;\n");
412 printf("} feed_eq_preamp[] = {\n");
413 for (i = (FEEDEQ_GAIN_MAX * 2 * FEEDEQ_GAIN_DIV); i >= 0; \
414 i -= FEEDEQ_GAIN_STEP) {
415 feedeq_calc_preamp(norm, i * FEEDEQ_GAIN_RECIPROCAL);
416 dbgain = ((FEEDEQ_GAIN_MAX * FEEDEQ_GAIN_DIV) - i) * \
417 FEEDEQ_GAIN_RECIPROCAL;
418 printf("\t{ 0x%08x, 0x%08x },\t/* %+5.1f dB */\n", \
419 norm["mul"], norm["shift"], dbgain);
421 printf("};\n");
423 printf("\n#define FEEDEQ_GAIN_MIN\t\t%d", FEEDEQ_GAIN_MIN);
424 printf("\n#define FEEDEQ_GAIN_MAX\t\t%d\n", FEEDEQ_GAIN_MAX);
426 printf("\n#define FEEDEQ_GAIN_SHIFT\t%d\n", FEEDEQ_GAIN_SHIFT);
427 printf("#define FEEDEQ_GAIN_DIV\t\t%d\n", FEEDEQ_GAIN_DIV);
428 printf("#define FEEDEQ_GAIN_FMASK\t0x%08x\n", FEEDEQ_GAIN_FMASK);
429 printf("#define FEEDEQ_GAIN_STEP\t%d\n", FEEDEQ_GAIN_STEP);
431 #printf("\n#define FEEDEQ_PREAMP_MIN\t-%d\n", \
432 # shl(FEEDEQ_GAIN_MAX, FEEDEQ_GAIN_SHIFT));
433 #printf("#define FEEDEQ_PREAMP_MAX\t%d\n", \
434 # shl(FEEDEQ_GAIN_MAX, FEEDEQ_GAIN_SHIFT));
436 printf("\n#define FEEDEQ_COEFF_SHIFT\t%d\n", FEEDEQ_COEFF_SHIFT);
438 #feedeq_calc_preamp(norm, FEEDEQ_GAIN_MAX);
440 #printf("#define FEEDEQ_COEFF_NORM(v)\t(");
441 #if (norm["mul"] == 1)
442 # printf("(v) >> %d", norm["shift"]);
443 #else
444 # printf("(0x%xLL * (v)) >> %d", norm["mul"], norm["shift"]);
445 #printf(")\n");
447 #printf("\n#define FEEDEQ_LEVELS\t\t%d\n", FEEDEQ_LEVELS);
448 if (FEEDEQ_ERR_CLIP != 0)
449 printf("\n#define FEEDEQ_ERR_CLIP\t\t%d\n", FEEDEQ_ERR_CLIP);
450 printf("\n/*\n");
451 printf(" * volume level mapping (0 - 100):\n");
452 printf(" *\n");
454 for (i = 0; i <= 100; i++) {
455 ind = floor((i * FEEDEQ_LEVELS) / 100);
456 if (ind >= FEEDEQ_LEVELS)
457 ind = FEEDEQ_LEVELS - 1;
458 printf(" *\t%3d -> %3d (%+5.1f dB)\n", \
459 i, ind, FEEDEQ_GAIN_MIN + \
460 (ind * (FEEDEQ_GAIN_RECIPROCAL * FEEDEQ_GAIN_STEP)));
463 printf(" */\n");
464 printf("\n/*\n * smallest: %.32f\n * largest: %.32f\n */\n", \
465 smallest, largest);
466 printf("\n#endif\t/* !_FEEDER_EQ_GEN_H_ */\n");