suppress.c 6.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/*
 *
 *  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"
#include "feedback.h"
#include <fftw3.h>
#include "subband.h"
#include "bessel.h"
#include "suppress.h"

/* (since this one is kinda unique) The Reverberation Suppressor....
   
   Reverberation in a measurably live environment displays
   log amplitude decay with time (linear decay when plotted on a dB
   scale).
   
   In its simplest form, the suppressor follows actual RMS amplitude
   attacks but chooses a slower-than-actual decay, then expands
   according to the dB distance between the slow and actual decay.
   
   Thus, the suppressor can be used to 'dry out' a very 'wet'
   reverberative track. */
    
extern int input_size;
extern int input_rate;
extern int input_ch;

typedef struct {
  subband_state ss;
  
  iir_filter smooth;
  iir_filter trigger;
  iir_filter release;
  
  iir_state *iirS[suppress_freqs];
  iir_state *iirT[suppress_freqs];
  iir_state *iirR[suppress_freqs];

} suppress_state;

61 62 63
suppress_settings suppress_channel_set;
static suppress_state channel_state;
static subband_window sw;
64 65 66 67

void suppress_reset(){
  int i,j;
  
68
  subband_reset(&channel_state.ss);
69 70 71
  
  for(i=0;i<suppress_freqs;i++){
    for(j=0;j<input_ch;j++){
72 73 74
      memset(&channel_state.iirS[i][j],0,sizeof(iir_state));
      memset(&channel_state.iirT[i][j],0,sizeof(iir_state));
      memset(&channel_state.iirR[i][j],0,sizeof(iir_state));
75 76 77 78
    }
  }
}

79 80
static void filter_set(subband_state *ss,
		       float msec,
81 82 83 84 85 86 87 88
		       iir_filter *filter,
		       int attackp,
		       int order){
  float alpha;
  float corner_freq= 500./msec;
  
  /* make sure the chosen frequency doesn't require a lookahead
     greater than what's available */
89
  if(impulse_freq4(input_size*2-ss->qblocksize*3)*1.01>corner_freq && 
90
     attackp)
91
    corner_freq=impulse_freq4(input_size*2-ss->qblocksize*3);
92 93 94 95 96 97 98 99 100 101 102
  
  alpha=corner_freq/input_rate;
  filter->g=mkbessel(alpha,order,filter->c);
  filter->alpha=alpha;
  filter->Hz=alpha*input_rate;
  filter->ms=msec;
}

int suppress_load(void){
  int i;
  int qblocksize=input_size/16;
103 104 105 106
  memset(&channel_state,0,sizeof(channel_state));

  suppress_channel_set.active=calloc(input_ch,sizeof(*suppress_channel_set.active));

107
  subband_load(&channel_state.ss,suppress_freqs,qblocksize,input_ch);
108
  subband_load_freqs(&channel_state.ss,&sw,suppress_freq_list,suppress_freqs);
109 110
   
  for(i=0;i<suppress_freqs;i++){
111 112 113
    channel_state.iirS[i]=calloc(input_ch,sizeof(iir_state));
    channel_state.iirT[i]=calloc(input_ch,sizeof(iir_state));
    channel_state.iirR[i]=calloc(input_ch,sizeof(iir_state));
114 115 116 117
  }
  return 0;
}

