mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
LinearSmoothedValue: Added some helpful member functions and deprecated setValue
This commit is contained in:
parent
097525ba5b
commit
b8278cec0e
11 changed files with 105 additions and 79 deletions
|
|
@ -722,9 +722,9 @@ public:
|
|||
jassert (currentlyPlayingNote.keyState == MPENote::keyDown
|
||||
|| currentlyPlayingNote.keyState == MPENote::keyDownAndSustained);
|
||||
|
||||
level.setValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
frequency.setValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
timbre.setValue (currentlyPlayingNote.timbre.asUnsignedFloat());
|
||||
level .setTargetValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
frequency.setTargetValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
timbre .setTargetValue (currentlyPlayingNote.timbre.asUnsignedFloat());
|
||||
|
||||
phase = 0.0;
|
||||
auto cyclesPerSample = frequency.getNextValue() / currentSampleRate;
|
||||
|
|
@ -756,17 +756,17 @@ public:
|
|||
|
||||
void notePressureChanged() override
|
||||
{
|
||||
level.setValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
level.setTargetValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
}
|
||||
|
||||
void notePitchbendChanged() override
|
||||
{
|
||||
frequency.setValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
frequency.setTargetValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
}
|
||||
|
||||
void noteTimbreChanged() override
|
||||
{
|
||||
timbre.setValue (currentlyPlayingNote.timbre.asUnsignedFloat());
|
||||
timbre.setTargetValue (currentlyPlayingNote.timbre.asUnsignedFloat());
|
||||
}
|
||||
|
||||
void noteKeyStateChanged() override {}
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ public:
|
|||
void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int) override
|
||||
{
|
||||
frequency = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
|
||||
phaseIncrement.setValue (((MathConstants<double>::twoPi) * frequency) / sampleRate);
|
||||
amplitude.setValue (velocity);
|
||||
phaseIncrement.setTargetValue (((MathConstants<double>::twoPi) * frequency) / sampleRate);
|
||||
amplitude.setTargetValue (velocity);
|
||||
|
||||
// Store the initial note and work out the maximum frequency deviations for pitch bend
|
||||
initialNote = midiNoteNumber;
|
||||
|
|
@ -77,14 +77,14 @@ public:
|
|||
void stopNote (float, bool) override
|
||||
{
|
||||
clearCurrentNote();
|
||||
amplitude.setValue (0.0);
|
||||
amplitude.setTargetValue (0.0);
|
||||
}
|
||||
|
||||
void pitchWheelMoved (int newValue) override
|
||||
{
|
||||
// Change the phase increment based on pitch bend amount
|
||||
auto frequencyOffset = ((newValue > 0 ? maxFreq : minFreq) * (newValue / 127.0));
|
||||
phaseIncrement.setValue (((MathConstants<double>::twoPi) * (frequency + frequencyOffset)) / sampleRate);
|
||||
phaseIncrement.setTargetValue (((MathConstants<double>::twoPi) * (frequency + frequencyOffset)) / sampleRate);
|
||||
}
|
||||
|
||||
void controllerMoved (int, int) override {}
|
||||
|
|
@ -92,7 +92,7 @@ public:
|
|||
void channelPressureChanged (int newChannelPressureValue) override
|
||||
{
|
||||
// Set the amplitude based on pressure value
|
||||
amplitude.setValue (newChannelPressureValue / 127.0);
|
||||
amplitude.setTargetValue (newChannelPressureValue / 127.0);
|
||||
}
|
||||
|
||||
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
|
||||
|
|
|
|||
|
|
@ -250,12 +250,12 @@ public:
|
|||
jassert (currentlyPlayingNote.keyState == MPENote::keyDown
|
||||
|| currentlyPlayingNote.keyState == MPENote::keyDownAndSustained);
|
||||
|
||||
level .setValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
frequency.setValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
level .setTargetValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
frequency.setTargetValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
|
||||
auto loopPoints = samplerSound->getLoopPointsInSeconds();
|
||||
loopBegin.setValue (loopPoints.getStart() * samplerSound->getSample()->getSampleRate());
|
||||
loopEnd .setValue (loopPoints.getEnd() * samplerSound->getSample()->getSampleRate());
|
||||
loopBegin.setTargetValue (loopPoints.getStart() * samplerSound->getSample()->getSampleRate());
|
||||
loopEnd .setTargetValue (loopPoints.getEnd() * samplerSound->getSample()->getSampleRate());
|
||||
|
||||
for (auto smoothed : { &level, &frequency, &loopBegin, &loopEnd })
|
||||
smoothed->reset (currentSampleRate, smoothingLengthInSeconds);
|
||||
|
|
@ -276,12 +276,12 @@ public:
|
|||
|
||||
void notePressureChanged() override
|
||||
{
|
||||
level.setValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
level.setTargetValue (currentlyPlayingNote.pressure.asUnsignedFloat());
|
||||
}
|
||||
|
||||
void notePitchbendChanged() override
|
||||
{
|
||||
frequency.setValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
frequency.setTargetValue (currentlyPlayingNote.getFrequencyInHertz());
|
||||
}
|
||||
|
||||
void noteTimbreChanged() override {}
|
||||
|
|
@ -294,8 +294,8 @@ public:
|
|||
jassert (samplerSound->getSample() != nullptr);
|
||||
|
||||
auto loopPoints = samplerSound->getLoopPointsInSeconds();
|
||||
loopBegin.setValue (loopPoints.getStart() * samplerSound->getSample()->getSampleRate());
|
||||
loopEnd .setValue (loopPoints.getEnd() * samplerSound->getSample()->getSampleRate());
|
||||
loopBegin.setTargetValue (loopPoints.getStart() * samplerSound->getSample()->getSampleRate());
|
||||
loopEnd .setTargetValue (loopPoints.getEnd() * samplerSound->getSample()->getSampleRate());
|
||||
|
||||
auto& data = samplerSound->getSample()->getBuffer();
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace juce
|
|||
//==============================================================================
|
||||
/**
|
||||
Utility class for linearly smoothed values like volume etc. that should
|
||||
not change abruptly but as a linear ramp, to avoid audio glitches.
|
||||
not change abruptly but as a linear ramp to avoid audio glitches.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
|
|
@ -44,43 +44,50 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Reset to a new sample rate and ramp length.
|
||||
@param sampleRate The sampling rate
|
||||
@param rampLengthInSeconds The duration of the ramp in seconds
|
||||
/** Set a new sample rate and ramp length in seconds.
|
||||
@param sampleRate The sampling rate
|
||||
@param rampLengthInSeconds The duration of the ramp in seconds
|
||||
*/
|
||||
void reset (double sampleRate, double rampLengthInSeconds) noexcept
|
||||
{
|
||||
jassert (sampleRate > 0 && rampLengthInSeconds >= 0);
|
||||
stepsToTarget = (int) std::floor (rampLengthInSeconds * sampleRate);
|
||||
currentValue = target;
|
||||
countdown = 0;
|
||||
reset ((int) std::floor (rampLengthInSeconds * sampleRate));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Set a new target value.
|
||||
|
||||
@param newValue The new target value
|
||||
@param force If true, the value will be set immediately, bypassing the ramp
|
||||
/** Set a new ramp length directly in samples.
|
||||
@param numSteps The number of samples over which the ramp should be active
|
||||
*/
|
||||
void setValue (FloatType newValue, bool force = false) noexcept
|
||||
void reset (int numSteps) noexcept
|
||||
{
|
||||
if (force)
|
||||
stepsToTarget = numSteps;
|
||||
setCurrentValueToTargetValue();
|
||||
}
|
||||
|
||||
/** Set the next value to ramp towards.
|
||||
@param newValue The new target value
|
||||
*/
|
||||
void setTargetValue (FloatType newValue) noexcept
|
||||
{
|
||||
if (target == newValue)
|
||||
return;
|
||||
|
||||
target = newValue;
|
||||
|
||||
if (stepsToTarget <= 0)
|
||||
{
|
||||
target = currentValue = newValue;
|
||||
countdown = 0;
|
||||
setCurrentValueToTargetValue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (target != newValue)
|
||||
{
|
||||
target = newValue;
|
||||
countdown = stepsToTarget;
|
||||
countdown = stepsToTarget;
|
||||
step = (target - currentValue) / static_cast<FloatType> (countdown);
|
||||
}
|
||||
|
||||
if (countdown <= 0)
|
||||
currentValue = target;
|
||||
else
|
||||
step = (target - currentValue) / (FloatType) countdown;
|
||||
}
|
||||
/** Sets the current value to the target value. */
|
||||
void setCurrentValueToTargetValue() noexcept
|
||||
{
|
||||
currentValue = target;
|
||||
countdown = 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -89,7 +96,7 @@ public:
|
|||
*/
|
||||
FloatType getNextValue() noexcept
|
||||
{
|
||||
if (countdown <= 0)
|
||||
if (! isSmoothing())
|
||||
return target;
|
||||
|
||||
--countdown;
|
||||
|
|
@ -98,16 +105,13 @@ public:
|
|||
}
|
||||
|
||||
/** Returns true if the current value is currently being interpolated. */
|
||||
bool isSmoothing() const noexcept
|
||||
{
|
||||
return countdown > 0;
|
||||
}
|
||||
bool isSmoothing() const noexcept { return countdown > 0; }
|
||||
|
||||
/** Returns the current value of the ramp. */
|
||||
FloatType getCurrentValue() const noexcept { return currentValue; }
|
||||
|
||||
/** Returns the target value towards which the smoothed value is currently moving. */
|
||||
FloatType getTargetValue() const noexcept
|
||||
{
|
||||
return target;
|
||||
}
|
||||
FloatType getTargetValue() const noexcept { return target; }
|
||||
|
||||
//==============================================================================
|
||||
/** Applies a linear smoothed gain to a stream of samples
|
||||
|
|
@ -194,8 +198,7 @@ public:
|
|||
{
|
||||
if (numSamples >= countdown)
|
||||
{
|
||||
currentValue = target;
|
||||
countdown = 0;
|
||||
setCurrentValueToTargetValue();
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +207,25 @@ public:
|
|||
return currentValue;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** THIS FUNCTION IS DEPRECATED.
|
||||
|
||||
Use `setTargetValue (float)` and `setCurrentValueToTargetValue()` instead:
|
||||
|
||||
lsv.setValue (x, false); -> lsv.setTargetValue (x);
|
||||
lsv.setValue (x, true); -> lsv.setTargetValue (x); lsv.setCurrentValueToTargetValue();
|
||||
|
||||
@param newValue The new target value
|
||||
@param force If true, the value will be set immediately, bypassing the ramp
|
||||
*/
|
||||
JUCE_DEPRECATED_WITH_BODY (void setValue (FloatType newValue, bool force = false) noexcept,
|
||||
{
|
||||
setTargetValue (newValue);
|
||||
|
||||
if (force)
|
||||
setCurrentValueToTargetValue();
|
||||
})
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
FloatType currentValue = 0, target = 0, step = 0;
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ public:
|
|||
const float dryScaleFactor = 2.0f;
|
||||
|
||||
const float wet = newParams.wetLevel * wetScaleFactor;
|
||||
dryGain.setValue (newParams.dryLevel * dryScaleFactor);
|
||||
wetGain1.setValue (0.5f * wet * (1.0f + newParams.width));
|
||||
wetGain2.setValue (0.5f * wet * (1.0f - newParams.width));
|
||||
dryGain.setTargetValue (newParams.dryLevel * dryScaleFactor);
|
||||
wetGain1.setTargetValue (0.5f * wet * (1.0f + newParams.width));
|
||||
wetGain2.setTargetValue (0.5f * wet * (1.0f - newParams.width));
|
||||
|
||||
gain = isFrozen (newParams.freezeMode) ? 0.0f : 0.015f;
|
||||
parameters = newParams;
|
||||
|
|
@ -207,8 +207,8 @@ private:
|
|||
|
||||
void setDamping (const float dampingToUse, const float roomSizeToUse) noexcept
|
||||
{
|
||||
damping.setValue (dampingToUse);
|
||||
feedback.setValue (roomSizeToUse);
|
||||
damping.setTargetValue (dampingToUse);
|
||||
feedback.setTargetValue (roomSizeToUse);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -1006,13 +1006,13 @@ private:
|
|||
|
||||
for (auto i = 0; i < 2; ++i)
|
||||
{
|
||||
changeVolumes[i].setValue (1.0f);
|
||||
changeVolumes[i].setTargetValue (1.0f);
|
||||
changeVolumes[i].reset (currentInfo.sampleRate, 0.05);
|
||||
changeVolumes[i].setValue (0.0f);
|
||||
changeVolumes[i].setTargetValue (0.0f);
|
||||
|
||||
changeVolumes[i + 2].setValue (0.0f);
|
||||
changeVolumes[i + 2].setTargetValue (0.0f);
|
||||
changeVolumes[i + 2].reset (currentInfo.sampleRate, 0.05);
|
||||
changeVolumes[i + 2].setValue (1.0f);
|
||||
changeVolumes[i + 2].setTargetValue (1.0f);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1235,13 +1235,13 @@ void Convolution::processSamples (const AudioBlock<float>& input, AudioBlock<flo
|
|||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
volumeDry[channel].setValue (isBypassed ? 0.0f : 1.0f);
|
||||
volumeDry[channel].setTargetValue (isBypassed ? 0.0f : 1.0f);
|
||||
volumeDry[channel].reset (sampleRate, 0.05);
|
||||
volumeDry[channel].setValue (isBypassed ? 1.0f : 0.0f);
|
||||
volumeDry[channel].setTargetValue (isBypassed ? 1.0f : 0.0f);
|
||||
|
||||
volumeWet[channel].setValue (isBypassed ? 1.0f : 0.0f);
|
||||
volumeWet[channel].setTargetValue (isBypassed ? 1.0f : 0.0f);
|
||||
volumeWet[channel].reset (sampleRate, 0.05);
|
||||
volumeWet[channel].setValue (isBypassed ? 0.0f : 1.0f);
|
||||
volumeWet[channel].setTargetValue (isBypassed ? 0.0f : 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public:
|
|||
void setBias (FloatType newBias) noexcept
|
||||
{
|
||||
jassert (newBias >= static_cast<FloatType> (-1) && newBias <= static_cast<FloatType> (1));
|
||||
bias.setValue(newBias);
|
||||
bias.setTargetValue (newBias);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Applies a new gain as a linear value. */
|
||||
void setGainLinear (FloatType newGain) noexcept { gain.setValue (newGain); }
|
||||
void setGainLinear (FloatType newGain) noexcept { gain.setTargetValue (newGain); }
|
||||
|
||||
/** Applies a new gain as a decibel value. */
|
||||
void setGainDecibels (FloatType newGainDecibels) noexcept { setGainLinear (Decibels::decibelsToGain<FloatType> (newGainDecibels)); }
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ void LadderFilter<Type>::reset() noexcept
|
|||
for (auto& s : state)
|
||||
s.fill (Type (0));
|
||||
|
||||
cutoffTransformSmoother.setValue (cutoffTransformSmoother.getTargetValue(), true);
|
||||
scaledResonanceSmoother.setValue (scaledResonanceSmoother.getTargetValue(), true);
|
||||
cutoffTransformSmoother.setCurrentValueToTargetValue();
|
||||
scaledResonanceSmoother.setCurrentValueToTargetValue();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -118,10 +118,8 @@ private:
|
|||
std::vector<std::array<Type, numStates>> state;
|
||||
std::array<Type, numStates> A;
|
||||
|
||||
LinearSmoothedValue<Type> cutoffTransformSmoother;
|
||||
LinearSmoothedValue<Type> scaledResonanceSmoother;
|
||||
Type cutoffTransformValue;
|
||||
Type scaledResonanceValue;
|
||||
LinearSmoothedValue<Type> cutoffTransformSmoother, scaledResonanceSmoother;
|
||||
Type cutoffTransformValue, scaledResonanceValue;
|
||||
|
||||
LookupTableTransform<Type> saturationLUT { [] (Type x) { return std::tanh (x); }, Type (-5), Type (5), 128 };
|
||||
|
||||
|
|
@ -136,8 +134,8 @@ private:
|
|||
//==============================================================================
|
||||
void setSampleRate (Type newValue) noexcept;
|
||||
void setNumChannels (size_t newValue) { state.resize (newValue); }
|
||||
void updateCutoffFreq() noexcept { cutoffTransformSmoother.setValue (std::exp (cutoffFreqHz * cutoffFreqScaler)); }
|
||||
void updateResonance() noexcept { scaledResonanceSmoother.setValue (jmap (resonance, Type (0.1), Type (1.0))); }
|
||||
void updateCutoffFreq() noexcept { cutoffTransformSmoother.setTargetValue (std::exp (cutoffFreqHz * cutoffFreqScaler)); }
|
||||
void updateResonance() noexcept { scaledResonanceSmoother.setTargetValue (jmap (resonance, Type (0.1), Type (1.0))); }
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
|
|
|
|||
|
|
@ -82,7 +82,13 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Sets the frequency of the oscillator. */
|
||||
void setFrequency (NumericType newFrequency, bool force = false) noexcept { frequency.setValue (newFrequency, force); }
|
||||
void setFrequency (NumericType newFrequency, bool force = false) noexcept
|
||||
{
|
||||
frequency.setTargetValue (newFrequency);
|
||||
|
||||
if (force)
|
||||
frequency.setCurrentValueToTargetValue();
|
||||
}
|
||||
|
||||
/** Returns the current frequency of the oscillator. */
|
||||
NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue