~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmidi/reverb_e.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *              reverb_e.c
 
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
 
8
 */
 
9
 
 
10
#include "config.h"
 
11
 
 
12
#ifdef CHANNEL_EFFECT
 
13
 
 
14
#ifndef NO_STRING_H
 
15
#include <string.h>
 
16
#else
 
17
#include <strings.h>
 
18
#endif
 
19
 
 
20
#include <stdio.h>
 
21
#ifndef __WIN32__
 
22
#include <unistd.h>
 
23
#endif
 
24
#include <stdlib.h>
 
25
#include "common.h"
 
26
#include "instrum.h"
 
27
#include "playmidi.h"
 
28
#include "effects.h"
 
29
#include "output.h"
 
30
 
 
31
 
 
32
/**************************************************************************/
 
33
/**      reverb_effect structure definition
 
34
 *      formula : 
 
35
 *
 
36
 *      early reflections
 
37
 *
 
38
 *      left    
 
39
 *              yel(n) = G1 * xl( n - d1 ) + G2 * xr( n - d2 ) + G3 * xl( n - d3 )
 
40
 *
 
41
 *      right
 
42
 *              yer(n) = G1 * xr( n - d1 ) + G2 * xl( n - d2 ) + G3 * xr( n - d3 )
 
43
 *
 
44
 *      ambient reverb with embedded filter 
 
45
 *      left    
 
46
 *              yal =  xl( n ) + G4 * xl( n - d4 ) + G5 * xl( n - d5 ) + G6 * xl( n - d6 ) + G7 * ( yal( n - d7 ) - m ) 
 
47
 *
 
48
 *      right
 
49
 *              yar =  xr( n ) + G4 * xl( n - d4 ) + G6 * xr( n - d6 ) + G7 * ( yal( n - d7 ) - m ) 
 
50
 *
 
51
 *              m : average      : used for hight pass filter   
 
52
 *
 
53
 *      outup signal
 
54
 *              s(n) = x(n) + Ge * ye(n) + Ga * ya(n) 
 
55
 */
 
56
 
 
57
/* >> choice of the day >> */
 
58
 
 
59
/** G_BIT and G : denominator size */
 
60
#define G_BITS 10
 
61
#define G       ((int32)( 1 << G_BITS ))
 
62
 
 
63
/** max die reverb time in ms */
 
64
#define DIE_TIME 2300
 
65
 
 
66
/** delays in ms */
 
67
#define D1 15
 
68
#define D2 30
 
69
#define D3 54
 
70
 
 
71
#define D4 70
 
72
#define D5 154  
 
73
#define D6 250 
 
74
 
 
75
#define D7 220
 
76
 
 
77
/** gains*/
 
78
#define G1      0.78
 
79
#define G2      (-0.79)
 
80
#define G3      0.4
 
81
 
 
82
#define G4      0.87
 
83
#define G5      0.67
 
84
#define G6      0.48
 
85
 
 
86
#define G7      0.7
 
87
 
 
88
/** gain variation between left and right channels in stereo mode */
 
89
#define DG  0.05 
 
90
 
 
91
/** relative min gain for echos */
 
92
#define G_MIN   0.1
 
93
 
 
94
/** for early and ambient echo gain tuning */
 
95
#define GE_MAX  0.31  
 
96
#define GA_MAX  0.056 
 
97
 
 
98
/** averaging hight filter cutoff frequency in Hz */
 
99
#define FILTER_FREQU 300        
 
100
 
 
101
/** averaging hight filter impulsionnal response size in samples*/
 
102
static int delay_flt = 0 ;
 
103
 
 
104
/** time param normalized to sampling rate*/
 
105
static int32 d1 , d2 , d3 , d4 , d5 , d6 , d7;
 
106
static uint32 dieTime;
 
107
 
 
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);
 
116
 
 
117
 
 
118
static int32 gm ;
 
119
 
 
120
typedef struct 
 
