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

« back to all changes in this revision

Viewing changes to arts/modules/synth_pitch_shift_impl.cc

  • 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
 
 
3
        Copyright (C) 2000 Jeff Tranter
 
4
                                   tranter@pobox.com
 
5
 
 
6
                          (C) 1999 Stefan Westerfeld
 
7
                       stefan@space.twc.de
 
8
 
 
9
    This program is free software; you can redistribute it and/or modify
 
10
    it under the terms of the GNU General Public License as published by
 
11
    the Free Software Foundation; either version 2 of the License, or
 
12
    (at your option) any later version.
 
13
 
 
14
    This program is distributed in the hope that it will be useful,
 
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
    GNU General Public License for more details.
 
18
 
 
19
    You should have received a copy of the GNU General Public License
 
20
    along with this program; if not, write to the Free Software
 
21
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
22
 
 
23
    */
 
24
 
 
25
#include <math.h>
 
26
#include "artsmodules.h"
 
27
#include "stdsynthmodule.h"
 
28
 
 
29
using namespace Arts;
 
30
 
 
31
class Synth_PITCH_SHIFT_impl : virtual public Synth_PITCH_SHIFT_skel,
 
32
                                                           virtual public StdSynthModule
 
33
{
 
34
protected:
 
35
        float _speed, _frequency;
 
36
 
 
37
        static const int MAXDELAY = 44100;
 
38
        float *dbuffer;
 
39
        float lfopos, b1pos, b2pos, b1inc, b2inc;
 
40
        bool b1reset, b2reset, initialized;
 
41
        int dbpos;
 
42
 
 
43
public:
 
44
        float speed() { return _speed; }
 
45
        void speed(float newSpeed) { _speed = newSpeed; }
 
46
 
 
47
        float frequency() { return _frequency; }
 
48
        void frequency(float newFrequency) { _frequency = newFrequency; }
 
49
 
 
50
 
 
51
        void streamInit()
 
52
        {
 
53
                dbuffer = new float[MAXDELAY];
 
54
                for (dbpos=0; dbpos<MAXDELAY; dbpos++)
 
55
                        dbuffer[dbpos] = 0;
 
56
 
 
57
                dbpos = 0;
 
58
                initialized = false;
 
59
                lfopos = 0;
 
60
        }
 
61
        void streamEnd()
 
62
        {
 
63
                delete[] dbuffer;
 
64
        }
 
65
 
 
66
        void calculateBlock(unsigned long samples)
 
67
        {
 
68
                float *outend = outvalue + samples;
 
69
                float fsr = (float)samplingRate;
 
70
                float pi2 = 2*M_PI;
 
71
                float lfo, b1value, b2value;
 
72
                float lfoposinc = _frequency / fsr;
 
73
 
 
74
                if (!initialized)
 
75
                {
 
76
                        if (_speed <= 1.0) {
 
77
                                b1pos = b2pos = 0.0;
 
78
                                b1inc = b2inc = 1.0 - _speed;
 
79
                        } else {
 
80
                                /* not yet sure what would be a nice initialization here? */
 
81
                                b1pos = b2pos = 0.0;
 
82
                                b1inc = b2inc = 0.0;
 
83
                        }
 
84
                        initialized = true;
 
85
                }
 
86
 
 
87
                while (outvalue < outend)
 
88
                {
 
89
                        /*
 
90
                         * fill delay buffer with the input signal
 
91
                         */
 
92
                        dbuffer[dbpos] = *invalue++;
 
93
 
 
94
                        lfopos += lfoposinc;
 
95
                        lfopos -= floor(lfopos);
 
96
 
 
97
                        if (lfopos < 0.25) {
 
98
                                b1reset = b2reset = false;
 
99
                        }
 
100
 
 
101
                        /*
 
102
                         * _speed < 1.0 (downpitching)
 
103
                         *
 
104
                         *  start with current sample and increase delay slowly
 
105
                         *
 
106
                         * _speed > 1.0 (uppitching)
 
107
                         *
 
108
                         *  start with a sample from long ago and slowly decrease delay
 
109
                         */
 
110
                        if (!b1reset && lfopos > 0.25) {
 
111
                                if (_speed <= 1.0) {
 
112
                                        b1pos = 0;
 
113
                                        b1inc = 1 - _speed;
 
114
                                } else {
 
115
                                        b1inc = 1 - _speed;
 
116
                                        b1pos = 10 + ((-b1inc) * (1 / lfoposinc));
 
117
                                        /* 10+ are not strictly necessary */
 
118
                                }
 
119
                                b1reset = true;
 
120
                        }
 
121
 
 
122
                        if (!b2reset && lfopos > 0.75) {
 
123
                                if (_speed <= 1.0) {
 
124
                                        b2pos = 0;
 
125
                                        b2inc = 1 - _speed;
 
126
                                } else{
 
127
                                        b2inc = 1 - _speed;
 
128
                                        b2pos = 10 + ((-b2inc) * (1/lfoposinc));
 
129
                                        /* 10+ are not strictly necessary */
 
130
                                }
 
131
                                b2reset = true;
 
132
                        }
 
133
 
 
134
                        b1pos += b1inc;
 
135
                        b2pos += b2inc;
 
136
 
 
137
                        int position, position1;
 
138
                        double error,int_pos;
 
139
 
 
140
                        /*
 
141
                         * Interpolate value from buffer position 1
 
142
                         */
 
143
                        error = modf(b1pos, &int_pos);
 
144
        
 
145
                        position = dbpos - (int)int_pos;
 
146
                        if (position < 0)
 
147
                                position += MAXDELAY;
 
148
                        position1 = position - 1;
 
149
                        if (position1 < 0)
 
150
                                position1 += MAXDELAY;
 
151
 
 
152
                        b1value = dbuffer[position] * (1 - error) + dbuffer[position1] * error;
 
153
 
 
154
                        /*
 
155
                         * Interpolate value from buffer position 2
 
156
                         */
 
157
                        error = modf(b2pos,&int_pos);
 
158
        
 
159
                        position = dbpos - (int)int_pos;
 
160
                        if (position < 0)
 
161
                                position += MAXDELAY;
 
162
                        position1 = position-1;
 
163
                        if ( position1 < 0)
 
164
                                position1 += MAXDELAY;
 
165
 
 
166
                        b2value = dbuffer[position]*(1-error) + dbuffer[position1]*error;
 
167
 
 
168
                        /*
 
169
                         * Calculate output signal from these two buffers
 
170
                         */
 
171
 
 
172
                        lfo = (sin(pi2 * lfopos) + 1) / 2;
 
173
 
 
174
                        /*             position    sin   lfo variable
 
175
                         *------------------------------------------------------------------
 
176
                         * lfo value:    0.25       1         1        => buffer 2 is used
 
177
                         *               0.75      -1         0        => buffer 1 is used
 
178
                         */
 
179
                        
 
180
                        *outvalue++ = b1value * (1.0 - lfo) + b2value * lfo;
 
181
                        
 
182
                        /*
 
183
                         * increment delay buffer position
 
184
                         */
 
185
                        dbpos++;
 
186
                        if (dbpos == MAXDELAY)
 
187
                                dbpos = 0;
 
188
                }
 
189
        }
 
190
};
 
191
 
 
192
REGISTER_IMPLEMENTATION(Synth_PITCH_SHIFT_impl);