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

« back to all changes in this revision

Viewing changes to kmidi/phaser_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
 *              phaser_e.c
 
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
 
9
 */
 
10
 
 
11
#include "config.h"
 
12
 
 
13
#ifdef CHANNEL_EFFECT
 
14
#ifndef NO_STRING_H
 
15
#include <string.h>
 
16
#else
 
17
#include <strings.h>
 
18
#endif
 
19
#include <stdio.h>
 
20
#ifndef __WIN32__
 
21
#include <unistd.h>
 
22
#endif
 
23
#include <stdlib.h>
 
24
#include "common.h"
 
25
#include "instrum.h"
 
26
#include "playmidi.h"
 
27
#include "effects.h"
 
28
#include "output.h"
 
29
#include "tables.h"
 
30
 
 
31
/**************************************************************************/
 
32
/**      phaser_effect structure definition
 
33
 *      formula : 
 
34
 *
 
35
 *      output signal
 
36
 *
 
37
 *              phi = d + sw * triangle( 2Pi/T  * t )
 
38
 *
 
39
 *              y(n) =  - GP * x(n) + x( n - phi ) + GP * y( n - d )  (phase filter)
 
40
 *
 
41
 *              s = gx * x + gy * y(n) 
 
42
 */
 
43
 
 
44
 
 
45
/* >> choice of the day >> */
 
46
 
 
47
/** G_BIT and G : denominator size and fractionnal time part */
 
48
#define G_BITS 9
 
49
#define G       ((int32)( 1 << G_BITS ))
 
50
 
 
51
/** average delays in ms */
 
52
#define D 1.0
 
53
 
 
54
/** phaser loopback gain*/
 
55
#define GP 0.5
 
56
 
 
57
/** relative min gain for phased signal */
 
58
#define G_MIN   0.3
 
59
 
 
60
/** max die time in ms */
 
61
#define DIE_TIME ( 1000 / FREQU )
 
62
 
 
63
/** approximate phaser frequency Hz */
 
64
#define FREQU 1.0
 
65
 
 
66
/** sweep ratio in percent of D */
 
67
#define SWEEP ( D / 1.01 )
 
68
 
 
69
/** time param normalized to sampling rate*/
 
70
static uint32 dieTime = 0 ;
 
71
 
 
72
/** phaser loopback gain normalized to G */
 
73
static int32 gp = ( (int32)( GP * G) ) ;
 
74
 
 
75
/** d_min , d_max : phaser depth and average delay relative to sampling rate and G_BITS fractionnal part for 
 
76
 *      linear interpolation
 
77
 */
 
78
static uint32 d_min = 0 ;
 
79
static uint32 d_max = 0 ;
 
80
 
 
81
typedef struct 
 
82
{
 
83
/*---------------------------------------------------*/ 
 
84
/* Effect base implementation */
 
85
        void *m_pfnActionMono;
 
86
        void *m_pfnActionStereo ;
 
87
        void *m_pfnCtrlChange ;
 
88
        void *m_pfnCtrlReset ;
 
89
        void *m_pfnName ;
 
90
        void *m_pfnDestruct ;   
 
91
 
 
92
/*---------------------------------------------------*/ 
 
93
/* additionnal parameters */
 
94
 
 
95
        /** m_uiNullCount : number of last null samples or 0 
 
96
         */
 
97
        uint32 m_uiNullCount ;
 
98
 
 
99
        /**     l/rX/Y past samples circular buffer for x and ya left(or mono) and right */
 
100
        cirbuff leftX , rightX , leftY , rightY ;
 
101
        
 
102
        /** current state for triangle phase ramp relative to fractionnal part G_BITS */
 
103
        uint32 d ;
 
104
        
 
105
        /** incremental step for phaser phase eval , calculated according to FREQU and depth */
 
106
        int32 incr;
 
107
 
 
108
        /** dry and phased gain normalized to G */
 
109
        int32 gx , gy ;
 
110
 
 
111
} phaser_effect ;
 
112
 
 
113
/**************************************************************************/
 
114
/**      reverb_effect function overriding
 
115
 */
 