121
{
 
122
/*---------------------------------------------------*/ 
 
123
/* Effect base implementation */
 
124
        void *m_pfnActionMono ;
 
125
        void *m_pfnActionStereo ;
 
126
        void *m_pfnCtrlChange ;
 
127
        void *m_pfnCtrlReset ;
 
128
        void *m_pfnName ;
 
129
        void *m_pfnDestruct ;   
 
130
 
 
131
/*---------------------------------------------------*/ 
 
132
/* additionnal parameters */
 
133
 
 
134
        /** m_uiNullCount : number of last null samples or 0 
 
135
         */
 
136
        uint32 m_uiNullCount ;
 
137
 
 
138
        /**     l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
 
139
        cirbuff leftX , leftYa , rightX , rightYa  ;
 
140
 
 
141
        /** gain param normalized to G : if ge == 0 inactivated */
 
142
        int32 ge , ga;
 
143
 
 
144
        /** average value of last 128 x samples */
 
145
        int32 m_left , m_right ;
 
146
 
 
147
} reverb_effect ;
 
148
 
 
149
 
 
150
/**************************************************************************/
 
151
/**      reverb_effect function overriding
 
152
 */
 
153
static void ActionMono( reverb_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
 
154
{
 
155
        if( pThis->ge == 0 )
 
156
                return ;
 
157
        if( *pbSignal )
 
158
                pThis->m_uiNullCount = 0 ;
 
159
        else
 
160
                pThis->m_uiNullCount += count ;
 
161
        if( pThis->m_uiNullCount < dieTime )
 
162
        {
 
163
                int32* pCur = pMonoBuffer;      
 
164
                int32* pEnd = pMonoBuffer + count ;                             
 
165
                int x ,ye, ya ;
 
166
                for( ; pCur != pEnd ; ++ pCur )
 
167
                {                       
 
168
                        x = *pCur / G ;
 
169
                        
 
170
                        ye = (  ( (pThis->leftX.m_pCur)[d1] * g1 ) 
 
171
                                + ( (pThis->leftX.m_pCur)[d2] * g2 ) 
 
172
                                + ( (pThis->leftX.m_pCur)[d3] * g3 ) ) / G ;
 
173
                        
 
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 )
 
179
                                        ) / G ;                 
 
180
                
 
181
                        *pCur =  x * G + ( ye * pThis->ge  ) + ( ya * pThis->ga )  ;
 
182
                        
 
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 ) ;                      
 
187
                }
 
188
                *pbSignal = 1 ;
 
189
        }
 
190
        else
 
191
        {
 
192
                shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;
 
193
                shift_cirbuff( &( pThis->leftYa ) , pThis->m_uiNullCount ) ;
 
194
                
 
195
                pThis->m_left = 0 ;             
 
196
        }
 
197
}
 
198
 
 
199
static void ActionStereo( reverb_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
 
200
{
 
201
        /* int32 test = G ; */
 
202
        if( pThis->ge == 0 )
 
203
                return ;
 
204
        if( *pbSignal )
 
205
                pThis->m_uiNullCount = 0 ;
 
206
        else
 
207
                pThis->m_uiNullCount += count ;
 
208
        if( pThis->m_uiNullCount < dieTime )
 
209
        {
 
210
                int32* pCur = pStereoBuffer;    
 
211
                int32* pEnd = pStereoBuffer + 2 * count ;                               
 
212
                int x , ye , ya ;
 
213
 
 
214
                for( ; pCur != pEnd ; ++ pCur )
 
215
                {                       
 
216
                        x = *pCur / G ;         
 
217
                        ye = ( ( (pThis->leftX.m_pCur)[d1] * g1 ) 
 
218
                                + ( (pThis->rightX.m_pCur)[d2] * g2 ) 
 
219
                                + ( (pThis->leftX.m_pCur)[d3] * g3 ) ) / G ;
 
220
                        
 
221
                        ya = (  
 
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 )
 
227
                                        ) / G ;         
 
228
                
 
229
                        *pCur =  x * G + ( ye * pThis->ge  ) + ( ya * pThis->ga )  ;
 
230
 
 
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 ) ;
 
235
                
 
236
                        ++pCur ;
 
237
 
 
238
                        x = *pCur / G ;         
 
239
                        ye = ( ( (pThis->rightX.m_pCur)[d1] * g1 ) 
 
240
                                + ( (pThis->leftX.m_pCur)[d2] * g2 ) 
 
241
                                + ( (pThis->rightX.m_pCur)[d3] * g3 ) ) / G ;   
 
242
                        
 
243
                        ya = (  
 
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 )
 
249
                                        ) / G ;                         
 
250
                
 
251
                        *pCur =  x * G + ( ye * pThis->ge  ) + ( ya * pThis->ga )  ;
 
252
 
 
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 ) ;             
 
