Jamoma API  0.6.0.a19
TTHighMidLowShelf.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTHighMidLowShelf is a High-Mid-Low shelf filter
6  *
7  * @details ported by Nils Peters 2009, from the PD external hml_shelf~ by Thomas Musil.
8  * https://github.com/rfabbri/pd-macambira/blob/master/externals/iemlib/iemlib1/src/hml_shelf~.c
9  * Use of the code under the Jamoma BSD license was authorized by Thomas MUSIL on Jan 13 2014.
10  *
11  * @authors Thomas Musil, Nils Peters, Trond Lossius
12  *
13  * @copyright Copyright © 2010, Thomas Musil @n
14  * This code is licensed under the terms of the "New BSD License" @n
15  * http://creativecommons.org/licenses/BSD/
16  */
17 
18 
19 #include "TTHighMidLowShelf.h"
20 
21 #define thisTTClass TTHighMidLowShelf
22 #define thisTTClassName "highmidlowshelf"
23 #define thisTTClassTags "dspFilterLib, audio, processor, threebandfilter"
24 
25 
26 TT_AUDIO_CONSTRUCTOR
27 {
28  // register attributes
30  addAttributeProperty(FrequencyLm, range, TTValue(10.0, sr*0.475));
31  addAttributeProperty(FrequencyLm, rangeChecking, TT("clip"));
32 
34  addAttributeProperty(FrequencyMh, range, TTValue(10.0, sr*0.475));
35  addAttributeProperty(FrequencyMh, rangeChecking, TT("clip"));
36 
38  addAttributeProperty(GainL, range, TTValue(0.0000001, 16));
39  addAttributeProperty(GainL, rangeChecking, TT("clip"));
40 
42  addAttributeProperty(GainM, range, TTValue(0.0000001, 16));
43  addAttributeProperty(GainM, rangeChecking, TT("clip"));
44 
46  addAttributeProperty(GainH, range, TTValue(0.0000001, 16));
47  addAttributeProperty(GainH, rangeChecking, TT("clip"));
48 
49  // register for notifications from the parent class so we can allocate memory as required
50  addUpdates(MaxNumChannels);
51  // register for notifications from the parent class so we can recalculate coefficients as required
52  addUpdates(SampleRate);
53  // make the clear method available to the outside world
54  addMessage(clear);
55 
56  // Set Defaults...
57  setAttributeValue(kTTSym_maxNumChannels, arguments); // This attribute is inherited
58  setAttributeValue(TT("frequencyMh"), 3000.0);
59  setAttributeValue(TT("frequencyLm"), 300.0);
60  setAttributeValue(TT("gainL"), 1.0);
61  setAttributeValue(TT("gainM"), 1.0);
62  setAttributeValue(TT("gainH"), 1.0);
63  setCalculateMethod(calculateValue);
64  setProcessMethod(processAudio);
65 }
66 
67 
68 
69 TTHighMidLowShelf::~TTHighMidLowShelf()
70 {
71  ;
72 }
73 
74 
76 {
77 
78  mX1.resize(mMaxNumChannels);
79  mX2.resize(mMaxNumChannels);
80  mX0.resize(mMaxNumChannels);
81  clear();
82  return kTTErrNone;
83 }
84 
85 
87 {
88  return calculateCoefficients();
89 }
90 
91 
92 TTErr TTHighMidLowShelf::clear()
93 {
94  mX1.assign(mMaxNumChannels, 0.0);
95  mX2.assign(mMaxNumChannels, 0.0);
96  mX0.assign(mMaxNumChannels, 0.0);
97  return kTTErrNone;
98 }
99 
100 TTErr TTHighMidLowShelf::setFrequencyLm(const TTValue& newValue)
101 {
102  if (static_cast<TTFloat64>(newValue) < mFrequencyMh)
103  {
104  mFrequencyLm = newValue;
105  mFmid = sqrt(mFrequencyMh) * sqrt(mFrequencyLm); // mFmid depends on mFrequencyMh and mFrequencyLm
106  }
107  return calculateCoefficients();
108 }
109 
110 TTErr TTHighMidLowShelf::setFrequencyMh(const TTValue& newValue)
111 {
112  if (static_cast<TTFloat64>(newValue) > mFrequencyLm)
113  {
114  mFrequencyMh = newValue;
115  mFmid = sqrt(mFrequencyMh) * sqrt(mFrequencyLm); // mFmid depends on mFrequencyMh and mFrequencyLm
116  }
117  return calculateCoefficients();
118 }
119 
121 {
122  mGainL = newValue;
123  return calculateCoefficients();
124 }
125 
126 
127 TTErr TTHighMidLowShelf::setGainM(const TTValue& newValue)
128 {
129  mGainM = newValue;
130  return calculateCoefficients();
131 }
132 
133 TTErr TTHighMidLowShelf::setGainH(const TTValue& newValue)
134 {
135  mGainH = newValue;
136  return calculateCoefficients();
137 }
138 
139 
140 TTErr TTHighMidLowShelf::calculateCoefficients()
141 {
142  double f = mFmid * (kTTPi / sr); //kTTPi / sr could be calculated outside
143  //double rf = sqrt(mFrequencyMh) / sqrt(mFrequencyLm); //could be improved
144  double rf = pow((mFrequencyMh / mFrequencyLm), 0.5); //could be improved
145  double l = cos(f) / sin(f);
146  double invHg = 1.0 / mGainH;
147  double invLg = 1.0 / mGainL;
148  double invMg = 1.0 / mGainM;
149  double k1 = rf * l;
150  double k2 = l / rf;
151  double k3 = l * l;
152  double k4 = k3 * mGainH;
153  double k5 = k3 * invHg;
154  double k6 = invLg + k5;
155  double k7 = invMg * k1 + k2 * invLg * invHg * mGainM;
156  double k8 = mGainL + k4;
157  double k9 = (mGainM * k1) + (k2 * mGainL * mGainH * invMg);
158  double k10 = 1.0 / (k6 + k7);
159 
160  /*
161  double tempb2 = k10 * (k7 - k6);
162  double tempb1 = k10 * 2.0 * (k5 - invLg);
163  double tempa2 = k10 * (k8 - k9);
164  double tempa1 = k10 * 2.0 * (mGainL - k4);
165  double tempa0 = k10 * (k8 + k9);
166 
167 
168  // stability check //
169 
170  double discriminant = tempb1 * tempb1 + 4.0 * tempb2;
171  TTClip<double>(tempb1, -1.9999996, 1.9999996);
172  TTClip<double>(tempb2, -0.9999998, 0.9999998);
173 
174  if (discriminant >= 0.0)
175  {
176  if (0.9999998 - tempb1 - tempb2 < 0.0)
177  tempb2 = 0.9999998 - tempb1;
178  if (0.9999998 + tempb1 - tempb2 < 0.0)
179  tempb2 = 0.9999998 + tempb1;
180  }
181  //TTClip<double>(tempb2, 0.9999998 - tempb1, 0.9999998 + tempb1); //[NP] is that what the loop above means ?
182  a0 = tempa0;
183  a1 = tempa1;
184  a2 = tempa2;
185  b1 = tempb1;
186  b2 = tempb2;
187  */
188 
189 
190  mB2 = k10 * (k7 - k6);
191  mB1 = k10 * 2.0 * (k5 - invLg);
192  mA2 = k10 * (k8 - k9);
193  mA1 = k10 * 2.0 * (mGainL - k4);
194  mA0 = k10 * (k8 + k9);
195 
196  // stability check //
197  double discriminant = mB1 * mB1 + 4.0 * mB2;
198  TTClip<double>(mB1, -1.9999996, 1.9999996);
199  TTClip<double>(mB2, -0.9999998, 0.9999998);
200 
201  if (discriminant >= 0.0)
202  {
203  if (0.9999998 - mB1 - mB2 < 0.0)
204  mB2 = 0.9999998 - mB1;
205  if (0.9999998 + mB1 - mB2 < 0.0)
206  mB2 = 0.9999998 + mB1;
207  }
208 
209  return kTTErrNone;
210 }
211 
212 
213 
215 {
216  TT_WRAP_CALCULATE_METHOD(calculateValue);
217 }
218 
219 
221 {
222  mX0[channel] = x + mB1 * mX1[channel] + mB2 * mX2[channel];
223  TTZeroDenormal(mX0[channel]); // put TTZeroDenormal here for superstition
224  y = mA0 * mX0[channel] + mA1 * mX1[channel] + mA2 * mX2[channel];
225  TTZeroDenormal(y);
226  mX2[channel] = mX1[channel]; // update feedback values
227  mX1[channel] = mX0[channel];
228  return kTTErrNone;
229 }
230 
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
Standard audio processing method as used by TTBlue objects.
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
TTErr calculateValue(const TTFloat64 &x, TTFloat64 &y, TTPtrSizedInt channel)
y = f(x)
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTErr updateSampleRate(const TTValue &oldSampleRate, TTValue &)
Receives notifications when there are changes to the inherited sr attribute.
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
TTErr setGainL(const TTValue &value)
Setter for the filter attribute.
TTFloat64 mB2
filter coefficients
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
#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
TTErr updateMaxNumChannels(const TTValue &oldMaxNumChannels, TTValue &)
Receives notifications when there are changes to the inherited mMaxNumChannels attribute.
No Error.
Definition: TTBase.h:343
TTFOUNDATION_EXPORT const TTFloat64 kTTPi
[doxygenAppendixC_constExample]
Definition: TTBase.cpp:23
TTFloat64 mGainH
filter parameter
[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
TTHighMidLowShelf is a High-Mid-Low shelf filter
TTUInt32 sr
Current sample rate being used by this object.