118
static void suppress_work_helper(void *vs, suppress_settings *sset){
119 120
  suppress_state *sss=(suppress_state *)vs;
  subband_state *ss=&sss->ss;
121
  int i,j,k,l;
122 123 124
  float smoothms=sset->smooth*.1;
  float triggerms=sset->trigger*.1;
  float releasems=sset->release*.1;
125 126 127
  iir_filter *trigger=&sss->trigger;
  iir_filter *smooth=&sss->smooth;
  iir_filter *release=&sss->release;
128 129
  int ahead;

130 131 132
  if(smoothms!=smooth->ms)filter_set(ss,smoothms,smooth,1,4);
  if(triggerms!=trigger->ms)filter_set(ss,triggerms,trigger,0,1);
  if(releasems!=release->ms)filter_set(ss,releasems,release,0,1);
133 134 135 136

  ahead=impulse_ahead4(smooth->alpha);
  
  for(i=0;i<suppress_freqs;i++){
137 138 139
    int firstlink=0;
    float fast[input_size];
    float slow[input_size];
140
    float multiplier = 1.-1000./sset->ratio[i];
141 142 143 144 145 146 147
    
    for(j=0;j<input_ch;j++){
      int active=(ss->effect_active1[j] || 
		  ss->effect_active0[j] || 
		  ss->effect_activeC[j]);
      
      if(active){
148
	if(sset->linkp){
149 150
	  if(!firstlink){
	    firstlink++;
151 152 153
	    memset(fast,0,sizeof(fast));
	    float scale=1./input_ch;
	    for(l=0;l<input_ch;l++){
154
	      float *x=sss->ss.lap[i][l]+ahead;
155 156 157 158 159
	      for(k=0;k<input_size;k++)
		fast[k]+=x[k]*x[k];
	    }
	    for(k=0;k<input_size;k++)
	      fast[k]*=scale;
160
	    
161 162 163
	  }
	  
	}else{
164
	  float *x=sss->ss.lap[i][j]+ahead;
165 166 167 168
	  for(k=0;k<input_size;k++)
	    fast[k]=x[k]*x[k];
	}
	
169
	
170
	if(sset->linkp==0 || firstlink==1){
171 172 173
	  
	  compute_iir_symmetric4(fast, input_size, &sss->iirS[i][j],
				 smooth);
174 175 176
	  
	  //_analysis("smooth",i,fast,input_size,1,offset);
	  
177 178
	  compute_iir_freefall1(fast, input_size, &sss->iirT[i][j],
				trigger);
179
	  memcpy(slow,fast,sizeof(slow));
180 181
	  compute_iir_freefall1(slow, input_size, &sss->iirR[i][j],
				release);
182 183 184 185 186 187
	  
	  //_analysis("fast",i,fast,input_size,1,offset);
	  //_analysis("slow",i,slow,input_size,1,offset);
	  for(k=0;k<input_size;k++)
	    fast[k]=fromdB_a((todB_a(slow+k)-todB_a(fast+k))*.5*multiplier);
	  //_analysis("adj",i,fast,input_size,1,offset);
188

189
	  if(sset->linkp && firstlink==1){
190 191 192 193 194 195 196 197 198 199 200

	    for(l=0;l<input_ch;l++){
	      if(l!=j){
		memcpy(&sss->iirS[i][l],&sss->iirS[i][j],sizeof(iir_state));
		memcpy(&sss->iirT[i][l],&sss->iirT[i][j],sizeof(iir_state));
		memcpy(&sss->iirR[i][l],&sss->iirR[i][j],sizeof(iir_state));
	      }
	    }
	  }

	  firstlink++;
201
	}
202 203
	
	
204
	{
205
	  float *x=sss->ss.lap[i][j];
206 207 208 209
	  for(k=0;k<input_size;k++)
	    if(fast[k]<1.)
	      x[k]*=fast[k];
	}
210 211 212 213 214
      }else{
	/* reset filters to sane inactive default */
	memset(&sss->iirS[i][j],0,sizeof(iir_state));
	memset(&sss->iirT[i][j],0,sizeof(iir_state));
	memset(&sss->iirR[i][j],0,sizeof(iir_state));
215 216 217 218 219
      }
    }
  }
}

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
static void suppress_work_channel(void *vs){
  suppress_work_helper(vs,&suppress_channel_set);
}

time_linkage *suppress_read_channel(time_linkage *in){
  int visible[input_ch];
  int active [input_ch];
  subband_window *w[input_ch];
  int i;
  
  for(i=0;i<input_ch;i++){
    visible[i]=0;
    active[i]=suppress_channel_set.active[i];
    w[i]=&sw;
  }
  
  return subband_read(in, &channel_state.ss, w, visible, active, 
		      suppress_work_channel, &channel_state);
}