Jamoma API  0.6.0.a19
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFilterLib
4  *
5  * @brief #TTHilbert9 is a 9th-order Hilbert Transform filter built up from a 2-path allpass structure
6  *
7  * @details A 9th-order Hilber Transform filter built-up from allpass building blocks. Based on Multirate Signal Processing for Communication Systems, Chapter 10 and "The Digital All-Pass Filter: A Versatile Signal Processing Building Block" by REGALIA, MITRA, and P.VAIDYANATHAN, 1988. @n
8  * @n
9  * This filter is so-named because we base this filter on TTHalfband9 filter, which we transform to produce the phase quadrature by flipping coefficient signs and decoupling the output of the two paths. @n
10  * @n
11  * This particular Hilbert filter may be a bit too crude for many applications, as the distortion to the phase quadrature (perfect 90º) begins to distort somewhat rapidly as the frequencies at the input get further and further away from f_s/2. Because of this, a higher-order filter would be a better match for most applications. For example, TTHilbert17 will offer more accurate results, albeit at a higher computational cost. @n
12  * @n
13  * An additional caveat regards phase linearity with regard to the input signal. While the output phases of the real and imaginary signals from this filter are 90º to each other, the phase response of both in relation to the input signal is non-linear. To acheive a linear-phase version, a linear halfband filter needs to serve as the base from which to transform. E.g. TTHalfbandLinear33 could be modified to become TTHilbertLinear33. @n
14  * @n
15  * Current implementation does not perform resampling. As with the halfband filters, we could make a version of this object that has downsampling and upsampling (e.g. for inverse hilber transforms) built-in. @n
16  * @n
17  * At the moment, however, we do not have any applications in Jamoma which require the use of hilbert-transformed signals to be processed at a lower rate.
18  *
19  * @authors Timothy Place, Trond Lossius
20  *
21  * @copyright Copyright © 2010, Timothy Place @n
22  * This code is licensed under the terms of the "New BSD License" @n
23  * http://creativecommons.org/licenses/BSD/
24  */
27 #include "TTHilbert9.h"
29 #define thisTTClass TTHilbert9
30 #define thisTTClassName "hilbert.9"
31 #define thisTTClassTags "dspFilterLib, audio, processor, hilbert"
32 // no "filter" tag because this is a special case that produces two outputs for one input and doesn't fit the general filter schema
35 #include <Algorithm>
36 #endif
39  mF0("allpass.1b"),
40  mF2("allpass.1b"),
41  mF1("allpass.1b"),
42  mF3("allpass.1b"),
43  mDelay("allpass.1a")
44 {
45  TTChannelCount initialMaxNumChannels = arguments;
47  addMessage(clear);
48  addUpdates(MaxNumChannels);
50  setAttributeValue(kTTSym_maxNumChannels, initialMaxNumChannels);
52  // for the simple 1-sample delay, we set alpha (the feedback coefficient) to zero
53  mDelay.set("alpha", 0.0);
55  // These coefficients are sign-flipped copies from the TTHalfband9 filter
56  mF0.set("alpha", -0.043646929608759);
57  mF2.set("alpha", -0.399125646691078);
59  mF1.set("alpha", -0.174628080915462);
60  mF3.set("alpha", -0.749510679417446);
62  setProcessMethod(processAudio);
63 }
66 TTHilbert9::~TTHilbert9()
67 {
68 }
71 TTErr TTHilbert9::updateMaxNumChannels(const TTValue& oldMaxNumChannels, TTValue&)
72 {
73  mF0.set(kTTSym_maxNumChannels, mMaxNumChannels);
74  mF1.set(kTTSym_maxNumChannels, mMaxNumChannels);
75  mF2.set(kTTSym_maxNumChannels, mMaxNumChannels);
76  mF3.set(kTTSym_maxNumChannels, mMaxNumChannels);
77  mDelay.set(kTTSym_maxNumChannels, mMaxNumChannels);
79  clear();
80  return kTTErrNone;
81 }
84 TTErr TTHilbert9::clear()
85 {
86  mF0.send(kTTSym_clear);
87  mF1.send(kTTSym_clear);
88  mF2.send(kTTSym_clear);
89  mF3.send(kTTSym_clear);
90  mDelay.send(kTTSym_clear);
91  return kTTErrNone;
92 }
95 TTErr TTHilbert9::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
96 {
97  TTAudioSignal& in = inputs->getSignal(0);
98  TTAudioSignal& outReal = outputs->getSignal(0);
99  TTAudioSignal& outImaginary = outputs->getSignal(1);
100  TTSampleValue* inSample;
101  TTSampleValue* outRealSample;
102  TTSampleValue* outImaginarySample;
103  TTChannelCount numChannels = TTAudioSignal::getMinChannelCount(in, outReal, outImaginary);
104  TTPtrSizedInt channel;
105  TTFloat64 temp_0;
106  TTFloat64 x;
107  TTUInt16 n;
108  TTFloat64 delayOutput;
110  for (channel=0; channel<numChannels; channel++) {
111  n = in.getVectorSizeAsInt();
113  inSample = in.mSampleVectors[channel];
114  outRealSample = outReal.mSampleVectors[channel];
115  outImaginarySample = outImaginary.mSampleVectors[channel];
117  while (n--) {
118  x = *inSample++;
120  TTBASE(mF0, TTAllpass1b)->calculateValue(x, temp_0, channel);
121  TTBASE(mF2, TTAllpass1b)->calculateValue(temp_0, *outRealSample++, channel);
123  TTBASE(mDelay, TTAllpass1a)->calculateValue(x, delayOutput, channel);
124  TTBASE(mF1, TTAllpass1b)->calculateValue(delayOutput, temp_0, channel);
125  TTBASE(mF3, TTAllpass1b)->calculateValue(temp_0, *outImaginarySample++, channel);
126  }
127  }
128  return kTTErrNone;
129 }
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTAudioObject mF1
Definition: TTHilbert9.h:73
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.
TTAudioObject mF0
Definition: TTHilbert9.h:70
#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.
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
TTAudioObject mDelay
Definition: TTHilbert9.h:75
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
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 mF2
Definition: TTHilbert9.h:71
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
A first-order building-block allpass filter.
Definition: TTAllpass1b.h:25
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
TTAudioObject mF3
Definition: TTHilbert9.h:74
No Error.
Definition: TTBase.h:343
TTHilbert9 is a 9th-order Hilbert Transform filter built up from a 2-path allpass structure ...
TTFloat64 TTSampleValue
A value representing a single audio sample.
Definition: TTBase.h:230
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