void Source::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) { // calculations float trackCutoff = parameters->getUnchecked(Controller::getParameterId(Controller::params::cutoff, trackId))->getScaledValue(); float trackDistort = parameters->getUnchecked(Controller::getParameterId(Controller::params::distort, trackId))->getScaledValue(); float trackLevel = parameters->getUnchecked(Controller::getParameterId(Controller::params::level, trackId))->getScaledValue(); float trackMute = parameters->getUnchecked(Controller::getParameterId(Controller::params::mute, trackId))->getScaledValue(); float globalCutoff = parameters->getUnchecked(Controller::getParameterId(Controller::params::cutoff))->getScaledValue(); float globalDistort = parameters->getUnchecked(Controller::getParameterId(Controller::params::distort))->getScaledValue(); float modulationCutoff = sampler.currentModulations != nullptr ? Parameter::scale(Controller::params::cutoff, true, sampler.currentModulations->getUnchecked(Mixer::mods::cutoff)) : 0.0; float cutoff = fmax(0, fmin(1, trackCutoff + globalCutoff + modulationCutoff)); float distort = 1 - fmax(0, fmin(0.93, trackDistort + globalDistort)); float level = trackLevel * !trackMute; // setup bufferToFill.clearActiveBufferRegion(); midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples); // render sampler sampler.renderNextBlock(*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples); // dsp: distortion float* outL = bufferToFill.buffer->getWritePointer (0, 0); float* outR = bufferToFill.buffer->getWritePointer (1, 0); for (int i=bufferToFill.numSamples; i>=0; --i) { outL[i] = foldback(outL[i], distort); outR[i] = foldback(outR[i], distort); } // dsp: filter filterL.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, MidiMessage::getMidiNoteInHertz(cutoff * 128))); filterR.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, MidiMessage::getMidiNoteInHertz(cutoff * 128))); filterL.processSamples(bufferToFill.buffer->getWritePointer(0), bufferToFill.buffer->getNumSamples()); filterR.processSamples(bufferToFill.buffer->getWritePointer(1), bufferToFill.buffer->getNumSamples()); // dsp: level bufferToFill.buffer->applyGainRamp(0, bufferToFill.numSamples, lastLevel, level); lastLevel = level; }
TEST test_manual_foldback() { // Lower foldback: wrap tonewheels < 13 back into the 13..92 range. for (int i = 1; i < 13; i++) { ASSERT_EQ_FMT(i + 12, foldback(i), "%d"); } // No foldback applied up through tonewheel 92. for (int i = 13; i < 92; i++) { ASSERT_EQ_FMT(i, foldback(i), "%d"); } // Upper foldback: the first octave above 91 is mapped down one octave. for (int i = 92; i < 104; i++) { ASSERT_EQ_FMT(i - 12, foldback(i), "%d"); } // Upper foldback: the next octave is mapped down two octaves. for (int i = 104; i < 116; i++) { ASSERT_EQ_FMT(i - 24, foldback(i), "%d"); } PASS(); }