1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - 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
23 namespace juce
24 {
25
IIRCoefficients()26 IIRCoefficients::IIRCoefficients() noexcept
27 {
28 zeromem (coefficients, sizeof (coefficients));
29 }
30
~IIRCoefficients()31 IIRCoefficients::~IIRCoefficients() noexcept {}
32
IIRCoefficients(const IIRCoefficients & other)33 IIRCoefficients::IIRCoefficients (const IIRCoefficients& other) noexcept
34 {
35 memcpy (coefficients, other.coefficients, sizeof (coefficients));
36 }
37
operator =(const IIRCoefficients & other)38 IIRCoefficients& IIRCoefficients::operator= (const IIRCoefficients& other) noexcept
39 {
40 memcpy (coefficients, other.coefficients, sizeof (coefficients));
41 return *this;
42 }
43
IIRCoefficients(double c1,double c2,double c3,double c4,double c5,double c6)44 IIRCoefficients::IIRCoefficients (double c1, double c2, double c3,
45 double c4, double c5, double c6) noexcept
46 {
47 auto a = 1.0 / c4;
48
49 coefficients[0] = (float) (c1 * a);
50 coefficients[1] = (float) (c2 * a);
51 coefficients[2] = (float) (c3 * a);
52 coefficients[3] = (float) (c5 * a);
53 coefficients[4] = (float) (c6 * a);
54 }
55
makeLowPass(double sampleRate,double frequency)56 IIRCoefficients IIRCoefficients::makeLowPass (double sampleRate,
57 double frequency) noexcept
58 {
59 return makeLowPass (sampleRate, frequency, 1.0 / MathConstants<double>::sqrt2);
60 }
61
makeLowPass(double sampleRate,double frequency,double Q)62 IIRCoefficients IIRCoefficients::makeLowPass (double sampleRate,
63 double frequency,
64 double Q) noexcept
65 {
66 jassert (sampleRate > 0.0);
67 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
68 jassert (Q > 0.0);
69
70 auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
71 auto nSquared = n * n;
72 auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
73
74 return IIRCoefficients (c1,
75 c1 * 2.0,
76 c1,
77 1.0,
78 c1 * 2.0 * (1.0 - nSquared),
79 c1 * (1.0 - 1.0 / Q * n + nSquared));
80 }
81
makeHighPass(double sampleRate,double frequency)82 IIRCoefficients IIRCoefficients::makeHighPass (double sampleRate,
83 double frequency) noexcept
84 {
85 return makeHighPass (sampleRate, frequency, 1.0 / std::sqrt(2.0));
86 }
87
makeHighPass(double sampleRate,double frequency,double Q)88 IIRCoefficients IIRCoefficients::makeHighPass (double sampleRate,
89 double frequency,
90 double Q) noexcept
91 {
92 jassert (sampleRate > 0.0);
93 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
94 jassert (Q > 0.0);
95
96 auto n = std::tan (MathConstants<double>::pi * frequency / sampleRate);
97 auto nSquared = n * n;
98 auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
99
100 return IIRCoefficients (c1,
101 c1 * -2.0,
102 c1,
103 1.0,
104 c1 * 2.0 * (nSquared - 1.0),
105 c1 * (1.0 - 1.0 / Q * n + nSquared));
106 }
107
makeBandPass(double sampleRate,double frequency)108 IIRCoefficients IIRCoefficients::makeBandPass (double sampleRate,
109 double frequency) noexcept
110 {
111 return makeBandPass (sampleRate, frequency, 1.0 / MathConstants<double>::sqrt2);
112 }
113
makeBandPass(double sampleRate,double frequency,double Q)114 IIRCoefficients IIRCoefficients::makeBandPass (double sampleRate,
115 double frequency,
116 double Q) noexcept
117 {
118 jassert (sampleRate > 0.0);
119 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
120 jassert (Q > 0.0);
121
122 auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
123 auto nSquared = n * n;
124 auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
125
126 return IIRCoefficients (c1 * n / Q,
127 0.0,
128 -c1 * n / Q,
129 1.0,
130 c1 * 2.0 * (1.0 - nSquared),
131 c1 * (1.0 - 1.0 / Q * n + nSquared));
132 }
133
makeNotchFilter(double sampleRate,double frequency)134 IIRCoefficients IIRCoefficients::makeNotchFilter (double sampleRate,
135 double frequency) noexcept
136 {
137 return makeNotchFilter (sampleRate, frequency, 1.0 / MathConstants<double>::sqrt2);
138 }
139
makeNotchFilter(double sampleRate,double frequency,double Q)140 IIRCoefficients IIRCoefficients::makeNotchFilter (double sampleRate,
141 double frequency,
142 double Q) noexcept
143 {
144 jassert (sampleRate > 0.0);
145 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
146 jassert (Q > 0.0);
147
148 auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
149 auto nSquared = n * n;
150 auto c1 = 1.0 / (1.0 + n / Q + nSquared);
151
152 return IIRCoefficients (c1 * (1.0 + nSquared),
153 2.0 * c1 * (1.0 - nSquared),
154 c1 * (1.0 + nSquared),
155 1.0,
156 c1 * 2.0 * (1.0 - nSquared),
157 c1 * (1.0 - n / Q + nSquared));
158 }
159
makeAllPass(double sampleRate,double frequency)160 IIRCoefficients IIRCoefficients::makeAllPass (double sampleRate,
161 double frequency) noexcept
162 {
163 return makeAllPass (sampleRate, frequency, 1.0 / MathConstants<double>::sqrt2);
164 }
165
makeAllPass(double sampleRate,double frequency,double Q)166 IIRCoefficients IIRCoefficients::makeAllPass (double sampleRate,
167 double frequency,
168 double Q) noexcept
169 {
170 jassert (sampleRate > 0.0);
171 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
172 jassert (Q > 0.0);
173
174 auto n = 1.0 / std::tan (MathConstants<double>::pi * frequency / sampleRate);
175 auto nSquared = n * n;
176 auto c1 = 1.0 / (1.0 + 1.0 / Q * n + nSquared);
177
178 return IIRCoefficients (c1 * (1.0 - n / Q + nSquared),
179 c1 * 2.0 * (1.0 - nSquared),
180 1.0,
181 1.0,
182 c1 * 2.0 * (1.0 - nSquared),
183 c1 * (1.0 - n / Q + nSquared));
184 }
185
makeLowShelf(double sampleRate,double cutOffFrequency,double Q,float gainFactor)186 IIRCoefficients IIRCoefficients::makeLowShelf (double sampleRate,
187 double cutOffFrequency,
188 double Q,
189 float gainFactor) noexcept
190 {
191 jassert (sampleRate > 0.0);
192 jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
193 jassert (Q > 0.0);
194
195 auto A = jmax (0.0f, std::sqrt (gainFactor));
196 auto aminus1 = A - 1.0;
197 auto aplus1 = A + 1.0;
198 auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
199 auto coso = std::cos (omega);
200 auto beta = std::sin (omega) * std::sqrt (A) / Q;
201 auto aminus1TimesCoso = aminus1 * coso;
202
203 return IIRCoefficients (A * (aplus1 - aminus1TimesCoso + beta),
204 A * 2.0 * (aminus1 - aplus1 * coso),
205 A * (aplus1 - aminus1TimesCoso - beta),
206 aplus1 + aminus1TimesCoso + beta,
207 -2.0 * (aminus1 + aplus1 * coso),
208 aplus1 + aminus1TimesCoso - beta);
209 }
210
makeHighShelf(double sampleRate,double cutOffFrequency,double Q,float gainFactor)211 IIRCoefficients IIRCoefficients::makeHighShelf (double sampleRate,
212 double cutOffFrequency,
213 double Q,
214 float gainFactor) noexcept
215 {
216 jassert (sampleRate > 0.0);
217 jassert (cutOffFrequency > 0.0 && cutOffFrequency <= sampleRate * 0.5);
218 jassert (Q > 0.0);
219
220 auto A = jmax (0.0f, std::sqrt (gainFactor));
221 auto aminus1 = A - 1.0;
222 auto aplus1 = A + 1.0;
223 auto omega = (MathConstants<double>::twoPi * jmax (cutOffFrequency, 2.0)) / sampleRate;
224 auto coso = std::cos (omega);
225 auto beta = std::sin (omega) * std::sqrt (A) / Q;
226 auto aminus1TimesCoso = aminus1 * coso;
227
228 return IIRCoefficients (A * (aplus1 + aminus1TimesCoso + beta),
229 A * -2.0 * (aminus1 + aplus1 * coso),
230 A * (aplus1 + aminus1TimesCoso - beta),
231 aplus1 - aminus1TimesCoso + beta,
232 2.0 * (aminus1 - aplus1 * coso),
233 aplus1 - aminus1TimesCoso - beta);
234 }
235
makePeakFilter(double sampleRate,double frequency,double Q,float gainFactor)236 IIRCoefficients IIRCoefficients::makePeakFilter (double sampleRate,
237 double frequency,
238 double Q,
239 float gainFactor) noexcept
240 {
241 jassert (sampleRate > 0.0);
242 jassert (frequency > 0.0 && frequency <= sampleRate * 0.5);
243 jassert (Q > 0.0);
244
245 auto A = jmax (0.0f, std::sqrt (gainFactor));
246 auto omega = (MathConstants<double>::twoPi * jmax (frequency, 2.0)) / sampleRate;
247 auto alpha = 0.5 * std::sin (omega) / Q;
248 auto c2 = -2.0 * std::cos (omega);
249 auto alphaTimesA = alpha * A;
250 auto alphaOverA = alpha / A;
251
252 return IIRCoefficients (1.0 + alphaTimesA,
253 c2,
254 1.0 - alphaTimesA,
255 1.0 + alphaOverA,
256 c2,
257 1.0 - alphaOverA);
258 }
259
260 //==============================================================================
IIRFilter()261 IIRFilter::IIRFilter() noexcept
262 {
263 }
264
IIRFilter(const IIRFilter & other)265 IIRFilter::IIRFilter (const IIRFilter& other) noexcept : active (other.active)
266 {
267 const SpinLock::ScopedLockType sl (other.processLock);
268 coefficients = other.coefficients;
269 }
270
~IIRFilter()271 IIRFilter::~IIRFilter() noexcept
272 {
273 }
274
275 //==============================================================================
makeInactive()276 void IIRFilter::makeInactive() noexcept
277 {
278 const SpinLock::ScopedLockType sl (processLock);
279 active = false;
280 }
281
setCoefficients(const IIRCoefficients & newCoefficients)282 void IIRFilter::setCoefficients (const IIRCoefficients& newCoefficients) noexcept
283 {
284 const SpinLock::ScopedLockType sl (processLock);
285 coefficients = newCoefficients;
286 active = true;
287 }
288
289 //==============================================================================
reset()290 void IIRFilter::reset() noexcept
291 {
292 const SpinLock::ScopedLockType sl (processLock);
293 v1 = v2 = 0.0;
294 }
295
processSingleSampleRaw(float in)296 float IIRFilter::processSingleSampleRaw (float in) noexcept
297 {
298 auto out = coefficients.coefficients[0] * in + v1;
299
300 JUCE_SNAP_TO_ZERO (out);
301
302 v1 = coefficients.coefficients[1] * in - coefficients.coefficients[3] * out + v2;
303 v2 = coefficients.coefficients[2] * in - coefficients.coefficients[4] * out;
304
305 return out;
306 }
307
processSamples(float * const samples,const int numSamples)308 void IIRFilter::processSamples (float* const samples, const int numSamples) noexcept
309 {
310 const SpinLock::ScopedLockType sl (processLock);
311
312 if (active)
313 {
314 auto c0 = coefficients.coefficients[0];
315 auto c1 = coefficients.coefficients[1];
316 auto c2 = coefficients.coefficients[2];
317 auto c3 = coefficients.coefficients[3];
318 auto c4 = coefficients.coefficients[4];
319 auto lv1 = v1, lv2 = v2;
320
321 for (int i = 0; i < numSamples; ++i)
322 {
323 auto in = samples[i];
324 auto out = c0 * in + lv1;
325 samples[i] = out;
326
327 lv1 = c1 * in - c3 * out + lv2;
328 lv2 = c2 * in - c4 * out;
329 }
330
331 JUCE_SNAP_TO_ZERO (lv1); v1 = lv1;
332 JUCE_SNAP_TO_ZERO (lv2); v2 = lv2;
333 }
334 }
335
336 } // namespace juce
337