32 |
#include "rtelmemorypool.h" |
#include "rtelmemorypool.h" |
33 |
#include "audiothread.h" |
#include "audiothread.h" |
34 |
#include "filter.h" |
#include "filter.h" |
35 |
|
#include "lfo.h" |
36 |
|
|
37 |
#define MAX_PITCH 4 //FIXME: at the moment in octaves, should be changed into semitones |
#define MAX_PITCH 4 //FIXME: at the moment in octaves, should be changed into semitones |
38 |
#define USE_LINEAR_INTERPOLATION 1 ///< set to 0 if you prefer cubic interpolation (slower, better quality) |
#define USE_LINEAR_INTERPOLATION 1 ///< set to 0 if you prefer cubic interpolation (slower, better quality) |
53 |
/// Reflects a MIDI controller |
/// Reflects a MIDI controller |
54 |
struct midi_ctrl { |
struct midi_ctrl { |
55 |
uint8_t controller; ///< MIDI control change controller number |
uint8_t controller; ///< MIDI control change controller number |
56 |
uint8_t value; ///< Current controller value |
uint8_t value; ///< Current MIDI controller value |
57 |
|
float fvalue; ///< Transformed / effective value (e.g. volume level or filter cutoff frequency) |
58 |
}; |
}; |
59 |
|
|
60 |
class Voice { |
class Voice { |
107 |
GigFilter FilterRight; |
GigFilter FilterRight; |
108 |
midi_ctrl VCFCutoffCtrl; |
midi_ctrl VCFCutoffCtrl; |
109 |
midi_ctrl VCFResonanceCtrl; |
midi_ctrl VCFResonanceCtrl; |
110 |
ModulationSystem::Event* pTriggerEvent; ///< First event on the key's list the voice should process (only needed for the first audio fragment in which voice was triggered, after that it will be set to NULL). |
LFO* pLFO1; |
111 |
|
LFO* pLFO2; |
112 |
|
LFO* pLFO3; |
113 |
|
ModulationSystem::Event* pTriggerEvent; ///< First event on the key's list the voice should process (only needed for the first audio fragment in which voice was triggered, after that it will be set to NULL). |
114 |
|
|
115 |
// Methods |
// Methods |
116 |
void ProcessEvents(uint Samples); |
void ProcessEvents(uint Samples); |
120 |
int pos_int = double_to_int(this->Pos); // integer position |
int pos_int = double_to_int(this->Pos); // integer position |
121 |
float pos_fract = this->Pos - pos_int; // fractional part of position |
float pos_fract = this->Pos - pos_int; // fractional part of position |
122 |
pos_int <<= 1; |
pos_int <<= 1; |
123 |
|
|
124 |
#if ENABLE_FILTER |
#if ENABLE_FILTER |
125 |
UpdateFilter_Stereo(cutoff, resonance); |
UpdateFilter_Stereo(cutoff + 20.0f, resonance); // 20Hz min. |
126 |
#endif // ENABLE_FILTER |
#endif // ENABLE_FILTER |
127 |
|
|
128 |
#if USE_LINEAR_INTERPOLATION |
#if USE_LINEAR_INTERPOLATION |
131 |
this->pOutputLeft[i] += this->FilterLeft.Apply(effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]))); |
this->pOutputLeft[i] += this->FilterLeft.Apply(effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]))); |
132 |
// right channel |
// right channel |
133 |
this->pOutputRight[i++] += this->FilterRight.Apply(effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]))); |
this->pOutputRight[i++] += this->FilterRight.Apply(effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]))); |
134 |
#else // no filter |
#else // no filter |
135 |
// left channel |
// left channel |
136 |
this->pOutputLeft[i] += effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])); |
this->pOutputLeft[i] += effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])); |
137 |
// right channel |
// right channel |
150 |
this->pOutputLeft[i] += this->FilterLeft.Apply(effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0)); |
this->pOutputLeft[i] += this->FilterLeft.Apply(effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0)); |
151 |
#else // no filter |
#else // no filter |
152 |
this->pOutputLeft[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0); |
this->pOutputLeft[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0); |
153 |
#endif // ENABLE_FILTER |
#endif // ENABLE_FILTER |
154 |
|
|
155 |
//calculate right channel |
//calculate right channel |
156 |
xm1 = pSrc[pos_int+1]; |
xm1 = pSrc[pos_int+1]; |
172 |
inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) { |
inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) { |
173 |
int pos_int = double_to_int(this->Pos); // integer position |
int pos_int = double_to_int(this->Pos); // integer position |
174 |
float pos_fract = this->Pos - pos_int; // fractional part of position |
float pos_fract = this->Pos - pos_int; // fractional part of position |
175 |
|
|
176 |
#if ENABLE_FILTER |
#if ENABLE_FILTER |
177 |
UpdateFilter_Mono(cutoff, resonance); |
UpdateFilter_Mono(cutoff + 20.0f, resonance); // 20Hz min. |
178 |
#endif // ENABLE_FILTER |
#endif // ENABLE_FILTER |
179 |
|
|
180 |
#if USE_LINEAR_INTERPOLATION |
#if USE_LINEAR_INTERPOLATION |
188 |
float b = 2 * x1 + xm1 - (5 * x0 + x2) / 2; |
float b = 2 * x1 + xm1 - (5 * x0 + x2) / 2; |
189 |
float c = (x1 - xm1) / 2; |
float c = (x1 - xm1) / 2; |
190 |
float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0); |
float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0); |
191 |
#endif // USE_LINEAR_INTERPOLATION |
#endif // USE_LINEAR_INTERPOLATION |
192 |
|
|
193 |
#if ENABLE_FILTER |
#if ENABLE_FILTER |
194 |
sample_point = this->FilterLeft.Apply(sample_point); |
sample_point = this->FilterLeft.Apply(sample_point); |
195 |
#endif // ENABLE_FILTER |
#endif // ENABLE_FILTER |
196 |
|
|
199 |
|
|
200 |
this->Pos += pitch; |
this->Pos += pitch; |
201 |
} |
} |
202 |
inline void UpdateFilter_Stereo(float& cutoff, float& resonance) { |
inline void UpdateFilter_Stereo(float cutoff, float& resonance) { |
203 |
static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples |
static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples |
204 |
if (!(++updatecounter % FILTER_UPDATE_PERIOD) && cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
if (!(++updatecounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) { |
205 |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
206 |
FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
207 |
} |
} |
208 |
} |
} |
209 |
inline void UpdateFilter_Mono(float& cutoff, float& resonance) { |
inline void UpdateFilter_Mono(float cutoff, float& resonance) { |
210 |
static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples |
static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples |
211 |
if (!(++updatecounter % FILTER_UPDATE_PERIOD) && cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
if (!(++updatecounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) { |
212 |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
213 |
} |
} |
214 |
} |
} |
215 |
inline void ForceUpdateFilter_Stereo(float& cutoff, float& resonance) { |
inline void ForceUpdateFilter_Stereo(float cutoff, float& resonance) { |
216 |
if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
217 |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
218 |
FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
219 |
} |
} |
220 |
} |
} |
221 |
inline void ForceUpdateFilter_Mono(float& cutoff, float& resonance) { |
inline void ForceUpdateFilter_Mono(float cutoff, float& resonance) { |
222 |
if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) { |
223 |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate()); |
224 |
} |
} |
226 |
inline float Constrain(float ValueToCheck, float Min, float Max) { |
inline float Constrain(float ValueToCheck, float Min, float Max) { |
227 |
if (ValueToCheck > Max) ValueToCheck = Max; |
if (ValueToCheck > Max) ValueToCheck = Max; |
228 |
else if (ValueToCheck < Min) ValueToCheck = Min; |
else if (ValueToCheck < Min) ValueToCheck = Min; |
229 |
return ValueToCheck; |
return ValueToCheck; |
230 |
} |
} |
231 |
inline int double_to_int(double f) { |
inline int double_to_int(double f) { |
232 |
#if ARCH_X86 |
#if ARCH_X86 |