Run/process function for plugins without MIDI input. `inputs` is commented out because this plugin has no inputs. */
| 270 | `inputs` is commented out because this plugin has no inputs. |
| 271 | */ |
| 272 | void run(const float** /* inputs */, float** outputs, uint32_t frames) override |
| 273 | { |
| 274 | const TimePosition& timePos(getTimePosition()); |
| 275 | float* const output = outputs[0]; |
| 276 | |
| 277 | if (timePos.playing && timePos.bbt.valid) |
| 278 | { |
| 279 | // Better to use double when manipulating time. |
| 280 | double secondsPerBeat = 60.0 / timePos.bbt.beatsPerMinute; |
| 281 | double framesPerBeat = sampleRate * secondsPerBeat; |
| 282 | double beatFraction = timePos.bbt.tick / timePos.bbt.ticksPerBeat; |
| 283 | |
| 284 | // If beatFraction is zero, next beat is exactly at the start of currenct cycle. |
| 285 | // Otherwise, reset counter to the frames to the next beat. |
| 286 | counter = d_isZero(beatFraction) |
| 287 | ? 0 |
| 288 | : static_cast<uint32_t>(framesPerBeat * (1.0 - beatFraction)); |
| 289 | |
| 290 | // Compute deltaPhase in normalized frequency. |
| 291 | // semitone is midi note number, which is A4 (440Hz at standard tuning) at 69. |
| 292 | // Frequency goes up to 1 octave higher at the start of bar. |
| 293 | float frequency = 440.0f * std::pow(2.0f, (100.0f * (semitone - 69.0f) + cent) / 1200.0f); |
| 294 | float deltaPhase = frequency / sampleRate; |
| 295 | float octave = timePos.bbt.beat == 1 ? 2.0f : 1.0f; |
| 296 | |
| 297 | // Envelope reaches 1e-5 at decayTime after triggering. |
| 298 | decay = std::pow(1e-5, 1.0 / (decayTime * sampleRate)); |
| 299 | |
| 300 | // Reset phase and frequency at the start of transpose. |
| 301 | if (!wasPlaying) |
| 302 | { |
| 303 | phase = 0.0f; |
| 304 | |
| 305 | deltaPhaseSmoother.value = deltaPhase; |
| 306 | envelopeSmoother.value = 0.0f; |
| 307 | gainSmoother.value = 0.0f; |
| 308 | } |
| 309 | |
| 310 | for (uint32_t i = 0; i < frames; ++i) |
| 311 | { |
| 312 | if (counter <= 0) |
| 313 | { |
| 314 | envelope = 1.0f; |
| 315 | counter = static_cast<uint32_t>(framesPerBeat + 0.5); |
| 316 | octave = (!wasPlaying || timePos.bbt.beat == static_cast<int32_t>(timePos.bbt.beatsPerBar)) ? 2.0f |
| 317 | : 1.0f; |
| 318 | } |
| 319 | --counter; |
| 320 | |
| 321 | envelope *= decay; |
| 322 | |
| 323 | phase += octave * deltaPhaseSmoother.process(deltaPhase); |
| 324 | phase -= std::floor(phase); |
| 325 | |
| 326 | output[i] = gainSmoother.process(gain) |
| 327 | * envelopeSmoother.process(envelope) |
| 328 | * std::sin(float(2.0 * M_PI) * phase); |
| 329 | } |