116
static void ActionMono( phaser_effect* pThis , int32* pMonoBuffer, int32 count , int* pbSignal )
 
117
{
 
118
        if( pThis->gy == 0 )
 
119
                return ;
 
120
        if( *pbSignal )
 
121
                pThis->m_uiNullCount = 0 ;
 
122
        else
 
123
                pThis->m_uiNullCount += count ;
 
124
        if( pThis->m_uiNullCount < dieTime )
 
125
        {
 
126
                int32* pCur = pMonoBuffer;      
 
127
                int32* pEnd = pMonoBuffer + count ;                             
 
128
                int32  x , y , xd , yd , v1 , v2 , tmp ;                
 
129
                for( ; pCur != pEnd ; ++ pCur )
 
130
                {                       
 
131
                        x = *pCur / G ;
 
132
                        
 
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 ) ;
 
137
 
 
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 ) ; ;
 
142
 
 
143
                        y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
 
144
 
 
145
                        *pCur = ( G * x ) + ( pThis->gy * y ) ;
 
146
                        pushval_cirbuff( &(pThis->leftX) , x ) ;
 
147
                        pushval_cirbuff( &(pThis->leftY) , y ) ;
 
148
 
 
149
                        if( pThis->d > d_max )
 
150
                        {
 
151
                                pThis->incr = -abs( pThis->incr ) ;
 
152
                                pThis->d  = d_max ;
 
153
                        }
 
154
                        else if( pThis->d < d_min )
 
155
                        {
 
156
                                pThis->incr = +abs( pThis->incr ) ;
 
157
                                pThis->d = d_min ;
 
158
                        }
 
159
                        else
 
160
                                pThis->d += pThis->incr ;
 
161
                }
 
162
                *pbSignal = 1 ;
 
163
        }
 
164
        else
 
165
        {
 
166
                shift_cirbuff( &( pThis->leftX ) , pThis->m_uiNullCount ) ;     
 
167
                shift_cirbuff( &( pThis->leftY ) , pThis->m_uiNullCount ) ;     
 
168
                pThis->d = d_min ;
 
169
        }
 
170
}
 
171
 
 
172
static void ActionStereo( phaser_effect* pThis , int32* pStereoBuffer , int32 count , int* pbSignal )
 
173
{
 
174
        if( pThis->gy == 0 )
 
175
                return ;
 
176
        if( *pbSignal )
 
177
                pThis->m_uiNullCount = 0 ;
 
178
        else
 
179
                pThis->m_uiNullCount += count ;
 
180
        if( pThis->m_uiNullCount < dieTime )
 
181
        {
 
182
                int32* pCur = pStereoBuffer;    
 
183
                int32* pEnd = pStereoBuffer + 2 * count ;                               
 
184
                int32  x , y , xd , yd , v1 , v2 , tmp ;
 
185
                for( ; pCur != pEnd ; ++ pCur )
 
186
                {                       
 
187
                        x = *pCur / G ;
 
188
                        
 
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 ) ;
 
193
 
 
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 ) ;
 
198
 
 
199
                        y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
 
200
 
 
201
                        *pCur = ( G * x ) + ( pThis->gy * y ) ;
 
202
                        pushval_cirbuff( &(pThis->leftX) , x ) ;
 
203
                        pushval_cirbuff( &(pThis->leftY) , y ) ;
 
204
 
 
205
                        ++pCur;
 
206
 
 
207
                        x = *pCur / G ;
 
208
                        
 
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 ) ;
 
213
 
 
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 ) ;
 
218
 
 
219
                        y = ( ( - gp * x ) + ( gp * yd ) + ( G * xd ) ) / G ;
 
220
 
 
221
                        *pCur = ( G * x ) + ( pThis->gy * y ) ;
 
222
                        pushval_cirbuff( &(pThis->rightX) , x ) ;
 
223
                        pushval_cirbuff( &(pThis->rightY) , y ) ;
 
224
 
 
225
                        if( pThis->d > d_max )
 
226
                        {
 
227
                                pThis->incr = -abs( pThis->incr ) ;
 
228
                                pThis->d  = d_max ;
 
229
                        }
 
