Jamoma API  0.6.0.a19
TTHalfband9.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTHalfband9 is a 9-Pole Halfband filter built up from a 2-path allpass structure.
6  *
7  * @details
8  *
9  * @authors Timothy Place, Trond Lossius
10  *
11  * @copyright Copyright © 2010, Timothy Place @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 #include "TTHalfband9.h"
18 
19 #define thisTTClass TTHalfband9
20 #define thisTTClassName "halfband.9"
21 #define thisTTClassTags "dspFilterLib, audio, processor, filter, lowpass, highpass"
22 
23 #ifdef TT_PLATFORM_WIN
24 #include <Algorithm>
25 #endif
26 
27 TT_AUDIO_CONSTRUCTOR,
28  mF0("allpass.1b"),
29  mF2("allpass.1b"),
30  mR0("allpass.1a"),
31  mR2("allpass.1a"),
32 
33  mF1("allpass.1b"),
34  mF3("allpass.1b"),
35  mR1("allpass.1a"),
36  mR3("allpass.1a"),
37  mDelay("allpass.1a")
38 {
39  TTChannelCount initialMaxNumChannels = arguments;
40 
42  addMessage(clear);
43  addUpdates(MaxNumChannels);
44 
45  setAttributeValue(kTTSym_maxNumChannels, initialMaxNumChannels);
46  setAttributeValue(TT("mode"), TT("lowpass"));
47 
48  // for the simple 1-sample delay, we set alpha (the feedback coefficient) to zero
49  mDelay.set("alpha", 0.0);
50 
51  // stopband edge (-60db) at Fs*0.284.
52  // mF0->setAttributeValue(TT("alpha"), 0.101467517);
53  // mF2->setAttributeValue(TT("alpha"), 0.612422841);
54  // mF1->setAttributeValue(TT("alpha"), 0.342095596);
55  // mF3->setAttributeValue(TT("alpha"), 0.867647439);
56 
57  // These yield a -113 dB stopband attenuation, with a stopband edge (w_0) at f_s * 0.37
58  mF0.set("alpha", 0.043646929608759);
59  mR0.set("alpha", 0.043646929608759);
60  mF2.set("alpha", 0.399125646691078);
61  mR2.set("alpha", 0.399125646691078);
62  mF1.set("alpha", 0.174628080915462);
63  mR1.set("alpha", 0.174628080915462);
64  mF3.set("alpha", 0.749510679417446);
65  mR3.set("alpha", 0.749510679417446);
66 }
67 
68 
69 TTHalfband9::~TTHalfband9()
70 {
71 }
72 
73 
74 TTErr TTHalfband9::updateMaxNumChannels(const TTValue& oldMaxNumChannels, TTValue&)
75 {
76  // update internal filters
77  mF0.set(kTTSym_maxNumChannels, mMaxNumChannels);
78  mF1.set(kTTSym_maxNumChannels, mMaxNumChannels);
79  mF2.set(kTTSym_maxNumChannels, mMaxNumChannels);
80  mF3.set(kTTSym_maxNumChannels, mMaxNumChannels);
81  mR0.set(kTTSym_maxNumChannels, mMaxNumChannels);
82  mR1.set(kTTSym_maxNumChannels, mMaxNumChannels);
83  mR2.set(kTTSym_maxNumChannels, mMaxNumChannels);
84  mR3.set(kTTSym_maxNumChannels, mMaxNumChannels);
85  mDelay.set(kTTSym_maxNumChannels, mMaxNumChannels);
86 
87  mRSwitch.resize(mMaxNumChannels);
88  mRSwitch.assign(mMaxNumChannels, 0.0);
89 
90  mY0.resize(mMaxNumChannels);
91  mY0.assign(mMaxNumChannels, 0.0);
92  mY1.resize(mMaxNumChannels);
93  mY1.assign(mMaxNumChannels, 0.0);
94 
95  clear();
96  return kTTErrNone;
97 }
98 
99 
100 TTErr TTHalfband9::clear()
101 {
102  mF0.send(kTTSym_clear);
103  mF1.send(kTTSym_clear);
104  mF2.send(kTTSym_clear);
105  mF3.send(kTTSym_clear);
106  mR0.send(kTTSym_clear);
107  mR1.send(kTTSym_clear);
108  mR2.send(kTTSym_clear);
109  mR3.send(kTTSym_clear);
110  mDelay.send(kTTSym_clear);
111  return kTTErrNone;
112 }
113 
114 
115 TTErr TTHalfband9::setMode(const TTValue& newValue)
116 {
117  TTSymbol newMode = newValue;
118 
119  if (newMode == TT("upsample")) {
120  mMode = TT("upsample");
121  setCalculateMethod(calculateUpsample);
122  setProcessMethod(processUpsample);
123  }
124  else if (newMode == TT("downsample")) { // downsample
125  mMode = TT("downsample");
126  setCalculateMethod(calculateDownsample);
127  setProcessMethod(processDownsample);
128  }
129  else if (newMode == TT("highpass")) {
130  mMode = TT("highpass");
131  setCalculateMethod(calculateHighpass);
132  setProcessMethod(processHighpass);
133  }
134  else { // lowpass
135  mMode = TT("lowpass");
136  setCalculateMethod(calculateLowpass);
137  setProcessMethod(processLowpass);
138  }
139  return kTTErrNone;
140 }
141 
142 
143 inline void TTHalfband9::filterKernel(const TTFloat64& input, TTFloat64& outputPath0, TTFloat64& outputPath1, TTPtrSizedInt channel)
144 {
145  TTFloat64 delayOutput;
146  TTFloat64 temp;
147 
148  TTBASE(mF0, TTAllpass1b)->calculateValue(input, temp, channel);
149  TTBASE(mF2, TTAllpass1b)->calculateValue(temp, outputPath0, channel);
150 
151  TTBASE(mDelay, TTAllpass1a)->calculateValue(input, delayOutput, channel);
152  TTBASE(mF1, TTAllpass1b)->calculateValue(delayOutput, temp, channel);
153  TTBASE(mF3, TTAllpass1b)->calculateValue(temp, outputPath1, channel);
154 }
155 
156 
157 TTErr TTHalfband9::calculateLowpass(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
158 {
159  TTFloat64 outputFromPath0;
160  TTFloat64 outputFromPath1;
161 
162  filterKernel(x, outputFromPath0, outputFromPath1, channel);
163  y = (outputFromPath0 + outputFromPath1) * 0.5;
164  return kTTErrNone;
165 }
166 
167 
168 TTErr TTHalfband9::calculateHighpass(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
169 {
170  TTFloat64 outputFromPath0;
171  TTFloat64 outputFromPath1;
172 
173  filterKernel(x, outputFromPath0, outputFromPath1, channel);
174  y = (outputFromPath0 - outputFromPath1) * 0.5;
175  return kTTErrNone;
176 }
177 
178 
179 // for every second input sample, we calculate an output sample
180 TTErr TTHalfband9::calculateDownsample(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
181 {
182  TTFloat64 temp_0;
183  TTFloat64 temp_1;
184 
185  if (mRSwitch[channel]) {
186  TTBASE(mR0, TTAllpass1a)->calculateValue(x, temp_0, channel);
187  TTBASE(mR2, TTAllpass1a)->calculateValue(temp_0, temp_1, channel);
188  y = (temp_1 + mY1[channel]) * 0.5;
189  mRSwitch[channel] = 0;
190  }
191  else {
192  TTBASE(mR1, TTAllpass1a)->calculateValue(x, temp_0, channel);
193  TTBASE(mR3, TTAllpass1a)->calculateValue(temp_0, mY1[channel], channel);
194  mRSwitch[channel] = 1;
195  }
196 
197  return kTTErrNone;
198 }
199 
200 
201 // for every second output sample, we calculate from a given input sample
202 TTErr TTHalfband9::calculateUpsample(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
203 {
204  TTFloat64 temp;
205 
206  if (mRSwitch[channel]) {
207  TTBASE(mR0, TTAllpass1a)->calculateValue(x, temp, channel);
208  TTBASE(mR2, TTAllpass1a)->calculateValue(temp, mY0[channel], channel);
209 
210  TTBASE(mR1, TTAllpass1a)->calculateValue(x, temp, channel);
211  TTBASE(mR3, TTAllpass1a)->calculateValue(temp, mY1[channel], channel);
212 
213  mRSwitch[channel] = 0;
214  }
215  else {
216  mRSwitch[channel] = 1;
217  }
218 
219  TTBASE(mDelay, TTAllpass1a)->calculateValue(mY1[channel], temp, channel);
220  y = (mY0[channel] + temp) * 0.5;
221 
222  return kTTErrNone;
223 }
224 
225 
226 TTErr TTHalfband9::processLowpass(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
227 {
228  TT_WRAP_CALCULATE_METHOD(calculateLowpass);
229 }
230 
231 
232 TTErr TTHalfband9::processHighpass(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
233 {
234  TT_WRAP_CALCULATE_METHOD(calculateHighpass);
235 }
236 
237 
238 TTErr TTHalfband9::processDownsample(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
239 {
240  TTAudioSignal& in = inputs->getSignal(0);
241  TTAudioSignal& out = outputs->getSignal(0);
242  TTSampleValue* inSample;
243  TTSampleValue* outSample;
244  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(in, out);
245  TTPtrSizedInt channel;
246  TTUInt16 targetVectorSize = in.getVectorSizeAsInt() / 2;
247  //TTErr err;
248 
249  out.changeVectorSize(targetVectorSize);
250  out.setSampleRate(in.getSampleRate() / 2);
251  for (channel=0; channel<numchannels; channel++) {
252  TTUInt16 n = targetVectorSize;
253 
254  inSample = in.mSampleVectors[channel];
255  outSample = out.mSampleVectors[channel];
256 
257  while (n--) {
258  calculateDownsample(*inSample, *outSample, channel);
259  inSample++;
260  calculateDownsample(*inSample, *outSample, channel);
261  inSample++;
262  outSample++;
263  }
264  }
265  return kTTErrNone;
266 }
267 
268 
269 TTErr TTHalfband9::processUpsample(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
270 {
271  TTAudioSignal& in = inputs->getSignal(0);
272  TTAudioSignal& out = outputs->getSignal(0);
273  TTSampleValue* inSample;
274  TTSampleValue* outSample;
275  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(in, out);
276  TTPtrSizedInt channel;
277  TTUInt16 targetVectorSize = in.getVectorSizeAsInt() * 2;
278  TTErr err;
279 
280  err = out.changeVectorSize(targetVectorSize);
281  if (!err) {
282  out.setSampleRate(in.getSampleRate() * 2);
283  for (channel=0; channel<numchannels; channel++) {
284  TTUInt16 n = in.getVectorSizeAsInt();
285 
286  inSample = in.mSampleVectors[channel];
287  outSample = out.mSampleVectors[channel];
288 
289  while (n--) {
290  calculateUpsample(*inSample, *outSample, channel);
291  outSample++;
292  calculateUpsample(*inSample, *outSample, channel);
293  outSample++;
294  inSample++;
295  }
296  }
297  }
298  return kTTErrNone;
299 }
300 
TTAudioObject mF2
path0
Definition: TTHalfband9.h:36
TTHalfband9 is a 9-Pole Halfband filter built up from a 2-path allpass structure. ...
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTAudioObject mDelay
path1
Definition: TTHalfband9.h:44
TTSymbol mMode
Attribute: lowpass or highpass.
Definition: TTHalfband9.h:50
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
TTSampleVector mY1
resampling path1 output (for each channel)
Definition: TTHalfband9.h:48
#define TTBASE(instance_, class_)
Macro to access the actual C++ class that is contained inside of the TTObject as a pointer...
Definition: TTObject.h:211
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTSampleVector mY0
resampling path0 output (for each channel)
Definition: TTHalfband9.h:47
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
TTAudioObject mR0
path0, resampling
Definition: TTHalfband9.h:37
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
A first-order building-block allpass filter.
Definition: TTAllpass1a.h:25
static TTChannelCount getMinChannelCount(const TTAudioSignal &signal1, const TTAudioSignal &signal2)
Use this class method to determine the least number of channels the two signals have in common...
The TTAudioSignal class represents N vectors of audio samples for M channels.
Definition: TTAudioSignal.h:57
TTSampleValue ** mSampleVectors
An array of pointers to the first sample in each vector. Declared Public for fast access...
Definition: TTAudioSignal.h:74
TTUInt16 TTChannelCount
Data type used when counting the number of channels in multi-channel audio signals and processes...
Definition: TTAudioSignal.h:31
TTAudioObject mR2
path0, resampling
Definition: TTHalfband9.h:38
A simple container for an array of TTAudioSignal pointers.
TTSampleVector mRSwitch
resampling switch (so we know which path to calculate)
Definition: TTHalfband9.h:46
long TTPtrSizedInt
An integer that is the same size as a pointer.
Definition: TTBase.h:240
A first-order building-block allpass filter.
Definition: TTAllpass1b.h:25
TTAudioObject mF3
path1
Definition: TTHalfband9.h:41
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTAudioObject mR1
path1, resampling
Definition: TTHalfband9.h:42
TTAudioObject mF0
path0
Definition: TTHalfband9.h:35
#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
TTAudioObject mR3
path1, resampling
Definition: TTHalfband9.h:43
TTFloat64 TTSampleValue
A value representing a single audio sample.
Definition: TTBase.h:230
[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
TTAudioObject mF1
path1
Definition: TTHalfband9.h:40