[xiph-cvs] r6589 - trunk/postfish

xiphmont at xiph.org xiphmont at xiph.org
Tue May 4 21:26:38 PDT 2004



Author: xiphmont
Date: 2004-04-24 01:16:26 -0400 (Sat, 24 Apr 2004)
New Revision: 6589

Modified:
   trunk/postfish/mainpanel.c
   trunk/postfish/output.c
   trunk/postfish/singlecomp.c
   trunk/postfish/singlecomp.h
   trunk/postfish/singlepanel.c
   trunk/postfish/singlepanel.h
   trunk/postfish/version.h
Log:
Full revamp of Singleband Compander signal path
Implement per-channel singleband compander panels

<p><p>Modified: trunk/postfish/mainpanel.c
===================================================================
--- trunk/postfish/mainpanel.c	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/mainpanel.c	2004-04-24 05:16:26 UTC (rev 6589)
@@ -955,7 +955,7 @@
   mainpanel_chentry(panel,channeltable,"Mute ",0,0,0,mutedummy_create);
   mainpanel_chentry(panel,channeltable,"_Declip ",1,1,0,clippanel_create);
   mainpanel_chentry(panel,channeltable,"_Multicomp ",2,0,1,compandpanel_create_channel);
-  mainpanel_chentry(panel,channeltable,"_Singlecomp ",3,0,1,0);
+  mainpanel_chentry(panel,channeltable,"_Singlecomp ",3,0,1,singlepanel_create_channel);
   mainpanel_chentry(panel,channeltable,"De_verb ",4,1,0,suppresspanel_create_channel);
   mainpanel_chentry(panel,channeltable,"_Reverb ",5,1,0,0);
   mainpanel_chentry(panel,channeltable,"_EQ ",6,0,1,0);
@@ -983,7 +983,7 @@
 
   mainpanel_masterentry(panel,mastertable,"_Crossmix "," c ",GDK_c,0,0);
   mainpanel_masterentry(panel,mastertable,"_Multicomp "," m ",GDK_m,1,compandpanel_create_master);
-  mainpanel_masterentry(panel,mastertable,"_Singlecomp "," s ",GDK_s,2,singlepanel_create);
+  mainpanel_masterentry(panel,mastertable,"_Singlecomp "," s ",GDK_s,2,singlepanel_create_master);
   mainpanel_masterentry(panel,mastertable,"_Reverb "," r ",GDK_r,3,0);
   mainpanel_masterentry(panel,mastertable,"_EQ "," e ",GDK_e,4,eqpanel_create);
   mainpanel_masterentry(panel,mastertable,"_Limit "," l ",GDK_l,5,limitpanel_create);

Modified: trunk/postfish/output.c
===================================================================
--- trunk/postfish/output.c	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/output.c	2004-04-24 05:16:26 UTC (rev 6589)
@@ -240,13 +240,20 @@
     result|=link->samples;
     link=multicompand_read_channel(link);
     result|=link->samples;
+    link=singlecomp_read_channel(link);
+    result|=link->samples;
     link=suppress_read_channel(link);
     result|=link->samples;
 
     link=multicompand_read_master(link);
     result|=link->samples;
-    link=singlecomp_read(link);
+    link=singlecomp_read_master(link);
     result|=link->samples;
+
+    for(i=0;i<input_ch;i++)
+      if(mute_channel_muted(link->active,i))
+	memset(link->data[i],0,sizeof(**link->data)*input_size);
+
     link=eq_read(link);
     result|=link->samples;
     

Modified: trunk/postfish/singlecomp.c
===================================================================
--- trunk/postfish/singlecomp.c	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/singlecomp.c	2004-04-24 05:16:26 UTC (rev 6589)
@@ -30,9 +30,6 @@
 extern int input_rate;
 extern int input_ch;
 
-sig_atomic_t singlecomp_active;
-sig_atomic_t singlecomp_visible;
-
 typedef struct {
   int loc;
   float val;
@@ -50,24 +47,36 @@
   peak_state *u_peak;
   peak_state *b_peak;
 
-  iir_filter o_attack;
-  iir_filter o_decay;
-  iir_filter u_attack;
-  iir_filter u_decay;
-  iir_filter b_attack;
-  iir_filter b_decay;
+  iir_filter *o_attack;
+  iir_filter *o_decay;
+  iir_filter *u_attack;
+  iir_filter *u_decay;
+  iir_filter *b_attack;
+  iir_filter *b_decay;
 
   int fillstate;
   float **cache;
   int cache_samples;
 
-  u_int32_t mutemask0;
+  int *activeP;
+  int *active0;
 
+  int mutemaskP;
+  int mutemask0;
+
 } singlecomp_state;
 
-singlecomp_settings scset;
-singlecomp_state scs;
+float *window;
 
+singlecomp_settings  singlecomp_master_set;
+singlecomp_settings *singlecomp_channel_set;
+
+static singlecomp_settings **master_set_bundle;
+static singlecomp_settings **channel_set_bundle;
+
+static singlecomp_state     master_state;
+static singlecomp_state     channel_state;
+
 /* feedback! */
 typedef struct singlecomp_feedback{
   feedback_generic parent_class;
@@ -80,8 +89,8 @@
   return (feedback_generic *)ret;
 }
 
