void stopNote (bool allowTailOff) { if (allowTailOff) { // start a tail-off by setting this flag. The render callback will pick up on // this and do a fade out, calling clearCurrentNote() when it's finished. if (playing == keyHeld) { // we only need to begin a tail-off if it's not already doing so - the // stopNote method could be called more than once. playing = keyReleased; tailOff = 1.0; } } else { // we're being told to stop playing immediately, so reset everything.. clearCurrentNote(); playing = notPlaying; angleDelta = 0.0; } }
void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) { double (*currentSampleBase)(double currentAngle); if (soundIndex == 0) { currentSampleBase = sineCurrentSampleBase; } else if (soundIndex == 1) { currentSampleBase = squareCurrentSampleBase; } else if (soundIndex == 2) { currentSampleBase = triangleCurrentSampleBase; } else if (soundIndex == 3) { currentSampleBase = sawToothCurrentSampleBase; } else if (soundIndex == 4) { currentSampleBase = FMCurrentSampleBase; } else if (soundIndex == 5) { currentSampleBase = AMCurrentSampleBase; } else if (soundIndex == 6) { currentSampleBase = FMixCurrentSampleBase; } else { assert(false); } if (angleDelta != 0.0) { if (tailOff > 0) { while (--numSamples >= 0) { const float currentSample = (float) (currentSampleBase(currentAngle) * level * tailOff); for (int i = outputBuffer.getNumChannels(); --i >= 0;) *outputBuffer.getSampleData (i, startSample) += currentSample; currentAngle = currentAngle + angleDelta; ++startSample; tailOff *= 0.99; if (tailOff <= 0.005) { clearCurrentNote(); angleDelta = 0.0; break; } } } else { while (--numSamples >= 0) { const float currentSample = (float) (currentSampleBase(currentAngle) * level); for (int i = outputBuffer.getNumChannels(); --i >= 0;) *outputBuffer.getSampleData (i, startSample) += currentSample; currentAngle = currentAngle + angleDelta; ++startSample; } } } }
void renderNextBlock(AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override { Levels levels = envGen->getLevels(); if (angleDelta != 0.0) { if (level > 0) { while (--numSamples >= 0) { // Find where we are in the levels sections and set volume level int currEnvIndex; if (currEnvSection == Attack) { currEnvIndex = (sampleCounter * 100 * levels.attackRate / getSampleRate()); if (currEnvIndex >= 12) { level = levels.sustainValues[0]; currEnvSection = Sustain; sampleCounter = 0; } else { level = levels.attackValues[currEnvIndex]; } } else if (currEnvSection == Sustain) { currEnvIndex = (sampleCounter * 100 * levels.sustainRate / getSampleRate()); if ((!levels.isSustain && currEnvIndex >= 12) || needFinishSustain) { currEnvSection = Release; sampleCounter = 0; level = levels.releaseValues[0]; } else { currEnvIndex %= 12; level = levels.sustainValues[currEnvIndex]; } } else // Release { currEnvIndex = (sampleCounter * 100 * levels.releaseRate / getSampleRate()); if (currEnvIndex >= 12) { level = 0; sampleCounter = 0; } else { level = levels.releaseValues[currEnvIndex]; } } const float currentSample = (float)(sin(currentAngle) * level * 0.15); for (int i = outputBuffer.getNumChannels(); --i >= 0;) outputBuffer.addSample(i, startSample, currentSample); currentAngle += angleDelta; ++startSample; ++sampleCounter; if (level == 0) { clearCurrentNote(); angleDelta = 0.0; currEnvSection = Attack; sampleCounter = 0; break; } } } } }
/** Stop current note. */ void LorisVoice::stop() noexcept { synthesise = false; tailOff = false; clearCurrentNote(); }
void stopNote (const bool allowTailOff) { clearCurrentNote(); angleDelta = 0.0f; }
void SFZVoice::killNote() { region = NULL; clearCurrentNote(); }