3
* experimental channel effects processing
4
* provided under GNU General Public License
5
* contents : chorus ( controller 93 ) effect processing
6
* Nicolas Witczak juillet 1998
7
* witczak@geocities.com
30
/**************************************************************************/
31
/** chorus_effect structure definition
36
* phi = d + sw * triangle( 2Pi/T * t )
38
* sl(n) = xl(n) + A * x( n - phi(t) )
40
* sr(n) = xr(n) + A * x( n - phi(t - T / 4 ) )
45
/* >> choice of the day >> */
47
/** G_BIT and G : denominator size */
49
#define G ((int32)( 1 << G_BITS ))
51
/** average delays in ms */
54
/** max die time in ms */
55
#define DIE_TIME ( D * 2 )
57
/** sweep ratio in percent of D */
60
/** max chorus amplitude */
64
/** time param normalized to sampling rate*/
65
static uint32 dieTime = 0 ;
67
/** approximate chorus frequency Hz */
70
/** d_min , d_max : chorus depth and average delay relative to sampling rate and G_BITS fractionnal part for
71
* linear interpolation
73
static uint32 d_min = 0 ;
74
static uint32 d_max = 0 ;
78
/*---------------------------------------------------*/
79
/* Effect base implementation */
80
void *m_pfnActionMono;
81
void *m_pfnActionStereo ;
82
void *m_pfnCtrlChange ;
83
void *m_pfnCtrlReset ;
87
/*---------------------------------------------------*/
88
/* additionnal parameters */
90
/** m_uiNullCount : number of last null samples or 0
92
uint32 m_uiNullCount ;
94
/** l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
95
cirbuff leftX , rightX ;
97
/** gain param , if != 0 this effect is active*/
100
/** current state for triangle phase ramp relative to fractionnal part G_BITS */
101
uint32 d_left , d_right ;
103
/** incremental step for chorus phase eval , calculated according to FREQU and depth */
104
int32 incr_left , incr_right ;
108
/**************************************************************************/
109
/** reverb_effect function overriding
111
static void ActionMono( chorus_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
116
pThis->m_uiNullCount = 0 ;
118
pThis->m_uiNullCount += count ;
119
if( pThis->m_uiNullCount < dieTime )
121
int32* pCur = pMonoBuffer;
122
int32* pEnd = pMonoBuffer + count ;
123
int32 x , v1 , v2 , delta , tmp ;
125
for( ; pCur != pEnd ; ++ pCur )
128
v1 = (pThis->leftX.m_pCur)[ - ( pThis->d_left >> FRACTION_BITS ) ] ;
129
v2 = (pThis->leftX.m_pCur)[ 1 - ( pThis->d_left >> FRACTION_BITS ) ] ;
130
tmp = ( FRACTION_MASK - ( pThis->d_left & FRACTION_MASK ) ) ;
131
delta = ( (v2-v1) * tmp ) / FRACTION ;
133
*pCur += pThis->a * ( v1 + delta ) ;
134
pushval_cirbuff( &(pThis->leftX) , x ) ;
135
if( pThis->d_left > d_max )
137
pThis->incr_left = -abs( pThis->incr_left ) ;
138
pThis->d_left = d_max ;
140
else if( pThis->d_left < d_min )
142
pThis->incr_left = +abs( pThis->incr_left ) ;
143
pThis->d_left = d_min ;
146
pThis->d_left += pThis->incr_left ;
152
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
153
pThis->d_left = ( d_max + d_min ) / 2 ;
157
static void ActionStereo( chorus_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
162
pThis->m_uiNullCount = 0 ;
164
pThis->m_uiNullCount += count ;
165
if( pThis->m_uiNullCount < dieTime )
167
int32* pCur = pStereoBuffer;
168
int32* pEnd = pStereoBuffer + 2 * count ;
169
int32 x , v1 , v2 , delta , tmp ;
171
for( ; pCur != pEnd ; ++ pCur )
174
v1 = (pThis->leftX.m_pCur)[ - ( pThis->d_left >> FRACTION_BITS ) ] ;
175
v2 = (pThis->leftX.m_pCur)[ 1 - ( pThis->d_left >> FRACTION_BITS ) ] ;
176
tmp = ( FRACTION_MASK - ( pThis->d_left & FRACTION_MASK ) ) ;
177
delta = ( (v2-v1) * tmp ) / FRACTION ;
179
*pCur += pThis->a * ( v1 + delta ) ;
180
pushval_cirbuff( &(pThis->leftX) , x ) ;
181
if( pThis->d_left > d_max )
183
pThis->incr_left = -abs( pThis->incr_left ) ;
184
pThis->d_left = d_max ;
186
else if( pThis->d_left < d_min )
188
pThis->incr_left = +abs( pThis->incr_left ) ;
189
pThis->d_left = d_min ;
192
pThis->d_left += pThis->incr_left ;
197
v1 = (pThis->rightX.m_pCur)[ - ( pThis->d_right >> FRACTION_BITS ) ] / G ;
198
v2 = (pThis->rightX.m_pCur)[ 1 - ( pThis->d_right >> FRACTION_BITS ) ] / G ;
199
tmp = ( FRACTION_MASK - ( pThis->d_right & FRACTION_MASK ) ) ;
200
delta = ( (v2-v1) * tmp ) / FRACTION ;
202
*pCur += pThis->a * ( v1 + delta ) ;
203
pushval_cirbuff( &(pThis->rightX) , x ) ;
204
if( pThis->d_right > d_max )
206
pThis->incr_right = -abs( pThis->incr_right ) ;
207
pThis->d_right = d_max ;
209
else if( pThis->d_right < d_min )
211
pThis->incr_right = +abs( pThis->incr_right ) ;
212
pThis->d_right = d_min ;
215
pThis->d_right += pThis->incr_right ;
222
shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
223
shift_cirbuff( &( pThis->rightX ) , pThis->m_uiNullCount ) ;
224
pThis->d_left = ( d_max + d_min ) / 2 ;
225
pThis->d_right = d_min ;
229
static void CtrlReset( chorus_effect* pThis )
231
pThis->m_uiNullCount = 0 ;
232
redim_cirbuff( &( pThis->leftX ) , 0 ) ;
233
redim_cirbuff( &( pThis->rightX ) , 0 ) ;
235
d_max = (uint32)( ( ( ( D * ( 1.0 + ( SWEEP / 2 ) ) * play_mode->rate ) / 1000 ) - 1 ) * FRACTION );
236
d_min = (uint32)( ( ( ( D * ( 1.0 - ( SWEEP / 2 ) ) * play_mode->rate ) / 1000 ) - 1 ) * FRACTION );
238
pThis->incr_left = (int32)( ( 2 * ( d_max - d_min ) * FREQU ) / play_mode->rate );
239
pThis->incr_right = pThis->incr_left ;
240
pThis->d_left = ( d_max + d_min ) / 2 ;
241
pThis->d_right = d_min ;
242
dieTime = ( DIE_TIME * play_mode->rate ) / 1000 ;
246
static void CtrlChange( chorus_effect* pThis , MidiEvent* pCurrentEvent )
248
int amount = pCurrentEvent->a;
249
if (amount < global_chorus) amount = global_chorus;
251
if( pCurrentEvent->b == ME_CELESTE ||
252
(pCurrentEvent->b == ME_CHORUSDEPTH && XG_effect_chorus_is_celeste_flag) )
253
if( pCurrentEvent->b == ME_CHORUSDEPTH && !XG_effect_chorus_is_celeste_flag &&
254
!XG_effect_chorus_is_phaser_flag)
258
redim_cirbuff( &( pThis->leftX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
259
if( ! ( play_mode->encoding & PE_MONO ) )
261
redim_cirbuff( &( pThis->rightX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
263
pThis->a = (int32)( G * ( A_MIN + ( A_MAX - A_MIN ) * ( amount - 1 ) / 126.0 ) );
270
static void Name( char* pszBuff )
272
strcpy( pszBuff , "chorus" );
275
static void Destruct( chorus_effect* pThis )
277
delete_cirbuff( &( pThis->leftX ) ) ;
278
delete_cirbuff( &( pThis->rightX ) ) ;
280
memset( pThis , 0 , sizeof( chorus_effect ) ) ;
285
/**************************************************************************/
286
/** chorus_effect construction function prototype
290
chorus_effect* pReturn = 0 ;
291
pReturn = (chorus_effect *) malloc( sizeof( chorus_effect ) ) ;
292
memset( pReturn , 0 , sizeof( chorus_effect ) ) ;
294
pReturn->m_pfnActionMono = (void*)&ActionMono ;
295
pReturn->m_pfnActionStereo = (void*)&ActionStereo ;
296
pReturn->m_pfnCtrlChange = (void*)&CtrlChange ;
297
pReturn->m_pfnCtrlReset = (void*)&CtrlReset ;
298
pReturn->m_pfnName = (void*)&Name ;
299
pReturn->m_pfnDestruct = (void*)&Destruct ;
301
create_cirbuff( &( pReturn->leftX ) , 0 ) ;
302
create_cirbuff( &( pReturn->rightX ) , 0 ) ;
304
CtrlReset( pReturn ) ;
305
return ( Effect* )pReturn ;
313
#endif /* CHANNEL_EFFECT */