-int pull_singlecomp_feedback(float *peak,float *rms){
-  singlecomp_feedback *f=(singlecomp_feedback *)feedback_pull(&scs.feedpool);
+static int pull_singlecomp_feedback(singlecomp_state *scs, float *peak,float *rms){
+  singlecomp_feedback *f=(singlecomp_feedback *)feedback_pull(&scs->feedpool);
   
   if(!f)return 0;
   
@@ -89,38 +98,77 @@
     memcpy(peak,f->peak,sizeof(*peak)*input_ch);
   if(rms)
     memcpy(rms,f->rms,sizeof(*rms)*input_ch);
-  feedback_old(&scs.feedpool,(feedback_generic *)f);
+  feedback_old(&scs->feedpool,(feedback_generic *)f);
   return 1;
 }
 
-/* called only by initial setup */
-int singlecomp_load(void){
+int pull_singlecomp_feedback_master(float *peak,float *rms){
+  return pull_singlecomp_feedback(&master_state,peak,rms);
+}
+
+int pull_singlecomp_feedback_channel(float *peak,float *rms){
+  return pull_singlecomp_feedback(&channel_state,peak,rms);
+}
+
+static void singlecomp_load_helper(singlecomp_state *scs){
   int i;
-  memset(&scs,0,sizeof(scs));
+  memset(scs,0,sizeof(scs));
 
-  scs.o_iir=calloc(input_ch,sizeof(*scs.o_iir));
-  scs.b_iir=calloc(input_ch,sizeof(*scs.b_iir));
-  scs.u_iir=calloc(input_ch,sizeof(*scs.u_iir));
+  scs->activeP=calloc(input_ch,sizeof(*scs->activeP));
+  scs->active0=calloc(input_ch,sizeof(*scs->active0));
 
-  scs.o_peak=calloc(input_ch,sizeof(*scs.o_peak));
-  scs.b_peak=calloc(input_ch,sizeof(*scs.b_peak));
-  scs.u_peak=calloc(input_ch,sizeof(*scs.u_peak));
+  scs->o_attack=calloc(input_ch,sizeof(*scs->o_attack));
+  scs->o_decay=calloc(input_ch,sizeof(*scs->o_decay));
+  scs->u_attack=calloc(input_ch,sizeof(*scs->u_attack));
+  scs->u_decay=calloc(input_ch,sizeof(*scs->u_decay));
+  scs->b_attack=calloc(input_ch,sizeof(*scs->b_attack));
+  scs->b_decay=calloc(input_ch,sizeof(*scs->b_decay));
 
-  scs.out.size=input_size;
-  scs.out.channels=input_ch;
-  scs.out.rate=input_rate;
-  scs.out.data=malloc(input_ch*sizeof(*scs.out.data));
+  scs->o_iir=calloc(input_ch,sizeof(*scs->o_iir));
+  scs->b_iir=calloc(input_ch,sizeof(*scs->b_iir));
+  scs->u_iir=calloc(input_ch,sizeof(*scs->u_iir));
+
+  scs->o_peak=calloc(input_ch,sizeof(*scs->o_peak));
+  scs->b_peak=calloc(input_ch,sizeof(*scs->b_peak));
+  scs->u_peak=calloc(input_ch,sizeof(*scs->u_peak));
+
+  scs->out.size=input_size;
+  scs->out.channels=input_ch;
+  scs->out.rate=input_rate;
+  scs->out.data=malloc(input_ch*sizeof(*scs->out.data));
   for(i=0;i<input_ch;i++)
-    scs.out.data[i]=malloc(input_size*sizeof(**scs.out.data));
+    scs->out.data[i]=malloc(input_size*sizeof(**scs->out.data));
 
-  scs.fillstate=0;
-  scs.cache=malloc(input_ch*sizeof(*scs.cache));
+  scs->fillstate=0;
+  scs->cache=malloc(input_ch*sizeof(*scs->cache));
   for(i=0;i<input_ch;i++)
-    scs.cache[i]=malloc(input_size*sizeof(**scs.cache));
+    scs->cache[i]=malloc(input_size*sizeof(**scs->cache));
 
-  return(0);
 }
 
+/* called only by initial setup */
+int singlecomp_load(void){
+  int i;
+  singlecomp_load_helper(&master_state);
+  singlecomp_load_helper(&channel_state);
+
+  window=malloc(input_size/2*sizeof(*window));
+  for(i=0;i<input_size/2;i++){
+    window[i]=sin( (i+.5)/input_size*M_PIl);
+    window[i]*=window[i];
+  }
+
+  singlecomp_channel_set=calloc(input_ch,sizeof(*singlecomp_channel_set));
+  master_set_bundle=malloc(input_ch*sizeof(*master_set_bundle));
+  channel_set_bundle=malloc(input_ch*sizeof(*channel_set_bundle));
+  for(i=0;i<input_ch;i++){
+    master_set_bundle[i]=&singlecomp_master_set;
+    channel_set_bundle[i]=&singlecomp_channel_set[i];
+  }
+
+  return 0;
+}
+
 static void filter_set(float msec,
                        iir_filter *filter,
                        int attackp){
@@ -139,18 +187,25 @@
   filter->ms=msec;
 }
 
+static void reset_filter(singlecomp_state *scs){
+  memset(scs->o_peak,0,input_ch*sizeof(&scs->o_peak));
+  memset(scs->u_peak,0,input_ch*sizeof(&scs->u_peak));
+  memset(scs->b_peak,0,input_ch*sizeof(&scs->b_peak));
+  memset(scs->o_iir,0,input_ch*sizeof(&scs->o_iir));
+  memset(scs->u_iir,0,input_ch*sizeof(&scs->u_iir));
+  memset(scs->b_iir,0,input_ch*sizeof(&scs->b_iir));
+}
+
 /* called only in playback thread */
 int singlecomp_reset(void ){
   /* reset cached pipe state */
-  scs.fillstate=0;
-  while(pull_singlecomp_feedback(NULL,NULL));
+  master_state.fillstate=0;
+  channel_state.fillstate=0;
+  while(pull_singlecomp_feedback_master(NULL,NULL));
+  while(pull_singlecomp_feedback_channel(NULL,NULL));
 
-  memset(scs.o_peak,0,input_ch*sizeof(&scs.o_peak));
-  memset(scs.u_peak,0,input_ch*sizeof(&scs.u_peak));
-  memset(scs.b_peak,0,input_ch*sizeof(&scs.b_peak));
-  memset(scs.o_iir,0,input_ch*sizeof(&scs.o_iir));
-  memset(scs.u_iir,0,input_ch*sizeof(&scs.u_iir));
-  memset(scs.b_iir,0,input_ch*sizeof(&scs.b_iir));
+  reset_filter(&master_state);
+  reset_filter(&channel_state);
   return 0;
 }
 
@@ -166,8 +221,8 @@
 
   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;
       }
   }
@@ -175,18 +230,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; 
@@ -224,12 +279,8 @@
   
   compute_iir2(work, input_size, iir, attack, decay);
   
-  if(mode==0)
-    for(k=0;k<input_size;k++)
-      work[k]=todB_a(work+k)*.5f;
-  else
-    for(k=0;k<input_size;k++)
-      work[k]=todB_a(work+k);
+  for(k=0;k<input_size;k++)
+    work[k]=todB_a(work+k)*.5f;
 }
 
 static float soft_knee(float x){
@@ -312,190 +363,285 @@
 
 }
 