230
                        else if( pThis->d < d_min )
 
231
                        {
 
232
                                pThis->incr = +abs( pThis->incr ) ;
 
233
                                pThis->d = d_min ;
 
234
                        }
 
235
                        else
 
236
                                pThis->d += pThis->incr ;
 
237
                }
 
238
                *pbSignal = 1 ;
 
239
        }
 
240
        else
 
241
        {
 
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 ) ;    
 
246
                pThis->d = d_min ;
 
247
        }
 
248
}
 
249
 
 
250
static void CtrlReset( phaser_effect* pThis )
 
251
{
 
252
        pThis->m_uiNullCount = 0 ;
 
253
        redim_cirbuff( &( pThis->leftX ) , 0 ) ;
 
254
        redim_cirbuff( &( pThis->rightX ) , 0 ) ;       
 
255
        
 
256
        pThis->gy = 0 ;
 
257
        
 
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 );
 
260
 
 
261
        pThis->incr = (int32)( ( 2 * ( d_max - d_min ) * FREQU ) / play_mode->rate  );
 
262
        pThis->d =  d_min ;
 
263
        dieTime = (uint32)( ( DIE_TIME  * play_mode->rate ) / 1000 );
 
264
}
 
265
 
 
266
static void CtrlChange( phaser_effect* pThis , MidiEvent* pCurrentEvent )
 
267
{
 
268
        if( pCurrentEvent->b ==  ME_PHASER ||
 
269
            (pCurrentEvent->b ==  ME_CHORUSDEPTH && XG_effect_chorus_is_phaser_flag) )
 
270
        {
 
271
                if( pCurrentEvent->a != 0 )
 
272
                {
 
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 ) )
 
276
                        {
 
277
                                redim_cirbuff( &( pThis->rightX ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
 
278
                                redim_cirbuff( &( pThis->rightY ) , ( d_max >> FRACTION_BITS ) + 1 ) ;
 
279
                        }
 
280
                        pThis->gy = (int32)( G * ( G_MIN  + ( ( 1.0 - G_MIN ) / 126.0 ) * ( pCurrentEvent->a - 1 ) ) );
 
281
                }
 
282
                else
 
283
                        CtrlReset( pThis ) ;
 
284
        }
 
285
}
 
286
 
 
287
static void Name( char* pszBuff )
 
288
{
 
289
        strcpy( pszBuff , "phaser" );
 
290
}
 
291
 
 
292
static void Destruct( phaser_effect* pThis  )
 
293
{
 
294
        delete_cirbuff( &( pThis->leftX ) ) ;
 
295
        delete_cirbuff( &( pThis->rightX ) ) ;
 
296
        delete_cirbuff( &( pThis->leftY ) ) ;
 
297
        delete_cirbuff( &( pThis->rightY ) ) ;
 
298
 
 
299
        memset( pThis , 0 , sizeof( phaser_effect ) ) ;
 
300
        free( pThis ) ;
 
301
}
 
302
 
 
303
 
 
304
/**************************************************************************/
 
305
/**      phaser_effect construction function prototype
 
306
 */
 
307
Effect* PhaserCtor() 
 
308
{
 
309
        phaser_effect* pReturn = 0 ;
 
310
        pReturn = ( phaser_effect* )malloc( sizeof( phaser_effect) ) ;
 
311
        memset( pReturn , 0 , sizeof( phaser_effect ) ) ;
 
312
        
 
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 ;
 
319
 
 
320
        create_cirbuff( &( pReturn->leftX ) , 0 ) ;
 
321
        create_cirbuff( &( pReturn->rightX ) , 0 ) ;
 
322
        create_cirbuff( &( pReturn->leftY ) , 0 ) ;
 
323
        create_cirbuff( &( pReturn->rightY ) , 0 ) ;
 
324
 
 
325
        CtrlReset( pReturn ) ;
 
326
        return ( Effect* )pReturn ;
 
327
}
 
328
 
 
329
 
 
330
 
 
331
 
 
332
 
 
333
 
 
334
#endif /* CHANNEL_EFFECT */