oscillator.cpp (11234B)
1 2 #include "oscillator.hpp" 3 #include "noise.hpp" 4 5 using namespace bogaudio::dsp; 6 7 void Phasor::setSampleWidth(float sw) { 8 if (sw < 0.0f) { 9 sw = 0.0f; 10 } 11 else if (sw > maxSampleWidth) { 12 sw = maxSampleWidth; 13 } 14 if (_sampleWidth != sw) { 15 _sampleWidth = sw; 16 if (_sampleWidth > 0.001f) { 17 _samplePhase = _sampleWidth * (float)cyclePhase; 18 } 19 else { 20 _samplePhase = 0; 21 } 22 } 23 } 24 25 void Phasor::resetPhase() { 26 _phase = 0; 27 } 28 29 void Phasor::setPhase(float radians) { 30 _phase = radiansToPhase(radians); 31 } 32 33 void Phasor::syncPhase(const Phasor& phasor) { 34 _phase = phasor._phase; 35 } 36 37 float Phasor::nextFromPhasor(const Phasor& phasor, phase_delta_t offset) { 38 offset += phasor._phase; 39 if (_samplePhase > 0) { 40 offset -= offset % _samplePhase; 41 } 42 return nextForPhase(offset); 43 } 44 45 void Phasor::_update() { 46 _delta = ((phase_delta_t)((_frequency / _sampleRate) * cyclePhase)) % cyclePhase; 47 } 48 49 float Phasor::_next() { 50 advancePhase(); 51 if (_samplePhase > 0) { 52 return nextForPhase(_phase - (_phase % _samplePhase)); 53 } 54 return nextForPhase(_phase); 55 } 56 57 float Phasor::nextForPhase(phase_t phase) { 58 return phase; 59 } 60 61 62 void TablePhasor::setInterpolation(Interpolation interpolation) { 63 _interpolation = interpolation; 64 } 65 66 float TablePhasor::nextForPhase(phase_t phase) { 67 phase %= cyclePhase; 68 if (_interpolation == INTERPOLATION_OFF || (_interpolation == INTERPOLATION_DEFAULT && _tableLength >= 1024)) { 69 int i = (((((uint64_t)phase) << 16) / cyclePhase) * _tableLength) >> 16; 70 i %= _tableLength; 71 return _table.value(i); 72 } 73 74 float fi = phase / (float)cyclePhase; 75 assert(fi >= 0.0f && fi < 1.0f); 76 fi *= _tableLength; 77 int i = fi; 78 float v1 = _table.value(i); 79 float v2 = _table.value(i + 1 == _tableLength ? 0 : i + 1); 80 return v1 + (fi - i)*(v2 - v1); 81 } 82 83 84 // A New Recursive Quadrature Oscillator, Martin Vicanek, 2015 - http://vicanek.de/articles/QuadOsc.pdf 85 void SineOscillator::setPhase(double phase) { 86 _x = cos(phase); 87 _y = sin(phase); 88 } 89 90 void SineOscillator::update() { 91 double w = (_frequency / _sampleRate) * 2.0 * M_PI; 92 _k1 = tan(w / 2.0); 93 _k2 = 2.0 * _k1 / (1 + _k1*_k1); 94 } 95 96 float SineOscillator::_next() { 97 double t = _x - _k1*_y; 98 _y = _y + _k2*t; 99 _x = t - _k1*_y; 100 return _y; 101 } 102 103 104 float SawOscillator::nextForPhase(phase_t phase) { 105 return ((phase % cyclePhase) / (float)cyclePhase) * 2.0f - 1.0f; 106 } 107 108 109 void SaturatingSawOscillator::setSaturation(float saturation) { 110 if (_saturation != saturation) { 111 assert(saturation >= 0.0f); 112 _saturation = saturation; 113 if (_saturation >= 0.1f) { 114 if (_saturation < 1.0f) { 115 _saturationNormalization = 1.0f / tanhf(_saturation * M_PI); 116 } 117 else { 118 _saturationNormalization = 1.0f; 119 } 120 } 121 } 122 } 123 124 float SaturatingSawOscillator::nextForPhase(phase_t phase) { 125 float sample = SawOscillator::nextForPhase(phase); 126 if (_saturation >= 0.1f) { 127 sample = _tanhf.value(sample * _saturation * M_PI) * _saturationNormalization; 128 } 129 return sample; 130 } 131 132 133 void BandLimitedSawOscillator::setQuality(int quality) { 134 if (_quality != quality) { 135 assert(quality >= 0); 136 _quality = quality; 137 _update(); 138 } 139 } 140 141 void BandLimitedSawOscillator::_update() { 142 Phasor::_update(); 143 int q = std::min(_quality, (int)(0.5f * (_sampleRate / _frequency))); 144 _qd = q * _delta; 145 } 146 147 float BandLimitedSawOscillator::nextForPhase(phase_t phase) { 148 phase %= cyclePhase; 149 150 float sample = SaturatingSawOscillator::nextForPhase(phase); 151 if (phase > cyclePhase - _qd) { 152 float i = (cyclePhase - phase) / (float)_qd; 153 i = (1.0f - i) * _halfTableLen; 154 sample -= _table.value((int)i); 155 } 156 else if (phase < _qd) { 157 float i = phase / (float)_qd; 158 i *= _halfTableLen - 1; 159 i += _halfTableLen; 160 sample -= _table.value((int)i); 161 } 162 return sample; 163 } 164 165 166 void SquareOscillator::setPulseWidth(float pw) { 167 if (_pulseWidthInput == pw) { 168 return; 169 } 170 _pulseWidthInput = pw; 171 172 if (pw >= maxPulseWidth) { 173 pw = maxPulseWidth; 174 } 175 else if (pw <= minPulseWidth) { 176 pw = minPulseWidth; 177 } 178 _nextPulseWidth = cyclePhase * pw; 179 } 180 181 float SquareOscillator::nextForPhase(phase_t phase) { 182 phase_t cycle = phase / cyclePhase; 183 if (_lastCycle != cycle) { 184 _lastCycle = cycle; 185 _pulseWidth = _nextPulseWidth; 186 } 187 phase %= cyclePhase; 188 189 if (positive) { 190 if (phase >= _pulseWidth) { 191 positive = false; 192 return -1.0f; 193 } 194 return 1.0f; 195 } 196 if (phase < _pulseWidth) { 197 positive = true; 198 return 1.0f; 199 } 200 return -1.0f; 201 } 202 203 204 void BandLimitedSquareOscillator::setPulseWidth(float pw, bool dcCorrection) { 205 if (_pulseWidthInput == pw && _dcCorrection == dcCorrection) { 206 return; 207 } 208 _pulseWidthInput = pw; 209 _dcCorrection = dcCorrection; 210 211 if (pw >= maxPulseWidth) { 212 pw = maxPulseWidth; 213 } 214 else if (pw <= minPulseWidth) { 215 pw = minPulseWidth; 216 } 217 _nextPulseWidth = cyclePhase * pw; 218 219 if (pw > 0.5) { 220 _nextOffset = 2.0f * pw - 1.0f; 221 } 222 else { 223 _nextOffset = -(1.0f - 2.0f * pw); 224 } 225 226 _nextDcOffset = _dcCorrection ? 1.0f - 2.0f * pw : 0.0f; 227 } 228 229 float BandLimitedSquareOscillator::nextForPhase(phase_t phase) { 230 phase_t cycle = phase / cyclePhase; 231 if (_lastCycle != cycle) { 232 _lastCycle = cycle; 233 _pulseWidth = _nextPulseWidth; 234 _offset = _nextOffset; 235 _dcOffset = _nextDcOffset; 236 } 237 238 float sample = -BandLimitedSawOscillator::nextForPhase(phase); 239 sample += BandLimitedSawOscillator::nextForPhase(phase - _pulseWidth); 240 return sample + _offset + _dcOffset; 241 } 242 243 244 float TriangleOscillator::nextForPhase(phase_t phase) { 245 phase %= cyclePhase; 246 247 float p = (phase / (float)cyclePhase) * 4.0f; 248 if (phase < quarterCyclePhase) { 249 return p; 250 } 251 if (phase < threeQuartersCyclePhase) { 252 return 2.0f - p; 253 } 254 return p - 4.0f; 255 } 256 257 258 SteppedRandomOscillator::SteppedRandomOscillator( 259 float sampleRate, 260 float frequency, 261 phase_t seed 262 ) 263 : Phasor(sampleRate, frequency) 264 , _n(4096) 265 , _k(4093) // prime less than _n 266 { 267 if (seed == 0) { 268 _seed = Seeds::getInstance().next(); 269 } 270 else { 271 _seed = seed; 272 } 273 274 WhiteNoiseGenerator noise; 275 _t = new float[_n]; 276 for (phase_t i = 0; i < _n; ++i) { 277 _t[i] = noise.next(); 278 } 279 } 280 281 SteppedRandomOscillator::~SteppedRandomOscillator() { 282 delete[] _t; 283 } 284 285 void SteppedRandomOscillator::resetPhase() { 286 _phase -= _phase % cyclePhase; 287 _phase += cyclePhase; 288 } 289 290 float SteppedRandomOscillator::nextForPhase(phase_t phase) { 291 phase_t i = phase / cyclePhase; 292 return _t[(_seed + i + (_seed + i) % _k) % _n]; 293 } 294 295 296 void SineBankOscillator::setPartial(int i, float frequencyRatio, float amplitude) { 297 setPartialFrequencyRatio(i, frequencyRatio); 298 setPartialAmplitude(i, amplitude); 299 } 300 301 bool SineBankOscillator::setPartialFrequencyRatio(int i, float frequencyRatio) { 302 if (i <= (int)_partials.size()) { 303 Partial& p = _partials[i - 1]; 304 p.frequencyRatio = frequencyRatio; 305 double f = (double)_frequency * (double)frequencyRatio; 306 p.frequency = f; 307 p.sine.setFrequency(f); 308 return f < _maxPartialFrequency; 309 } 310 return false; 311 } 312 313 void SineBankOscillator::setPartialAmplitude(int i, float amplitude, bool envelope) { 314 if (i <= (int)_partials.size()) { 315 Partial& p = _partials[i - 1]; 316 if (envelope) { 317 p.amplitudeTarget = amplitude; 318 p.amplitudeStepDelta = (amplitude - p.amplitude) / (float)_amplitudeEnvelopeSamples; 319 p.amplitudeSteps = _amplitudeEnvelopeSamples; 320 } 321 else if (p.amplitudeSteps > 0) { 322 p.amplitudeTarget = amplitude; 323 p.amplitudeStepDelta = (amplitude - p.amplitude) / (float)p.amplitudeSteps; 324 } 325 else { 326 p.amplitude = amplitude; 327 } 328 } 329 } 330 331 void SineBankOscillator::syncToPhase(float phase) { 332 for (Partial& p : _partials) { 333 p.sine.setPhase(phase); 334 } 335 } 336 337 void SineBankOscillator::syncTo(const SineBankOscillator& other) { 338 for (int i = 0, n = std::min(_partials.size(), other._partials.size()); i < n; ++i) { 339 _partials[i].sine.syncPhase(other._partials[i].sine); 340 } 341 } 342 343 void SineBankOscillator::_sampleRateChanged() { 344 _maxPartialFrequency = _maxPartialFrequencySRRatio * _sampleRate; 345 _amplitudeEnvelopeSamples = _sampleRate * (_amplitudeEnvelopeMS / 1000.0f); 346 for (Partial& p : _partials) { 347 p.sine.setSampleRate(_sampleRate); 348 } 349 } 350 351 void SineBankOscillator::_frequencyChanged() { 352 for (Partial& p : _partials) { 353 p.frequency = _frequency * p.frequencyRatio; 354 p.sine.setFrequency(_frequency * p.frequencyRatio); 355 } 356 } 357 358 float SineBankOscillator::next(Phasor::phase_t phaseOffset) { 359 float next = 0.0; 360 for (Partial& p : _partials) { 361 p.sine.advancePhase(); 362 if (p.frequency < _maxPartialFrequency && (p.amplitude > 0.001 || p.amplitude < -0.001 || p.amplitudeSteps > 0)) { 363 if (p.amplitudeSteps > 0) { 364 if (p.amplitudeSteps == 1) { 365 p.amplitude = p.amplitudeTarget; 366 } 367 else { 368 p.amplitude += p.amplitudeStepDelta; 369 } 370 --p.amplitudeSteps; 371 } 372 next += p.sine.nextFromPhasor(p.sine, phaseOffset) * p.amplitude; 373 } 374 } 375 return next; 376 } 377 378 379 constexpr float ChirpOscillator::minFrequency; 380 constexpr float ChirpOscillator::minTimeSeconds; 381 382 void ChirpOscillator::setParams(float frequency1, float frequency2, float time, bool linear) { 383 frequency1 = std::max(minFrequency, std::min(frequency1, 0.99f * 0.5f * _sampleRate)); 384 frequency2 = std::max(minFrequency, std::min(frequency2, 0.99f * 0.5f * _sampleRate)); 385 assert(time >= minTimeSeconds); 386 387 if (_f1 != frequency1 || _f2 != frequency2 || _Time != time || _linear != linear) { 388 _f1 = frequency1; 389 _f2 = frequency2; 390 _Time = time; 391 _linear = linear; 392 393 _k = pow((double)(_f2 / _f1), 1.0f / (double)_Time); 394 } 395 } 396 397 void ChirpOscillator::_sampleRateChanged() { 398 _oscillator.setSampleRate(_sampleRate); 399 _sampleTime = 1.0f / _sampleRate; 400 } 401 402 float ChirpOscillator::_next() { 403 _complete = false; 404 if (_time > _Time) { 405 _time = 0.0f; 406 _complete = true; 407 } 408 else { 409 _time += _sampleTime; 410 } 411 412 if (_linear) { 413 _oscillator.setFrequency(_f1 + (_time / _Time) * (_f2 - _f1)); 414 } 415 else { 416 _oscillator.setFrequency((double)_f1 * pow(_k, (double)_time)); 417 } 418 return _oscillator.next(); 419 } 420 421 void ChirpOscillator::reset() { 422 _time = 0.0f; 423 _oscillator.resetPhase(); 424 } 425 426 427 constexpr float PureChirpOscillator::minFrequency; 428 constexpr float PureChirpOscillator::minTimeSeconds; 429 430 void PureChirpOscillator::setParams(float frequency1, float frequency2, double time, bool linear) { 431 frequency1 = std::max(minFrequency, std::min(frequency1, 0.99f * 0.5f * _sampleRate)); 432 frequency2 = std::max(minFrequency, std::min(frequency2, 0.99f * 0.5f * _sampleRate)); 433 assert(time >= minTimeSeconds); 434 435 if (_f1 != frequency1 || _f2 != frequency2 || _Time != time || _linear != linear) { 436 _f1 = frequency1; 437 _f2 = frequency2; 438 _Time = time; 439 _linear = linear; 440 update(); 441 } 442 } 443 444 void PureChirpOscillator::_sampleRateChanged() { 445 _sampleTime = 1.0 / (double)_sampleRate; 446 update(); 447 } 448 449 void PureChirpOscillator::update() { 450 _Time = std::max(2.0f * _sampleTime, _Time); 451 _c = (double)(_f2 - _f1) / (double)_Time; 452 _k = pow((double)(_f2 / _f1), 1.0f / (double)_Time); 453 _invlogk = 1.0 / log(_k); 454 } 455 456 float PureChirpOscillator::_next() { 457 // formulas from https://en.wikipedia.org/wiki/Chirp 458 double phase = 0.0f; 459 if (_linear) { 460 phase = 2.0 * M_PI * (0.5 * _c * (double)(_time * _time) + (double)(_f1 * _time)); 461 } 462 else { 463 phase = 2.0 * M_PI * (double)_f1 * ((pow(_k, (double)_time) - 1.0) * _invlogk); 464 } 465 466 _complete = false; 467 if (_Time - _time < _sampleTime) { 468 _time = 0.0f; 469 _complete = true; 470 } 471 else { 472 _time += _sampleTime; 473 } 474 475 return sin(phase); 476 } 477 478 void PureChirpOscillator::reset() { 479 _time = 0.0f; 480 }