-time_linkage *singlecomp_read(time_linkage *in){
+static void work_and_lapping(singlecomp_state *scs,
+			     singlecomp_settings **scset,
+			     time_linkage *in,
+			     time_linkage *out,
+			     int *active){
+  int i;
+  int have_feedback=0;
+  u_int32_t mutemaskC=in->active;
+  u_int32_t mutemask0=scs->mutemask0;
+  u_int32_t mutemaskP=scs->mutemaskP;
+
   float peakfeed[input_ch];
   float rmsfeed[input_ch];
+  memset(peakfeed,0,sizeof(peakfeed));
+  memset(rmsfeed,0,sizeof(rmsfeed));
+  
+  for(i=0;i<input_ch;i++){
 
-  int active=singlecomp_active;
-  int i;
+    int activeC= active[i] && !mute_channel_muted(mutemaskC,i);
+    int active0= scs->active0[i];
+    int activeP= scs->activeP[i];
 
-  float o_attackms=scset.o_attack*.1;
-  float o_decayms=scset.o_decay*.1;
-  float u_attackms=scset.u_attack*.1;
-  float u_decayms=scset.u_decay*.1;
-  float b_attackms=scset.b_attack*.1;
-  float b_decayms=scset.b_decay*.1;
+    int mutedC=mute_channel_muted(mutemaskC,i);
+    int muted0=mute_channel_muted(mutemask0,i);
+    int mutedP=mute_channel_muted(mutemaskP,i);
 
-  if(o_attackms!=scs.o_attack.ms)filter_set(o_attackms,&scs.o_attack,1);
-  if(o_decayms!=scs.o_decay.ms)filter_set(o_decayms,&scs.o_decay,0);
-  if(u_attackms!=scs.u_attack.ms)filter_set(u_attackms,&scs.u_attack,1);
-  if(u_decayms!=scs.u_decay.ms)filter_set(u_decayms,&scs.u_decay,0);
-  if(b_attackms!=scs.b_attack.ms)filter_set(b_attackms,&scs.b_attack,1);
-  if(b_decayms!=scs.b_decay.ms)filter_set(b_decayms,&scs.b_decay,0);
+    float o_attackms=scset[i]->o_attack*.1;
+    float o_decayms=scset[i]->o_decay*.1;
+    float u_attackms=scset[i]->u_attack*.1;
+    float u_decayms=scset[i]->u_decay*.1;
+    float b_attackms=scset[i]->b_attack*.1;
+    float b_decayms=scset[i]->b_decay*.1;
+
+    if(o_attackms!=scs->o_attack[i].ms)filter_set(o_attackms,&scs->o_attack[i],1);
+    if(o_decayms!=scs->o_decay[i].ms)filter_set(o_decayms,&scs->o_decay[i],0);
+    if(u_attackms!=scs->u_attack[i].ms)filter_set(u_attackms,&scs->u_attack[i],1);
+    if(u_decayms!=scs->u_decay[i].ms)filter_set(u_decayms,&scs->u_decay[i],0);
+    if(b_attackms!=scs->b_attack[i].ms)filter_set(b_attackms,&scs->b_attack[i],1);
+    if(b_decayms!=scs->b_decay[i].ms)filter_set(b_decayms,&scs->b_decay[i],0);
   
-  switch(scs.fillstate){
-  case 0: /* prime the cache */
-    if(in->samples==0){
-      scs.out.samples=0;
-      return &scs.out;
-    }
-    scs.mutemask0=in->active;
+    if(!active0 && !activeC){
 
-    for(i=0;i<input_ch;i++){
-      float *temp=in->data[i];
-      float adj[input_size]; // under will set it
+      if(activeP) reset_filter(scs); /* just became inactive; reset all filters */
 
-      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));
-      memset(scs.cache[i],0,sizeof(**scs.cache)*input_size);
+      /* feedabck */
+      if(scset[i]->panel_visible){
+	int k;
+	float rms=0.;
+	float peak=0.;
+        float *x=scs->cache[i];
+	have_feedback=1;
 
-      under_compand(scs.cache[i],in->data[i],adj,
-		    (float)(scset.u_thresh),
-		    1.-1./(scset.u_ratio/1000.),
-		    scset.u_lookahead/1000.,
-		    scset.u_mode,
-		    scset.u_softknee,
-		    &scs.u_attack,&scs.u_decay,
-		    scs.u_iir+i,scs.u_peak+i,
-		    active);
-      
-      over_compand(scs.cache[i],in->data[i],adj,
-		   (float)(scset.o_thresh),
-		   1.-1./(scset.o_ratio/1000.),
-		   scset.o_lookahead/1000.,
-		   scset.o_mode,
-		   scset.o_softknee,
-		   &scs.o_attack,&scs.o_decay,
-		   scs.o_iir+i,scs.o_peak+i,
-		   active);
+	if(!muted0){
+	  for(k=0;k<input_size;k++){
+	    float val=x[k]*x[k];
+	    rms+= val;
+	    if(peak<val)peak=val;
+	  }
+	}
+	peakfeed[i]=todB_a(&peak)*.5;
+	rms/=input_size;
+	rmsfeed[i]=todB_a(&rms)*.5;
+      }
 
-      base_compand(scs.cache[i],in->data[i],adj,
-		   1.-1./(scset.b_ratio/1000.),
-		   scset.b_mode,
-		   &scs.b_attack,&scs.b_decay,
-		   scs.b_iir+i,scs.b_peak+i,
-		   active);
+      /* rotate data vectors */
+      if(out){
+	float *temp=out->data[i];
+	out->data[i]=scs->cache[i];
+	scs->cache[i]=temp;
+      }
+	
 
+    }else if(active0 || activeC){
 
-      in->data[i]=scs.cache[i];
-      scs.cache[i]=temp;
-    }
-    scs.cache_samples=in->samples;
-    scs.fillstate=1;
-    scs.out.samples=0;
-    if(in->samples==in->size)goto tidy_up;
-    
-    for(i=0;i<input_ch;i++)
-      memset(in->data[i],0,sizeof(**in->data)*in->size);
-    in->samples=0;
-    /* fall through */
-  case 1: /* nominal processing */
-
-    for(i=0;i<input_ch;i++){
-      
+      /* run the filters */
       float adj[input_size]; // under will set it
       
-      under_compand(scs.cache[i],in->data[i],adj,
-		    (float)(scset.u_thresh),
-		    1.-1./(scset.u_ratio/1000.),
-		    scset.u_lookahead/1000.,
-		    scset.u_mode,
-		    scset.u_softknee,
-		    &scs.u_attack,&scs.u_decay,
-		    scs.u_iir+i,scs.u_peak+i,
-		    active);
+      under_compand(scs->cache[i],in->data[i],adj,
+		    (float)(scset[i]->u_thresh),
+		    1.-1000./scset[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);
       
-      over_compand(scs.cache[i],in->data[i],adj,
-		   (float)(scset.o_thresh),
-		   1.-1./(scset.o_ratio/1000.),
-		   scset.o_lookahead/1000.,
-		   scset.o_mode,
-		   scset.o_softknee,
-		   &scs.o_attack,&scs.o_decay,
-		   scs.o_iir+i,scs.o_peak+i,
-		   active);
-
+      over_compand(scs->cache[i],in->data[i],adj,
+		   (float)(scset[i]->o_thresh),
+		   1.-1000./scset[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);
+      
       /* feedback before base */
-      {
+      if(scset[i]->panel_visible){
         int k;
         float rms=0.;
         float peak=0.;
-        float *x=scs.cache[i];
+        float *x=scs->cache[i];
+	have_feedback=1;
 
-	for(k=0;k<input_size;k++){
-	  float mul=fromdB_a(adj[k]);
-	  float val=x[k]*mul;
+	if(!muted0){
+	  for(k=0;k<input_size;k++){
+	    float mul=fromdB_a(adj[k]);
+	    float val=x[k]*mul;
           
-	  val*=val;
-	  rms+= val;
-	  if(peak<val)peak=val;
-
+	    val*=val;
+	    rms+= val;
+	    if(peak<val)peak=val;
+	    
+	  }
         }
-
         peakfeed[i]=todB_a(&peak)*.5;
         rms/=input_size;
         rmsfeed[i]=todB_a(&rms)*.5;
       }
       
-      base_compand(scs.cache[i],in->data[i],adj,
-		   1.-1./(scset.b_ratio/1000.),
-		   scset.b_mode,
-		   &scs.b_attack,&scs.b_decay,
-		   scs.b_iir+i,scs.b_peak+i,
-		   active);
+      base_compand(scs->cache[i],in->data[i],adj,
+		   1.-1000./scset[i]->b_ratio,
+		   scset[i]->b_mode,
+		   scs->b_attack+i,scs->b_decay+i,
+		   scs->b_iir+i,scs->b_peak+i,
+		   active0);
 
-      if(active){
+      if(active0 && out){
+	/* current frame should be manipulated; render into out,
+	   handle transitioning after */
         int k;
-        float *x=scs.cache[i];
-        float *out=scs.out.data[i];
+        float *ix=scs->cache[i];
+        float *ox=out->data[i];
 
         for(k=0;k<input_size;k++)
-          out[k]=x[k]*fromdB_a(adj[k]);
-      }else
-	memcpy(scs.out.data[i],scs.cache[i],input_size*sizeof(*scs.cache[i]));
+          ox[k]=ix[k]*fromdB_a(adj[k]);
 
-      {
-	float *temp=scs.cache[i];
-	scs.cache[i]=in->data[i];
-	in->data[i]=temp;
+	/* is this frame preceeded/followed by an 'inactive' or muted frame?
+	   If so, smooth the transition */
+	if(!activeP){
+	  if(mutedP){
+	    for(k=0;k<input_size/2;k++)
+	      ox[k]*=window[k];
+	  }else{
+	    for(k=0;k<input_size/2;k++){
+	      float w=window[k];
+	      ox[k]= ox[k]*w + ix[k]*(1.-w);
+	    }
+	  }
+	}
+	if(!activeC){
+	  float *cox=ox+input_size/2;
+	  if(mutedC){
+	    for(k=0;k<input_size/2;k++){
+	      float w=1.-window[k];
+	      cox[k]*=w;
+	    }
+	  }else{
+	    float *cix=ix+input_size/2;
+	    for(k=0;k<input_size/2;k++){
+	      float w=window[k];
+	      cox[k]= cox[k]*(1.-w) + cix[k]*w;
+	    }
+	  }
+	}
+      }else if(out){
+	float *temp=out->data[i];
+	out->data[i]=scs->cache[i];
+	scs->cache[i]=temp;
       }
     }
-    scs.out.samples=scs.cache_samples;
-    scs.cache_samples=in->samples;
-    if(scs.out.samples<scs.out.size)scs.fillstate=2;
-    break;
-  case 2: /* we've pushed out EOF already */
-    scs.out.samples=0;
+    {
+      float *temp=scs->cache[i];
+      scs->cache[i]=in->data[i];
+      in->data[i]=temp;
+    }
+    scs->activeP[i]=active0;
+    scs->active0[i]=activeC;
+
   }
-  
-  /* finish up the state feedabck */
-  {
+
+  if(out){
+    /* feedback is also triggered off of output */
     singlecomp_feedback *ff=
-      (singlecomp_feedback *)feedback_new(&scs.feedpool,new_singlecomp_feedback);
+      (singlecomp_feedback *)feedback_new(&scs->feedpool,new_singlecomp_feedback);
     
     if(!ff->peak)
       ff->peak=malloc(input_ch*sizeof(*ff->peak));
     
     if(!ff->rms)
       ff->rms=malloc(input_ch*sizeof(*ff->rms));
-
+    
     memcpy(ff->peak,peakfeed,sizeof(peakfeed));
     memcpy(ff->rms,rmsfeed,sizeof(rmsfeed));
+    
+    feedback_push(&scs->feedpool,(feedback_generic *)ff);
 
-    feedback_push(&scs.feedpool,(feedback_generic *)ff);
+    out->active=mutemask0;
+    out->samples=scs->cache_samples;
   }
    
+  scs->cache_samples=in->samples;
+  scs->mutemaskP=mutemask0;
+  scs->mutemask0=mutemaskC;
+}
+
+time_linkage *singlecomp_read_helper(time_linkage *in,
+				     singlecomp_state *scs, 
+				     singlecomp_settings **scset,
+				     int *active){
+  int i;
+
+  switch(scs->fillstate){
+  case 0: /* prime the cache */
+    if(in->samples==0){
+      scs->out.samples=0;
+      return &scs->out;
+    }
+    
+    for(i=0;i<input_ch;i++){
+      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));
+      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));
+      memset(scs->cache[i],0,sizeof(**scs->cache)*input_size);
+      scs->activeP[i]=scs->active0[i]=active[i];
+    }
+    scs->mutemaskP=scs->mutemask0=in->active;
+    
+    work_and_lapping(scs,scset,in,0,active);
+
+    scs->fillstate=1;
+    scs->out.samples=0;
+    if(in->samples==in->size)goto tidy_up;
+    
+    for(i=0;i<input_ch;i++)
+      memset(in->data[i],0,sizeof(**in->data)*in->size);
+    in->samples=0;
+    /* fall through */
+  case 1: /* nominal processing */
+
+    work_and_lapping(scs,scset,in,&scs->out,active);
+
+    if(scs->out.samples<scs->out.size)scs->fillstate=2;
+    break;
+  case 2: /* we've pushed out EOF already */
+    scs->out.samples=0;
+  }
+  
  tidy_up:
   {
-    int tozero=scs.out.size-scs.out.samples;
+    int tozero=scs->out.size-scs->out.samples;
     if(tozero)
-      for(i=0;i<scs.out.channels;i++)
-        memset(scs.out.data[i]+scs.out.samples,0,sizeof(**scs.out.data)*tozero);
+      for(i=0;i<scs->out.channels;i++)
+        memset(scs->out.data[i]+scs->out.samples,0,sizeof(**scs->out.data)*tozero);
   }
 
-  scs.out.active=scs.mutemask0;
-  scs.mutemask0=in->active;
-  return &scs.out;
+  return &scs->out;
 }
 
+time_linkage *singlecomp_read_master(time_linkage *in){
+  int active[input_ch],i;
+
+  /* local copy required to avoid concurrency problems */
+  for(i=0;i<input_ch;i++)
+    active[i]=singlecomp_master_set.panel_active;
+
+  return singlecomp_read_helper(in, &master_state, master_set_bundle,active);
+}
+
+time_linkage *singlecomp_read_channel(time_linkage *in){
+  int active[input_ch],i;
+
+  /* local copy required to avoid concurrency problems */
+  for(i=0;i<input_ch;i++)
+    active[i]=singlecomp_channel_set[i].panel_active;
+  
+  return singlecomp_read_helper(in, &channel_state, channel_set_bundle,active);
+}

Modified: trunk/postfish/singlecomp.h
===================================================================
--- trunk/postfish/singlecomp.h	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/singlecomp.h	2004-04-24 05:16:26 UTC (rev 6589)
@@ -46,9 +46,13 @@
   sig_atomic_t b_ratio;
   sig_atomic_t b_mode;
 
+  sig_atomic_t panel_visible;
+  sig_atomic_t panel_active;
 } singlecomp_settings;
 
-extern int pull_singlecomp_feedback(float *peak,float *rms);
+extern int pull_singlecomp_feedback_master(float *peak,float *rms);
+extern int pull_singlecomp_feedback_channel(float *peak,float *rms);
 extern int singlecomp_load(void);
 extern int singlecomp_reset(void);
-extern time_linkage *singlecomp_read(time_linkage *in);
+extern time_linkage *singlecomp_read_master(time_linkage *in);
+extern time_linkage *singlecomp_read_channel(time_linkage *in);

Modified: trunk/postfish/singlepanel.c
===================================================================
--- trunk/postfish/singlepanel.c	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/singlepanel.c	2004-04-24 05:16:26 UTC (rev 6589)
@@ -32,25 +32,55 @@
 #include "singlecomp.h"
 #include "singlepanel.h"
 
-extern sig_atomic_t singlecomp_active;
-extern sig_atomic_t singlecomp_visible;
+extern singlecomp_settings singlecomp_master_set;
+extern singlecomp_settings *singlecomp_channel_set;
+
 extern int input_ch;
 extern int input_size;
 extern int input_rate;
 
-extern singlecomp_settings scset;
-
 typedef struct {
-  GtkWidget *r0;
-  GtkWidget *r1;
-} multireadout;
+  GtkWidget *slider;
+  GtkWidget *readouto;
+  GtkWidget *readoutu;
+  sig_atomic_t *vu;
+  sig_atomic_t *vo;
+} cbar;
 
-GtkWidget *t_label;
-GtkWidget *t_slider;
-multireadout t_readout;
+typedef struct{
+  Readout *r;
+  sig_atomic_t *v;
+} callback_arg_rv;
 
+typedef struct{
+  Readout *r0;
+  Readout *r1;
+  sig_atomic_t *v0;
+  sig_atomic_t *v1;
+} callback_arg_rv2;
 
-static void compand_change(GtkWidget *w,Readout *r,sig_atomic_t *var){
+typedef struct singlecomp_panel_state{
+  callback_arg_rv over_compand;
+  callback_arg_rv under_compand;
+  callback_arg_rv base_compand;
+
+  callback_arg_rv over_lookahead;
+  callback_arg_rv under_lookahead;
+
+  callback_arg_rv2 over_timing;
+  callback_arg_rv2 under_timing;
+  callback_arg_rv2 base_timing;
+
+  singlecomp_settings *ms;
+  cbar bar;
+
+} singlecomp_panel_state;
+
+static singlecomp_panel_state *master_panel;
+static singlecomp_panel_state **channel_panel;
+
+static void compand_change(GtkWidget *w,gpointer in){
+  callback_arg_rv *ca=(callback_arg_rv *)in;
   char buffer[80];
   float val=1./multibar_get_value(MULTIBAR(w),0);
 
@@ -66,143 +96,96 @@
     sprintf(buffer,"1:%4.1f",1./val);
   }
 
-  readout_set(r,buffer);
+  readout_set(ca->r,buffer);
   
-  *var=rint(val*1000.);
+  *ca->v=rint(val*1000.);
 }
-static void under_compand_change(GtkWidget *w,gpointer in){
-  compand_change(w,(Readout *)in,&scset.u_ratio);
-}
 
-static void over_compand_change(GtkWidget *w,gpointer in){
-  compand_change(w,(Readout *)in,&scset.o_ratio);
-}
+static void timing_change(GtkWidget *w,gpointer in){
+  callback_arg_rv2 *ca=(callback_arg_rv2 *)in;
 
-static void base_compand_change(GtkWidget *w,gpointer in){
-  compand_change(w,(Readout *)in,&scset.b_ratio);
-}
-
-static void timing_display(GtkWidget *w,GtkWidget *r,float v){
+  float attack=multibar_get_value(MULTIBAR(w),0);
+  float decay=multibar_get_value(MULTIBAR(w),1);
   char buffer[80];
 
-  if(v<10){
-    sprintf(buffer,"%4.2fms",v);
-  }else if(v<100){
-    sprintf(buffer,"%4.1fms",v);
-  }else if (v<1000){
-    sprintf(buffer,"%4.0fms",v);
-  }else if (v<10000){
-    sprintf(buffer,"%4.2fs",v/1000.);
+  if(attack<10){
+    sprintf(buffer,"%4.2fms",attack);
+  }else if(attack<100){
+    sprintf(buffer,"%4.1fms",attack);
+  }else if (attack<1000){
+    sprintf(buffer,"%4.0fms",attack);
+  }else if (attack<10000){
+    sprintf(buffer,"%4.2fs",attack/1000.);
   }else{
-    sprintf(buffer,"%4.1fs",v/1000.);
+    sprintf(buffer,"%4.1fs",attack/1000.);
   }
+  readout_set(ca->r0,buffer);
 
-  readout_set(READOUT(r),buffer);
-}
+  if(decay<10){
+    sprintf(buffer,"%4.2fms",decay);
+  }else if(decay<100){
+    sprintf(buffer,"%4.1fms",decay);
+  }else if (decay<1000){
+    sprintf(buffer,"%4.0fms",decay);
+  }else if (decay<10000){
+    sprintf(buffer,"%4.2fs",decay/1000.);
+  }else{
+    sprintf(buffer,"%4.1fs",decay/1000.);
+  }
+  readout_set(ca->r1,buffer);
 
-static void under_timing_change(GtkWidget *w,gpointer in){
-  multireadout *r=(multireadout *)in;
-  float attack=multibar_get_value(MULTIBAR(w),0);
-  float decay=multibar_get_value(MULTIBAR(w),1);
-
-  timing_display(w,r->r0,attack);
-  timing_display(w,r->r1,decay);
-
-  scset.u_attack=rint(attack*10.);
-  scset.u_decay=rint(decay*10.);
+  *ca->v0=rint(attack*10.);
+  *ca->v1=rint(decay*10.);
 }
 
-static void over_timing_change(GtkWidget *w,gpointer in){
-  multireadout *r=(multireadout *)in;
-  float attack=multibar_get_value(MULTIBAR(w),0);
-  float decay=multibar_get_value(MULTIBAR(w),1);
-
-  timing_display(w,r->r0,attack);
-  timing_display(w,r->r1,decay);
-
-  scset.o_attack=rint(attack*10.);
-  scset.o_decay=rint(decay*10.);
-}
-
-static void base_timing_change(GtkWidget *w,gpointer in){
-  multireadout *r=(multireadout *)in;
-  float attack=multibar_get_value(MULTIBAR(w),0);
-  float decay=multibar_get_value(MULTIBAR(w),1);
-
-  timing_display(w,r->r0,attack);
-  timing_display(w,r->r1,decay);
-
-  scset.b_attack=rint(attack*10.);
-  scset.b_decay=rint(decay*10.);
-}
-
-static void under_lookahead_change(GtkWidget *w,gpointer in){
+static void lookahead_change(GtkWidget *w,gpointer in){
+  callback_arg_rv *ca=(callback_arg_rv *)in;
   char buffer[80];
-  Readout *r=(Readout *)in;
+  Readout *r=ca->r;
   float val=multibar_get_value(MULTIBAR(w),0);
 
   sprintf(buffer,"%3.0f%%",val);
   readout_set(r,buffer);
   
-  scset.u_lookahead=rint(val*10.);
+  *ca->v=rint(val*10.);
 }
 
-static void over_lookahead_change(GtkWidget *w,gpointer in){
-  char buffer[80];
-  Readout *r=(Readout *)in;
-  float val=multibar_get_value(MULTIBAR(w),0);
-
-  sprintf(buffer,"%3.0f%%",val);
-  readout_set(r,buffer);
-  
-  scset.o_lookahead=rint(val*10.);
-}
-
 static void slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
-  multireadout *r=(multireadout *)in;
+  cbar *b=(cbar *)in;
   int o,u;
 
   u=multibar_get_value(MULTIBAR(w),0);
   sprintf(buffer,"%+4ddB",u);
-  readout_set(READOUT(r->r0),buffer);
-  scset.u_thresh=u;
+  readout_set(READOUT(b->readoutu),buffer);
+  *b->vu=u;
   
   o=multibar_get_value(MULTIBAR(w),1);
   sprintf(buffer,"%+4ddB",o);
-  readout_set(READOUT(r->r1),buffer);
-  scset.o_thresh=o;
+  readout_set(READOUT(b->readouto),buffer);
+  *b->vo=o;
 }
 
-static void over_mode(GtkButton *b,gpointer in){
-  int mode=(int)in;
-  scset.o_mode=mode;
+static void mode_rms(GtkButton *b,gpointer in){
+  sig_atomic_t *var=(sig_atomic_t *)in;
+  *var=0;
 }
 
-static void under_mode(GtkButton *b,gpointer in){
-  int mode=(int)in;
-  scset.u_mode=mode;
+static void mode_peak(GtkButton *b,gpointer in){
+  sig_atomic_t *var=(sig_atomic_t *)in;
+  *var=1;
 }
 
-static void base_mode(GtkButton *b,gpointer in){
-  int mode=(int)in;
-  scset.b_mode=mode;
-}
-
-static void under_knee(GtkToggleButton *b,gpointer in){
+static void mode_knee(GtkToggleButton *b,gpointer in){
   int mode=gtk_toggle_button_get_active(b);
-  scset.u_softknee=mode;
+  sig_atomic_t *var=(sig_atomic_t *)in;
+  *var=mode;
 }
 
-static void over_knee(GtkToggleButton *b,gpointer in){
-  int mode=gtk_toggle_button_get_active(b);
-  scset.o_softknee=mode;
-}
+static singlecomp_panel_state *singlepanel_create_helper (postfish_mainpanel *mp,
+							  subpanel_generic *panel,
+							  singlecomp_settings *scset){
 
-void singlepanel_create(postfish_mainpanel *mp,
-			GtkWidget *windowbutton,
-			GtkWidget *activebutton){
-
   char *labels[14]={"130","120","110","100","90","80","70",
                     "60","50","40","30","20","10","0"};
   float levels[15]={-140,-130,-120,-110,-100,-90,-80,-70,-60,-50,-40,
@@ -217,14 +200,9 @@
   float per_levels[9]={0,12.5,25,37.5,50,62.5,75,87.5,100};
   char  *per_labels[8]={"","25%","","50%","","75%","","100%"};
 
-  char *shortcut[]={" o "};
+  singlecomp_panel_state *ps=calloc(1,sizeof(singlecomp_panel_state));
+  ps->ms=scset;
 
-  subpanel_generic *panel=subpanel_create(mp,windowbutton,&activebutton,
-					  &singlecomp_active,
-					  &singlecomp_visible,
-					  "_Oneband Compand",shortcut,
-					  0,1);
-  
   GtkWidget *sliderframe=gtk_frame_new(NULL);
   GtkWidget *allbox=gtk_vbox_new(0,0);
   GtkWidget *slidertable=gtk_table_new(2,3,0);
@@ -274,7 +252,6 @@
   gtk_box_pack_start(GTK_BOX(panel->subpanel_box),allbox,0,0,0);
   gtk_box_pack_start(GTK_BOX(allbox),sliderframe,0,0,0);
 
-
   {
     GtkWidget *hs1=gtk_hseparator_new();
     GtkWidget *hs2=gtk_hseparator_new();
@@ -307,11 +284,12 @@
     gtk_box_pack_end(GTK_BOX(envelopebox),knee_button,0,0,5);
 
     g_signal_connect (G_OBJECT (knee_button), "clicked",
-		      G_CALLBACK (under_knee), (gpointer)0);
+                      G_CALLBACK (mode_knee), &ps->ms->u_softknee);
     g_signal_connect (G_OBJECT (rms_button), "clicked",
-		      G_CALLBACK (under_mode), (gpointer)0);
+                      G_CALLBACK (mode_rms), &ps->ms->u_mode);
     g_signal_connect (G_OBJECT (peak_button), "clicked",
-		      G_CALLBACK (under_mode), (gpointer)1); //To Hell I Go
+                      G_CALLBACK (mode_peak), &ps->ms->u_mode);
+
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rms_button),1);
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(knee_button),1);
     gtk_table_attach(GTK_TABLE(undertable),envelopebox,0,4,0,1,GTK_FILL,0,0,0);
@@ -324,7 +302,10 @@
     GtkWidget *readout=readout_new("1.55:1");
     GtkWidget *slider=multibar_slider_new(8,compand_labels,compand_levels,1);
    
-    multibar_callback(MULTIBAR(slider),under_compand_change,readout);
+    ps->under_compand.r=READOUT(readout);
+    ps->under_compand.v=&ps->ms->u_ratio;
+
+    multibar_callback(MULTIBAR(slider),compand_change,&ps->under_compand);
     multibar_thumb_set(MULTIBAR(slider),1.,0);
 
     gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
@@ -340,15 +321,16 @@
   {
 
     GtkWidget *label=gtk_label_new("attack/decay:");
+    GtkWidget *readout0=readout_new(" 100ms");
     GtkWidget *readout1=readout_new(" 100ms");
-    GtkWidget *readout2=readout_new(" 100ms");
     GtkWidget *slider=multibar_slider_new(5,timing_labels,timing_levels,2);
-    multireadout *r=calloc(1,sizeof(*r));
 
-    r->r0=readout1;
-    r->r1=readout2;
+    ps->under_timing.r0=READOUT(readout0);
+    ps->under_timing.r1=READOUT(readout1);
+    ps->under_timing.v0=&ps->ms->u_attack;
+    ps->under_timing.v1=&ps->ms->u_decay;
    
-    multibar_callback(MULTIBAR(slider),under_timing_change,r);
+    multibar_callback(MULTIBAR(slider),timing_change,&ps->under_timing);
     multibar_thumb_set(MULTIBAR(slider),1,0);
     multibar_thumb_set(MULTIBAR(slider),100,1);
 
@@ -357,8 +339,8 @@
     gtk_table_set_row_spacing(GTK_TABLE(undertable),2,4);
     gtk_table_attach(GTK_TABLE(undertable),label,0,1,4,5,GTK_FILL,0,2,0);
     gtk_table_attach(GTK_TABLE(undertable),slider,1,2,4,5,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
-    gtk_table_attach(GTK_TABLE(undertable),readout1,2,3,4,5,GTK_FILL,0,0,0);
-    gtk_table_attach(GTK_TABLE(undertable),readout2,3,4,4,5,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(undertable),readout0,2,3,4,5,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(undertable),readout1,3,4,4,5,GTK_FILL,0,0,0);
 
   }
 
@@ -369,7 +351,10 @@
     GtkWidget *readout=readout_new("100%");
     GtkWidget *slider=multibar_slider_new(8,per_labels,per_levels,1);
     
-    multibar_callback(MULTIBAR(slider),under_lookahead_change,readout);
+    ps->under_lookahead.r=READOUT(readout);
+    ps->under_lookahead.v=&ps->ms->u_lookahead;
+    
+    multibar_callback(MULTIBAR(slider),lookahead_change,&ps->under_lookahead);    
     multibar_thumb_set(MULTIBAR(slider),100.,0);
     multibar_thumb_increment(MULTIBAR(slider),1.,10.);
 
@@ -396,11 +381,12 @@
     gtk_box_pack_end(GTK_BOX(envelopebox),knee_button,0,0,5);
 
     g_signal_connect (G_OBJECT (knee_button), "clicked",
-		      G_CALLBACK (over_knee), (gpointer)0);
+                      G_CALLBACK (mode_knee), &ps->ms->o_softknee);
     g_signal_connect (G_OBJECT (rms_button), "clicked",
-		      G_CALLBACK (over_mode), (gpointer)0);
+                      G_CALLBACK (mode_rms), &ps->ms->o_mode);
     g_signal_connect (G_OBJECT (peak_button), "clicked",
-		      G_CALLBACK (over_mode), (gpointer)1); //To Hell I Go
+                      G_CALLBACK (mode_peak), &ps->ms->o_mode);
+
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rms_button),1);
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(knee_button),1);
     gtk_table_attach(GTK_TABLE(overtable),envelopebox,0,4,0,1,GTK_FILL,0,0,0);
