OpenShot Audio Library | OpenShotAudio  0.6.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 
26 namespace juce::dsp
27 {
28 
29 //==============================================================================
30 template <typename SampleType>
32 {
33  update();
34 }
35 
36 //==============================================================================
37 template <typename SampleType>
39 {
40  filterType = newType;
41 }
42 
43 template <typename SampleType>
44 void 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 //==============================================================================
53 template <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 
70 template <typename SampleType>
72 {
73  for (auto s : { &s1, &s2, &s3, &s4 })
74  std::fill (s->begin(), s->end(), static_cast<SampleType> (0));
75 }
76 
77 template <typename SampleType>
79 {
80  for (auto s : { &s1, &s2, &s3, &s4 })
81  for (auto& element : *s)
82  util::snapToZero (element);
83 }
84 
85 //==============================================================================
86 template <typename SampleType>
87 SampleType 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 
111 template <typename SampleType>
112 void 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 
134 template <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 //==============================================================================
143 template class LinkwitzRileyFilter<float>;
144 template class LinkwitzRileyFilter<double>;
145 
146 } // namespace juce::dsp
void prepare(const ProcessSpec &spec)
SampleType processSample(int channel, SampleType inputValue)
void setCutoffFrequency(SampleType newCutoffFrequencyHz)