[xiph-cvs] r6573 - trunk/postfish
xiphmont at xiph.org
xiphmont at xiph.org
Tue May 4 21:25:28 PDT 2004
Author: xiphmont
Date: 2004-04-22 05:31:18 -0400 (Thu, 22 Apr 2004)
New Revision: 6573
Modified:
trunk/postfish/compandpanel.c
trunk/postfish/freq.c
trunk/postfish/multicompand.c
trunk/postfish/multicompand.h
trunk/postfish/singlecomp.c
trunk/postfish/subband.c
trunk/postfish/subband.h
trunk/postfish/suppress.c
trunk/postfish/version.h
Log:
Major signal path upgrade to subband.c:
eliminate all clicks/thumps/dropouts on realtime interaction
implement mute infrastructure
active/visible by channel
<p><p>Modified: trunk/postfish/compandpanel.c
===================================================================
--- trunk/postfish/compandpanel.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/compandpanel.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -226,6 +226,7 @@
cbar *b=(cbar *)in;
int o,u;
int i;
+ int adj;
u=multibar_get_value(MULTIBAR(b->slider),0);
sprintf(buffer,"%+4ddB",u);
@@ -246,101 +247,98 @@
bc[2].static_o[0]+=o-bc[2].static_o[1];
bc[2].static_u[0]+=u-bc[2].static_u[1];
}
- if (b->number<9){
- int adj;
-
- /* convolutions for roundoff behavior */
- if(b->number>0){
- adj=(bc[1].static_o[b->number*2-1]*2 -
- bc[1].static_o[b->number*2-2]-bc[1].static_o[b->number*2])/2;
- bc[1].static_o[b->number*2-1]=
+
+ /* convolutions for roundoff behavior */
+ if(b->number>0){
+ adj=(bc[1].static_o[b->number*2-1]*2 -
+ bc[1].static_o[b->number*2-2]-bc[1].static_o[b->number*2])/2;
+ bc[1].static_o[b->number*2-1]=
(bc[1].static_o[b->number*2-2]+o)/2+adj;
-
- adj=(bc[1].static_u[b->number*2-1]*2 -
- bc[1].static_u[b->number*2-2]-bc[1].static_u[b->number*2])/2;
- bc[1].static_u[b->number*2-1]=
- (bc[1].static_u[b->number*2-2]+u)/2+adj;
-
- adj=(bc[2].static_o[b->number*3-1]*3 -
- bc[2].static_o[b->number*3-2] -
- bc[2].static_o[b->number*3-2] -
- bc[2].static_o[b->number*3+1])/3;
- bc[2].static_o[b->number*3-1]=
- (bc[2].static_o[b->number*3-2]+
- bc[2].static_o[b->number*3-2]+
- o)/3+adj;
-
- adj=(bc[2].static_o[b->number*3]*3 -
- bc[2].static_o[b->number*3-2] -
- bc[2].static_o[b->number*3+1] -
- bc[2].static_o[b->number*3+1])/3;
- bc[2].static_o[b->number*3]=
- (bc[2].static_o[b->number*3-2]+o+o)/3+adj;
-
- adj=(bc[2].static_u[b->number*3-1]*3 -
- bc[2].static_u[b->number*3-2] -
- bc[2].static_u[b->number*3-2] -
- bc[2].static_u[b->number*3+1])/3;
- bc[2].static_u[b->number*3-1]=
- (bc[2].static_u[b->number*3-2]+
- bc[2].static_u[b->number*3-2]+
- u)/3+adj;
-
- adj=(bc[2].static_u[b->number*3]*3 -
- bc[2].static_u[b->number*3-2] -
- bc[2].static_u[b->number*3+1] -
- bc[2].static_u[b->number*3+1])/3;
- bc[2].static_u[b->number*3]=
- (bc[2].static_u[b->number*3-2]+u+u)/3+adj;
-
- }
-
- if(b->number<9){
- adj=(bc[1].static_o[b->number*2+1]*2-
- bc[1].static_o[b->number*2+2]-bc[1].static_o[b->number*2])/2;
- bc[1].static_o[b->number*2+1]=
- (bc[1].static_o[b->number*2+2]+o)/2+adj;
-
- adj=(bc[1].static_u[b->number*2+1]*2-
- bc[1].static_u[b->number*2+2]-bc[1].static_u[b->number*2])/2;
- bc[1].static_u[b->number*2+1]=
- (bc[1].static_u[b->number*2+2]+u)/2+adj;
-
- adj=(bc[2].static_o[b->number*3+3]*3 -
- bc[2].static_o[b->number*3+4] -
- bc[2].static_o[b->number*3+4] -
- bc[2].static_o[b->number*3+1])/3;
- bc[2].static_o[b->number*3+3]=
- (bc[2].static_o[b->number*3+4]+
- bc[2].static_o[b->number*3+4]+
- o)/3+adj;
-
- adj=(bc[2].static_o[b->number*3+2]*3 -
- bc[2].static_o[b->number*3+4] -
- bc[2].static_o[b->number*3+1] -
- bc[2].static_o[b->number*3+1])/3;
- bc[2].static_o[b->number*3+2]=
- (bc[2].static_o[b->number*3+4]+o+o)/3+adj;
-
- adj=(bc[2].static_u[b->number*3+3]*3 -
- bc[2].static_u[b->number*3+4] -
- bc[2].static_u[b->number*3+4] -
- bc[2].static_u[b->number*3+1])/3;
- bc[2].static_u[b->number*3+3]=
- (bc[2].static_u[b->number*3+4]+
- bc[2].static_u[b->number*3+4]+
- u)/3+adj;
-
- adj=(bc[2].static_u[b->number*3+2]*3 -
- bc[2].static_u[b->number*3+4] -
- bc[2].static_u[b->number*3+1] -
- bc[2].static_u[b->number*3+1])/3;
- bc[2].static_u[b->number*3+2]=
- (bc[2].static_u[b->number*3+4]+u+u)/3+adj;
-
- }
+
+ adj=(bc[1].static_u[b->number*2-1]*2 -
+ bc[1].static_u[b->number*2-2]-bc[1].static_u[b->number*2])/2;
+ bc[1].static_u[b->number*2-1]=
+ (bc[1].static_u[b->number*2-2]+u)/2+adj;
+
+ adj=(bc[2].static_o[b->number*3-1]*3 -
+ bc[2].static_o[b->number*3-2] -
+ bc[2].static_o[b->number*3-2] -
+ bc[2].static_o[b->number*3+1])/3;
+ bc[2].static_o[b->number*3-1]=
+ (bc[2].static_o[b->number*3-2]+
+ bc[2].static_o[b->number*3-2]+
+ o)/3+adj;
+
+ adj=(bc[2].static_o[b->number*3]*3 -
+ bc[2].static_o[b->number*3-2] -
+ bc[2].static_o[b->number*3+1] -
+ bc[2].static_o[b->number*3+1])/3;
+ bc[2].static_o[b->number*3]=
+ (bc[2].static_o[b->number*3-2]+o+o)/3+adj;
+
+ adj=(bc[2].static_u[b->number*3-1]*3 -
+ bc[2].static_u[b->number*3-2] -
+ bc[2].static_u[b->number*3-2] -
+ bc[2].static_u[b->number*3+1])/3;
+ bc[2].static_u[b->number*3-1]=
+ (bc[2].static_u[b->number*3-2]+
+ bc[2].static_u[b->number*3-2]+
+ u)/3+adj;
+
+ adj=(bc[2].static_u[b->number*3]*3 -
+ bc[2].static_u[b->number*3-2] -
+ bc[2].static_u[b->number*3+1] -
+ bc[2].static_u[b->number*3+1])/3;
+ bc[2].static_u[b->number*3]=
+ (bc[2].static_u[b->number*3-2]+u+u)/3+adj;
+
}
-
+
+ if(b->number<9){
+ adj=(bc[1].static_o[b->number*2+1]*2-
+ bc[1].static_o[b->number*2+2]-bc[1].static_o[b->number*2])/2;
+ bc[1].static_o[b->number*2+1]=
+ (bc[1].static_o[b->number*2+2]+o)/2+adj;
+
+ adj=(bc[1].static_u[b->number*2+1]*2-
+ bc[1].static_u[b->number*2+2]-bc[1].static_u[b->number*2])/2;
+ bc[1].static_u[b->number*2+1]=
+ (bc[1].static_u[b->number*2+2]+u)/2+adj;
+
+ adj=(bc[2].static_o[b->number*3+3]*3 -
+ bc[2].static_o[b->number*3+4] -
+ bc[2].static_o[b->number*3+4] -
+ bc[2].static_o[b->number*3+1])/3;
+ bc[2].static_o[b->number*3+3]=
+ (bc[2].static_o[b->number*3+4]+
+ bc[2].static_o[b->number*3+4]+
+ o)/3+adj;
+
+ adj=(bc[2].static_o[b->number*3+2]*3 -
+ bc[2].static_o[b->number*3+4] -
+ bc[2].static_o[b->number*3+1] -
+ bc[2].static_o[b->number*3+1])/3;
+ bc[2].static_o[b->number*3+2]=
+ (bc[2].static_o[b->number*3+4]+o+o)/3+adj;
+
+ adj=(bc[2].static_u[b->number*3+3]*3 -
+ bc[2].static_u[b->number*3+4] -
+ bc[2].static_u[b->number*3+4] -
+ bc[2].static_u[b->number*3+1])/3;
+ bc[2].static_u[b->number*3+3]=
+ (bc[2].static_u[b->number*3+4]+
+ bc[2].static_u[b->number*3+4]+
+ u)/3+adj;
+
+ adj=(bc[2].static_u[b->number*3+2]*3 -
+ bc[2].static_u[b->number*3+4] -
+ bc[2].static_u[b->number*3+1] -
+ bc[2].static_u[b->number*3+1])/3;
+ bc[2].static_u[b->number*3+2]=
+ (bc[2].static_u[b->number*3+4]+u+u)/3+adj;
+
+ }
+
if(b->number==9){
bc[1].static_o[19]+=o-bc[1].static_o[18];
bc[1].static_u[19]+=u-bc[1].static_u[18];
@@ -461,7 +459,8 @@
gtk_widget_hide(bars[i].readoutu);
}
}
- multicompand_set_bank(bank_active);
+
+ c.active_bank=bank_active;
}
}
Modified: trunk/postfish/freq.c
===================================================================
--- trunk/postfish/freq.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/freq.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -476,6 +476,7 @@
break;
case 3: /* we've pushed out EOF already */
f->out.samples=0;
+ return &f->out;
}
/* finish up the state feedabck */
Modified: trunk/postfish/multicompand.c
===================================================================
--- trunk/postfish/multicompand.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/multicompand.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -32,23 +32,33 @@
extern int input_rate;
extern int input_ch;
+/* feedback! */
+typedef struct multicompand_feedback{
+ feedback_generic parent_class;
+ float **peak;
+ float **rms;
+ int freq_bands;
+ int bypass;
+} multicompand_feedback;
+
typedef struct {
int loc;
float val;
} peak_state;
typedef struct {
+ feedback_generic_pool feedpool;
subband_state ss;
subband_window sw[multicomp_banks];
- iir_filter over_attack[multicomp_banks][multicomp_freqs_max];
- iir_filter over_decay[multicomp_banks][multicomp_freqs_max];
+ iir_filter over_attack;
+ iir_filter over_decay;
- iir_filter under_attack[multicomp_banks][multicomp_freqs_max];
- iir_filter under_decay[multicomp_banks][multicomp_freqs_max];
+ iir_filter under_attack;
+ iir_filter under_decay;
- iir_filter base_attack[multicomp_banks][multicomp_freqs_max];
- iir_filter base_decay[multicomp_banks][multicomp_freqs_max];
+ iir_filter base_attack;
+ iir_filter base_decay;
iir_state *over_iir[multicomp_freqs_max];
iir_state *under_iir[multicomp_freqs_max];
@@ -58,9 +68,8 @@
peak_state *under_peak[multicomp_freqs_max];
peak_state *base_peak[multicomp_freqs_max];
- sig_atomic_t pending_bank;
- sig_atomic_t active_bank;
-
+ float **peak;
+ float **rms;
} multicompand_state;
sig_atomic_t compand_visible;
@@ -71,26 +80,66 @@
static multicompand_state ms;
-int pull_multicompand_feedback(float **peak,float **rms,int *bands){
- return pull_subband_feedback(&ms.ss,peak,rms,bands);
+static feedback_generic *new_multicompand_feedback(void){
+ int i;
+ multicompand_feedback *ret=calloc(1,sizeof(*ret));
+
+ ret->peak=malloc(multicomp_freqs_max*sizeof(*ret->peak));
+ for(i=0;i<multicomp_freqs_max;i++)
+ ret->peak[i]=malloc(input_ch*sizeof(**ret->peak));
+
+ ret->rms=malloc(multicomp_freqs_max*sizeof(*ret->rms));
+ for(i=0;i<multicomp_freqs_max;i++)
+ ret->rms[i]=malloc(input_ch*sizeof(**ret->rms));
+
+ return (feedback_generic *)ret;
}
-void multicompand_reset(){
- int i,j;
+/* total, peak, rms are pulled in array[freqs][input_ch] order */
+
+int pull_multicompand_feedback(float **peak,float **rms,int *b){
+ multicompand_feedback *f=(multicompand_feedback *)feedback_pull(&ms.feedpool);
+ int i;
- subband_reset(&ms.ss);
+ if(!f)return 0;
+ if(f->bypass){
+ feedback_old(&ms.feedpool,(feedback_generic *)f);
+ return 2;
+ }else{
+ if(peak)
+ for(i=0;i<f->freq_bands;i++)
+ memcpy(peak[i],f->peak[i],sizeof(**peak)*input_ch);
+ if(rms)
+ for(i=0;i<f->freq_bands;i++)
+ memcpy(rms[i],f->rms[i],sizeof(**rms)*input_ch);
+ if(b)*b=f->freq_bands;
+ feedback_old(&ms.feedpool,(feedback_generic *)f);
+ return 1;
+ }
+}
+
+static void reset_filters(multicompand_state *ms){
+ int i,j;
for(i=0;i<multicomp_freqs_max;i++)
for(j=0;j<input_ch;j++){
- memset(&ms.over_peak[i][j],0,sizeof(peak_state));
- memset(&ms.under_peak[i][j],0,sizeof(peak_state));
- memset(&ms.base_peak[i][j],0,sizeof(peak_state));
- memset(&ms.over_iir[i][j],0,sizeof(iir_state));
- memset(&ms.under_iir[i][j],0,sizeof(iir_state));
- memset(&ms.base_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->over_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->under_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->base_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->over_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->under_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->base_iir[i][j],0,sizeof(iir_state));
}
}
+void multicompand_reset(){
+
+ subband_reset(&ms.ss);
+ while(pull_multicompand_feedback(NULL,NULL,NULL));
+ reset_filters(&ms);
+
+}
+
int multicompand_load(void){
int h,i;
int qblocksize=input_size/8;
@@ -111,14 +160,17 @@
ms.base_iir[i]=calloc(input_ch,sizeof(iir_state));
}
- ms.active_bank=0;
-
+ ms.peak=calloc(multicomp_freqs_max,sizeof(*ms.peak));
+ ms.rms=calloc(multicomp_freqs_max,sizeof(*ms.rms));
+ for(i=0;i<multicomp_freqs_max;i++)ms.peak[i]=malloc(input_ch*sizeof(**ms.peak));
+ for(i=0;i<multicomp_freqs_max;i++)ms.rms[i]=malloc(input_ch*sizeof(**ms.rms));
+
return 0;
}
-static void multicompand_filter_set(float msec,
- iir_filter *filter,
- int attackp){
+static int multicompand_filter_set(float msec,
+ iir_filter *filter,
+ int attackp){
float alpha;
float corner_freq= 500./msec;
@@ -131,47 +183,32 @@
filter->g=mkbessel(alpha,2,filter->c);
filter->alpha=alpha;
filter->Hz=alpha*input_rate;
-}
-
-static int multicompand_filterbank_set(float msec,
- iir_filter
- filterbank[multicomp_banks]
- [multicomp_freqs_max],
- int attackp){
- int i,j;
- for(j=0;j<multicomp_banks;j++){
- int bands=multicomp_freqs[j];
- iir_filter *filters=filterbank[j];
-
- for(i=0;i<bands;i++)
- multicompand_filter_set(msec,filters+i,attackp);
- }
return 0;
}
int multicompand_over_attack_set(float msec){
- return multicompand_filterbank_set(msec,ms.over_attack,1);
+ return multicompand_filter_set(msec,&ms.over_attack,1);
}
int multicompand_over_decay_set(float msec){
- return multicompand_filterbank_set(msec,ms.over_decay,0);
+ return multicompand_filter_set(msec,&ms.over_decay,0);
}
int multicompand_under_attack_set(float msec){
- return multicompand_filterbank_set(msec,ms.under_attack,1);
+ return multicompand_filter_set(msec,&ms.under_attack,1);
}
int multicompand_under_decay_set(float msec){
- return multicompand_filterbank_set(msec,ms.under_decay,0);
+ return multicompand_filter_set(msec,&ms.under_decay,0);
}
int multicompand_base_attack_set(float msec){
- return multicompand_filterbank_set(msec,ms.base_attack,1);
+ return multicompand_filter_set(msec,&ms.base_attack,1);
}
int multicompand_base_decay_set(float msec){
- return multicompand_filterbank_set(msec,ms.base_decay,0);
+ return multicompand_filter_set(msec,&ms.base_decay,0);
}
static void prepare_rms(float *rms, float *xx, int n, int ahead){
@@ -192,8 +229,8 @@
reset if the lookahead is exceptionally long */
if(loc==0 && val==0){
for(ii=0;ii<ahead;ii++)
- if(fabs(x[ii])>val){
- val=fabs(x[ii]);
+ if((x[ii]*x[ii])>val){
+ val=(x[ii]*x[ii]);
loc=ii+hold;
}
}
@@ -201,18 +238,18 @@
if(val>peak[0])peak[0]=val;
for(ii=1;ii<n;ii++){
- if(fabs(x[ii+ahead])>val){
- val=fabs(x[ii+ahead]);
+ 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(fabs(x[jj])>val)val=fabs(x[jj]);
+ if((x[jj]*x[jj])>val)val=(x[jj]*x[jj]);
if(jj<n && val>peak[jj])peak[jj]=val;
}
- val=fabs(x[ii+ahead-1]);
+ val=(x[ii+ahead-1]*x[ii+ahead-1]);
loc=ii+ahead+hold;
}
if(val>peak[ii])peak[ii]=val;
@@ -223,25 +260,11 @@
}
-static void run_filter_only(float *dB,int n,int mode,
- iir_state *iir,iir_filter *attack,iir_filter *decay){
- int i;
- compute_iir2(dB, n, iir, attack, decay);
-
- if(mode==0)
- for(i=0;i<n;i++)
- dB[i]=todB_a(dB+i)*.5f;
- else
- for(i=0;i<n;i++)
- dB[i]=todB_a(dB+i);
-
-}
-
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)
@@ -252,8 +275,11 @@
else
prepare_rms(dB, x, n, impulse_ahead2(attack->alpha)*lookahead);
+ compute_iir2(dB, n, iir, attack, decay);
- run_filter_only(dB,n,mode,iir,attack,decay);
+ for(i=0;i<n;i++)
+ dB[i]=todB_a(dB+i)*.5f;
+
}
static float soft_knee(float x){
@@ -267,16 +293,16 @@
static void over_compand(float *lx,float zerocorner,
iir_filter *attack, iir_filter *decay,
iir_state *iir, peak_state *ps,
- float *peakfeed, float *rmsfeed,float *adj,int active){
+ float *adj){
int k;
float overdB[input_size];
float lookahead=c.over_lookahead/1000.;
int mode=c.over_mode;
- float corner_multiplier=(1.-1./(c.over_ratio/1000.));
- run_filter(overdB,lx,input_size,lookahead,mode,iir,attack, decay,ps);
+ run_filter(overdB,lx,input_size,lookahead,mode,iir,attack,decay,ps);
- if(active){
+ if(adj){
+ float corner_multiplier=(1.-1./(c.over_ratio*.001));
if(c.over_softknee){
for(k=0;k<input_size;k++)
adj[k]+=soft_knee(overdB[k]-zerocorner)*corner_multiplier;
@@ -285,126 +311,206 @@
adj[k]+=hard_knee(overdB[k]-zerocorner)*corner_multiplier;
}
}
-
- {
- /* determine rms and peak for feedback */
- float max=-1.;
- int maxpos=-1;
- float rms=0.;
-
- for(k=0;k<input_size;k++){
- float val=lx[k]*lx[k];
- if(val>max){
- max=val;
- maxpos=k;
- }
- rms+=val;
- }
- *peakfeed=todB(max)*.5+adj[maxpos];
- *rmsfeed=todB(rms/input_size)*.5+adj[maxpos];
- }
}
static void base_compand(float *x,
iir_filter *attack, iir_filter *decay,
iir_state *iir, peak_state *ps,
- float *adj,int active){
+ float *adj){
int k;
float basedB[input_size];
int mode=c.base_mode;
- float base_multiplier=(1.-1./(c.base_ratio/1000.));
run_filter(basedB,x,input_size,1.,mode,
iir,attack,decay,ps);
- if(active)
+ if(adj){
+ float base_multiplier=(1.-1./(c.base_ratio*.001));
for(k=0;k<input_size;k++)
adj[k]-=(basedB[k]+adj[k])*base_multiplier;
-
+ }
}
static void under_compand(float *x,float zerocorner,
iir_filter *attack, iir_filter *decay,
iir_state *iir, peak_state *ps,
- float *adj,int active){
+ float *adj){
int k;
float underdB[input_size];
float lookahead=c.under_lookahead/1000.;
int mode=c.under_mode;
- float corner_multiplier=(1.-1./(c.under_ratio/1000.));
run_filter(underdB,x,input_size,lookahead,mode,
iir,attack,decay,ps);
- if(active){
+ if(adj){
+ float corner_multiplier=(1./(c.under_ratio*.001)-1.);
if(c.under_softknee){
for(k=0;k<input_size;k++)
- adj[k]-=soft_knee(zerocorner-underdB[k])*corner_multiplier;
+ adj[k]=soft_knee(zerocorner-underdB[k])*corner_multiplier;
}else{
for(k=0;k<input_size;k++)
- adj[k]-=hard_knee(zerocorner-underdB[k])*corner_multiplier;
+ adj[k]=hard_knee(zerocorner-underdB[k])*corner_multiplier;
}
}
}
-static void multicompand_work(float **peakfeed,float **rmsfeed){
- int i,j,k;
+static void multicompand_work(void *vs){
+
+ multicompand_state *ms=(multicompand_state *)vs;
+ subband_state *ss=&ms->ss;
+ int i,j,k,bypass_visible=1;
float adj[input_size];
- float *x;
- int active=compand_active;
- for(i=0;i<multicomp_freqs[ms.active_bank];i++){
+ float **peakfeed=ms->peak;
+ float **rmsfeed=ms->rms;
+ int bank;
+ subband_window *w=ss->w1;
+ subband_window *wP=ss->wP;
+ int maxbands=ss->wC->freq_bands;
+ if(maxbands<ss->w0->freq_bands)maxbands=ss->w0->freq_bands;
+ if(maxbands<ss->w1->freq_bands)maxbands=ss->w1->freq_bands;
+
+ if(w==&ms->sw[0]){
+ bank=0;
+ }else if(w==&ms->sw[1]){
+ bank=1;
+ }else bank=2;
+
+ for(i=0;i<maxbands;i++){
for(j=0;j<input_ch;j++){
- memset(adj,0,sizeof(adj));
+ float *x=ss->lap[i][j];
+ int active=(ss->effect_active1[j] ||
+ ss->effect_active0[j] ||
+ ss->effect_activeC[j]);
- if(active || compand_visible){
- under_compand(ms.ss.lap[i][j],
- bc[ms.active_bank].static_u[i],
- &ms.under_attack[ms.active_bank][i],
- &ms.under_decay[ms.active_bank][i],
- &ms.under_iir[i][j],
- &ms.under_peak[i][j],
- adj,active);
+ if(active){
+ /* one thing is worth a note here; 'maxbands' can be
+ 'overrange' for the current bank. This is intentional; we
+ may need to run the additional (allocated and valid)
+ filters before or after their bands are active. The only
+ garbage data here is the xxxx_u, xxxx_o and xxxx_b
+ settings. There are allocated, but unset; if overrange,
+ they're ignored in the compand worker */
+ under_compand(x,
+ bc[bank].static_u[i],
+ &ms->under_attack,
+ &ms->under_decay,
+ &ms->under_iir[i][j],
+ &ms->under_peak[i][j],
+ (i>=w->freq_bands?0:adj));
- over_compand(ms.ss.lap[i][j],
- bc[ms.active_bank].static_o[i],
- &ms.over_attack[ms.active_bank][i],
- &ms.over_decay[ms.active_bank][i],
- &ms.over_iir[i][j],
- &ms.over_peak[i][j],
- &peakfeed[i][j],
- &rmsfeed[i][j],
- adj,active);
-
- base_compand(ms.ss.lap[i][j],
- &ms.base_attack[ms.active_bank][i],
- &ms.base_decay[ms.active_bank][i],
- &ms.base_iir[i][j],
- &ms.base_peak[i][j],
- adj,active);
+ over_compand(x,
+ bc[bank].static_o[i],
+ &ms->over_attack,
+ &ms->over_decay,
+ &ms->over_iir[i][j],
+ &ms->over_peak[i][j],
+ (i>=w->freq_bands?0:adj));
+
}
+ if(ss->visible1[j] && !mute_channel_muted(ss->mutemask1,j)){
+ /* determine rms and peak for feedback */
+ float max=-1.;
+ int maxpos=-1;
+ float rms=0.;
+ if(bypass_visible){
+ int ii;
+ for(ii=0;ii<w->freq_bands;ii++){
+ memset(peakfeed[ii],0,input_ch*sizeof(**peakfeed));
+ memset(rmsfeed[ii],0,input_ch*sizeof(**rmsfeed));
+ }
+ }
+ bypass_visible=0;
+
+ for(k=0;k<input_size;k++){
+ float val=x[k]*x[k];
+ if(val>max){
+ max=val;
+ maxpos=k;
+ }
+ rms+=val;
+ }
+ if(active){
+ peakfeed[i][j]=todB(max)*.5+adj[maxpos];
+ rmsfeed[i][j]=todB(rms/input_size)*.5+adj[maxpos];
+ }else{
+ peakfeed[i][j]=todB(max)*.5;
+ rmsfeed[i][j]=todB(rms/input_size)*.5;
+ }
+ }
if(active){
- x=ms.ss.lap[i][j];
- for(k=0;k<input_size;k++)
- x[k]*=fromdB_a(adj[k]);
+ base_compand(x,
+ &ms->base_attack,
+ &ms->base_decay,
+ &ms->base_iir[i][j],
+ &ms->base_peak[i][j],
+ (i>=w->freq_bands?0:adj));
+
+ if(ss->effect_activeC[j]){
+ for(k=0;k<input_size;k++)
+ x[k]*=fromdB_a(adj[k]);
+ }
+ } else if (ss->effect_activeP[j]){
+ /* this lapping channel just became inactive */
+ memset(&ms->over_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->under_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->base_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->over_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->under_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->base_iir[i][j],0,sizeof(iir_state));
}
+
}
}
-}
-void multicompand_set_bank(int bank){
- ms.pending_bank=bank;
+ for(;i<wP->freq_bands;i++)
+ for(j=0;j<input_ch;j++){
+ memset(&ms->over_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->under_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->base_peak[i][j],0,sizeof(peak_state));
+ memset(&ms->over_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->under_iir[i][j],0,sizeof(iir_state));
+ memset(&ms->base_iir[i][j],0,sizeof(iir_state));
+ }
+
+ /* finish up the state feedabck */
+ if(bypass_visible){
+ multicompand_feedback *ff=
+ (multicompand_feedback *)
+ feedback_new(&ms->feedpool,new_multicompand_feedback);
+ ff->bypass=1;
+ feedback_push(&ms->feedpool,(feedback_generic *)ff);
+ }else{
+ multicompand_feedback *ff=
+ (multicompand_feedback *)
+ feedback_new(&ms->feedpool,new_multicompand_feedback);
+
+ for(i=0;i<w->freq_bands;i++){
+ memcpy(ff->peak[i],ms->peak[i],input_ch*sizeof(**ms->peak));
+ memcpy(ff->rms[i],ms->rms[i],input_ch*sizeof(**ms->rms));
+ }
+ ff->bypass=0;
+ ff->freq_bands=w->freq_bands;
+ feedback_push(&ms->feedpool,(feedback_generic *)ff);
+ }
}
time_linkage *multicompand_read(time_linkage *in){
- int bypass=!(compand_visible||compand_active);
-
- ms.active_bank=ms.pending_bank;
+ int visible[input_ch];
+ int active[input_ch];
+ int i;
- return subband_read(in,&ms.ss,&ms.sw[ms.active_bank],
- multicompand_work,bypass);
+ for(i=0;i<input_ch;i++){
+ visible[i]=compand_visible;
+ active[i]=compand_active;
+ }
+ return subband_read(in, &ms.ss, &ms.sw[c.active_bank],
+ visible,active,multicompand_work,&ms);
+
}
+
Modified: trunk/postfish/multicompand.h
===================================================================
--- trunk/postfish/multicompand.h 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/multicompand.h 2004-04-22 09:31:18 UTC (rev 6573)
@@ -73,12 +73,12 @@
sig_atomic_t under_lookahead;
sig_atomic_t under_trim;
+ sig_atomic_t active_bank;
} other_compand_settings;
extern void multicompand_reset();
extern int multicompand_load(void);
extern time_linkage *multicompand_read(time_linkage *in);
-extern void multicompand_set_bank(int bank);
extern int pull_multicompand_feedback(float **peak,float **rms,int *bands);
extern int multicompand_over_attack_set(float msec);
Modified: trunk/postfish/singlecomp.c
===================================================================
--- trunk/postfish/singlecomp.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/singlecomp.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -61,35 +61,13 @@
float **cache;
int cache_samples;
+ u_int32_t mutemask0;
+
} singlecomp_state;
singlecomp_settings scset;
singlecomp_state scs;
-static void _analysis(char *base,int i,float *v,int n,int dB,int offset){
- int j;
- FILE *of;
- char buffer[80];
-
- sprintf(buffer,"%s_%d.m",base,i);
- of=fopen(buffer,"a");
-
- if(!of)perror("failed to open data dump file");
-
- for(j=0;j<n;j++){
- fprintf(of,"%f ",(float)j+offset);
- if(dB)
- fprintf(of,"%f\n",todB(v[j]));
- else
- fprintf(of,"%f\n",(v[j]));
- }
- fprintf(of,"\n");
- fclose(of);
-}
-
-static int offset=0;
-
-
/* feedback! */
typedef struct singlecomp_feedback{
feedback_generic parent_class;
@@ -361,6 +339,8 @@
scs.out.samples=0;
return &scs.out;
}
+ scs.mutemask0=in->active;
+
for(i=0;i<input_ch;i++){
float *temp=in->data[i];
float adj[input_size]; // under will set it
@@ -514,8 +494,8 @@
memset(scs.out.data[i]+scs.out.samples,0,sizeof(**scs.out.data)*tozero);
}
- offset+=input_size;
-
+ scs.out.active=scs.mutemask0;
+ scs.mutemask0=in->active;
return &scs.out;
}
Modified: trunk/postfish/subband.c
===================================================================
--- trunk/postfish/subband.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/subband.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -23,7 +23,6 @@
#include "postfish.h"
#include <fftw3.h>
-#include "feedback.h"
#include "subband.h"
#include "lpc.h"
@@ -31,44 +30,6 @@
extern int input_rate;
extern int input_ch;
-/* feedback! */
-typedef struct subband_feedback{
- feedback_generic parent_class;
- float **peak;
- float **rms;
- int freq_bands;
- int bypass;
-} subband_feedback;
-
-static feedback_generic *new_subband_feedback(void){
- subband_feedback *ret=calloc(1,sizeof(*ret));
- return (feedback_generic *)ret;
-}
-
-/* total, peak, rms are pulled in array[freqs][input_ch] order */
-
-int pull_subband_feedback(subband_state *ff,float **peak,float **rms,int *b){
- subband_feedback *f=(subband_feedback *)feedback_pull(&ff->feedpool);
- int i;
-
- if(!f)return 0;
-
- if(f->bypass){
- feedback_old(&ff->feedpool,(feedback_generic *)f);
- return 2;
- }else{
- if(peak)
- for(i=0;i<ff->bands;i++)
- memcpy(peak[i],f->peak[i],sizeof(**peak)*input_ch);
- if(rms)
- for(i=0;i<ff->bands;i++)
- memcpy(rms[i],f->rms[i],sizeof(**rms)*input_ch);
- if(b)*b=f->freq_bands;
- feedback_old(&ff->feedpool,(feedback_generic *)f);
- return 1;
- }
-}
-
/* called only by initial setup */
int subband_load(subband_state *f,int bands,int qblocksize){
int i,j;
@@ -79,10 +40,27 @@
f->fillstate=0;
f->lap_samples=0;
f->lap=malloc(bands*sizeof(*f->lap));
- f->cache=malloc(input_ch*sizeof(*f->cache));
+ f->cache0=malloc(input_ch*sizeof(*f->cache0));
+ f->cache1=malloc(input_ch*sizeof(*f->cache1));
+
+ f->lap_activeP=malloc(input_ch*sizeof(*f->lap_activeP));
+ f->lap_active1=malloc(input_ch*sizeof(*f->lap_active1));
+ f->lap_active0=malloc(input_ch*sizeof(*f->lap_active0));
+ f->lap_activeC=malloc(input_ch*sizeof(*f->lap_activeC));
+
+ f->visible1=malloc(input_ch*sizeof(*f->visible1));
+ f->visible0=malloc(input_ch*sizeof(*f->visible0));
+ f->visibleC=malloc(input_ch*sizeof(*f->visibleC));
+ f->effect_activeP=malloc(input_ch*sizeof(*f->effect_activeP));
+ f->effect_active1=malloc(input_ch*sizeof(*f->effect_active1));
+ f->effect_active0=malloc(input_ch*sizeof(*f->effect_active0));
+ f->effect_activeC=malloc(input_ch*sizeof(*f->effect_activeC));
+
for(i=0;i<input_ch;i++)
- f->cache[i]=malloc(input_size*sizeof(**f->cache));
+ f->cache0[i]=malloc(input_size*sizeof(**f->cache0));
+ for(i=0;i<input_ch;i++)
+ f->cache1[i]=malloc(input_size*sizeof(**f->cache1));
for(i=0;i<bands;i++){
f->lap[i]=malloc(input_ch*sizeof(**f->lap));
@@ -101,8 +79,6 @@
f->window=malloc(f->qblocksize*2*sizeof(*f->window));
/* we need a smooth-edged, symmetric window */
for(i=0;i<f->qblocksize*2;i++)f->window[i]=sin(M_PIl*i/(f->qblocksize*2));
- //for(i=0;i<f->qblocksize*2;i++)f->window[i]*=f->window[i];
- //for(i=0;i<f->qblocksize*2;i++)f->window[i]=sin(f->window[i]*M_PIl*.5);
for(i=0;i<f->qblocksize*2;i++)f->window[i]*=f->window[i]*.25/f->qblocksize;
f->fftwf_forward_out = fftwf_malloc(sizeof(*f->fftwf_forward_out) *
@@ -137,7 +113,6 @@
/* supersample the spectrum */
w->ho_window=malloc(bands*sizeof(*w->ho_window));
- w->ho_area=calloc(bands,sizeof(*w->ho_area));
{
float working[f->qblocksize*4+2];
@@ -176,11 +151,11 @@
convolution is properly padded against being circular */
memset(f->fftwf_backward_in,0,sizeof(*f->fftwf_backward_in)*
(f->qblocksize*4+2));
- for(j=0;j<f->qblocksize*2;j++)
+ for(j=0;j<f->qblocksize*2+2;j++)
f->fftwf_backward_in[j*2]=working[j];
-
+
fftwf_execute(f->fftwf_backward);
-
+
/* window response in time */
memcpy(f->fftwf_forward_in,f->fftwf_backward_out,
f->qblocksize*4*sizeof(*f->fftwf_forward_in));
@@ -207,7 +182,7 @@
/* now take what we learned and distill it a bit */
w->ho_window[i]=calloc((f->qblocksize*2+1),sizeof(**w->ho_window));
for(j=0;j<f->qblocksize*2+1;j++)
- w->ho_area[i]+=w->ho_window[i][j]=f->fftwf_forward_out[j*2];
+ w->ho_window[i][j]=f->fftwf_forward_out[j*2];
lastf=thisf;
@@ -221,7 +196,6 @@
int subband_reset(subband_state *f){
/* reset cached pipe state */
f->fillstate=0;
- while(pull_subband_feedback(f,NULL,NULL,NULL));
return 0;
}
@@ -229,171 +203,288 @@
linear time-convolution using the response filters created earlier
and padded FFTs with 75% overlap. */
-static void subband_work(subband_state *f,time_linkage *in,subband_window *w){
+static void subband_work(subband_state *f,
+ time_linkage *in,
+ subband_window *w,
+ int *visible,
+ int *active){
+
+
int i,j,k,l,off;
float *workoff=f->fftwf_forward_in+f->qblocksize;
+ u_int32_t mutemask=in->active;
+ f->mutemaskC=mutemask;
+ f->wC=w;
+
for(i=0;i<input_ch;i++){
- off=0;
- for(j=0;j<(input_size/f->qblocksize);j++){
-
- switch(j){
- case 0:
- memcpy(workoff,f->cache[i]+input_size-f->qblocksize*2,
- sizeof(*workoff)*f->qblocksize*2);
- break;
- case 1:
- memcpy(workoff,f->cache[i]+input_size-f->qblocksize,
- sizeof(*workoff)*f->qblocksize);
- memcpy(workoff+f->qblocksize,in->data[i],
- sizeof(*workoff)*f->qblocksize);
- break;
- default:
- memcpy(workoff,in->data[i]+off,
- sizeof(*workoff)*f->qblocksize*2);
- off+=f->qblocksize;
- break;
- }
+ int content_p= f->lap_activeC[i]= (visible[i]||active[i]) && !mute_channel_muted(mutemask,i);
+ int content_p0= f->lap_active0[i];
+ int content_p1= f->lap_active1[i];
- /* window; assume the edges are already zeroed */
- for(k=0;k<f->qblocksize*2;k++)workoff[k]*=f->window[k];
+ int maxbands=w->freq_bands;
+ if(maxbands<f->w0->freq_bands)maxbands=f->w0->freq_bands;
+ if(maxbands<f->w1->freq_bands)maxbands=f->w1->freq_bands;
- fftwf_execute(f->fftwf_forward);
+ f->effect_activeC[i] = active[i] && !mute_channel_muted(mutemask,i);
+ f->visibleC[i] = visible[i];
- /* repeatedly filter and transform back */
- for(k=0;k<w->freq_bands;k++){
- float *lapcb=f->lap[k][i]+input_size*2+(j-3)*f->qblocksize;
+ if(!content_p1 && !content_p0 && !content_p){
+ /* all disabled, lap is already zeroed. Nothing to do */
+ continue;
+
+ }else if(!content_p0 && content_p){
+ /* from inactive to active; first block to be processed must be
+ entirely within new data so prepare the lap */
+
+ for(k=0;k<maxbands;k++)
+ memset(f->lap[k][i]+input_size*2,0,f->qblocksize*3*sizeof(***f->lap));
+
+ }else if (content_p0 && !content_p){
+ /* from active to inactive; the previous lap is done, just zero out this frame */
+ for(k=0;k<maxbands;k++)
+ memset(f->lap[k][i]+input_size*2,0,input_size*sizeof(*f->lap[k][i]));
+ }
+
+ if(content_p){ /* there is something to do */
+
+ if(content_p0){ /* was lap active last block? */
+ j=0; /* yes; span the gap */
+ off=0;
+ }else{
+ j=3; /* no; start entirely within new data */
+ off=f->qblocksize;
+ }
+
+ for(;j<(input_size/f->qblocksize);j++){
- for(l=0;l<f->qblocksize*2+1;l++){
- f->fftwf_backward_in[2*l]=
- f->fftwf_forward_out[2*l]*w->ho_window[k][l];
- f->fftwf_backward_in[2*l+1]=
- f->fftwf_forward_out[2*l+1]*w->ho_window[k][l];
+ switch(j){
+ case 0:
+ memcpy(workoff,f->cache0[i]+input_size-f->qblocksize*2,
+ sizeof(*workoff)*f->qblocksize*2);
+ break;
+ case 1:
+ memcpy(workoff,f->cache0[i]+input_size-f->qblocksize,
+ sizeof(*workoff)*f->qblocksize);
+ memcpy(workoff+f->qblocksize,in->data[i],
+ sizeof(*workoff)*f->qblocksize);
+ break;
+ default:
+ memcpy(workoff,in->data[i]+off,
+ sizeof(*workoff)*f->qblocksize*2);
+ off+=f->qblocksize;
+ break;
}
- fftwf_execute(f->fftwf_backward);
+ /* window; assume the edges are already zeroed */
+ for(k=0;k<f->qblocksize*2;k++)workoff[k]*=f->window[k];
- /* lap back into the subband; the convolution is already
- balanced so no further windowing needed */
- for(l=0;l<f->qblocksize*3;l++)
- lapcb[l]+=f->fftwf_backward_out[l];
- for(;l<f->qblocksize*4;l++)
- lapcb[l]=f->fftwf_backward_out[l];
-
- }
- /* if we're suddenly processing fewer bands than we were, we
- have to trail out zeroes until the band lap is emptied */
- {
- int bands=f->lapbands[0];
- if(bands<f->lapbands[1])bands=f->lapbands[1];
- if(bands<f->lapbands[2])bands=f->lapbands[2];
-
- for(;k<bands;k++){
+ fftwf_execute(f->fftwf_forward);
+
+ /* repeatedly filter and transform back */
+ for(k=0;k<w->freq_bands;k++){
float *lapcb=f->lap[k][i]+input_size*2+(j-3)*f->qblocksize;
- memset(lapcb+f->qblocksize*3,0,sizeof(*lapcb)*f->qblocksize);
+
+ for(l=0;l<f->qblocksize*2+1;l++){
+ f->fftwf_backward_in[2*l]=
+ f->fftwf_forward_out[2*l]*w->ho_window[k][l];
+ f->fftwf_backward_in[2*l+1]=
+ f->fftwf_forward_out[2*l+1]*w->ho_window[k][l];
+ }
+
+ fftwf_execute(f->fftwf_backward);
+
+ /* lap back into the subband; the convolution is already
+ balanced so no further windowing needed */
+ for(l=0;l<f->qblocksize*3;l++)
+ lapcb[l]+=f->fftwf_backward_out[l];
+ for(;l<f->qblocksize*4;l++)
+ lapcb[l]=f->fftwf_backward_out[l];
+
}
}
+ /* if we're suddenly processing fewer bands than we were, we
+ have to trail out zeroes until the band lap is emptied */
+ for(k=w->freq_bands;k<maxbands;k++)
+ memset(f->lap[k][i]+input_size*2,0,sizeof(*f->lap[k][i])*input_size);
+
}
}
}
-static void bypass_work(subband_state *f,time_linkage *in){
- int i,j;
- float scale=f->qblocksize*4.;
+static void unsubband_work(subband_state *f,time_linkage *in, time_linkage *out){
+ int i,j,k;
+ f->lap_samples+=in->samples;
for(i=0;i<input_ch;i++){
- float *lapcb=f->lap[0][i]+input_size*2-f->qblocksize*2;
- float *x=f->cache[i]+input_size-f->qblocksize*2;
-
- for(j=0;j<f->qblocksize;j++)
- lapcb[j]+=x[j]*f->window[j]*scale;
-
- lapcb+=f->qblocksize;
- x+=f->qblocksize;
- memcpy(lapcb,x,sizeof(*x)*f->qblocksize);
+ int content_pP= f->lap_activeP[i];
+ int content_p1= f->lap_active1[i];
+ int content_p0= f->lap_active0[i];
+ int content_pC= f->lap_activeC[i];
- lapcb+=f->qblocksize;
- x=in->data[i];
+ int active_pP= f->effect_activeP[i];
+ int active_p1= f->effect_active1[i];
+ int active_p0= f->effect_active0[i];
- memcpy(lapcb,x,sizeof(*x)*(input_size-f->qblocksize*2));
+ int muted_p1= mute_channel_muted(f->mutemask1,i);
- lapcb+=(input_size-f->qblocksize*2);
- x+=(input_size-f->qblocksize*2);
+ int maxbands=f->wC->freq_bands;
+ if(maxbands<f->w0->freq_bands)maxbands=f->w0->freq_bands;
+ if(maxbands<f->w1->freq_bands)maxbands=f->w1->freq_bands;
+
+ /* even if the lapping for a channel is active, we will draw
+ output from the cache is the effect is inactive; it saves
+ performing the summation across bands */
- for(j=0;j<f->qblocksize;j++)
- lapcb[j]=x[j]*f->window[j+f->qblocksize]*scale;
+ /* OUTPUT PROCESSING
- for(;j<f->qblocksize*2;j++)
- lapcb[j]=0.;
+ if muted, lap is inactive
+ if visible or active (and not muted) lap is active
+ if inactive and invisible, lap is inactive
- /* do we need to keep propogating zeros forward in other bands? */
- {
- int bands=f->lapbands[0];
- if(bands<f->lapbands[1])bands=f->lapbands[1];
- if(bands<f->lapbands[2])bands=f->lapbands[2];
-
- for(j=1;j<bands;j++){
- float *lapcb=f->lap[j][i]+input_size*2-f->qblocksize;
- memset(lapcb,0,sizeof(*lapcb)*(input_size+f->qblocksize));
- }
- }
- }
-}
+ lap effect mute
+ 1. (I) (I) A : muted; do nothing, the mask will take care of it
+ 2. X I I : full bypass, audible data; rotate the cache into output
+ 3. I A I : not possible
+ 4. A A I : nominal
+
+ we transition from effect active/inactive/active:
-static void unsubband_work(subband_state *f,float **out,int inbands){
- int i,j,k;
+ a) transitions always happen in the shared active portion
+ b) sum frame from active lap
+ c) window beginning/end of resulting summation if necessary
+ d) window/add beginning/end of final frame from cache data if necessary
- int bands=f->lapbands[0];
- if(bands<f->lapbands[1])bands=f->lapbands[1];
- if(bands<f->lapbands[2])bands=f->lapbands[2];
- if(bands<inbands)bands=inbands;
+ */
- for(i=0;i<input_ch;i++){
- for(j=bands-1;j>=0;j--){
-
- /* add bands back together for output */
- if(out){
- if(j==bands-1){
- memcpy(out[i],f->lap[j][i],input_size*(sizeof **out));
- }else{
+ if(out){
+ if(muted_p1 || !active_p1){
+ /* case 1,2; they're similar enough */
+
+ float *temp=f->cache1[i];
+ f->cache1[i]=out->data[i];
+ out->data[i]=temp;
+ /* mutemask will be propogated later */
+
+ }else{
+ /* 'other' */
+
+ /* b) sum the lap */
+ float *o=out->data[i];
+ memcpy(o,f->lap[0][i],input_size*sizeof(*out->data[i]));
+ for(j=1;j<maxbands;j++){
+ float *x=f->lap[j][i];
for(k=0;k<input_size;k++)
- out[i][k]+=f->lap[j][i][k];
+ o[k]+=x[k];
}
+
+ /* c) window beginning/end of summation if needed */
+ if(!active_pP && content_pP){
+
+ /* transitioning to active effect, but the lap was already
+ previously active; window the transition */
+ float *lo=o+f->qblocksize;
+ float scale=f->qblocksize*4;
+ memset(o,0,sizeof(*o)*f->qblocksize);
+ for(j=0;j<f->qblocksize;j++)
+ lo[j]*=f->window[j]*scale;
+
+ }else if (!active_p0 && content_p0){
+
+ /* transitioning from active effect, but the lap will continue
+ to be active; window the transition */
+ float *lo=o+input_size-f->qblocksize*2;
+ float *lw=f->window+f->qblocksize;
+ float scale=f->qblocksize*4;
+ memset(o+input_size-f->qblocksize,0,sizeof(*o)*f->qblocksize);
+ for(j=0;j<f->qblocksize;j++)
+ lo[j]*=lw[j]*scale;
+
+ } /* otherwise any transitions we need are already windowed as
+ above by the lap handling code in subband_work */
+
+ /* d) window/add cache bits if needed */
+ if(!active_pP){
+ /* beginning transition */
+ float *lo=o+f->qblocksize;
+ float *lc=f->cache1[i]+f->qblocksize;
+ float *lw=f->window+f->qblocksize;
+ float scale=f->qblocksize*4;
+
+ memcpy(o,f->cache1[i],sizeof(*o)*f->qblocksize);
+ for(j=0;j<f->qblocksize;j++)
+ lo[j]+=lc[j]*lw[j]*scale;
+
+ }else if (!active_p0){
+ /* end transition */
+ float *lo=o+input_size-f->qblocksize*2;
+ float *lc=f->cache1[i]+input_size-f->qblocksize*2;
+ float scale=f->qblocksize*4;
+
+ memcpy(o+input_size-f->qblocksize,
+ f->cache1[i]+input_size-f->qblocksize,
+ sizeof(*o)*f->qblocksize);
+ for(j=0;j<f->qblocksize;j++)
+ lo[j]+=lc[j]*f->window[j]*scale;
+
+ }
}
+
+ }
+
+ /* out is done for this channel */
+ /* rotate lap */
+ if(content_p1 || content_p0 || content_pC){
+ for(j=0;j<maxbands;j++)
+ memmove(f->lap[j][i],f->lap[j][i]+input_size,
+ sizeof(***f->lap)*input_size*2);
- /* shift bands for next lap */
- /* optimization target: ringbuffer me! */
- memmove(f->lap[j][i],f->lap[j][i]+input_size,
- sizeof(***f->lap)*input_size*2);
-
+ f->lap_activeP[i]=f->lap_active1[i];
+ f->lap_active1[i]=f->lap_active0[i];
+ f->lap_active0[i]=f->lap_activeC[i];
}
+ /* rotate cache data vectors */
+ {
+ float *temp=f->cache1[i];
+ f->cache1[i]=f->cache0[i];
+ f->cache0[i]=in->data[i];
+ in->data[i]=temp;
+ }
}
+ if(out){
+ out->active=f->mutemask1;
+ f->out.samples=(f->lap_samples>input_size?input_size:f->lap_samples);
+ }
- f->lapbands[0]=f->lapbands[1];
- f->lapbands[1]=f->lapbands[2];
- f->lapbands[2]=inbands;
+ /* rotate full-frame data for next frame */
+ memcpy(f->effect_activeP,f->effect_active1,input_ch*sizeof(*f->effect_active1));
+ memcpy(f->effect_active1,f->effect_active0,input_ch*sizeof(*f->effect_active0));
+ memcpy(f->effect_active0,f->effect_activeC,input_ch*sizeof(*f->effect_activeC));
+
+ memcpy(f->visible1,f->visible0,input_ch*sizeof(*f->visible0));
+ memcpy(f->visible0,f->visibleC,input_ch*sizeof(*f->visibleC));
+
+ f->mutemaskP=f->mutemask1;
+ f->mutemask1=f->mutemask0;
+ f->mutemask0=f->mutemaskC;
+
+ f->wP=f->w1;
+ f->w1=f->w0;
+ f->w0=f->wC;
+
+ f->lap_samples-=(out?f->out.samples:0);
+
}
/* called only by playback thread */
time_linkage *subband_read(time_linkage *in, subband_state *f,
- subband_window *w,
- void (*func)(float **, float **),int bypass){
+ subband_window *w,int *visible, int *active,
+ void (*workfunc)(void *),void *arg){
int i,j;
- float peak[w->freq_bands][input_ch];
- float rms[w->freq_bands][input_ch];
- float *peakp[w->freq_bands];
- float *rmsp[w->freq_bands];
-
- if(!bypass)
- for(i=0;i<w->freq_bands;i++){
- peakp[i]=peak[i];
- rmsp[i]=rms[i];
- }
-
switch(f->fillstate){
case 0: /* begin priming the lapping and cache */
if(in->samples==0){
@@ -401,44 +492,64 @@
return &f->out;
}
- /* initially zero the lapping */
+ /* initially zero the lapping and cache */
for(i=0;i<input_ch;i++){
for(j=0;j<f->bands;j++)
memset(f->lap[j][i],0,sizeof(***f->lap)*input_size*2);
- memset(f->cache[i],0,sizeof(**f->cache)*input_size);
+ memset(f->cache1[i],0,sizeof(**f->cache1)*input_size);
+ memset(f->cache0[i],0,sizeof(**f->cache0)*input_size);
}
+ /* and set up state variables */
+ /* set the vars to 'active' so that if the first frame is an
+ active frame, we don't transition window into it (the window
+ would have been in the previous frame */
+ for(i=0;i<input_ch;i++){
+ int set=(visible[i]||active[i]) && !mute_channel_muted(in->active,i);
+ memset(f->lap_activeP,set,sizeof(*f->lap_activeP)*input_ch);
+ memset(f->lap_active1,set,sizeof(*f->lap_active1)*input_ch);
+ memset(f->lap_active0,set,sizeof(*f->lap_active0)*input_ch);
+ //memset(f->lap_activeC,1,sizeof(*f->lap_activeC)*input_ch);
+ }
+
+ memcpy(f->effect_activeP,active,sizeof(*f->effect_activeP)*input_ch);
+ memcpy(f->effect_active1,active,sizeof(*f->effect_active1)*input_ch);
+ memcpy(f->effect_active0,active,sizeof(*f->effect_active0)*input_ch);
+ //memset(f->effect_activeC,1,sizeof(*f->effect_activeC)*input_ch);
+
+ memset(f->visible1,0,sizeof(*f->visible1)*input_ch);
+ memset(f->visible0,0,sizeof(*f->visible0)*input_ch);
+
+ f->mutemaskP=in->active;
+ f->mutemask1=in->active;
+ f->mutemask0=in->active;
+
+ f->wP=w;
+ f->w1=w;
+ f->w0=w;
+
/* initially zero the padding of the input working array */
memset(f->fftwf_forward_in,0,f->qblocksize*4*sizeof(*f->fftwf_forward_in));
- if(bypass){
- bypass_work(f,in);
- unsubband_work(f,0,1);
- }else{
- /* extrapolation mechanism; avoid harsh transients at edges */
- for(i=0;i<input_ch;i++){
+ /* extrapolation mechanism; avoid harsh transients at edges */
+ for(i=0;i<input_ch;i++){
+
+ if(f->lap_active0[i]){
preextrapolate_helper(in->data[i],input_size,
- f->cache[i],input_size);
+ f->cache0[i],input_size);
- if(in->samples<in->size)
- postextrapolate_helper(f->cache[i],input_size,
- in->data[i],in->samples,
- in->data[i]+in->samples,
- in->size-in->samples);
+ if(in->samples<in->size)
+ postextrapolate_helper(f->cache0[i],input_size,
+ in->data[i],in->samples,
+ in->data[i]+in->samples,
+ in->size-in->samples);
}
+ }
- subband_work(f,in,w);
- func(peakp,rmsp);
- unsubband_work(f,0,w->freq_bands);
- }
+ subband_work(f,in,w,visible,active);
+ workfunc(arg);
+ unsubband_work(f,in,NULL);
- for(i=0;i<input_ch;i++){
- float *temp=in->data[i];
- in->data[i]=f->cache[i];
- f->cache[i]=temp;
- }
-
- f->lap_samples=in->samples;
f->fillstate=1;
f->out.samples=0;
if(in->samples==in->size)goto tidy_up;
@@ -450,31 +561,21 @@
case 1: /* finish priming the lapping and cache */
- if(bypass){
- bypass_work(f,in);
- unsubband_work(f,0,1);
- }else{
- /* extrapolation mechanism; avoid harsh transients at edges */
+ /* extrapolation mechanism; avoid harsh transients at edges */
+
+ if(in->samples<in->size)
for(i=0;i<input_ch;i++){
- if(in->samples<in->size)
- postextrapolate_helper(f->cache[i],input_size,
+ if((active[i] || visible[i]) && !mute_channel_muted(in->active,i))
+ postextrapolate_helper(f->cache0[i],input_size,
in->data[i],in->samples,
in->data[i]+in->samples,
in->size-in->samples);
}
- subband_work(f,in,w);
- func(peakp,rmsp);
- unsubband_work(f,0,w->freq_bands);
- }
+ subband_work(f,in,w,visible,active);
+ workfunc(arg);
+ unsubband_work(f,in,NULL);
- for(i=0;i<input_ch;i++){
- float *temp=in->data[i];
- in->data[i]=f->cache[i];
- f->cache[i]=temp;
- }
-
- f->lap_samples=in->samples;
f->fillstate=2;
f->out.samples=0;
if(in->samples==in->size)goto tidy_up;
@@ -486,34 +587,20 @@
case 2: /* nominal processing */
- if(bypass){
- bypass_work(f,in);
- unsubband_work(f,f->out.data,1);
- }else{
- /* extrapolation mechanism; avoid harsh transients at edges */
+ if(in->samples<in->size)
for(i=0;i<input_ch;i++){
- if(in->samples<in->size)
- postextrapolate_helper(f->cache[i],input_size,
+ if((active[i] || visible[i]) && !mute_channel_muted(in->active,i))
+ postextrapolate_helper(f->cache0[i],input_size,
in->data[i],in->samples,
in->data[i]+in->samples,
in->size-in->samples);
}
- subband_work(f,in,w);
- func(peakp,rmsp);
- unsubband_work(f,f->out.data,w->freq_bands);
- }
- for(i=0;i<input_ch;i++){
- float *temp=in->data[i];
- in->data[i]=f->cache[i];
- f->cache[i]=temp;
- }
-
- f->lap_samples+=in->samples;
- f->fillstate=2;
- f->out.samples=(f->lap_samples>input_size?input_size:f->lap_samples);
- f->lap_samples-=f->out.samples;
- if(f->out.samples<f->out.size)f->fillstate=2;
+ subband_work(f,in,w,visible,active);
+ workfunc(arg);
+ unsubband_work(f,in,&f->out);
+
+ if(f->out.samples<f->out.size)f->fillstate=3;
break;
case 3: /* we've pushed out EOF already */
@@ -521,36 +608,6 @@
break;
}
- /* finish up the state feedabck */
- if(!bypass){
- subband_feedback *ff=
- (subband_feedback *)feedback_new(&f->feedpool,new_subband_feedback);
-
- if(!ff->peak){
- ff->peak=malloc(f->bands*sizeof(*ff->peak));
- for(i=0;i<f->bands;i++)
- ff->peak[i]=malloc(input_ch*sizeof(**ff->peak));
- }
- if(!ff->rms){
- ff->rms=malloc(f->bands*sizeof(*ff->rms));
- for(i=0;i<f->bands;i++)
- ff->rms[i]=malloc(input_ch*sizeof(**ff->rms));
- }
-
- for(i=0;i<w->freq_bands;i++){
- memcpy(ff->peak[i],peak[i],input_ch*sizeof(**peak));
- memcpy(ff->rms[i],rms[i],input_ch*sizeof(**rms));
- }
- ff->bypass=0;
- ff->freq_bands=w->freq_bands;
- feedback_push(&f->feedpool,(feedback_generic *)ff);
- }else{
- subband_feedback *ff=
- (subband_feedback *)feedback_new(&f->feedpool,new_subband_feedback);
- ff->bypass=1;
- feedback_push(&f->feedpool,(feedback_generic *)ff);
- }
-
tidy_up:
{
int tozero=f->out.size-f->out.samples;
@@ -558,6 +615,6 @@
for(i=0;i<f->out.channels;i++)
memset(f->out.data[i]+f->out.samples,0,sizeof(**f->out.data)*tozero);
}
-
+
return &f->out;
}
Modified: trunk/postfish/subband.h
===================================================================
--- trunk/postfish/subband.h 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/subband.h 2004-04-22 09:31:18 UTC (rev 6573)
@@ -24,8 +24,14 @@
#include "postfish.h"
typedef struct {
+
+ int freq_bands;
+ float **ho_window;
+
+} subband_window;
+
+typedef struct {
time_linkage out;
- feedback_generic_pool feedpool;
float *fftwf_forward_out;
float *fftwf_backward_in;
@@ -38,36 +44,50 @@
float *window;
int bands;
float ***lap;
- float **cache;
+ float **cache0;
+ float **cache1;
+
+ int *lap_activeC;
+ int *lap_active0;
+ int *lap_active1;
+ int *lap_activeP;
+
+ int *visibleC;
+ int *visible0;
+ int *visible1;
+
+ int *effect_activeC;
+ int *effect_active0;
+ int *effect_active1;
+ int *effect_activeP;
+
+ u_int32_t mutemaskC;
+ u_int32_t mutemask0;
+ u_int32_t mutemask1;
+ u_int32_t mutemaskP;
+
int lap_samples;
int fillstate; /* 0: uninitialized
1: partial prime
2: nominal
3: eof processed */
- int lapbands[3];
+ subband_window *wP;
+ subband_window *w0;
+ subband_window *w1;
+ subband_window *wC;
+
} subband_state;
-typedef struct {
- int freq_bands;
- float **ho_window;
- float *ho_area;
-
-} subband_window;
-
-
extern int subband_load(subband_state *f,int bands, int qb);
extern int subband_load_freqs(subband_state *f,subband_window *w,
const float *freq_list,int bands);
extern time_linkage *subband_read(time_linkage *in, subband_state *f,
- subband_window *w,
- void (*func)(float **, float **),
- int bypass);
+ subband_window *w,int *visible, int *active,
+ void (*workfunc)(void *),void *arg);
extern int subband_reset(subband_state *f);
-extern int pull_subband_feedback(subband_state *ff,
- float **peak,float **rms,int *bands);
Modified: trunk/postfish/suppress.c
===================================================================
--- trunk/postfish/suppress.c 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/suppress.c 2004-04-22 09:31:18 UTC (rev 6573)
@@ -115,14 +115,16 @@
return 0;
}
-static void suppress_work(float **peakfeed,float **rmsfeed){
+static void suppress_work(void *vs){
+ suppress_state *sss=(suppress_state *)vs;
+ subband_state *ss=&sss->ss;
int i,j,k,l;
float smoothms=sset.smooth*.1;
float triggerms=sset.trigger*.1;
float releasems=sset.release*.1;
- iir_filter *trigger=&sss.trigger;
- iir_filter *smooth=&sss.smooth;
- iir_filter *release=&sss.release;
+ iir_filter *trigger=&sss->trigger;
+ iir_filter *smooth=&sss->smooth;
+ iir_filter *release=&sss->release;
int ahead;
if(smoothms!=smooth->ms)filter_set(smoothms,smooth,1,4);
@@ -132,48 +134,52 @@
ahead=impulse_ahead4(smooth->alpha);
for(i=0;i<suppress_freqs;i++){
-
- if(suppress_active){
- float fast[input_size];
- float slow[input_size];
- float multiplier = 1.-1000./sset.ratio[i];
-
- for(j=0;j<input_ch;j++){
+ int firstlink=0;
+ float fast[input_size];
+ float slow[input_size];
+ float multiplier = 1.-1000./sset.ratio[i];
+
+ for(j=0;j<input_ch;j++){
+ int active=(ss->effect_active1[j] ||
+ ss->effect_active0[j] ||
+ ss->effect_activeC[j]);
+
+ if(active){
if(sset.linkp){
- if(j==0){
+ if(!firstlink){
+ firstlink++;
memset(fast,0,sizeof(fast));
float scale=1./input_ch;
for(l=0;l<input_ch;l++){
- float *x=sss.ss.lap[i][l]+ahead;
+ float *x=sss->ss.lap[i][l]+ahead;
for(k=0;k<input_size;k++)
fast[k]+=x[k]*x[k];
}
for(k=0;k<input_size;k++)
fast[k]*=scale;
-
- //_analysis("rms",i,fast,input_size,0,offset);
-
+
}
}else{
- float *x=sss.ss.lap[i][j]+ahead;
+ float *x=sss->ss.lap[i][j]+ahead;
for(k=0;k<input_size;k++)
fast[k]=x[k]*x[k];
}
-
- if(j==0 || sset.linkp==0){
-
- compute_iir_symmetric4(fast, input_size, &sss.iirS[i][j],
- smooth);
+
+ if(sset.linkp==0 || firstlink==1){
+ firstlink++;
+ compute_iir_symmetric4(fast, input_size, &sss->iirS[i][j],
+ smooth);
+
//_analysis("smooth",i,fast,input_size,1,offset);
- compute_iir_freefall1(fast, input_size, &sss.iirT[i][j],
- trigger);
+ compute_iir_freefall1(fast, input_size, &sss->iirT[i][j],
+ trigger);
memcpy(slow,fast,sizeof(slow));
- compute_iir_freefall1(slow, input_size, &sss.iirR[i][j],
- release);
+ compute_iir_freefall1(slow, input_size, &sss->iirR[i][j],
+ release);
//_analysis("fast",i,fast,input_size,1,offset);
//_analysis("slow",i,slow,input_size,1,offset);
@@ -181,24 +187,35 @@
fast[k]=fromdB_a((todB_a(slow+k)-todB_a(fast+k))*.5*multiplier);
//_analysis("adj",i,fast,input_size,1,offset);
}
-
-
+
+
{
- float *x=sss.ss.lap[i][j];
+ float *x=sss->ss.lap[i][j];
for(k=0;k<input_size;k++)
if(fast[k]<1.)
x[k]*=fast[k];
}
+ }else{
+ /* reset filters to sane inactive default */
+ memset(&sss->iirS[i][j],0,sizeof(iir_state));
+ memset(&sss->iirT[i][j],0,sizeof(iir_state));
+ memset(&sss->iirR[i][j],0,sizeof(iir_state));
}
}
}
}
time_linkage *suppress_read(time_linkage *in){
- int bypass=!(suppress_active);
+ int visible[input_ch];
+ int active[input_ch];
+ int i;
+
+ for(i=0;i<input_ch;i++){
+ visible[i]=0;
+ active[i]=suppress_active;
+ }
- return subband_read(in,&sss.ss,&sss.sw,
- suppress_work,bypass);
+ return subband_read(in, &sss.ss, &sss.sw, visible, active, suppress_work, &sss);
}
Modified: trunk/postfish/version.h
===================================================================
--- trunk/postfish/version.h 2004-04-22 07:37:57 UTC (rev 6572)
+++ trunk/postfish/version.h 2004-04-22 09:31:18 UTC (rev 6573)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Sun Apr 18 22:28:48 EDT 2004] */
+/* DO NOT EDIT: Automated versioning hack [Thu Apr 22 05:28:07 EDT 2004] */
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list