3
* experimental channel effects processing
4
* provided under GNU General Public License
5
* contents : reverb ( controller 91 ) effect processing
6
* Nicolas Witczak juillet 1998
7
* witczak@geocities.com
32
/**************************************************************************/
33
/** reverb_effect structure definition
39
* yel(n) = G1 * xl( n - d1 ) + G2 * xr( n - d2 ) + G3 * xl( n - d3 )
42
* yer(n) = G1 * xr( n - d1 ) + G2 * xl( n - d2 ) + G3 * xr( n - d3 )
44
* ambient reverb with embedded filter
46
* yal = xl( n ) + G4 * xl( n - d4 ) + G5 * xl( n - d5 ) + G6 * xl( n - d6 ) + G7 * ( yal( n - d7 ) - m )
49
* yar = xr( n ) + G4 * xl( n - d4 ) + G6 * xr( n - d6 ) + G7 * ( yal( n - d7 ) - m )
51
* m : average : used for hight pass filter
54
* s(n) = x(n) + Ge * ye(n) + Ga * ya(n)
57
/* >> choice of the day >> */
59
/** G_BIT and G : denominator size */
61
#define G ((int32)( 1 << G_BITS ))
63
/** max die reverb time in ms */
88
/** gain variation between left and right channels in stereo mode */
91
/** relative min gain for echos */
94
/** for early and ambient echo gain tuning */
98
/** averaging hight filter cutoff frequency in Hz */
99
#define FILTER_FREQU 300
101
/** averaging hight filter impulsionnal response size in samples*/
102
static int delay_flt = 0 ;
104
/** time param normalized to sampling rate*/
105
static int32 d1 , d2 , d3 , d4 , d5 , d6 , d7;
106
static uint32 dieTime;
108
/** gain param normalized to G */
109
static int32 g1 = (int32)(G * G1);
110
static int32 g2 = (int32)(G * G2);
111
static int32 g3 = (int32)(G * G3);
112
static int32 g4 = (int32)(G * G4);
113
static int32 g5 = (int32)(G * G5);
114
static int32 g6 = (int32)(G * G6);
115
static int32 g7 = (int32)(G * G7);
122
/*---------------------------------------------------*/
123
/* Effect base implementation */
124
void *m_pfnActionMono ;
125
void *m_pfnActionStereo ;
126
void *m_pfnCtrlChange ;
127
void *m_pfnCtrlReset ;
129
void *m_pfnDestruct ;
131
/*---------------------------------------------------*/
132
/* additionnal parameters */
134
/** m_uiNullCount : number of last null samples or 0
136
uint32 m_uiNullCount ;
138
/** l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
139
cirbuff leftX , leftYa , rightX , rightYa ;
141
/** gain param normalized to G : if ge == 0 inactivated */
144
/** average value of last 128 x samples */
145
int32 m_left , m_right ;
150
/**************************************************************************/
151
/** reverb_effect function overriding
153
static void ActionMono( reverb_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
158
pThis->m_uiNullCount = 0 ;
160
pThis->m_uiNullCount += count ;
161
if( pThis->m_uiNullCount < dieTime )
163
int32* pCur = pMonoBuffer;
164
int32* pEnd = pMonoBuffer + count ;
166
for( ; pCur != pEnd ; ++ pCur )
170
ye = ( ( (pThis->leftX.m_pCur)[d1] * g1 )
171
+ ( (pThis->leftX.m_pCur)[d2] * g2 )
172
+ ( (pThis->leftX.m_pCur)[d3] * g3 ) ) / G ;
174
ya = ( ( (pThis->leftX.m_pCur)[d4] * g4 )
175
+ ( (pThis->leftX.m_pCur)[d5] * g5 )
176
+ ( (pThis->leftX.m_pCur)[d6] * g6 )
177
+ ( (pThis->leftYa.m_pCur)[d7] * g7 )
178
- ( pThis->m_left * gm )
181
*pCur = x * G + ( ye * pThis->ge ) + ( ya * pThis->ga ) ;
183
pThis->m_left += (pThis->leftYa.m_pCur)[ d7 ] ;
184
pThis->m_left -= (pThis->leftYa.m_pCur)[ d7 - delay_flt ] ;
185
pushval_cirbuff( &(pThis->leftX) , x ) ;
186
pushval_cirbuff( &(pThis->leftYa) , ya ) ;
192
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
193
shift_cirbuff( &( pThis->leftYa ) , pThis->m_uiNullCount ) ;
199
static void ActionStereo( reverb_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
201
/* int32 test = G ; */
205
pThis->m_uiNullCount = 0 ;
207
pThis->m_uiNullCount += count ;
208
if( pThis->m_uiNullCount < dieTime )
210
int32* pCur = pStereoBuffer;
211
int32* pEnd = pStereoBuffer + 2 * count ;
214
for( ; pCur != pEnd ; ++ pCur )
217
ye = ( ( (pThis->leftX.m_pCur)[d1] * g1 )
218
+ ( (pThis->rightX.m_pCur)[d2] * g2 )
219
+ ( (pThis->leftX.m_pCur)[d3] * g3 ) ) / G ;
222
( (pThis->leftX.m_pCur)[d4] * g4 )
223
+ ( (pThis->leftX.m_pCur)[d5] * g5 )
224
+ ( (pThis->leftX.m_pCur)[d6] * g6 )
225
+ ( (pThis->leftYa.m_pCur)[d7] * g7 )
226
- ( pThis->m_left * gm )
229
*pCur = x * G + ( ye * pThis->ge ) + ( ya * pThis->ga ) ;
231
pThis->m_left += (pThis->leftYa.m_pCur)[ d7 ] ;
232
pThis->m_left -= (pThis->leftYa.m_pCur)[ d7 - delay_flt ] ;
233
pushval_cirbuff( &(pThis->leftX) , x ) ;
234
pushval_cirbuff( &(pThis->leftYa) , ya ) ;
239
ye = ( ( (pThis->rightX.m_pCur)[d1] * g1 )
240
+ ( (pThis->leftX.m_pCur)[d2] * g2 )
241
+ ( (pThis->rightX.m_pCur)[d3] * g3 ) ) / G ;
244
( (pThis->rightX.m_pCur)[d4] * g4 )
245
+ ( (pThis->rightX.m_pCur)[d5] * g5 )
246
+ ( (pThis->rightX.m_pCur)[d6] * g6 )
247
+ ( (pThis->rightYa.m_pCur)[d7] * g7 )
248
- ( pThis->m_right * gm )
251
*pCur = x * G + ( ye * pThis->ge ) + ( ya * pThis->ga ) ;
253
pThis->m_right += (pThis->rightYa.m_pCur)[ d7 ] ;
254
pThis->m_right -= (pThis->rightYa.m_pCur)[ d7 - delay_flt ] ;
255
pushval_cirbuff( &(pThis->rightX) , x ) ;
256
pushval_cirbuff( &(pThis->rightYa) , ya ) ;
263
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
264
shift_cirbuff( &( pThis->leftYa ) , pThis->m_uiNullCount ) ;
265
shift_cirbuff( &( pThis->rightX ) , pThis->m_uiNullCount ) ;
266
shift_cirbuff( &( pThis->rightYa ) , pThis->m_uiNullCount ) ;
272
static void CtrlReset( reverb_effect* pThis )
274
pThis->m_uiNullCount = 0 ;
275
redim_cirbuff( &( pThis->leftX ) , 0 ) ;
276
redim_cirbuff( &( pThis->leftYa ) , 0 ) ;
277
redim_cirbuff( &( pThis->rightX ) , 0 ) ;
278
redim_cirbuff( &( pThis->rightYa ) , 0 ) ;
280
d1 = 1 - ( ( D1 * play_mode->rate ) / 1000 ) ;
281
d2 = 1 - ( ( D2 * play_mode->rate ) / 1000 ) ;
282
d3 = 1 - ( ( D3 * play_mode->rate ) / 1000 ) ;
283
d4 = 1 - ( ( D4 * play_mode->rate ) / 1000 ) ;
284
d5 = 1 - ( ( D5 * play_mode->rate ) / 1000 ) ;
285
d6 = 1 - ( ( D6 * play_mode->rate ) / 1000 ) ;
286
d7 = 1 - ( ( D7 * play_mode->rate ) / 1000 ) ;
287
dieTime = ( DIE_TIME * play_mode->rate ) / 1000 ;
289
delay_flt = play_mode->rate / FILTER_FREQU ;
290
gm = g7 / delay_flt ;
299
static void CtrlChange( reverb_effect* pThis , MidiEvent* pCurrentEvent )
301
int amount = pCurrentEvent->a;
302
if (amount < global_reverb) amount = global_reverb;
304
if( pCurrentEvent->b == ME_REVERBERATION )
308
if ( 1-d6 < 0 ) fprintf(stderr,"Check reverb_e.c!\n");
309
redim_cirbuff( &( pThis->leftX ) , (uint32)(1 - d6) ) ;
310
if ( 1+delay_flt-d6 < 0 ) fprintf(stderr,"Check reverb_e.c!\n");
311
redim_cirbuff( &( pThis->leftYa ) , (uint32)(1 + delay_flt - d6) ) ;
312
if( ! ( play_mode->encoding & PE_MONO ) )
314
if ( 1-d6 < 0 ) fprintf(stderr,"Check reverb_e.c!\n");
315
redim_cirbuff( &( pThis->rightX ) , (uint32)(1 - d6) ) ;
316
if ( 1+delay_flt-d6 < 0 ) fprintf(stderr,"Check reverb_e.c!\n");
317
redim_cirbuff( &( pThis->rightYa) , (uint32)(1 + delay_flt - d6) ) ;
320
pThis->ge = (int32)( G * ( ( GE_MAX * G_MIN ) + ( GE_MAX * ( 1.0 - G_MIN ) / 126.0 ) * ( amount - 1 ) ) );
321
pThis->ga = (int32)( G * ( ( GA_MAX * G_MIN ) + ( GA_MAX * ( 1.0 - G_MIN ) / 126.0 ) * ( amount - 1 ) ) );
329
static void Name( char* pszBuff )
331
strcpy( pszBuff , "reverb" );
334
static void Destruct( reverb_effect* pThis )
336
delete_cirbuff( &( pThis->leftX ) ) ;
337
delete_cirbuff( &( pThis->leftYa ) ) ;
338
delete_cirbuff( &( pThis->rightX ) ) ;
339
delete_cirbuff( &( pThis->rightYa ) ) ;
341
memset( pThis , 0 , sizeof( reverb_effect ) ) ;
346
/**************************************************************************/
347
/** reverb_effect construction function prototype
351
reverb_effect* pReturn = 0 ;
352
pReturn =(reverb_effect*) malloc( sizeof( reverb_effect ) ) ;
353
memset( pReturn , 0 , sizeof( reverb_effect ) ) ;
355
pReturn->m_pfnActionMono = (void*)&ActionMono ;
356
pReturn->m_pfnActionStereo = (void*)&ActionStereo ;
357
pReturn->m_pfnCtrlChange = (void*)&CtrlChange ;
358
pReturn->m_pfnCtrlReset = (void*)&CtrlReset ;
359
pReturn->m_pfnName = (void*)&Name ;
360
pReturn->m_pfnDestruct = (void*)&Destruct ;
362
create_cirbuff( &( pReturn->leftX ) , 0 ) ;
363
create_cirbuff( &( pReturn->leftYa ) , 0 ) ;
364
create_cirbuff( &( pReturn->rightX ) , 0 ) ;
365
create_cirbuff( &( pReturn->rightYa ) , 0 ) ;
367
CtrlReset( pReturn ) ;
368
return ( Effect* )pReturn ;
374
#endif /* CHANNEL_EFFECT */