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_Reverb.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 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
38class Reverb
39{
40public:
41 //==============================================================================
42 Reverb()
43 {
45 setSampleRate (44100.0);
46 }
47
48 //==============================================================================
51 {
52 float roomSize = 0.5f;
53 float damping = 0.5f;
54 float wetLevel = 0.33f;
55 float dryLevel = 0.4f;
56 float width = 1.0f;
57 float freezeMode = 0.0f;
59 };
60
61 //==============================================================================
63 const Parameters& getParameters() const noexcept { return parameters; }
64
70 {
71 const float wetScaleFactor = 3.0f;
72 const float dryScaleFactor = 2.0f;
73
74 const float wet = newParams.wetLevel * wetScaleFactor;
75 dryGain.setTargetValue (newParams.dryLevel * dryScaleFactor);
76 wetGain1.setTargetValue (0.5f * wet * (1.0f + newParams.width));
77 wetGain2.setTargetValue (0.5f * wet * (1.0f - newParams.width));
78
79 gain = isFrozen (newParams.freezeMode) ? 0.0f : 0.015f;
80 parameters = newParams;
81 updateDamping();
82 }
83
84 //==============================================================================
88 void setSampleRate (const double sampleRate)
89 {
90 jassert (sampleRate > 0);
91
92 static const short combTunings[] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }; // (at 44100Hz)
93 static const short allPassTunings[] = { 556, 441, 341, 225 };
94 const int stereoSpread = 23;
95 const int intSampleRate = (int) sampleRate;
96
97 for (int i = 0; i < numCombs; ++i)
98 {
99 comb[0][i].setSize ((intSampleRate * combTunings[i]) / 44100);
100 comb[1][i].setSize ((intSampleRate * (combTunings[i] + stereoSpread)) / 44100);
101 }
102
103 for (int i = 0; i < numAllPasses; ++i)
104 {
105 allPass[0][i].setSize ((intSampleRate * allPassTunings[i]) / 44100);
106 allPass[1][i].setSize ((intSampleRate * (allPassTunings[i] + stereoSpread)) / 44100);
107 }
108
109 const double smoothTime = 0.01;
110 damping .reset (sampleRate, smoothTime);
111 feedback.reset (sampleRate, smoothTime);
112 dryGain .reset (sampleRate, smoothTime);
113 wetGain1.reset (sampleRate, smoothTime);
114 wetGain2.reset (sampleRate, smoothTime);
115 }
116
118 void reset()
119 {
120 for (int j = 0; j < numChannels; ++j)
121 {
122 for (int i = 0; i < numCombs; ++i)
123 comb[j][i].clear();
124
125 for (int i = 0; i < numAllPasses; ++i)
126 allPass[j][i].clear();
127 }
128 }
129
130 //==============================================================================
132 void processStereo (float* const left, float* const right, const int numSamples) noexcept
133 {
134 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
135 jassert (left != nullptr && right != nullptr);
136
137 for (int i = 0; i < numSamples; ++i)
138 {
139 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
140 const float input = (left[i] + right[i]) * gain;
141 float outL = 0, outR = 0;
142
143 const float damp = damping.getNextValue();
144 const float feedbck = feedback.getNextValue();
145
146 for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
147 {
148 outL += comb[0][j].process (input, damp, feedbck);
149 outR += comb[1][j].process (input, damp, feedbck);
150 }
151
152 for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
153 {
154 outL = allPass[0][j].process (outL);
155 outR = allPass[1][j].process (outR);
156 }
157
158 const float dry = dryGain.getNextValue();
159 const float wet1 = wetGain1.getNextValue();
160 const float wet2 = wetGain2.getNextValue();
161
162 left[i] = outL * wet1 + outR * wet2 + left[i] * dry;
163 right[i] = outR * wet1 + outL * wet2 + right[i] * dry;
164 }
165 JUCE_END_IGNORE_WARNINGS_MSVC
166 }
167
169 void processMono (float* const samples, const int numSamples) noexcept
170 {
171 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
172 jassert (samples != nullptr);
173
174 for (int i = 0; i < numSamples; ++i)
175 {
176 const float input = samples[i] * gain;
177 float output = 0;
178
179 const float damp = damping.getNextValue();
180 const float feedbck = feedback.getNextValue();
181
182 for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
183 output += comb[0][j].process (input, damp, feedbck);
184
185 for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
186 output = allPass[0][j].process (output);
187
188 const float dry = dryGain.getNextValue();
189 const float wet1 = wetGain1.getNextValue();
190
191 samples[i] = output * wet1 + samples[i] * dry;
192 }
193 JUCE_END_IGNORE_WARNINGS_MSVC
194 }
195
196private:
197 //==============================================================================
198 static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; }
199
200 void updateDamping() noexcept
201 {
202 const float roomScaleFactor = 0.28f;
203 const float roomOffset = 0.7f;
204 const float dampScaleFactor = 0.4f;
205
206 if (isFrozen (parameters.freezeMode))
207 setDamping (0.0f, 1.0f);
208 else
209 setDamping (parameters.damping * dampScaleFactor,
210 parameters.roomSize * roomScaleFactor + roomOffset);
211 }
212
213 void setDamping (const float dampingToUse, const float roomSizeToUse) noexcept
214 {
216 feedback.setTargetValue (roomSizeToUse);
217 }
218
219 //==============================================================================
220 class CombFilter
221 {
222 public:
223 CombFilter() noexcept {}
224
225 void setSize (const int size)
226 {
227 if (size != bufferSize)
228 {
229 bufferIndex = 0;
230 buffer.malloc (size);
231 bufferSize = size;
232 }
233
234 clear();
235 }
236
237 void clear() noexcept
238 {
239 last = 0;
240 buffer.clear ((size_t) bufferSize);
241 }
242
243 float process (const float input, const float damp, const float feedbackLevel) noexcept
244 {
245 const float output = buffer[bufferIndex];
246 last = (output * (1.0f - damp)) + (last * damp);
247 JUCE_UNDENORMALISE (last);
248
249 float temp = input + (last * feedbackLevel);
250 JUCE_UNDENORMALISE (temp);
251 buffer[bufferIndex] = temp;
252 bufferIndex = (bufferIndex + 1) % bufferSize;
253 return output;
254 }
255
256 private:
257 HeapBlock<float> buffer;
258 int bufferSize = 0, bufferIndex = 0;
259 float last = 0.0f;
260
261 JUCE_DECLARE_NON_COPYABLE (CombFilter)
262 };
263
264 //==============================================================================
265 class AllPassFilter
266 {
267 public:
268 AllPassFilter() noexcept {}
269
270 void setSize (const int size)
271 {
272 if (size != bufferSize)
273 {
274 bufferIndex = 0;
275 buffer.malloc (size);
276 bufferSize = size;
277 }
278
279 clear();
280 }
281
282 void clear() noexcept
283 {
284 buffer.clear ((size_t) bufferSize);
285 }
286
287 float process (const float input) noexcept
288 {
289 const float bufferedValue = buffer [bufferIndex];
290 float temp = input + (bufferedValue * 0.5f);
291 JUCE_UNDENORMALISE (temp);
292 buffer [bufferIndex] = temp;
293 bufferIndex = (bufferIndex + 1) % bufferSize;
294 return bufferedValue - input;
295 }
296
297 private:
298 HeapBlock<float> buffer;
299 int bufferSize = 0, bufferIndex = 0;
300
301 JUCE_DECLARE_NON_COPYABLE (AllPassFilter)
302 };
303
304 //==============================================================================
305 enum { numCombs = 8, numAllPasses = 4, numChannels = 2 };
306
307 Parameters parameters;
308 float gain;
309
310 CombFilter comb [numChannels][numCombs];
311 AllPassFilter allPass [numChannels][numAllPasses];
312
313 SmoothedValue<float> damping, feedback, dryGain, wetGain1, wetGain2;
314
316};
317
318} // namespace juce
Performs a simple reverb effect on a stream of audio data.
Definition juce_Reverb.h:39
float roomSize
Room size, 0 to 1.0, where 1.0 is big, 0 is small.
Definition juce_Reverb.h:52
void processMono(float *const samples, const int numSamples) noexcept
Applies the reverb to a single mono channel of audio data.
float width
Reverb width, 0 to 1.0, where 1.0 is very wide.
Definition juce_Reverb.h:56
void reset()
Clears the reverb's buffers.
void processStereo(float *const left, float *const right, const int numSamples) noexcept
Applies the reverb to two stereo channels of audio data.
float dryLevel
Dry level, 0 to 1.0.
Definition juce_Reverb.h:55
float wetLevel
Wet level, 0 to 1.0.
Definition juce_Reverb.h:54
float freezeMode
Freeze mode - values < 0.5 are "normal" mode, values > 0.5 put the reverb into a continuous feedback ...
Definition juce_Reverb.h:57
void setParameters(const Parameters &newParams)
Applies a new set of parameters to the reverb.
Definition juce_Reverb.h:69
const Parameters & getParameters() const noexcept
Returns the reverb's current parameters.
Definition juce_Reverb.h:63
void setSampleRate(const double sampleRate)
Sets the sample rate that will be used for the reverb.
Definition juce_Reverb.h:88
float damping
Damping, 0 to 1.0, where 0 is not damped, 1.0 is fully damped.
Definition juce_Reverb.h:53
Holds the parameters being used by a Reverb object.
Definition juce_Reverb.h:51
FloatType getNextValue() noexcept
Compute the next value.
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
void setTargetValue(FloatType newValue) noexcept
Set the next value to ramp towards.
#define JUCE_UNDENORMALISE(x)
This macro can be applied to a float variable to check whether it contains a denormalised value,...
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE(className)
This is a shorthand macro for deleting a class's copy constructor and copy assignment operator.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
typedef int
JUCE Namespace.
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)