Jamoma API  0.6.0.a19
TTFFT.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFftLib
4  *
5  * @brief ##TTfft - Fast Fourier Transforms
6  *
7  * @details If a channel is simultaneously muted and soloed, soloing takes presedence.
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @copyright Copyright © 2010, Tim 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 "TTFFT.h"
18 
19 #define thisTTClass TTfft
20 #define thisTTClassName "fft"
21 #define thisTTClassTags "audio, processor, math"
22 
23 const int TTfft::kTTFFTPerformFFT = 1;
24 const int TTfft::kTTFFTPerformIFFT = -1;
25 
26 // prototype of function from fftsg.c
27 extern "C" void cdft(int n, int isgn, double *a, int *ip, double *w);
28 extern "C" void rdft(int n, int isgn, double *a, int *ip, double *w);
29 // mayer prototypes
30 #include "mayer_fft.h"
31 
32 
33 TT_AUDIO_CONSTRUCTOR,
34  mVectorSize(0),
35  mInverse(false),
36  mInverseValue(1)
37 {
41 
42  setAttributeValue(TT("mode"), TT("real"));
43  setAttributeValue(TT("algorithm"), TT("ooura"));
44 
45  // TODO: add the ooura-radix4 -- maybe it should even be the should be the default?
46  // (based on benchmarks @ fftw's site and powers-of-two?) or maybe the split-radix is fine...
47 }
48 
49 
50 TTfft::~TTfft()
51 {
52  ;
53 }
54 
55 
57 {
58  mInverse = newValue;
59  if (mInverse)
60  mInverseValue = kTTFFTPerformIFFT;
61  else
62  mInverseValue = kTTFFTPerformFFT;
63  return kTTErrNone;
64 }
65 
66 
67 TTErr TTfft::setMode(const TTValue& newValue)
68 {
69  mMode = newValue;
70  return updateProcessPointers();
71 }
72 
73 
75 {
76  mAlgorithm = newValue;
77  return updateProcessPointers();
78 }
79 
80 
81 TTErr TTfft::updateProcessPointers()
82 {
83  if (mMode == TT("real") && mAlgorithm == TT("ooura"))
84  setProcessMethod(processRealOoura);
85  else if (mMode == TT("complex") && mAlgorithm == TT("ooura"))
87  else if (mMode == TT("real") && mAlgorithm == TT("mayer"))
88  setProcessMethod(processRealMayer);
89  else // complex && mayer
90  setProcessMethod(processComplexMayer);
91  return kTTErrNone;
92 }
93 
94 
95 #if 0
96 #pragma mark -
97 #pragma mark Process Routines
98 #endif
99 
100 #define TTFFT_PROCESS_UPDATE_CHANNELCOUNT \
101  numChannels = in.getNumChannelsAsInt(); \
102  /* if we're doing an IFFT, then we assume the out channels is <= in channels already*/ \
103  if (out.getNumChannelsAsInt() != numChannels*2 && !mInverse) { \
104  TTValue v = numChannels*2; \
105  out.setMaxNumChannels(v); \
106  out.setNumChannels(v); \
107  }
108 
109 #define TTFFT_PROCESS_UPDATE_VECTORSIZE \
110  if (vs != mVectorSize) { \
111  mWorkArea.resize(vs); \
112  mWorkArea.assign(vs, 0); \
113  \
114  mCosSinTable.resize(vs); \
115  mCosSinTable.assign(vs, 0.0); \
116  \
117  mBuffer.resize(vs*2); \
118  mBuffer.assign(vs, 0.0); \
119  \
120  mVectorSize = vs; \
121  mRVectorSize = 1.0/(mVectorSize/2.0); \
122  }
123 
124 #define TTFFT_PROCESS_IFFT_PREP_INPUT_BUFFER \
125  for (int i=0; i<vs; i++) { \
126  /* mult by mRVectorSize to normalize the FFT */ \
127  mBuffer[i] = *inSampleReal++ * mRVectorSize; \
128  mBuffer[i+vs] = *inSampleImaginary++ * mRVectorSize; \
129  }
130 
131 #define TTFFT_PROCESS_IFFT_PREP_OUTPUT_BUFFER \
132  for (int i=0; i<vs; i++) \
133  *outSample++ = mBuffer[i];
134 
135 #define TTFFT_PROCESS_FFT_PREP_INPUT_BUFFER \
136  for (int i=0; i<vs; i++) \
137  mBuffer[i] = *inSample++;
138 
139 #define TTFFT_PROCESS_FFT_PREP_OUTPUT_BUFFER \
140  for (int i=0; i<vs; i++) { \
141  *outSampleReal++ = mBuffer[i]; \
142  *outSampleImaginary++ = mBuffer[i+vs]; \
143  }
144 
145 
147 {
148  TTAudioSignal& in = inputs->getSignal(0);
149  TTAudioSignal& out = outputs->getSignal(0);
150  TTUInt16 vs = in.getVectorSizeAsInt();
151  TTChannelCount numChannels;
152  TTChannelCount channel;
153 
154  TTFFT_PROCESS_UPDATE_CHANNELCOUNT
155  TTFFT_PROCESS_UPDATE_VECTORSIZE
156 
157  if (mInverse) {
158  for (channel=0; channel<numChannels/2; channel++) {
159  TTSampleValuePtr inSampleReal = in.mSampleVectors[channel];
160  TTSampleValuePtr inSampleImaginary = in.mSampleVectors[channel*2+1];
161  TTSampleValuePtr outSample = out.mSampleVectors[channel];
162 
163  TTFFT_PROCESS_IFFT_PREP_INPUT_BUFFER
164  cdft(mVectorSize, mInverseValue, &mBuffer[0], &mWorkArea[0], &mCosSinTable[0]);
165  TTFFT_PROCESS_IFFT_PREP_OUTPUT_BUFFER
166  }
167  }
168  else {
169  for (channel=0; channel<numChannels; channel++) {
170  TTSampleValuePtr inSample = in.mSampleVectors[channel];
171  TTSampleValuePtr outSampleReal = out.mSampleVectors[channel*2];
172  TTSampleValuePtr outSampleImaginary = out.mSampleVectors[channel*2+1];
173 
174  TTFFT_PROCESS_FFT_PREP_INPUT_BUFFER
175  cdft(mVectorSize, mInverseValue, &mBuffer[0], &mWorkArea[0], &mCosSinTable[0]);
176  TTFFT_PROCESS_FFT_PREP_OUTPUT_BUFFER
177  }
178  }
179 
180  return kTTErrNone;
181 }
182 
183 
184 TTErr TTfft::processRealOoura(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
185 {
186  TTAudioSignal& in = inputs->getSignal(0);
187  TTAudioSignal& out = outputs->getSignal(0);
188  TTUInt16 vs = in.getVectorSizeAsInt();
189  TTChannelCount numChannels;
190  TTChannelCount channel;
191 
192  TTFFT_PROCESS_UPDATE_CHANNELCOUNT
193  TTFFT_PROCESS_UPDATE_VECTORSIZE
194 
195  if (mInverse) {
196  for (channel=0; channel<numChannels/2; channel++) {
197  TTSampleValuePtr inSampleReal = in.mSampleVectors[channel];
198  TTSampleValuePtr inSampleImaginary = in.mSampleVectors[channel*2+1];
199  TTSampleValuePtr outSample = out.mSampleVectors[channel];
200 
201  TTFFT_PROCESS_IFFT_PREP_INPUT_BUFFER
202  rdft(mVectorSize, mInverseValue, &mBuffer[0], &mWorkArea[0], &mCosSinTable[0]);
203  TTFFT_PROCESS_IFFT_PREP_OUTPUT_BUFFER
204  }
205  }
206  else {
207  for (channel=0; channel<numChannels; channel++) {
208  TTSampleValuePtr inSample = in.mSampleVectors[channel];
209  TTSampleValuePtr outSampleReal = out.mSampleVectors[channel*2];
210  TTSampleValuePtr outSampleImaginary = out.mSampleVectors[channel*2+1];
211 
212  TTFFT_PROCESS_FFT_PREP_INPUT_BUFFER
213  rdft(mVectorSize, mInverseValue, &mBuffer[0], &mWorkArea[0], &mCosSinTable[0]);
214  TTFFT_PROCESS_FFT_PREP_OUTPUT_BUFFER
215  }
216  }
217 
218  return kTTErrNone;
219 }
220 
221 
222 TTErr TTfft::processComplexMayer(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
223 {
224  TTAudioSignal& in = inputs->getSignal(0);
225  TTAudioSignal& out = outputs->getSignal(0);
226  TTUInt16 vs = in.getVectorSizeAsInt();
227  TTChannelCount numChannels;
228  TTChannelCount channel;
229 
230  TTFFT_PROCESS_UPDATE_CHANNELCOUNT
231  TTFFT_PROCESS_UPDATE_VECTORSIZE
232 
233  if (mInverse) {
234  for (channel=0; channel<numChannels/2; channel++) {
235  TTSampleValuePtr inSampleReal = in.mSampleVectors[channel];
236  TTSampleValuePtr inSampleImaginary = in.mSampleVectors[channel*2+1];
237  TTSampleValuePtr outSample = out.mSampleVectors[channel];
238 
239  TTFFT_PROCESS_IFFT_PREP_INPUT_BUFFER
240  mayer_ifft(mVectorSize, &mBuffer[0], &mBuffer[vs]);
241  TTFFT_PROCESS_IFFT_PREP_OUTPUT_BUFFER
242  }
243  }
244  else {
245  for (channel=0; channel<numChannels; channel++) {
246  TTSampleValuePtr inSample = in.mSampleVectors[channel];
247  TTSampleValuePtr outSampleReal = out.mSampleVectors[channel*2];
248  TTSampleValuePtr outSampleImaginary = out.mSampleVectors[channel*2+1];
249 
250  TTFFT_PROCESS_FFT_PREP_INPUT_BUFFER
251  mayer_fft(mVectorSize, &mBuffer[0], &mBuffer[vs]);
252  TTFFT_PROCESS_FFT_PREP_OUTPUT_BUFFER
253  }
254  }
255 
256  return kTTErrNone;
257 }
258 
259 
260 TTErr TTfft::processRealMayer(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
261 {
262  TTAudioSignal& in = inputs->getSignal(0);
263  TTAudioSignal& out = outputs->getSignal(0);
264  TTUInt16 vs = in.getVectorSizeAsInt();
265  TTChannelCount numChannels;
266  TTChannelCount channel;
267 
268  TTFFT_PROCESS_UPDATE_CHANNELCOUNT
269  TTFFT_PROCESS_UPDATE_VECTORSIZE
270 
271  if (mInverse) {
272  for (channel=0; channel<numChannels/2; channel++) {
273  TTSampleValuePtr inSampleReal = in.mSampleVectors[channel];
274  TTSampleValuePtr inSampleImaginary = in.mSampleVectors[channel*2+1];
275  TTSampleValuePtr outSample = out.mSampleVectors[channel];
276 
277  TTFFT_PROCESS_IFFT_PREP_INPUT_BUFFER
278  mayer_realifft(mVectorSize, &mBuffer[0]);
279  TTFFT_PROCESS_IFFT_PREP_OUTPUT_BUFFER
280  }
281  }
282  else {
283  for (channel=0; channel<numChannels; channel++) {
284  TTSampleValuePtr inSample = in.mSampleVectors[channel];
285  TTSampleValuePtr outSampleReal = out.mSampleVectors[channel*2];
286  TTSampleValuePtr outSampleImaginary = out.mSampleVectors[channel*2+1];
287 
288  TTFFT_PROCESS_FFT_PREP_INPUT_BUFFER
289  mayer_realfft(mVectorSize, &mBuffer[0]);
290  TTFFT_PROCESS_FFT_PREP_OUTPUT_BUFFER
291  }
292  }
293 
294  return kTTErrNone;
295 }
296 
297 
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTErr setMode(const TTValue &newValue)
Attribute accessor.
Definition: TTFFT.cpp:67
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTErr setInverse(const TTValue &newValue)
Attribute accessor.
Definition: TTFFT.cpp:56
TTErr setAlgorithm(const TTValue &newValue)
Attribute accessor.
Definition: TTFFT.cpp:74
Symbol type.
Definition: TTBase.h:282
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
TTfft - Fast Fourier Transforms
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
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.
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
No Error.
Definition: TTBase.h:343
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr processComplexOoura(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
FFT Audio Process Routine.
Definition: TTFFT.cpp:146