[xiph-commits] r8579 - trunk/postfish

xiphmont at motherfish-iii.xiph.org xiphmont at motherfish-iii.xiph.org
Sun Jan 2 12:23:41 PST 2005


Author: xiphmont
Date: 2005-01-02 12:23:41 -0800 (Sun, 02 Jan 2005)
New Revision: 8579

Added:
   trunk/postfish/freeverb.c
   trunk/postfish/freeverb.h
Log:
It would be helpful to actually add the source for the new reverb :-P



Added: trunk/postfish/freeverb.c
===================================================================
--- trunk/postfish/freeverb.c	2005-01-02 20:21:01 UTC (rev 8578)
+++ trunk/postfish/freeverb.c	2005-01-02 20:23:41 UTC (rev 8579)
@@ -0,0 +1,650 @@
+/*
+ *
+ *  postfish
+ *    
+ *      Copyright (C) 2002-2005 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.
+ *
+ * 
+ */
+
+/* Derived from the Freeverb3 public domain reverb code by Jezar at
+   Dreampoint. This C version of the original C++ assumes reverb to be
+   a solved problem and so is not structured for tinkering; it removes
+   much of the pretty OO to make it a monolithic black box. */
+
+#include "postfish.h"
+#include "internal.h"
+#include "freeverb.h"
+#include "window.h"
+
+static void inject_set(reverb_state *r,int inject){
+  int i;
+  for(i=0;i<numcombs;i++){
+    int off=(1000-inject)*r->comb[i].size/scaleroom;
+    r->comb[i].extpending=r->comb[i].injptr-off;
+    if(r->comb[i].extpending<r->comb[i].buffer)r->comb[i].extpending+=r->comb[i].size;
+  }
+}
+
+static void inject_finalize(reverb_state *r){
+  int i;
+  for(i=0;i<numcombs;i++)
+    r->comb[i].extptr=r->comb[i].extpending;
+}
+ 
+static void reset_one(reverb_state *r,int inject, const int *combtuning, const int *alltuning){
+  int i;
+  memset(r,0,sizeof(*r));
+  
+  r->comb[0].buffer=r->bufcomb0;
+  r->comb[1].buffer=r->bufcomb1;
+  r->comb[2].buffer=r->bufcomb2;
+  r->comb[3].buffer=r->bufcomb3;
+  r->comb[4].buffer=r->bufcomb4;
+  r->comb[5].buffer=r->bufcomb5;
+  r->comb[6].buffer=r->bufcomb6;
+  r->comb[7].buffer=r->bufcomb7;
+
+  for(i=0;i<numcombs;i++)
+    r->comb[i].size=combtuning[i];
+  for(i=0;i<numcombs;i++)
+    r->comb[i].injptr=r->comb[i].buffer;
+
+  r->allpass[0].buffer=r->bufallpass0;
+  r->allpass[1].buffer=r->bufallpass1;
+  r->allpass[2].buffer=r->bufallpass2;
+  r->allpass[3].buffer=r->bufallpass3;
+  for(i=0;i<numallpasses;i++)
+    r->allpass[i].size=alltuning[i];
+  for(i=0;i<numallpasses;i++)
+    r->allpass[i].bufptr=r->allpass[i].buffer;
+
+  inject_set(r,inject);
+  for(i=0;i<numcombs;i++)
+    r->comb[i].extptr=r->comb[i].extpending;
+}
+
+static inline float allpass_process(allpass_state *a,
+				    float  input){
+  float val    = *a->bufptr;
+  float output = val - input;
+  
+  *a->bufptr   = val * .5f + input;
+  underguard(a->bufptr);
+  
+  if(a->bufptr<=a->buffer) a->bufptr += a->size;
+  --a->bufptr;
+
+  return output;
+}
+
+static inline float comb_process(comb_state *c,
+				 float  feedback,
+				 float  hfdamp,
+				 float  input){
+  float val      = *c->extptr;
+  c->filterstore = val + (c->filterstore - val)*hfdamp;
+  underguard(&c->filterstore);
+
+  *c->injptr     = input + c->filterstore * feedback;
+  underguard(c->injptr);
+
+
+  if(c->injptr<=c->buffer) c->injptr += c->size;
+  --c->injptr;
+  if(c->extptr<=c->buffer) c->extptr += c->size;
+  --c->extptr;
+
+  return val;
+}
+
+static inline float comb_process_exttrans(comb_state *c,
+					  float  transval,
+					  float  feedback,
+					  float  hfdamp,
+					  float  input){
+  float val      = *c->extpending*(1.f-transval) + *c->extptr*transval;
+  c->filterstore = val + (c->filterstore - val)*hfdamp;
+  underguard(&c->filterstore);
+
+  *c->injptr     = input + c->filterstore * feedback;
+  underguard(c->injptr);
+
+
+  if(c->injptr<=c->buffer) c->injptr += c->size;
+  --c->injptr;
+  if(c->extptr<=c->buffer) c->extptr += c->size;
+  --c->extptr;
+  if(c->extpending<=c->buffer) c->extpending += c->size;
+  --c->extpending;
+
+  return val;
+}
+
+static void reverb_instance_one_reset(reverb_instance_one *rio){
+  rio->initstate=0;
+}
+
+void reverb_instance_reset(reverb_instance *ri){
+  int i;
+  ri->initstate=0;
+  for(i=0;i<ri->ch;i++)
+    reverb_instance_one_reset(ri->reverbs+i);
+}
+
+static void process_one_inner(reverb_state *r, 
+			      float feedback, float hfdamp, float att,
+			      float *input, float *output, long n){
+  float out,val=0;
+  int i;
+
+  att=fromdB(att) * fixedgain;
+
+  while(n-- > 0){
+    out = 0;
+    if(input) val = *input++;
+
+    for(i=0;i<numcombs;i++)
+      out += comb_process(r->comb+i,feedback,hfdamp,val);
+    
+    for(i=0;i<numallpasses;i++)
+      out  = allpass_process(r->allpass+i,out);
+    
+    if(output) *output++ = out*att;
+  }
+}
+
+static void process_one_inner2(reverb_state *r, float *transwindow,
+			       float feedback1, float feedback2, 
+			       float hfdamp1, float hfdamp2, 
+			       float att1, float att2,
+			       int inject1, int inject2,
+			       float *input1, long n1,
+			       float *input2, long n2,
+			       float *output){
+
+  int n=n1+n2,i;
+  float out,val=0;
+  float *input=input1;
+
+  if(inject1 != inject2) inject_set(r,inject2);
+
+  while(n > 0){
+    float feedback= transwindow[n]*(feedback1-feedback2) + feedback2;
+    float hfdamp= transwindow[n]*(hfdamp1-hfdamp2) + hfdamp2;
+    float att = fromdB(transwindow[n]*(att1-att2) + att2) * fixedgain;
+
+    if(n == n2)input=input2;
+    n--;
+
+    out = 0;
+    if(input) val = *input++;
+
+    if(inject1 != inject2){
+      for(i=0;i<numcombs;i++)
+	out += comb_process_exttrans(r->comb+i,transwindow[n],feedback,hfdamp,val);
+    }else{
+      for(i=0;i<numcombs;i++)
+	out += comb_process(r->comb+i,feedback,hfdamp,val);
+    }
+
+    for(i=0;i<numallpasses;i++)
+      out  = allpass_process(r->allpass+i,out);
+
+    if(output) *output++ = out*att;
+
+  }
+
+
+  if(inject1 != inject2)inject_finalize(r);
+
+}
+
+static void process_one_wrapper(reverb_state *r,
+				float *transwindow,
+				float feedback, float feedback2, 
+				float hfdamp, float hfdamp2, 
+				float att, float att2,
+				int inject, int inject2, 
+				float *input1, long n1,
+				float *input2, long n2,
+				float *output){
+  if(att != att2 ||
+     hfdamp != hfdamp2 ||
+     feedback != feedback2 ||
+     inject != inject2 ){
+    
+    process_one_inner2(r,transwindow,
+		       feedback,feedback2,hfdamp,hfdamp2,att,att2,
+		       inject,inject2,input1,n1,input2,n2,output);
+  }else{
+    process_one_inner(r,feedback,hfdamp,att,input1,output,n1);      
+    process_one_inner(r,feedback,hfdamp,att,input2,output+n1,n2);
+  }
+}
+
+/* returns active or inactive status */
+static u_int32_t process_one(reverb_instance_one *ri, reverb_settings *s, 
+			     float *in, int muted, float *outL, float *outR, 
+			     float *transwindow, long n, long blocksize){
+  
+  float *cache=ri->cache;
+  int i;
+  int energy=0;
+
+  /* convert settings */
+  float feedback = (s->liveness*scaleliveness/1000.f+offsetliveness);
+  float hfdamp   = s->hfdamp*.001*scalehfdamp;
+  float wet      = s->wet * .1f;
+  int   width    = s->width;
+  float wet1     = sin(width * M_PI * .0005)*.5f+.5f;
+  float wet2     = cos(width * M_PI * .0005)*.5;
+  int   delay    = s->delay *blocksize/1000; 
+  int   inject   = s->roomsize;
+
+  int   first    = delay;
+  int   second   = n-first;
+  int   active   = s->active;
+
+  if(!ri->initstate){
+    ri->sC.feedback=feedback;
+    ri->sC.hfdamp=hfdamp;
+    ri->sC.wet=wet;
+    ri->sC.wet1=wet1;
+    ri->sC.wet2=wet2;
+    ri->sC.width=width;
+    ri->sC.delay=delay;
+    ri->sC.inject=inject;
+    ri->sC.active=0; /* soft start */
+    ri->initstate=1;
+    
+    if(ri->rL)reset_one(ri->rL,inject,combL,allL);
+    if(ri->rR)reset_one(ri->rR,inject,combR,allR);
+
+    /* clear cache to empty */
+    memset(cache,0,blocksize*sizeof(*cache));
+  }
+
+  /* if this frame is inactive or muted, let the reverb 'ring' out.
+     if the reverb tail has rung out, nothing to do */
+  if((!ri->sC.active && !active) || muted){
+
+    if(ri->rL && ri->rL->energy){
+
+      process_one_wrapper(ri->rL,transwindow,
+			  ri->sC.feedback,feedback,
+			  ri->sC.hfdamp,hfdamp,
+			  ri->sC.wet,wet,
+			  ri->sC.inject,inject,
+			  0,n,0,0,outL);      
+      
+      for(i=0;i<n;i++)if(outL[i]*outL[i] > 1e-15f)break;
+      if(i==n)
+	ri->rL->energy=0;
+      else
+	energy=1;
+      
+    }
+
+    if(ri->rR && ri->rR->energy){
+      process_one_wrapper(ri->rR,transwindow,
+			  ri->sC.feedback,feedback,
+			  ri->sC.hfdamp,hfdamp,
+			  ri->sC.wet,wet,
+			  ri->sC.inject,inject,
+			  0,n,0,0,outR);  
+
+      for(i=0;i<n;i++)if(outR[i]*outR[i] > 1e-15f)break;
+      if(i==n)
+	ri->rR->energy=0;
+      else
+	energy=1;
+    }
+
+  }else{
+
+    /* we have input and are active or transitioning */
+
+    /* if the previous delay and delay this frame differ, build a
+       smoothed transition using the cache buffer as working space */
+    if(delay != ri->sC.delay){
+      float *ptrC=cache + n - ri->sC.delay;
+      float *ptr =cache + n - delay;
+      
+      int firstC=ri->sC.delay;
+      
+      for(i=0;i<n;i++){
+	if(i==firstC)ptrC=in;
+	if(i==first)ptr=in;
+	cache[i]=transwindow[i]*(*ptr++) + 
+	  (1.f-transwindow[i])*(*ptrC++);
+      }
+      
+      first=n;
+      second=0;
+    }
+
+    /* If we're active now but previous frame was inactive, build a
+       soft-started input into the cache.  Not needed for muted
+       frames, as muted transitions are soft-started already. */
+    if(active && !ri->sC.active){
+      float *ptr = cache + n - first;
+
+      for(i=0;i<n;i++){
+	if(i==first)ptr=in;
+	cache[i]=transwindow[i]* *ptr++;
+      }
+
+      first=n;
+      second=0;
+    }
+
+    /* As above, but active -> inactive */
+    if(!active && ri->sC.active){
+      float *ptr = cache + n - first;
+
+      for(i=0;i<n;i++){
+	if(i==first)ptr=in;
+	cache[i]=transwindow[n-i]* *ptr++;
+      }
+
+      first=n;
+      second=0;
+    }
+
+    /* run the filters */
+    if(ri->rL){
+      ri->rL->energy=1;
+      energy=1;
+      process_one_wrapper(ri->rL,transwindow,
+			  ri->sC.feedback,feedback,
+			  ri->sC.hfdamp,hfdamp,
+			  ri->sC.wet,wet,
+			  ri->sC.inject,inject,
+			  cache,first,in,second,outL);      
+    }
+
+    if(ri->rR){
+      ri->rR->energy=1;
+      energy=1;
+      process_one_wrapper(ri->rR,transwindow,
+			  ri->sC.feedback,feedback,
+			  ri->sC.hfdamp,hfdamp,
+			  ri->sC.wet,wet,
+			  ri->sC.inject,inject,
+			  cache,first,in,second,outR);
+    }
+  }
+
+  /* all or none consistency check */
+  if(ri->rL && ri->rR && energy){
+    if(!ri->rL->energy)
+      memset(outL,0,sizeof(*outL)*blocksize);
+    if(!ri->rR->energy)
+      memset(outR,0,sizeof(*outR)*blocksize);
+  }
+
+  /* stereo butterfly? */
+  if(ri->rL && ri->rR && energy &&
+     (width<1000 || ri->sC.width<1000)){
+
+    /* static butterfly or transitional? */
+    if(width != ri->sC.width){
+      float wetdel1=(wet1-ri->sC.wet1)/n;
+      float wetacc1=ri->sC.wet1;
+      float wetdel2=(wet2-ri->sC.wet2)/n;
+      float wetacc2=ri->sC.wet2;
+
+      for(i=0;i<n;i++){
+	float newL=outL[i]*wetacc1 + outR[i]*wetacc2;
+	float newR=outR[i]*wetacc1 + outL[i]*wetacc2;
+
+	outL[i]=newL;
+	outR[i]=newR;
+	wetacc1+=wetdel1;
+	wetacc2+=wetdel2;
+	
+      }
+      
+    }else{
+      for(i=0;i<n;i++){
+	float newL=outL[i]*wet1 + outR[i]*wet2;
+	float newR=outR[i]*wet1 + outL[i]*wet2;
+
+	outL[i]=newL;
+	outR[i]=newR;
+      }
+    }
+  }
+
+  ri->sC.feedback=feedback;
+  ri->sC.hfdamp=hfdamp;
+  ri->sC.wet=wet;
+  ri->sC.wet1=wet1;
+  ri->sC.wet2=wet2;
+  ri->sC.width=width;
+  ri->sC.delay=delay;
+  ri->sC.inject=inject;
+  ri->sC.active=active;
+
+  return energy;
+}
+
+void reverb_settings_init(reverb_settings *s){
+  memset(s,0,sizeof(*s));
+  s->liveness=500;
+  s->hfdamp=500;
+  s->wet=1000;
+  s->width=1000;
+  s->delay=0;
+  s->roomsize=1000;
+}
+
+/* ri: pointer to array of instances
+   rs: pointer to array of settings 
+
+   return processing status: -) input error
+                             0) pre-stream
+                             1) processing
+                             2) eos 
+
+   array sizes must match number of channels in in/outL/outR */
+
+extern int input_size;
+
+int reverb_process(reverb_instance *ri, reverb_settings **rs,
+		   time_linkage *in, time_linkage *outL, time_linkage *outR){
+  
+  int ch=ri->ch,i;
+  u_int32_t active=0;
+
+  /* verify input consistency */
+  //if(ri->blocksize != in->blocksize) return -1;
+  //if(ri->blocksize != outL->blocksize) return -1;
+  //if(outR && ri->blocksize != outR->blocksize) return -1;
+  if(ch != in->channels) return -1;
+  if(ch != outL->channels) return -1;
+  if(outR && ch != outR->channels) return -1;
+  if(ri->reverbs->rR && !outR) return -1;
+  if(!ri->reverbs->rR && outR) return -1;
+
+  switch(ri->initstate){
+  case 0:
+    
+    if(in->samples==0){
+      /* clear output, return pre stream status */
+      if(outL)time_linkage_clear(outL);
+      if(outR)time_linkage_clear(outR);
+      
+      return 0;
+    }
+    
+    ri->initstate=1; 
+    /* fall through */
+  case 1:
+
+    if(in->samples>0){
+      for(i=0;i<ch;i++){
+	reverb_instance_one *rio=ri->reverbs+i;
+	float *tmp=rio->cache;
+
+	u_int32_t ret=process_one(rio, rs[i], in->data[i], mute_channel_muted(in->active,i),
+				  outL->data[i],(outR?outR->data[i]:0),ri->transwindow,
+				  in->samples,ri->blocksize);
+	
+	if(rs[i]->dry_mix && !mute_channel_muted(in->active,i)){
+	  int j;
+	  float *dataO=outL->data[i];
+	  float *dataI=in->data[i];
+	  
+	  if(ret){
+	    for(j=0;j<in->samples;j++)
+	      dataO[j]+=dataI[j];
+	    
+	    if(outR){
+	      dataO=outR->data[j];
+	      for(j=0;j<in->samples;j++)
+		dataO[j]+=dataI[j];
+	    }
+	  }else{
+	    for(j=0;j<in->samples;j++)
+	      dataO[j]=dataI[j];
+	    
+	    if(outR){
+	      dataO=outR->data[j];
+	      for(j=0;j<in->samples;j++)
+		dataO[j]=dataI[j];
+	    }
+	  }
+	  
+	  active |= (1<<i);
+	  
+	}
+	rio->cache=in->data[i];
+	in->data[i]=tmp;
+	active|=(ret<<i);
+      }
+      if(outL){
+	outL->samples=in->samples;
+	outL->active=active;
+      }
+      if(outR){
+	outR->samples=in->samples;
+	outR->active=active;
+      }
+      if(in->samples<input_size)ri->initstate=2;
+      return 1;
+    }
+    ri->initstate=2;
+    /* fall through */
+  case 2:
+    if(outL)time_linkage_clear(outL);
+    if(outR)time_linkage_clear(outR);    
+    return 2;
+  }
+  return -1;
+}
+
+int reverb_instance_init(reverb_instance *ri, int ch, int stereo){
+  int i;
+  memset(ri,0,sizeof(*ri));
+
+  ri->ch=ch;
+  ri->blocksize=input_size;
+  ri->transwindow=window_get(1,ri->blocksize);
+  ri->reverbs=malloc(ch*sizeof(*ri->reverbs));
+
+  for(i=0;i<ch;i++){
+    reverb_instance_one *rio=ri->reverbs+i;
+    
+    rio->cache=malloc(ri->blocksize*sizeof(*rio->cache));
+    rio->rL=malloc(sizeof(*rio->rL));
+    rio->rR=0;
+    if(stereo) rio->rR=malloc(sizeof(*rio->rR));
+
+  }
+  
+  reverb_instance_reset(ri);
+  return 0;
+}
+
+/* Old postfish hooks; these will be removed next step when
+   libpostfish appears */
+
+extern int input_ch;
+static reverb_instance cs;
+static reverb_instance ms;
+reverb_settings *reverb_channelset; 
+reverb_settings reverb_masterset; 
+
+static reverb_settings **rcs;
+static reverb_settings **rms;
+
+static time_linkage outA;
+static time_linkage outB;
+static time_linkage outC;
+static time_linkage outM;
+
+int p_reverb_load(void){
+  int i;
+
+  reverb_instance_init(&cs,input_ch,1);
+  reverb_instance_init(&ms,OUTPUT_CHANNELS,0);
+
+  reverb_channelset=malloc(input_ch*sizeof(*reverb_channelset));
+  for(i=0;i<input_ch;i++)
+    reverb_settings_init(reverb_channelset+i);
+  reverb_settings_init(&reverb_masterset);
+
+  rcs=malloc(input_ch*sizeof(*rcs));
+  for(i=0;i<input_ch;i++)
+    rcs[i]=reverb_channelset+i;
+  rms=malloc(OUTPUT_CHANNELS*sizeof(*rms));
+  for(i=0;i<input_ch;i++)
+    rms[i]=&reverb_masterset;
+
+  time_linkage_init(&outA,input_ch);
+  time_linkage_init(&outB,input_ch);
+  time_linkage_init(&outC,input_ch);
+  time_linkage_init(&outM,OUTPUT_CHANNELS);
+  
+  reverb_masterset.dry_mix=1;
+
+  return 0;
+}
+
+void p_reverb_reset(void){
+  reverb_instance_reset(&cs);
+  reverb_instance_reset(&ms);
+}
+ 
+time_linkage *p_reverb_read_channel(time_linkage *in,
+				    time_linkage **revA,
+				    time_linkage **revB){
+  
+  time_linkage_copy(&outC,in);
+  reverb_process(&cs,rcs,in,&outA,&outB);
+  *revA=&outA;
+  *revB=&outB;
+  return &outC;
+}
+
+time_linkage *p_reverb_read_master(time_linkage *in){  
+  reverb_process(&ms,rms,in,&outM,0);
+  return &outM;
+}
+

