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

« back to all changes in this revision

Viewing changes to kmidi/chorus_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
 *              chorus_e.c
 
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
 
8
 */
 
9
 
 
10
#include "config.h"
 
11
 
 
12
#ifdef CHANNEL_EFFECT
 
13
#ifndef NO_STRING_H
 
14
#include <string.h>
 
15
#else
 
16
#include <strings.h>
 
17
#endif
 
18
#include <stdio.h>
 
19
#ifndef __WIN32__
 
20
#include <unistd.h>
 
21
#endif
 
22
#include <stdlib.h>
 
23
#include "common.h"
 
24
#include "instrum.h"
 
25
#include "playmidi.h"
 
26
#include "effects.h"
 
27
#include "output.h"
 
28
#include "tables.h"
 
29
 
 
30
/**************************************************************************/
 
31
/**      chorus_effect structure definition
 
32
 *      formula : 
 
33
 *
 
34
 *      output signal
 
35
 *
 
36
 *              phi = d + sw * triangle( 2Pi/T  * t )
 
37
 *
 
38
 *              sl(n) = xl(n) + A * x( n - phi(t) ) 
 
39
 *
 
40
 *              sr(n) = xr(n) + A * x( n - phi(t - T / 4 ) ) 
 
41
 *
 
42
 */
 
43
 
 
44
 
 
45
/* >> choice of the day >> */
 
46
 
 
47
/** G_BIT and G : denominator size  */
 
48
#define G_BITS 9
 
49
#define G       ((int32)( 1 << G_BITS ))
 
50
 
 
51
/** average delays in ms */
 
52
#define D 25
 
53
 
 
54
/** max die time in ms */
 
55
#define DIE_TIME ( D * 2 )
 
56
 
 
57
/** sweep ratio in percent of D */
 
58
#define SWEEP 0.08
 
59
 
 
60
/** max chorus amplitude */
 
61
#define A_MAX 1.0
 
62
#define A_MIN 0.3
 
63
 
 
64
/** time param normalized to sampling rate*/
 
65
static uint32 dieTime = 0 ;
 
66
 
 
67
/** approximate chorus frequency Hz */
 
68
#define FREQU   1.5
 
69
 
 
70
/** d_min , d_max : chorus depth and average delay relative to sampling rate and G_BITS fractionnal part for 
 
71
 *      linear interpolation
 
72
 */
 
73
static uint32 d_min = 0 ;
 
74
static uint32 d_max = 0 ;
 
75
 
 
76
typedef struct 
 
77
{
 
78
/*---------------------------------------------------*/ 
 
79
/* Effect base implementation */
 
80
        void *m_pfnActionMono;
 
81
        void *m_pfnActionStereo ;
 
82
        void *m_pfnCtrlChange ;
 
83
        void *m_pfnCtrlReset ;
 
84
        void *m_pfnName ;
 
85
        void *m_pfnDestruct ;   
 
86
 
 
87
/*---------------------------------------------------*/ 
 
88
/* additionnal parameters */
 
89
 
 
90
        /** m_uiNullCount : number of last null samples or 0 
 
91
         */
 
92
        uint32 m_uiNullCount ;
 
93
 
 
94
        /**     l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
 
95
        cirbuff leftX , rightX  ;
 
96
 
 
97
        /** gain param , if != 0 this effect is active*/
 
98
        int32 a ;
 
99
        
 
100
        /** current state for triangle phase ramp relative to fractionnal part G_BITS */
 
101
        uint32 d_left , d_right ;
 
102
        
 
103
        /** incremental step for chorus phase eval , calculated according to FREQU and depth */
 
104
        int32 incr_left , incr_right ;
 
105
 
 
106
} chorus_effect ;
 
107
 
 
108
/**************************************************************************/
 
109
/**      reverb_effect function overriding
 
110
 */
 
