Jamoma API  0.6.0.a19
TTHalfband3.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTHalfband3 is a 3rd-order up/down-sampling 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 "TTHalfband3.h"
18 
19 #define thisTTClass TTHalfband3
20 #define thisTTClassName "halfband.3"
21 #define thisTTClassTags "dspFilterLib, audio, processor, filter, lowpass, highpass, resampling"
22 
23 #ifdef TT_PLATFORM_WIN
24 #include <Algorithm>
25 #endif
26 
27 TT_AUDIO_CONSTRUCTOR,
28  mF0("allpass.1b"),
29  mDelay("allpass.1a"),
30  mR0("allpass.1a")
31 {
32  TTChannelCount initialMaxNumChannels = arguments;
33 
35  addUpdates(MaxNumChannels);
36 
37  setAttributeValue(kTTSym_maxNumChannels, initialMaxNumChannels);
38  setAttributeValue(TT("mode"), TT("lowpass"));
39 
40  // this coefficient gives w0 (stopband edge) at 0.48 * F_nyquist, with an attentuation of -85dB
41  mF0.set("alpha", 0.334654061320571);
42  mR0.set("alpha", 0.334654061320571);
43 
44  // this coefficient gives w0 (stopband edge) at 0.45 * F_nyquist, with an attentuation of -60dB
45  //mF0->setAttributeValue(TT("alpha"), 0.341748648258737);
46  //mR0->setAttributeValue(TT("alpha"), 0.341748648258737);
47  mDelay.set("alpha", 0.0);
48 }
49 
50 
51 TTHalfband3::~TTHalfband3()
52 {
53 }
54 
55 
56 TTErr TTHalfband3::updateMaxNumChannels(const TTValue& oldMaxNumChannels, TTValue&)
57 {
58  // update internal filters
59  mF0.set(kTTSym_maxNumChannels, mMaxNumChannels);
60  mR0.set(kTTSym_maxNumChannels, mMaxNumChannels);
61 
62  // update ourselves
63  mX1.resize(mMaxNumChannels);
64  mX1.assign(mMaxNumChannels, 0.0);
65 
66  return kTTErrNone;
67 }
68 
69 
70 TTErr TTHalfband3::setMode(const TTValue& newValue)
71 {
72  TTSymbol newMode = newValue;
73 
74  if (newMode == mMode)
75  return kTTErrNone;
76 
77  if (newMode == TT("upsample")) {
78  mMode = TT("upsample");
79  setCalculateMethod(calculateUpsample);
80  setProcessMethod(processUpsample);
81  }
82  else if (newMode == TT("downsample")) { // downsample
83  mMode = TT("downsample");
84  setCalculateMethod(calculateDownsample);
85  setProcessMethod(processDownsample);
86  }
87  else if (newMode == TT("highpass")) {
88  mMode = TT("highpass");
89  setCalculateMethod(calculateHighpass);
90  setProcessMethod(processHighpass);
91  }
92  else { // lowpass
93  mMode = TT("lowpass");
94  setCalculateMethod(calculateLowpass);
95  setProcessMethod(processLowpass);
96  }
97  return kTTErrNone;
98 }
99 
100 
101 TTErr TTHalfband3::calculateLowpass(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
102 {
103  TTFloat64 outputFromTopPath;
104  TTFloat64 outputFromBottomPathDelay;
105  TTBASE(mF0, TTAllpass1b)->calculateValue(x, outputFromTopPath, channel);
106  TTBASE(mDelay, TTAllpass1a)->calculateValue(x, outputFromBottomPathDelay, channel);
107  y = (outputFromTopPath + outputFromBottomPathDelay) * 0.5;
108  return kTTErrNone;
109 }
110 
111 
112 TTErr TTHalfband3::calculateHighpass(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
113 {
114  TTFloat64 outputFromTopPath;
115  TTFloat64 outputFromBottomPathDelay;
116 
117  TTBASE(mF0, TTAllpass1b)->calculateValue(x, outputFromTopPath, channel);
118  TTBASE(mDelay, TTAllpass1a)->calculateValue(x, outputFromBottomPathDelay, channel);
119 
120  y = (outputFromTopPath - outputFromBottomPathDelay) * 0.5;
121  return kTTErrNone;
122 }
123 
124 
125 // for every second input sample, we calculate an output sample
126 // see TTHalfband5 for more details
127 TTErr TTHalfband3::calculateDownsample(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
128 {
129  if (mX1[channel]) {
130  TTFloat64 temp;
131  TTBASE(mR0, TTAllpass1a)->calculateValue(x, temp, channel);
132  y = (temp + mX1[channel]) * 0.5;
133  mX1[channel] = 0;
134  }
135  else
136  mX1[channel] = x;
137 
138  return kTTErrNone;
139 }
140 
141 
142 // for every second output sample, we calculate from a given input sample
143 TTErr TTHalfband3::calculateUpsample(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel)
144 {
145  TTFloat64 temp;
146 
147  TTBASE(mDelay, TTAllpass1a)->calculateValue(x, temp, channel);
148  if (mX1[channel]) {
149  y = (temp + mX1[channel]) * 0.5;
150  mX1[channel] = 0;
151  }
152  else {
153  TTBASE(mR0, TTAllpass1a)->calculateValue(x, mX1[channel], channel);
154  y = (temp + mX1[channel]) * 0.5;
155  }
156  return kTTErrNone;
157 }
158 
159 
160 TTErr TTHalfband3::processLowpass(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
161 {
162  TT_WRAP_CALCULATE_METHOD(calculateLowpass);
163 }
164 
165 
166 TTErr TTHalfband3::processHighpass(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
167 {
168  TT_WRAP_CALCULATE_METHOD(calculateHighpass);
169 }
170 
171 
172 TTErr TTHalfband3::processDownsample(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
173 {
174  TTAudioSignal& in = inputs->getSignal(0);
175  TTAudioSignal& out = outputs->getSignal(0);
176  TTSampleValue* inSample;
177  TTSampleValue* outSample;
178  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(in, out);
179  TTPtrSizedInt channel;
180  TTUInt16 targetVectorSize = in.getVectorSizeAsInt() / 2;
181  //TTErr err;
182 
183  out.changeVectorSize(targetVectorSize);
184  out.setSampleRate(in.getSampleRate() / 2);
185  for (channel=0; channel<numchannels; channel++) {
186  TTUInt16 n = targetVectorSize;
187 
188  inSample = in.mSampleVectors[channel];
189  outSample = out.mSampleVectors[channel];
190 
191  while (n--) {
192  calculateDownsample(*inSample, *outSample, channel);
193  inSample++;
194  calculateDownsample(*inSample, *outSample, channel);
195  inSample++;
196  outSample++;
197  }
198  }
199  return kTTErrNone;
200 }
201 
202 
203 TTErr TTHalfband3::processUpsample(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
204 {
205  TTAudioSignal& in = inputs->getSignal(0);
206  TTAudioSignal& out = outputs->getSignal(0);
207  TTSampleValue* inSample;
208  TTSampleValue* outSample;
209  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(in, out);
210  TTPtrSizedInt channel;
211  TTUInt16 targetVectorSize = in.getVectorSizeAsInt() * 2;
212  TTErr err;
213 
214  err = out.changeVectorSize(targetVectorSize);
215  if (!err) {
216  out.setSampleRate(in.getSampleRate() / 2);
217  for (channel=0; channel<numchannels; channel++) {
218  TTUInt16 n = in.getVectorSizeAsInt();
219 
220  inSample = in.mSampleVectors[channel];
221  outSample = out.mSampleVectors[channel];
222 
223  while (n--) {
224  calculateUpsample(*inSample, *outSample, channel);
225  outSample++;
226  calculateUpsample(*inSample, *outSample, channel);
227  outSample++;
228  inSample++;
229  }
230  }
231  }
232  return kTTErrNone;
233 }
234 
TTAudioObject mDelay
pure delay (used by lowpass/highpass modes)
Definition: TTHalfband3.h:34
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
#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.
Symbol type.
Definition: TTBase.h:282
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
TTAudioObject mR0
path 0 (used by resampling modes)
Definition: TTHalfband3.h:35
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTAudioObject mF0
path0 (used by lowpass/highpass modes)
Definition: TTHalfband3.h:33
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
A simple container for an array of TTAudioSignal pointers.
TTSymbol mMode
Attribute: upsample or downsample.
Definition: TTHalfband3.h:37
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
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
TTSampleVector mX1
previous input sample (for each channel)
Definition: TTHalfband3.h:36
No Error.
Definition: TTBase.h:343
TTHalfband3 is a 3rd-order up/down-sampling filter built up from a 2-path allpass structure ...
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