Jamoma API  0.6.0.a19
TTLowpassLinkwitzRiley4.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTLowpassLinkwitzRiley4 is a fourth-order Linkwitz-Riley lowpass filter.
6  *
7  * @details 4th order Linkwitz-Riley filters are typically used as crossover filters, with the following properties: @n
8  * @n
9  * 1. Absolutely flat amplitude response throughout the passband with a 6 dB/octave rolloff rate after the crossover point. @n
10  * 2. The acoustic sum of the two driver responses is unity at crossover. (Amplitude response of each is -3 dB at crossover, i.e., there is no peaking in the summed acoustic output.) @n
11  * 3. Zero phase difference between drivers at crossover. (Lobing error equals zero, i.e., no tilt to the polar radiation pattern.) In addition, the phase difference of zero degrees through crossover places the lobe of the summed acoustic output on axis at all frequencies. @n
12  * 4. The low pass and high pass outputs are everywhere in phase. (This guarantees symmetry of the polar response about the crossover point.) @n
13  * 5. All drivers are always wired the same (in phase). @n
14  * @n
15  * Filter equations from: @n
16  * @n
17  * Second-order IIR Filters will support cascade implementations @n
18  * By Rusty Allred, Texas Instruments, Dallas @n
19  * July 01, 2003 @n
20  * http://www.eetimes.com/document.asp?doc_id=1272177
21  *
22  * @authors Trond Lossius, Timothy Place,
23  *
24  * @copyright Copyright © 2008, Trond Lossius @n
25  * This code is licensed under the terms of the "New BSD License" @n
26  * http://creativecommons.org/licenses/BSD/
27  */
28 
29 
31 
32 #define thisTTClass TTLowpassLinkwitzRiley4
33 #define thisTTClassName "lowpass.linkwitzriley.4"
34 #define thisTTClassTags "dspFilterLib, audio, processor, filter, lowpass, crossover"
35 
36 
37 TT_AUDIO_CONSTRUCTOR
38 {
39  // register attributes
41  addAttributeProperty(Frequency, range, TTValue(10.0, sr*0.475));
42  addAttributeProperty(Frequency, rangeChecking, TT("clip"));
43 
44  // register for notifications from the parent class so we can allocate memory as required
45  addUpdates(MaxNumChannels);
46  // register for notifications from the parent class so we can recalculate coefficients as required
47  addUpdates(SampleRate);
48  // make the clear method available to the outside world
49  addMessage(clear);
50 
51  // Set Defaults...
52  setAttributeValue(kTTSym_maxNumChannels, arguments); // This attribute is inherited
53  setAttributeValue(TT("frequency"), 1000.0);
54  setProcessMethod(processAudio);
55  setCalculateMethod(calculateValue);
56 
57 }
58 
59 
60 TTLowpassLinkwitzRiley4::~TTLowpassLinkwitzRiley4()
61 {
62  ;
63 }
64 
65 
67 {
68  mX1.resize(mMaxNumChannels);
69  mX2.resize(mMaxNumChannels);
70  mX3.resize(mMaxNumChannels);
71  mX4.resize(mMaxNumChannels);
72  mY1.resize(mMaxNumChannels);
73  mY2.resize(mMaxNumChannels);
74  mY3.resize(mMaxNumChannels);
75  mY4.resize(mMaxNumChannels);
76  clear();
77  return kTTErrNone;
78 }
79 
80 
81 TTErr TTLowpassLinkwitzRiley4::updateSampleRate(const TTValue& oldSampleRate, TTValue&)
82 {
84  return setFrequency(v);
85 }
86 
87 
89 {
90  mX1.assign(mMaxNumChannels, 0.0);
91  mX2.assign(mMaxNumChannels, 0.0);
92  mX3.assign(mMaxNumChannels, 0.0);
93  mX4.assign(mMaxNumChannels, 0.0);
94  mY1.assign(mMaxNumChannels, 0.0);
95  mY2.assign(mMaxNumChannels, 0.0);
96  mY3.assign(mMaxNumChannels, 0.0);
97  mY4.assign(mMaxNumChannels, 0.0);
98  return kTTErrNone;
99 }
100 
101 
103 {
104  mFrequency = newValue;
106  mK = mRadians/tan(kTTPi*mFrequency/sr);
107  calculateCoefficients();
108  return kTTErrNone;
109 }
110 void TTLowpassLinkwitzRiley4::calculateCoefficients() //TODO: with a little bit of thinking, this can be optimized [NP]
111 {
112  TTFloat64 temp;
113  temp = (4*pow(mRadians,2)*pow(mK,2)+2*kTTSqrt2*pow(mRadians,3)*mK+pow(mK,4)+2*kTTSqrt2*mRadians*pow(mK,3)+pow(mRadians,4));
114 
115  mA0 = pow(mRadians,4) / temp;
116  mA1 = 4*pow(mRadians,4) / temp;
117  mA2 = 6*pow(mRadians,4) / temp;
118  //mA3 = mA1;// 4*pow(mRadians,4) / temp;
119  //mA4 = mA0;// pow(mRadians,4) / temp;
120 
121  mB1 = (4*pow(mRadians,4)+4*kTTSqrt2*pow(mRadians,3)*mK-4*pow(mK,4)-4*kTTSqrt2*mRadians*pow(mK,3)) / temp;
122  mB2 = (6*pow(mRadians,4)-8*pow(mRadians,2)*pow(mK,2)+6*pow(mK,4)) / temp;
123  mB3 = (-4*kTTSqrt2*pow(mRadians,3)*mK+4*pow(mRadians,4)+4*kTTSqrt2*mRadians*pow(mK,3)-4*pow(mK,4)) / temp;
124  mB4 = (pow(mK,4)-2*kTTSqrt2*pow(mRadians,3)*mK+pow(mRadians,4)-2*kTTSqrt2*mRadians*pow(mK,3)+4*pow(mRadians,2)*pow(mK,2)) / temp;
125 
126 
127 }
128 
129 
131 {
132  //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] + mA2*mX2[channel] + mA3*mX3[channel] + mA4*mX4[channel] - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel] - mB4*mY4[channel]);
133  // since mA3 = mA1 and mA0 = mA4, we can simplyfy to
134  y = mA0*(x + mX4[channel]) + mA1*( mX1[channel] + mX3[channel] ) + mA2*mX2[channel] - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel] - mB4*mY4[channel];
135  TTZeroDenormal(y);
136  mX4[channel] = mX3[channel];
137  mX3[channel] = mX2[channel];
138  mX2[channel] = mX1[channel];
139  mX1[channel] = x;
140  mY4[channel] = mY3[channel];
141  mY3[channel] = mY2[channel];
142  mY2[channel] = mY1[channel];
143  mY1[channel] = y;
144  return kTTErrNone;
145 }
146 
147 
149 {
150  TT_WRAP_CALCULATE_METHOD(calculateValue);
151 }
TTSampleVector mX2
Input sample n-2.
TTFloat64 mFrequency
filter cutoff frequency
TTSampleVector mY4
Output sample n-4.
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
TTFOUNDATION_EXPORT const TTFloat64 kTTTwoPi
Pre-calculated value of pi * 2.
Definition: TTBase.cpp:24
TTSampleVector mX3
Input sample n-3.
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTSampleVector mY3
Output sample n-3.
TTLowpassLinkwitzRiley4 is a fourth-order Linkwitz-Riley lowpass filter.
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
TTSampleVector mY2
Output sample n-2.
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTSampleVector mY1
Output sample n-1.
TTSampleVector mX4
Input sample n-4.
64-bit floating point
Definition: TTBase.h:272
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
Definition: TTAttribute.h:68
TTFloat64 mRadians
filter coefficients
TTErr clear()
This algorithm uses an IIR filter, meaning that it relies on feedback.
TTFOUNDATION_EXPORT const TTFloat64 kTTSqrt2
Pre-calculated square-root of 2 (1.4142).
Definition: TTBase.cpp:25
TTErr calculateValue(const TTFloat64 &x, TTFloat64 &y, TTPtrSizedInt channel)
Standard single value calculate method as used by DSP objects.
A simple container for an array of TTAudioSignal pointers.
long TTPtrSizedInt
An integer that is the same size as a pointer.
Definition: TTBase.h:240
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTFloat64 mB4
filter coefficients for output samples
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
Definition: TTAttribute.h:47
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
No Error.
Definition: TTBase.h:343
TTFOUNDATION_EXPORT const TTFloat64 kTTPi
[doxygenAppendixC_constExample]
Definition: TTBase.cpp:23
TTErr setFrequency(const TTValue &value)
Setter for the frequency attribute.
TTSampleVector mX1
Input sample n-1.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr updateMaxNumChannels(const TTValue &oldMaxNumChannels, TTValue &)
Receives notifications when there are changes to the inherited mMaxNumChannels attribute.
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
Standard audio processing method as used by TTBlue objects.
#define addUpdates(updateName)
An 'update' is a message sent to a subclass instance from its parent class.
Definition: TTMessage.h:44
TTUInt32 sr
Current sample rate being used by this object.