[xiph-cvs] cvs commit: postfish lpc.c lpc.h multicompand.c multicompand.h Makefile clippanel.c compandpanel.c declip.c declip.h eq.c eq.h eqpanel.c freq.c freq.h input.c input.h main.c mainpanel.c multibar.c multibar.h output.c output.h postfish.h readout.c reconstruct.c reconstruct.h version.h

Monty xiphmont at xiph.org
Sat Feb 28 19:16:18 PST 2004



xiphmont    04/02/28 22:16:18

  Modified:    .        Makefile clippanel.c compandpanel.c declip.c
                        declip.h eq.c eq.h eqpanel.c freq.c freq.h input.c
                        input.h main.c mainpanel.c multibar.c multibar.h
                        output.c output.h postfish.h readout.c
                        reconstruct.c reconstruct.h version.h
  Added:       .        lpc.c lpc.h multicompand.c multicompand.h
  Log:
  Avoid losing work in progress

Revision  Changes    Path
1.14      +7 -7      postfish/Makefile

Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/postfish/Makefile,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Makefile	20 Feb 2004 02:09:39 -0000	1.13
+++ Makefile	29 Feb 2004 03:16:17 -0000	1.14
@@ -11,21 +11,21 @@
 MANDIR=$PREFIX/man
 
 SRC = main.c mainpanel.c multibar.c readout.c input.c output.c clippanel.c \
-	declip.c reconstruct.c smallft.c windowbutton.c subpanel.c \
-	feedback.c freq.c eq.c eqpanel.c compand.c compandpanel.c
+	declip.c reconstruct.c multicompand.c windowbutton.c subpanel.c \
+	feedback.c freq.c eq.c eqpanel.c compandpanel.c subband.c lpc.c
 OBJ = main.o mainpanel.o multibar.o readout.o input.o output.o clippanel.o \
-	declip.o reconstruct.o smallft.o windowbutton.o subpanel.o \
-	feedback.o freq.o eq.o eqpanel.o compand.o compandpanel.o
+	declip.o reconstruct.o multicompand.o windowbutton.o subpanel.o \
+	feedback.o freq.o eq.o eqpanel.o compandpanel.o subband.o lpc.o
 GCF = `pkg-config --cflags gtk+-2.0` -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED
 
 all:	
-	$(MAKE) target CFLAGS="-W -O2 $(GCF)"
+	$(MAKE) target CFLAGS="-W -O3 -ffast-math $(GCF)"
 
 debug:
         $(MAKE) target CFLAGS="-g -W -D__NO_MATH_INLINES $(GCF)"
 
 profile:
-	$(MAKE) target CFLAGS="-W -pg -g -O2 $(GCF)"
+	$(MAKE) target CFLAGS="-W -pg -g -O3 $(GCF)"
 
 clean:
         rm -f $(OBJ) *.d 
@@ -37,7 +37,7 @@
 
 target: $(OBJ)
         ./touch-version
