CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

Spectral.cpp
Go to the documentation of this file.
1 //
2 // Spectral.cpp -- UnitGenerator for going to/from the spectral domain using FFTW
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5
6 #include "Spectral.h"
7 #include "Window.h"
8 #include <stdlib.h>
9 #include <math.h>
10 #include <string.h>
11
12 using namespace csl;
13
14 /// Forward FFT = analysis
15
16 // Constructor - Default size to the buffer size and flags to measure
17 // mBlockResizer(size) needed if different size than the default
18
19 FFT::FFT(UnitGenerator & in, int size, CSL_FFTType type)
20 : Effect(in), mFFTSize(size),
21 mWrapper(size, type, CSL_FFT_FORWARD), mInBuf(1, size), mWindowBuffer(0) {
22 // mSampleBuffer = (SampleBuffer) fftwf_malloc(sizeof(SampleBuffer) * mFFTSize);
23 HammingWindow * window = new HammingWindow(mFFTSize);
24 mWindowBuffer = window->window(); ///< Buffer to store samples
25 free(window);
26 mOverwriteOutput = false; // leave the spectrum in the buffer by default
27 mInBuf.allocateBuffers();
28 }
29
30 FFT::~FFT() {
31 free(mWindowBuffer);
32 }
33
34 // nextBuffer does the FFT -- note that we override the higher-level version of this method
35
36 void FFT::nextBuffer(Buffer& outputBuffer) throw (CException) {
37 unsigned numFrames = outputBuffer.mNumFrames; // get buffer length
38
39 pullInput(numFrames); // get the input samples via Effect
40 // Copy the input data into the buffer
41 memcpy(mInBuf.buffer(0), mInputPtr, numFrames * sizeof(sample));
42
43 SampleBuffer bufPtr = mInBuf.buffer(0); // apply signal window to buffer
44 SampleBuffer winPtr = mWindowBuffer;
45 for (int i = 0; i < mFFTSize; i++)
46 *bufPtr++ *= *winPtr++;
47
48 mWrapper.nextBuffer(mInBuf, outputBuffer); // execute the FFT
49
50 outputBuffer.mType = kSpectra; // set the type flag of the output buffer
51 this->changed((void *) & outputBuffer); // signal dependents (if any) of my change
52 return;
53 }
54
55 //
56 //// InvFFT = synthesis
57 //
58
59 IFFT::IFFT(int size, CSL_FFTType type)
60 : UnitGenerator(), mFFTSize(size),
61 mWrapper(size, type, CSL_FFT_INVERSE) {
62 SAFE_MALLOC(mSpectrum, SampleComplex, mFFTSize);
63 }
64
65 IFFT::~IFFT() {
66 SAFE_FREE(mSpectrum);
67 }
68
69 void IFFT::binValue(int binNumber, float * outRealPart, float * outImagPart) {
70 *outRealPart = cx_r(mSpectrum[binNumber]);
71 *outImagPart = cx_r(mSpectrum[binNumber]);
72 }
73
74 void IFFT::binValueMagPhase(int binNumber, float * outMag, float * outPhase) {
75 float myReal, myComplex;
76 binValue(binNumber, &myReal, &myComplex);
77 *outMag = hypot(myReal, myComplex);
78 *outPhase = (0.0 == myReal) ? 0 : atan(myComplex/myReal);
79 }
80
81 void IFFT::setBin(int binNumber, float realPart, float imagPart) {
82 #ifdef CSL_DEBUG
83 logMsg("\t\tset [%d] = %5.3f @ %5.3f", binNumber, realPart, imagPart);
84 #endif
85 cx_r(mSpectrum[binNumber]) = realPart;
86 cx_i(mSpectrum[binNumber]) = imagPart;
87 }
88
89 void IFFT::setBins(float * real, float * imag) {
90 for (int i = 0; i < mFFTSize; i++) {
91 cx_r(mSpectrum[i]) = real[i];
92 cx_i(mSpectrum[i]) = imag[i];
93 }
94 }
95
96 void IFFT::setBins(SampleComplexVector cmplxSpectrum) {
97 for (int i = 0; i < mFFTSize; i++) {
98 cx_r(mSpectrum[i]) = cx_r(cmplxSpectrum[i]);
99 cx_i(mSpectrum[i]) = cx_i(cmplxSpectrum[i]);
100 }
101 }
102
103 void IFFT::setBins(SampleBuffer cmplxSpectrum) {
104 for (int i = 0; i < mFFTSize; i += 2) {
105 cx_r(mSpectrum[i]) = *cmplxSpectrum++;
106 cx_i(mSpectrum[i]) = *cmplxSpectrum++;
107 }
108 }
109
110 void IFFT::setBins(int lower, int upper, float* real, float* imag) {
111 if (lower <0 || lower >= mFFTSize ) { return; } // It should throw an "out of range" exception.
112 if (upper <0 || upper >= mFFTSize ) { return; }
113 if (upper <lower ) { return; }
114
115 for (int i = lower; i < upper; i++) {
116 cx_r(mSpectrum[i]) = real[i];
117 cx_i(mSpectrum[i]) = imag[i];
118 }
119 }
120
121 void IFFT::setBinMagPhase(int binNumber, float mag, float phase) {
122 float myReal, myComplex;
123 myReal = mag*cos(phase);
124 myComplex = mag*sin(phase);
125 setBin(binNumber, myReal, myComplex);
126 }
127
128 void IFFT::setBinsMagPhase(float* mags, float* phases) {
129 for (int i = 0; i < mFFTSize; i++) {
130 cx_r(mSpectrum[i]) = mags[i] * cos(phases[i]);
131 cx_i(mSpectrum[i]) = mags[i] * sin(phases[i]);
132 }
133 }
134
135 // Do the IFFT::nextBuffer by calling the wrapper
136
137 void IFFT::nextBuffer(Buffer & outputBuffer) throw (CException) {
138 if (outputBuffer.mNumFrames != mWrapper.mSize) {
139 logMsg(kLogError,
140 "IFFT::nextBuffer # frames %d wrong for FFT size %d (use a block resizer).",
141 outputBuffer.mNumFrames, mWrapper.mSize);
142 return;
143 }
144 mInBuf.setSize(1, outputBuffer.mNumFrames);
145 mInBuf.setBuffer(0, (SampleBuffer) mSpectrum);
146
147 mWrapper.nextBuffer(mInBuf, outputBuffer); // execute the IFFT via the wrapper
148
149 return;
150 }
151