3
* experimental channel effects processing
4
* provided under GNU General Public License
5
* contents : channel pre-mix , effect struct definition
6
* Nicolas Witczak juillet 1998
7
* witczak@geocities.com
33
int XG_effect_chorus_is_celeste_flag = 0;
34
int XG_effect_chorus_is_flanger_flag = 0;
35
int XG_effect_chorus_is_phaser_flag = 0;
37
/**************************************************************************/
38
/** null terminated list of effects types
39
extern Effect* ChorusCtor( int ) ;
40
extern Effect* PhaserCtor( int ) ;
41
extern Effect* CelesteCtor( int ) ;
42
extern Effect* ReverbCtor( int ) ;
45
EFFECT_CTOR effect_type_list[]={
46
ChorusCtor , PhaserCtor , CelesteCtor , ReverbCtor , 0
49
/* number of effects*/
50
#define NUM_EFFECTS (int)(( sizeof(effect_type_list) / sizeof(EFFECT_CTOR) ) - 1)
52
Effect* effect_list[ NUM_EFFECTS ][MAXCHAN] ;
54
char effect_name[NUM_EFFECTS][MAXCHAN] ;
56
/**************************************************************************/
57
/** channel buffers and empty flags
59
static int32 channel_buffer[MAXCHAN][AUDIO_BUFFER_SIZE*2] ; /* stereo samples */
60
static int channel_buffer_state[MAXCHAN] ; /* 0 means null signal , 1 non null */
62
void do_compute_data_effect(uint32 count);
64
/**************************************************************************/
65
/** c_buff structure helpers functions */
67
#define CIRCBUFF_PARAM 8 /* define factor between active content part and actual buffer */
69
void create_cirbuff( cirbuff* pThis , uint32 count )
71
memset( pThis , 0 , sizeof( cirbuff ) ) ;
74
pThis->m_pBufLast = (int32 *) safe_malloc( count * CIRCBUFF_PARAM * 4 ) ;
75
memset( pThis->m_pBufLast , 0 , count * CIRCBUFF_PARAM * 4 ) ;
76
-- pThis->m_pBufLast ;
77
pThis->m_pBufCur = pThis->m_pBufLast + count * CIRCBUFF_PARAM ;
78
pThis->m_pCur = pThis->m_pBufLast + count ;
79
pThis->m_count = count ;
83
void delete_cirbuff( cirbuff* pThis )
85
if( pThis->m_pBufLast != 0 )
87
++ pThis->m_pBufLast ;
88
free( pThis->m_pBufLast ) ;
90
memset( pThis , 0 , sizeof( cirbuff ) ) ;
93
void redim_cirbuff( cirbuff* pThis , uint32 count )
96
delete_cirbuff( pThis ) ;
97
else if( count <= pThis->m_count )
98
pThis->m_count = count ;
102
create_cirbuff( &CircTmp , count ) ;
103
memcpy( CircTmp.m_pCur - pThis->m_count + 1 , pThis->m_pCur - pThis->m_count + 1, pThis->m_count * 4 ) ;
104
delete_cirbuff( pThis ) ;
105
memcpy( pThis , &CircTmp , sizeof( cirbuff ) ) ;
109
void pushval_cirbuff( cirbuff* pThis , int32 newSample )
111
if( pThis->m_pCur >= pThis->m_pBufCur )
113
memcpy( pThis->m_pBufLast + 1 , pThis->m_pCur - pThis->m_count + 2 , ( pThis->m_count - 1 ) * 4 ) ;
114
pThis->m_pCur = pThis->m_pBufLast + pThis->m_count - 1 ;
117
*(pThis->m_pCur) = newSample ;
120
void shift_cirbuff( cirbuff* pThis , uint32 uiShift )
124
if( uiShift >= pThis->m_count )
126
memset( pThis->m_pBufLast + 1 , 0 , pThis->m_count * 4 ) ;
127
pThis->m_pCur = pThis->m_pBufLast + pThis->m_count ;
132
if( pThis->m_pCur + uiShift <= pThis->m_pBufCur )
133
pThis->m_pCur += uiShift ;
136
offset = pThis->m_count - uiShift ;
137
memcpy( pThis->m_pBufLast + 1
138
, pThis->m_pCur - offset + 1, offset * 4 );
139
pThis->m_pCur = pThis->m_pBufLast + pThis->m_count ;
141
memset( pThis->m_pCur - uiShift + 1 , 0 , uiShift * 4 );
145
void dump_cirbuff( cirbuff* pThis , FILE* pOutFile )
148
fprintf( pOutFile , "{ " ) ;
149
for( pTest = pThis->m_pBufLast + 1 ; pTest <= pThis->m_pBufCur ; ++ pTest )
151
fprintf( pOutFile , " %lu " , *pTest ) ;
152
if( pTest == pThis->m_pCur - pThis->m_count )
153
fprintf( pOutFile , "[ " ) ;
154
if( pTest == pThis->m_pCur )
155
fprintf( pOutFile , " ]" ) ;
157
fprintf( pOutFile , " }\n\n" ) ;
160
/** performs various buffer manipulations */
162
static void DebugCircBuffer()
166
pfTest = fopen("test.txt","w");
167
create_cirbuff( &test , 4 ) ;
168
pushval_cirbuff( &test , 1 ) ;
169
dump_cirbuff( &test , pfTest ) ;
171
pushval_cirbuff( &test , 2 ) ;
172
dump_cirbuff( &test , pfTest ) ;
174
pushval_cirbuff( &test , 3 ) ;
175
dump_cirbuff( &test , pfTest ) ;
177
pushval_cirbuff( &test , 4 ) ;
178
dump_cirbuff( &test , pfTest ) ;
180
shift_cirbuff( &test , 2 ) ;
181
dump_cirbuff( &test , pfTest ) ;
183
pushval_cirbuff( &test , 5 ) ;
184
dump_cirbuff( &test , pfTest ) ;
186
redim_cirbuff( &test , 6 ) ;
187
dump_cirbuff( &test , pfTest ) ;
189
pushval_cirbuff( &test , 6 ) ;
190
dump_cirbuff( &test , pfTest ) ;
192
shift_cirbuff( &test , 2 ) ;
193
dump_cirbuff( &test , pfTest ) ;
195
pushval_cirbuff( &test , 7 ) ;
196
dump_cirbuff( &test , pfTest ) ;
198
pushval_cirbuff( &test , 8 ) ;
199
dump_cirbuff( &test , pfTest ) ;
201
shift_cirbuff( &test , 3 ) ;
202
dump_cirbuff( &test , pfTest ) ;
204
delete_cirbuff( &test ) ;
208
/**************************************************************************/
209
/** do_compute_data redefined from playmidi
211
void do_compute_data_effect(uint32 count)
213
int idChannel , idVoice , idEffect;
215
int32 *pBuffDestEnd ;
217
if( play_mode->encoding & PE_MONO )
218
byteCount = count * 4 ;
220
byteCount = count * 8 ;
222
/* mix voices into channel buffers*/
223
for ( idVoice = 0; idVoice < voices; ++idVoice )
225
if( voice[ idVoice ].status != VOICE_FREE )
227
idChannel = voice[ idVoice ].channel ;
228
if (!voice[ idVoice ].sample_offset && voice[ idVoice ].echo_delay_count)
230
if (voice[ idVoice ].echo_delay_count >= count) voice[ idVoice ].echo_delay_count -= count;
233
mix_voice( channel_buffer[ idChannel ] + voice[ idVoice ].echo_delay_count, idVoice,
234
count - voice[ idVoice ].echo_delay_count);
235
voice[ idVoice ].echo_delay_count = 0;
238
else mix_voice( channel_buffer[ idChannel ] , idVoice , count );
239
channel_buffer_state[ idChannel ] = 1 ;
245
if( play_mode->encoding & PE_MONO )
246
for( idEffect = 0 ; idEffect < NUM_EFFECTS ; ++ idEffect )
248
for( idChannel = 0 ; idChannel < MAXCHAN ; ++ idChannel )
250
if( effect_list[idEffect][idChannel] != 0 )
251
(( effect_list[idEffect][idChannel] )->m_pfnActionMono)
252
( effect_list[idEffect][idChannel] , channel_buffer[ idChannel ]
253
, count , &(channel_buffer_state[ idChannel ]) ) ;
257
for( idEffect = 0 ; idEffect < NUM_EFFECTS ; ++ idEffect )
259
for( idChannel = 0 ; idChannel < MAXCHAN ; ++ idChannel )
261
if( effect_list[idEffect][idChannel] != 0 )
262
(( effect_list[idEffect][idChannel] )->m_pfnActionStereo)
263
( effect_list[idEffect][idChannel] , channel_buffer[ idChannel ]
264
, count , &(channel_buffer_state[ idChannel ]) ) ;
268
/* clear common buffer */
269
memset(buffer_pointer, 0, byteCount );
271
/* mix channel buffers into common_buffer */
272
if( play_mode->encoding & PE_MONO )
273
pBuffDestEnd = buffer_pointer + count ;
275
pBuffDestEnd = buffer_pointer + ( count * 2 ) ;
277
for( idChannel = 0 ; idChannel < MAXCHAN ; ++ idChannel )
279
int32 *pBuffSrcCur , *pBuffDestCur ;
280
if( channel_buffer_state[ idChannel ] )
281
{ /* mix this channel if non empty */
282
pBuffSrcCur = channel_buffer[ idChannel ] ;
283
pBuffDestCur = buffer_pointer ;
284
for( ; pBuffDestCur != pBuffDestEnd ; ++ pBuffDestCur , ++ pBuffSrcCur )
285
*pBuffDestCur += *pBuffSrcCur ;
289
/* clear channel buffer */
290
for( idChannel = 0 ; idChannel < MAXCHAN ; ++ idChannel )
292
if( channel_buffer_state[ idChannel ] )
294
memset( channel_buffer[ idChannel ] , 0, byteCount ) ;
295
channel_buffer_state[ idChannel ] = 0 ;
299
current_sample += count;
302
/** cut and paste from playmidi*/
304
static void do_compute_data_default(uint32 count)
307
if (!count) return; /* (gl) */
308
memset(buffer_pointer, 0,
309
(play_mode->encoding & PE_MONO) ? (count * 4) : (count * 8));
310
for (i=0; i<voices; i++)
312
if(voice[i].status != VOICE_FREE)
314
if (!voice[i].sample_offset && voice[i].echo_delay_count)
316
if (voice[i].echo_delay_count >= count) voice[i].echo_delay_count -= count;
319
mix_voice(buffer_pointer+voice[i].echo_delay_count, i, count - voice[i].echo_delay_count);
320
voice[i].echo_delay_count = 0;
323
else mix_voice(buffer_pointer, i, count);
326
current_sample += count;
328
/**************************************************************************/
329
/** switch beetween effect / no_effect mixing mode */
330
void (*do_compute_data)(uint32) = &do_compute_data_default ;
333
/**************************************************************************/
334
/** fct : effect_activate
336
void effect_activate( int iSwitch )
340
do_compute_data = &do_compute_data_effect ;
345
do_compute_data = &do_compute_data_default ;
350
/**************************************************************************/
351
/** initialize this file scope variables according to (TODO) command line
352
* switches , to be called prior any other processing
353
* return 1 if success
358
for( idChannel = 0 ; idChannel < MAXCHAN ; ++ idChannel )
361
memset( channel_buffer[ idChannel ] , 0, AUDIO_BUFFER_SIZE*8 ) ;
362
channel_buffer_state[ idChannel ] = 0 ;
363
for( idEffect = 0 ; idEffect < NUM_EFFECTS ; ++ idEffect )
365
effect_list[ idEffect ][ idChannel ] = effect_type_list[idEffect]() ;
366
if( effect_list[ idEffect ][ idChannel ] == 0 )
369
((effect_list[ idEffect ][ idChannel ])->m_pfnName)( effect_name[idEffect] );
371
effect_list[ idEffect ][ idChannel ] = 0 ;
377
/**************************************************************************/
378
/** fct : effect_ctrl_change
380
void effect_ctrl_change( MidiEvent* pCurrentEvent )
383
for( idEffect = 0 ; idEffect < NUM_EFFECTS ; ++ idEffect )
385
if( effect_list[idEffect][pCurrentEvent->channel] != 0 )
386
( (effect_list[idEffect][pCurrentEvent->channel])->m_pfnCtrlChange )
387
( effect_list[idEffect][pCurrentEvent->channel] , pCurrentEvent ) ;
391
/**************************************************************************/
392
/** get info about XG effects
394
static void reset_XG_effect_info() {
396
XG_effect_chorus_is_celeste_flag =
397
XG_effect_chorus_is_flanger_flag =
398
XG_effect_chorus_is_phaser_flag = 0;
400
if (XG_System_chorus_type >= 0) {
401
/* int subtype = XG_System_chorus_type & 0x07; */
402
int chtype = 0x0f & (XG_System_chorus_type >> 3);
404
case 0: /* no effect */
408
case 2: /* celeste */
409
XG_effect_chorus_is_celeste_flag = 1;
411
case 3: /* flanger */
412
XG_effect_chorus_is_flanger_flag = 1;
414
case 4: /* symphonic : cf Children of the Night /128 bad, /1024 ok */
417
XG_effect_chorus_is_phaser_flag = 1;
423
if (XG_System_reverb_type >= 0) {
424
/* int subtype = XG_System_reverb_type & 0x07; */
425
int rtype = XG_System_reverb_type >>3;
427
case 0: /* no effect */
437
case 16: /* white room */
439
case 17: /* tunnel */
441
case 18: /* canyon */
443
case 19: /* basement */
450
/**************************************************************************/
451
/** fct : effect_ctrl_reset
453
void effect_ctrl_reset( int idChannel )
457
if (!idChannel) reset_XG_effect_info();
459
for( idEffect = 0 ; idEffect < NUM_EFFECTS ; ++ idEffect )
461
if( effect_list[idEffect][idChannel] != 0 )
462
( (effect_list[idEffect][idChannel])->m_pfnCtrlReset )( effect_list[idEffect][idChannel] ) ;
466
#endif /*CHANNEL_EFFECT*/