@@ -412,8 +398,11 @@
     GtkWidget *label=gtk_label_new("compand ratio:");
     GtkWidget *readout=readout_new("1.55:1");
     GtkWidget *slider=multibar_slider_new(8,compand_labels,compand_levels,1);
-   
-    multibar_callback(MULTIBAR(slider),over_compand_change,readout);
+
+    ps->over_compand.r=READOUT(readout);
+    ps->over_compand.v=&ps->ms->o_ratio;
+
+    multibar_callback(MULTIBAR(slider),compand_change,&ps->over_compand);
     multibar_thumb_set(MULTIBAR(slider),1.,0);
 
     gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
@@ -429,15 +418,16 @@
   {
 
     GtkWidget *label=gtk_label_new("attack/decay:");
+    GtkWidget *readout0=readout_new(" 100ms");
     GtkWidget *readout1=readout_new(" 100ms");
-    GtkWidget *readout2=readout_new(" 100ms");
     GtkWidget *slider=multibar_slider_new(5,timing_labels,timing_levels,2);
    
-    multireadout *r=calloc(1,sizeof(*r));
-    r->r0=readout1;
-    r->r1=readout2;
-
-    multibar_callback(MULTIBAR(slider),over_timing_change,r);
+    ps->over_timing.r0=READOUT(readout0);
+    ps->over_timing.r1=READOUT(readout1);
+    ps->over_timing.v0=&ps->ms->o_attack;
+    ps->over_timing.v1=&ps->ms->o_decay;
+    
+    multibar_callback(MULTIBAR(slider),timing_change,&ps->over_timing);
     multibar_thumb_set(MULTIBAR(slider),1,0);
     multibar_thumb_set(MULTIBAR(slider),100,1);
 
@@ -446,8 +436,8 @@
     gtk_table_set_row_spacing(GTK_TABLE(overtable),2,4);
     gtk_table_attach(GTK_TABLE(overtable),label,0,1,5,6,GTK_FILL,0,2,0);
     gtk_table_attach(GTK_TABLE(overtable),slider,1,2,5,6,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
-    gtk_table_attach(GTK_TABLE(overtable),readout1,2,3,5,6,GTK_FILL,0,0,0);
-    gtk_table_attach(GTK_TABLE(overtable),readout2,3,4,5,6,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(overtable),readout0,2,3,5,6,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(overtable),readout1,3,4,5,6,GTK_FILL,0,0,0);
 
   }
 
@@ -458,7 +448,10 @@
     GtkWidget *readout=readout_new("100%");
     GtkWidget *slider=multibar_slider_new(8,per_labels,per_levels,1);
    
-    multibar_callback(MULTIBAR(slider),over_lookahead_change,readout);
+    ps->over_lookahead.r=READOUT(readout);
+    ps->over_lookahead.v=&ps->ms->o_lookahead;
+    
+    multibar_callback(MULTIBAR(slider),lookahead_change,&ps->over_lookahead);
     multibar_thumb_set(MULTIBAR(slider),100.,0);
     multibar_thumb_increment(MULTIBAR(slider),1.,10.);
 
@@ -484,9 +477,10 @@
     gtk_box_pack_end(GTK_BOX(envelopebox),rms_button,0,0,5);
 
     g_signal_connect (G_OBJECT (rms_button), "clicked",
-		      G_CALLBACK (base_mode), (gpointer)0);
+                      G_CALLBACK (mode_rms), &ps->ms->b_mode);
     g_signal_connect (G_OBJECT (peak_button), "clicked",
-		      G_CALLBACK (base_mode), (gpointer)1); //To Hell I Go
+                      G_CALLBACK (mode_peak), &ps->ms->b_mode);
+
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rms_button),1);
     gtk_table_attach(GTK_TABLE(basetable),envelopebox,0,4,0,1,GTK_FILL,0,0,0);
   }
