tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_Chorus.cpp
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
14ChorusPlugin::ChorusPlugin (PluginCreationInfo info) : Plugin (info)
15{
16 auto um = getUndoManager();
17
18 depthMs.referTo (state, IDs::depthMs, um, 3.0f);
19 speedHz.referTo (state, IDs::speedHz, um, 1.0f);
20 width.referTo (state, IDs::width, um, 0.5f);
21 mixProportion.referTo (state, IDs::mixProportion, um, 0.5f);
22}
23
24ChorusPlugin::~ChorusPlugin()
25{
26 notifyListenersOfDeletion();
27}
28
29const char* ChorusPlugin::xmlTypeName = "chorus";
30
31void ChorusPlugin::initialise (const PluginInitialisationInfo& info)
32{
33 const float delayMs = 20.0f;
34 auto maxLengthMs = 1 + juce::roundToInt (delayMs + depthMs);
35 auto bufferSizeSamples = juce::roundToInt ((maxLengthMs * info.sampleRate) / 1000.0);
36 delayBuffer.ensureMaxBufferSize (bufferSizeSamples);
37 delayBuffer.clearBuffer();
38 phase = 0.0f;
39}
40
41void ChorusPlugin::deinitialise()
42{
43 delayBuffer.releaseBuffer();
44}
45
46void ChorusPlugin::applyToBuffer (const PluginRenderContext& fc)
47{
48 if (fc.destBuffer == nullptr)
49 return;
50
51 SCOPED_REALTIME_CHECK
52
53 float ph = 0.0f;
54 int bufPos = 0;
55
56 const float delayMs = 20.0f;
57 const float minSweepSamples = (float) ((delayMs * sampleRate) / 1000.0);
58 const float maxSweepSamples = (float) (((delayMs + depthMs) * sampleRate) / 1000.0);
59 const float speed = (float)((juce::MathConstants<double>::pi * 2.0) / (sampleRate / speedHz));
60 const int maxLengthMs = 1 + juce::roundToInt (delayMs + depthMs);
61 const int lengthInSamples = juce::roundToInt ((maxLengthMs * sampleRate) / 1000.0);
62
63 delayBuffer.ensureMaxBufferSize (lengthInSamples);
64
65 const float feedbackGain = 0.0f; // xxx not sure why this value was here..
66 const float lfoFactor = 0.5f * (maxSweepSamples - minSweepSamples);
67 const float lfoOffset = minSweepSamples + lfoFactor;
68
69 AudioFadeCurve::CrossfadeLevels wetDry (mixProportion);
70
71 clearChannels (*fc.destBuffer, 2, -1, fc.bufferStartSample, fc.bufferNumSamples);
72
73 for (int chan = std::min (2, fc.destBuffer->getNumChannels()); --chan >= 0;)
74 {
75 float* const d = fc.destBuffer->getWritePointer (chan, fc.bufferStartSample);
76 float* const buf = (float*) delayBuffer.buffers[chan].getData();
77
78 ph = phase;
79 if (chan > 0)
81
82 bufPos = delayBuffer.bufferPos;
83
84 for (int i = 0; i < fc.bufferNumSamples; ++i)
85 {
86 const float in = d[i];
87
88 const float sweep = lfoOffset + lfoFactor * sinf (ph);
89 ph += speed;
90
91 int intSweepPos = juce::roundToInt (sweep);
92 const float interp = sweep - intSweepPos;
93 intSweepPos = bufPos + lengthInSamples - intSweepPos;
94
95 const float out = buf[(intSweepPos - 1) % lengthInSamples] * interp
96 + buf[intSweepPos % lengthInSamples] * (1.0f - interp);
97
98 float n = in + out * feedbackGain;
99
101
102 buf[bufPos] = n;
103
104 d[i] = out * wetDry.gain1 + in * wetDry.gain2;
105
106 bufPos = (bufPos + 1) % lengthInSamples;
107 }
108 }
109
110 jassert (! hasFloatingPointDenormaliseOccurred());
111 zeroDenormalisedValuesIfNeeded (*fc.destBuffer);
112
113 phase = ph;
114 if (phase >= juce::MathConstants<float>::pi * 2)
116
117 delayBuffer.bufferPos = bufPos;
118}
119
120void ChorusPlugin::restorePluginStateFromValueTree (const juce::ValueTree& v)
121{
122 copyPropertiesToCachedValues (v, depthMs, width, mixProportion, speedHz);
123
124 for (auto p : getAutomatableParameters())
125 p->updateFromAttachedValue();
126}
127
128}} // namespace tracktion { inline namespace engine
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
#define JUCE_UNDENORMALISE(x)
#define jassert(expression)
typedef float
T min(T... args)
int roundToInt(const FloatType value) noexcept
Passed into Plugins when they are being initialised, to give them useful contextual information that ...
sinf
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.