//============================================================================== void Processor::prepareToPlay(double /*sampleRate*/, int samplesPerBlock) { // Play safe to be clean releaseResources(); // Prepare convolvers { juce::ScopedLock convolverLock(_convolverMutex); _convolverHeadBlockSize = 1; while (_convolverHeadBlockSize < static_cast<size_t>(samplesPerBlock)) { _convolverHeadBlockSize *= 2; } _convolverTailBlockSize = std::max(size_t(8192), 2 * _convolverHeadBlockSize); } // Prepare convolution buffers _wetBuffer.setSize(2, samplesPerBlock); _convolutionBuffer.resize(samplesPerBlock); // Initialize parameters _stereoWidth.initializeWidth(getParameter(Parameters::StereoWidth)); // Initialize IR agents for (size_t i=0; i<_agents.size(); ++i) { _agents[i]->initialize(); } notifyAboutChange(); updateConvolvers(); }
void Processor::setIREnd(double irEnd) { bool changed = false; bool irChanged = false; { juce::ScopedLock convolverLock(_convolverMutex); double irEndClamped = std::min(1.0, std::max(_irBegin, irEnd)); if (::fabs(irEndClamped-irEnd) > 0.0001) { changed = true; } if (::fabs(_irEnd-irEndClamped) > 0.0001) { _irEnd = irEndClamped; changed = true; irChanged = true; } } if (changed) { notifyAboutChange(); } if (irChanged) { updateConvolvers(); } }
void Processor::setParameter(int index, float newValue) { if (_parameterSet.setNormalizedParameter(index, newValue)) { notifyAboutChange(); } }
void Processor::clearConvolvers() { { juce::ScopedLock convolverLock(_convolverMutex); _reverse = false; _predelayMs = 0.0; _stretch = 1.0; _irBegin = 0.0; _irEnd = 1.0; _attackLength = 0.0; _attackShape = 0.0; _decayShape = 0.0; } setParameterNotifyingHost(Parameters::EqLowCutFreq, Parameters::EqLowCutFreq.getDefaultValue()); setParameterNotifyingHost(Parameters::EqLowShelfFreq, Parameters::EqLowShelfFreq.getDefaultValue()); setParameterNotifyingHost(Parameters::EqLowShelfDecibels, Parameters::EqLowShelfDecibels.getDefaultValue()); setParameterNotifyingHost(Parameters::EqHighCutFreq, Parameters::EqHighCutFreq.getDefaultValue()); setParameterNotifyingHost(Parameters::EqHighShelfFreq, Parameters::EqHighShelfFreq.getDefaultValue()); setParameterNotifyingHost(Parameters::EqHighShelfDecibels, Parameters::EqHighShelfDecibels.getDefaultValue()); setParameterNotifyingHost(Parameters::StereoWidth, Parameters::StereoWidth.getDefaultValue()); for (size_t i=0; i<_agents.size(); ++i) { _agents[i]->clear(); } notifyAboutChange(); updateConvolvers(); }
void Processor::releaseResources() { _wetBuffer.setSize(1, 0, false, true, false); _convolutionBuffer.clear(); _beatsPerMinute.set(0); notifyAboutChange(); }
void Processor::setPredelayMs(double predelayMs) { bool changed = false; { juce::ScopedLock convolverLock(_convolverMutex); if (_predelayMs != predelayMs) { _predelayMs = predelayMs; changed = true; } } if (changed) { notifyAboutChange(); updateConvolvers(); } }
void Processor::setReverse(bool reverse) { bool changed = false; { juce::ScopedLock convolverLock(_convolverMutex); if (_reverse != reverse) { _reverse = reverse; changed = true; } } if (changed) { notifyAboutChange(); updateConvolvers(); } }
void Processor::setStretch(double stretch) { bool changed = false; { juce::ScopedLock convolverLock(_convolverMutex); if (::fabs(_stretch-stretch) > 0.000001) { _stretch = stretch; changed = true; } } if (changed) { notifyAboutChange(); updateConvolvers(); } }
void Processor::setDecayShape(double shape) { bool changed = false; { juce::ScopedLock convolverLock(_convolverMutex); if (_decayShape != shape) { _decayShape = shape; changed = true; } } if (changed) { notifyAboutChange(); updateConvolvers(); } }
void Processor::setAttackLength(double length) { bool changed = false; length = std::max(0.0, std::min(1.0, length)); { juce::ScopedLock convolverLock(_convolverMutex); if (_attackLength != length) { _attackLength = length; changed = true; } } if (changed) { notifyAboutChange(); updateConvolvers(); } }
void Processor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& /*midiMessages*/) { const int numInputChannels = getTotalNumInputChannels(); const int numOutputChannels = getTotalNumOutputChannels(); const size_t samplesToProcess = buffer.getNumSamples(); // Determine channel data const float* channelData0 = nullptr; const float* channelData1 = nullptr; if (numInputChannels == 1) { channelData0 = buffer.getReadPointer(0); channelData1 = buffer.getReadPointer(0); } else if (numInputChannels == 2) { channelData0 = buffer.getReadPointer(0); channelData1 = buffer.getReadPointer(1); } // Convolution _wetBuffer.clear(); if (numInputChannels > 0 && numOutputChannels > 0) { float autoGain = 1.0f; if (getParameter(Parameters::AutoGainOn)) { autoGain = DecibelScaling::Db2Gain(getParameter(Parameters::AutoGainDecibels)); } // Convolve IRAgent* irAgent00 = getAgent(0, 0); if (irAgent00 && irAgent00->getConvolver() && numInputChannels >= 1 && numOutputChannels >= 1) { irAgent00->process(channelData0, &_convolutionBuffer[0], samplesToProcess); _wetBuffer.addFrom(0, 0, &_convolutionBuffer[0], samplesToProcess, autoGain); } IRAgent* irAgent01 = getAgent(0, 1); if (irAgent01 && irAgent01->getConvolver() && numInputChannels >= 1 && numOutputChannels >= 2) { irAgent01->process(channelData0, &_convolutionBuffer[0], samplesToProcess); _wetBuffer.addFrom(1, 0, &_convolutionBuffer[0], samplesToProcess, autoGain); } IRAgent* irAgent10 = getAgent(1, 0); if (irAgent10 && irAgent10->getConvolver() && numInputChannels >= 2 && numOutputChannels >= 1) { irAgent10->process(channelData1, &_convolutionBuffer[0], samplesToProcess); _wetBuffer.addFrom(0, 0, &_convolutionBuffer[0], samplesToProcess, autoGain); } IRAgent* irAgent11 = getAgent(1, 1); if (irAgent11 && irAgent11->getConvolver() && numInputChannels >= 2 && numOutputChannels >= 2) { irAgent11->process(channelData1, &_convolutionBuffer[0], samplesToProcess); _wetBuffer.addFrom(1, 0, &_convolutionBuffer[0], samplesToProcess, autoGain); } } // Stereo width if (numOutputChannels >= 2) { _stereoWidth.updateWidth(getParameter(Parameters::StereoWidth)); _stereoWidth.process(_wetBuffer.getWritePointer(0), _wetBuffer.getWritePointer(1), samplesToProcess); } // Dry/wet gain { float dryGain0, dryGain1; _dryGain.updateValue(DecibelScaling::Db2Gain(getParameter(Parameters::DryDecibels))); _dryGain.getSmoothValues(samplesToProcess, dryGain0, dryGain1); buffer.applyGainRamp(0, samplesToProcess, dryGain0, dryGain1); } { float wetGain0, wetGain1; _wetGain.updateValue(DecibelScaling::Db2Gain(getParameter(Parameters::WetDecibels))); _wetGain.getSmoothValues(samplesToProcess, wetGain0, wetGain1); _wetBuffer.applyGainRamp(0, samplesToProcess, wetGain0, wetGain1); } // Level measurement (dry) if (numInputChannels == 1) { _levelMeasurementsDry[0].process(samplesToProcess, buffer.getReadPointer(0)); _levelMeasurementsDry[1].reset(); } else if (numInputChannels == 2) { _levelMeasurementsDry[0].process(samplesToProcess, buffer.getReadPointer(0)); _levelMeasurementsDry[1].process(samplesToProcess, buffer.getReadPointer(1)); } // Sum wet to dry signal { float dryOnGain0, dryOnGain1; _dryOn.updateValue(getParameter(Parameters::DryOn) ? 1.0f : 0.0f); _dryOn.getSmoothValues(samplesToProcess, dryOnGain0, dryOnGain1); buffer.applyGainRamp(0, samplesToProcess, dryOnGain0, dryOnGain1); } { float wetOnGain0, wetOnGain1; _wetOn.updateValue(getParameter(Parameters::WetOn) ? 1.0f : 0.0f); _wetOn.getSmoothValues(samplesToProcess, wetOnGain0, wetOnGain1); if (numOutputChannels > 0) { buffer.addFromWithRamp(0, 0, _wetBuffer.getReadPointer(0), samplesToProcess, wetOnGain0, wetOnGain1); } if (numOutputChannels > 1) { buffer.addFromWithRamp(1, 0, _wetBuffer.getReadPointer(1), samplesToProcess, wetOnGain0, wetOnGain1); } } // Level measurement (wet/out) if (numOutputChannels == 1) { _levelMeasurementsWet[0].process(samplesToProcess, _wetBuffer.getReadPointer(0)); _levelMeasurementsWet[1].reset(); _levelMeasurementsOut[0].process(samplesToProcess, buffer.getReadPointer(0)); _levelMeasurementsOut[1].reset(); } else if (numOutputChannels == 2) { _levelMeasurementsWet[0].process(samplesToProcess, _wetBuffer.getReadPointer(0)); _levelMeasurementsWet[1].process(samplesToProcess, _wetBuffer.getReadPointer(1)); _levelMeasurementsOut[0].process(samplesToProcess, buffer.getReadPointer(0)); _levelMeasurementsOut[1].process(samplesToProcess, buffer.getReadPointer(1)); } // In case we have more outputs than inputs, we'll clear any output // channels that didn't contain input data, (because these aren't // guaranteed to be empty - they may contain garbage). for (int i=numInputChannels; i<numOutputChannels; ++i) { buffer.clear(i, 0, buffer.getNumSamples()); } // Update beats per minute info float beatsPerMinute = 0.0f; juce::AudioPlayHead* playHead = getPlayHead(); if (playHead) { juce::AudioPlayHead::CurrentPositionInfo currentPositionInfo; if (playHead->getCurrentPosition(currentPositionInfo)) { beatsPerMinute = static_cast<float>(currentPositionInfo.bpm); } } if (::fabs(_beatsPerMinute.exchange(beatsPerMinute)-beatsPerMinute) > 0.001f) { notifyAboutChange(); } }
void Property::setReadOnly(const bool& value) { readOnly_ = value; notifyObserversOnSetReadOnly(readOnly_); notifyAboutChange(); }
void Property::setDisplayName(const std::string& displayName) { displayName_ = displayName; notifyObserversOnSetDisplayName(displayName_); notifyAboutChange(); }
void Processor::numChannelsChanged() { juce::AudioProcessor::numChannelsChanged(); notifyAboutChange(); }
void IRAgent::propagateChange() { notifyAboutChange(); _processor.notifyAboutChange(); }
void Property::setVisible(bool val) { visible_ = val; notifyObserversOnSetVisible(visible_); notifyAboutChange(); }
void Property::setUsageMode(UsageMode usageMode) { usageMode_ = usageMode; notifyObserversOnSetUsageMode(usageMode_); notifyAboutChange(); }
void Property::setIdentifier(const std::string& identifier) { identifier_ = identifier; notifyObserversOnSetIdentifier(identifier_); notifyAboutChange(); }
void Property::setSemantics(const PropertySemantics& semantics) { semantics_ = semantics; notifyObserversOnSetSemantics(semantics_); notifyAboutChange(); }