JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_DelayLine.h
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce::dsp
27{
28
29//==============================================================================
34namespace DelayLineInterpolationTypes
35{
43 struct None {};
44
53 struct Linear {};
54
63 struct Lagrange3rd {};
64
74 struct Thiran {};
75}
76
77//==============================================================================
91template <typename SampleType, typename InterpolationType = DelayLineInterpolationTypes::Linear>
93{
94public:
95 //==============================================================================
97 DelayLine();
98
100 explicit DelayLine (int maximumDelayInSamples);
101
102 //==============================================================================
104 void setDelay (SampleType newDelayInSamples);
105
107 SampleType getDelay() const;
108
109 //==============================================================================
111 void prepare (const ProcessSpec& spec);
112
120
126 int getMaximumDelayInSamples() const noexcept { return totalSize - 2; }
127
129 void reset();
130
131 //==============================================================================
140 void pushSample (int channel, SampleType sample);
141
159 SampleType popSample (int channel, SampleType delayInSamples = -1, bool updateReadPointer = true);
160
161 //==============================================================================
169 template <typename ProcessContext>
170 void process (const ProcessContext& context) noexcept
171 {
172 const auto& inputBlock = context.getInputBlock();
173 auto& outputBlock = context.getOutputBlock();
174 const auto numChannels = outputBlock.getNumChannels();
175 const auto numSamples = outputBlock.getNumSamples();
176
177 jassert (inputBlock.getNumChannels() == numChannels);
178 jassert (inputBlock.getNumChannels() == writePos.size());
179 jassert (inputBlock.getNumSamples() == numSamples);
180
181 if (context.isBypassed)
182 {
183 outputBlock.copyFrom (inputBlock);
184 return;
185 }
186
187 for (size_t channel = 0; channel < numChannels; ++channel)
188 {
189 auto* inputSamples = inputBlock.getChannelPointer (channel);
190 auto* outputSamples = outputBlock.getChannelPointer (channel);
191
192 for (size_t i = 0; i < numSamples; ++i)
193 {
194 pushSample ((int) channel, inputSamples[i]);
195 outputSamples[i] = popSample ((int) channel);
196 }
197 }
198 }
199
200private:
201 //==============================================================================
202 SampleType interpolateSample (int channel)
203 {
204 if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>)
205 {
206 auto index = (readPos[(size_t) channel] + delayInt) % totalSize;
207 return bufferData.getSample (channel, index);
208 }
209 else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>)
210 {
211 auto index1 = readPos[(size_t) channel] + delayInt;
212 auto index2 = index1 + 1;
213
214 if (index2 >= totalSize)
215 {
216 index1 %= totalSize;
217 index2 %= totalSize;
218 }
219
220 auto value1 = bufferData.getSample (channel, index1);
221 auto value2 = bufferData.getSample (channel, index2);
222
223 return value1 + delayFrac * (value2 - value1);
224 }
225 else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
226 {
227 auto index1 = readPos[(size_t) channel] + delayInt;
228 auto index2 = index1 + 1;
229 auto index3 = index2 + 1;
230 auto index4 = index3 + 1;
231
232 if (index4 >= totalSize)
233 {
234 index1 %= totalSize;
235 index2 %= totalSize;
236 index3 %= totalSize;
237 index4 %= totalSize;
238 }
239
240 auto* samples = bufferData.getReadPointer (channel);
241
242 auto value1 = samples[index1];
243 auto value2 = samples[index2];
244 auto value3 = samples[index3];
245 auto value4 = samples[index4];
246
247 auto d1 = delayFrac - 1.f;
248 auto d2 = delayFrac - 2.f;
249 auto d3 = delayFrac - 3.f;
250
251 auto c1 = -d1 * d2 * d3 / 6.f;
252 auto c2 = d2 * d3 * 0.5f;
253 auto c3 = -d1 * d3 * 0.5f;
254 auto c4 = d1 * d2 / 6.f;
255
256 return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);
257 }
258 else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
259 {
260 auto index1 = readPos[(size_t) channel] + delayInt;
261 auto index2 = index1 + 1;
262
263 if (index2 >= totalSize)
264 {
265 index1 %= totalSize;
266 index2 %= totalSize;
267 }
268
269 auto value1 = bufferData.getSample (channel, index1);
270 auto value2 = bufferData.getSample (channel, index2);
271
272 auto output = approximatelyEqual (delayFrac, (SampleType) 0) ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
273 v[(size_t) channel] = output;
274
275 return output;
276 }
277 }
278
279 //==============================================================================
280 void updateInternalVariables()
281 {
282 if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
283 {
284 if (delayFrac < (SampleType) 2.0 && delayInt >= 1)
285 {
286 delayFrac++;
287 delayInt--;
288 }
289 }
290 else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
291 {
292 if (delayFrac < (SampleType) 0.618 && delayInt >= 1)
293 {
294 delayFrac++;
295 delayInt--;
296 }
297
298 alpha = (1 - delayFrac) / (1 + delayFrac);
299 }
300 }
301
302 //==============================================================================
303 double sampleRate;
304
305 //==============================================================================
306 AudioBuffer<SampleType> bufferData;
308 std::vector<int> writePos, readPos;
309 SampleType delay = 0.0, delayFrac = 0.0;
310 int delayInt = 0, totalSize = 4;
311 SampleType alpha = 0.0;
312};
313
314} // namespace juce::dsp
Type getSample(int channel, int sampleIndex) const noexcept
Returns a sample from the buffer.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
A delay line processor featuring several algorithms for the fractional delay calculation,...
void prepare(const ProcessSpec &spec)
Initialises the processor.
int getMaximumDelayInSamples() const noexcept
Gets the maximum possible delay in samples.
void setDelay(SampleType newDelayInSamples)
Sets the delay in samples.
SampleType popSample(int channel, SampleType delayInSamples=-1, bool updateReadPointer=true)
Pops a single sample from one channel of the delay line.
DelayLine()
Default constructor.
void setMaximumDelayInSamples(int maxDelayInSamples)
Sets a new maximum delay in samples.
SampleType getDelay() const
Returns the current delay in samples.
void process(const ProcessContext &context) noexcept
Processes the input and output samples supplied in the processing context.
void reset()
Resets the internal state variables of the processor.
void pushSample(int channel, SampleType sample)
Pushes a single sample into one channel of the delay line.
#define jassert(expression)
Platform-independent assertion macro.
Successive samples in the delay line will be interpolated using a 3rd order Lagrange interpolator.
Successive samples in the delay line will be linearly interpolated.
No interpolation between successive samples in the delay line will be performed.
Successive samples in the delay line will be interpolated using 1st order Thiran interpolation.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
T size(T... args)
This structure is passed into a DSP algorithm's prepare() method, and contains information about vari...
typedef size_t