Jamoma API  0.6.0.a19
TTAllpass1.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTAllpass1 is a first order allpass filter
6  *
7  * @details
8  *
9  * @authors Timothy Place, Trond Lossius
10  *
11  * @copyright Copyright © 2003, 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 "TTAllpass1.h"
18 
19 #define thisTTClass TTAllpass1
20 #define thisTTClassName "allpass.1"
21 #define thisTTClassTags "dspFilterLib, audio, processor, filter, allpass"
22 
23 #ifdef TT_PLATFORM_WIN
24 #include <Algorithm>
25 #endif
26 
27 TT_AUDIO_CONSTRUCTOR,
28  mDelay(0),
29  mDelayMax(0),
30  mDelayInSamples(0),
31  mDelayMaxInSamples(0)
32 {
33  TTChannelCount initialMaxNumChannels = arguments;
34 
36  addAttributeWithSetter(DelayInSamples, kTypeInt64);
38  addAttributeWithSetter(DelayMaxInSamples, kTypeInt64);
41 
42  addMessage(clear);
43  addUpdates(SampleRate);
44  addUpdates(MaxNumChannels);
45 
46  setAttributeValue(kTTSym_maxNumChannels, initialMaxNumChannels);
47  setAttributeValue(TT("linearGain"), 1.0);
48  setAttributeValue(TT("delayMax"), 100.0);
49  setAttributeValue(TT("delay"), 0.0);
50  setProcessMethod(processAudio);
51 }
52 
53 
54 TTAllpass1::~TTAllpass1()
55 {
56  ;
57 }
58 
59 
60 // This is called every time that:
61 // 1. sr changes
62 // 2. mMaxNumChannels changes
63 // 3. maxNumSamples change
64 TTErr TTAllpass1::init(TTUInt64 newDelayMaxInSamples)
65 {
66  if (newDelayMaxInSamples) {
67  mDelayMaxInSamples = newDelayMaxInSamples;
69 
70  for (TTDelayBufferIter buffer = mFeedforward.begin(); buffer != mFeedforward.end(); ++buffer) {
71  buffer->resize(mDelayMaxInSamples);
72  buffer->clear();
73  }
74  for (TTDelayBufferIter buffer = mFeedback.begin(); buffer != mFeedback.end(); ++buffer) {
75  buffer->resize(mDelayMaxInSamples);
76  buffer->clear();
77  }
78  reset();
79  }
80  return kTTErrNone;
81 }
82 
83 
84 void TTAllpass1::reset()
85 {
86  for (TTDelayBufferIter buffer = mFeedforward.begin(); buffer != mFeedforward.end(); ++buffer)
87  buffer->setDelay(mDelayInSamples);
88  for (TTDelayBufferIter buffer = mFeedback.begin(); buffer != mFeedback.end(); ++buffer)
89  buffer->setDelay(mDelayInSamples);
90 }
91 
92 
93 TTErr TTAllpass1::updateMaxNumChannels(const TTValue& oldMaxNumChannels, TTValue&)
94 {
96  mFeedback.resize(mMaxNumChannels);
97  return init(mDelayMaxInSamples);
98 }
99 
100 
101 TTErr TTAllpass1::updateSampleRate(const TTValue& oldSampleRate, TTValue&)
102 {
103  init(long(srMill * mDelayMax)); // allocate a larger delay buffer if neccessary
104  return setDelay(mDelay); // hold the delay time in ms constant, despite the change of sr
105 }
106 
107 
109 {
110  for_each(mFeedforward.begin(), mFeedforward.end(), std::mem_fun_ref(&TTDelayBuffer::clear));
111  for_each(mFeedback.begin(), mFeedback.end(), std::mem_fun_ref(&TTDelayBuffer::clear));
112  return kTTErrNone;
113 }
114 
115 
117 {
118  mGain = newValue;
120  return kTTErrNone;
121 }
122 
123 
125 {
126  mLinearGain = newValue;
128  return kTTErrNone;
129 }
130 
131 
133 {
134  /*
135  delay = TTClip<TTFloat64>(newValue, 0.0, delayMax);
136  delayInSamples = long(delay * (sr / 1000.0));
137  for (TTChannelCount channel=0; channel<mMaxNumChannels; channel++) {
138  ffEndPtr[channel] = feedforward[channel] + delayInSamples;
139  fbEndPtr[channel] = feedback[channel] + delayInSamples;
140  }
141  return kTTErrNone;
142  */
143  mDelay = TTClip<TTFloat64>(newValue, 0.0, mDelayMax);
144 // mFractionalDelaySamples = mDelay * srMill;
145 // mDelayInSamples = mFractionalDelaySamples;
146 // mFractionalDelay = mFractionalDelaySamples - mDelayInSamples;
148 
149  reset();
150  return kTTErrNone;
151 }
152 
153 
155 {
156 // mFractionalDelaySamples = TTClip<TTUInt64>(newValue, 0, mDelayMaxInSamples);
157  mDelayInSamples = TTClip<TTUInt64>(newValue, 0, mDelayMaxInSamples);
158 // mDelayInSamples = mFractionalDelaySamples;
159 // mFractionalDelay = mFractionalDelaySamples - mDelayInSamples;
160 
161  mDelay = mDelayInSamples * 1000.0 * srInv;
162 
163  reset();
164  return kTTErrNone;
165 }
166 
167 
169 {
170  mDelayMax = newValue;
173  return kTTErrNone;
174 }
175 
176 
178 {
179  mDelayMaxInSamples = newValue;
180  mDelayMax = mDelayMaxInSamples * 1000.0 * srInv;
182  return kTTErrNone;
183 }
184 
185 
186 #if 0
187 #pragma mark -
188 #pragma mark dsp routines
189 #endif
190 
191 
192 inline TTErr TTAllpass1::calculateValue(const TTFloat64& x, TTFloat64& y, TTDelayBufferPtr* buffers)
193 {
194  TTDelayBufferPtr feedforwardBuffer = buffers[0];
195  TTDelayBufferPtr feedbackBuffer = buffers[1]; // NOTE: This is a little tricky!
196  TTFloat64 x1 = *feedforwardBuffer->mReadPointer;
197  TTFloat64 y1 = *feedbackBuffer->mReadPointer;
198  TTFloat64 alpha = mLinearGain;
199 
200  // Store the input in the feedforward buffer
201  *feedforwardBuffer->mWritePointer = x;
202 
203  // Apply the filter
204  // We start with the equation in standard form:
205  // y = alpha * x + x1 - alpha * y1;
206  // Then to a version that Fred Harris refers to as a "Re-Ordered All-Pass Filter Structure" in Multirate Signal Processing
207  // y = x1 + alpha * x - alpha * y1;
208  // Finally, here is a "Single Coefficient All-Pass Filter", dropping from 2 adds and 2 mults down to 2 adds and 1 mult
209  y = x1 + ((x - y1) * alpha);
210 
211  // The possibility of denormals is always lurking for IIR filters
212  TTZeroDenormal(y);
213 
214  // Store the output in the feedback buffer
215  *feedbackBuffer->mWritePointer = y;
216 
217  // Move the heads
218  feedforwardBuffer->mReadPointer++;
219  feedforwardBuffer->mWritePointer++;
220  feedbackBuffer->mReadPointer++;
221  feedbackBuffer->mWritePointer++;
222 
223  // wrap the pointers in the buffer, if needed
224  feedforwardBuffer->wrapForward();
225  feedbackBuffer->wrapForward();
226 
227  return kTTErrNone;
228 }
229 
230 
231 TTErr TTAllpass1::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
232 {
233  TTAudioSignal& in = inputs->getSignal(0);
234  TTAudioSignal& out = outputs->getSignal(0);
235  TTUInt16 vs;
236  TTSampleValue* inSample;
237  TTSampleValue* outSample;
238  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(in, out);
239  TTPtrSizedInt channel;
240  TTDelayBufferPtr buffers[2];
241 
242  for (channel=0; channel<numchannels; channel++) {
243  inSample = in.mSampleVectors[channel];
244  outSample = out.mSampleVectors[channel];
245  vs = in.getVectorSizeAsInt();
246  buffers[0] = &mFeedforward[channel];
247  buffers[1] = &mFeedback[channel];
248 
249  while (vs--) {
250  calculateValue(*inSample, *outSample, buffers);
251  outSample++;
252  inSample++;
253  }
254  }
255  return kTTErrNone;
256 }
257 
TTFloat64 TTDecibelsToLinearGain(TTFloat64 value)
Convert decibels into linear ampliude.
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTFloat64 TTLinearGainToDecibels(const TTFloat64 value)
Convert linear amplitude into deciBels.
TTErr setDelay(const TTValue &newValue)
Attribute accessor.
Definition: TTAllpass1.cpp:132
TTDelayBufferVector mFeedback
fb buffers for each channel
Definition: TTAllpass1.h:38
TTErr setDelayMaxInSamples(const TTValue &newValue)
Attribute Accessor.
Definition: TTAllpass1.cpp:177
TTFloat64 mDelayMax
Maximum delay time in milliseconds (how long is the buffer?)
Definition: TTAllpass1.h:31
TTErr clear()
This algorithm uses an IIR filter, meaning that it relies on feedback.
Definition: TTAllpass1.cpp:108
std::uint64_t TTUInt64
64 bit unsigned integer
Definition: TTBase.h:180
TTChannelCount mMaxNumChannels
This is the maximum number of channels that can be guaranteed to work.
TTErr setLinearGain(const TTValue &newValue)
Attribute accessor.
Definition: TTAllpass1.cpp:124
TTSampleValuePtr mWritePointer
"record" pointer for buffer
Definition: TTDelayBuffer.h:32
TTErr setDelayMax(const TTValue &newValue)
Attribute Accessor.
Definition: TTAllpass1.cpp:168
TTUInt32 mDelayMaxInSamples
size of the delay buffers
Definition: TTAllpass1.h:33
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTFloat64 mGain
Attribute: gain in db.
Definition: TTAllpass1.h:34
TTDelayBufferVector mFeedforward
ff buffers for each channel
Definition: TTAllpass1.h:37
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
TTUInt32 mDelayInSamples
Delay time in samples (internal)
Definition: TTAllpass1.h:32
64-bit floating point
Definition: TTBase.h:272
TTErr setGain(const TTValue &newValue)
Attribute accessor.
Definition: TTAllpass1.cpp:116
TTSampleValuePtr mReadPointer
"playback" pointer
Definition: TTDelayBuffer.h:33
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
64-bit signed integer, ragne is −9,223,372,036,854,775,808 through 9,223,372,036,854,775,807
Definition: TTBase.h:279
A simple container for an array of TTAudioSignal pointers.
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
TTFloat64 mDelay
Attribute: delay time in milliseconds.
Definition: TTAllpass1.h:30
TTFloat64 mLinearGain
Attribute: linear gain coefficient.
Definition: TTAllpass1.h:35
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 srMill
1/1000 of the current sample rate (samples per millisecond)
TTErr setDelayInSamples(const TTValue &newValue)
Attribute Accessor.
Definition: TTAllpass1.cpp:154
#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
TTFloat64 srInv
1.0 over the current sample rate (inverse)
No Error.
Definition: TTBase.h:343
TTAllpass1 is a first order allpass filter
void resize(size_type n)
Change the number of elements.
TTErr init(TTUInt64 newDelayMaxInSamples)
Internal initialization of buffers and pointers etc.
Definition: TTAllpass1.cpp:64
TTFloat64 TTSampleValue
A value representing a single audio sample.
Definition: TTBase.h:230
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTDelayBuffer is a container object that holds some audio in a chunk of memory, with accessors for us...
Definition: TTDelayBuffer.h:27
#define addUpdates(updateName)
An 'update' is a message sent to a subclass instance from its parent class.
Definition: TTMessage.h:44