[xiph-commits] r8033 - trunk/postfish
xiphmont at motherfish-iii.xiph.org
xiphmont at motherfish-iii.xiph.org
Sat Oct 16 13:57:40 PDT 2004
Author: xiphmont
Date: 2004-10-16 13:57:39 -0700 (Sat, 16 Oct 2004)
New Revision: 8033
Added:
trunk/postfish/follower.c
trunk/postfish/follower.h
Modified:
trunk/postfish/Makefile
trunk/postfish/bessel.c
trunk/postfish/bessel.h
trunk/postfish/compandpanel.c
trunk/postfish/deverb.c
trunk/postfish/multicompand.c
trunk/postfish/outpanel.c
trunk/postfish/postfish.h
trunk/postfish/singlecomp.c
trunk/postfish/version.h
Log:
A second major upgrade to the math behind the Bessel followers used by
the companders.
a) Soft knees are now computed as a freebie during filter following.
No explicit soft-knee means no sqrt() means considerable optimization
b) streamlined the computation pathway of the followers, partially as
an optimization, partially to prepare for adding the scond tier
over/under filters before release
c) found a bug in the behavior of the new peak-follower math (that was
instigated to repair a more serious bug in the original version);
decay was still using a second order bessel which could still ring
about zero. Restored the peak-hold behavior to near-original
behavior, but now use the same first-order-decay-limited filters as
the RMS follower.
Depending on platform and compander usage, these changes are good for
getting back 10-25% of the CPU.
Modified: trunk/postfish/Makefile
===================================================================
--- trunk/postfish/Makefile 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/Makefile 2004-10-16 20:57:39 UTC (rev 8033)
@@ -30,13 +30,13 @@
feedback.c freq.c eq.c eqpanel.c compandpanel.c subband.c lpc.c \
bessel.c deverbpanel.c deverb.c singlecomp.c singlepanel.c \
limit.c limitpanel.c mute.c mixpanel.c mix.c reverb.c reverbpanel.c \
- outpanel.c config.c window.c
+ outpanel.c config.c window.c follower.c
OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.o \
declip.o reconstruct.o multicompand.o windowbutton.o subpanel.o \
feedback.o freq.o eq.o eqpanel.o compandpanel.o subband.o lpc.o \
bessel.o deverbpanel.o deverb.o singlecomp.o singlepanel.o \
limit.o limitpanel.o mute.o mixpanel.o mix.o reverb.o reverbpanel.o \
- outpanel.o config.o window.o
+ outpanel.o config.o window.o follower.o
GCF = -DETCDIR=\\\"$(ETCDIR)\\\" `pkg-config --cflags gtk+-2.0` -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED
all:
Modified: trunk/postfish/bessel.c
===================================================================
--- trunk/postfish/bessel.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/bessel.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -201,7 +201,7 @@
while(i<n){
double ya= (x[i]+x0*2.+x1)*a_g + y0*a_c0+y1*a_c1;
double yl= y0*l_c0;
- if(ya<y0 && ya<yl)ya=yl;
+ if(ya<yl)ya=yl;
x1=x0;x0=x[i];
y1=y0;x[i]=y0=ya;
@@ -269,7 +269,7 @@
x1=x0;x0=x[i];
}
- if(ya<y0 && ya<yl)ya=yl;
+ if(ya<yl)ya=yl;
y1=y0;x[i]=y0=ya;
i++;
@@ -313,40 +313,225 @@
}
-/* applies a 1st order freefall filter, followed by a 2nd order attack
- filter */
-void compute_iir_freefall1_then_symmetric2(float *x, int n, iir_state *is,
- iir_filter *attack,
- iir_filter *decay){
- double a_c0=attack->c[0],d_c0=decay->c[0];
- double a_c1=attack->c[1];
- double a_g=1./attack->g;
-
- double x0=is->x[0],x1=is->x[1];
- double y0=is->y[0],y1=is->y[1];
- double yd=is->y[2];
-
- int i=0;
+/* a new experiment; bessel followers constructed specifically for
+ compand functions. Hard and soft knee are implemented as part of
+ the follower. */
- if(zerome(y0) && zerome(y1)) y0=y1=0.;
- if(zerome(yd)) yd=0.;
+#define prologue double a_c0=attack->c[0],l_c0=limit->c[0]; \
+ double a_c1=attack->c[1]; \
+ double a_g=1./(knee * attack->g);\
+ double x0=is->x[0],x1=is->x[1]; \
+ double y0=is->y[0],y1=is->y[1]; \
+ int i=0; \
+ if(zerome(y0) && zerome(y1)) y0=y1=0.; \
+ while(i<n)
- while(i<n){
-
- yd*=d_c0;
- if(yd<x[i])yd=x[i];
-
- {
- double ya= (yd+x0*2.+x1)*a_g + y0*a_c0+y1*a_c1;
-
- x1=x0;x0=yd;
- y1=y0;x[i]=y0=ya;
- }
+/* Three delicious filters in one: The 'attack' filter is a fast
+ second-order Bessel used two ways; as a direct RMS follower and as
+ a filter pegged to free-fall to the knee value. The 'limit' filter
+ is a first-order free-fall (to 0) Bessel used to limit the 'attack'
+ filter to a linear-dB decay. Output is normalized to place the knee
+ at 1.0 (0dB) */
+
+void compute_iir_over_soft(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj){
+ double xag=4./attack->g;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ if(ya<xag)ya=xag;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ adj[i++]-= todB_a((float)ya)*mult;
+
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void compute_iir_under_soft(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj){
+ double xag=4./attack->g;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ if(ya>xag)ya=xag;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ adj[i++]-= todB_a((float)ya)*mult;
+
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void compute_iir_over_hard(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj){
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ if(ya>1.)adj[i]-= todB_a((float)ya)*mult;
i++;
- }
+ }
is->x[0]=x0;is->x[1]=x1;
is->y[0]=y0;is->y[1]=y1;
- is->y[2]=yd;
}
+void compute_iir_under_hard(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj){
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ if(ya<1.)adj[i]-= todB_a((float)ya)*mult;
+ i++;
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+/* One more take on the above; we need to be able to gently slew
+ multiplier changes from one block to the next. Although it seems
+ absurd to make eight total compander follower variants, doing this
+ inline avoids a copy later on, and these are enough of a CPU sink
+ that the silliness is actually worth it. */
+
+void compute_iir_over_soft_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj){
+ float multadd=(mult2-mult)/n;
+ double xag=4./attack->g;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ if(ya<xag)ya=xag;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ adj[i++]-= todB_a((float)ya)*mult;
+ mult+=multadd;
+
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void compute_iir_under_soft_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj){
+ float multadd=(mult2-mult)/n;
+ double xag=4./attack->g;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ if(ya>xag)ya=xag;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ adj[i++]-= todB_a((float)ya)*mult;
+ mult+=multadd;
+
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void compute_iir_over_hard_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj){
+ float multadd=(mult2-mult)/n;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ if(ya>1.)adj[i]-= todB_a((float)ya)*mult;
+ mult+=multadd;
+ i++;
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void compute_iir_under_hard_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj){
+ float multadd=(mult2-mult)/n;
+ prologue {
+
+ double ya = (x[i]+x0*2.+x1)*a_g;
+ ya += y0*a_c0;
+ ya += y1*a_c1;
+ double yl = y0*l_c0;
+ if(ya<yl)ya=yl;
+
+ x1=x0;x0=x[i];
+ y1=y0;y0=ya;
+ if(ya<1.)adj[i]-= todB_a((float)ya)*mult;
+ mult+=multadd;
+ i++;
+ }
+
+ is->x[0]=x0;is->x[1]=x1;
+ is->y[0]=y0;is->y[1]=y1;
+}
+
+void reset_iir(iir_state *is,float value){
+ int i;
+ for(i=0;i<MAXORDER;i++){
+ is->x[i]=(double)value;
+ is->y[i]=(double)value;
+ }
+}
+
Modified: trunk/postfish/bessel.h
===================================================================
--- trunk/postfish/bessel.h 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/bessel.h 2004-10-16 20:57:39 UTC (rev 8033)
@@ -66,7 +66,7 @@
typedef struct {
double x[MAXORDER];
- double y[MAXORDER+1];
+ double y[MAXORDER];
} iir_state;
extern double mkbessel(double raw_alpha,int order,double *ycoeff);
@@ -85,7 +85,42 @@
extern void compute_iir_freefallonly1(float *x, int n, iir_state *is,
iir_filter *decay);
-extern void compute_iir_freefall1_then_symmetric2(float *x, int n,
- iir_state *is,
- iir_filter *attack,
- iir_filter *decay);
+
+extern void compute_iir_over_soft(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj);
+
+extern void compute_iir_under_soft(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj);
+
+extern void compute_iir_over_hard(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj);
+
+extern void compute_iir_under_hard(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float *adj);
+
+extern void compute_iir_over_soft_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj);
+
+extern void compute_iir_under_soft_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj);
+
+extern void compute_iir_over_hard_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj);
+
+extern void compute_iir_under_hard_del(float *x, int n, iir_state *is,
+ iir_filter *attack, iir_filter *limit,
+ float knee, float mult, float mult2,
+ float *adj);
+
+extern void reset_iir(iir_state *is,float value);
+
Modified: trunk/postfish/compandpanel.c
===================================================================
--- trunk/postfish/compandpanel.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/compandpanel.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -317,8 +317,6 @@
static void average_change(GtkWidget *w,gpointer in){
multi_panel_state *mp=(multi_panel_state *)in;
if(!mp->updating_av_slider){
- multicompand_settings *ms=mp->ms;
- banked_multicompand_settings *bc=ms->bc;
cbar *b=mp->bars+multicomp_freqs_max;
cbar *bars=mp->bars;
int bank_active=mp->bank_active;
@@ -370,8 +368,6 @@
int bank_active=mp->bank_active;
int o,u;
- int i;
- int adj;
u=multibar_get_value(MULTIBAR(b->slider),0);
sprintf(buffer,"%+4ddB",u);
Modified: trunk/postfish/deverb.c
===================================================================
--- trunk/postfish/deverb.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/deverb.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -213,14 +213,14 @@
if(multiplier==sss->prevratio[i]){
for(k=0;k<input_size;k++)
- fast[k]=fromdB_a((todB_a(slow+k)-todB_a(fast+k))*.5*multiplier);
+ fast[k]=fromdB_a((todB_a(slow[k])-todB_a(fast[k]))*.5*multiplier);
}else{
float multiplier_add=(multiplier-sss->prevratio[i])/input_size;
multiplier=sss->prevratio[i];
for(k=0;k<input_size;k++){
- fast[k]=fromdB_a((todB_a(slow+k)-todB_a(fast+k))*.5*multiplier);
+ fast[k]=fromdB_a((todB_a(slow[k])-todB_a(fast[k]))*.5*multiplier);
multiplier+=multiplier_add;
}
Added: trunk/postfish/follower.c
===================================================================
--- trunk/postfish/follower.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/follower.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -0,0 +1,231 @@
+/*
+ *
+ * postfish
+ *
+ * Copyright (C) 2002-2004 Monty
+ *
+ * Postfish is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Postfish is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Postfish; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include "postfish.h"
+#include "follower.h"
+
+static void _analysis(char *base,int seq, float *data, int n,int dB,
+ off_t offset){
+
+ FILE *f;
+ char buf[80];
+ sprintf(buf,"%s_%d.m",base,seq);
+
+ f=fopen(buf,"a");
+ if(f){
+ int i;
+ for(i=0;i<n;i++)
+ if(dB)
+ fprintf(f,"%d %f\n",(int)(i+offset),todB(data[i]));
+ else
+ fprintf(f,"%d %f\n",(int)(i+offset),(data[i]));
+
+ }
+ fclose(f);
+}
+
+off_t offset=0;
+int offch;
+
+/* Common follower code */
+
+static void prepare_peak(float *peak, float *x, int n, int ahead,
+ int hold, peak_state *ps){
+ int ii,jj;
+ int loc=ps->loc;
+ float val=ps->val;
+
+ /* Although we have two input_size blocks of zeroes after a
+ reset, we may still need to look ahead explicitly after a
+ reset if the lookahead is exceptionally long */
+
+ if(loc==0 && val==0){
+ for(ii=0;ii<ahead;ii++)
+ if((x[ii]*x[ii])>val){
+ val=(x[ii]*x[ii]);
+ loc=ii+hold;
+ }
+ }
+
+ if(val>peak[0])peak[0]=val;
+
+ for(ii=1;ii<n;ii++){
+ if((x[ii+ahead]*x[ii+ahead])>val){
+ val=(x[ii+ahead]*x[ii+ahead]);
+ loc=ii+ahead+hold;
+ }
+ if(ii>=loc){
+ /* backfill */
+ val=0;
+ for(jj=ii+ahead-1;jj>=ii;jj--){
+ if((x[jj]*x[jj])>val)val=(x[jj]*x[jj]);
+ if(jj<n && val>peak[jj])peak[jj]=val;
+ }
+ val=(x[ii+ahead]*x[ii+ahead]);
+ loc=ii+ahead+hold;
+ }
+ if(val>peak[ii])peak[ii]=val;
+ }
+
+ ps->loc=loc-input_size;
+ ps->val=val;
+}
+
+static void fill_work(float *A, float *B, float *work,
+ int ahead, int hold, int mode, peak_state *ps){
+ int k;
+
+ if(mode){
+ /* peak mode */
+
+ memset(work,0,sizeof(*work)*input_size);
+
+ if(B){
+ float bigcache[input_size*2];
+ memcpy(bigcache,A,sizeof(*work)*input_size);
+ memcpy(bigcache+input_size,B,sizeof(*work)*input_size);
+
+ prepare_peak(work, bigcache, input_size, ahead, hold, ps);
+ }else{
+ prepare_peak(work, A, input_size, ahead, hold, ps);
+ }
+ }else{
+ /* rms mode */
+ float *cachea=A+ahead;
+
+ if(B){
+ float *worka=work+input_size-ahead;
+
+ for(k=0;k<input_size-ahead;k++)
+ work[k]=cachea[k]*cachea[k];
+
+ for(k=0;k<ahead;k++)
+ worka[k]=B[k]*B[k];
+ }else{
+
+ for(k=0;k<input_size;k++)
+ work[k]=cachea[k]*cachea[k];
+
+ }
+ }
+
+}
+
+void bi_compand(float *A,float *B,float *adj,
+ float corner,
+ float multiplier,
+ float currmultiplier,
+ float lookahead,
+ int mode,int softknee,
+ iir_filter *attack, iir_filter *decay,
+ iir_state *iir, peak_state *ps,
+ int active,
+ int over){
+
+ float work[input_size];
+ float kneelevel=fromdB(corner*2);
+ int hold,ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
+
+ if(ahead>input_size)ahead=input_size;
+ hold=ahead*(1.-lookahead);
+ ahead*=lookahead;
+
+ fill_work(A,B,work,ahead,hold,mode,ps);
+
+ multiplier*=.5;
+ currmultiplier*=.5;
+
+ if(!active || !adj)adj=work;
+
+ if(over){
+ if(multiplier!=currmultiplier){
+ if(softknee){
+ compute_iir_over_soft_del(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, currmultiplier, adj);
+ }else{
+ compute_iir_over_hard_del(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, currmultiplier, adj);
+ }
+ }else{
+ if(softknee){
+ compute_iir_over_soft(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, adj);
+ }else{
+ compute_iir_over_hard(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, adj);
+ }
+ }
+ }else{
+ if(multiplier!=currmultiplier){
+ if(softknee){
+ compute_iir_under_soft_del(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, currmultiplier, adj);
+ }else{
+ compute_iir_under_hard_del(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, currmultiplier, adj);
+ }
+ }else{
+ if(softknee){
+ compute_iir_under_soft(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, adj);
+ }else{
+ compute_iir_under_hard(work, input_size, iir, attack, decay,
+ kneelevel, multiplier, adj);
+ }
+ }
+ }
+
+}
+
+void full_compand(float *A,float *B,float *adj,
+ float multiplier,float currmultiplier,
+ int mode,
+ iir_filter *attack, iir_filter *decay,
+ iir_state *iir, peak_state *ps,
+ int active){
+
+ int k;
+ float work[input_size];
+ int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
+
+ fill_work(A,B,work,ahead,0,mode,ps);
+
+ multiplier*=.5;
+ currmultiplier*=.5;
+
+ compute_iir_symmetric_limited(work, input_size, iir, attack, decay);
+
+ if(active){
+ if(multiplier!=currmultiplier){
+ float multiplier_add=(currmultiplier-multiplier)/input_size;
+
+ for(k=0;k<input_size;k++){
+ adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;
+ multiplier+=multiplier_add;
+ }
+ }else{
+ for(k=0;k<input_size;k++)
+ adj[k]-=(todB_a2(work[k])+adj[k])*multiplier;
+ }
+ }
+}
Added: trunk/postfish/follower.h
===================================================================
--- trunk/postfish/follower.h 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/follower.h 2004-10-16 20:57:39 UTC (rev 8033)
@@ -0,0 +1,47 @@
+/*
+ *
+ * postfish
+ *
+ * Copyright (C) 2002-2004 Monty
+ *
+ * Postfish is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Postfish is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Postfish; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include "bessel.h"
+
+typedef struct {
+ int loc;
+ float val;
+} peak_state;
+
+extern void bi_compand(float *A,float *B,float *adj,
+ float corner,
+ float multiplier,
+ float currmultiplier,
+ float lookahead,
+ int mode,int softknee,
+ iir_filter *attack, iir_filter *decay,
+ iir_state *iir, peak_state *ps,
+ int active,
+ int over);
+
+extern void full_compand(float *A,float *B,float *adj,
+ float multiplier,float currmultiplier,
+ int mode,
+ iir_filter *attack, iir_filter *decay,
+ iir_state *iir, peak_state *ps,
+ int active);
Modified: trunk/postfish/multicompand.c
===================================================================
--- trunk/postfish/multicompand.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/multicompand.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -26,8 +26,11 @@
#include "multicompand.h"
#include <fftw3.h>
#include "subband.h"
-#include "bessel.h"
+#include "follower.h"
+extern off_t offset;
+extern int offch;
+
/* feedback! */
typedef struct multicompand_feedback{
feedback_generic parent_class;
@@ -38,11 +41,6 @@
} multicompand_feedback;
typedef struct {
- int loc;
- float val;
-} peak_state;
-
-typedef struct {
sig_atomic_t static_u[multicomp_freqs_max];
sig_atomic_t under_ratio;
@@ -134,9 +132,12 @@
static void reset_filters_onech(multicompand_state *ms,int ch){
int i;
- ms->base_delay[ch]=2;
- ms->over_delay[ch]=2;
- ms->under_delay[ch]=2;
+ /* delays are only used to softstart individual filters that went
+ inactive at unity; the key is that we know they're starting from
+ mult of zero, which is not necessarily true at a reset */
+ ms->base_delay[ch]=0;
+ ms->over_delay[ch]=0;
+ ms->under_delay[ch]=0;
for(i=0;i<multicomp_freqs_max;i++){
memset(&ms->over_peak[i][ch],0,sizeof(peak_state));
memset(&ms->under_peak[i][ch],0,sizeof(peak_state));
@@ -249,218 +250,6 @@
}
-static void prepare_rms(float *rms, float *xx, int n, int ahead){
- int i;
- float *x=xx+ahead;
- for(i=0;i<n;i++)
- rms[i]+=x[i]*x[i];
-}
-
-static void prepare_peak(float *peak, float *x, int n, int ahead,
- peak_state *ps){
- int ii,jj;
- int loc=ps->loc;
- float val=ps->val;
-
- /* Although we have two input_size blocks of zeroes after a
- reset, we may still need to look ahead explicitly after a
- reset if the lookahead is exceptionally long */
-
- if(loc==0 && val==0){
- for(ii=0;ii<ahead;ii++)
- if((x[ii]*x[ii])>val){
- val=(x[ii]*x[ii]);
- loc=ii;
- }
- }
-
- if(val>peak[0])peak[0]=val;
-
- for(ii=1;ii<n;ii++){
- if((x[ii+ahead]*x[ii+ahead])>val){
- val=(x[ii+ahead]*x[ii+ahead]);
- loc=ii+ahead;
- }
- if(ii>=loc){
- /* backfill */
- val=0;
- for(jj=ii+ahead-1;jj>=ii;jj--){
- if((x[jj]*x[jj])>val)val=(x[jj]*x[jj]);
- if(jj<n && val>peak[jj])peak[jj]=val;
- }
- val=(x[ii+ahead]*x[ii+ahead]);
- loc=ii+ahead;
- }
- if(val>peak[ii])peak[ii]=val;
- }
-
- ps->loc=loc-input_size;
- ps->val=val;
-}
-
-static void run_filter(float *dB,float *x,int n,
- float lookahead,int mode,
- iir_state *iir,iir_filter *attack,iir_filter *decay,
- peak_state *ps){
- int i;
- memset(dB,0,sizeof(*dB)*n);
-
- if(mode){
- int ahead=step_ahead(attack->alpha)*lookahead;
- if(ahead>input_size*2)ahead=input_size*2;
-
- prepare_peak(dB, x, n, ahead, ps);
- compute_iir_freefall1_then_symmetric2(dB, n, iir, attack, decay);
-
- }else{
- int ahead=impulse_ahead2(attack->alpha)*lookahead;
- if(ahead>input_size*2)ahead=input_size*2;
- prepare_rms(dB, x, n, ahead);
- compute_iir_symmetric_limited(dB, n, iir, attack, decay);
-
- }
-
- for(i=0;i<n;i++)
- dB[i]=todB_a(dB+i)*.5f;
-
-}
-
-static float soft_knee(float x){
- return (sqrtf(x*x+30.f)+x)*-.5f;
-}
-
-static float hard_knee(float x){
- return (x>0.f?-x:0.f);
-}
-
-static void over_compand(float *lx,
- float zerocorner,
- float currcorner,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- float lookahead,int mode,int knee,
- float prevratio,
- float currratio,
- float *adj){
- int k;
- float overdB[input_size];
-
- run_filter(overdB,lx,input_size,lookahead,mode,iir,attack,decay,ps);
-
- if(adj){
- float ratio_multiplier= 1.- 1000./prevratio;
-
- if(zerocorner!=currcorner || prevratio!=currratio){
- /* slew limit these attenuators */
- float ratio_add= ((1.- 1000./currratio)-ratio_multiplier)/input_size;
- float corner_add= (currcorner-zerocorner)/input_size;
-
- if(knee){
- for(k=0;k<input_size;k++){
- adj[k]+=soft_knee(overdB[k]-zerocorner)*ratio_multiplier;
- ratio_multiplier+=ratio_add;
- zerocorner+=corner_add;
- }
- }else{
- for(k=0;k<input_size;k++){
- adj[k]+=hard_knee(overdB[k]-zerocorner)*ratio_multiplier;
- ratio_multiplier+=ratio_add;
- zerocorner+=corner_add;
- }
- }
- }else{
- if(knee){
- for(k=0;k<input_size;k++)
- adj[k]+=soft_knee(overdB[k]-zerocorner)*ratio_multiplier;
- }else{
- for(k=0;k<input_size;k++)
- adj[k]+=hard_knee(overdB[k]-zerocorner)*ratio_multiplier;
- }
- }
- }
-}
-
-static void base_compand(float *x,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- int mode,
- float prevratio,
- float currratio,
- float *adj){
- int k;
- float basedB[input_size];
-
- run_filter(basedB,x,input_size,1.,mode,
- iir,attack,decay,ps);
-
- if(adj){
- float ratio_multiplier=1.-1000./prevratio;
-
- if(prevratio!=currratio){
- /* slew limit the attenuators */
- float ratio_add= ((1.- 1000./currratio)-ratio_multiplier)/input_size;
-
- for(k=0;k<input_size;k++){
- adj[k]-=(basedB[k]+adj[k])*ratio_multiplier;
- ratio_multiplier+=ratio_add;
- }
-
- }else{
- for(k=0;k<input_size;k++)
- adj[k]-=(basedB[k]+adj[k])*ratio_multiplier;
- }
- }
-}
-
-static void under_compand(float *x,
- float zerocorner,
- float currcorner,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- float lookahead,int mode,int knee,
- float prevratio,
- float currratio,
- float *adj){
- int k;
- float underdB[input_size];
-
- run_filter(underdB,x,input_size,lookahead,mode,
- iir,attack,decay,ps);
-
- if(adj){
- float ratio_multiplier=1000./prevratio - 1.;
-
- if(zerocorner!=currcorner || prevratio!=currratio){
- /* slew limit these attenuators */
- float ratio_add= ((1000./currratio - 1.)-ratio_multiplier)/input_size;
- float corner_add= (currcorner-zerocorner)/input_size;
-
- if(knee){
- for(k=0;k<input_size;k++){
- adj[k]+=soft_knee(zerocorner-underdB[k])*ratio_multiplier;
- ratio_multiplier+=ratio_add;
- zerocorner+=corner_add;
- }
- }else{
- for(k=0;k<input_size;k++){
- adj[k]+=hard_knee(zerocorner-underdB[k])*ratio_multiplier;
- ratio_multiplier+=ratio_add;
- zerocorner+=corner_add;
- }
- }
-
- }else{
- if(knee){
- for(k=0;k<input_size;k++)
- adj[k]+=soft_knee(zerocorner-underdB[k])*ratio_multiplier;
- }else{
- for(k=0;k<input_size;k++)
- adj[k]+=hard_knee(zerocorner-underdB[k])*ratio_multiplier;
- }
- }
- }
-}
-
static int find_maxbands(subband_state *ss,int channel){
int maxbands=ss->wC[channel]->freq_bands;
if(maxbands<ss->w0[channel]->freq_bands)maxbands=ss->w0[channel]->freq_bands;
@@ -567,35 +356,39 @@
memset(adj,0,sizeof(*adj)*input_size);
if(u_active)
- under_compand(x,
- prevset->static_u[i],
- currset->static_u[i],
- &ms->under_attack[channel],
- &ms->under_decay[channel],
- &ms->under_iir[i][channel],
- &ms->under_peak[i][channel],
- c->under_lookahead/1000.,
- c->under_mode,
- c->under_softknee,
- prevset->under_ratio,
- currset->under_ratio,
- (i>=w->freq_bands?0:adj));
-
- if(o_active)
- over_compand(x,
- prevset->static_o[i],
- currset->static_o[i],
- &ms->over_attack[channel],
- &ms->over_decay[channel],
- &ms->over_iir[i][channel],
- &ms->over_peak[i][channel],
- c->over_lookahead/1000.,
- c->over_mode,
- c->over_softknee,
- prevset->over_ratio,
- currset->over_ratio,
- (i>=w->freq_bands?0:adj));
+ bi_compand(x,0,(i>=w->freq_bands?0:adj),
+ //prevset->static_u[i],
+ currset->static_u[i],
+ 1.f-1000.f/prevset->under_ratio,
+ 1.f-1000.f/currset->under_ratio,
+ c->under_lookahead/1000.f,
+ c->under_mode,
+ c->under_softknee,
+ &ms->under_attack[channel],
+ &ms->under_decay[channel],
+ &ms->under_iir[i][channel],
+ &ms->under_peak[i][channel],
+ ss->effect_active1[channel] &&
+ (i<w->freq_bands),
+ 0);
+ if(o_active)
+ bi_compand(x,0,(i>=w->freq_bands?0:adj),
+ //prevset->static_o[i],
+ currset->static_o[i],
+ 1.f-1000.f/prevset->over_ratio,
+ 1.f-1000.f/currset->over_ratio,
+ c->over_lookahead/1000.f,
+ c->over_mode,
+ c->over_softknee,
+ &ms->over_attack[channel],
+ &ms->over_decay[channel],
+ &ms->over_iir[i][channel],
+ &ms->over_peak[i][channel],
+ ss->effect_active1[channel] &&
+ (i<w->freq_bands),
+ 1);
+
if(ss->visible1[channel]){
feedback_p=1;
@@ -613,7 +406,7 @@
}
rms+=val;
}
- if(active){
+ if(u_active || o_active || b_active){
peakfeed[i][channel]=todB(max)*.5+adj[maxpos];
rmsfeed[i][channel]=todB(rms/input_size)*.5+adj[maxpos];
}else{
@@ -624,15 +417,16 @@
}
if(b_active)
- base_compand(x,
+ full_compand(x,0,(i>=w->freq_bands?0:adj),
+ 1.f-1000.f/prevset->base_ratio,
+ 1.f-1000.f/currset->base_ratio,
+ c->base_mode,
&ms->base_attack[channel],
&ms->base_decay[channel],
&ms->base_iir[i][channel],
&ms->base_peak[i][channel],
- c->base_mode,
- prevset->base_ratio,
- currset->base_ratio,
- (i>=w->freq_bands?0:adj));
+ ss->effect_active1[channel] &&
+ i<w->freq_bands);
if(u_active || o_active || b_active){
if(ss->effect_active1[channel]){
Modified: trunk/postfish/outpanel.c
===================================================================
--- trunk/postfish/outpanel.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/outpanel.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -81,7 +81,8 @@
config_get_sigat("output_monitor_set",bank,0,0,0,0,&outset.monitor.device);
/* don't set a device that doesn't exist */
- if(state.monitor.device && outset.monitor.device<monitor_entries)
+ if(outset.monitor.device>=monitor_entries)outset.monitor.device=monitor_entries-1;
+ if(state.monitor.device)
gtk_combo_box_set_active(GTK_COMBO_BOX(state.monitor.device),outset.monitor.device);
config_get_sigat("output_monitor_set",bank,0,0,0,1,&outset.monitor.bytes);
Modified: trunk/postfish/postfish.h
===================================================================
--- trunk/postfish/postfish.h 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/postfish.h 2004-10-16 20:57:39 UTC (rev 8033)
@@ -85,10 +85,15 @@
#ifdef UGLY_IEEE754_FLOAT32_HACK
-static inline float todB_a(const float *x){
- return (float)((*(int32_t *)x)&0x7fffffff) * 7.17711438e-7f -764.6161886f;
+static inline float todB_a(float x){
+ return (float)((*((int32_t *)&x))&0x7fffffff) * 7.17711438e-7f -764.6161886f;
}
+// eliminate a *.5 in ops on sq magnitudes
+static inline float todB_a2(float x){
+ return (float)((*((int32_t *)&x))&0x7fffffff) * 3.58855719e-7f -382.3080943f;
+}
+
static inline float fromdB_a(float x){
int y=(x < -300 ? 0 : 1.39331762961e+06f*(x+764.6161886f));
return *(float *)&y;
Modified: trunk/postfish/singlecomp.c
===================================================================
--- trunk/postfish/singlecomp.c 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/singlecomp.c 2004-10-16 20:57:39 UTC (rev 8033)
@@ -24,7 +24,7 @@
#include "postfish.h"
#include "feedback.h"
#include "window.h"
-#include "bessel.h"
+#include "follower.h"
#include "singlecomp.h"
extern int input_size;
@@ -32,11 +32,6 @@
extern int input_ch;
typedef struct {
- int loc;
- float val;
-} peak_state;
-
-typedef struct {
sig_atomic_t u_thresh;
sig_atomic_t u_ratio;
@@ -191,12 +186,19 @@
memset(scs->o_peak+i,0,sizeof(*scs->o_peak));
memset(scs->u_peak+i,0,sizeof(*scs->u_peak));
memset(scs->b_peak+i,0,sizeof(*scs->b_peak));
+
+ /* all filters are set to 0, even the ones that steady-state at one,
+ because we know that our steepest attack will complete in the
+ pre-charge time, but there's no such guarantee about decay */
memset(scs->o_iir+i,0,sizeof(*scs->o_iir));
memset(scs->u_iir+i,0,sizeof(*scs->u_iir));
memset(scs->b_iir+i,0,sizeof(*scs->b_iir));
- scs->o_delay[i]=1;
- scs->u_delay[i]=1;
- scs->b_delay[i]=1;
+
+ /* delays are only used for soft-starting individual filters when we
+ know things began at unity multiplier */
+ scs->o_delay[i]=0;
+ scs->u_delay[i]=0;
+ scs->b_delay[i]=0;
}
static void reset_filter(singlecomp_state *scs){
@@ -218,241 +220,6 @@
return 0;
}
-static void prepare_peak(float *peak, float *x, int n, int ahead,
- peak_state *ps){
- int ii,jj;
- int loc=ps->loc;
- float val=ps->val;
-
- /* Although we have two input_size blocks of zeroes after a
- reset, we may still need to look ahead explicitly after a
- reset if the lookahead is exceptionally long */
-
- if(loc==0 && val==0){
- for(ii=0;ii<ahead;ii++)
- if((x[ii]*x[ii])>val){
- val=(x[ii]*x[ii]);
- loc=ii;
- }
- }
-
- if(val>peak[0])peak[0]=val;
-
- for(ii=1;ii<n;ii++){
- if((x[ii+ahead]*x[ii+ahead])>val){
- val=(x[ii+ahead]*x[ii+ahead]);
- loc=ii+ahead;
- }
- if(ii>=loc){
- /* backfill */
- val=0;
- for(jj=ii+ahead-1;jj>=ii;jj--){
- if((x[jj]*x[jj])>val)val=(x[jj]*x[jj]);
- if(jj<n && val>peak[jj])peak[jj]=val;
- }
- val=(x[ii+ahead]*x[ii+ahead]);
- loc=ii+ahead;
- }
- if(val>peak[ii])peak[ii]=val;
- }
-
- ps->loc=loc-input_size;
- ps->val=val;
-}
-
-#if 0
-static void _analysis(char *base,int seq, float *data, int n,int dB,
- off_t offset){
-
- FILE *f;
- char buf[80];
- sprintf(buf,"%s_%d.m",base,seq);
-
- f=fopen(buf,"a");
- if(f){
- int i;
- for(i=0;i<n;i++)
- if(dB)
- fprintf(f,"%d %f\n",(int)(i+offset),todB(data[i]));
- else
- fprintf(f,"%d %f\n",(int)(i+offset),(data[i]));
-
- }
- fclose(f);
-}
-
-static int seq=0;
-static int offch;
-#endif
-
-static void run_filter(float *cache, float *in, float *work,
- int ahead,int mode,
- iir_state *iir,
- iir_filter *attack,
- iir_filter *decay,
- peak_state *ps){
- int k;
-
- if(mode){
- /* peak mode */
- float bigcache[input_size*2];
- memcpy(bigcache,cache,sizeof(*work)*input_size);
- memcpy(bigcache+input_size,in,sizeof(*work)*input_size);
-
- memset(work,0,sizeof(*work)*input_size);
- prepare_peak(work, bigcache, input_size, ahead, ps);
-
- compute_iir_freefall1_then_symmetric2(work, input_size, iir, attack, decay);
-
- }else{
- /* rms mode */
- float *cachea=cache+ahead;
- float *worka=work+input_size-ahead;
-
- for(k=0;k<input_size-ahead;k++)
- work[k]=cachea[k]*cachea[k];
-
- for(k=0;k<ahead;k++)
- worka[k]=in[k]*in[k];
-
- compute_iir_symmetric_limited(work, input_size, iir, attack, decay);
-
- }
-
- for(k=0;k<input_size;k++)
- work[k]=todB_a(work+k)*.5f;
-}
-
-static float soft_knee(float x){
- return (sqrtf(x*x+30.f)+x)*-.5f;
-}
-
-static float hard_knee(float x){
- return (x>0.f?-x:0.f);
-}
-
-static void over_compand(float *A,float *B,float *adj,
- float zerocorner,
- float currcorner,
- float multiplier,
- float currmultiplier,
- float lookahead,int mode,int softknee,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- int active){
-
- int k;
- float work[input_size*2];
- int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha))*lookahead;
- if(ahead>input_size)ahead=input_size;
-
- run_filter(A,B,work,ahead,mode,iir,attack,decay,ps);
-
- if(active){
- if(multiplier!=currmultiplier || zerocorner!=currcorner){
- float multiplier_add=(currmultiplier-multiplier)/input_size;
- float zerocorner_add=(currcorner-zerocorner)/input_size;
-
- if(softknee){
- for(k=0;k<input_size;k++){
- adj[k]+=soft_knee(work[k]-zerocorner)*multiplier;
- multiplier+=multiplier_add;
- zerocorner+=zerocorner_add;
- }
- }else{
- for(k=0;k<input_size;k++){
- adj[k]+=hard_knee(work[k]-zerocorner)*multiplier;
- multiplier+=multiplier_add;
- zerocorner+=zerocorner_add;
- }
- }
-
- }else{
- if(softknee){
- for(k=0;k<input_size;k++)
- adj[k]+=soft_knee(work[k]-zerocorner)*multiplier;
- }else{
- for(k=0;k<input_size;k++)
- adj[k]+=hard_knee(work[k]-zerocorner)*multiplier;
- }
- }
- }
-}
-
-static void under_compand(float *A,float *B,float *adj,
- float zerocorner,float currcorner,
- float multiplier,float currmultiplier,
- float lookahead,int mode,int softknee,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- int active){
- int k;
- float work[input_size*2];
- int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha))*lookahead;
- if(ahead>input_size)ahead=input_size;
-
- run_filter(A,B,work,ahead,mode,iir,attack,decay,ps);
-
- if(active){
- if(multiplier!=currmultiplier || zerocorner!=currcorner){
- float multiplier_add=(currmultiplier-multiplier)/input_size;
- float zerocorner_add=(currcorner-zerocorner)/input_size;
-
- if(softknee){
- for(k=0;k<input_size;k++){
- adj[k]+= -soft_knee(zerocorner-work[k])*multiplier;
- multiplier+=multiplier_add;
- zerocorner+=zerocorner_add;
- }
- }else{
- for(k=0;k<input_size;k++){
- adj[k]+= -hard_knee(zerocorner-work[k])*multiplier;
- multiplier+=multiplier_add;
- zerocorner+=zerocorner_add;
- }
- }
-
- }else{
- if(softknee){
- for(k=0;k<input_size;k++)
- adj[k]+= -soft_knee(zerocorner-work[k])*multiplier;
- }else{
- for(k=0;k<input_size;k++)
- adj[k]+= -hard_knee(zerocorner-work[k])*multiplier;
- }
- }
- }
-
-}
-
-static void base_compand(float *A,float *B,float *adj,
- float multiplier,float currmultiplier,
- int mode,
- iir_filter *attack, iir_filter *decay,
- iir_state *iir, peak_state *ps,
- int active){
-
- int k;
- float work[input_size*2];
- int ahead=(mode?step_ahead(attack->alpha):impulse_ahead2(attack->alpha));
-
- run_filter(A,B,work,ahead,mode,iir,attack,decay,ps);
-
- if(active){
- if(multiplier!=currmultiplier){
- float multiplier_add=(currmultiplier-multiplier)/input_size;
-
- for(k=0;k<input_size;k++){
- adj[k]-=(work[k]+adj[k])*multiplier;
- multiplier+=multiplier_add;
- }
- }else{
- for(k=0;k<input_size;k++)
- adj[k]-=(work[k]+adj[k])*multiplier;
- }
- }
-}
-
static void work_and_lapping(singlecomp_state *scs,
singlecomp_settings **scset,
time_linkage *in,
@@ -497,7 +264,9 @@
if(!active0 && !activeC){
- if(activeP) reset_onech_filter(scs,i); /* just became inactive; reset all filters for this channel */
+ if(activeP) reset_onech_filter(scs,i); /* just became inactive;
+ reset all filters for
+ this channel */
/* feedback */
if(scset[i]->panel_visible){
@@ -514,9 +283,9 @@
if(peak<val)peak=val;
}
}
- peakfeed[i]=todB_a(&peak)*.5;
+ peakfeed[i]=todB_a(peak)*.5;
rms/=input_size;
- rmsfeed[i]=todB_a(&rms)*.5;
+ rmsfeed[i]=todB_a(rms)*.5;
}
/* rotate data vectors */
@@ -539,13 +308,12 @@
currset->b_ratio=scset[i]->b_ratio;
/* don't slew from an unknown value */
-
if(!activeP || !scs->fillstate)
memcpy(prevset,currset,sizeof(*currset));
-
+
/* don't run filters that will be applied at unity */
if(prevset->u_ratio==1000 && currset->u_ratio==1000){
- scs->u_delay[i]=2;
+ scs->u_delay[i]=1;
memset(scs->u_peak+i,0,sizeof(peak_state));
memset(scs->u_iir+i,0,sizeof(iir_state));
}else{
@@ -555,7 +323,7 @@
}
if(prevset->o_ratio==1000 && currset->o_ratio==1000){
- scs->o_delay[i]=2;
+ scs->o_delay[i]=1;
memset(scs->o_peak+i,0,sizeof(peak_state));
memset(scs->o_iir+i,0,sizeof(iir_state));
}else{
@@ -565,7 +333,7 @@
}
if(prevset->b_ratio==1000 && currset->b_ratio==1000){
- scs->b_delay[i]=2;
+ scs->b_delay[i]=1;
memset(scs->b_peak+i,0,sizeof(peak_state));
memset(scs->b_iir+i,0,sizeof(iir_state));
}else{
@@ -573,36 +341,37 @@
if(scs->b_delay[i]<0)scs->b_delay[i]=0;
b_active=1;
}
-
+
/* run the filters */
memset(adj,0,sizeof(*adj)*input_size);
if(u_active)
- under_compand(scs->cache[i],in->data[i],adj,
- scs->prevset[i].u_thresh,
- scs->currset[i].u_thresh,
- 1.-1000./scs->prevset[i].u_ratio,
- 1.-1000./scs->currset[i].u_ratio,
- scset[i]->u_lookahead/1000.,
- scset[i]->u_mode,
- scset[i]->u_softknee,
- scs->u_attack+i,scs->u_decay+i,
- scs->u_iir+i,scs->u_peak+i,
- active0);
+ bi_compand(scs->cache[i],in->data[i],adj,
+ //scs->prevset[i].u_thresh,
+ scs->currset[i].u_thresh,
+ 1.f-1000./scs->prevset[i].u_ratio,
+ 1.f-1000./scs->currset[i].u_ratio,
+ scset[i]->u_lookahead/1000.f,
+ scset[i]->u_mode,
+ scset[i]->u_softknee,
+ scs->u_attack+i,scs->u_decay+i,
+ scs->u_iir+i,scs->u_peak+i,
+ active0,0);
if(o_active)
- over_compand(scs->cache[i],in->data[i],adj,
- scs->prevset[i].o_thresh,
- scs->currset[i].o_thresh,
- 1.-1000./scs->prevset[i].o_ratio,
- 1.-1000./scs->currset[i].o_ratio,
- scset[i]->o_lookahead/1000.,
- scset[i]->o_mode,
- scset[i]->o_softknee,
- scs->o_attack+i,scs->o_decay+i,
- scs->o_iir+i,scs->o_peak+i,
- active0);
+ bi_compand(scs->cache[i],in->data[i],adj,
+ //scs->prevset[i].o_thresh,
+ scs->currset[i].o_thresh,
+ 1.f-1000.f/scs->prevset[i].o_ratio,
+ 1.f-1000.f/scs->currset[i].o_ratio,
+ scset[i]->o_lookahead/1000.f,
+ scset[i]->o_mode,
+ scset[i]->o_softknee,
+ scs->o_attack+i,scs->o_decay+i,
+ scs->o_iir+i,scs->o_peak+i,
+ active0,1);
+
/* feedback before base */
if(scset[i]->panel_visible){
int k;
@@ -622,16 +391,16 @@
}
}
- peakfeed[i]=todB_a(&peak)*.5;
+ peakfeed[i]=todB_a(peak)*.5;
rms/=input_size;
- rmsfeed[i]=todB_a(&rms)*.5;
+ rmsfeed[i]=todB_a(rms)*.5;
}
if(b_active)
- base_compand(scs->cache[i],in->data[i],adj,
+ full_compand(scs->cache[i],in->data[i],adj,
1.-1000./scs->prevset[i].b_ratio,
1.-1000./scs->currset[i].b_ratio,
- scset[i]->b_mode,
+ scset[i]->b_mode,
scs->b_attack+i,scs->b_decay+i,
scs->b_iir+i,scs->b_peak+i,
active0);
@@ -785,6 +554,6 @@
/* local copy required to avoid concurrency problems */
for(i=0;i<channel_state.ch;i++)
active[i]=singlecomp_channel_set[i].panel_active;
-
+
return singlecomp_read_helper(in, &channel_state, channel_set_bundle,active);
}
Modified: trunk/postfish/version.h
===================================================================
--- trunk/postfish/version.h 2004-10-16 18:05:24 UTC (rev 8032)
+++ trunk/postfish/version.h 2004-10-16 20:57:39 UTC (rev 8033)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Mon Oct 11 22:10:04 EDT 2004] */
+/* DO NOT EDIT: Automated versioning hack [Sat Oct 16 17:09:50 EDT 2004] */
More information about the commits
mailing list