111
static void ActionMono( chorus_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
 
112
{
 
113
        if( pThis->a == 0 )
 
114
                return ;
 
115
        if( *pbSignal )
 
116
                pThis->m_uiNullCount = 0 ;
 
117
        else
 
118
                pThis->m_uiNullCount += count ;
 
119
        if( pThis->m_uiNullCount < dieTime )
 
120
        {
 
121
                int32* pCur = pMonoBuffer;      
 
122
                int32* pEnd = pMonoBuffer + count ;                             
 
123
                int32 x , v1 , v2 , delta , tmp ;
 
124
                
 
125
                for( ; pCur != pEnd ; ++ pCur )
 
126
                {                       
 
127
                        x = *pCur / G;
 
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 ;
 
132
                        
 
133
                        *pCur += pThis->a * ( v1 + delta ) ;                    
 
134
                        pushval_cirbuff( &(pThis->leftX) , x ) ;
 
135
                        if( pThis->d_left > d_max )
 
136
                        {
 
137
                                pThis->incr_left = -abs( pThis->incr_left ) ;
 
138
                                pThis->d_left  = d_max ;
 
139
                        }
 
140
                        else if( pThis->d_left < d_min )
 
141
                        {
 
142
                                pThis->incr_left = +abs( pThis->incr_left ) ;
 
143
                                pThis->d_left = d_min ;
 
144
                        }
 
145
                        else
 
146
                                pThis->d_left += pThis->incr_left ;
 
147
                }
 
148
                *pbSignal = 1 ;
 
149
        }
 
150
        else
 
151
        {
 
152
                shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;     
 
153
                pThis->d_left = ( d_max + d_min ) / 2 ;
 
154
        }
 
155
}
 
156
 
 
157
static void ActionStereo( chorus_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
 
158
{
 
159
        if( pThis->a == 0 )
 
160
                return ;
 
161
        if( *pbSignal )
 
162
                pThis->m_uiNullCount = 0 ;
 
163
        else
 
164
                pThis->m_uiNullCount += count ;
 
165
        if( pThis->m_uiNullCount < dieTime )
 
166
        {
 
167
                int32* pCur = pStereoBuffer;    
 
168
                int32* pEnd = pStereoBuffer + 2 * count ;                               
 
169
                int32 x , v1 , v2 , delta , tmp ;
 
170
                
 
171
                for( ; pCur != pEnd ; ++ pCur )
 
172
                {                       
 
173
                        x = *pCur / G ;
 
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 ;
 
178
                        
 
179
                        *pCur += pThis->a * ( v1 + delta ) ;                    
 
180
                        pushval_cirbuff( &(pThis->leftX) , x ) ;
 
181
                        if( pThis->d_left > d_max )
 
182
                        {
 
183
                                pThis->incr_left = -abs( pThis->incr_left ) ;
 
184
                                pThis->d_left  = d_max ;
 
185
                        }
 
186
                        else if( pThis->d_left < d_min )
 
187
                        {
 
188
                                pThis->incr_left = +abs( pThis->incr_left ) ;
 
189
                                pThis->d_left = d_min ;
 
190
                        }
 
191
                        else
 
192
                                pThis->d_left += pThis->incr_left ;
 
193
                        
 
194
                        ++pCur ;
 
195
 
 
196
                        x = *pCur ;
 
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 ;
 
201
                        
 
202
                        *pCur += pThis->a * ( v1 + delta ) ;                    
 
203
                        pushval_cirbuff( &(pThis->rightX) , x ) ;
 
204
                        if( pThis->d_right > d_max )
 
205
                        {
 
206
                                pThis->incr_right = -abs( pThis->incr_right ) ;
 
207
                                pThis->d_right  = d_max ;
 
208
                        }
 
209
                        else if( pThis->d_right < d_min )
 
210
                        {
 
211
                                pThis->incr_right = +abs( pThis->incr_right ) ;
 
212
                                pThis->d_right = d_min ;
 
213
                        }
 
214
                        else
 
215
                                pThis->d_right += pThis->incr_right ;
 
216
                        
 
217
                }
 
218
                *pbSignal = 1 ;
 
219
        }
 
220
        else
 
221
        {
 
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 ;
 
226
        }
 
227
}
 
228
 
 
229
static void CtrlReset( chorus_effect* pThis )
 
230
{
 
231
        pThis->m_uiNullCount = 0 ;
 
232
        redim_cirbuff( &( pThis->leftX ) , 0 ) ;
 
233
        redim_cirbuff( &( pThis->rightX ) , 0 ) ;       
 
234
        
 
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 );
 
237
 
 
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 ;
 
243
        pThis->a = 0 ;
 
244
}
 
245
 
 
246
static void CtrlChange( chorus_effect* pThis , MidiEvent* pCurrentEvent )
 
247
{
 
248
        int amount = pCurrentEvent->a;
 
249
        if (amount < global_chorus) amount = global_chorus;
 
250
 
 
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)
 
255
        {
 
256
                if( amount != 0 )
 
257
                {
 
258
                        redim_cirbuff( &( pThis->leftX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
 
259
                        if( ! ( play_mode->encoding & PE_MONO ) )
 
260
                        {
 
261
                                redim_cirbuff( &( pThis->rightX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
 
262
                        }
 
263
                        pThis->a = (int32)( G * ( A_MIN + ( A_MAX - A_MIN ) * ( amount - 1 ) / 126.0 ) );       
 
264
                }
 
265
                else
 
266
                        CtrlReset( pThis ) ;
 
267
        }
 
268
}
 
269
 
 
270
static void Name( char* pszBuff )
 
271
{
 
272
        strcpy( pszBuff , "chorus" );
 
273
}
 
274
 
 
275
static void Destruct( chorus_effect* pThis  )
 
276
{
 
277
        delete_cirbuff( &( pThis->leftX ) ) ;
 
278
        delete_cirbuff( &( pThis->rightX ) ) ;
 
279
 
 
280
        memset( pThis , 0 , sizeof( chorus_effect ) ) ;
 
281
        free( pThis ) ;
 
282
}
 
283
 
 
284
 
 
285
/**************************************************************************/
 
286
/**      chorus_effect construction function prototype
 
287
 */
 
288
Effect* ChorusCtor() 
 
289
{
 
290
        chorus_effect* pReturn = 0 ;
 
291
        pReturn = (chorus_effect *) malloc( sizeof( chorus_effect ) ) ;
 
292
        memset( pReturn , 0 , sizeof( chorus_effect ) ) ;
 
293
        
 
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 ;
 
300
 
 
301
        create_cirbuff( &( pReturn->leftX ) , 0 ) ;
 
302
        create_cirbuff( &( pReturn->rightX ) , 0 ) ;
 
303
 
 
304
        CtrlReset( pReturn ) ;
 
305
        return ( Effect* )pReturn ;
 
306
}
 
307
 
 
308
 
 
309
 
 
310
 
 
311
 
 
312
 
 
313
#endif /* CHANNEL_EFFECT */