Index: apps/menus/eq_menu.c =================================================================== --- apps/menus/eq_menu.c (revision 30989) +++ apps/menus/eq_menu.c (working copy) @@ -46,6 +46,7 @@ #include "menu_common.h" #include "viewport.h" #include "exported_menus.h" +#include "fixedpoint.h" /* * Utility functions @@ -378,6 +379,91 @@ return; } + +void draw_eq_response_graph(long *curve, int x, int y, int width, int height) +{ + int h_height = height >> 1; + + FOR_NB_SCREENS(i) { + screens[i].set_drawmode(DRMODE_BG | DRMODE_INVERSEVID); + screens[i].fillrect(x, y, width, height); + screens[i].set_drawmode(DRMODE_SOLID); + int value; + + screens[i].drawrect(x,y,width,height); + for (int n=0; n < width-2; n++ ) { + value = (long) fp_div( fp_mul(h_height,fp_decibels((1 << 13) + curve[n],13), 13), + 24, 13) >> 13; /* 24dB dynamic range */ + if (value >= h_height) { + value = h_height-1; + } + if (value <= -h_height) { + value = -h_height+1; + } + screens[i].drawpixel(x+n, y+h_height-value); + } + + screens[i].set_drawmode(DRMODE_COMPLEMENT ); + long step = fp_div( fp_log10( fp_div(EQ_CUTOFF_MAX<<13, EQ_CUTOFF_MIN<<13, 13), 13), (width-2)<<13 ,13); /* s18.13 */ + for (int l=0; l<5; l++) { + int cutoff = *(&global_settings.eq_band0_cutoff + 3 * l); + int c_freq = fp_div( fp_log10( cutoff<<13, 13) - fp_log10(EQ_CUTOFF_MIN<<13, 13), step, 13) >> 13; + screens[i].vline( x+c_freq, y+1, y+height+1); + } + screens[i].set_drawmode(DRMODE_SOLID); + //screens[i].update_rect(x, y, width, height); + + } +} + + +static long* get_filter_response(int band, long *filter_curve, int num_samples) +{ + int *filter = &global_settings.eq_band0_gain; + filter += 3 * band; + long gain = *filter; + unsigned long cutoff = *(&global_settings.eq_band0_cutoff + 3 * band); + cutoff = cutoff << 13; /* s18.13 */ + unsigned long q = *(&global_settings.eq_band0_q + 3 * band); + const long minfreq = EQ_CUTOFF_MIN<<13; + const long sqrtA = fp_exp10(fp_div(gain<<13, 800<<13, 13), 13); /* 10^(db/80), s18.13 */ + const long A = fp_exp10(fp_div(gain<<13, 400<<13, 13), 13); /* s18.13 */ + //A = get_replaygain_int(gain*5) >> 11; /* 10^(db/40), s18,13 */ + + long step = fp_div( fp_log10( fp_div(EQ_CUTOFF_MAX<<13, EQ_CUTOFF_MIN<<13, 13), 13), + num_samples<<13, 13); /* s18.13 */ + const long offset = fp_div(fp_log10(minfreq, 13), step, 13); /* graph starts from minfreq */ + long s, s2, num, den; + int one = 1 << 13; + long fp_q = fp_div(q<<13, 10<<13, 13);/* s18.13 */ + const long A_mul_q = fp_mul(A,fp_q,13);/* s18.13 */ + const long A_div_q = fp_div(A,fp_q,13);/* s18.13 */ + const long sqrtA_div_q = fp_div(sqrtA,fp_q,13);/* s18.13 */ + + for (int i=0; i < num_samples; i++){ + s = fp_div( fp_exp10(fp_mul( (i<<13) + offset,step,13) , 13), cutoff, 13); + s2 = fp_mul(s,s,13); + if (band == 0 ) { /* H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) */ + num = fp_mul(A, (s2 + fp_mul((sqrtA_div_q),s,13) + A),13); + den = fp_mul(A,s2,13) + fp_mul((sqrtA_div_q),s,13) + one; + filter_curve[i] = fp_div(num,den,13); + } + else if (band == 4) { /* H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) */ + num = fp_mul(A, (fp_mul(A,s2,13) + fp_mul((sqrtA_div_q),s,13) + one),13); + den = s2 + fp_mul((sqrtA_div_q),s,13) + A; + filter_curve[i] = fp_div(num,den,13); + } + else { /* H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)*/ + filter_curve[i] = fp_div((s2 + fp_mul(s,(A_div_q),13) + one) , + (s2 + fp_div(s,(A_mul_q),13) + one),13); + } + + } + + return filter_curve; +} + + /* Provides a graphical means of editing the EQ settings */ bool eq_menu_graphical(void) { @@ -415,6 +501,29 @@ nb_eq_sliders[i] = 5; } + int ypos = 120; + int xpos = 5; + + int vertsize = screens[0].lcdheight - ypos -5; + int horizsize = screens[0].lcdwidth - (xpos << 1); + long sum; + int i; + + long curves[5][horizsize-2]; + for (i=0; i<5; i++) { + get_filter_response(i, curves[i], horizsize-2); + } + + long graph[horizsize-2]; + + for (i=0; i < (horizsize-2); i++) { + sum = 0; + for (int c=0; c < 5; c++) { + sum += curves[c][i] - (1 << 13); + } + graph[i] = sum; + } + y = h + 1; /* Start off editing gain on the first band */ @@ -489,7 +598,7 @@ /* Draw equalizer band details */ draw_eq_sliders(&screens[i], x, y, nb_eq_sliders[i], start_item, current_band, mode); - + draw_eq_response_graph((long*) &graph[0] , xpos, ypos, horizsize, vertsize); screens[i].update(); } @@ -562,6 +671,17 @@ if (has_changed) { dsp_set_eq_coefs(current_band); has_changed = false; + + get_filter_response(current_band, curves[current_band], horizsize-2); + for (i=0; i < (horizsize-2); i++) { + sum = 0; + for (int c=0; c < 5; c++) { + sum += curves[c][i] - (1<<13); + } + //printf("punto: %i, valore: %i | ", i, curves[current_band][i]); + graph[i] = sum; + } + } } @@ -576,6 +696,7 @@ return result; } + static bool eq_save_preset(void) { /* make sure that the eq is enabled for setting saving */ Index: apps/fixedpoint.c =================================================================== --- apps/fixedpoint.c (revision 30989) +++ apps/fixedpoint.c (working copy) @@ -358,7 +358,7 @@ /** FIXED POINT EXP10 * Return 10^x as FP integer. Argument is FP integer. */ -static long fp_exp10(long x, unsigned int fracbits) +long fp_exp10(long x, unsigned int fracbits) { long k; long z; @@ -413,11 +413,11 @@ } -#if 0 /* useful code, but not currently used */ + /** FIXED POINT LOG10 * Return log10(x) as FP integer. Argument is FP integer. */ -static long fp_log10(long n, unsigned int fracbits) +long fp_log10(long n, unsigned int fracbits) { /* Calculate log2 of argument */ @@ -465,7 +465,6 @@ /* decibels = 20 * log10(factor) */ return FP_MUL_FRAC((20L << fracbits), fp_log10(factor, fracbits)); } -#endif /* unused code */ /** CONVERT DECIBELS TO FACTOR */ Index: apps/fixedpoint.h =================================================================== --- apps/fixedpoint.h (revision 30989) +++ apps/fixedpoint.h (working copy) @@ -45,13 +45,14 @@ * and decibels is a fixed point integer. */ + #ifndef _FIXEDPOINT_H_APPS #define _FIXEDPOINT_H_APPS + #define fp_mul(x, y, z) (long)((((long long)(x)) * ((long long)(y))) >> (z)) #define fp_div(x, y, z) (long)((((long long)(x)) << (z)) / ((long long)(y))) - /** TAKEN FROM ORIGINAL fixedpoint.h */ long fp_sincos(unsigned long phase, long *cos); @@ -66,4 +67,10 @@ /* long fp_decibels(unsigned long factor, unsigned int fracbits); */ long fp_factor(long decibels, unsigned int fracbits); +long fp_decibels(unsigned long factor, unsigned int fracbits); + +long fp_log10(long n, unsigned int fracbits); + +long fp_exp10(long n, unsigned int fracbits); + #endif