@@ -498,7 +492,10 @@
     GtkWidget *readout=readout_new("1.55:1");
     GtkWidget *slider=multibar_slider_new(8,compand_labels,compand_levels,1);
    
-    multibar_callback(MULTIBAR(slider),base_compand_change,readout);
+    ps->base_compand.r=READOUT(readout);
+    ps->base_compand.v=&ps->ms->b_ratio;
+
+    multibar_callback(MULTIBAR(slider),compand_change,&ps->base_compand);
     multibar_thumb_set(MULTIBAR(slider),1.,0);
 
     gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
@@ -514,15 +511,16 @@
   {
 
     GtkWidget *label=gtk_label_new("attack/decay:");
+    GtkWidget *readout0=readout_new(" 100ms");
     GtkWidget *readout1=readout_new(" 100ms");
-    GtkWidget *readout2=readout_new(" 100ms");
     GtkWidget *slider=multibar_slider_new(5,timing_labels,timing_levels,2);
-    multireadout *r=calloc(1,sizeof(*r));
 
-    r->r0=readout1;
-    r->r1=readout2;
+    ps->base_timing.r0=READOUT(readout0);
+    ps->base_timing.r1=READOUT(readout1);
+    ps->base_timing.v0=&ps->ms->b_attack;
+    ps->base_timing.v1=&ps->ms->b_decay;
    
-    multibar_callback(MULTIBAR(slider),base_timing_change,r);
+    multibar_callback(MULTIBAR(slider),timing_change,&ps->base_timing);
     multibar_thumb_set(MULTIBAR(slider),1,0);
     multibar_thumb_set(MULTIBAR(slider),100,1);
 
@@ -531,54 +529,111 @@
     gtk_table_set_row_spacing(GTK_TABLE(basetable),2,4);
     gtk_table_attach(GTK_TABLE(basetable),label,0,1,4,5,GTK_FILL,0,2,0);
     gtk_table_attach(GTK_TABLE(basetable),slider,1,2,4,5,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
-    gtk_table_attach(GTK_TABLE(basetable),readout1,2,3,4,5,GTK_FILL,0,0,0);
-    gtk_table_attach(GTK_TABLE(basetable),readout2,3,4,4,5,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(basetable),readout0,2,3,4,5,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(basetable),readout1,3,4,4,5,GTK_FILL,0,0,0);
 
   }
 
-  /* threshold controls */
+  /* threshold control */
 
   {
-    t_readout.r0=readout_new("  +0");
-    t_readout.r1=readout_new("  +0");
-    t_slider=multibar_new(14,labels,levels,2,HI_DECAY|LO_DECAY|LO_ATTACK);
+    ps->bar.readoutu=readout_new("  +0");
+    ps->bar.readouto=readout_new("  +0");
+    ps->bar.slider=multibar_new(14,labels,levels,2,HI_DECAY|LO_DECAY|LO_ATTACK);
+    ps->bar.vu=&ps->ms->u_thresh;
+    ps->bar.vo=&ps->ms->o_thresh;
 
-    multibar_callback(MULTIBAR(t_slider),slider_change,&t_readout);
-    multibar_thumb_set(MULTIBAR(t_slider),-140.,0);
-    multibar_thumb_set(MULTIBAR(t_slider),0.,1);
-    multibar_thumb_bounds(MULTIBAR(t_slider),-140,0);
-    multibar_thumb_increment(MULTIBAR(t_slider),1.,10.);
+    multibar_callback(MULTIBAR(ps->bar.slider),slider_change,&ps->bar);
+    multibar_thumb_set(MULTIBAR(ps->bar.slider),-140.,0);
+    multibar_thumb_set(MULTIBAR(ps->bar.slider),0.,1);
+    multibar_thumb_bounds(MULTIBAR(ps->bar.slider),-140,0);
+    multibar_thumb_increment(MULTIBAR(ps->bar.slider),1.,10.);
     
     
-    gtk_table_attach(GTK_TABLE(slidertable),t_readout.r0,0,1,1,2,
+    gtk_table_attach(GTK_TABLE(slidertable),ps->bar.readoutu,0,1,1,2,
                      0,0,0,0);
-    gtk_table_attach(GTK_TABLE(slidertable),t_slider,1,2,1,2,
+    gtk_table_attach(GTK_TABLE(slidertable),ps->bar.slider,1,2,1,2,
                      GTK_FILL|GTK_EXPAND,GTK_EXPAND,0,0);
-    gtk_table_attach(GTK_TABLE(slidertable),t_readout.r1,2,3,1,2,
+    gtk_table_attach(GTK_TABLE(slidertable),ps->bar.readouto,2,3,1,2,
                      0,0,0,0);
   }
   
   subpanel_show_all_but_toplevel(panel);
-
+  
+  return ps;
 }
 
 static float *peakfeed=0;
 static float *rmsfeed=0;
 
 void singlepanel_feedback(int displayit){
+  int j;
   if(!peakfeed){
     peakfeed=malloc(sizeof(*peakfeed)*input_ch);
     rmsfeed=malloc(sizeof(*rmsfeed)*input_ch);
   }
   
-  if(pull_singlecomp_feedback(peakfeed,rmsfeed)==1)
-    multibar_set(MULTIBAR(t_slider),rmsfeed,peakfeed,
-		 input_ch,(displayit && singlecomp_visible));
+  if(pull_singlecomp_feedback_master(peakfeed,rmsfeed)==1)
+    multibar_set(MULTIBAR(master_panel->bar.slider),rmsfeed,peakfeed,
+		 input_ch,(displayit && singlecomp_master_set.panel_visible));
+  
+  /* channel panels are a bit different; we want each in its native color */
+  if(pull_singlecomp_feedback_channel(peakfeed,rmsfeed)==1){
+    for(j=0;j<input_ch;j++){
+      float rms[input_ch];
+      float peak[input_ch];
+      
+      memset(rms,0,sizeof(rms));
+      memset(peak,0,sizeof(peak));
+      rms[j]=rmsfeed[j];
+      peak[j]=peakfeed[j];
+      
+      multibar_set(MULTIBAR(channel_panel[j]->bar.slider),rms,peak,
+		   input_ch,(displayit && singlecomp_channel_set[j].panel_visible));
+    }
+  }
 }
 
 void singlepanel_reset(void){
-  multibar_reset(MULTIBAR(t_slider));
+  int j;
+  multibar_reset(MULTIBAR(master_panel->bar.slider));
+  for(j=0;j<input_ch;j++)
+    multibar_reset(MULTIBAR(channel_panel[j]->bar.slider));
 }
 
 
+void singlepanel_create_master(postfish_mainpanel *mp,
+			       GtkWidget *windowbutton,
+			       GtkWidget *activebutton){
+  
+  char *shortcut[]={" s "};
+  subpanel_generic *panel=subpanel_create(mp,windowbutton,&activebutton,
+					  &singlecomp_master_set.panel_active,
+					  &singlecomp_master_set.panel_visible,
+					  "_Singleband Compand",shortcut,
+					  0,1);
+  master_panel=singlepanel_create_helper(mp,panel,&singlecomp_master_set);
+}
 
+void singlepanel_create_channel(postfish_mainpanel *mp,
+				GtkWidget **windowbutton,
+				GtkWidget **activebutton){
+  int i;
+  
+  channel_panel=calloc(input_ch,sizeof(*channel_panel));
+  
+  /* a panel for each channel */
+  for(i=0;i<input_ch;i++){
+    subpanel_generic *panel;
+    char buffer[80];
+    
+    sprintf(buffer,"_Singleband Compand (channel %d)",i+1);
+    panel=subpanel_create(mp,windowbutton[i],activebutton+i,
+                          &singlecomp_channel_set[i].panel_active,
+                          &singlecomp_channel_set[i].panel_visible,
+                          buffer,NULL,
+                          i,1);
+    
+    channel_panel[i]=singlepanel_create_helper(mp,panel,singlecomp_channel_set+i);
+  }
+}

Modified: trunk/postfish/singlepanel.h
===================================================================
--- trunk/postfish/singlepanel.h	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/singlepanel.h	2004-04-24 05:16:26 UTC (rev 6589)
@@ -21,9 +21,12 @@
  * 
  */
 
-extern void singlepanel_create(postfish_mainpanel *mp,
-			       GtkWidget *windowbutton,
-			       GtkWidget *activebutton);
+extern void singlepanel_create_master(postfish_mainpanel *mp,
+				      GtkWidget *windowbutton,
+				      GtkWidget *activebutton);
+extern void singlepanel_create_channel(postfish_mainpanel *mp,
+				       GtkWidget **windowbutton,
+				       GtkWidget **activebutton);
 extern void singlepanel_feedback(int displayit);
 extern void singlepanel_reset(void);
 

Modified: trunk/postfish/version.h
===================================================================
--- trunk/postfish/version.h	2004-04-24 00:22:04 UTC (rev 6588)
+++ trunk/postfish/version.h	2004-04-24 05:16:26 UTC (rev 6589)
@@ -1,2 +1,2 @@
 #define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Fri Apr 23 20:18:58 EDT 2004] */
+/* DO NOT EDIT: Automated versioning hack [Sat Apr 24 01:12:30 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