257
                }
 
258
 
 
259
                *pbSignal = 1 ;
 
260
        }
 
261
        else
 
262
        {
 
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 ) ;           
 
267
                pThis->m_left = 0 ;
 
268
                pThis->m_right = 0 ;
 
269
        }
 
270
}
 
271
 
 
272
static void CtrlReset( reverb_effect* pThis )
 
273
{
 
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 ) ;      
 
279
        
 
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 ;
 
288
 
 
289
        delay_flt = play_mode->rate / FILTER_FREQU ;
 
290
        gm = g7 / delay_flt ;
 
291
 
 
292
        pThis->ge = 0 ;
 
293
        pThis->ga = 0 ; 
 
294
 
 
295
        pThis->m_left = 0 ;
 
296
        pThis->m_right = 0 ;
 
297
}
 
298
 
 
299
static void CtrlChange( reverb_effect* pThis , MidiEvent* pCurrentEvent )
 
300
{
 
301
        int amount = pCurrentEvent->a;
 
302
        if (amount < global_reverb) amount = global_reverb;
 
303
 
 
304
        if( pCurrentEvent->b ==  ME_REVERBERATION )
 
305
        {
 
306
                if( amount != 0 )
 
307
                {
 
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 ) )
 
313
                        {
 
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) ) ;
 
318
                        }
 
319
 
 
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 ) ) );
 
322
 
 
323
                }
 
324
                else
 
325
                        CtrlReset( pThis ) ;
 
326
        }
 
327
}
 
328
 
 
329
static void Name( char* pszBuff )
 
330
{
 
331
        strcpy( pszBuff , "reverb" );
 
332
}
 
333
 
 
334
static void Destruct( reverb_effect* pThis  )
 
335
{
 
336
        delete_cirbuff( &( pThis->leftX ) ) ;
 
337
        delete_cirbuff( &( pThis->leftYa ) ) ;  
 
338
        delete_cirbuff( &( pThis->rightX ) ) ;
 
339
        delete_cirbuff( &( pThis->rightYa )  ) ;        
 
340
 
 
341
        memset( pThis , 0 , sizeof( reverb_effect ) ) ;
 
342
        free( pThis ) ;
 
343
}
 
344
 
 
345
 
 
346
/**************************************************************************/
 
347
/**      reverb_effect construction function prototype
 
348
 */
 
349
Effect* ReverbCtor() 
 
350
{
 
351
        reverb_effect* pReturn = 0 ;
 
352
        pReturn =(reverb_effect*) malloc( sizeof( reverb_effect ) ) ;
 
353
        memset( pReturn , 0 , sizeof( reverb_effect ) ) ;
 
354
        
 
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 ;
 
361
 
 
362
        create_cirbuff( &( pReturn->leftX ) , 0 ) ;
 
363
        create_cirbuff( &( pReturn->leftYa ) , 0 ) ;    
 
364
        create_cirbuff( &( pReturn->rightX ) , 0 ) ;
 
365
        create_cirbuff( &( pReturn->rightYa ) , 0 ) ;   
 
366
 
 
367
        CtrlReset( pReturn ) ;
 
368
        return ( Effect* )pReturn ;
 
369
}
 
370
 
 
371
 
 
372
 
 
373
 
 
374
#endif /* CHANNEL_EFFECT */