OpenShot Audio Library | OpenShotAudio 0.4.0
juce_LinkwitzRileyFilter.cpp
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//==============================================================================
30template <typename SampleType>
32{
33 update();
34}
35
36//==============================================================================
37template <typename SampleType>
39{
40 filterType = newType;
41}
42
43template <typename SampleType>
44void LinkwitzRileyFilter<SampleType>::setCutoffFrequency (SampleType newCutoffFrequencyHz)
45{
46 jassert (isPositiveAndBelow (newCutoffFrequencyHz, static_cast<SampleType> (sampleRate * 0.5)));
47
48 cutoffFrequency = newCutoffFrequencyHz;
49 update();
50}
51
52//==============================================================================
53template <typename SampleType>
55{
56 jassert (spec.sampleRate > 0);
57 jassert (spec.numChannels > 0);
58
59 sampleRate = spec.sampleRate;
60 update();
61
62 s1.resize (spec.numChannels);
63 s2.resize (spec.numChannels);
64 s3.resize (spec.numChannels);
65 s4.resize (spec.numChannels);
66
67 reset();
68}
69
70template <typename SampleType>
72{
73 for (auto s : { &s1, &s2, &s3, &s4 })
74 std::fill (s->begin(), s->end(), static_cast<SampleType> (0));
75}
76
77template <typename SampleType>
79{
80 for (auto s : { &s1, &s2, &s3, &s4 })
81 for (auto& element : *s)
82 util::snapToZero (element);
83}
84
85//==============================================================================
86template <typename SampleType>
87SampleType LinkwitzRileyFilter<SampleType>::processSample (int channel, SampleType inputValue)
88{
89 auto yH = (inputValue - (R2 + g) * s1[(size_t) channel] - s2[(size_t) channel]) * h;
90
91 auto yB = g * yH + s1[(size_t) channel];
92 s1[(size_t) channel] = g * yH + yB;
93
94 auto yL = g * yB + s2[(size_t) channel];
95 s2[(size_t) channel] = g * yB + yL;
96
97 if (filterType == Type::allpass)
98 return yL - R2 * yB + yH;
99
100 auto yH2 = ((filterType == Type::lowpass ? yL : yH) - (R2 + g) * s3[(size_t) channel] - s4[(size_t) channel]) * h;
101
102 auto yB2 = g * yH2 + s3[(size_t) channel];
103 s3[(size_t) channel] = g * yH2 + yB2;
104
105 auto yL2 = g * yB2 + s4[(size_t) channel];
106 s4[(size_t) channel] = g * yB2 + yL2;
107
108 return filterType == Type::lowpass ? yL2 : yH2;
109}
110
111template <typename SampleType>
112void LinkwitzRileyFilter<SampleType>::processSample (int channel, SampleType inputValue, SampleType &outputLow, SampleType &outputHigh)
113{
114 auto yH = (inputValue - (R2 + g) * s1[(size_t) channel] - s2[(size_t) channel]) * h;
115
116 auto yB = g * yH + s1[(size_t) channel];
117 s1[(size_t) channel] = g * yH + yB;
118
119 auto yL = g * yB + s2[(size_t) channel];
120 s2[(size_t) channel] = g * yB + yL;
121
122 auto yH2 = (yL - (R2 + g) * s3[(size_t) channel] - s4[(size_t) channel]) * h;
123
124 auto yB2 = g * yH2 + s3[(size_t) channel];
125 s3[(size_t) channel] = g * yH2 + yB2;
126
127 auto yL2 = g * yB2 + s4[(size_t) channel];
128 s4[(size_t) channel] = g * yB2 + yL2;
129
130 outputLow = yL2;
131 outputHigh = yL - R2 * yB + yH - yL2;
132}
133
134template <typename SampleType>
136{
137 g = (SampleType) std::tan (MathConstants<double>::pi * cutoffFrequency / sampleRate);
138 R2 = (SampleType) std::sqrt (2.0);
139 h = (SampleType) (1.0 / (1.0 + R2 * g + g * g));
140}
141
142//==============================================================================
143template class LinkwitzRileyFilter<float>;
144template class LinkwitzRileyFilter<double>;
145
146} // namespace juce::dsp
void prepare(const ProcessSpec &spec)
SampleType processSample(int channel, SampleType inputValue)
void setCutoffFrequency(SampleType newCutoffFrequencyHz)