Mercurial > audlegacy
changeset 4849:123b35cd71ab
Heal the equalizer's clipping prevention of insanity
author | John Lindgren <john.lindgren@tds.net> |
---|---|
date | Sun, 12 Apr 2009 23:52:38 -0400 |
parents | b2ee645f3e59 |
children | 47b72fc78e92 |
files | src/audlegacy/af_equalizer.c src/audlegacy/equalizer_flow.c |
diffstat | 2 files changed, 32 insertions(+), 57 deletions(-) [+] |
line wrap: on
line diff
--- a/src/audlegacy/af_equalizer.c Sun Apr 12 23:03:39 2009 -0400 +++ b/src/audlegacy/af_equalizer.c Sun Apr 12 23:52:38 2009 -0400 @@ -1,5 +1,5 @@ /*============================================================================= -// +// // This software has been released under the terms of the GNU General Public // license. See http://www.gnu.org/copyleft/gpl.html for details. // @@ -24,14 +24,14 @@ #include "af_compat.h" #define L 2 // Storage for filter taps -#define KM 10 // Max number of bands +#define KM 10 // Max number of bands #define Q 1.2247449 /* Q value for band-pass filters 1.2247=(3/2)^(1/2) gives 4dB suppression @ Fc*2 and Fc/2 */ /* Center frequencies for band-pass filters - The different frequency bands are: + The different frequency bands are: nr. center frequency 0 31.25 Hz 1 62.50 Hz @@ -49,7 +49,7 @@ // Maximum and minimum gain for the bands #define G_MAX +12.0 -#define G_MIN -12.0 +#define G_MIN -12.0 // Data for specific instances of this filter typedef struct af_equalizer_s @@ -60,12 +60,11 @@ float g[AF_NCH][KM]; // Gain factor for each channel and band int K; // Number of used eq bands int channels; // Number of channels - float gain_factor; // applied at output to avoid clipping } af_equalizer_t; static int af_test_output(struct af_instance_s* af, af_data_t* out) { - if((af->data->format != out->format) || + if((af->data->format != out->format) || (af->data->bps != out->bps) || (af->data->rate != out->rate) || (af->data->nch != out->nch)){ @@ -82,7 +81,7 @@ a[0] = (1.0 + C) * cos(th); a[1] = -1 * C; - + b[0] = (1.0 - C)/2.0; b[1] = -1.0050; } @@ -90,30 +89,28 @@ // Initialization and runtime control static int control(struct af_instance_s* af, int cmd, void* arg) { - af_equalizer_t* s = (af_equalizer_t*)af->setup; + af_equalizer_t* s = (af_equalizer_t*)af->setup; switch(cmd){ case AF_CONTROL_REINIT:{ - int k =0, i =0; + int k = 0; float F[KM] = CF; - - s->gain_factor=0.0; // Sanity check if(!arg) return AF_ERROR; - + af->data->rate = ((af_data_t*)arg)->rate; af->data->nch = ((af_data_t*)arg)->nch; af->data->format = AF_FORMAT_FLOAT_NE; af->data->bps = 4; - + // Calculate number of active filters s->K=KM; while(F[s->K-1] > (float)af->data->rate/2.2) s->K--; - + if(s->K != KM) - af_msg(AF_MSG_INFO,"[equalizer] Limiting the number of filters to" + af_msg(AF_MSG_INFO,"[equalizer] Limiting the number of filters to" " %i due to low sample rate.\n",s->K); // Generate filter taps @@ -122,35 +119,17 @@ // Calculate how much this plugin adds to the overall time delay af->delay = 2 * af->data->nch * af->data->bps; - - // Calculate gain factor to prevent clipping at output - for(k=0;k<AF_NCH;k++) - { - for(i=0;i<KM;i++) - { - if(s->gain_factor < s->g[k][i]) s->gain_factor=s->g[k][i]; - } - } - s->gain_factor=log10(s->gain_factor + 1.0) * 20.0; - - if(s->gain_factor > 0.0) - { - s->gain_factor=0.1+(s->gain_factor/12.0); - }else{ - s->gain_factor=1; - } - return af_test_output(af,arg); } case AF_CONTROL_COMMAND_LINE:{ float g[10]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; int i,j; - sscanf((char*)arg,"%f:%f:%f:%f:%f:%f:%f:%f:%f:%f", &g[0], &g[1], + sscanf((char*)arg,"%f:%f:%f:%f:%f:%f:%f:%f:%f:%f", &g[0], &g[1], &g[2], &g[3], &g[4], &g[5], &g[6], &g[7], &g[8] ,&g[9]); for(i=0;i<AF_NCH;i++){ for(j=0;j<KM;j++){ - ((af_equalizer_t*)af->setup)->g[i][j] = + ((af_equalizer_t*)af->setup)->g[i][j] = pow(10.0,clamp(g[j],G_MIN,G_MAX)/20.0)-1.0; } } @@ -184,7 +163,7 @@ return AF_UNKNOWN; } -// Deallocate memory +// Deallocate memory static void uninit(struct af_instance_s* af) { if(af->data) @@ -197,12 +176,12 @@ static af_data_t* play(struct af_instance_s* af, af_data_t* data) { af_data_t* c = data; // Current working data - af_equalizer_t* s = (af_equalizer_t*)af->setup; // Setup + af_equalizer_t* s = (af_equalizer_t*)af->setup; // Setup uint32_t ci = af->data->nch; // Index for channels uint32_t nch = af->data->nch; // Number of channels while(ci--){ - float* g = s->g[ci]; // Gain factor + float* g = s->g[ci]; // Gain factor float* in = ((float*)c->audio)+ci; float* out = ((float*)c->audio)+ci; float* end = in + c->len/4; // Block loop end @@ -211,7 +190,7 @@ register int k = 0; // Frequency band index register float yt = *in; // Current input sample in+=nch; - + // Run the filters for(;k<s->K;k++){ // Pointer to circular buffer wq @@ -224,8 +203,8 @@ wq[1] = wq[0]; wq[0] = w; } - // Calculate output - *out=yt*s->gain_factor; + // Calculate output + * out = yt; out+=nch; } }
--- a/src/audlegacy/equalizer_flow.c Sun Apr 12 23:03:39 2009 -0400 +++ b/src/audlegacy/equalizer_flow.c Sun Apr 12 23:52:38 2009 -0400 @@ -70,7 +70,7 @@ eq_rate = context->srate; bands_changed = FALSE; } - + data.nch = context->channels; data.audio = context->data; data.len = context->len; @@ -82,27 +82,23 @@ { int i; af_control_ext_t ctl; - gfloat b[10]; - gfloat adj = 0.0; - AUDDBG("\n"); - + gfloat highest; + gfloat adjusted [10]; + if(eq == NULL) { eq = g_malloc(sizeof(af_instance_t)); equalizer_open(eq); } - for(i = 0; i < 10; i++) - b[i] = bands[i] + pre; - - for(i = 0; i < 10; i++) - if(fabsf(b[i]) > fabsf(adj)) adj = b[i]; + highest = - EQUALIZER_MAX_GAIN; + for (i = 0; i < 10; i ++) { + if (bands [i] > highest) + highest = bands [i]; + } + for (i = 0; i < 10; i ++) + adjusted [i] = pre + bands [i] - highest; - if(fabsf(adj) > EQUALIZER_MAX_GAIN) { - adj = adj > 0.0 ? EQUALIZER_MAX_GAIN - adj : -EQUALIZER_MAX_GAIN - adj; - for(i = 0; i < 10; i++) b[i] += adj; - } - - ctl.arg = b; + ctl.arg = adjusted; for(i = 0; i < AF_NCH; i++) { ctl.ch = i; eq->control(eq, AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_SET, &ctl);