git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
159
deps/juce/modules/juce_dsp/widgets/juce_Bias.h
vendored
Normal file
159
deps/juce/modules/juce_dsp/widgets/juce_Bias.h
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
Adds a DC offset (voltage bias) to the audio samples.
|
||||
|
||||
This is a useful preprocessor for asymmetric waveshaping when a waveshaper is
|
||||
bookended by a bias on input and a DC-offset removing high pass filter on output.
|
||||
|
||||
This is an extremely simple bias implementation that simply adds a value to a signal.
|
||||
More complicated bias behaviours exist in real circuits - for your homework ;).
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename FloatType>
|
||||
class Bias
|
||||
{
|
||||
public:
|
||||
Bias() noexcept = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the DC bias
|
||||
@param newBias DC offset in range [-1, 1]
|
||||
*/
|
||||
void setBias (FloatType newBias) noexcept
|
||||
{
|
||||
jassert (newBias >= static_cast<FloatType> (-1) && newBias <= static_cast<FloatType> (1));
|
||||
bias.setTargetValue (newBias);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the DC bias
|
||||
@return DC bias, which should be in the range [-1, 1]
|
||||
*/
|
||||
FloatType getBias() const noexcept { return bias.getTargetValue(); }
|
||||
|
||||
/** Sets the length of the ramp used for smoothing gain changes. */
|
||||
void setRampDurationSeconds (double newDurationSeconds) noexcept
|
||||
{
|
||||
if (rampDurationSeconds != newDurationSeconds)
|
||||
{
|
||||
rampDurationSeconds = newDurationSeconds;
|
||||
updateRamp();
|
||||
}
|
||||
}
|
||||
|
||||
double getRampDurationSeconds() const noexcept { return rampDurationSeconds; }
|
||||
|
||||
//==============================================================================
|
||||
/** Called before processing starts */
|
||||
void prepare (const ProcessSpec& spec) noexcept
|
||||
{
|
||||
sampleRate = spec.sampleRate;
|
||||
updateRamp();
|
||||
}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
bias.reset (sampleRate, rampDurationSeconds);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the result of processing a single sample. */
|
||||
template <typename SampleType>
|
||||
SampleType processSample (SampleType inputSample) noexcept
|
||||
{
|
||||
return inputSample + bias.getNextValue();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output buffers supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
auto&& inBlock = context.getInputBlock();
|
||||
auto&& outBlock = context.getOutputBlock();
|
||||
|
||||
jassert (inBlock.getNumChannels() == outBlock.getNumChannels());
|
||||
jassert (inBlock.getNumSamples() == outBlock.getNumSamples());
|
||||
|
||||
auto len = inBlock.getNumSamples();
|
||||
auto numChannels = inBlock.getNumChannels();
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
bias.skip (static_cast<int> (len));
|
||||
|
||||
if (context.usesSeparateInputAndOutputBlocks())
|
||||
outBlock.copyFrom (inBlock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (numChannels == 1)
|
||||
{
|
||||
auto* src = inBlock.getChannelPointer (0);
|
||||
auto* dst = outBlock.getChannelPointer (0);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = src[i] + bias.getNextValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6386)
|
||||
auto* biases = static_cast<FloatType*> (alloca (sizeof (FloatType) * len));
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
biases[i] = bias.getNextValue();
|
||||
|
||||
for (size_t chan = 0; chan < numChannels; ++chan)
|
||||
FloatVectorOperations::add (outBlock.getChannelPointer (chan),
|
||||
inBlock.getChannelPointer (chan),
|
||||
biases, static_cast<int> (len));
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
SmoothedValue<FloatType> bias;
|
||||
double sampleRate = 0, rampDurationSeconds = 0;
|
||||
|
||||
void updateRamp() noexcept
|
||||
{
|
||||
if (sampleRate > 0)
|
||||
bias.reset (sampleRate, rampDurationSeconds);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
141
deps/juce/modules/juce_dsp/widgets/juce_Chorus.cpp
vendored
Normal file
141
deps/juce/modules/juce_dsp/widgets/juce_Chorus.cpp
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
Chorus<SampleType>::Chorus()
|
||||
{
|
||||
auto oscFunction = [] (SampleType x) { return std::sin (x); };
|
||||
osc.initialise (oscFunction);
|
||||
|
||||
dryWet.setMixingRule (DryWetMixingRule::linear);
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::setRate (SampleType newRateHz)
|
||||
{
|
||||
jassert (isPositiveAndBelow (newRateHz, static_cast<SampleType> (100.0)));
|
||||
|
||||
rate = newRateHz;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::setDepth (SampleType newDepth)
|
||||
{
|
||||
jassert (isPositiveAndNotGreaterThan (newDepth, maxDepth));
|
||||
|
||||
depth = newDepth;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::setCentreDelay (SampleType newDelayMs)
|
||||
{
|
||||
jassert (isPositiveAndBelow (newDelayMs, maxCentreDelayMs));
|
||||
|
||||
centreDelay = jlimit (static_cast<SampleType> (1.0), maxCentreDelayMs, newDelayMs);
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::setFeedback (SampleType newFeedback)
|
||||
{
|
||||
jassert (newFeedback >= static_cast<SampleType> (-1.0) && newFeedback <= static_cast<SampleType> (1.0));
|
||||
|
||||
feedback = newFeedback;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::setMix (SampleType newMix)
|
||||
{
|
||||
jassert (isPositiveAndNotGreaterThan (newMix, static_cast<SampleType> (1.0)));
|
||||
|
||||
mix = newMix;
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
jassert (spec.sampleRate > 0);
|
||||
jassert (spec.numChannels > 0);
|
||||
|
||||
sampleRate = spec.sampleRate;
|
||||
|
||||
const auto maxPossibleDelay = std::ceil ((maximumDelayModulation * maxDepth * oscVolumeMultiplier + maxCentreDelayMs)
|
||||
* sampleRate / 1000.0);
|
||||
delay = DelayLine<SampleType, DelayLineInterpolationTypes::Linear>{ static_cast<int> (maxPossibleDelay) };
|
||||
delay.prepare (spec);
|
||||
|
||||
dryWet.prepare (spec);
|
||||
feedbackVolume.resize (spec.numChannels);
|
||||
lastOutput.resize (spec.numChannels);
|
||||
|
||||
osc.prepare (spec);
|
||||
bufferDelayTimes.setSize (1, (int) spec.maximumBlockSize, false, false, true);
|
||||
|
||||
update();
|
||||
reset();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::reset()
|
||||
{
|
||||
std::fill (lastOutput.begin(), lastOutput.end(), static_cast<SampleType> (0));
|
||||
|
||||
delay.reset();
|
||||
osc.reset();
|
||||
dryWet.reset();
|
||||
|
||||
oscVolume.reset (sampleRate, 0.05);
|
||||
|
||||
for (auto& vol : feedbackVolume)
|
||||
vol.reset (sampleRate, 0.05);
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Chorus<SampleType>::update()
|
||||
{
|
||||
osc.setFrequency (rate);
|
||||
oscVolume.setTargetValue (depth * oscVolumeMultiplier);
|
||||
dryWet.setWetMixProportion (mix);
|
||||
|
||||
for (auto& vol : feedbackVolume)
|
||||
vol.setTargetValue (feedback);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class Chorus<float>;
|
||||
template class Chorus<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
169
deps/juce/modules/juce_dsp/widgets/juce_Chorus.h
vendored
Normal file
169
deps/juce/modules/juce_dsp/widgets/juce_Chorus.h
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
A simple chorus DSP widget that modulates the delay of a delay line in order to
|
||||
create sweeping notches in the magnitude frequency response.
|
||||
|
||||
This audio effect can be controlled via the speed and depth of the LFO controlling
|
||||
the frequency response, a mix control, a feedback control, and the centre delay
|
||||
of the modulation.
|
||||
|
||||
Note: To get classic chorus sounds try to use a centre delay time around 7-8 ms
|
||||
with a low feeback volume and a low depth. This effect can also be used as a
|
||||
flanger with a lower centre delay time and a lot of feedback, and as a vibrato
|
||||
effect if the mix value is 1.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class Chorus
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
Chorus();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the rate (in Hz) of the LFO modulating the chorus delay line. This rate
|
||||
must be lower than 100 Hz.
|
||||
*/
|
||||
void setRate (SampleType newRateHz);
|
||||
|
||||
/** Sets the volume of the LFO modulating the chorus delay line (between 0 and 1).
|
||||
*/
|
||||
void setDepth (SampleType newDepth);
|
||||
|
||||
/** Sets the centre delay in milliseconds of the chorus delay line modulation.
|
||||
This delay must be between 1 and 100 ms.
|
||||
*/
|
||||
void setCentreDelay (SampleType newDelayMs);
|
||||
|
||||
/** Sets the feedback volume (between -1 and 1) of the chorus delay line.
|
||||
Negative values can be used to get specific chorus sounds.
|
||||
*/
|
||||
void setFeedback (SampleType newFeedback);
|
||||
|
||||
/** Sets the amount of dry and wet signal in the output of the chorus (between 0
|
||||
for full dry and 1 for full wet).
|
||||
*/
|
||||
void setMix (SampleType newMix);
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the processor. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Resets the internal state variables of the processor. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output samples supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumChannels() == lastOutput.size());
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
auto delayValuesBlock = AudioBlock<SampleType>(bufferDelayTimes).getSubBlock (0, numSamples);
|
||||
auto contextDelay = ProcessContextReplacing<SampleType> (delayValuesBlock);
|
||||
delayValuesBlock.clear();
|
||||
|
||||
osc.process (contextDelay);
|
||||
delayValuesBlock.multiplyBy (oscVolume);
|
||||
|
||||
auto* delaySamples = bufferDelayTimes.getWritePointer (0);
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
{
|
||||
auto lfo = jmax (static_cast<SampleType> (1.0), maximumDelayModulation * delaySamples[i] + centreDelay);
|
||||
delaySamples[i] = static_cast<SampleType> (lfo * sampleRate / 1000.0);
|
||||
}
|
||||
|
||||
dryWet.pushDrySamples (inputBlock);
|
||||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
auto* inputSamples = inputBlock .getChannelPointer (channel);
|
||||
auto* outputSamples = outputBlock.getChannelPointer (channel);
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
{
|
||||
auto input = inputSamples[i];
|
||||
auto output = input - lastOutput[channel];
|
||||
|
||||
delay.pushSample ((int) channel, output);
|
||||
delay.setDelay (delaySamples[i]);
|
||||
output = delay.popSample ((int) channel);
|
||||
|
||||
outputSamples[i] = output;
|
||||
lastOutput[channel] = output * feedbackVolume[channel].getNextValue();
|
||||
}
|
||||
}
|
||||
|
||||
dryWet.mixWetSamples (outputBlock);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update();
|
||||
|
||||
//==============================================================================
|
||||
Oscillator<SampleType> osc;
|
||||
DelayLine<SampleType, DelayLineInterpolationTypes::Linear> delay;
|
||||
SmoothedValue<SampleType, ValueSmoothingTypes::Linear> oscVolume;
|
||||
std::vector<SmoothedValue<SampleType, ValueSmoothingTypes::Linear>> feedbackVolume { 2 };
|
||||
DryWetMixer<SampleType> dryWet;
|
||||
std::vector<SampleType> lastOutput { 2 };
|
||||
AudioBuffer<SampleType> bufferDelayTimes;
|
||||
|
||||
double sampleRate = 44100.0;
|
||||
SampleType rate = 1.0, depth = 0.25, feedback = 0.0, mix = 0.5,
|
||||
centreDelay = 7.0;
|
||||
|
||||
static constexpr SampleType maxDepth = 1.0,
|
||||
maxCentreDelayMs = 100.0,
|
||||
oscVolumeMultiplier = 0.5,
|
||||
maximumDelayModulation = 20.0;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
121
deps/juce/modules/juce_dsp/widgets/juce_Compressor.cpp
vendored
Normal file
121
deps/juce/modules/juce_dsp/widgets/juce_Compressor.cpp
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
Compressor<SampleType>::Compressor()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::setThreshold (SampleType newThreshold)
|
||||
{
|
||||
thresholddB = newThreshold;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::setRatio (SampleType newRatio)
|
||||
{
|
||||
jassert (newRatio >= static_cast<SampleType> (1.0));
|
||||
|
||||
ratio = newRatio;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::setAttack (SampleType newAttack)
|
||||
{
|
||||
attackTime = newAttack;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::setRelease (SampleType newRelease)
|
||||
{
|
||||
releaseTime = newRelease;
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
jassert (spec.sampleRate > 0);
|
||||
jassert (spec.numChannels > 0);
|
||||
|
||||
sampleRate = spec.sampleRate;
|
||||
|
||||
envelopeFilter.prepare (spec);
|
||||
|
||||
update();
|
||||
reset();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::reset()
|
||||
{
|
||||
envelopeFilter.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
SampleType Compressor<SampleType>::processSample (int channel, SampleType inputValue)
|
||||
{
|
||||
// Ballistics filter with peak rectifier
|
||||
auto env = envelopeFilter.processSample (channel, inputValue);
|
||||
|
||||
// VCA
|
||||
auto gain = (env < threshold) ? static_cast<SampleType> (1.0)
|
||||
: std::pow (env * thresholdInverse, ratioInverse - static_cast<SampleType> (1.0));
|
||||
|
||||
// Output
|
||||
return gain * inputValue;
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Compressor<SampleType>::update()
|
||||
{
|
||||
threshold = Decibels::decibelsToGain (thresholddB, static_cast<SampleType> (-200.0));
|
||||
thresholdInverse = static_cast<SampleType> (1.0) / threshold;
|
||||
ratioInverse = static_cast<SampleType> (1.0) / ratio;
|
||||
|
||||
envelopeFilter.setAttackTime (attackTime);
|
||||
envelopeFilter.setReleaseTime (releaseTime);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class Compressor<float>;
|
||||
template class Compressor<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
110
deps/juce/modules/juce_dsp/widgets/juce_Compressor.h
vendored
Normal file
110
deps/juce/modules/juce_dsp/widgets/juce_Compressor.h
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
A simple compressor with standard threshold, ratio, attack time and release time
|
||||
controls.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class Compressor
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
Compressor();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the threshold in dB of the compressor.*/
|
||||
void setThreshold (SampleType newThreshold);
|
||||
|
||||
/** Sets the ratio of the compressor (must be higher or equal to 1).*/
|
||||
void setRatio (SampleType newRatio);
|
||||
|
||||
/** Sets the attack time in milliseconds of the compressor.*/
|
||||
void setAttack (SampleType newAttack);
|
||||
|
||||
/** Sets the release time in milliseconds of the compressor.*/
|
||||
void setRelease (SampleType newRelease);
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the processor. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Resets the internal state variables of the processor. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output samples supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
auto* inputSamples = inputBlock .getChannelPointer (channel);
|
||||
auto* outputSamples = outputBlock.getChannelPointer (channel);
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
outputSamples[i] = processSample ((int) channel, inputSamples[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs the processing operation on a single sample at a time. */
|
||||
SampleType processSample (int channel, SampleType inputValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update();
|
||||
|
||||
//==============================================================================
|
||||
SampleType threshold, thresholdInverse, ratioInverse;
|
||||
BallisticsFilter<SampleType> envelopeFilter;
|
||||
|
||||
double sampleRate = 44100.0;
|
||||
SampleType thresholddB = 0.0, ratio = 1.0, attackTime = 1.0, releaseTime = 100.0;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
148
deps/juce/modules/juce_dsp/widgets/juce_Gain.h
vendored
Normal file
148
deps/juce/modules/juce_dsp/widgets/juce_Gain.h
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
Applies a gain to audio samples as single samples or AudioBlocks.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename FloatType>
|
||||
class Gain
|
||||
{
|
||||
public:
|
||||
Gain() noexcept = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Applies a new gain as a linear value. */
|
||||
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)); }
|
||||
|
||||
/** Returns the current gain as a linear value. */
|
||||
FloatType getGainLinear() const noexcept { return gain.getTargetValue(); }
|
||||
|
||||
/** Returns the current gain in decibels. */
|
||||
FloatType getGainDecibels() const noexcept { return Decibels::gainToDecibels<FloatType> (getGainLinear()); }
|
||||
|
||||
/** Sets the length of the ramp used for smoothing gain changes. */
|
||||
void setRampDurationSeconds (double newDurationSeconds) noexcept
|
||||
{
|
||||
if (rampDurationSeconds != newDurationSeconds)
|
||||
{
|
||||
rampDurationSeconds = newDurationSeconds;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the ramp duration in seconds. */
|
||||
double getRampDurationSeconds() const noexcept { return rampDurationSeconds; }
|
||||
|
||||
/** Returns true if the current value is currently being interpolated. */
|
||||
bool isSmoothing() const noexcept { return gain.isSmoothing(); }
|
||||
|
||||
//==============================================================================
|
||||
/** Called before processing starts. */
|
||||
void prepare (const ProcessSpec& spec) noexcept
|
||||
{
|
||||
sampleRate = spec.sampleRate;
|
||||
reset();
|
||||
}
|
||||
|
||||
/** Resets the internal state of the gain */
|
||||
void reset() noexcept
|
||||
{
|
||||
if (sampleRate > 0)
|
||||
gain.reset (sampleRate, rampDurationSeconds);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the result of processing a single sample. */
|
||||
template <typename SampleType>
|
||||
SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType s) noexcept
|
||||
{
|
||||
return s * gain.getNextValue();
|
||||
}
|
||||
|
||||
/** Processes the input and output buffers supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
auto&& inBlock = context.getInputBlock();
|
||||
auto&& outBlock = context.getOutputBlock();
|
||||
|
||||
jassert (inBlock.getNumChannels() == outBlock.getNumChannels());
|
||||
jassert (inBlock.getNumSamples() == outBlock.getNumSamples());
|
||||
|
||||
auto len = inBlock.getNumSamples();
|
||||
auto numChannels = inBlock.getNumChannels();
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
gain.skip (static_cast<int> (len));
|
||||
|
||||
if (context.usesSeparateInputAndOutputBlocks())
|
||||
outBlock.copyFrom (inBlock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (numChannels == 1)
|
||||
{
|
||||
auto* src = inBlock.getChannelPointer (0);
|
||||
auto* dst = outBlock.getChannelPointer (0);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = src[i] * gain.getNextValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6255 6386)
|
||||
auto* gains = static_cast<FloatType*> (alloca (sizeof (FloatType) * len));
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
gains[i] = gain.getNextValue();
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
|
||||
for (size_t chan = 0; chan < numChannels; ++chan)
|
||||
FloatVectorOperations::multiply (outBlock.getChannelPointer (chan),
|
||||
inBlock.getChannelPointer (chan),
|
||||
gains, static_cast<int> (len));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
SmoothedValue<FloatType> gain;
|
||||
double sampleRate = 0, rampDurationSeconds = 0;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
176
deps/juce/modules/juce_dsp/widgets/juce_LadderFilter.cpp
vendored
Normal file
176
deps/juce/modules/juce_dsp/widgets/juce_LadderFilter.cpp
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
LadderFilter<SampleType>::LadderFilter() : state (2)
|
||||
{
|
||||
setSampleRate (SampleType (1000)); // intentionally setting unrealistic default
|
||||
// sample rate to catch missing initialisation bugs
|
||||
setResonance (SampleType (0));
|
||||
setDrive (SampleType (1.2));
|
||||
|
||||
mode = Mode::LPF24;
|
||||
setMode (Mode::LPF12);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::setMode (Mode newMode) noexcept
|
||||
{
|
||||
if (newMode == mode)
|
||||
return;
|
||||
|
||||
switch (newMode)
|
||||
{
|
||||
case Mode::LPF12: A = {{ SampleType (0), SampleType (0), SampleType (1), SampleType (0), SampleType (0) }}; comp = SampleType (0.5); break;
|
||||
case Mode::HPF12: A = {{ SampleType (1), SampleType (-2), SampleType (1), SampleType (0), SampleType (0) }}; comp = SampleType (0); break;
|
||||
case Mode::BPF12: A = {{ SampleType (0), SampleType (0), SampleType (-1), SampleType (1), SampleType (0) }}; comp = SampleType (0.5); break;
|
||||
case Mode::LPF24: A = {{ SampleType (0), SampleType (0), SampleType (0), SampleType (0), SampleType (1) }}; comp = SampleType (0.5); break;
|
||||
case Mode::HPF24: A = {{ SampleType (1), SampleType (-4), SampleType (6), SampleType (-4), SampleType (1) }}; comp = SampleType (0); break;
|
||||
case Mode::BPF24: A = {{ SampleType (0), SampleType (0), SampleType (1), SampleType (-2), SampleType (1) }}; comp = SampleType (0.5); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
static constexpr auto outputGain = SampleType (1.2);
|
||||
|
||||
for (auto& a : A)
|
||||
a *= outputGain;
|
||||
|
||||
mode = newMode;
|
||||
reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
setSampleRate (SampleType (spec.sampleRate));
|
||||
setNumChannels (spec.numChannels);
|
||||
reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::reset() noexcept
|
||||
{
|
||||
for (auto& s : state)
|
||||
s.fill (SampleType (0));
|
||||
|
||||
cutoffTransformSmoother.setCurrentAndTargetValue (cutoffTransformSmoother.getTargetValue());
|
||||
scaledResonanceSmoother.setCurrentAndTargetValue (scaledResonanceSmoother.getTargetValue());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::setCutoffFrequencyHz (SampleType newCutoff) noexcept
|
||||
{
|
||||
jassert (newCutoff > SampleType (0));
|
||||
cutoffFreqHz = newCutoff;
|
||||
updateCutoffFreq();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::setResonance (SampleType newResonance) noexcept
|
||||
{
|
||||
jassert (newResonance >= SampleType (0) && newResonance <= SampleType (1));
|
||||
resonance = newResonance;
|
||||
updateResonance();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::setDrive (SampleType newDrive) noexcept
|
||||
{
|
||||
jassert (newDrive >= SampleType (1));
|
||||
|
||||
drive = newDrive;
|
||||
gain = std::pow (drive, SampleType (-2.642)) * SampleType (0.6103) + SampleType (0.3903);
|
||||
drive2 = drive * SampleType (0.04) + SampleType (0.96);
|
||||
gain2 = std::pow (drive2, SampleType (-2.642)) * SampleType (0.6103) + SampleType (0.3903);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
SampleType LadderFilter<SampleType>::processSample (SampleType inputValue, size_t channelToUse) noexcept
|
||||
{
|
||||
auto& s = state[channelToUse];
|
||||
|
||||
const auto a1 = cutoffTransformValue;
|
||||
const auto g = a1 * SampleType (-1) + SampleType (1);
|
||||
const auto b0 = g * SampleType (0.76923076923);
|
||||
const auto b1 = g * SampleType (0.23076923076);
|
||||
|
||||
const auto dx = gain * saturationLUT (drive * inputValue);
|
||||
const auto a = dx + scaledResonanceValue * SampleType (-4) * (gain2 * saturationLUT (drive2 * s[4]) - dx * comp);
|
||||
|
||||
const auto b = b1 * s[0] + a1 * s[1] + b0 * a;
|
||||
const auto c = b1 * s[1] + a1 * s[2] + b0 * b;
|
||||
const auto d = b1 * s[2] + a1 * s[3] + b0 * c;
|
||||
const auto e = b1 * s[3] + a1 * s[4] + b0 * d;
|
||||
|
||||
s[0] = a;
|
||||
s[1] = b;
|
||||
s[2] = c;
|
||||
s[3] = d;
|
||||
s[4] = e;
|
||||
|
||||
return a * A[0] + b * A[1] + c * A[2] + d * A[3] + e * A[4];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::updateSmoothers() noexcept
|
||||
{
|
||||
cutoffTransformValue = cutoffTransformSmoother.getNextValue();
|
||||
scaledResonanceValue = scaledResonanceSmoother.getNextValue();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void LadderFilter<SampleType>::setSampleRate (SampleType newValue) noexcept
|
||||
{
|
||||
jassert (newValue > SampleType (0));
|
||||
cutoffFreqScaler = SampleType (-2.0 * juce::MathConstants<double>::pi) / newValue;
|
||||
|
||||
static constexpr SampleType smootherRampTimeSec = SampleType (0.05);
|
||||
cutoffTransformSmoother.reset (newValue, smootherRampTimeSec);
|
||||
scaledResonanceSmoother.reset (newValue, smootherRampTimeSec);
|
||||
|
||||
updateCutoffFreq();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class LadderFilter<float>;
|
||||
template class LadderFilter<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
153
deps/juce/modules/juce_dsp/widgets/juce_LadderFilter.h
vendored
Normal file
153
deps/juce/modules/juce_dsp/widgets/juce_LadderFilter.h
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
enum class LadderFilterMode
|
||||
{
|
||||
LPF12, // low-pass 12 dB/octave
|
||||
HPF12, // high-pass 12 dB/octave
|
||||
BPF12, // band-pass 12 dB/octave
|
||||
LPF24, // low-pass 24 dB/octave
|
||||
HPF24, // high-pass 24 dB/octave
|
||||
BPF24 // band-pass 24 dB/octave
|
||||
};
|
||||
|
||||
/**
|
||||
Multi-mode filter based on the Moog ladder filter.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class LadderFilter
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
using Mode = LadderFilterMode;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an uninitialised filter. Call prepare() before first use. */
|
||||
LadderFilter();
|
||||
|
||||
/** Enables or disables the filter. If disabled it will simply pass through the input signal. */
|
||||
void setEnabled (bool isEnabled) noexcept { enabled = isEnabled; }
|
||||
|
||||
/** Sets filter mode. */
|
||||
void setMode (Mode newMode) noexcept;
|
||||
|
||||
/** Initialises the filter. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Returns the current number of channels. */
|
||||
size_t getNumChannels() const noexcept { return state.size(); }
|
||||
|
||||
/** Resets the internal state variables of the filter. */
|
||||
void reset() noexcept;
|
||||
|
||||
/** Sets the cutoff frequency of the filter.
|
||||
|
||||
@param newCutoff cutoff frequency in Hz
|
||||
*/
|
||||
void setCutoffFrequencyHz (SampleType newCutoff) noexcept;
|
||||
|
||||
/** Sets the resonance of the filter.
|
||||
|
||||
@param newResonance a value between 0 and 1; higher values increase the resonance and can result in self oscillation!
|
||||
*/
|
||||
void setResonance (SampleType newResonance) noexcept;
|
||||
|
||||
/** Sets the amount of saturation in the filter.
|
||||
|
||||
@param newDrive saturation amount; it can be any number greater than or equal to one. Higher values result in more distortion.
|
||||
*/
|
||||
void setDrive (SampleType newDrive) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() <= getNumChannels());
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (! enabled || context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t n = 0; n < numSamples; ++n)
|
||||
{
|
||||
updateSmoothers();
|
||||
|
||||
for (size_t ch = 0; ch < numChannels; ++ch)
|
||||
outputBlock.getChannelPointer (ch)[n] = processSample (inputBlock.getChannelPointer (ch)[n], ch);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
SampleType processSample (SampleType inputValue, size_t channelToUse) noexcept;
|
||||
void updateSmoothers() noexcept;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void setSampleRate (SampleType newValue) noexcept;
|
||||
void setNumChannels (size_t newValue) { state.resize (newValue); }
|
||||
void updateCutoffFreq() noexcept { cutoffTransformSmoother.setTargetValue (std::exp (cutoffFreqHz * cutoffFreqScaler)); }
|
||||
void updateResonance() noexcept { scaledResonanceSmoother.setTargetValue (jmap (resonance, SampleType (0.1), SampleType (1.0))); }
|
||||
|
||||
//==============================================================================
|
||||
SampleType drive, drive2, gain, gain2, comp;
|
||||
|
||||
static constexpr size_t numStates = 5;
|
||||
std::vector<std::array<SampleType, numStates>> state;
|
||||
std::array<SampleType, numStates> A;
|
||||
|
||||
SmoothedValue<SampleType> cutoffTransformSmoother, scaledResonanceSmoother;
|
||||
SampleType cutoffTransformValue, scaledResonanceValue;
|
||||
|
||||
LookupTableTransform<SampleType> saturationLUT { [] (SampleType x) { return std::tanh (x); },
|
||||
SampleType (-5), SampleType (5), 128 };
|
||||
|
||||
SampleType cutoffFreqHz { SampleType (200) };
|
||||
SampleType resonance;
|
||||
|
||||
SampleType cutoffFreqScaler;
|
||||
|
||||
Mode mode;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
98
deps/juce/modules/juce_dsp/widgets/juce_Limiter.cpp
vendored
Normal file
98
deps/juce/modules/juce_dsp/widgets/juce_Limiter.cpp
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Limiter<SampleType>::setThreshold (SampleType newThreshold)
|
||||
{
|
||||
thresholddB = newThreshold;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Limiter<SampleType>::setRelease (SampleType newRelease)
|
||||
{
|
||||
releaseTime = newRelease;
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Limiter<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
jassert (spec.sampleRate > 0);
|
||||
jassert (spec.numChannels > 0);
|
||||
|
||||
sampleRate = spec.sampleRate;
|
||||
|
||||
firstStageCompressor.prepare (spec);
|
||||
secondStageCompressor.prepare (spec);
|
||||
|
||||
update();
|
||||
reset();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Limiter<SampleType>::reset()
|
||||
{
|
||||
firstStageCompressor.reset();
|
||||
secondStageCompressor.reset();
|
||||
|
||||
outputVolume.reset (sampleRate, 0.001);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Limiter<SampleType>::update()
|
||||
{
|
||||
firstStageCompressor.setThreshold ((SampleType) -10.0);
|
||||
firstStageCompressor.setRatio ((SampleType) 4.0);
|
||||
firstStageCompressor.setAttack ((SampleType) 2.0);
|
||||
firstStageCompressor.setRelease ((SampleType) 200.0);
|
||||
|
||||
secondStageCompressor.setThreshold (thresholddB);
|
||||
secondStageCompressor.setRatio ((SampleType) 1000.0);
|
||||
secondStageCompressor.setAttack ((SampleType) 0.001);
|
||||
secondStageCompressor.setRelease (releaseTime);
|
||||
|
||||
auto ratioInverse = (SampleType) (1.0 / 4.0);
|
||||
|
||||
auto gain = (SampleType) std::pow (10.0, 10.0 * (1.0 - ratioInverse) / 40.0);
|
||||
gain *= Decibels::decibelsToGain (-thresholddB, (SampleType) -100.0);
|
||||
|
||||
outputVolume.setTargetValue (gain);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class Limiter<float>;
|
||||
template class Limiter<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
105
deps/juce/modules/juce_dsp/widgets/juce_Limiter.h
vendored
Normal file
105
deps/juce/modules/juce_dsp/widgets/juce_Limiter.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
A simple limiter with standard threshold and release time controls, featuring
|
||||
two compressors and a hard clipper at 0 dB.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class Limiter
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
Limiter() = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the threshold in dB of the limiter.*/
|
||||
void setThreshold (SampleType newThreshold);
|
||||
|
||||
/** Sets the release time in milliseconds of the limiter.*/
|
||||
void setRelease (SampleType newRelease);
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the processor. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Resets the internal state variables of the processor. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output samples supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
firstStageCompressor.process (context);
|
||||
|
||||
auto secondContext = ProcessContextReplacing<SampleType> (outputBlock);
|
||||
secondStageCompressor.process (secondContext);
|
||||
|
||||
outputBlock.multiplyBy (outputVolume);
|
||||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
FloatVectorOperations::clip (outputBlock.getChannelPointer (channel), outputBlock.getChannelPointer (channel),
|
||||
(SampleType) -1.0, (SampleType) 1.0, (int) numSamples);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update();
|
||||
|
||||
//==============================================================================
|
||||
Compressor<SampleType> firstStageCompressor, secondStageCompressor;
|
||||
SmoothedValue<SampleType, ValueSmoothingTypes::Linear> outputVolume;
|
||||
|
||||
double sampleRate = 44100.0;
|
||||
SampleType thresholddB = -10.0, releaseTime = 100.0;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
129
deps/juce/modules/juce_dsp/widgets/juce_NoiseGate.cpp
vendored
Normal file
129
deps/juce/modules/juce_dsp/widgets/juce_NoiseGate.cpp
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
NoiseGate<SampleType>::NoiseGate()
|
||||
{
|
||||
update();
|
||||
|
||||
RMSFilter.setLevelCalculationType (BallisticsFilterLevelCalculationType::RMS);
|
||||
RMSFilter.setAttackTime (static_cast<SampleType> (0.0));
|
||||
RMSFilter.setReleaseTime (static_cast<SampleType> (50.0));
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::setThreshold (SampleType newValue)
|
||||
{
|
||||
thresholddB = newValue;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::setRatio (SampleType newRatio)
|
||||
{
|
||||
jassert (newRatio >= static_cast<SampleType> (1.0));
|
||||
|
||||
ratio = newRatio;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::setAttack (SampleType newAttack)
|
||||
{
|
||||
attackTime = newAttack;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::setRelease (SampleType newRelease)
|
||||
{
|
||||
releaseTime = newRelease;
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
jassert (spec.sampleRate > 0);
|
||||
jassert (spec.numChannels > 0);
|
||||
|
||||
sampleRate = spec.sampleRate;
|
||||
|
||||
RMSFilter.prepare (spec);
|
||||
envelopeFilter.prepare (spec);
|
||||
|
||||
update();
|
||||
reset();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::reset()
|
||||
{
|
||||
RMSFilter.reset();
|
||||
envelopeFilter.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
SampleType NoiseGate<SampleType>::processSample (int channel, SampleType sample)
|
||||
{
|
||||
// RMS ballistics filter
|
||||
auto env = RMSFilter.processSample (channel, sample);
|
||||
|
||||
// Ballistics filter
|
||||
env = envelopeFilter.processSample (channel, env);
|
||||
|
||||
// VCA
|
||||
auto gain = (env > threshold) ? static_cast<SampleType> (1.0)
|
||||
: std::pow (env * thresholdInverse, currentRatio - static_cast<SampleType> (1.0));
|
||||
|
||||
// Output
|
||||
return gain * sample;
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void NoiseGate<SampleType>::update()
|
||||
{
|
||||
threshold = Decibels::decibelsToGain (thresholddB, static_cast<SampleType> (-200.0));
|
||||
thresholdInverse = static_cast<SampleType> (1.0) / threshold;
|
||||
currentRatio = ratio;
|
||||
|
||||
envelopeFilter.setAttackTime (attackTime);
|
||||
envelopeFilter.setReleaseTime (releaseTime);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class NoiseGate<float>;
|
||||
template class NoiseGate<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
110
deps/juce/modules/juce_dsp/widgets/juce_NoiseGate.h
vendored
Normal file
110
deps/juce/modules/juce_dsp/widgets/juce_NoiseGate.h
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
A simple noise gate with standard threshold, ratio, attack time and
|
||||
release time controls. Can be used as an expander if the ratio is low.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class NoiseGate
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
NoiseGate();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the threshold in dB of the noise-gate.*/
|
||||
void setThreshold (SampleType newThreshold);
|
||||
|
||||
/** Sets the ratio of the noise-gate (must be higher or equal to 1).*/
|
||||
void setRatio (SampleType newRatio);
|
||||
|
||||
/** Sets the attack time in milliseconds of the noise-gate.*/
|
||||
void setAttack (SampleType newAttack);
|
||||
|
||||
/** Sets the release time in milliseconds of the noise-gate.*/
|
||||
void setRelease (SampleType newRelease);
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the processor. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Resets the internal state variables of the processor. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output samples supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
auto* inputSamples = inputBlock .getChannelPointer (channel);
|
||||
auto* outputSamples = outputBlock.getChannelPointer (channel);
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
outputSamples[i] = processSample ((int) channel, inputSamples[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs the processing operation on a single sample at a time. */
|
||||
SampleType processSample (int channel, SampleType inputValue);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update();
|
||||
|
||||
//==============================================================================
|
||||
SampleType threshold, thresholdInverse, currentRatio;
|
||||
BallisticsFilter<SampleType> envelopeFilter, RMSFilter;
|
||||
|
||||
double sampleRate = 44100.0;
|
||||
SampleType thresholddB = -100, ratio = 10.0, attackTime = 1.0, releaseTime = 100.0;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
251
deps/juce/modules/juce_dsp/widgets/juce_Oscillator.h
vendored
Normal file
251
deps/juce/modules/juce_dsp/widgets/juce_Oscillator.h
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
Generates a signal based on a user-supplied function.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class Oscillator
|
||||
{
|
||||
public:
|
||||
/** The NumericType is the underlying primitive type used by the SampleType (which
|
||||
could be either a primitive or vector)
|
||||
*/
|
||||
using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
|
||||
|
||||
/** Creates an uninitialised oscillator. Call initialise before first use. */
|
||||
Oscillator() = default;
|
||||
|
||||
/** Creates an oscillator with a periodic input function (-pi..pi).
|
||||
|
||||
If lookup table is not zero, then the function will be approximated
|
||||
with a lookup table.
|
||||
*/
|
||||
Oscillator (const std::function<NumericType (NumericType)>& function,
|
||||
size_t lookupTableNumPoints = 0)
|
||||
{
|
||||
initialise (function, lookupTableNumPoints);
|
||||
}
|
||||
|
||||
/** Returns true if the Oscillator has been initialised. */
|
||||
bool isInitialised() const noexcept { return static_cast<bool> (generator); }
|
||||
|
||||
/** Initialises the oscillator with a waveform. */
|
||||
void initialise (const std::function<NumericType (NumericType)>& function,
|
||||
size_t lookupTableNumPoints = 0)
|
||||
{
|
||||
if (lookupTableNumPoints != 0)
|
||||
{
|
||||
auto* table = new LookupTableTransform<NumericType> (function,
|
||||
-MathConstants<NumericType>::pi,
|
||||
MathConstants<NumericType>::pi,
|
||||
lookupTableNumPoints);
|
||||
|
||||
lookupTable.reset (table);
|
||||
generator = [table] (NumericType x) { return (*table) (x); };
|
||||
}
|
||||
else
|
||||
{
|
||||
generator = function;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the frequency of the oscillator. */
|
||||
void setFrequency (NumericType newFrequency, bool force = false) noexcept
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
frequency.setCurrentAndTargetValue (newFrequency);
|
||||
return;
|
||||
}
|
||||
|
||||
frequency.setTargetValue (newFrequency);
|
||||
}
|
||||
|
||||
/** Returns the current frequency of the oscillator. */
|
||||
NumericType getFrequency() const noexcept { return frequency.getTargetValue(); }
|
||||
|
||||
//==============================================================================
|
||||
/** Called before processing starts. */
|
||||
void prepare (const ProcessSpec& spec) noexcept
|
||||
{
|
||||
sampleRate = static_cast<NumericType> (spec.sampleRate);
|
||||
rampBuffer.resize ((int) spec.maximumBlockSize);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
/** Resets the internal state of the oscillator */
|
||||
void reset() noexcept
|
||||
{
|
||||
phase.reset();
|
||||
|
||||
if (sampleRate > 0)
|
||||
frequency.reset (sampleRate, 0.05);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the result of processing a single sample. */
|
||||
SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType input) noexcept
|
||||
{
|
||||
jassert (isInitialised());
|
||||
auto increment = MathConstants<NumericType>::twoPi * frequency.getNextValue() / sampleRate;
|
||||
return input + generator (phase.advance (increment) - MathConstants<NumericType>::pi);
|
||||
}
|
||||
|
||||
/** Processes the input and output buffers supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
jassert (isInitialised());
|
||||
auto&& outBlock = context.getOutputBlock();
|
||||
auto&& inBlock = context.getInputBlock();
|
||||
|
||||
// this is an output-only processor
|
||||
jassert (outBlock.getNumSamples() <= static_cast<size_t> (rampBuffer.size()));
|
||||
|
||||
auto len = outBlock.getNumSamples();
|
||||
auto numChannels = outBlock.getNumChannels();
|
||||
auto inputChannels = inBlock.getNumChannels();
|
||||
auto baseIncrement = MathConstants<NumericType>::twoPi / sampleRate;
|
||||
|
||||
if (context.isBypassed)
|
||||
context.getOutputBlock().clear();
|
||||
|
||||
if (frequency.isSmoothing())
|
||||
{
|
||||
auto* buffer = rampBuffer.getRawDataPointer();
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
buffer[i] = phase.advance (baseIncrement * frequency.getNextValue())
|
||||
- MathConstants<NumericType>::pi;
|
||||
|
||||
if (! context.isBypassed)
|
||||
{
|
||||
size_t ch;
|
||||
|
||||
if (context.usesSeparateInputAndOutputBlocks())
|
||||
{
|
||||
for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
|
||||
{
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
auto* src = inBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = src[i] + generator (buffer[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
|
||||
{
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] += generator (buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (; ch < numChannels; ++ch)
|
||||
{
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = generator (buffer[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto freq = baseIncrement * frequency.getNextValue();
|
||||
auto p = phase;
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
frequency.skip (static_cast<int> (len));
|
||||
p.advance (freq * static_cast<NumericType> (len));
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t ch;
|
||||
|
||||
if (context.usesSeparateInputAndOutputBlocks())
|
||||
{
|
||||
for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
|
||||
{
|
||||
p = phase;
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
auto* src = inBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = src[i] + generator (p.advance (freq) - MathConstants<NumericType>::pi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ch = 0; ch < jmin (numChannels, inputChannels); ++ch)
|
||||
{
|
||||
p = phase;
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] += generator (p.advance (freq) - MathConstants<NumericType>::pi);
|
||||
}
|
||||
}
|
||||
|
||||
for (; ch < numChannels; ++ch)
|
||||
{
|
||||
p = phase;
|
||||
auto* dst = outBlock.getChannelPointer (ch);
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
dst[i] = generator (p.advance (freq) - MathConstants<NumericType>::pi);
|
||||
}
|
||||
}
|
||||
|
||||
phase = p;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
std::function<NumericType (NumericType)> generator;
|
||||
std::unique_ptr<LookupTableTransform<NumericType>> lookupTable;
|
||||
Array<NumericType> rampBuffer;
|
||||
SmoothedValue<NumericType> frequency { static_cast<NumericType> (440.0) };
|
||||
NumericType sampleRate = 48000.0;
|
||||
Phase<NumericType> phase;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
154
deps/juce/modules/juce_dsp/widgets/juce_Phaser.cpp
vendored
Normal file
154
deps/juce/modules/juce_dsp/widgets/juce_Phaser.cpp
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
Phaser<SampleType>::Phaser()
|
||||
{
|
||||
auto oscFunction = [] (SampleType x) { return std::sin (x); };
|
||||
osc.initialise (oscFunction);
|
||||
|
||||
for (auto n = 0; n < numStages; ++n)
|
||||
{
|
||||
filters.add (new FirstOrderTPTFilter<SampleType>());
|
||||
filters[n]->setType (FirstOrderTPTFilterType::allpass);
|
||||
}
|
||||
|
||||
dryWet.setMixingRule (DryWetMixingRule::linear);
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::setRate (SampleType newRateHz)
|
||||
{
|
||||
jassert (isPositiveAndBelow (newRateHz, static_cast<SampleType> (100.0)));
|
||||
|
||||
rate = newRateHz;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::setDepth (SampleType newDepth)
|
||||
{
|
||||
jassert (isPositiveAndNotGreaterThan (newDepth, static_cast<SampleType> (1.0)));
|
||||
|
||||
depth = newDepth;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::setCentreFrequency (SampleType newCentreHz)
|
||||
{
|
||||
jassert (isPositiveAndBelow (newCentreHz, static_cast<SampleType> (sampleRate * 0.5)));
|
||||
|
||||
centreFrequency = newCentreHz;
|
||||
normCentreFrequency = mapFromLog10 (centreFrequency, static_cast<SampleType> (20.0), static_cast<SampleType> (jmin (20000.0, 0.49 * sampleRate)));
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::setFeedback (SampleType newFeedback)
|
||||
{
|
||||
jassert (newFeedback >= static_cast<SampleType> (-1.0) && newFeedback <= static_cast<SampleType> (1.0));
|
||||
|
||||
feedback = newFeedback;
|
||||
update();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::setMix (SampleType newMix)
|
||||
{
|
||||
jassert (isPositiveAndNotGreaterThan (newMix, static_cast<SampleType> (1.0)));
|
||||
|
||||
mix = newMix;
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::prepare (const ProcessSpec& spec)
|
||||
{
|
||||
jassert (spec.sampleRate > 0);
|
||||
jassert (spec.numChannels > 0);
|
||||
|
||||
sampleRate = spec.sampleRate;
|
||||
|
||||
for (auto n = 0; n < numStages; ++n)
|
||||
filters[n]->prepare (spec);
|
||||
|
||||
dryWet.prepare (spec);
|
||||
feedbackVolume.resize (spec.numChannels);
|
||||
lastOutput.resize (spec.numChannels);
|
||||
|
||||
auto specDown = spec;
|
||||
specDown.sampleRate /= (double) maxUpdateCounter;
|
||||
specDown.maximumBlockSize = specDown.maximumBlockSize / (uint32) maxUpdateCounter + 1;
|
||||
|
||||
osc.prepare (specDown);
|
||||
bufferFrequency.setSize (1, (int) specDown.maximumBlockSize, false, false, true);
|
||||
|
||||
update();
|
||||
reset();
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::reset()
|
||||
{
|
||||
std::fill (lastOutput.begin(), lastOutput.end(), static_cast<SampleType> (0));
|
||||
|
||||
for (auto n = 0; n < numStages; ++n)
|
||||
filters[n]->reset();
|
||||
|
||||
osc.reset();
|
||||
dryWet.reset();
|
||||
|
||||
oscVolume.reset (sampleRate / (double) maxUpdateCounter, 0.05);
|
||||
|
||||
for (auto& vol : feedbackVolume)
|
||||
vol.reset (sampleRate, 0.05);
|
||||
|
||||
updateCounter = 0;
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void Phaser<SampleType>::update()
|
||||
{
|
||||
osc.setFrequency (rate);
|
||||
oscVolume.setTargetValue (depth * (SampleType) 0.5);
|
||||
dryWet.setWetMixProportion (mix);
|
||||
|
||||
for (auto& vol : feedbackVolume)
|
||||
vol.setTargetValue (feedback);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template class Phaser<float>;
|
||||
template class Phaser<double>;
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
206
deps/juce/modules/juce_dsp/widgets/juce_Phaser.h
vendored
Normal file
206
deps/juce/modules/juce_dsp/widgets/juce_Phaser.h
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
A 6 stage phaser that modulates first order all-pass filters to create sweeping
|
||||
notches in the magnitude frequency response.
|
||||
|
||||
This audio effect can be controlled with standard phaser parameters: the speed
|
||||
and depth of the LFO controlling the frequency response, a mix control, a
|
||||
feedback control, and the centre frequency of the modulation.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename SampleType>
|
||||
class Phaser
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Constructor. */
|
||||
Phaser();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the rate (in Hz) of the LFO modulating the phaser all-pass filters. This
|
||||
rate must be lower than 100 Hz.
|
||||
*/
|
||||
void setRate (SampleType newRateHz);
|
||||
|
||||
/** Sets the volume (between 0 and 1) of the LFO modulating the phaser all-pass
|
||||
filters.
|
||||
*/
|
||||
void setDepth (SampleType newDepth);
|
||||
|
||||
/** Sets the centre frequency (in Hz) of the phaser all-pass filters modulation.
|
||||
*/
|
||||
void setCentreFrequency (SampleType newCentreHz);
|
||||
|
||||
/** Sets the feedback volume (between -1 and 1) of the phaser. Negative can be
|
||||
used to get specific phaser sounds.
|
||||
*/
|
||||
void setFeedback (SampleType newFeedback);
|
||||
|
||||
/** Sets the amount of dry and wet signal in the output of the phaser (between 0
|
||||
for full dry and 1 for full wet).
|
||||
*/
|
||||
void setMix (SampleType newMix);
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the processor. */
|
||||
void prepare (const ProcessSpec& spec);
|
||||
|
||||
/** Resets the internal state variables of the processor. */
|
||||
void reset();
|
||||
|
||||
//==============================================================================
|
||||
/** Processes the input and output samples supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumChannels() == numChannels);
|
||||
jassert (inputBlock.getNumChannels() == lastOutput.size());
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
if (context.isBypassed)
|
||||
{
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
int numSamplesDown = 0;
|
||||
auto counter = updateCounter;
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
{
|
||||
if (counter == 0)
|
||||
numSamplesDown++;
|
||||
|
||||
counter++;
|
||||
|
||||
if (counter == maxUpdateCounter)
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
if (numSamplesDown > 0)
|
||||
{
|
||||
auto freqBlock = AudioBlock<SampleType>(bufferFrequency).getSubBlock (0, (size_t) numSamplesDown);
|
||||
auto contextFreq = ProcessContextReplacing<SampleType> (freqBlock);
|
||||
freqBlock.clear();
|
||||
|
||||
osc.process (contextFreq);
|
||||
freqBlock.multiplyBy (oscVolume);
|
||||
}
|
||||
|
||||
auto* freqSamples = bufferFrequency.getWritePointer (0);
|
||||
|
||||
for (int i = 0; i < numSamplesDown; ++i)
|
||||
{
|
||||
auto lfo = jlimit (static_cast<SampleType> (0.0),
|
||||
static_cast<SampleType> (1.0),
|
||||
freqSamples[i] + normCentreFrequency);
|
||||
|
||||
freqSamples[i] = mapToLog10 (lfo, static_cast<SampleType> (20.0),
|
||||
static_cast<SampleType> (jmin (20000.0, 0.49 * sampleRate)));
|
||||
}
|
||||
|
||||
auto currentFrequency = filters[0]->getCutoffFrequency();
|
||||
dryWet.pushDrySamples (inputBlock);
|
||||
|
||||
for (size_t channel = 0; channel < numChannels; ++channel)
|
||||
{
|
||||
counter = updateCounter;
|
||||
int k = 0;
|
||||
|
||||
auto* inputSamples = inputBlock .getChannelPointer (channel);
|
||||
auto* outputSamples = outputBlock.getChannelPointer (channel);
|
||||
|
||||
for (size_t i = 0; i < numSamples; ++i)
|
||||
{
|
||||
auto input = inputSamples[i];
|
||||
auto output = input - lastOutput[channel];
|
||||
|
||||
if (i == 0 && counter != 0)
|
||||
for (int n = 0; n < numStages; ++n)
|
||||
filters[n]->setCutoffFrequency (currentFrequency);
|
||||
|
||||
if (counter == 0)
|
||||
{
|
||||
for (int n = 0; n < numStages; ++n)
|
||||
filters[n]->setCutoffFrequency (freqSamples[k]);
|
||||
|
||||
k++;
|
||||
}
|
||||
|
||||
for (int n = 0; n < numStages; ++n)
|
||||
output = filters[n]->processSample ((int) channel, output);
|
||||
|
||||
outputSamples[i] = output;
|
||||
lastOutput[channel] = output * feedbackVolume[channel].getNextValue();
|
||||
|
||||
counter++;
|
||||
|
||||
if (counter == maxUpdateCounter)
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dryWet.mixWetSamples (outputBlock);
|
||||
updateCounter = (updateCounter + (int) numSamples) % maxUpdateCounter;
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update();
|
||||
|
||||
//==============================================================================
|
||||
Oscillator<SampleType> osc;
|
||||
OwnedArray<FirstOrderTPTFilter<SampleType>> filters;
|
||||
SmoothedValue<SampleType, ValueSmoothingTypes::Linear> oscVolume;
|
||||
std::vector<SmoothedValue<SampleType, ValueSmoothingTypes::Linear>> feedbackVolume { 2 };
|
||||
DryWetMixer<SampleType> dryWet;
|
||||
std::vector<SampleType> lastOutput { 2 };
|
||||
AudioBuffer<SampleType> bufferFrequency;
|
||||
SampleType normCentreFrequency = 0.5;
|
||||
double sampleRate = 44100.0;
|
||||
|
||||
int updateCounter = 0;
|
||||
static constexpr int maxUpdateCounter = 4;
|
||||
|
||||
SampleType rate = 1.0, depth = 0.5, feedback = 0.0, mix = 0.5;
|
||||
SampleType centreFrequency = 1300.0;
|
||||
static constexpr int numStages = 6;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
115
deps/juce/modules/juce_dsp/widgets/juce_Reverb.h
vendored
Normal file
115
deps/juce/modules/juce_dsp/widgets/juce_Reverb.h
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
Processor wrapper around juce::Reverb for easy integration into ProcessorChain.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
class Reverb
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an uninitialised Reverb processor. Call prepare() before first use. */
|
||||
Reverb() = default;
|
||||
|
||||
//==============================================================================
|
||||
using Parameters = juce::Reverb::Parameters;
|
||||
|
||||
/** Returns the reverb's current parameters. */
|
||||
const Parameters& getParameters() const noexcept { return reverb.getParameters(); }
|
||||
|
||||
/** Applies a new set of parameters to the reverb.
|
||||
Note that this doesn't attempt to lock the reverb, so if you call this in parallel with
|
||||
the process method, you may get artifacts.
|
||||
*/
|
||||
void setParameters (const Parameters& newParams) { reverb.setParameters (newParams); }
|
||||
|
||||
/** Returns true if the reverb is enabled. */
|
||||
bool isEnabled() const noexcept { return enabled; }
|
||||
|
||||
/** Enables/disables the reverb. */
|
||||
void setEnabled (bool newValue) noexcept { enabled = newValue; }
|
||||
|
||||
//==============================================================================
|
||||
/** Initialises the reverb. */
|
||||
void prepare (const ProcessSpec& spec)
|
||||
{
|
||||
reverb.setSampleRate (spec.sampleRate);
|
||||
}
|
||||
|
||||
/** Resets the reverb's internal state. */
|
||||
void reset() noexcept
|
||||
{
|
||||
reverb.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Applies the reverb to a mono or stereo buffer. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) noexcept
|
||||
{
|
||||
const auto& inputBlock = context.getInputBlock();
|
||||
auto& outputBlock = context.getOutputBlock();
|
||||
const auto numInChannels = inputBlock.getNumChannels();
|
||||
const auto numOutChannels = outputBlock.getNumChannels();
|
||||
const auto numSamples = outputBlock.getNumSamples();
|
||||
|
||||
jassert (inputBlock.getNumSamples() == numSamples);
|
||||
|
||||
outputBlock.copyFrom (inputBlock);
|
||||
|
||||
if (! enabled || context.isBypassed)
|
||||
return;
|
||||
|
||||
if (numInChannels == 1 && numOutChannels == 1)
|
||||
{
|
||||
reverb.processMono (outputBlock.getChannelPointer (0), (int) numSamples);
|
||||
}
|
||||
else if (numInChannels == 2 && numOutChannels == 2)
|
||||
{
|
||||
reverb.processStereo (outputBlock.getChannelPointer (0),
|
||||
outputBlock.getChannelPointer (1),
|
||||
(int) numSamples);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // invalid channel configuration
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
juce::Reverb reverb;
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
85
deps/juce/modules/juce_dsp/widgets/juce_WaveShaper.h
vendored
Normal file
85
deps/juce/modules/juce_dsp/widgets/juce_WaveShaper.h
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
namespace dsp
|
||||
{
|
||||
|
||||
/**
|
||||
Applies waveshaping to audio samples as single samples or AudioBlocks.
|
||||
|
||||
@tags{DSP}
|
||||
*/
|
||||
template <typename FloatType, typename Function = FloatType (*) (FloatType)>
|
||||
struct WaveShaper
|
||||
{
|
||||
Function functionToUse;
|
||||
|
||||
//==============================================================================
|
||||
/** Called before processing starts. */
|
||||
void prepare (const ProcessSpec&) noexcept {}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the result of processing a single sample. */
|
||||
template <typename SampleType>
|
||||
SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType inputSample) const noexcept
|
||||
{
|
||||
return functionToUse (inputSample);
|
||||
}
|
||||
|
||||
/** Processes the input and output buffers supplied in the processing context. */
|
||||
template <typename ProcessContext>
|
||||
void process (const ProcessContext& context) const noexcept
|
||||
{
|
||||
if (context.isBypassed)
|
||||
{
|
||||
if (context.usesSeparateInputAndOutputBlocks())
|
||||
context.getOutputBlock().copyFrom (context.getInputBlock());
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioBlock<FloatType>::process (context.getInputBlock(),
|
||||
context.getOutputBlock(),
|
||||
functionToUse);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() noexcept {}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// Although clang supports C++17, their standard library still has no invoke_result
|
||||
// support. Remove the "|| JUCE_CLANG" once clang supports this properly!
|
||||
#if (! JUCE_CXX17_IS_AVAILABLE) || (JUCE_CLANG && ! JUCE_WINDOWS)
|
||||
template <typename Functor>
|
||||
static WaveShaper<typename std::result_of<Functor>, Functor> CreateWaveShaper (Functor functionToUse) { return {functionToUse}; }
|
||||
#else
|
||||
template <typename Functor>
|
||||
static WaveShaper<typename std::invoke_result<Functor>, Functor> CreateWaveShaper (Functor functionToUse) { return {functionToUse}; }
|
||||
#endif
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace juce
|
Reference in New Issue
Block a user