Added: trunk/postfish/freeverb.h
===================================================================
--- trunk/postfish/freeverb.h	2005-01-02 20:21:01 UTC (rev 8578)
+++ trunk/postfish/freeverb.h	2005-01-02 20:23:41 UTC (rev 8579)
@@ -0,0 +1,157 @@
+/*
+ *
+ *  postfish
+ *    
+ *      Copyright (C) 2002-2005 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.
+ *
+ * 
+ */
+
+typedef struct reverb_settings {
+  sig_atomic_t roomsize; /* 0 - 1000 */
+  sig_atomic_t liveness;     /* 0 - 1000 */
+  sig_atomic_t hfdamp;   /* 0 - 1000 */
+  sig_atomic_t delay;    /* 0 - 1000 */
+
+  sig_atomic_t wet;      /* dB * 10  */
+  sig_atomic_t width;    /* 0 - 1000 */
+  sig_atomic_t dry_mix;  /* 0, 1 */
+
+  sig_atomic_t active;   /* 0, 1 */
+  sig_atomic_t visible;  /* 0, 1 */
+} reverb_settings;
+
+typedef struct allpass{
+  float *buffer;
+  float *bufptr;
+  int    size;
+} allpass_state;
+
+typedef struct comb{
+  float	 filterstore;
+  float *buffer;
+  float *injptr;
+  float *extptr;
+  float *extpending;
+  int    size;
+} comb_state;
+
+#define numcombs 8
+#define numallpasses 4
+#define scalehfdamp 0.4f
+#define scaleliveness 0.4f
+#define offsetliveness 0.58f
+#define scaleroom 1111
+#define stereospread 23
+#define fixedgain 0.015f
+
+#define comb0 1116
+#define comb1 1188
+#define comb2 1277
+#define comb3 1356
+#define comb4 1422
+#define comb5 1491
+#define comb6 1557
+#define comb7 1617
+
+#define all0 556
+#define all1 441
+#define all2 341
+#define all3 225
+
+/* These values assume 44.1KHz sample rate
+   they will probably be OK for 48KHz sample rate
+   but would need scaling for 96KHz (or other) sample rates.
+   The values were obtained by listening tests. */
+
+static const int combL[numcombs]={
+  comb0, comb1, comb2, comb3, 
+  comb4, comb5, comb6, comb7 
+};
+
+static const int combR[numcombs]={
+  comb0+stereospread, comb1+stereospread, comb2+stereospread, comb3+stereospread, 
+  comb4+stereospread, comb5+stereospread, comb6+stereospread, comb7+stereospread 
+};
+
+static const int allL[numallpasses]={
+  all0, all1, all2, all3,
+};
+
+static const int allR[numallpasses]={
+  all0+stereospread, all1+stereospread, all2+stereospread, all3+stereospread,
+};
+
+/* enough storage for L or R */
+typedef struct reverb_state {
+  comb_state comb[numcombs];
+  allpass_state allpass[numallpasses];
+
+  float	bufcomb0[comb0+stereospread];
+  float	bufcomb1[comb1+stereospread];
+  float	bufcomb2[comb2+stereospread];
+  float	bufcomb3[comb3+stereospread];
+  float	bufcomb4[comb4+stereospread];
+  float	bufcomb5[comb5+stereospread];
+  float	bufcomb6[comb6+stereospread];
+  float	bufcomb7[comb7+stereospread];
+  
+  float	bufallpass0[all0+stereospread];
+  float	bufallpass1[all1+stereospread];
+  float	bufallpass2[all2+stereospread];
+  float	bufallpass3[all3+stereospread];
+
+  int energy;
+} reverb_state;
+
+typedef struct converted_reverb_settings {
+  float feedback;
+  float hfdamp;
+  int   inject;
+  float wet;  
+  float wet1;
+  float wet2;
+  int width;  
+  int active;
+  int delay;
+} converted_reverb_settings;
+
+typedef struct reverb_instance_one{
+  int initstate;
+  float *cache;
+  reverb_state *rL;
+  reverb_state *rR;
+  converted_reverb_settings sC;
+} reverb_instance_one;
+
+typedef struct reverb_instance{
+  int    initstate;
+  int    ch;
+  float *transwindow;
+  int    blocksize; /* can go away after lib conversion */
+  reverb_instance_one *reverbs;
+} reverb_instance;
+
+extern time_linkage *p_reverb_read_master(time_linkage *in);
+extern time_linkage *p_reverb_read_channel(time_linkage *in,
+					   time_linkage **revA,
+					   time_linkage **revB);
+extern void p_reverb_reset(void);
+extern int p_reverb_load(void);
+
+extern reverb_settings *reverb_channelset; 
+extern reverb_settings reverb_masterset; 



More information about the commits mailing list