Jamoma API  0.6.0.a19
TTHighpassLinkwitzRiley4.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTHighpassLinkwitzRiley4 is a fourth-order Linkwitz-Riley highpass 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.planetanalog.com/article/printableArticle.jhtml?articleID=12802683
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 TTHighpassLinkwitzRiley4
33 #define thisTTClassName "highpass.linkwitzriley.4"
34 #define thisTTClassTags "dspFilterLib, audio, processor, filter, highpass, 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 TTHighpassLinkwitzRiley4::~TTHighpassLinkwitzRiley4()
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 TTHighpassLinkwitzRiley4::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;
105 
107  mK = mRadians/tan(kTTPi*mFrequency/sr); // kTTTwoPi*frequency/tan(kTTPi*frequency/sr);
108  calculateCoefficients();
109  return kTTErrNone;
110 }
111 
112 
113 void TTHighpassLinkwitzRiley4::calculateCoefficients() //TODO: with a little bit of thinking, this can be optimized
114 {
115  TTFloat64 temp;
116  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));
117 
118  mA0 = pow(mK,4)/ temp;
119  mA1 = -4*pow(mK,4)/ temp;
120  mA2 = 6*pow(mK,4)/ temp;
121  //mA3 = mA1;//mA3 = -4*pow(mK,4)/ temp;
122  //mA4 = mA0; //mA4 = pow(mK,4)/ temp;
123 
124  mB1 = (4*pow(mRadians,4)+4*kTTSqrt2*pow(mRadians,3)*mK-4*pow(mK,4)-4*kTTSqrt2*mRadians*pow(mK,3))/ temp;
125  mB2 = (6*pow(mRadians,4)-8*pow(mRadians,2)*pow(mK,2)+6*pow(mK,4))/ temp;
126  mB3 = (-4*kTTSqrt2*pow(mRadians,3)*mK+4*pow(mRadians,4)+4*kTTSqrt2*mRadians*pow(mK,3)-4*pow(mK,4))/ temp;
127  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;
128 }
129 
130 
132 {
133  //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]);
134  // since mA3 = mA1 and mA0 = mA4, we can simplyfy to
135  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];
136  TTZeroDenormal(y);
137  mX4[channel] = mX3[channel];
138  mX3[channel] = mX2[channel];
139  mX2[channel] = mX1[channel];
140  mX1[channel] = x;
141  mY4[channel] = mY3[channel];
142  mY3[channel] = mY2[channel];
143  mY2[channel] = mY1[channel];
144  mY1[channel] = y;
145  return kTTErrNone;
146 }
147 
148 
150 {
151  TT_WRAP_CALCULATE_METHOD(calculateValue);
152 }
TTSampleVector mY4
Output sample n-4.
TTSampleVector mY3
Output sample n-3.
TTFloat64 mB4
filter coefficients for output samples
TTSampleVector mX2
Input sample n-2.
TTSampleVector mY1
Output sample n-1.
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
TTSampleVector mX3
Input sample n-3.
TTErr calculateValue(const TTFloat64 &x, TTFloat64 &y, TTPtrSizedInt channel)
Standard single value calculate method as used by DSP objects.
TTFloat64 mFrequency
filter cutoff frequency
TTFOUNDATION_EXPORT const TTFloat64 kTTTwoPi
Pre-calculated value of pi * 2.
Definition: TTBase.cpp:24
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTSampleVector mX4
Input sample n-4.
TTErr updateMaxNumChannels(const TTValue &oldMaxNumChannels, TTValue &)
Receives notifications when there are changes to the inherited mMaxNumChannels attribute.
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 mX1
Input sample n-1.
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTFloat64 mRadians
filter coefficients
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
Standard audio processing method as used by TTBlue objects.
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
TTFOUNDATION_EXPORT const TTFloat64 kTTSqrt2
Pre-calculated square-root of 2 (1.4142).
Definition: TTBase.cpp:25
A simple container for an array of TTAudioSignal pointers.
TTErr clear()
This algorithm uses an IIR filter, meaning that it relies on feedback.
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
#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.
TTHighpassLinkwitzRiley4 is a fourth-order Linkwitz-Riley highpass filter.
TTSampleVector mY2
Output sample n-2.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
#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.