-	$(LD) $(OBJ) $(CFLAGS) -o postfish `pkg-config --libs gtk+-2.0` -lpthread -lm
+	$(LD) $(OBJ) $(CFLAGS) -o postfish `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm
 
 install:
         $(INSTALL) -d -m 0755 $(BINDIR)

<p><p>1.14      +40 -39    postfish/clippanel.c

Index: clippanel.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/clippanel.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- clippanel.c	20 Feb 2004 06:06:00 -0000	1.13
+++ clippanel.c	29 Feb 2004 03:16:17 -0000	1.14
@@ -58,7 +58,7 @@
 static void trigger_slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
   clipslider *p=(clipslider *)in;
-  gdouble linear=multibar_get_value(MULTIBAR(p->slider),0);
+  float linear=multibar_get_value(MULTIBAR(p->slider),0);
   
   sprintf(buffer,"%1.2f",linear);
   readout_set(READOUT(p->readout),buffer);
@@ -72,7 +72,7 @@
 
 static void blocksize_slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
-  int choice=rint(gtk_range_get_value(GTK_RANGE(w)));
+  int choice=rint(multibar_get_value(MULTIBAR(w),0));
   int blocksize=64<<choice;
 
   sprintf(buffer,"%5d  ",blocksize);
@@ -89,8 +89,8 @@
 
 static void depth_slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
-  double dB=gtk_range_get_value(GTK_RANGE(w));
-
+  float dB=multibar_get_value(MULTIBAR(w),0);
+  
   sprintf(buffer,"%3ddB",(int)dB);
   readout_set(READOUT(depth_readout),buffer);
 
@@ -99,7 +99,7 @@
 
 static void limit_slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
-  double percent=gtk_range_get_value(GTK_RANGE(w));
+  float percent=multibar_get_value(MULTIBAR(w),0);
 
   sprintf(buffer,"%3d%%",(int)percent);
   readout_set(READOUT(limit_readout),buffer);
@@ -112,7 +112,7 @@
                       GtkWidget *activebutton){
   int i;
   char *labels[2]={"10%","100%"};
-  double levels[3]={0.,10.,100.};
+  float levels[3]={0.,10.,100.};
   int block_choices=0;
 
   subpanel_generic *panel=subpanel_create(mp,windowbutton,activebutton,
@@ -142,11 +142,14 @@
   /* set up blocksize config */
   for(i=64;i<=input_size*2;i*=2)block_choices++;
   {
+    float levels[9]={0,1,2,3,4,5,6,7,8};
+    char *labels[8]={"128","256","512","1024","2048","4096","8192","16384"};
+
     GtkWidget *table=gtk_table_new(4,2,0);
     GtkWidget *sliderbox=gtk_hbox_new(0,0);
     GtkWidget *fastlabel=gtk_label_new("fastest");
     GtkWidget *qualitylabel=gtk_label_new("best");
-    GtkWidget *slider=gtk_hscale_new_with_range(0,block_choices-1,1);
+    GtkWidget *slider=multibar_slider_new(block_choices-1,labels,levels,1);
     GtkWidget *samplelabel=gtk_label_new("window sample width");
     GtkWidget *mslabel=gtk_label_new("window time width");
     GtkWidget *hzlabel=gtk_label_new("approximate lowest response");
@@ -154,7 +157,6 @@
     msreadout=readout_new("00000ms");
     hzreadout=readout_new("00000Hz");
 
-    gtk_scale_set_draw_value(GTK_SCALE(slider),FALSE);
     gtk_misc_set_alignment(GTK_MISC(samplelabel),1,.5);
     gtk_misc_set_alignment(GTK_MISC(mslabel),1,.5);
     gtk_misc_set_alignment(GTK_MISC(hzlabel),1,.5);
@@ -172,27 +174,26 @@
     gtk_table_attach(GTK_TABLE(table),hzreadout,1,2,3,4,GTK_FILL,0,5,0);
     gtk_container_add(GTK_CONTAINER(blocksize_box),table);
 
+    multibar_thumb_increment(MULTIBAR(slider),1.,1.);
+    multibar_callback(MULTIBAR(slider),blocksize_slider_change,0);
 
-    g_signal_connect (G_OBJECT (slider), "key-press-event",
-		      G_CALLBACK (slider_keymodify), NULL);
-    g_signal_connect_after (G_OBJECT(slider), "value-changed",
-			    G_CALLBACK(blocksize_slider_change), 0);
-    gtk_range_set_value(GTK_RANGE(slider),2.);
+    multibar_thumb_set(MULTIBAR(slider),2.,0);
     
   }
   gtk_container_add(GTK_CONTAINER(blocksize_frame),blocksize_box);
 
   /* set up convergence config */
   {
+    float levels[7]={20,40,60,80,100,120,140};
+    char *labels[6]={"40","60","80","100","120","140"};
     GtkWidget *table=gtk_table_new(2,2,0);
     GtkWidget *sliderbox=gtk_hbox_new(0,0);
     GtkWidget *fastlabel=gtk_label_new("fastest");
     GtkWidget *qualitylabel=gtk_label_new("best");
-    GtkWidget *slider=gtk_hscale_new_with_range(1,140,1);
+    GtkWidget *slider=multibar_slider_new(6,labels,levels,1);
     GtkWidget *label=gtk_label_new("solution depth");
     depth_readout=readout_new("000dB");
 
-    gtk_scale_set_draw_value(GTK_SCALE(slider),FALSE);
     gtk_misc_set_alignment(GTK_MISC(label),1,.5);
 
     gtk_box_pack_start(GTK_BOX(sliderbox),fastlabel,0,0,4);
@@ -205,25 +206,24 @@
 
     gtk_container_add(GTK_CONTAINER(converge_box),table);
 
-    g_signal_connect (G_OBJECT (slider), "key-press-event",
-		      G_CALLBACK (slider_keymodify), NULL);
-    g_signal_connect_after (G_OBJECT(slider), "value-changed",
-			    G_CALLBACK(depth_slider_change), 0);
-    gtk_range_set_value(GTK_RANGE(slider),60.);
+    multibar_thumb_increment(MULTIBAR(slider),1.,10.);
+    multibar_callback(MULTIBAR(slider),depth_slider_change,0);
+    multibar_thumb_set(MULTIBAR(slider),60.,0);
   }
 
 
   /* set up limit config */
   {
+    float levels[7]={1,5,10,20,40,60,100};
+    char *labels[6]={"5","10","20","40","60","100"};
     GtkWidget *table=gtk_table_new(2,2,0);
     GtkWidget *sliderbox=gtk_hbox_new(0,0);
     GtkWidget *fastlabel=gtk_label_new("fastest");
     GtkWidget *qualitylabel=gtk_label_new("best");
-    GtkWidget *slider=gtk_hscale_new_with_range(1,100,1);
+    GtkWidget *slider=multibar_slider_new(6,labels,levels,1);
     GtkWidget *label=gtk_label_new("hard iteration limit");
     limit_readout=readout_new("000%");
 
-    gtk_scale_set_draw_value(GTK_SCALE(slider),FALSE);
     gtk_misc_set_alignment(GTK_MISC(label),1,.5);
 
     gtk_box_pack_start(GTK_BOX(sliderbox),fastlabel,0,0,4);
@@ -236,17 +236,15 @@
 
     gtk_container_add(GTK_CONTAINER(limit_box),table);
 
-    g_signal_connect (G_OBJECT (slider), "key-press-event",
-		      G_CALLBACK (slider_keymodify), NULL);
-    g_signal_connect_after (G_OBJECT(slider), "value-changed",
-			    G_CALLBACK(limit_slider_change), 0);
-    gtk_range_set_value(GTK_RANGE(slider),100.);
+    multibar_thumb_increment(MULTIBAR(slider),1.,10.);
+    multibar_callback(MULTIBAR(slider),limit_slider_change,0);
+    multibar_thumb_set(MULTIBAR(slider),100.,0);
   }
 
   for(i=0;i<input_ch;i++){
     char *slabels[8]={".05",".1",".2",".3",".4",
                       ".6",".8","1."};
-    double slevels[9]={.01,.05,.1,.2,.3,.4,.6,
+    float slevels[9]={.01,.05,.1,.2,.3,.4,.6,
                        .8,1.};
 
     char buffer[80];
@@ -320,26 +318,29 @@
 
 void clippanel_feedback(int displayit){
   int clip[input_ch],count;
-  double peak[input_ch];
+  float peak[input_ch];
   if(pull_declip_feedback(clip,peak,&count)){
     int i;
     for(i=0;i<input_ch;i++){
-      double val[2],zero[2];
+      float val[2],zero[2];
       val[0]=-1.,zero[0]=-1.;
       val[1]=(count?clip[i]*100./count-.1:-1);
       zero[1]=-1.;
 
-      if(displayit && declip_visible){
-	multibar_set(MULTIBAR(feedback_bars[i]),zero,val,2);
-	
-	val[0]=(count?peak[i]:-1);
-	multibar_set(MULTIBAR(trigger_bars[i]),zero,val,1);
-      }
+      multibar_set(MULTIBAR(feedback_bars[i]),zero,val,2,
+		   (displayit && declip_visible));
+      
+      val[0]=(count?peak[i]:-1);
+      multibar_set(MULTIBAR(trigger_bars[i]),zero,val,1,
+		   (displayit && declip_visible));
 
       if(clip[i]){
-	multibar_setwarn(MULTIBAR(mainpanel_inbar));
-	multibar_setwarn(MULTIBAR(feedback_bars[i]));
-	multibar_setwarn(MULTIBAR(trigger_bars[i]));
+	multibar_setwarn(MULTIBAR(mainpanel_inbar),
+			 (displayit && declip_visible));
+	multibar_setwarn(MULTIBAR(feedback_bars[i]),
+			 (displayit && declip_visible));
+	multibar_setwarn(MULTIBAR(trigger_bars[i]),
+			 (displayit && declip_visible));
       }
     }
   }

<p><p>1.4       +281 -66   postfish/compandpanel.c

Index: compandpanel.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/compandpanel.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- compandpanel.c	20 Feb 2004 06:06:00 -0000	1.3
+++ compandpanel.c	29 Feb 2004 03:16:17 -0000	1.4
@@ -29,8 +29,7 @@
 #include "mainpanel.h"
 #include "subpanel.h"
 #include "feedback.h"
-#include "freq.h"
-#include "compand.h"
+#include "multicompand.h"
 #include "compandpanel.h"
 
 extern sig_atomic_t compand_active;
@@ -39,6 +38,7 @@
 extern int input_size;
 extern int input_rate;
 
+extern compand_settings c;
 
 typedef struct {
   GtkWidget *slider;
@@ -48,114 +48,187 @@
   int number;
 } cbar;
 
-static cbar bars[freqs];
+static cbar bars[multicomp_freqs];
+
+static void static_compressor_change(GtkWidget *w,gpointer in){
+  char buffer[80];
+  Readout *r=READOUT(in);
+  float val=-multibar_get_value(MULTIBAR(w),0);
+
+  if(rint(1./val)>=10.)
+    sprintf(buffer,"%3.0f:1",1./val);
+  else
+    sprintf(buffer,"%3.1f:1",1./val);
+
+  if(val==1.)
+    sprintf(buffer,"  off");
+
+  readout_set(r,buffer);
+  c.static_c_ratio=rint(100./val);
+}
+
+static void static_expander_change(GtkWidget *w,gpointer in){
+  char buffer[80];
+  Readout *r=READOUT(in);
+  float val=-multibar_get_value(MULTIBAR(w),0);
+
+  if(rint(1./val)>=10.)
+    sprintf(buffer,"%3.0f:1",1./val);
+  else
+  sprintf(buffer,"%3.1f:1",1./val);
+
+  if(val==1.)
+    sprintf(buffer,"  off");
+
+  readout_set(r,buffer);
+  c.static_e_ratio=rint(100./val);
+}
+
+static void static_decay_change(GtkWidget *w,gpointer in){
+  char buffer[80];
+  Readout *r=READOUT(in);
+  float val=-multibar_get_value(MULTIBAR(w),0);
+
+  sprintf(buffer,"%.2f",val);
+
+  if(val==1.)
+    sprintf(buffer," fast");
+
+  if(val==.01)
+    sprintf(buffer," slow");
+
+  readout_set(r,buffer);
+  c.static_decay=rint(100./val);
+}
+
+static void static_trim_change(GtkWidget *w,gpointer in){
+  char buffer[80];
+  Readout *r=READOUT(in);
+  float val=multibar_get_value(MULTIBAR(w),0);
+
+  sprintf(buffer,"%+2.0fdB",val);
+
+  readout_set(r,buffer);
+  c.static_trim=rint(val*10.);
+}
+
+static void static_trim_apply(GtkWidget *w,gpointer in){
+  char buffer[80];
+  Multibar *m=MULTIBAR(in);
+  float val=multibar_get_value(m,0);
+
+  /* XXXXX */
+}
 
 static void link_toggled(GtkToggleButton *b,gpointer in){
   int active=gtk_toggle_button_get_active(b);
-  compand_set_link(active);    
+  c.link_mode=active;
 }
 
-static void suppressor_mode(GtkButton *b,gpointer in){
+static void static_mode(GtkButton *b,gpointer in){
   int mode=(int)in;
+  c.static_mode=mode;
+}
 
-  if(mode)
-    /* peak mode */
-    compand_s_peakmode();
-  else
-    /* rms mode */
-    compand_s_rmsmode();
+static void suppressor_mode(GtkButton *b,gpointer in){
+  int mode=(int)in;
+  c.suppress_mode=mode;
+}
 
+static void envelope_mode(GtkButton *b,gpointer in){
+  int mode=(int)in;
+  c.envelope_mode=mode;
 }
 
 static void suppress_bias_change(GtkWidget *w,gpointer in){
   char buffer[80];
   Readout *r=READOUT(in);
-  gdouble val=multibar_get_value(MULTIBAR(w),0);
+  float val=multibar_get_value(MULTIBAR(w),0);
 
   sprintf(buffer,"%+2.0fdB",val);
   readout_set(r,buffer);
-  compand_s_setbias(val);
+  c.suppress_bias=rint(val*10.);
 }
 
 static void suppress_decay_change(GtkWidget *w,gpointer in){
   char buffer[80];
   Readout *r=READOUT(in);
-  gdouble val=-multibar_get_value(MULTIBAR(w),0);
+  float val=-multibar_get_value(MULTIBAR(w),0);
 
   sprintf(buffer,"%.2f",val);
 
   if(val==1.)
-    sprintf(buffer,"fast");
+    sprintf(buffer," fast");
 
   if(val==.01)
-    sprintf(buffer,"slow");
+    sprintf(buffer," slow");
 
   readout_set(r,buffer);
-  compand_s_setdecay(val);
+  c.suppress_decay=rint(100./val);
 }
 
 static void suppress_ratio_change(GtkWidget *w,gpointer in){
   char buffer[80];
   Readout *r=READOUT(in);
-  gdouble val=-multibar_get_value(MULTIBAR(w),0);
+  float val=-multibar_get_value(MULTIBAR(w),0);
 
   sprintf(buffer,"%3.1f:1",1./val);
 
   if(val==1.)
-    sprintf(buffer,"off");
+    sprintf(buffer,"  off");
 
   if(val==.1)
-    sprintf(buffer,"gate");
+    sprintf(buffer," gate");
 
   readout_set(r,buffer);
-  compand_s_setratio(val);
+  c.suppress_ratio=rint(100./val);
 }
 
 static void suppress_depth_change(GtkWidget *w,gpointer in){
   char buffer[80];
   Readout *r=READOUT(in);
-  gdouble val=-140.-multibar_get_value(MULTIBAR(w),0);
+  float val=-140.-multibar_get_value(MULTIBAR(w),0);
   
   sprintf(buffer,"%3.0fdB",-val);
 
   if(val==0.)
-    sprintf(buffer,"off");
+    sprintf(buffer,"  off");
 
   if(val==-140)
-    sprintf(buffer,"deep");
+    sprintf(buffer," deep");
 
-  readout_set(r,buffer);
-  compand_s_setdepth(val);
+  readout_set(r,buffer); 
+  c.suppress_depth=rint(val*10.);
 }
 
 static void envelope_compander_change(GtkWidget *w,gpointer in){
   char buffer[80];
   Readout *r=READOUT(in);
-  gdouble val=multibar_get_value(MULTIBAR(w),0);
+  float val=multibar_get_value(MULTIBAR(w),0);
 
-  sprintf(buffer,"%3.1f%%",val);
+  sprintf(buffer,"%+5.1f%%",val);
   readout_set(r,buffer);
-  compand_ec_set(val);
+  c.envelope_c=rint(val*10.);
 }
 
 static void slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
   cbar *b=(cbar *)in;
 
-  gdouble val=multibar_get_value(MULTIBAR(b->slider),0);
+  float val=multibar_get_value(MULTIBAR(b->slider),0);
   sprintf(buffer,"%3.0fdB",val);
   readout_set(READOUT(b->readoutg),buffer);
-  compand_g_set(b->number,val);
+  c.static_g[b->number]=rint(val*10.);
   
   val=multibar_get_value(MULTIBAR(b->slider),1);
   sprintf(buffer,"%+4.0fdB",val);
   readout_set(READOUT(b->readoute),buffer);
-  compand_e_set(b->number,val);
+  c.static_e[b->number]=rint(val*10.);
 
   val=multibar_get_value(MULTIBAR(b->slider),2);
   sprintf(buffer,"%+4.0fdB",val);
   readout_set(READOUT(b->readoutc),buffer);
-  compand_c_set(b->number,val);
+  c.static_c[b->number]=rint(val*10.);
 
 }
 
@@ -163,9 +236,9 @@
                          GtkWidget *windowbutton,
                          GtkWidget *activebutton){
   int i;
-  char *labels[14]={"-130","-120","-110","-100","-90","-80","-70",
-		    "-60","-50","-40","-30","-20","-10","0"};
-  double levels[15]={-140,-130,-120,-110,-100,-90,-80,-70,-60,-50,-40,
+  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,
                      -30,-20,-10,0};
 
   subpanel_generic *panel=subpanel_create(mp,windowbutton,activebutton,
@@ -175,18 +248,22 @@
   
   GtkWidget *hbox=gtk_hbox_new(0,0);
   GtkWidget *staticbox=gtk_vbox_new(0,0);
+  GtkWidget *staticframe=gtk_frame_new(NULL);
   GtkWidget *envelopeframe=gtk_frame_new(" Envelope Compander ");
   GtkWidget *suppressframe=gtk_frame_new(" Suppressor ");
 
-  GtkWidget *envelopetable=gtk_table_new(2,3,0);
+  GtkWidget *envelopetable=gtk_table_new(3,3,0);
   GtkWidget *suppresstable=gtk_table_new(5,3,0);
+  GtkWidget *statictable=gtk_table_new(6,4,0);
 
-  GtkWidget *slidertable=gtk_table_new(freqs+1,5,0);
+  GtkWidget *slidertable=gtk_table_new(multicomp_freqs+1,5,0);
   
-
   GtkWidget *link_box=gtk_hbox_new(0,0);
   GtkWidget *link_check=gtk_check_button_new_with_mnemonic("_link channel envelopes");
-  gtk_box_pack_end(GTK_BOX(link_box),link_check,0,0,0);  
+
+  if(input_ch>1)
+    gtk_box_pack_end(GTK_BOX(link_box),link_check,0,0,0);  
+
   gtk_box_pack_end(GTK_BOX(staticbox),link_box,0,0,0);
   gtk_container_set_border_width(GTK_CONTAINER(link_box),5);
   g_signal_connect (G_OBJECT (link_check), "toggled",
@@ -198,25 +275,158 @@
   gtk_box_pack_start(GTK_BOX(hbox),slidertable,0,0,0);
   gtk_box_pack_start(GTK_BOX(hbox),staticbox,0,0,0);
 
+  gtk_box_pack_start(GTK_BOX(staticbox),staticframe,0,0,0);
   gtk_box_pack_end(GTK_BOX(staticbox),suppressframe,0,0,0);
   gtk_box_pack_end(GTK_BOX(staticbox),envelopeframe,0,0,0);
+  gtk_container_add(GTK_CONTAINER(staticframe),statictable);
   gtk_container_add(GTK_CONTAINER(envelopeframe),envelopetable);
   gtk_container_add(GTK_CONTAINER(suppressframe),suppresstable);
 
   gtk_container_set_border_width(GTK_CONTAINER(suppressframe),5);
   gtk_container_set_border_width(GTK_CONTAINER(envelopeframe),5);
   gtk_container_set_border_width(GTK_CONTAINER(envelopeframe),5);
+  gtk_frame_set_shadow_type(GTK_FRAME(staticframe),GTK_SHADOW_NONE);
+
+  /* static compand */
+  {
+    float ratio_levels[7]={-1.,-.67,-.5,-.33,-.25,-.17,-.1};
+    char  *ratio_labels[6]={"1.5:1","2:1","3:1","4:1","6:1","10:1"};
+
+    float decay_levels[7]={-1.,-.5,-.2,-.1,-.05,-.02,-.01};
+    char  *decay_labels[6]={".5",".2",".1",".05",".02","slow"};
+
+    float bias_levels[7]={-30,-20,-10,0,10,20,30};
+    char  *bias_labels[6]={"20","10","0","10","20","30"};
+
+    GtkWidget *label0=gtk_label_new("mode");
+
+    GtkWidget *label1=gtk_label_new("cmpr:");
+    GtkWidget *label2=gtk_label_new("expd:");
+    GtkWidget *label3=gtk_label_new("decay:");
+    GtkWidget *label4=gtk_label_new("trim:");
+
+    GtkWidget *readout1=readout_new("1.5:1");
+    GtkWidget *readout2=readout_new("1.5:1");
+    GtkWidget *readout3=readout_new(" fast");
+    GtkWidget *readout4=readout_new("-40dB");
+
+    GtkWidget *slider1=multibar_slider_new(6,ratio_labels,ratio_levels,1);
+    GtkWidget *slider2=multibar_slider_new(6,ratio_labels,ratio_levels,1);
+    GtkWidget *slider3=multibar_slider_new(6,decay_labels,decay_levels,1);
+    GtkWidget *slider4=multibar_slider_new(6,bias_labels,bias_levels,1);
+
+    GtkWidget *button4=gtk_button_new_with_label("a[p]ply trim");
+
+    GtkWidget *envelopebox=gtk_hbox_new(0,0);
+    GtkWidget *rms_button=gtk_radio_button_new_with_label(NULL,"RMS");
+    GtkWidget *peak_button=
+      gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rms_button),
+						  "peak");
+
+    gtk_box_pack_start(GTK_BOX(envelopebox),rms_button,0,0,5);
+    gtk_box_pack_start(GTK_BOX(envelopebox),peak_button,0,0,5);
+
+    g_signal_connect (G_OBJECT (button4), "clicked",
+		      G_CALLBACK (static_trim_apply), (gpointer)slider4);
+
+    g_signal_connect (G_OBJECT (rms_button), "clicked",
+		      G_CALLBACK (static_mode), (gpointer)0); //To Hell I Go
+    g_signal_connect (G_OBJECT (peak_button), "clicked",
+		      G_CALLBACK (static_mode), (gpointer)1);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rms_button),1);
+
+    gtk_container_set_border_width(GTK_CONTAINER(statictable),4);
+
+    multibar_callback(MULTIBAR(slider1),
+		      static_compressor_change,
+		      readout1);
+    multibar_thumb_set(MULTIBAR(slider1),-1.,0);
+
+    multibar_callback(MULTIBAR(slider2),
+		      static_expander_change,
+		      readout2);
+    multibar_thumb_set(MULTIBAR(slider2),-1.,0);
+
+    multibar_callback(MULTIBAR(slider3),
+		      static_decay_change,
+		      readout3);
+    multibar_thumb_set(MULTIBAR(slider3),-1.,0);
+
+    multibar_callback(MULTIBAR(slider4),
+		      static_trim_change,
+		      readout4);
+    multibar_thumb_increment(MULTIBAR(slider4),1.,10.);
+
+
+    gtk_misc_set_alignment(GTK_MISC(label0),1,.5);
+    gtk_misc_set_alignment(GTK_MISC(label1),1,.5);
+    gtk_misc_set_alignment(GTK_MISC(label2),1,.5);
+    gtk_misc_set_alignment(GTK_MISC(label3),1,.5);
+    gtk_misc_set_alignment(GTK_MISC(label4),1,.5);
+
+
+    gtk_table_attach(GTK_TABLE(statictable),label0,0,1,0,1,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(statictable),label1,0,1,1,2,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(statictable),label2,0,1,2,3,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(statictable),label3,0,1,3,4,GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(statictable),label4,0,1,4,5,GTK_FILL,0,0,0);
+
+    gtk_table_attach(GTK_TABLE(statictable),envelopebox,1,4,0,1,GTK_FILL,0,0,0);
+
+    gtk_table_attach(GTK_TABLE(statictable),slider1,1,3,1,2,
+		     GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
+    gtk_table_attach(GTK_TABLE(statictable),slider2,1,3,2,3,
+		     GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
+    gtk_table_attach(GTK_TABLE(statictable),slider3,1,3,3,4,
+		     GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
+    gtk_table_attach(GTK_TABLE(statictable),slider4,1,3,4,5,
+		     GTK_FILL|GTK_EXPAND,GTK_FILL,2,0);
+
+    gtk_table_attach(GTK_TABLE(statictable),button4,1,3,5,6,GTK_EXPAND,0,2,5);
+
+    gtk_table_attach(GTK_TABLE(statictable),readout1,3,4,1,2,GTK_FILL,0,0,2);
+    gtk_table_attach(GTK_TABLE(statictable),readout2,3,4,2,3,GTK_FILL,0,0,2);
+    gtk_table_attach(GTK_TABLE(statictable),readout3,3,4,3,4,GTK_FILL,0,0,2);
+    gtk_table_attach(GTK_TABLE(statictable),readout4,3,4,4,5,GTK_FILL,0,0,2);
+    gtk_container_set_border_width(GTK_CONTAINER(statictable),4);
+
+  }
 
   /* envelope compand */
   {
-    double levels[11]={-50,-40,-30,-20,-10,0,10,20,30,40,50};
+    float levels[11]={-50,-40,-30,-20,-10,0,10,20,30,40,50};
     char *labels[10]={"40%","30%","20%","10%","0%","10%","20%",
                       "30%","40%","50%"};
+
+    GtkWidget *label0=gtk_label_new("mode:");
     GtkWidget *label1=gtk_label_new("compress");
     GtkWidget *label2=gtk_label_new("expand");
     GtkWidget *envelope_compress_readout=readout_new(" 0.0%");
     GtkWidget *envelope_compress_slider=multibar_slider_new(10,labels,levels,1);
-    
+
+    GtkWidget *envelopebox=gtk_hbox_new(0,0);
+    GtkWidget *rms_button=gtk_radio_button_new_with_label(NULL,"RMS");
+    GtkWidget *peak_button=
+      gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rms_button),
+						  "peak");
+    GtkWidget *total_button=
+      gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(rms_button),
+						  "total");
+
+    gtk_box_pack_start(GTK_BOX(envelopebox),label0,0,0,1);
+    gtk_box_pack_start(GTK_BOX(envelopebox),rms_button,0,0,5);
+    gtk_box_pack_start(GTK_BOX(envelopebox),peak_button,0,0,5);
+    gtk_box_pack_start(GTK_BOX(envelopebox),total_button,0,0,5);
+
+    g_signal_connect (G_OBJECT (rms_button), "clicked",
+		      G_CALLBACK (envelope_mode), (gpointer)0); //To Hell I Go
+    g_signal_connect (G_OBJECT (peak_button), "clicked",
+		      G_CALLBACK (envelope_mode), (gpointer)1);
+    g_signal_connect (G_OBJECT (peak_button), "clicked",
+		      G_CALLBACK (envelope_mode), (gpointer)2);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rms_button),1);
+
+   
     gtk_container_set_border_width(GTK_CONTAINER(envelopetable),4);
     multibar_callback(MULTIBAR(envelope_compress_slider),
                       envelope_compander_change,
@@ -228,28 +438,31 @@
     gtk_misc_set_alignment(GTK_MISC(label1),0,.5);
     gtk_misc_set_alignment(GTK_MISC(label2),1,.5);
 
-    gtk_table_attach(GTK_TABLE(envelopetable),label1,0,1,1,2,GTK_FILL,0,2,0);
-    gtk_table_attach(GTK_TABLE(envelopetable),label2,1,2,1,2,GTK_FILL,0,2,0);
+    gtk_table_attach(GTK_TABLE(envelopetable),label1,0,1,2,3,GTK_FILL,0,2,0);
+    gtk_table_attach(GTK_TABLE(envelopetable),label2,1,2,2,3,GTK_FILL,0,2,0);
+    gtk_table_attach(GTK_TABLE(envelopetable),envelopebox,
+		     0,2,0,1,GTK_FILL,0,0,0);
+
     gtk_table_attach(GTK_TABLE(envelopetable),envelope_compress_slider,
-		     0,2,0,1,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,0,0);
+		     0,2,1,2,GTK_FILL|GTK_EXPAND,GTK_FILL|GTK_EXPAND,2,0);
     gtk_table_attach(GTK_TABLE(envelopetable),envelope_compress_readout,
-		     2,3,0,1,GTK_FILL,0,0,2);
+		     2,3,1,2,GTK_FILL,0,0,0);
 
   }
 
   /* suppressor */
   {
 
-    double bias_levels[7]={-30,-20,-10,0,10,20,30};
+    float bias_levels[7]={-30,-20,-10,0,10,20,30};
     char  *bias_labels[6]={"20","10","0","10","20","30"};
 
-    double decay_levels[7]={-1.,-.5,-.2,-.1,-.05,-.02,-.01};
+    float decay_levels[7]={-1.,-.5,-.2,-.1,-.05,-.02,-.01};
     char  *decay_labels[6]={".5",".2",".1",".05",".02","slow"};
 
-    double ratio_levels[7]={-1.,-.67,-.5,-.33,-.25,-.17,-.1};
+    float ratio_levels[7]={-1.,-.67,-.5,-.33,-.25,-.17,-.1};
     char  *ratio_labels[6]={"1.5:1","2:1","3:1","4:1","6:1","gate"};
 
-    double depth_levels[7]={-140,-130,-120,-110,-100,-80,-0};
+    float depth_levels[7]={-140,-130,-120,-110,-100,-80,-0};
     char  *depth_labels[6]={"10","20","30","40","60","deep"};
 
     GtkWidget *suppress_bias_slider=multibar_slider_new(6,bias_labels,bias_levels,1);
@@ -334,13 +547,13 @@
                      GTK_FILL|GTK_EXPAND,2,0);
 
     gtk_table_attach(GTK_TABLE(suppresstable),
-		     suppress_bias_readout,2,3,1,2,GTK_FILL,0,0,2);
+		     suppress_bias_readout,2,3,1,2,GTK_FILL,0,0,0);
     gtk_table_attach(GTK_TABLE(suppresstable),
-		     suppress_decay_readout,2,3,2,3,GTK_FILL,0,0,2);
+		     suppress_decay_readout,2,3,2,3,GTK_FILL,0,0,0);
     gtk_table_attach(GTK_TABLE(suppresstable),
-		     suppress_ratio_readout,2,3,3,4,GTK_FILL,0,0,2);
+		     suppress_ratio_readout,2,3,3,4,GTK_FILL,0,0,0);
     gtk_table_attach(GTK_TABLE(suppresstable),
-		     suppress_depth_readout,2,3,4,5,GTK_FILL,0,0,2);
+		     suppress_depth_readout,2,3,4,5,GTK_FILL,0,0,0);
 
   }
 
@@ -355,8 +568,8 @@
     
   }
 
-  for(i=0;i<freqs;i++){
-    const char *labeltext=freq_frequency_label(i);
+  for(i=0;i<multicomp_freqs;i++){
+    const char *labeltext=multicomp_freq_labels[i];
 
     GtkWidget *label=gtk_label_new(labeltext);
     gtk_widget_set_name(label,"smallmarker");
@@ -391,30 +604,32 @@
 
 }
 
-static double **peakfeed=0;
-static double **rmsfeed=0;
+static float **peakfeed=0;
+static float **rmsfeed=0;
 
 void compandpanel_feedback(int displayit){
   int i;
   if(!peakfeed){
-    peakfeed=malloc(sizeof(*peakfeed)*freqs);
-    rmsfeed=malloc(sizeof(*rmsfeed)*freqs);
+    peakfeed=malloc(sizeof(*peakfeed)*multicomp_freqs);
+    rmsfeed=malloc(sizeof(*rmsfeed)*multicomp_freqs);
 
-    for(i=0;i<freqs;i++){
+    for(i=0;i<multicomp_freqs;i++){
       peakfeed[i]=malloc(sizeof(**peakfeed)*input_ch);
       rmsfeed[i]=malloc(sizeof(**rmsfeed)*input_ch);
     }
   }
-  
+
+#if 0  
   if(pull_compand_feedback(peakfeed,rmsfeed)==1)
-    if(displayit && compand_visible)
-      for(i=0;i<freqs;i++)
-	multibar_set(MULTIBAR(bars[i].slider),rmsfeed[i],peakfeed[i],input_ch);
+    for(i=0;i<multicomp_freqs;i++)
+      multibar_set(MULTIBAR(bars[i].slider),rmsfeed[i],peakfeed[i],
+		   input_ch,(displayit && compand_visible));
+#endif
 }
 
 void compandpanel_reset(void){
   int i;
-  for(i=0;i<freqs;i++)
+  for(i=0;i<multicomp_freqs;i++)
     multibar_reset(MULTIBAR(bars[i].slider));
 }
 

<p><p>1.9       +113 -127  postfish/declip.c

Index: declip.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/declip.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- declip.c	20 Feb 2004 00:33:21 -0000	1.8
+++ declip.c	29 Feb 2004 03:16:17 -0000	1.9
@@ -24,7 +24,7 @@
 #include "postfish.h"
 #include <math.h>
 #include <sys/types.h>
-#include "smallft.h"
+#include <fftw3.h>
 #include "reconstruct.h"
 #include "feedback.h"
 
@@ -34,14 +34,17 @@
 extern int inbytes;
 
 /* accessed only in playback thread/setup */
-static drft_lookup fft;
+static fftwf_plan fftwf_weight;
+static float *work;
+static float *freq;
+
 static int blocksize=0;
 static int lopad=0,hipad=0;
 static u_int32_t *widthlookup=0;
-static double *window=0;
-static double width=.5;
-static double **lap=0;
-static double **cache;
+static float *window=0;
+static float width=.5;
+static float **lap=0;
+static float **cache;
 static int cache_samples;
 static int fillstate=0; /* 0: uninitialized
                            1: normal
@@ -53,16 +56,16 @@
 sig_atomic_t declip_visible=0;
 sig_atomic_t declip_converge=2; /* 0=over, 1=full, 2=half, 3=partial, 4=approx */
 
-static double *chtrigger=0;
+static float *chtrigger=0;
 static sig_atomic_t pending_blocksize=0;
-static double convergence=0.;
-static double iterations=0.;
+static float convergence=0.;
+static float iterations=0.;
 
 
 /* feedback! */
 typedef struct declip_feedback{
   feedback_generic parent_class;
-  double *peak;
+  float *peak;
   int *clipcount;
   int total;
 } declip_feedback;
@@ -76,7 +79,7 @@
   return (feedback_generic *)ret;
 }
 
-static void push_declip_feedback(int *clip,double *peak,int total){
+static void push_declip_feedback(int *clip,float *peak,int total){
   int i,n=input_ch;
   declip_feedback *f=(declip_feedback *)
     feedback_new(&feedpool,new_declip_feedback);
@@ -86,7 +89,7 @@
   feedback_push(&feedpool,(feedback_generic *)f);
 }
 
-int pull_declip_feedback(int *clip,double *peak,int *total){
+int pull_declip_feedback(int *clip,float *peak,int *total){
   declip_feedback *f=(declip_feedback *)feedback_pull(&feedpool);
   int i,j;
 
@@ -132,7 +135,7 @@
   return 0;
 }
 
-int declip_settrigger(double trigger,int ch){
+int declip_settrigger(float trigger,int ch){
   if(ch<0 || ch>=input_ch)return -1;
   pthread_mutex_lock(&master_mutex);
   chtrigger[ch]=trigger-(1./(1<<(inbytes*8-1)))-(1./(1<<(inbytes*8-2)));
@@ -140,13 +143,13 @@
   return 0;
 }
 
-int declip_setiterations(double it){
+int declip_setiterations(float it){
   pthread_mutex_lock(&master_mutex);
   iterations=it;
   pthread_mutex_unlock(&master_mutex);
 }
 
-int declip_setconvergence(double c){
+int declip_setconvergence(float c){
   pthread_mutex_lock(&master_mutex);
   convergence=c;
   pthread_mutex_unlock(&master_mutex);
@@ -160,38 +163,22 @@
   return 0;
 }
 
-static void sliding_bark_average(double *f,double *w, int n,double width){
+static void sliding_bark_average(float *f,int n,float width){
   int i=0,j;
-  double acc=0.,del=0.;
-  double sec[hipad+1];
+  float acc=0.,del=0.;
+  float sec[hipad+1];
 
   memset(sec,0,sizeof(sec));
 
-  {
-    double bark=toBark(0.);
-    int hi=widthlookup[0]>>16;
-    int lo=widthlookup[0]&(0xffff);
-    double del=fabs(f[0])/(lo-hi);
-
-    double hidel=del/(-hi+lopad);
-    double lodel=del/(lo-lopad);
-
-    sec[hi]+=hidel;
-    sec[lopad]-=hidel;
-    sec[lopad]-=lodel;
-    sec[lo]+=lodel;
-    
-  }
-
-  for(i=1;i<n/2;i++){
+  for(i=0;i<n/2;i++){
 
-    double bark=toBark(44100.*i/n);
+    float bark=toBark(44100.*i/n);
     int hi=widthlookup[i]>>16;
     int lo=widthlookup[i]&(0xffff);
-    double del=hypot(f[(i<<1)-1],f[i<<1])/(lo-hi);
+    float del=hypot(f[(i<<1)+1],f[i<<1])/(lo-hi);
 
-    double hidel=del/((i-hi+lopad));
-    double lodel=del/((lo-i-lopad));
+    float hidel=del/((i-hi+lopad));
+    float lodel=del/((lo-i-lopad));
 
     sec[hi]+=hidel;
     sec[i+lopad]-=hidel;
@@ -205,31 +192,27 @@
     acc+=del;
   }
 
-  w[0]=1./(acc*acc);
-  del+=sec[lopad];
-  acc+=del;
-
-  for(i=1;i<n/2;i++){
-    w[(i<<1)-1]=w[i<<1]=1./(acc*acc);
+  for(i=0;i<n/2;i++){
+    f[(i<<1)+1]=f[i<<1]=1./(acc*acc);
     del+=sec[i+lopad];
     acc+=del;
-
+    
   }
-  w[n-1]=w[n-2];
+  f[n+1]=f[n]=f[n-1];
 }
 
-static void declip(double *data,double *lap,double *out,
-		   int blocksize,double trigger,
-		   double epsilon, double iteration,
-		   int *runningtotal, int *runningcount,double *peak){
-  double freq[blocksize*2];
-  double flag[blocksize*2];
+/* work,freq are passed through the static buffer fftwf requires */
+static void declip(float *lap,float *out,
+		   int blocksize,float trigger,
+		   float epsilon, float iteration,
+		   int *runningtotal, int *runningcount,float *peak){
+  float flag[blocksize*2];
   int    iterbound,i,j,count=0;
   
   for(i=blocksize/2;i<blocksize*3/2;i++){
-    if(fabs(data[i])>*peak)*peak=fabs(data[i]);
+    if(fabs(work[i])>*peak)*peak=fabs(work[i]);
     flag[i]=0.;
-    if(data[i]>=trigger || data[i]<=-trigger){
+    if(work[i]>=trigger || work[i]<=-trigger){
       flag[i]=1.;
       count++;
     }
@@ -243,33 +226,32 @@
     for(i=0;i<blocksize/2;i++)flag[i]=0.;
     for(i=blocksize*3/2;i<blocksize*2;i++)flag[i]=0.;
 
-    for(i=0;i<blocksize/2;i++)data[i]=0.;
-    for(i=0;i<blocksize;i++)data[i+blocksize/2]*=window[i];
-    for(i=blocksize*3/2;i<blocksize*2;i++)data[i]=0.;
-
-    memcpy(freq,data,sizeof(freq));
-    drft_forward(&fft,freq);
-    sliding_bark_average(freq,freq,blocksize*2,width);
-    iterbound=count*iteration;
+    for(i=0;i<blocksize/2;i++)work[i]=0.;
+    for(i=0;i<blocksize;i++)work[i+blocksize/2]*=window[i];
+    for(i=blocksize*3/2;i<blocksize*2;i++)work[i]=0.;
+
+    fftwf_execute(fftwf_weight);
+    sliding_bark_average(freq,blocksize*2,width);
+    iterbound=blocksize*iteration;
     if(iterbound<10)iterbound=10;
 
-    if(count)reconstruct(&fft,data,freq,flag,epsilon,iterbound,blocksize*2);
+    if(count)reconstruct(work,freq,flag,epsilon,iterbound);
 
     if(out)
       for(i=0;i<blocksize/2;i++)
-	out[i]=lap[i]+data[i+blocksize/2]*window[i];
+	out[i]=lap[i]+work[i+blocksize/2]*window[i];
     
     for(i=blocksize/2,j=0;i<blocksize;i++)
-      lap[j++]=data[i+blocksize/2]*window[i];
+      lap[j++]=work[i+blocksize/2]*window[i];
 
   }else{
 
     if(out)
       for(i=0;i<blocksize/2;i++)
-	out[i]=data[i+blocksize/2];
+	out[i]=work[i+blocksize/2];
   
     for(i=blocksize/2,j=0;i<blocksize;i++)
-      lap[j++]=data[i+blocksize/2]*window[i]*window[i];
+      lap[j++]=work[i+blocksize/2]*window[i]*window[i];
   }
   for(i=blocksize/2;i<input_size;i++)
     lap[i]=0.;
@@ -278,15 +260,15 @@
 /* called only by playback thread */
 time_linkage *declip_read(time_linkage *in){
   int i;
-  double local_trigger[input_ch];
+  float local_trigger[input_ch];
   int total=0;
   int count[input_ch];
-  double peak[input_ch];
+  float peak[input_ch];
 
   time_linkage dummy;
 
-  double local_convergence;
-  double local_iterations;
+  float local_convergence;
+  float local_iterations;
   
   pthread_mutex_lock(&master_mutex);
   local_convergence=convergence;
@@ -301,85 +283,89 @@
     if(blocksize){
       free(widthlookup);
       free(window);
-      drft_clear(&fft);
+      fftwf_destroy_plan(fftwf_weight);
+      fftwf_free(freq);
+      fftwf_free(work);
     }
     blocksize=pending_blocksize;
 
+    freq=fftwf_malloc((blocksize*2+2)*sizeof(freq));
+    work=fftwf_malloc((blocksize*2)*sizeof(freq));
+    fftwf_weight=fftwf_plan_dft_r2c_1d(blocksize*2,
+				       work,
+				       (fftwf_complex *)freq,
+				       FFTW_MEASURE);
+
     lopad=1-rint(fromBark(toBark(0.)-width)*blocksize*2/input_rate);
     hipad=rint(fromBark(toBark(input_rate*.5)+width)*blocksize*2/input_rate)+lopad;
     widthlookup=malloc((hipad+1)*sizeof(*widthlookup));
     for(i=0;i<blocksize;i++){
-      double bark=toBark(input_rate*i/(blocksize*2));
+      float bark=toBark(input_rate*i/(blocksize*2));
       int hi=rint(fromBark(bark-width)*(blocksize*2)/input_rate)-1+lopad;
       int lo=rint(fromBark(bark+width)*(blocksize*2)/input_rate)+1+lopad;
       widthlookup[i]=(hi<<16)+lo;
     }
     
-    drft_init(&fft,blocksize*2);
-
     window=malloc(blocksize*sizeof(*window));
     for(i=0;i<blocksize;i++) window[i]=sin( M_PIl*i/blocksize );
     for(i=0;i<blocksize;i++) window[i]*=window[i];
     for(i=0;i<blocksize;i++) window[i]=sin(window[i]*M_PIl*.5);
 
+    reconstruct_reinit(blocksize*2);
   }
 
-  {
-    double work[blocksize*2];
+  switch(fillstate){
+  case 0: /* prime the lapping and cache */
+    for(i=0;i<input_ch;i++){
+      int j;
+      float *temp=in->data[i];
+      total=0;
+      memset(work+blocksize/2,0,sizeof(*work)*blocksize/2);
+      memcpy(work+blocksize,temp,sizeof(*work)*blocksize/2);
+      declip(lap[i],0,blocksize,
+	     local_trigger[i],local_convergence,local_iterations,
+	     &total,count+i,peak+i);
+      
+      memset(cache[i],0,sizeof(**cache)*input_size);
+      in->data[i]=cache[i];
+      cache[i]=temp;
+    }
+    cache_samples=in->samples;
+    fillstate=1;
+    out.samples=0;
+    if(in->samples==in->size)goto tidy_up;
     
-    switch(fillstate){
-    case 0: /* prime the lapping and cache */
-      for(i=0;i<input_ch;i++){
-	int j;
-	double *temp=in->data[i];
-	total=0;
-	memset(work+blocksize/2,0,sizeof(*work)*blocksize/2);
-	memcpy(work+blocksize,temp,sizeof(*work)*blocksize/2);
-	declip(work,lap[i],0,blocksize,
-	       local_trigger[i],local_convergence,local_iterations,
-	       &total,count+i,peak+i);
-	
-	memset(cache[i],0,sizeof(**cache)*input_size);
-	in->data[i]=cache[i];
-	cache[i]=temp;
-      }
-      cache_samples=in->samples;
-      fillstate=1;
-      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++){
-	double *temp=cache[i];
-	int j;
-	total=0;
-	for(j=0;j+blocksize<=out.size;j+=blocksize/2){
-	  memcpy(work+blocksize/2,temp+j,sizeof(*work)*blocksize);
-	  declip(work,lap[i],out.data[i]+j,blocksize,
-		 local_trigger[i],local_convergence,local_iterations,
-		 &total,count+i,peak+i);
-	}
-	memcpy(work+blocksize/2,temp+j,sizeof(*work)*blocksize/2);
-	memcpy(work+blocksize,in->data[i],sizeof(*work)*blocksize/2);
-
-	declip(work,lap[i],out.data[i]+j,blocksize,
+    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++){
+      float *temp=cache[i];
+      int j;
+      total=0;
+      for(j=0;j+blocksize<=out.size;j+=blocksize/2){
+	memcpy(work+blocksize/2,temp+j,sizeof(*work)*blocksize);
+	declip(lap[i],out.data[i]+j,blocksize,
                local_trigger[i],local_convergence,local_iterations,
                &total,count+i,peak+i);
-	
-	cache[i]=in->data[i];
-	in->data[i]=temp;
       }
-      out.samples=cache_samples;
-      cache_samples=in->samples;
-      if(out.samples<out.size)fillstate=2;
-      break;
-    case 2: /* we've pushed out EOF already */
-      out.samples=0;
+      memcpy(work+blocksize/2,temp+j,sizeof(*work)*blocksize/2);
+      memcpy(work+blocksize,in->data[i],sizeof(*work)*blocksize/2);
+      
+      declip(lap[i],out.data[i]+j,blocksize,
+	     local_trigger[i],local_convergence,local_iterations,
+	     &total,count+i,peak+i);
+      
+      cache[i]=in->data[i];
+      in->data[i]=temp;
     }
+    out.samples=cache_samples;
+    cache_samples=in->samples;
+    if(out.samples<out.size)fillstate=2;
+    break;
+  case 2: /* we've pushed out EOF already */
+    out.samples=0;
   }
 
   push_declip_feedback(count,peak,total);

<p><p>1.4       +4 -4      postfish/declip.h

Index: declip.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/declip.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- declip.h	16 Feb 2004 05:00:54 -0000	1.3
+++ declip.h	29 Feb 2004 03:16:17 -0000	1.4
@@ -23,9 +23,9 @@
 
 extern int declip_load(void);
 extern int declip_setblock(int n);
-extern int declip_settrigger(double trigger,int ch);
-extern int declip_setiterations(double x);
-extern int declip_setconvergence(double x);
+extern int declip_settrigger(float trigger,int ch);
+extern int declip_setiterations(float x);
+extern int declip_setconvergence(float x);
 extern int declip_reset(void);
 extern time_linkage *declip_read(time_linkage *in);
-extern int pull_declip_feedback(int *clip,double *peak,int *total);
+extern int pull_declip_feedback(int *clip,float *peak,int *total);

<p><p>1.5       +34 -25    postfish/eq.c

Index: eq.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/eq.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- eq.c	20 Feb 2004 02:09:39 -0000	1.4
+++ eq.c	29 Feb 2004 03:16:17 -0000	1.5
@@ -32,15 +32,18 @@
 sig_atomic_t eq_active;
 sig_atomic_t eq_visible;
 
+sig_atomic_t curve_dirty=1;
+
 freq_state eq;
 
-int pull_eq_feedback(double **peak,double **rms){
+/* accessed only in playback thread/setup */
+int pull_eq_feedback(float **peak,float **rms){
   return pull_freq_feedback(&eq,peak,rms);
 }
 
 /* called only by initial setup */
 int eq_load(void){
-  return freq_load(&eq,input_size*2);
+  return freq_load(&eq,eq_freq_list,eq_freqs,input_size);
 }
 
 /* called only in playback thread */
@@ -48,39 +51,45 @@
   return freq_reset(&eq);
 }
 
-static sig_atomic_t settings[freqs];
+static sig_atomic_t settings[eq_freqs];
 
-void eq_set(int freq, double value){
+void eq_set(int freq, float value){
   settings[freq]=rint(value*10.);
+  curve_dirty=1;
 }
+ 
+static float *curve_cache=0;
+ 
+static void workfunc(freq_state *f,float **data,float **peak, float **rms){
+  int h,i,j,k;
+  float sq_mags[f->qblocksize*2+1];
   
-static void workfunc(double *data,freq_state *f,
-		     double *peak, double *rms){
-  int i,j,k;
-  double work[f->blocksize+1];
-  double sq_mags[f->blocksize+1];
-
-  if(eq_active){
-    memset(work,0,sizeof(work));
+  if(curve_dirty || !curve_cache){
+    curve_dirty=0;
     
-    for(i=0;i<freqs;i++){
-      double set=fromdB(settings[i]*.1);
-      for(k=0,j=f->ho_bin_lo[i];j<f->ho_bin_hi[i];j++,k++)
-	work[j]+=f->ho_window[i][k]*set;
-      peak[i]*=set;
-      rms[i]*=set;
+    if(!curve_cache)curve_cache=malloc((f->qblocksize*2+1)*sizeof(*curve_cache));
+    memset(curve_cache,0,(f->qblocksize*2+1)*sizeof(*curve_cache));
+    
+    for(i=0;i<eq_freqs;i++){
+      float set=fromdB(settings[i]*.1);
+      for(j=0;j<f->qblocksize*2+1;j++)
+	curve_cache[j]+=f->ho_window[i][j]*set;
     }
+  }
+  
+  for(h=0;h<input_ch;h++){
     
-    data[0]*=work[0];
-    data[f->blocksize*2-1]*=work[f->blocksize];
-    for(i=1;i<f->blocksize;i++){
-      data[i*2]*=work[i];
-      data[i*2-1]*=work[i];
+    if(eq_active){
+      
+      for(i=0;i<f->qblocksize*2+1;i++){
+	data[h][i*2]*=curve_cache[i];
+	data[h][i*2+1]*=curve_cache[i];
+      }
     }
+    
+    freq_metric_work(data[h],f,sq_mags,peak[h],rms[h]);
   }
 
-  freq_metric_work(data,f,sq_mags,peak,rms);
-
   return;
 }
 

<p><p>1.3       +20 -2     postfish/eq.h

Index: eq.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/eq.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- eq.h	19 Feb 2004 00:49:37 -0000	1.2
+++ eq.h	29 Feb 2004 03:16:17 -0000	1.3
@@ -23,8 +23,26 @@
 
 #include "postfish.h"
 
-extern int pull_eq_feedback(double **peak,double **rms);
+#define eq_freqs 30
+
+static float eq_freq_list[eq_freqs+1]={
+  25,31.5,40,50,63,80,
+  100,125,160,200,250,315,
+  400,500,630,800,1000,1250,1600,
+  2000,2500,3150,4000,5000,6300,
+  8000,10000,12500,16000,20000,9e10};
+
+static char *eq_freq_labels[eq_freqs]={
+  "25","31.5","40","50","63","80",
+  "100","125","160","200","250","315",
+  "400","500","630","800","1k","1.2k","1.6k",
+  "2k","2.5k","3.1k","4k","5k","6.3k",
+  "8k","10k","12.5k","16k","20k"
+};
+
+
+extern int pull_eq_feedback(float **peak,float **rms);
 extern int eq_load(void);
 extern int eq_reset();
-extern void eq_set(int freq, double value);
+extern void eq_set(int freq, float value);
 extern time_linkage *eq_read(time_linkage *in);

<p><p>1.6       +19 -23    postfish/eqpanel.c

Index: eqpanel.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/eqpanel.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- eqpanel.c	20 Feb 2004 06:06:00 -0000	1.5
+++ eqpanel.c	29 Feb 2004 03:16:17 -0000	1.6
@@ -44,12 +44,12 @@
   int number;
 } bar;
 
-static bar bars[freqs];
+static bar bars[eq_freqs];
 
 static void slider_change(GtkWidget *w,gpointer in){
   char buffer[80];
   bar *b=(bar *)in;
-  gdouble val=multibar_get_value(MULTIBAR(b->slider),0);
+  float val=multibar_get_value(MULTIBAR(b->slider),0);
   
   sprintf(buffer,"%+3.0fdB",val);
   readout_set(READOUT(b->readout),buffer);
@@ -62,9 +62,9 @@
                     GtkWidget *windowbutton,
                     GtkWidget *activebutton){
   int i;
-  char *labels[15]={"-110","-100","-90","-80","-70","-60","-50","-40",
-		    "-30","-20","-10","0","+10","+20","+30"};
-  double levels[16]={-120,-110,-100,-90,-80,-70,-60,-50,-40,
+  char *labels[15]={"110","100","90","80","70","60","50","40",
+		    "30","20","10","0","+10","+20","+30"};
+  float levels[16]={-120,-110,-100,-90,-80,-70,-60,-50,-40,
                      -30,-20,-10,0,10,20,30};
 
   subpanel_generic *panel=subpanel_create(mp,windowbutton,activebutton,
@@ -72,10 +72,10 @@
                                           &eq_visible,
                                           "_Equalization filter"," [e] ");
   
-  GtkWidget *slidertable=gtk_table_new(freqs,3,0);
+  GtkWidget *slidertable=gtk_table_new(eq_freqs,3,0);
 
-  for(i=0;i<freqs;i++){
-    const char *labeltext=freq_frequency_label(i);
+  for(i=0;i<eq_freqs;i++){
+    const char *labeltext=eq_freq_labels[i];
 
     GtkWidget *label=gtk_label_new(labeltext);
     gtk_widget_set_name(label,"smallmarker");
@@ -87,7 +87,7 @@
 
     multibar_callback(MULTIBAR(bars[i].slider),slider_change,bars+i);
     multibar_thumb_set(MULTIBAR(bars[i].slider),0.,0);
-    multibar_thumb_bounds(MULTIBAR(bars[i].slider),-40,30);
+    multibar_thumb_bounds(MULTIBAR(bars[i].slider),-60,30);
     multibar_thumb_increment(MULTIBAR(bars[i].slider),1,10);
 
     gtk_misc_set_alignment(GTK_MISC(label),1,.5);
@@ -104,35 +104,31 @@
 
 }
 
-static double **peakfeed=0;
-static double **rmsfeed=0;
+static float **peakfeed=0;
+static float **rmsfeed=0;
 
 void eqpanel_feedback(int displayit){
   int i;
   if(!peakfeed){
-    peakfeed=malloc(sizeof(*peakfeed)*freqs);
-    rmsfeed=malloc(sizeof(*rmsfeed)*freqs);
+    peakfeed=malloc(sizeof(*peakfeed)*eq_freqs);
+    rmsfeed=malloc(sizeof(*rmsfeed)*eq_freqs);
 
-    for(i=0;i<freqs;i++){
+    for(i=0;i<eq_freqs;i++){
       peakfeed[i]=malloc(sizeof(**peakfeed)*input_ch);
       rmsfeed[i]=malloc(sizeof(**rmsfeed)*input_ch);
     }
   }
   
   if(pull_eq_feedback(peakfeed,rmsfeed)==1)
-    if(displayit && eq_visible)
-      for(i=0;i<freqs;i++)
-	multibar_set(MULTIBAR(bars[i].slider),rmsfeed[i],peakfeed[i],input_ch);
+    for(i=0;i<eq_freqs;i++)
+      multibar_set(MULTIBAR(bars[i].slider),rmsfeed[i],peakfeed[i],
+		   input_ch,(displayit && eq_visible));
+  
 }
 
 void eqpanel_reset(void){
   int i;
-  for(i=0;i<freqs;i++)
+  for(i=0;i<eq_freqs;i++)
     multibar_reset(MULTIBAR(bars[i].slider));
 }
 
-
-
-
-
-

<p><p>1.5       +415 -217  postfish/freq.c

Index: freq.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/freq.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- freq.c	20 Feb 2004 06:43:32 -0000	1.4
+++ freq.c	29 Feb 2004 03:16:17 -0000	1.5
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include "feedback.h"
 #include "freq.h"
+#include "lpc.h"
 
 extern int input_rate;
 extern int input_ch;
@@ -34,44 +35,72 @@
 /* feedback! */
 typedef struct freq_feedback{
   feedback_generic parent_class;
-  double **peak;
-  double **rms;
+  float **peak;
+  float **rms;
   int bypass;
 } freq_feedback;
 
-/* accessed only in playback thread/setup */
-static double frequencies[freqs+1]={
-  25,31.5,40,50,63,80,
-  100,125,160,200,250,315,
-  400,500,630,800,1000,1250,1600,
-  2000,2500,3150,4000,5000,6300,
-  8000,10000,12500,16000,20000,9e10};
-
-static char *freq_labels[freqs]={
-  "25","31.5","40","50","63","80",
-  "100","125","160","200","250","315",
-  "400","500","630","800","1k","1.2k","1.6k",
-  "2k","2.5k","3.1k","4k","5k","6.3k",
-  "8k","10k","12.5k","16k","20k"
-};
-
 static feedback_generic *new_freq_feedback(void){
   int i;
   freq_feedback *ret=malloc(sizeof(*ret));
-  ret->peak=malloc(input_ch*sizeof(*ret->peak));
-  ret->rms=malloc(input_ch*sizeof(*ret->rms));
+  ret->peak=calloc(input_ch,sizeof(*ret->peak));
+  ret->rms=calloc(input_ch,sizeof(*ret->rms));
 
-  for(i=0;i<input_ch;i++){
-    ret->peak[i]=malloc(freqs*sizeof(**ret->peak));
-    ret->rms[i]=malloc(freqs*sizeof(**ret->rms));
+  return (feedback_generic *)ret;
+}
+
+static int seq=0;
+static void _analysis(char *base,int i,float *v,int n,int bark,int dB){
+  int j;
+  FILE *of;
+  char buffer[80];
+
+  sprintf(buffer,"%s_%d.m",base,i);
+  of=fopen(buffer,"w");
+  
+  if(!of)perror("failed to open data dump file");
+  
+  for(j=0;j<n;j++){
+    if(bark){
+      float b=toBark((4000.f*j/n)+.25);
+      fprintf(of,"%f ",b);
+    }else
+      fprintf(of,"%f ",(float)j);
+    
+    if(dB){
+      float val=todB(hypot(v[j],v[j+1]));
+      if(val<-140)val=-140;
+      fprintf(of,"%f\n",val);
+      j++;
+     
+    }else{
+      fprintf(of,"%f\n",v[j]);
+    }
   }
+  fclose(of);
+}
 
-  return (feedback_generic *)ret;
+static void _analysis_append(char *base,int basemod,float *v,int n,int off){
+  int j;
+  FILE *of;
+  char buffer[80];
+
+  sprintf(buffer,"%s_%d.m",base,basemod);
+  of=fopen(buffer,"a");
+  
+  if(!of)perror("failed to open data dump file");
+  
+  for(j=0;j<n;j++){
+    fprintf(of,"%f ",(float)j+off);    
+    fprintf(of,"%f\n",v[j]);
+  }
+  fprintf(of,"\n");
+  fclose(of);
 }
 
 /* total, peak, rms are pulled in array[freqs][input_ch] order */
 
-int pull_freq_feedback(freq_state *ff,double **peak,double **rms){
+int pull_freq_feedback(freq_state *ff,float **peak,float **rms){
   freq_feedback *f=(freq_feedback *)feedback_pull(&ff->feedpool);
   int i,j;
   
@@ -82,12 +111,12 @@
     return 2;
   }else{
     if(peak)
-      for(i=0;i<freqs;i++)
+      for(i=0;i<ff->bands;i++)
         for(j=0;j<input_ch;j++)
           peak[i][j]=f->peak[j][i];
     
     if(rms)
-      for(i=0;i<freqs;i++)
+      for(i=0;i<ff->bands;i++)
         for(j=0;j<input_ch;j++)
           rms[i][j]=f->rms[j][i];
     feedback_old(&ff->feedpool,(feedback_generic *)f);
@@ -96,22 +125,24 @@
 }
 
 /* called only by initial setup */
-int freq_load(freq_state *f,int blocksize){
+int freq_load(freq_state *f,float *frequencies, int bands, 
+	      int blocksize){
   int i,j;
   
   memset(f,0,sizeof(*f));
 
-  drft_init(&f->fft,blocksize*2);
-  f->blocksize=blocksize;
-  
+  f->qblocksize=blocksize/2;
+  f->bands=bands;
+  f->frequencies=frequencies;
+
   f->fillstate=0;
   f->cache_samples=0;
   f->cache=malloc(input_ch*sizeof(*f->cache));
   for(i=0;i<input_ch;i++)
-    f->cache[i]=malloc(input_size*sizeof(**f->cache));
+    f->cache[i]=calloc(input_size,sizeof(**f->cache));
   f->lap=malloc(input_ch*sizeof(*f->lap));
   for(i=0;i<input_ch;i++)
-    f->lap[i]=malloc(input_size*sizeof(**f->lap));
+    f->lap[i]=calloc(f->qblocksize*3,sizeof(**f->lap));
 
   f->out.size=input_size;
   f->out.channels=input_ch;
@@ -120,72 +151,119 @@
   for(i=0;i<input_ch;i++)
     f->out.data[i]=malloc(input_size*sizeof(**f->out.data));
 
+  /* fill in time window */
+  f->window=malloc(blocksize*sizeof(*f->window)); 
+  for(i=0;i<blocksize;i++)f->window[i]=sin(M_PIl*i/blocksize);
+  for(i=0;i<blocksize;i++)f->window[i]*=f->window[i];
+  for(i=0;i<blocksize;i++)f->window[i]=sin(f->window[i]*M_PIl*.5);
+  for(i=0;i<blocksize;i++)f->window[i]*=f->window[i];
+
   /* unlike old postfish, we offer all frequencies via smoothly
      supersampling the spectrum */
   /* I'm too lazy to figure out the integral symbolically, use this
      fancy CPU-thing for something */
   
-  f->ho_window=malloc(freqs*sizeof(*f->ho_window));
+  f->fftwf_buffer = fftwf_malloc(sizeof(*f->fftwf_buffer) * input_ch);
+  f->fftwf_backward = fftwf_malloc(sizeof(*f->fftwf_backward) * input_ch);
+  f->fftwf_forward = fftwf_malloc(sizeof(*f->fftwf_forward) * input_ch);
+  for(i=0;i<input_ch;i++){
+    f->fftwf_buffer[i] = fftwf_malloc(sizeof(**f->fftwf_buffer) * 
+				  (f->qblocksize*4+2));
+    
+    f->fftwf_forward[i]=fftwf_plan_dft_r2c_1d(f->qblocksize*4, 
+					      f->fftwf_buffer[i],
+					      (fftwf_complex *)(f->fftwf_buffer[i]), 
+					      FFTW_MEASURE);
+    
+    f->fftwf_backward[i]=fftwf_plan_dft_c2r_1d(f->qblocksize*4,
+					       (fftwf_complex *)(f->fftwf_buffer[i]), 
+					       f->fftwf_buffer[i], 
+					       FFTW_MEASURE);
+  }
+
+  /* unlike old postfish, we offer all frequencies via smoothly
+     supersampling the spectrum */
+  /* I'm too lazy to figure out the integral symbolically, use this
+     fancy CPU thingy for something */
+  
+  f->ho_window=malloc(bands*sizeof(*f->ho_window));
+  f->ho_area=calloc(bands,sizeof(*f->ho_area));
   {
-    double *working=alloca((blocksize+1)*sizeof(*working));
+    float working[f->qblocksize*4+2];
+    
+    for(i=0;i<bands;i++){
+      float lastf=(i>0?frequencies[i-1]:0);
+      float thisf=frequencies[i];
+      float nextf=frequencies[i+1];
+      memset(working,0,sizeof(working));
+
+      for(j=0;j<((f->qblocksize*2+1)<<5);j++){
+        float localf= .5*j*input_rate/(f->qblocksize<<6);
+        int localbin= j>>5;
+        float localwin;
+
+        if(localf>=lastf && localf<thisf){
+          if(i==0)
+            localwin=1.;
+          else
+            localwin= sin((localf-lastf)/(thisf-lastf)*M_PIl*.5);
+          localwin*=localwin;
+	  working[localbin]+=localwin*(1./32);
 
-    for(i=0;i<freqs;i++){
-      double lastf=(i>0?frequencies[i-1]:0);
-      double thisf=frequencies[i];
-      double nextf=frequencies[i+1];
-
-      /* conceptually simple, easy to verify, absurdly inefficient,
-         but hey, we're only doing it at init */
-      memset(working,0,sizeof(*working)*(blocksize+1));
+        }else if(localf>=thisf && localf<nextf){
+          if(i+1==bands)
+            localwin=1.;
+          else
+            localwin= sin((nextf-localf)/(nextf-thisf)*M_PIl*.5);
+          
+          localwin*=localwin;
+          working[localbin]+=localwin*(1./32);
+          
+        }
+      }
+
+      /* window this desired response in the time domain so that our
+         convolution is properly padded against being circular */
+      memset(f->fftwf_buffer[0],0,sizeof(**f->fftwf_buffer)*
+	     (f->qblocksize*4+2));
+      for(j=0;j<f->qblocksize*2;j++)
+	f->fftwf_buffer[0][j*2]=working[j];
       
-      for(j=0;j<((blocksize+1)<<5);j++){
-	double localf= .5*j*input_rate/(blocksize<<5);
-	int localbin= j>>5;
-	double localwin;
-
-	if(localf>=lastf && localf<thisf){
-	  if(i==0)
-	    localwin=1.;
-	  else
-	    localwin= sin((localf-lastf)/(thisf-lastf)*M_PIl*.5);
-	  localwin*=localwin;
-	  working[localbin]+=localwin*(1./32);
+      fftwf_execute(f->fftwf_backward[0]);
 
-	}else if(localf>=thisf && localf<nextf){
-	  if(i+1==freqs)
-	    localwin=1.;
-	  else
-	    localwin= sin((nextf-localf)/(nextf-thisf)*M_PIl*.5);
-	  
-	  localwin*=localwin;
-	  working[localbin]+=localwin*(1./32);
-	  
-	}
+      /* window response in time */
+      for(j=0;j<f->qblocksize;j++){
+	float val=cos(j*M_PI/(f->qblocksize*2));
+	val=sin(val*val*M_PIl*.5);
+	f->fftwf_buffer[0][j]*= sin(val*val*M_PIl*.5);
       }
 
-      /* now take what we learned and distill it a bit */
-      for(j=0;j<blocksize+1;j++)if(working[j]!=0.)break;
-      f->ho_bin_lo[i]=j;
-      for(;j<blocksize+1;j++)if(working[j]==0.)break;
-      f->ho_bin_hi[i]=j;
-      f->ho_window[i]=malloc((f->ho_bin_hi[i]-f->ho_bin_lo[i])*
-			     sizeof(**f->ho_window));
-      for(j=f->ho_bin_lo[i];j<f->ho_bin_hi[i];j++)
-	f->ho_area[i]+=f->ho_window[i][j-f->ho_bin_lo[i]]=working[j];
+      for(;j<f->qblocksize*3;j++)
+	f->fftwf_buffer[0][j]=0.;
+      
+      for(;j<f->qblocksize*4;j++){
+	float val=sin((j-f->qblocksize*3)*M_PI/(f->qblocksize*2));
+	val=sin(val*val*M_PIl*.5);
+	f->fftwf_buffer[0][j]*=sin(val*val*M_PIl*.5);
+      }
 
+      /* back to frequency; this is all-real data still */
+      fftwf_execute(f->fftwf_forward[0]);
+      for(j=0;j<f->qblocksize*4+2;j++)
+	f->fftwf_buffer[0][j]/=f->qblocksize*4;
+      
+      /* now take what we learned and distill it a bit */
+      f->ho_window[i]=calloc((f->qblocksize*2+1),sizeof(**f->ho_window));
+      for(j=0;j<f->qblocksize*2+1;j++){
+	f->ho_window[i][j]=f->fftwf_buffer[0][j*2];
+	f->ho_area[i]+=fabs(f->ho_window[i][j]);
+      }
       f->ho_area[i]=1./f->ho_area[i];
-      lastf=thisf;
 
+      lastf=thisf;
+      
     }
   }
-      
-  /* fill in time window */
-  f->window=malloc(blocksize*sizeof(*f->window)); 
-  /* we actually use 2x blocks, but the window is nonzero only in half */
-  
-  for(i=0;i<blocksize;i++)f->window[i]=sin(M_PIl*i/blocksize);
-  for(i=0;i<blocksize;i++)f->window[i]*=f->window[i];
-  for(i=0;i<blocksize;i++)f->window[i]=sin(f->window[i]*M_PIl*.5);
 
   return(0);
 }
@@ -198,46 +276,24 @@
   return 0;
 }
 
-const char *freq_frequency_label(int n){
-  if(n<0)return "";
-  if(n>freqs)return "";
-  return freq_labels[n];
-}
-
-static void transform_work(double *work,freq_state *f){
-  double *workoff=work+f->blocksize/2;
-  int i,j,k;
-  
-  /* window the time data */
-  memset(work,0,sizeof(*work)*f->blocksize/2);
-  memset(work+f->blocksize*3/2,0,sizeof(*work)*f->blocksize/2);
-  for(i=0;i<f->blocksize;i++)workoff[i]*=f->window[i];
-  
-  /* transform the time data */
-  drft_forward(&f->fft,work);
-  for(i=0;i<f->blocksize*2;i++)work[i]*=(.5/f->blocksize);
-}
+void freq_metric_work(float *work,freq_state *f,
+		      float *sq_mags,float *peak,float *rms){
+  int i,j;
 
+  /* fill in metrics */
+  memset(peak,0,sizeof(*peak)*f->bands);
+  memset(rms,0,sizeof(*rms)*f->bands);
 
-void freq_metric_work(double *work,freq_state *f,
-		      double *sq_mags,double *peak,double *rms){
-  int i,j,k;
+  for(i=0;i<f->qblocksize*2+1;i++)
+    sq_mags[i]=(work[i*2]*work[i*2]+work[i*2+1]*work[i*2+1])*64.;
 
-  /* fill in metrics */
-  memset(peak,0,sizeof(*peak)*freqs);
-  memset(rms,0,sizeof(*rms)*freqs);
-  sq_mags[0]=work[0]*work[0]*44.4444444;
-  sq_mags[f->blocksize]=
-    work[f->blocksize*2-1]*work[f->blocksize*2-1]*44.44444444;
-  for(i=1;i<f->blocksize;i++)
-    sq_mags[i]=(work[i*2]*work[i*2]+work[i*2-1]*work[i*2-1])*44.444444;
-  
-  for(i=0;i<freqs;i++){
-    double *ho_window=f->ho_window[i];
-    for(k=0,j=f->ho_bin_lo[i];j<f->ho_bin_hi[i];j++,k++){
-      double val=sq_mags[j]*ho_window[k];
+  
+  for(i=0;i<f->bands;i++){
+    float *ho_window=f->ho_window[i];
+    for(j=0;j<f->qblocksize*2+1;j++){
+      float val=fabs(sq_mags[j]*ho_window[j]);
 
-      rms[i]+=val;
+      rms[i]+=val*.5;
       if(val>peak[i])peak[i]=val;
     }
     rms[i]=sqrt(rms[i]*f->ho_area[i]);
@@ -246,158 +302,300 @@
 
 }
 
-static void feedback_work(double *peak,double *rms,
-		   double *feedback_peak,double *feedback_rms){
+static void feedback_work(freq_state *f,float *peak,float *rms,
+			  float *feedback_peak,float *feedback_rms){
   int i;
-  for(i=0;i<freqs;i++){
+  for(i=0;i<f->bands;i++){
     feedback_rms[i]+=rms[i]*rms[i];
     if(feedback_peak[i]<peak[i])feedback_peak[i]=peak[i];
   }
 }
 
-static void lap_work(double *work,double *lap,double *out,freq_state *f,int bypass){
-  double *workoff=work+f->blocksize/2;
-  int i,j;
-  
-  /* lap and out */
-  if(bypass){
-    if(out)
-      for(i=0;i<f->blocksize/2;i++)
-	out[i]=lap[i]+workoff[i]*f->window[i]*f->window[i];
+static void lap_bypass(float *cache,float *in,float *lap,float *out,freq_state *f){
+  int i;
+  if(out){
+    /* we're bypassing, so the input data hasn't spread from the half->block window.
+       The lap may well be spread though, so we can't cheat and ignore the last third */
+    for(i=0;i<f->qblocksize;i++)
+      out[i]=lap[i];
+
+    for(;i<f->qblocksize*2;i++)
+      out[i]=lap[i]+f->window[i-f->qblocksize]*cache[i];
+
+    if(f->qblocksize*2<input_size)
+      for(;i<f->qblocksize*3;i++)
+	out[i]=lap[i]+cache[i];
     
-    for(i=f->blocksize/2,j=0;i<f->blocksize;i++)
-      lap[j++]=workoff[i]*f->window[i]*f->window[i];
+    if(f->qblocksize*3<input_size)
+      memcpy(out+f->qblocksize*3,cache+f->qblocksize*3,
+	     sizeof(*out)*(input_size-f->qblocksize*3));
+  }
+
+  /* keep lap up to date; bypassed data has not spread from the half-block padded window */
+  if(f->qblocksize<input_size/2){
+    memcpy(lap,in,f->qblocksize*sizeof(*lap));
+    for(i=f->qblocksize;i<f->qblocksize*2;i++)
+      lap[i]=in[i]*f->window[i];
   }else{
-    if(out)
-      for(i=0;i<f->blocksize/2;i++)
-	out[i]=lap[i]+workoff[i]*f->window[i];
-    
-    for(i=f->blocksize/2,j=0;i<f->blocksize;i++)
-      lap[j++]=workoff[i]*f->window[i];
+    for(i=0;i<f->qblocksize;i++)
+      lap[i]=lap[i+f->qblocksize*2]+in[i];
+    for(;i<f->qblocksize*2;i++)
+      lap[i]=in[i]*f->window[i];
   }
+  memset(lap+f->qblocksize*2,0,f->qblocksize*sizeof(*lap));
 }
 
+static void lap_work(float *work,float *lap,float *out,freq_state *f){
+  int i,j;
+  
+  /* lap and out */
+  if(out)
+    for(i=0;i<f->qblocksize;i++)
+      out[i]=lap[i]+work[i];
+  
+  for(i=f->qblocksize,j=0;i<f->qblocksize*3;i++,j++)
+    lap[j]=lap[i]+work[i];
+  
+  for(;i<f->qblocksize*4;i++,j++)
+    lap[j]=work[i];
+  
+}
 
 /* called only by playback thread */
 time_linkage *freq_read(time_linkage *in, freq_state *f,
-			void (*func)(double *data,freq_state *f,
-				     double *peak, double *rms),
+			void (*func)(freq_state *f,float **data,
+				     float **peak, float **rms),
                         int bypass){
-  int i;
+  int i,j,k;
 
-  double feedback_peak[input_ch][freqs];
-  double feedback_rms[input_ch][freqs];
+  float feedback_peak[input_ch][f->bands];
+  float feedback_rms[input_ch][f->bands];
 
-  double peak[freqs];
-  double rms[freqs];
+  float peak[input_ch][f->bands];
+  float rms[input_ch][f->bands];
 
+  float *peakp[input_ch];
+  float *rmsp[input_ch];
+  
   int blocks=0;
 
   if(!bypass){
     memset(feedback_peak,0,sizeof(feedback_peak));
     memset(feedback_rms,0,sizeof(feedback_rms));
   }
-  {
-    double work[f->blocksize*2];
-    
-    switch(f->fillstate){
-    case 0: /* prime the lapping and cache */
-      if(in->samples==0){
-	f->out.samples=0;
-	return &f->out;
-      }
 
+  for(i=0;i<input_ch;i++){
+    peakp[i]=peak[i];
+    rmsp[i]=rms[i];
+  }
+  
+  switch(f->fillstate){
+  case 0: /* prime the lapping and cache */
+    if(in->samples==0){
+      f->out.samples=0;
+      return &f->out;
+    }
+
+    /* zero out lapping and cacahe state */
+    for(i=0;i<input_ch;i++){
+      memset(f->lap[i],0,sizeof(**f->lap)*f->qblocksize*3);
+      memset(f->cache[i],0,sizeof(**f->cache)*input_size);
+    }
+
+    if(bypass){
+      /* no need to do extra work; the panel is invisible (so no need
+         to collect metrics) and the effect is inactive.  Just keep
+         lapping state up to date and pass the data through.  Why
+         bother with lapping?  We don't want a 'pop' when the effect
+         is activated/deactivated */
+
+      for(i=0;i<input_ch;i++)
+	lap_bypass(f->cache[i],in->data[i],f->lap[i],0,f);
+
+    }else{
+
+      /* extrapolation mechanism; avoid harsh transients at edges */
       for(i=0;i<input_ch;i++){
-	double *temp=in->data[i];
+	preextrapolate_helper(in->data[i],input_size,
+			      f->cache[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);
+      }
+
+      /* only need the last two ops to prime the lapping, but they're
+	 the complex ones that span the cache/in gap.  We'd need
+	 three, but the passed input window is zero for the first/last
+	 quarter block and the 'cache' is zero (so the middle of the
+	 first window is also zero). */
+      
+      for(j=0;j<2;j++){
+	for(i=0;i<input_ch;i++){
+	  switch(j){
+	  case 0:
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize,
+		   f->cache[i]+input_size-f->qblocksize,
+		   sizeof(**f->fftwf_buffer)*f->qblocksize);
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize*2,
+		   in->data[i],
+		   sizeof(**f->fftwf_buffer)*f->qblocksize);
+	    break;
+	  case 1:
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize,
+		   in->data[i],
+		   sizeof(**f->fftwf_buffer)*f->qblocksize*2);
+	    break;
+	  }
+	  
 
-	memset(work+f->blocksize/2,0,sizeof(*work)*f->blocksize/2);
-	memcpy(work+f->blocksize,temp,sizeof(*work)*f->blocksize/2);
+	  memset(f->fftwf_buffer[i],0,
+		 sizeof(**f->fftwf_buffer)*f->qblocksize);
+	  memset(f->fftwf_buffer[i]+f->qblocksize*3,0,
+		 sizeof(**f->fftwf_buffer)*f->qblocksize);
+	  for(k=0;k<f->qblocksize*2;k++)
+	    f->fftwf_buffer[i][k+f->qblocksize]*=.25*f->window[k]/f->qblocksize;
+	  /* transform the time data */
 
-	if(!bypass){
-	  transform_work(work,f);
-	  func(work,f,peak,rms);
-	  feedback_work(peak,rms,feedback_peak[i],feedback_rms[i]);
-	  drft_backward(&f->fft,work);
+	  fftwf_execute(f->fftwf_forward[i]);
         }
-	lap_work(work,f->lap[i],0,f,bypass);
+	
+	func(f,f->fftwf_buffer,peakp,rmsp);
         blocks++;	
+	
+	for(i=0;i<input_ch;i++){
+	  feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
+	  fftwf_execute(f->fftwf_backward[i]);
+	  lap_work(f->fftwf_buffer[i],f->lap[i],0,f);
 
-	memset(f->cache[i],0,sizeof(**f->cache)*input_size);
-	in->data[i]=f->cache[i];
-	f->cache[i]=temp;
+	}
       }
-      f->cache_samples=in->samples;
-      f->fillstate=1;
-      f->out.samples=0;
-      if(in->samples==in->size)goto tidy_up;
-	
+    }
+
+    for(i=0;i<input_ch;i++){
+      float *temp=in->data[i];
+      memset(f->cache[i],0,sizeof(**f->cache)*input_size);
+      in->data[i]=f->cache[i];
+      f->cache[i]=temp;
+    }
+      
+    f->cache_samples=in->samples;
+    f->fillstate=1;
+    f->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 */
+
+    if(bypass){
+      /* bypass as above but deal with lapping whole block in and out */
+
       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 */
+	lap_bypass(f->cache[i],in->data[i],f->lap[i],f->out.data[i],f);
+
+    }else{
+
+      /* extrapolation mechanism; avoid harsh transients at edges */
       for(i=0;i<input_ch;i++){
-	double *temp=f->cache[i];
-	int j;
-	for(j=0;j+f->blocksize<=f->out.size;j+=f->blocksize/2){
-
-	  memset(work,0,sizeof(*work)*f->blocksize/2);
-	  memcpy(work+f->blocksize/2,temp+j,sizeof(*work)*f->blocksize);
-	  memset(work+f->blocksize*3/2,0,sizeof(*work)*f->blocksize/2);
-
-	  if(!bypass){
-	    transform_work(work,f);
-	    func(work,f,peak,rms);
-	    feedback_work(peak,rms,feedback_peak[i],feedback_rms[i]);
-	    drft_backward(&f->fft,work);
+	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);
+      }
+
+      for(j=input_size/f->qblocksize-1;j>=0;j--){
+	for(i=0;i<input_ch;i++){
+	  switch(j){
+
+	  case 0:
+	    /* last block, needed because the half-block wide non-zero
+	       data section of the window will spread out to full window
+	       width when we convolve */
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize,in->data[i],
+		   f->qblocksize*2*sizeof(**f->fftwf_buffer));
+	    break;
+	  case 1:
+	    /* second-to-last block, nonzero section of the input
+               spans the cache and input blocks */
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize,
+		   f->cache[i]+input_size-f->qblocksize,
+		   sizeof(**f->fftwf_buffer)*f->qblocksize);
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize*2,
+		   in->data[i],
+		   sizeof(**f->fftwf_buffer)*f->qblocksize);
+	    break;
+	  default:
+	    memcpy(f->fftwf_buffer[i]+f->qblocksize,
+		   f->cache[i]+input_size-(f->qblocksize*j),
+		   f->qblocksize*2*sizeof(**f->fftwf_buffer));
+	    break;
           }
-	  lap_work(work,f->lap[i],f->out.data[i]+j,f,bypass);
-	  blocks++;	
-	}
 
-	memset(work,0,sizeof(*work)*f->blocksize/2);
-	memcpy(work+f->blocksize/2,temp+j,sizeof(*work)*f->blocksize/2);
-	memcpy(work+f->blocksize,in->data[i],sizeof(*work)*f->blocksize/2);
-	memset(work+f->blocksize*3/2,0,sizeof(*work)*f->blocksize/2);
-	
-	if(!bypass){
-	  transform_work(work,f);
-	  func(work,f,peak,rms);
-	  feedback_work(peak,rms,feedback_peak[i],feedback_rms[i]);
-	  drft_backward(&f->fft,work);
+	  memset(f->fftwf_buffer[i],0,
+		 sizeof(**f->fftwf_buffer)*f->qblocksize);
+	  memset(f->fftwf_buffer[i]+f->qblocksize*3,0,
+		 sizeof(**f->fftwf_buffer)*f->qblocksize);
+	  for(k=0;k<f->qblocksize*2;k++)
+	    f->fftwf_buffer[i][k+f->qblocksize]*=.25*f->window[k]/f->qblocksize;
+	  /* transform the time data */
+	  fftwf_execute(f->fftwf_forward[i]);
         }
-	lap_work(work,f->lap[i],f->out.data[i]+j,f,bypass);
+	
+	func(f,f->fftwf_buffer,peakp,rmsp);
         blocks++;	
         
-	f->cache[i]=in->data[i];
-	in->data[i]=temp;
+	for(i=0;i<input_ch;i++){
+	  feedback_work(f,peak[i],rms[i],feedback_peak[i],feedback_rms[i]);
+	  fftwf_execute(f->fftwf_backward[i]);
+	  lap_work(f->fftwf_buffer[i],f->lap[i],
+		   f->out.data[i]+input_size-f->qblocksize*(j+1),f);
+	}
       }
-      f->out.samples=f->cache_samples;
-      f->cache_samples=in->samples;
-      if(f->out.samples<f->out.size)f->fillstate=2;
-      break;
-    case 2: /* we've pushed out EOF already */
-      f->out.samples=0;
     }
-  }
 
+    for(i=0;i<input_ch;i++){
+      float *temp=f->cache[i];
+      f->cache[i]=in->data[i];
+      in->data[i]=temp;
+    }
+    f->out.samples=f->cache_samples;
+    f->cache_samples=in->samples;
+    if(f->out.samples<f->out.size)f->fillstate=2;
+    break;
+  case 2: /* we've pushed out EOF already */
+    f->out.samples=0;
+  }
+  
   /* finish up the state feedabck */
-  blocks/=input_ch;
   if(!bypass){
     int j;
-    double scale=1./blocks;
+    float scale=1./blocks;
     freq_feedback *ff=
       (freq_feedback *)feedback_new(&f->feedpool,new_freq_feedback);
 
+    if(!ff->peak[0])
+      for(i=0;i<input_ch;i++)
+	ff->peak[i]=malloc(f->bands*sizeof(**ff->peak));
+    if(!ff->rms[0])
+      for(i=0;i<input_ch;i++)
+	ff->rms[i]=malloc(f->bands*sizeof(**ff->rms));
+
     for(i=0;i<input_ch;i++)
-      for(j=0;j<freqs;j++){
+      for(j=0;j<f->bands;j++){
         feedback_rms[i][j]=todB(sqrt(feedback_rms[i][j]*scale));
         feedback_peak[i][j]=todB(feedback_peak[i][j]);
       }
       
     for(i=0;i<input_ch;i++){
-      memcpy(ff->peak[i],feedback_peak[i],freqs*sizeof(**feedback_peak));
-      memcpy(ff->rms[i],feedback_rms[i],freqs*sizeof(**feedback_rms));
+      memcpy(ff->peak[i],feedback_peak[i],f->bands*sizeof(**feedback_peak));
+      memcpy(ff->rms[i],feedback_rms[i],f->bands*sizeof(**feedback_rms));
     } 
     ff->bypass=0;
     feedback_push(&f->feedpool,(feedback_generic *)ff);

<p><p>1.4       +23 -19    postfish/freq.h

Index: freq.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/freq.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- freq.h	20 Feb 2004 00:33:21 -0000	1.3
+++ freq.h	29 Feb 2004 03:16:17 -0000	1.4
@@ -22,38 +22,42 @@
  */
 
 #include "postfish.h"
-#include "smallft.h"
-
-#define freqs 30
+#include <fftw3.h>
 
 typedef struct {
-  drft_lookup fft;
   time_linkage out;
   feedback_generic_pool feedpool;
+
+  float **fftwf_buffer; // need one for each channel
+  fftwf_plan *fftwf_forward;   // need one for each channel
+  fftwf_plan *fftwf_backward;  // need one for each channel
   
-  int blocksize;
-  double **ho_window;
-  double   ho_area[freqs];
-  int      ho_bin_lo[freqs];
-  int      ho_bin_hi[freqs];
+  int qblocksize;
+  int bands;
+  float *frequencies;
+
+  float **ho_window;
+  float  *ho_area;
   
-  double *window;
-  double **lap;
-  double **cache;
+  float *window;
+  float **lap;
+  float **cache;
   int cache_samples;
   int fillstate;     /* 0: uninitialized
                         1: normal
                         2: eof processed */
 } freq_state;
 
-extern int pull_freq_feedback(freq_state *ff,double **peak,double **rms);
-extern int freq_load(freq_state *f,int blocksize);
+extern void freq_transform_work(float *work,freq_state *f);
+extern int pull_freq_feedback(freq_state *ff,float **peak,float **rms);
+extern int freq_load(freq_state *f,float *frequencies, int bands, 
+		     int blocksize);
 extern int freq_reset(freq_state *f);
-extern const char *freq_frequency_label(int n);
 extern time_linkage *freq_read(time_linkage *in, freq_state *f,
-			       void (*func)(double *data,freq_state *f,
-					    double *peak, double *rms),
+			       void (*func)(freq_state *f,
+					    float **data,
+					    float **peak, float **rms),
                                int bypassp);
 
-extern void freq_metric_work(double *work,freq_state *f,
-			    double *sq_mags,double *peak,double *rms);
+extern void freq_metric_work(float *work,freq_state *f,
+			     float *sq_mags,float *peak,float *rms);

<p><p>1.16      +12 -12    postfish/input.c

Index: input.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/input.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- input.c	19 Feb 2004 08:32:28 -0000	1.15
+++ input.c	29 Feb 2004 03:16:17 -0000	1.16
@@ -50,8 +50,8 @@
 typedef struct input_feedback{
   feedback_generic parent_class;
   off_t   cursor;
-  double *rms;
-  double *peak;
+  float *rms;
+  float *peak;
 } input_feedback;
 
 static feedback_generic_pool feedpool;
@@ -385,7 +385,7 @@
   return cursor;
 }
 
-off_t input_time_seek_rel(double s){
+off_t input_time_seek_rel(float s){
   off_t ret;
   pthread_mutex_lock(&master_mutex);
   ret=input_seek(cursor+input_rate*inbytes*input_ch*s);
@@ -400,7 +400,7 @@
   return (feedback_generic *)ret;
 }
 
-static void push_input_feedback(double *peak,double *rms, off_t cursor){
+static void push_input_feedback(float *peak,float *rms, off_t cursor){
   int i,n=input_ch+2;
   input_feedback *f=(input_feedback *)
     feedback_new(&feedpool,new_input_feedback);
@@ -410,7 +410,7 @@
   feedback_push(&feedpool,(feedback_generic *)f);
 }
 
-int pull_input_feedback(double *peak,double *rms,off_t *cursor){
+int pull_input_feedback(float *peak,float *rms,off_t *cursor){
   input_feedback *f=(input_feedback *)feedback_pull(&feedpool);
   int i,j,n=input_ch+2;
   if(!f)return 0;
@@ -425,8 +425,8 @@
   int read_b=0,i,j,k;
   int toread_b=out.size*out.channels*inbytes;
   unsigned char *readbuf;
-  double *rms=alloca(sizeof(*rms)*(out.channels+2));
-  double *peak=alloca(sizeof(*peak)*(out.channels+2));
+  float *rms=alloca(sizeof(*rms)*(out.channels+2));
+  float *peak=alloca(sizeof(*peak)*(out.channels+2));
 
   memset(rms,0,sizeof(*rms)*(out.channels+2));
   memset(peak,0,sizeof(*peak)*(out.channels+2));
@@ -495,12 +495,12 @@
   
   k=0;
   for(i=0;i<out.samples;i++){
-    double mean=0.;
-    double div=0.;
-    double divrms=0.;
+    float mean=0.;
+    float div=0.;
+    float divrms=0.;
 
     for(j=0;j<out.channels;j++){
-      double dval;
+      float dval;
       long val=0;
       switch(inbytes){
       case 1:
@@ -535,7 +535,7 @@
 
     /* div */
     for(j=0;j<out.channels;j++){
-      double dval=mean-out.data[j][i];
+      float dval=mean-out.data[j][i];
       if(fabs(dval)>peak[out.channels+1])peak[out.channels+1]=fabs(dval);
       divrms+=dval*dval;
     }

<p><p>1.8       +2 -2      postfish/input.h

Index: input.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/input.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- input.h	24 Dec 2003 09:49:16 -0000	1.7
+++ input.h	29 Feb 2004 03:16:17 -0000	1.8
@@ -6,6 +6,6 @@
 extern off_t input_seek(off_t pos);
 extern time_linkage *input_read(void);
 extern int input_load(int n,char *list[]);
-extern int pull_input_feedback(double *peak,double *rms,off_t *cursor);
+extern int pull_input_feedback(float *peak,float *rms,off_t *cursor);
 extern void input_reset(void);
-extern off_t input_time_seek_rel(double s);
+extern off_t input_time_seek_rel(float s);

<p><p>1.11      +3 -1      postfish/main.c

Index: main.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/main.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- main.c	20 Feb 2004 06:43:32 -0000	1.10
+++ main.c	29 Feb 2004 03:16:17 -0000	1.11
@@ -28,6 +28,7 @@
 
 /* sound playback code is OSS-specific for now */
 #include "postfish.h"
+#include <fftw3.h>
 #include "input.h"
 #include "output.h"
 
@@ -44,7 +45,7 @@
   /* set up filter chains */
   if(declip_load())exit(1);
   if(eq_load())exit(1);
-  if(compand_load())exit(1);
+  if(multicompand_load())exit(1);
 
   /* look at stdout... do we have a file or device? */
   if(!isatty(STDOUT_FILENO)){
@@ -77,6 +78,7 @@
 
   //save_settings(configfd);
   if(configfd>=0)close(configfd);
+
   return(0);
 }
 

<p><p>1.35      +38 -84    postfish/mainpanel.c

Index: mainpanel.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/mainpanel.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- mainpanel.c	20 Feb 2004 06:43:32 -0000	1.34
+++ mainpanel.c	29 Feb 2004 03:16:17 -0000	1.35
@@ -35,44 +35,6 @@
 #include "windowbutton.h"
 
 
-gboolean slider_keymodify(GtkWidget *w,GdkEventKey *event,gpointer in){
-  GtkWidget *toplevel=gtk_widget_get_toplevel(w);
-  GtkAdjustment *adj=gtk_range_get_adjustment(GTK_RANGE(w));
-  if(event->state&GDK_MOD1_MASK) return FALSE;
-  if(event->state&GDK_CONTROL_MASK) return FALSE;
-
-  switch(event->keyval){
-  case GDK_minus:
-    gtk_range_set_value(GTK_RANGE(w),adj->value-adj->step_increment);
-    break;
-  case GDK_underscore:
-    gtk_range_set_value(GTK_RANGE(w),adj->value-adj->page_increment);
-    break;
-  case GDK_equal:
-    gtk_range_set_value(GTK_RANGE(w),adj->value+adj->step_increment);
-    break;
-  case GDK_plus:
-    gtk_range_set_value(GTK_RANGE(w),adj->value+adj->page_increment);
-    break;
-
-  case GDK_Left:
-    gtk_widget_child_focus(toplevel,GTK_DIR_LEFT);
-    break;
-  case GDK_Up:
-    gtk_widget_child_focus(toplevel,GTK_DIR_UP);
-    break;
-  case GDK_Right:
-    gtk_widget_child_focus(toplevel,GTK_DIR_RIGHT);
-    break;
-  case GDK_Down:
-    gtk_widget_child_focus(toplevel,GTK_DIR_DOWN);
-    break;
-  default:
-    return FALSE;
-  }
-  return TRUE;
-}
-
 static void action_zero(GtkWidget *widget,postfish_mainpanel *p){
   const char *time=gtk_entry_get_text(GTK_ENTRY(p->entry_a));
   off_t cursor=input_time_to_cursor(time);
@@ -263,7 +225,7 @@
 static void masterdB_change(GtkWidget *dummy, gpointer in){
   postfish_mainpanel *p=in;
   char buf[80];
-  gdouble val=multibar_get_value(MULTIBAR(p->masterdB_s),0);
+  float val=multibar_get_value(MULTIBAR(p->masterdB_s),0);
   sprintf(buf,"%.1fdB",val);
   readout_set(READOUT(p->masterdB_r),buf);
 
@@ -556,6 +518,7 @@
   for(i=0;i<19;i++)
     panel->ff[i]=gdk_pixmap_create_from_xpm_d(root,
                                               panel->fb+i,NULL,ff_xpm[i]);
+
   xpm_bar[0]=gdk_pixmap_create_from_xpm_d(root,
                                           xbm_bar,NULL,bar_home_xpm);
   xpm_bar[1]=gdk_pixmap_create_from_xpm_d(root,
@@ -610,7 +573,7 @@
   {
     char *labels[12]={"-96","-72","-60","-48","-36","-24",
                       "-16","-8","-3","0","+3","+6"};
-    double levels[13]={-140.,-96.,-72.,-60.,-48.,-36.,-24.,
+    float levels[13]={-140.,-96.,-72.,-60.,-48.,-36.,-24.,
                        -16.,-8.,-3.,0.,+3.,+6.};
 
     GtkWidget *ttable=gtk_table_new(7,2,0);
@@ -658,7 +621,7 @@
     /* master dB slider */
     {
       char *sliderlabels[10]={"-40","-30","-20","-10","0","+10","+20","+30","+40","+50"};
-      double sliderlevels[11]={-50,-40,-30,-20,-10,0,10,20,30,40,50};
+      float sliderlevels[11]={-50,-40,-30,-20,-10,0,10,20,30,40,50};
       
       GtkWidget *box=gtk_hbox_new(0,0);
 
@@ -887,25 +850,33 @@
   /* second order of business; update the input meter if data is
      available and not dirtied by a seek */
   if(!playback_seeking){
-    if(output_feedback_deep()){
-
-      pull_input_feedback(NULL,NULL,NULL);
-      clippanel_feedback(0);
-      eqpanel_feedback(0);
-      compandpanel_feedback(0);
-      pull_output_feedback(NULL,NULL);
-
-
-    }else{
-      off_t   time_cursor;
-      int     n=(input_ch>1?input_ch+2:input_ch);
-      double *rms=alloca(sizeof(*rms)*(input_ch+2));
-      double *peak=alloca(sizeof(*peak)*(input_ch+2));
-      
-      if(pull_output_feedback(peak,rms)){
-	char buffer[14];
-	int i;
+    int     current_p=!output_feedback_deep();
+    off_t   time_cursor;
+    int     n=(input_ch>1?input_ch+2:input_ch);
+    float *rms=alloca(sizeof(*rms)*(input_ch+2));
+    float *peak=alloca(sizeof(*peak)*(input_ch+2));
+    
+    if(pull_output_feedback(peak,rms)){
+      char buffer[14];
+      int i;
+
+      for(i=0;i<n;i++){
+	if(i<input_ch && peak[i]>=1.)
+	  multibar_setwarn(MULTIBAR(panel->outbar),current_p);
+
+	if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->channelshow[i]))){
+	  peak[i]=todB(peak[i]);
+	  rms[i]=todB(rms[i]);
+	}else{
+	  peak[i]=-400;
+	  rms[i]=-400;
+	}
         
+      }
+      
+      multibar_set(MULTIBAR(panel->outbar),rms,peak,n,current_p);
+      
+      if(pull_input_feedback(peak,rms,&time_cursor)){
         for(i=0;i<n;i++){
           if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->channelshow[i]))){
             peak[i]=todB(peak[i]);
@@ -914,36 +885,19 @@
             peak[i]=-400;
             rms[i]=-400;
           }
-
-	  if(i<input_ch && peak[i]>=0.)multibar_setwarn(MULTIBAR(panel->outbar));
         }
-      
-	multibar_set(MULTIBAR(panel->outbar),rms,peak,n);
-	
-	if(pull_input_feedback(peak,rms,&time_cursor)){
-	  for(i=0;i<n;i++){
-	    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(panel->channelshow[i]))){
-	      peak[i]=todB(peak[i]);
-	      rms[i]=todB(rms[i]);
-	    }else{
-	      peak[i]=-400;
-	      rms[i]=-400;
-	    }
-	  }
-	  
-	  multibar_set(MULTIBAR(panel->inbar),rms,peak,n);
-	  input_cursor_to_time(time_cursor,buffer);
-	  readout_set(READOUT(panel->cue),buffer);
-	}
-	
-	clippanel_feedback(1);
-	eqpanel_feedback(1);
-	compandpanel_feedback(1);
         
+	multibar_set(MULTIBAR(panel->inbar),rms,peak,n,current_p);
+	input_cursor_to_time(time_cursor,buffer);
+	readout_set(READOUT(panel->cue),buffer);
       }
+      
+      clippanel_feedback(current_p);
+      eqpanel_feedback(current_p);
+      compandpanel_feedback(current_p);
+      
     }
   }
-  
 }
 
 static gboolean async_event_handle(GIOChannel *channel,

<p><p>1.23      +38 -36    postfish/multibar.c

Index: multibar.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/multibar.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- multibar.c	20 Feb 2004 06:06:00 -0000	1.22
+++ multibar.c	29 Feb 2004 03:16:17 -0000	1.23
@@ -30,9 +30,9 @@
 static GdkBitmap *stipple=NULL;
 static GdkBitmap *stippleB=NULL;
 
-static double compute_dampening(double width, double target,double current,double delta,int zerodamp){
-  double raw_delta=target-current;
-  double testdelta=delta+(raw_delta*.2);
+static float compute_dampening(float width, float target,float current,float delta,int zerodamp){
+  float raw_delta=target-current;
+  float testdelta=delta+(raw_delta*.2);
 
   if(target<0 && !zerodamp){
     if(current>0)
@@ -57,10 +57,10 @@
 
 
 /* call me roughly 10-20fps */
-static void compute(Multibar *m,double *lowvals, double *highvals, int n){
+static void compute(Multibar *m,float *lowvals, float *highvals, int n){
   int i,j,xpad;
   GtkWidget *widget=GTK_WIDGET(m);
-  double max=-400;
+  float max=-400;
   int height=widget->allocation.height;
   int width=widget->allocation.width;
 
@@ -128,7 +128,7 @@
         for(j=0;j<=m->labels;j++)
           if(lowvals[i]>=m->levels[j]){
             if(lowvals[i]<=m->levels[j+1]){
-	      double del=(lowvals[i]-m->levels[j])/(m->levels[j+1]-m->levels[j]);
+	      float del=(lowvals[i]-m->levels[j])/(m->levels[j+1]-m->levels[j]);
               pixlo[i]=(j+del)/m->labels*(widget->allocation.width-xpad*2)-xpad;
               break;
             }else if(j==m->labels){
@@ -141,7 +141,7 @@
         for(;j<=m->labels;j++)
           if(highvals[i]>=m->levels[j]){
             if(highvals[i]<=m->levels[j+1]){
-	      double del=(highvals[i]-m->levels[j])/(m->levels[j+1]-m->levels[j]);
+	      float del=(highvals[i]-m->levels[j])/(m->levels[j+1]-m->levels[j]);
               pixhi[i]=(j+del)/m->labels*(widget->allocation.width-xpad*2)+xpad;
               break;
             }else if(j==m->labels){
@@ -155,10 +155,10 @@
       /* dampen movement according to setup */
       
       for(i=0;i<n;i++){
-	double trackhi=m->bartrackers[i].pixelposhi;
-	double tracklo=m->bartrackers[i].pixelposlo;
-	double delhi=m->bartrackers[i].pixeldeltahi;
-	double dello=m->bartrackers[i].pixeldeltalo;
+	float trackhi=m->bartrackers[i].pixelposhi;
+	float tracklo=m->bartrackers[i].pixelposlo;
+	float delhi=m->bartrackers[i].pixeldeltahi;
+	float dello=m->bartrackers[i].pixeldeltalo;
         
         /* hi */
         delhi = compute_dampening(width-xpad*2,pixhi[i],trackhi,delhi,m->dampen_flags & ZERO_DAMP);
@@ -195,7 +195,7 @@
   GtkWidget *parent=gtk_widget_get_parent(widget);
 
   if(m->thumbs>0){
-    int leftover=height-widget->requisition.height;
+    int leftover=height-widget->requisition.height+3;
     if(leftover<height/4)
       lpad+=leftover;
     else
@@ -310,7 +310,7 @@
       for(j=0;j<=m->labels+1;j++)
         if(m->peak>=m->levels[j]){
           if(m->peak<=m->levels[j+1]){
-	    double del=(m->peak-m->levels[j])/(m->levels[j+1]-m->levels[j]);
+	    float del=(m->peak-m->levels[j])/(m->levels[j+1]-m->levels[j]);
             x=(j+del)/m->labels*(widget->allocation.width-xpad*2)+xpad;
             break;
           }else if (j==m->labels){
@@ -355,7 +355,7 @@
   }
 
   for(i=0;i<m->labels+1;i++){
-    int x=rint(((double)i)/m->labels*(widget->allocation.width-xpad*2))+xpad;
+    int x=rint(((float)i)/m->labels*(widget->allocation.width-xpad*2))+xpad;
     int y=widget->allocation.height-lpad-upad;
     int px,py;
     int gc=0;
@@ -634,6 +634,7 @@
   if(m->thumbs==0){
     xpad=2;
   }else{
+    maxy+=3;
     if(m->thumbs>1)
       xpad=maxy+(maxy/2-1)/2-1+2;
     else
@@ -704,7 +705,7 @@
 static gint determine_thumb(Multibar *m,int ix, int iy){
   GtkWidget *widget=GTK_WIDGET(m);
   int height=widget->allocation.height;
-  double distances[3]={-1,-1,-1};
+  float distances[3]={-1,-1,-1};
   int thumb=-1;
 
   /* lower thumb */
@@ -748,24 +749,24 @@
   return x;
 }
 
-static double pixel_to_val(Multibar *m,int x){
+static float pixel_to_val(Multibar *m,int x){
   GtkWidget *w=GTK_WIDGET(m);
   int j;
 
   for(j=0;j<=m->labels;j++){
-    int pixlo=rint((double)j/m->labels*(w->allocation.width-m->xpad*2));
-    int pixhi=rint((double)(j+1)/m->labels*(w->allocation.width-m->xpad*2));
+    int pixlo=rint((float)j/m->labels*(w->allocation.width-m->xpad*2));
+    int pixhi=rint((float)(j+1)/m->labels*(w->allocation.width-m->xpad*2));
 
     if(x>=pixlo && x<=pixhi){
       if(pixlo==pixhi)return m->levels[j];
-      double del=(double)(x-pixlo)/(pixhi-pixlo);
+      float del=(float)(x-pixlo)/(pixhi-pixlo);
       return (1.-del)*m->levels[j] + del*m->levels[j+1];
     }
   }
   return 0.;
 }
 
-static int val_to_pixel(Multibar *m,double v){
+static int val_to_pixel(Multibar *m,float v){
   GtkWidget *w=GTK_WIDGET(m);
   int j,ret=0;
 
@@ -776,9 +777,9 @@
   }else{
     for(j=0;j<=m->labels;j++){
       if(v>=m->levels[j] && v<=m->levels[j+1]){
-	double del=(v-m->levels[j])/(m->levels[j+1]-m->levels[j]);
-	int pixlo=rint((double)j/m->labels*(w->allocation.width-m->xpad*2));
-	int pixhi=rint((double)(j+1)/m->labels*(w->allocation.width-m->xpad*2));
+	float del=(v-m->levels[j])/(m->levels[j+1]-m->levels[j]);
+	int pixlo=rint((float)j/m->labels*(w->allocation.width-m->xpad*2));
+	int pixhi=rint((float)(j+1)/m->labels*(w->allocation.width-m->xpad*2));
         ret=rint(pixlo*(1.-del)+pixhi*del);
         break;
       }
@@ -828,7 +829,7 @@
   }
 
   if(m->thumbfocus>=0){
-    double v=m->thumbval[m->thumbfocus];
+    float v=m->thumbval[m->thumbfocus];
     int    x=m->thumbpixel[m->thumbfocus];
     
     if(m->thumbfocus==2){
@@ -875,7 +876,7 @@
   if(m->thumbgrab>=0){
     
     int x=event->x+m->thumbx;
-    double v;
+    float v;
 
     x=pixel_bound(m,x);
     m->thumbval[m->thumbgrab]=pixel_to_val(m,x);
@@ -1086,7 +1087,7 @@
   return m_type;
 }
 
-GtkWidget* multibar_new (int n, char **labels, double *levels, int thumbs,
+GtkWidget* multibar_new (int n, char **labels, float *levels, int thumbs,
                          int flags){
   int i;
   GtkWidget *ret= GTK_WIDGET (g_object_new (multibar_get_type (), NULL));
@@ -1131,7 +1132,7 @@
   return ret;
 }
 
-GtkWidget* multibar_slider_new (int n, char **labels, double *levels, 
+GtkWidget* multibar_slider_new (int n, char **labels, float *levels, 
                                 int thumbs){
   int i;
   GtkWidget *ret= multibar_new(n,labels,levels,thumbs,0);
@@ -1142,13 +1143,14 @@
   return ret;
 }
 
-void multibar_set(Multibar *m,double *lo, double *hi, int n){
+void multibar_set(Multibar *m,float *lo, float *hi, int n, int draw){
   GtkWidget *widget=GTK_WIDGET(m);
   compute(m,lo,hi,n);
-  draw_and_expose(widget);
+
+  if(draw)draw_and_expose(widget);
 }
 
-void multibar_thumb_set(Multibar *m,double v, int n){
+void multibar_thumb_set(Multibar *m,float v, int n){
   GtkWidget *w=GTK_WIDGET(m);
   int x;
 
@@ -1204,15 +1206,15 @@
   m->peakdelta=0;
   m->peakdelay=0;
   m->clipdelay=0;
-  multibar_set(m,NULL,NULL,0);
+  multibar_set(m,NULL,NULL,0,1);
 }
 
-void multibar_setwarn(Multibar *m){
+void multibar_setwarn(Multibar *m,int draw){
   GtkWidget *widget=GTK_WIDGET(m);
   if(!m->clipdelay){
     m->clipdelay=15*10;
 
-    draw_and_expose(widget);
+    if(draw)draw_and_expose(widget);
   }else
     m->clipdelay=15*10; /* ~ ten second hold */
 }
@@ -1224,13 +1226,13 @@
   m->callbackp=p;
 }
   
-double multibar_get_value(Multibar *m,int n){
+float multibar_get_value(Multibar *m,int n){
   if(n<0)return 0.;
   if(n>m->thumbs)return 0.;
   return m->thumbval[n];
 }
 
-void multibar_thumb_bounds(Multibar *m,double lo, double hi){
+void multibar_thumb_bounds(Multibar *m,float lo, float hi){
   GtkWidget *w=GTK_WIDGET(m);
   if(lo>hi)return;
 
@@ -1250,7 +1252,7 @@
   draw_and_expose(w);
 }
 
-void multibar_thumb_increment(Multibar *m,double small, double large){
+void multibar_thumb_increment(Multibar *m,float small, float large){
   GtkWidget *w=GTK_WIDGET(m);
   if(small>large)return;
 

<p><p>1.13      +21 -20    postfish/multibar.h

Index: multibar.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/multibar.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- multibar.h	20 Feb 2004 02:09:39 -0000	1.12
+++ multibar.h	29 Feb 2004 03:16:17 -0000	1.13
@@ -44,10 +44,10 @@
 typedef struct _MultibarClass  MultibarClass;
 
 typedef struct bartack {
-  double pixelposhi;
-  double pixelposlo;
-  double pixeldeltahi;
-  double pixeldeltalo;
+  float pixelposhi;
+  float pixelposlo;
+  float pixeldeltahi;
+  float pixeldeltalo;
 } bartrack;
 
 #define HI_ATTACK   (1<<0)
@@ -66,12 +66,12 @@
   int labels;
   int readout;
   PangoLayout **layout;
-  double       *levels;
+  float       *levels;
 
   GdkGC         *boxcolor;
-  double         peak;
+  float         peak;
   int            peakdelay;
-  double         peakdelta;
+  float         peakdelta;
 
   int            clipdelay;
 
@@ -80,17 +80,17 @@
   int dampen_flags;
 
   int    thumbs;
-  double thumbval[3];
+  float  thumbval[3];
   int    thumbpixel[3];
   GtkStateType thumbstate[3];
   int    thumbfocus;
   int    prev_thumbfocus;
   int    thumbgrab;
   int    thumbx;
-  double thumblo;
-  double thumbhi;
-  double thumbsmall;
-  double thumblarge;
+  float  thumblo;
+  float  thumbhi;
+  float  thumbsmall;
+  float  thumblarge;
 
   int    thumblo_x;
   int    thumbhi_x;
@@ -108,26 +108,27 @@
 };
 
 GType          multibar_get_type        (void);
-GtkWidget*     multibar_new             (int n, char **labels, double *levels,
+GtkWidget*     multibar_new             (int n, char **labels, float *levels,
                                          int thumbs, int flags);
-GtkWidget*     multibar_slider_new (int n, char **labels, double *levels, 
+GtkWidget*     multibar_slider_new (int n, char **labels, float *levels, 
                                     int thumbs);
 
 void	       multibar_clear           (Multibar *m);
-void	       multibar_set             (Multibar *m,double *lo,double *hi, int n);
-void	       multibar_thumb_set       (Multibar *m,double v, int n);
-void	       multibar_setwarn         (Multibar *m);
+void	       multibar_set             (Multibar *m,float *lo,float *hi, int n,int drawp);
+void	       multibar_thumb_set       (Multibar *m,float v, int n);
+void	       multibar_setwarn         (Multibar *m,int drawp);
 void           multibar_reset           (Multibar *m);
 void           multibar_callback        (Multibar *m,
                                          void (*callback)
                                          (GtkWidget *,gpointer),
                                          gpointer);
-double multibar_get_value(Multibar *m,int n);
-void multibar_thumb_bounds(Multibar *m,double lo, double hi);
-void multibar_thumb_increment(Multibar *m,double small, double large);
+float multibar_get_value(Multibar *m,int n);
+void multibar_thumb_bounds(Multibar *m,float lo, float hi);
+void multibar_thumb_increment(Multibar *m,float small, float large);
 
 G_END_DECLS
 
 #endif
 
 
+

<p><p>1.16      +16 -16    postfish/output.c

Index: output.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/output.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- output.c	20 Feb 2004 06:43:32 -0000	1.15
+++ output.c	29 Feb 2004 03:16:17 -0000	1.16
@@ -30,7 +30,7 @@
 #include "output.h"
 #include "declip.h"
 #include "eq.h"
-#include "compand.h"
+#include "multicompand.h"
 
 extern int input_size;
 sig_atomic_t playback_active=0;
@@ -55,14 +55,14 @@
   input_reset();  /* clear any persistent lapping state */
   declip_reset();  /* clear any persistent lapping state */
   eq_reset();      /* clear any persistent lapping state */
-  compand_reset();      /* clear any persistent lapping state */
+  multicompand_reset(); /* clear any persistent lapping state */
   output_reset(); /* clear any persistent lapping state */
 }
 
 typedef struct output_feedback{
   feedback_generic parent_class;
-  double *rms;
-  double *peak;
+  float *rms;
+  float *peak;
 } output_feedback;
 
 static feedback_generic_pool feedpool;
@@ -74,7 +74,7 @@
   return (feedback_generic *)ret;
 }
 
-static void push_output_feedback(double *peak,double *rms){
+static void push_output_feedback(float *peak,float *rms){
   int i,n=input_ch+2;
   output_feedback *f=(output_feedback *)
     feedback_new(&feedpool,new_output_feedback);
@@ -84,7 +84,7 @@
   feedback_push(&feedpool,(feedback_generic *)f);
 }
 
-int pull_output_feedback(double *peak,double *rms){
+int pull_output_feedback(float *peak,float *rms){
   output_feedback *f=(output_feedback *)feedback_pull(&feedpool);
   int i,j,n=input_ch+2;
   if(!f)return 0;
@@ -213,8 +213,8 @@
   long rate=-1;
 
   /* for output feedback */
-  double *rms=alloca(sizeof(*rms)*(input_ch+2));
-  double *peak=alloca(sizeof(*peak)*(input_ch+2));
+  float *rms=alloca(sizeof(*rms)*(input_ch+2));
+  float *peak=alloca(sizeof(*peak)*(input_ch+2));
 
   while(1){
     if(playback_seeking){
@@ -229,9 +229,9 @@
     result=link->samples;
     link=declip_read(link);
     result|=link->samples;
-    link=eq_read(link);
+    link=multicompand_read(link);
     result|=link->samples;
-    link=compand_read(link);
+    link=eq_read(link);
     result|=link->samples;
     
     if(!result)break;
@@ -241,7 +241,7 @@
     
     /* temporary; this would be frequency domain in the finished postfish */
     if(link->samples>0){
-      double scale=fromdB(master_att/10.);
+      float scale=fromdB(master_att/10.);
       for(i=0;i<link->samples;i++)
         for(j=0;j<link->channels;j++)
           link->data[j][i]*=scale;
@@ -279,12 +279,12 @@
       /* final limiting and conversion */
 
       for(k=0,i=0;i<link->samples;i++){
-	double mean=0.;
-	double div=0.;
-	double divrms=0.;
+	float mean=0.;
+	float div=0.;
+	float divrms=0.;
         
         for(j=0;j<link->channels;j++){
-	  double dval=link->data[j][i];
+	  float dval=link->data[j][i];
 
           switch(outbytes){
           case 3:
@@ -333,7 +333,7 @@
         
         /* div */
         for(j=0;j<link->channels;j++){
-	  double dval=mean-link->data[j][i];
+	  float dval=mean-link->data[j][i];
           if(fabs(dval)>peak[input_ch+1])peak[input_ch+1]=fabs(dval);
           divrms+=dval*dval;
         }

<p><p>1.6       +24 -1     postfish/output.h

Index: output.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/output.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- output.h	20 Feb 2004 00:33:21 -0000	1.5
+++ output.h	29 Feb 2004 03:16:17 -0000	1.6
@@ -1,4 +1,27 @@
-extern int pull_output_feedback(double *peak,double *rms);
+/*
+ *
+ *  postfish
+ *    
+ *      Copyright (C) 2002-2004 Monty
+ *
+ *  Postfish is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *   
+ *  Postfish is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *   
+ *  You should have received a copy of the GNU General Public License
+ *  along with Postfish; see the file COPYING.  If not, write to the
+ *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 
+ */
+
+extern int pull_output_feedback(float *peak,float *rms);
 extern void *playback_thread(void *dummy);
 extern void output_halt_playback(void);
 extern void output_reset(void);

<p><p>1.11      +1 -1      postfish/postfish.h

Index: postfish.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/postfish.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- postfish.h	17 Feb 2004 11:52:18 -0000	1.10
+++ postfish.h	29 Feb 2004 03:16:17 -0000	1.11
@@ -62,7 +62,7 @@
   int samples;  /* normally same as size; exception is EOF */
   int channels;
   int rate;
-  double **data;
+  float **data;
 } time_linkage;
 
 extern pthread_mutex_t master_mutex;

<p><p>1.7       +2 -2      postfish/readout.c

Index: readout.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/readout.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- readout.c	17 Feb 2004 11:52:18 -0000	1.6
+++ readout.c	29 Feb 2004 03:16:17 -0000	1.7
@@ -46,7 +46,7 @@
   pango_layout_get_pixel_size(r->layout,&px,&py);
 
   gdk_draw_layout (r->backing,text_gc,
-		   width-2-px-(py/2),(height-py)/2,
+		   width-2-px-(py/4),(height-py)/2,
                    r->layout);
   
   /* draw frame */
@@ -94,7 +94,7 @@
   
   pango_layout_get_pixel_size(r->layout,&x,&y);
   
-  requisition->width = x+4+y;
+  requisition->width = x+4+y/2;
   requisition->height = y+6;
 
 }

<p><p>1.6       +66 -38    postfish/reconstruct.c

Index: reconstruct.c
===================================================================
RCS file: /usr/local/cvsroot/postfish/reconstruct.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- reconstruct.c	13 Feb 2004 18:11:35 -0000	1.5
+++ reconstruct.c	29 Feb 2004 03:16:17 -0000	1.6
@@ -29,89 +29,117 @@
    n^3 -> n^2 log n jump possible. Google for it, you'll find it. */
 
 #include <string.h>
-#include "smallft.h"
+#include <fftw3.h>
 #include "reconstruct.h"
 
-static void AtWA(drft_lookup *fft, double *x, double *w,int n){
+/* fftw3 requires this kind of static setup */
+static fftwf_plan fftwf_qf;
+static fftwf_plan fftwf_qb;
+static fftwf_plan fftwf_sf;
+static fftwf_plan fftwf_sb;
+static float *q;
+static float *s;
+static blocksize=0;
+
+void reconstruct_reinit(int n){
+  if(blocksize!=n){
+    if(blocksize){
+      fftwf_destroy_plan(fftwf_qf);
+      fftwf_destroy_plan(fftwf_qb);
+      fftwf_destroy_plan(fftwf_sf);
+      fftwf_destroy_plan(fftwf_sb);
+      fftwf_free(q);
+      fftwf_free(s);
+    }
+    blocksize=n;
+
+    q=fftwf_malloc((n+2)*sizeof(*q));
+    s=fftwf_malloc((n+2)*sizeof(*s));
+    fftwf_qf=fftwf_plan_dft_r2c_1d(n,q,(fftwf_complex *)q,FFTW_MEASURE);
+    fftwf_qb=fftwf_plan_dft_c2r_1d(n,(fftwf_complex *)q,q,FFTW_MEASURE);
+    fftwf_sf=fftwf_plan_dft_r2c_1d(n,s,(fftwf_complex *)s,FFTW_MEASURE);
+    fftwf_sb=fftwf_plan_dft_c2r_1d(n,(fftwf_complex *)s,s,FFTW_MEASURE);
+  }
+}
+
+static void AtWA(float *w,int n){
   int i;
-  drft_forward(fft,x);
-  for(i=0;i<n;i++)x[i]*=w[i];
-  drft_backward(fft,x); /* this is almost the same as A'; see the
-			   correction factor rolled into w at the
-			   beginning of reconstruct() */
+  fftwf_execute(fftwf_qf);
+  for(i=0;i<n+2;i++)q[i]*=w[i];
+  fftwf_execute(fftwf_qb); /* this is almost the same as A'; see the
+			      correction factor rolled into w at the
+			      beginning of reconstruct() */
 }
 
 /* This is not the inverse of XA'WAX; the algebra isn't valid (due to
    the singularity of the selection matrix X) and as such is useless
    for direct solution.  However, it does _approximate_ the inverse
    and as such makes an excellent system preconditioner. */
-static void precondition(drft_lookup *fft, double *x, double *w,int n){
+static void precondition(float *w,int n){
   int i;
 
   /* no need to remove scaling of result; the relative stretching of
      the solution space is what's important */
 
-  drft_forward(fft,x); /* almost the same as A^-1'; see the correction
-			  factor rolled into w at the beginning of
-			  reconstruct() */
-  for(i=0;i<n;i++)x[i]/=w[i];  
-  drft_backward(fft,x);
+  fftwf_execute(fftwf_sf); /* almost the same as A^-1'; see the correction
+			      factor rolled into w at the beginning of
+			      reconstruct() */
+  for(i=0;i<n+2;i++)s[i]/=w[i];  
+  fftwf_execute(fftwf_sb); 
 }
 
-static double inner_product(double *a, double *b, int n){
+static float inner_product(float *a, float *b, int n){
   int i;
-  double acc=0.;
+  float acc=0.;
   for(i=0;i<n;i++)acc+=a[i]*b[i];
   return acc;
 }
 
-#include <stdio.h>
-void reconstruct(drft_lookup *fft,
-		 double *x, double *w, 
-		 double *flag, double e,int max,int n){
+void reconstruct(float *x, float *w,
+		 float *flag, float e,int max){
+  int n=blocksize;
   int i,j;
-  double Atb[n];
-  double r[n];
-  double d[n];
-  double q[n];
-  double s[n];
-  double phi_new,phi_old,res_0,res_new;
-  double alpha,beta;
+  float Atb[n];
+  float r[n];
+  float d[n];
+  float phi_new,phi_old,res_0,res_new;
+  float alpha,beta;
 
   /* hack; roll a correction factor for A'/A-1 into w */
   for(j=1;j<n-1;j++)w[j]*=.5;
 
   /* compute initial Atb */
-  for(j=0;j<n;j++)Atb[j]=x[j]*(flag[j]-1.);
-  AtWA(fft,Atb,w,n);
+  for(j=0;j<n;j++)q[j]=x[j]*(flag[j]-1.);
+  AtWA(w,n);
+  for(j=0;j<n;j++)Atb[j]=q[j];
 
   /* compute initial residue */
-  for(j=0;j<n;j++)r[j]=x[j]*flag[j];
-  AtWA(fft,r,w,n);
-  for(j=0;j<n;j++)d[j]=r[j]=(Atb[j]-r[j])*flag[j];
+  for(j=0;j<n;j++)q[j]=x[j]*flag[j];
+  AtWA(w,n);
+  for(j=0;j<n;j++)s[j]=r[j]=(Atb[j]-q[j])*flag[j];
 
   /* initial preconditioning */
-  precondition(fft,d,w,n);
-  for(j=0;j<n;j++)q[j]=d[j]*=flag[j];
+  precondition(w,n);
+  for(j=0;j<n;j++)q[j]=d[j]=s[j]*=flag[j];
 
   phi_new=inner_product(r,d,n);
   res_new=res_0=inner_product(Atb,Atb,n);
 
   for(i=0;i<max && sqrt(res_new)/sqrt(res_0)>e;i++){
-    AtWA(fft,q,w,n);
+    AtWA(w,n);
     alpha=phi_new/inner_product(d,q,n);
     for(j=0;j<n;j++)x[j]+=alpha*d[j];
 
     if((i & 0x3f)==0x3f){
-      for(j=0;j<n;j++)r[j]=x[j]*flag[j];
-      AtWA(fft,r,w,n);
-      for(j=0;j<n;j++)r[j]=(Atb[j]-r[j])*flag[j];
+      for(j=0;j<n;j++)q[j]=x[j]*flag[j];
+      AtWA(w,n);
+      for(j=0;j<n;j++)r[j]=(Atb[j]-q[j])*flag[j];
     }else
       for(j=0;j<n;j++)r[j]-=alpha*q[j]*flag[j];
     
     /* apply preconditioner */
     for(j=0;j<n;j++)s[j]=r[j]*flag[j];
-    precondition(fft,s,w,n);
+    precondition(w,n);
     for(j=0;j<n;j++)s[j]*=flag[j];
 
     phi_old=phi_new;

<p><p>1.4       +3 -2      postfish/reconstruct.h

Index: reconstruct.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/reconstruct.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- reconstruct.h	14 Jan 2004 16:03:34 -0000	1.3
+++ reconstruct.h	29 Feb 2004 03:16:17 -0000	1.4
@@ -21,5 +21,6 @@
  * 
  */
 
-extern void reconstruct(drft_lookup *fft,double *x, double *w, double *flag, 
-			double e,int max,int n);
+extern void reconstruct_reinit(int n);
+extern void reconstruct(float *x, float *w, float *flag, 
+			float e,int max);

<p><p>1.39      +2 -2      postfish/version.h

Index: version.h
===================================================================
RCS file: /usr/local/cvsroot/postfish/version.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- version.h	21 Feb 2004 01:50:55 -0000	1.38
+++ version.h	29 Feb 2004 03:16:17 -0000	1.39
@@ -1,2 +1,2 @@
-#define VERSION "$Id: version.h,v 1.38 2004/02/21 01:50:55 xiphmont Exp $ "
-/* DO NOT EDIT: Automated versioning hack [Fri Feb 20 03:14:29 EST 2004] */
+#define VERSION "$Id: version.h,v 1.39 2004/02/29 03:16:17 xiphmont Exp $ "
+/* DO NOT EDIT: Automated versioning hack [Sat Feb 28 22:13:31 EST 2004] */

<p><p>1.4       +69 -78    postfish/lpc.c

<p><p><p>1.3       +26 -32    postfish/lpc.h

<p><p><p>1.1                  postfish/multicompand.c

Index: multicompand.c
===================================================================
/*
 *
 *  postfish
 *    
 *      Copyright (C) 2002-2004 Monty and Xiph.Org
 *
 *  Postfish is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  Postfish is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with Postfish; see the file COPYING.  If not, write to the
 *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * 
 */

#include "multicompand.h"
#include <fftw3.h>
#include "subband.h"

tatic void _analysis(char *base,int i,float *v,int n,int bark,int dB){
  int j;
  FILE *of;
  char buffer[80];

  sprintf(buffer,"%s_%d.m",base,i);
  of=fopen(buffer,"w");
  
  if(!of)perror("failed to open data dump file");
  
  for(j=0;j<n;j++){
    if(bark){
      float b=toBark((4000.f*j/n)+.25);
      fprintf(of,"%f ",b);
    }else
      fprintf(of,"%f ",(float)j);
    
    if(dB){
      float val=todB(hypot(v[j],v[j+1]));
      if(val<-140)val=-140;
      fprintf(of,"%f\n",val);
      j++;
     
    }else{
      fprintf(of,"%f\n",v[j]);
    }
  }
  fclose(of);
}

tatic void _analysis_append(char *base,int basemod,float *v,int n,int off){
  int j;
  FILE *of;
  char buffer[80];

  sprintf(buffer,"%s_%d.m",base,basemod);
  of=fopen(buffer,"a");
  
  if(!of)perror("failed to open data dump file");
  
  for(j=0;j<n;j++){
    fprintf(of,"%f ",(float)j+off);    
    fprintf(of,"%f\n",v[j]);
  }
  fprintf(of,"\n");
  fclose(of);
}

extern int input_size;
extern int input_rate;
extern int input_ch;

/* An array of two tap Bessel filters for bandlimiting our followers
   and performing continuous RMS estimation.  Why Bessel filters?  Two
   reasons: They exhibit very little ringing in the time domain and
   about a half-order of magnitude less roundoff noise from gain
   (compared to other IIR families) */

tatic float iirg_list[7]={
  4.875178475e+06,  // 5
  1.008216556e+06,  // 11
  2.524889925e+05,  // 22
  6.3053949794e+04, // 44
  1.5872282930e+04, // 88
  4.086422543e+03,  // 175
  1.049342702e+03   // 350
};

tatic float iirc_list[7][2]={
  {1.9984308946, -.9984317150},  // 5
  {1.9965490514, -.9965530188},  // 11
  {1.9931020727, -.9931179150},  // 22
  {1.9861887623, -.98625220002}, // 44
  {1.9724411246, -.97269313627}, // 88
  {1.9455669653, -.9465458165},  // 175
  {1.8921217885, -.8959336985}   // 350
};

tatic float iir_corner_list[7]={5,11,22,44,88,175,350};
static float iir_rmsoffset_list[7]={1048,524,262,131,65,32,16};
static float iir_peakoffset_list[7]={7200,3600,1800,900,450,225,112};

/* ugly, ugly ugly */
static float iirx[2];
static float iiry[2];
static float iirg;
static float iirc[2];

tatic inline float iir(float x){ 
  float y=
    (iirx[1]+iirx[0]*2.+x)/iirg
    + iiry[1]*iirc[1]
    + iiry[0]*iirc[0];
  iiry[1]=iiry[0];iiry[0]=y;
  iirx[1]=iirx[0];iirx[0]=x;
  return y;
}

typedef struct {
  float peak_shelf_y[1];
  float rms_smooth_y[2];
  float rms_smooth_x[2];

  float main_decay_chase;
  float envelope_decay_chase;
  float suppress_decay_chase;

  float env1[2];
  float env2[2];

} envelope_state;

typedef struct {
  subband_state ss;

  int rmschoice[multicomp_freqs];

  envelope_state **e;
} multicompand_state;

ig_atomic_t compand_visible;
sig_atomic_t compand_active;
multicompand_state ms;
compand_settings c;

void multicompand_reset(){

}

int multicompand_load(void){
  int i,j;
  memset(&ms,0,sizeof(ms));

  subband_load(&ms.ss,multicomp_freq_list,multicomp_freqs);

  /* select the RMS follower filters to use according to 
     sample rate and band frequency */
  for(i=0;i<multicomp_freqs;i++){
    /* select a filter with a corner frequency of about 1/8 the
       band center. Don't go lower than 11 or higher than the 44 */
    double bf=multicomp_freq_list[i];

    ms.rmschoice[i]=3;
    for(j=1;j<4;j++)
      if(iir_corner_list[j]*input_rate/44100 > bf*.125){
        ms.rmschoice[i]=j;
        break;
      }

    fprintf(stderr,"band %d %fHz filter corner %f\n",
            i,bf,iir_corner_list[ms.rmschoice[i]]);
  }

  ms.e=calloc(input_ch,sizeof(*(ms.e)));
  for(i=0;i<input_ch;i++)
    ms.e[i]=calloc(multicomp_freqs,sizeof(**(ms.e)));

  return 0;
}

tatic long offset=0;
static void multicompand_work(void){
  float rms[input_size];
  float peak[input_size];
  int i,j,k;

  /* we chase both peak and RMS forward at all times. All portions of
     the compander can use the raw values of one or the other at any
     time */

  for(j=0;j<ms.ss.bands;j++){
    for(i=0;i<input_ch;i++){
      float *x=ms.ss.lap[i][j];
      int ahead=iir_rmsoffset_list[ms.rmschoice[j]];
      /* RMS chase [per channel] */
      iirg=iirg_list[ms.rmschoice[j]];
      iirc[0]=iirc_list[ms.rmschoice[j]][0];
      iirc[1]=iirc_list[ms.rmschoice[j]][1];
      iirx[0]=ms.e[i][j].rms_smooth_x[0];
      iirx[1]=ms.e[i][j].rms_smooth_x[1];
      iiry[0]=ms.e[i][j].rms_smooth_y[0];
      iiry[1]=ms.e[i][j].rms_smooth_y[1];

      for(k=0;k<input_size;k++)
        rms[k]=sqrt(iir(x[k+ahead]*x[k+ahead]));

      _analysis_append("band",j,x,input_size,offset);
      _analysis_append("envelope",j,rms,input_size,offset);

      ms.e[i][j].rms_smooth_x[0]=iirx[0];
      ms.e[i][j].rms_smooth_x[1]=iirx[1];
      ms.e[i][j].rms_smooth_y[0]=iiry[0];
      ms.e[i][j].rms_smooth_y[1]=iiry[1];

    }
  }

  offset+=input_size;
}

time_linkage *multicompand_read(time_linkage *in){
  return subband_read(in,&ms.ss,multicompand_work,
                      !(compand_visible||compand_active));
}

<p><p>1.1                  postfish/multicompand.h

Index: multicompand.h
===================================================================
/*
 *
 *  postfish
 *    
 *      Copyright (C) 2002-2004 Monty and Xiph.Org
 *
 *  Postfish is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  Postfish is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with Postfish; see the file COPYING.  If not, write to the
 *  Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * 
 */

#include "postfish.h"

#define multicomp_freqs 9

tatic float multicomp_freq_list[multicomp_freqs+1]={
  63,
  125,
  250,
  500,
  1000,
  2000,
  4000,
  8000,
  16000,9e10};

tatic char *multicomp_freq_labels[multicomp_freqs]={
  "63",
  "125",
  "250",
  "500",
  "1k",
  "2k",
  "4k",
  "8k",
  "16k"
};

typedef struct {
  sig_atomic_t link_mode;

  sig_atomic_t static_mode;
  sig_atomic_t static_trim;
  sig_atomic_t static_decay;
  sig_atomic_t static_c_ratio;
  sig_atomic_t static_e_ratio;
  sig_atomic_t static_g[multicomp_freqs];
  sig_atomic_t static_e[multicomp_freqs];
  sig_atomic_t static_c[multicomp_freqs];

  sig_atomic_t envelope_mode;
  sig_atomic_t envelope_c;

  sig_atomic_t suppress_mode;
  sig_atomic_t suppress_ratio;
  sig_atomic_t suppress_decay;
  sig_atomic_t suppress_bias;
  sig_atomic_t suppress_depth;

} compand_settings;

extern void multicompand_reset();
extern int multicompand_load(void);
extern time_linkage *multicompand_read(time_linkage *in);

<p><p><p><p>--- >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