CSL  6.0
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 
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
28 }
29 
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 
60  : UnitGenerator(), mFFTSize(size),
61  mWrapper(size, type, CSL_FFT_INVERSE) {
63 }
64 
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 
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
Definition: CSL_Types.h:194
void setBin(int binNumber, float realPart, float imagPart)
Definition: Spectral.cpp:81
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
SampleComplex * SampleComplexVector
complex vector
Definition: CSL_Types.h:202
void binValueMagPhase(int binNumber, float *outMag, float *outPhase)
Definition: Spectral.cpp:74
void nextBuffer(Buffer &outputBuffer)
get a buffer of Frames – this is the core CSL "pull" function; the given buffer can be written into...
Definition: Spectral.cpp:137
SampleBuffer mWindowBuffer
Buffer to store window.
Definition: Spectral.h:40
CSL_FFTType
real/complex flag (determines results from forward FFT)
Definition: FFT_Wrapper.h:55
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
Effect – mix-in for classes that have unit generators as inputs (like filters).
Definition: CSL_Core.h:466
FFT(UnitGenerator &in, int size=CGestalt::blockSize(), CSL_FFTType type=CSL_FFT_COMPLEX)
Default size to the buffer size and flags to measure.
Definition: Spectral.cpp:19
SampleBuffer window()
Definition: Window.h:39
void setBinsMagPhase(float *mags, float *phases)
Definition: Spectral.cpp:128
void binValue(int binNumber, float *outRealPart, float *outComplexPart)
getter methods
Definition: Spectral.cpp:69
#define cx_i(val)
Definition: CSL_Types.h:200
void setBinMagPhase(int binNumber, float mag, float phase)
Definition: Spectral.cpp:121
HammingWindow: Belongs to the familly of cosine window functions.
Definition: Window.h:81
#define cx_r(val)
complex # accesor macros
Definition: CSL_Types.h:199
float sample
(could be changed to int, or double)
Definition: CSL_Types.h:191
void nextBuffer(Buffer &outputBuffer)
we override the general-case version because this needs a mono input
Definition: Spectral.cpp:36
int mFFTSize
This should be unsigned, but is signed for compatability with FFTW.
Definition: Spectral.h:71
static size_t size
Definition: fft_N.c:40
void setBins(float *real, float *imag)
Definition: Spectral.cpp:89
#define SAFE_FREE(ptr)
Definition: CGestalt.h:137
IFFT(int size=CGestalt::blockSize(), CSL_FFTType type=CSL_FFT_COMPLEX)
Default size to the buffer size and flags to measure.
Definition: Spectral.cpp:59
int mFFTSize
This should be unsigned, but is signed for compatability with FFTW.
Definition: Spectral.h:37
FFT complex spectral frames.
Definition: CSL_Core.h:73
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
Buffer mInBuf
input buffer
Definition: Spectral.h:39
bool mOverwriteOutput
no setter – create a new FFT to change size
Definition: Spectral.h:34
void allocateBuffers()
fcn to malloc storage buffers
Definition: CSL_Core.cpp:122
forward declaration
Definition: CSL_Core.h:241
SampleComplexPtr mSpectrum
spectral data I accumulate
Definition: Spectral.h:74
sample SampleComplex[2]
array-of-2 complex # type (like FFTW)
Definition: CSL_Types.h:198
#define SAFE_MALLOC(ptr, type, len)
Useful Macros.
Definition: CGestalt.h:103
Base class of CSL exceptions (written upper-case). Has a string message.