11namespace tracktion {
inline namespace engine
14DelayPlugin::DelayPlugin (PluginCreationInfo info) : Plugin (info)
16 feedbackDb = addParam (
"feedback",
TRANS(
"Feedback"), { getMinDelayFeedbackDb(), 0.0f },
18 [] (
const juce::String& s) {
return dbStringToDb (s); });
20 mixProportion = addParam (
"mix proportion",
TRANS(
"Mix proportion"), { 0.0f, 1.0f },
24 auto um = getUndoManager();
26 feedbackValue.referTo (state, IDs::feedback, um, -6.0f);
27 mixValue.referTo (state, IDs::mix, um, 0.3f);
28 lengthMs.referTo (state, IDs::length, um, 150);
30 feedbackDb->attachToCurrentValue (feedbackValue);
31 mixProportion->attachToCurrentValue (mixValue);
34DelayPlugin::~DelayPlugin()
36 notifyListenersOfDeletion();
38 feedbackDb->detachFromCurrentValue();
39 mixProportion->detachFromCurrentValue();
42const char* DelayPlugin::xmlTypeName =
"delay";
46 const int lengthInSamples = (
int) (lengthMs * info.sampleRate / 1000.0);
47 delayBuffer.ensureMaxBufferSize (lengthInSamples);
48 delayBuffer.clearBuffer();
51void DelayPlugin::deinitialise()
53 delayBuffer.releaseBuffer();
56void DelayPlugin::reset()
58 delayBuffer.clearBuffer();
68 const float feedbackGain = feedbackDb->getCurrentValue() > getMinDelayFeedbackDb()
69 ? dbToGain (feedbackDb->getCurrentValue()) : 0.0f;
73 const int lengthInSamples = (
int) (lengthMs * sampleRate / 1000.0);
74 delayBuffer.ensureMaxBufferSize (lengthInSamples);
76 const int offset = delayBuffer.bufferPos;
83 float*
const buf = (
float*) delayBuffer.buffers[chan].getData();
87 float*
const b = buf + ((i + offset) % lengthInSamples);
90 d[i] = wetDry.gain2 * in + wetDry.gain1 * *b;
91 in += *b * feedbackGain;
97 delayBuffer.bufferPos = (delayBuffer.bufferPos + fc.
bufferNumSamples) % lengthInSamples;
99 zeroDenormalisedValuesIfNeeded (*fc.
destBuffer);
102void DelayPlugin::restorePluginStateFromValueTree (
const juce::ValueTree& v)
104 copyPropertiesToCachedValues (v, feedbackValue, mixValue, lengthMs);
106 for (
auto p : getAutomatableParameters())
107 p->updateFromAttachedValue();
110#if TRACKTION_UNIT_TESTS && ENGINE_UNIT_TESTS_DELAY_PLUGIN
117 DelayPluginTests() :
juce::UnitTest (
"DelayPlugin",
"Tracktion") {}
122 runRestoreStateTests();
126 void runRestoreStateTests()
128 auto edit = Edit::createSingleTrackEdit (*Engine::getEngines()[0]);
130 beginTest (
"Delay plugin instantiation");
132 Plugin::Ptr pluginPtr = edit->getPluginCache().createNewPlugin (DelayPlugin::xmlTypeName, {});
133 auto delay =
dynamic_cast<DelayPlugin*
> (pluginPtr.get());
134 expect (delay !=
nullptr);
137 beginTest (
"Restore feedback parameter from ValueTree");
139 Plugin::Ptr pluginPtr = edit->getPluginCache().createNewPlugin (DelayPlugin::xmlTypeName, {});
140 auto delay =
dynamic_cast<DelayPlugin*
> (pluginPtr.get());
141 expect (delay !=
nullptr);
143 float desiredValue = -30.0f;
145 auto preset = createValueTree (IDs::PLUGIN,
146 IDs::type, delay->getPluginName(),
147 IDs::feedback, desiredValue);
149 pluginPtr->restorePluginStateFromValueTree (preset);
150 pluginPtr->flushPluginStateToValueTree();
152 auto feedbackParam = delay->feedbackDb;
157 expect (! pluginPtr->state.hasProperty (IDs::parameters),
"State has erroneous parameters property");
162static DelayPluginTests delayPluginTests;
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
static String toString(Type decibels, int decimalPlaces=2, Type minusInfinityDb=Type(defaultMinusInfinitydB), bool shouldIncludeSuffix=true, StringRef customMinusInfinityString={})
float getFloatValue() const noexcept
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
void expectWithinAbsoluteError(ValueType actual, ValueType expected, ValueType maxAbsoluteError, String failureMessage=String())
#define TRANS(stringLiteral)
#define JUCE_UNDENORMALISE(x)
int roundToInt(const FloatType value) noexcept
Passed into Plugins when they are being initialised, to give them useful contextual information that ...
Calculates the two gain multipliers to use for mixing between two sources, given a position alpha fro...
The context passed to plugin render methods to provide it with buffers to fill.
int bufferNumSamples
The number of samples to write into the audio buffer.
juce::AudioBuffer< float > * destBuffer
The target audio buffer which needs to be filled.
int bufferStartSample
The index of the start point in the audio buffer from which data must be written.