3
* experimental channel effects processing
4
* based on timidity (Unix ) from Tuukka Toivonen tt@cgs.fi
5
* and provided under GNU General Public License
6
* contents : phaser ( controller 95 ) effect processing
7
* Nicolas Witczak juillet 1998
8
* witczak@geocities.com
31
/**************************************************************************/
32
/** phaser_effect structure definition
37
* phi = d + sw * triangle( 2Pi/T * t )
39
* y(n) = - GP * x(n) + x( n - phi ) + GP * y( n - d ) (phase filter)
41
* s = gx * x + gy * y(n)
45
/* >> choice of the day >> */
47
/** G_BIT and G : denominator size and fractionnal time part */
49
#define G ((int32)( 1 << G_BITS ))
51
/** average delays in ms */
54
/** phaser loopback gain*/
57
/** relative min gain for phased signal */
60
/** max die time in ms */
61
#define DIE_TIME ( 1000 / FREQU )
63
/** approximate phaser frequency Hz */
66
/** sweep ratio in percent of D */
67
#define SWEEP ( D / 1.01 )
69
/** time param normalized to sampling rate*/
70
static uint32 dieTime = 0 ;
72
/** phaser loopback gain normalized to G */
73
static int32 gp = ( (int32)( GP * G) ) ;
75
/** d_min , d_max : phaser depth and average delay relative to sampling rate and G_BITS fractionnal part for
76
* linear interpolation
78
static uint32 d_min = 0 ;
79
static uint32 d_max = 0 ;
83
/*---------------------------------------------------*/
84
/* Effect base implementation */
85
void *m_pfnActionMono;
86
void *m_pfnActionStereo ;
87
void *m_pfnCtrlChange ;
88
void *m_pfnCtrlReset ;
92
/*---------------------------------------------------*/
93
/* additionnal parameters */
95
/** m_uiNullCount : number of last null samples or 0
97
uint32 m_uiNullCount ;
99
/** l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
100
cirbuff leftX , rightX , leftY , rightY ;
102
/** current state for triangle phase ramp relative to fractionnal part G_BITS */
105
/** incremental step for phaser phase eval , calculated according to FREQU and depth */
108
/** dry and phased gain normalized to G */
113
/**************************************************************************/
114
/** reverb_effect function overriding
116
static void ActionMono( phaser_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
121
pThis->m_uiNullCount = 0 ;
123
pThis->m_uiNullCount += count ;
124
if( pThis->m_uiNullCount < dieTime )
126
int32* pCur = pMonoBuffer;
127
int32* pEnd = pMonoBuffer + count ;
128
int32 x , y , xd , yd , v1 , v2 , tmp ;
129
for( ; pCur != pEnd ; ++ pCur )
133
v1 = (pThis->leftX.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
134
v2 = (pThis->leftX.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
135
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
136
xd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ;
138
v1 = (pThis->leftY.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
139
v2 = (pThis->leftY.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
140
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
141
yd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ; ;
143
y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
145
*pCur = ( G * x ) + ( pThis->gy * y ) ;
146
pushval_cirbuff( &(pThis->leftX) , x ) ;
147
pushval_cirbuff( &(pThis->leftY) , y ) ;
149
if( pThis->d > d_max )
151
pThis->incr = -abs( pThis->incr ) ;
154
else if( pThis->d < d_min )
156
pThis->incr = +abs( pThis->incr ) ;
160
pThis->d += pThis->incr ;
166
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
167
shift_cirbuff( &( pThis->leftY ) , pThis->m_uiNullCount ) ;
172
static void ActionStereo( phaser_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
177
pThis->m_uiNullCount = 0 ;
179
pThis->m_uiNullCount += count ;
180
if( pThis->m_uiNullCount < dieTime )
182
int32* pCur = pStereoBuffer;
183
int32* pEnd = pStereoBuffer + 2 * count ;
184
int32 x , y , xd , yd , v1 , v2 , tmp ;
185
for( ; pCur != pEnd ; ++ pCur )
189
v1 = (pThis->leftX.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
190
v2 = (pThis->leftX.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
191
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
192
xd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ;
194
v1 = (pThis->leftY.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
195
v2 = (pThis->leftY.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
196
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
197
yd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ;
199
y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
201
*pCur = ( G * x ) + ( pThis->gy * y ) ;
202
pushval_cirbuff( &(pThis->leftX) , x ) ;
203
pushval_cirbuff( &(pThis->leftY) , y ) ;
209
v1 = (pThis->rightX.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
210
v2 = (pThis->rightX.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
211
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
212
xd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ;
214
v1 = (pThis->rightY.m_pCur)[ - ( pThis->d >> FRACTION_BITS ) ] ;
215
v2 = (pThis->rightY.m_pCur)[ 1 - ( pThis->d >> FRACTION_BITS ) ] ;
216
tmp = ( FRACTION_MASK - ( pThis->d & FRACTION_MASK ) ) ;
217
yd = v1 + ( ( (v2-v1) * tmp ) / FRACTION ) ;
219
y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
221
*pCur = ( G * x ) + ( pThis->gy * y ) ;
222
pushval_cirbuff( &(pThis->rightX) , x ) ;
223
pushval_cirbuff( &(pThis->rightY) , y ) ;
225
if( pThis->d > d_max )
227
pThis->incr = -abs( pThis->incr ) ;
230
else if( pThis->d < d_min )
232
pThis->incr = +abs( pThis->incr ) ;
236
pThis->d += pThis->incr ;
242
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
243
shift_cirbuff( &( pThis->leftY ) , pThis->m_uiNullCount ) ;
244
shift_cirbuff( &( pThis->rightX ) , pThis->m_uiNullCount ) ;
245
shift_cirbuff( &( pThis->rightY ) , pThis->m_uiNullCount ) ;
250
static void CtrlReset( phaser_effect* pThis )
252
pThis->m_uiNullCount = 0 ;
253
redim_cirbuff( &( pThis->leftX ) , 0 ) ;
254
redim_cirbuff( &( pThis->rightX ) , 0 ) ;
258
d_max = (uint32)( ( ( ( D * ( 1.0 + ( SWEEP / 2 ) ) * play_mode->rate ) / 1000 ) - 1 ) * FRACTION );
259
d_min = (uint32)( ( ( ( D * ( 1.0 - ( SWEEP / 2 ) ) * play_mode->rate ) / 1000 ) - 1 ) * FRACTION );
261
pThis->incr = (int32)( ( 2 * ( d_max - d_min ) * FREQU ) / play_mode->rate );
263
dieTime = (uint32)( ( DIE_TIME * play_mode->rate ) / 1000 );
266
static void CtrlChange( phaser_effect* pThis , MidiEvent* pCurrentEvent )
268
if( pCurrentEvent->b == ME_PHASER ||
269
(pCurrentEvent->b == ME_CHORUSDEPTH && XG_effect_chorus_is_phaser_flag) )
271
if( pCurrentEvent->a != 0 )
273
redim_cirbuff( &( pThis->leftX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
274
redim_cirbuff( &( pThis->leftY ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
275
if( ! ( play_mode->encoding & PE_MONO ) )
277
redim_cirbuff( &( pThis->rightX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
278
redim_cirbuff( &( pThis->rightY ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
280
pThis->gy = (int32)( G * ( G_MIN + ( ( 1.0 - G_MIN ) / 126.0 ) * ( pCurrentEvent->a - 1 ) ) );
287
static void Name( char* pszBuff )
289
strcpy( pszBuff , "phaser" );
292
static void Destruct( phaser_effect* pThis )
294
delete_cirbuff( &( pThis->leftX ) ) ;
295
delete_cirbuff( &( pThis->rightX ) ) ;
296
delete_cirbuff( &( pThis->leftY ) ) ;
297
delete_cirbuff( &( pThis->rightY ) ) ;
299
memset( pThis , 0 , sizeof( phaser_effect ) ) ;
304
/**************************************************************************/
305
/** phaser_effect construction function prototype
309
phaser_effect* pReturn = 0 ;
310
pReturn = ( phaser_effect* )malloc( sizeof( phaser_effect) ) ;
311
memset( pReturn , 0 , sizeof( phaser_effect ) ) ;
313
pReturn->m_pfnActionMono = (void*)&ActionMono ;
314
pReturn->m_pfnActionStereo = (void*)&ActionStereo ;
315
pReturn->m_pfnCtrlChange = (void*)&CtrlChange ;
316
pReturn->m_pfnCtrlReset = (void*)&CtrlReset ;
317
pReturn->m_pfnName = (void*)&Name ;
318
pReturn->m_pfnDestruct = (void*)&Destruct ;
320
create_cirbuff( &( pReturn->leftX ) , 0 ) ;
321
create_cirbuff( &( pReturn->rightX ) , 0 ) ;
322
create_cirbuff( &( pReturn->leftY ) , 0 ) ;
323
create_cirbuff( &( pReturn->rightY ) , 0 ) ;
325
CtrlReset( pReturn ) ;
326
return ( Effect* )pReturn ;
334
#endif /* CHANNEL_EFFECT */