Nsound  0.9.4
Public Member Functions | Static Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
Nsound::FFTransform Class Reference

A Class that performes the Fast Fouier Transfrom on a Buffer. More...

#include <Nsound/FFTransform.h>

Public Member Functions

 FFTransform (const float64 &sample_rate)
 
 ~FFTransform ()
 Destructor. More...
 
Buffer fft (const Buffer &time_domain) const
 Transforms the time_domain signal and calculates the FFT. More...
 
FFTChunkVector fft (const Buffer &input, int32 n_order, int32 n_overlap=0) const
 Performs the FFT of size N on the input Buffer of overlaping frames. More...
 
Buffer ifft (const FFTChunkVector &input) const
 Peforms an inverse FFT on each FFTChunk and concatenates the output. More...
 
Buffer ifft (const Buffer &frequency_domain) const
 Peforms an inverse FFT on the input Buffer. More...
 
void setWindow (WindowType type)
 A window is multiplied by the input prior to performing the transform, this help reduce artifacts near the edges. More...
 

Static Public Member Functions

static int32 roundUp2 (int32 raw)
 Returns nearest power of 2 >= raw. More...
 

Protected Attributes

uint32 sample_rate_
 Samples per second. More...
 

Private Member Functions

void fft (Buffer &real, Buffer &img, int32 n_order) const
 Peforms an inplace, nth order Fast Fouier Transform on the Buffers. More...
 

Private Attributes

WindowType type_
 

Detailed Description

A Class that performes the Fast Fouier Transfrom on a Buffer.

Implementing the fft algorithm on page 235 of the book: "Digital Signal Processing: A Practical Guide for Engineers and Scientists"

ISBN-13: 978-0-7506-7444-7

ISBN-10: 0-7506-7444-X

Definition at line 57 of file FFTransform.h.

Constructor & Destructor Documentation

FFTransform::FFTransform ( const float64 sample_rate)

Creates an FFTTransform instance. The sample rate here is only used to tell the FFTChunk objects how to plot the spectrum, otherwise it does play a role.

Example:
// C++
FFTransform t(44100.0);
// Python
t = FFTransform(44100.0)

Definition at line 41 of file FFTransform.cc.

42  :
43  sample_rate_(static_cast<uint32>(sample_rate)),
45 {
46 }
uint32 sample_rate_
Samples per second.
Definition: FFTransform.h:220
Nsound::FFTransform::~FFTransform ( )
inline

Destructor.

Definition at line 77 of file FFTransform.h.

77 {};

Member Function Documentation

Buffer FFTransform::fft ( const Buffer time_domain) const

Transforms the time_domain signal and calculates the FFT.

The size of the FFT is determined to be a power of 2 greater than or equal to the length of time_domain. If time_domain is less than a power of 2, the Buffer is padded with zeros until it is exactly a power of 2.

Example:
// C++
FFTransform t(44100.0);
Buffer b("california.wav");
Buffer fdomain;
fdomain = t.fft(b);
// Python
t = FFTransform(44100.0)
b = Buffer("california.wav")
fdomain = t.fft(b)

Definition at line 50 of file FFTransform.cc.

References Nsound::Buffer::getLength(), Nsound::Buffer::getSpeedUp(), roundUp2(), and sample_rate_.

Referenced by Nsound::Spectrogram::computeMagnitude(), fft(), FFTransform_UnitTest(), Nsound::Filter::getFrequencyResponse(), Nsound::Filter::getPhaseResponse(), ifft(), main(), my_main(), Nsound::Stretcher::searchForBestMatch(), and Nsound::Spectrogram::Spectrogram().

51 {
52  int32 N = roundUp2(time_domain.getLength());
53 
54  FFTChunkVector v = fft(time_domain, N);
55 
56  if(v.size() >= 1)
57  {
58  // Calculate the magnitude of the frequency domain.
59  Buffer f_domain = v[0].getMagnitude();
60 
61  // Resample so to return exacly sample_rate / 2 samples.
62  float64 sr_2 = sample_rate_ / 2.0;
63 
64  float64 factor = static_cast<float64>(f_domain.getLength()) / sr_2;
65 
66  // Simple down sample.
67  return f_domain.getSpeedUp(factor);
68  }
69 
70  return time_domain;
71 }
Buffer getSpeedUp(float64 step_size) const
Resamples a copy of this Buffer by the step_size, no interpolation.
Definition: Buffer.h:1707
double float64
Definition: Nsound.h:146
static int32 roundUp2(int32 raw)
Returns nearest power of 2 >= raw.
Definition: FFTransform.cc:274
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
uint32 sample_rate_
Samples per second.
Definition: FFTransform.h:220
A Buffer for storing audio samples.
Definition: Buffer.h:60
signed int int32
Definition: Nsound.h:142
Buffer fft(const Buffer &time_domain) const
Transforms the time_domain signal and calculates the FFT.
Definition: FFTransform.cc:50
std::vector< FFTChunk > FFTChunkVector
Definition: FFTChunk.h:119
FFTChunkVector FFTransform::fft ( const Buffer input,
int32  n_order,
int32  n_overlap = 0 
) const

Performs the FFT of size N on the input Buffer of overlaping frames.

The size of the FFT is specifed by n_order. The input Buffer is broken up into frames of size n_order, the returned FFTChunkVector is the result for each frame. If n_overlap is > 0, the frames will overlap by that number of samples.

Example 1:

Let n_order = 16 and n_overlap = 0, this how the input is split into frames.

input = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] // 42 samples
|xxxxxxxxxxxxxxx|xxxxxxxxxxxxxxx|xxxxxxxxxx00000| // frames
16 samples 16 samples 16 samples + pad

The returned FFTChunkVector will have 3 FFTChunk objects that represent the FFT for each of the frames above, note that the last frame will be padded out to compile a 16-point FFT.

Example 2:

Let n_order = 16 and n_overlap = 4, this how the input is split into frames.

input = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx] // 42 samples
|xxxxxxxxxxxxxxx|
16 samples |xxxxxxxxxxxxxxx|
16 samples |xxxxxxxxxxxxxxx|
16 samples |xxx000000000000|
16 samples

The returned FFTChunkVector will have 4 FFTChunk objects that represent the FFT for each of the frames above, note that the these frames contain overlapping samples as specified. Also note that the last frame in this case has a large number of padded zeros.

Code Example:
// C++
FFTransform t(44100.0);
Buffer b("california.wav");
vec = t.fft(b, 16, 4);
// Python
t = FFTransform(44100.0)
b = Buffer("california.wav")
vec = t.fft(b, 16, 4)

Definition at line 75 of file FFTransform.cc.

References Nsound::Generator::drawWindow(), fft(), Nsound::Buffer::getLength(), roundUp2(), sample_rate_, Nsound::Generator::silence(), Nsound::Buffer::subbuffer(), and type_.

76 {
77  const int32 N = roundUp2(n_order);
78 
79  const int32 input_length = input.getLength();
80 
81  FFTChunkVector vec;
82 
83  Generator gen(1);
84 
85  Buffer fft_window = gen.drawWindow(N, type_);
86 
87  for(int32 n = 0; n < input_length; n += (N - n_overlap))
88  {
89  // Create an FFTChunk to operate on.
90  FFTChunk chunk(N, sample_rate_, input.getLength());
91 
92  // Grab N samples from the input buffer
93 
94  Buffer sub_signal = input.subbuffer(n,N);
95 
96  // Apply window
97  int32 sub_length = sub_signal.getLength();
98  if(sub_length == N)
99  {
100  sub_signal *= fft_window;
101  }
102  else
103  {
104  sub_signal *= gen.drawWindow(sub_length, type_);
105  }
106 
107  (*chunk.real_) = sub_signal;
108 
109  int32 chunk_size = chunk.real_->getLength();
110 
111  // If there is less than N samples, pad with zeros
112  for(int32 i = 0; i < N - chunk_size; ++i)
113  {
114  (*chunk.real_) << 0.0;
115  }
116 
117  // Zero out the imaginary side.
118  (*chunk.imag_) = gen.silence(N);
119 
120  fft(*chunk.real_, *chunk.imag_, N);
121 
122  vec.push_back(chunk);
123  }
124 
125  return vec;
126 }
Buffer subbuffer(uint32 start_index, uint32 n_samples=0) const
Slice the Buffer.
Definition: Buffer.cc:2073
Results of performing an FFT are stored in this class.
Definition: FFTChunk.h:49
static int32 roundUp2(int32 raw)
Returns nearest power of 2 >= raw.
Definition: FFTransform.cc:274
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
uint32 sample_rate_
Samples per second.
Definition: FFTransform.h:220
A Buffer for storing audio samples.
Definition: Buffer.h:60
signed int int32
Definition: Nsound.h:142
Buffer fft(const Buffer &time_domain) const
Transforms the time_domain signal and calculates the FFT.
Definition: FFTransform.cc:50
std::vector< FFTChunk > FFTChunkVector
Definition: FFTChunk.h:119
A class the provides draw utilities and a wavetable oscillator.
Definition: Generator.h:50
Buffer FFTransform::ifft ( const FFTChunkVector input) const

Peforms an inverse FFT on each FFTChunk and concatenates the output.

This transforms the frequency domain signals held in the FFTChunkVector back to the time domain. If the FFTChunkVector was created with non-overlapping frames, the resulting output Buffer will be nearly identical to the original input (there will be some small round-off error).

Exmample:
// C++
FFTransform t(44100.0);
Buffer b("california.wav");
vec = t.fft(b, 16);
Buffer b2;
b2 = t.ifft(vec);
// Python
t = FFTransform(44100.0)
b = Buffer("california.wav")
vec = t.fft(b, 16)
b2 = t.ifft(vec)

Definition at line 207 of file FFTransform.cc.

References Nsound::Buffer::begin(), fft(), Nsound::FFTChunk::imag_, Nsound::FFTChunk::isPolar(), Nsound::FFTChunk::real_, roundUp2(), Nsound::Buffer::subbuffer(), and Nsound::FFTChunk::toCartesian().

Referenced by FFTransform_UnitTest(), ifft(), and main().

208 {
209  Buffer output;
210 
211  FFTChunkVector::const_iterator itor = vec.begin();
212  FFTChunkVector::const_iterator end = vec.end();
213 
214  const uint32 N = roundUp2(itor->real_->getLength() - 2);
215  const float64 f_N = static_cast<float64>(N);
216 
217  while(itor != end)
218  {
219  FFTChunk chunk(*itor);
220 
221  if(chunk.isPolar()) chunk.toCartesian();
222 
223  // Change the sign of img.
224  *chunk.imag_ *= -1.0;
225 
226  // Perform the forwared fft
227  fft(*chunk.real_, *chunk.imag_, N);
228 
229  *chunk.real_ = chunk.real_->subbuffer(0, itor->getOriginalSize());
230 
231  // Divide the real by N.
232  *chunk.real_ /= f_N;
233 
234  // Change the sign of img. But the img is never used again so don't
235  // bother.
236 //~ img *= -1.0;
237 
238  output << *chunk.real_;
239 
240  ++itor;
241  }
242 
243  return output;
244 }
unsigned int uint32
Definition: Nsound.h:153
Results of performing an FFT are stored in this class.
Definition: FFTChunk.h:49
double float64
Definition: Nsound.h:146
static int32 roundUp2(int32 raw)
Returns nearest power of 2 >= raw.
Definition: FFTransform.cc:274
iterator begin()
Retruns the itreator at the start of the Buffer.
Definition: Buffer.h:285
A Buffer for storing audio samples.
Definition: Buffer.h:60
Buffer fft(const Buffer &time_domain) const
Transforms the time_domain signal and calculates the FFT.
Definition: FFTransform.cc:50
Buffer FFTransform::ifft ( const Buffer frequency_domain) const

Peforms an inverse FFT on the input Buffer.

This transforms the frequency domain signal held in the input Buffer back to the time domain. The input signal will get padded so its length is exactly a power of 2.

Exmample:
// C++
FFTransform t(44100.0);
Buffer b("california.wav");
fdomain = t.fft(b);
Buffer tdomain;
tdomain = t.ifft(fdomain);
// Python
t = FFTransform(44100.0)
b = Buffer("california.wav")
fdomain = t.fft(b, 16)
tdomain = t.ifft(fdomain)

Definition at line 248 of file FFTransform.cc.

References Nsound::Buffer::getLength(), Nsound::Buffer::getReverse(), ifft(), roundUp2(), sample_rate_, and Nsound::Buffer::subbuffer().

249 {
250  int32 N = roundUp2(frequency_domain.getLength());
251 
252  FFTChunk chunk(N, sample_rate_);
253 
254  *chunk.real_ << frequency_domain;
255 
256  for(uint32 i = 0; i < 2 * (N - frequency_domain.getLength()); ++i)
257  {
258  *chunk.real_ << 0.0;
259  }
260 
261  *chunk.real_ << frequency_domain.getReverse();
262 
263  *chunk.imag_ = 0.0 * *chunk.real_;
264 
265  FFTChunkVector vec;
266 
267  vec.push_back(chunk);
268 
269  return ifft(vec).subbuffer(0, frequency_domain.getLength());
270 }
Buffer subbuffer(uint32 start_index, uint32 n_samples=0) const
Slice the Buffer.
Definition: Buffer.cc:2073
unsigned int uint32
Definition: Nsound.h:153
Results of performing an FFT are stored in this class.
Definition: FFTChunk.h:49
Buffer ifft(const FFTChunkVector &input) const
Peforms an inverse FFT on each FFTChunk and concatenates the output.
Definition: FFTransform.cc:207
static int32 roundUp2(int32 raw)
Returns nearest power of 2 >= raw.
Definition: FFTransform.cc:274
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
uint32 sample_rate_
Samples per second.
Definition: FFTransform.h:220
signed int int32
Definition: Nsound.h:142
Buffer getReverse() const
Reverses the samples in a copy of this Buffer.
Definition: Buffer.h:1558
std::vector< FFTChunk > FFTChunkVector
Definition: FFTChunk.h:119
int32 FFTransform::roundUp2 ( int32  raw)
static

Returns nearest power of 2 >= raw.

Definition at line 274 of file FFTransform.cc.

Referenced by fft(), Nsound::Filter::getFrequencyAxis(), ifft(), and Nsound::Spectrogram::Spectrogram().

275 {
276  raw = static_cast<int32>(::fabs(static_cast<float64>(raw - 1)));
277 
278  int32 n;
279 
280  n = 1;
281  while(raw)
282  {
283  n <<= 1; // Multiply n by 2
284  raw >>= 1; // Divide raw by 2
285  }
286 
287  return n;
288 }
signed int int32
Definition: Nsound.h:142
void FFTransform::setWindow ( WindowType  type)

A window is multiplied by the input prior to performing the transform, this help reduce artifacts near the edges.

Definition at line 292 of file FFTransform.cc.

References type_.

293 {
294  type_ = type;
295 }
void FFTransform::fft ( Buffer real,
Buffer img,
int32  n_order 
) const
private

Peforms an inplace, nth order Fast Fouier Transform on the Buffers.

Definition at line 130 of file FFTransform.cc.

References M_PI, and sr.

131 {
132  const float64 pi = M_PI;
133  const int32 n_minus_1 = N - 1;
134  const int32 n_devide_2 = N / 2;
135  const int32 m = static_cast<uint32>(
136  std::log10(static_cast<float64>(N)) / std::log10(2.0) + 0.5);
137 
138  int32 j = n_devide_2;
139 
140  // Bit reversal sorting.
141  for(int32 i = 1; i <= N - 2 ; ++i)
142  {
143  if(i < j)
144  {
145  float64 temp_real = real[j];
146  float64 temp_img = img[j];
147 
148  real[j] = real[i];
149  img[j] = img[i];
150 
151  real[i] = temp_real;
152  img[i] = temp_img;
153  }
154 
155  int32 k = n_devide_2;
156 
157  while(k <= j)
158  {
159  j -= k;
160  k /= 2;
161  }
162  j += k;
163  }
164 
165  // Loop for each fft stage.
166  for(int32 l = 1; l <= m; ++l)
167  {
168  int32 le = static_cast<int32>(std::pow(2.0, l) + 0.5);
169  int32 le2 = le / 2;
170 
171  float64 ur = 1.0;
172  float64 ui = 0.0;
173 
174  // Calculate sine and cosine values.
175  float64 sr = std::cos(pi / static_cast<float64>(le2));
176  float64 si = -1.0 * std::sin(pi / static_cast<float64>(le2));
177 
178  // Loop for each sub DFT.
179  for(j = 1; j <= le2; ++j)
180  {
181  int32 j_minus_1 = j - 1;
182 
183  // Loop for each butterfly.
184  for(int32 i = j_minus_1; i <= n_minus_1; i += le)
185  {
186  int32 ip = i + le2;
187 
188  // Butterfly calculation.
189  float64 temp_real = ur * real[ip] - ui * img[ip];
190  float64 temp_img = ui * real[ip] + ur * img[ip];
191 
192  real[ip] = real[i] - temp_real;
193  img[ip] = img[i] - temp_img;
194 
195  real[i] += temp_real;
196  img[i] += temp_img;
197  }
198  float64 temp = ur;
199  ur = temp * sr - ui * si;
200  ui = temp * si + ui * sr;
201  }
202  }
203 }
unsigned int uint32
Definition: Nsound.h:153
#define M_PI
Definition: Nsound.h:121
double float64
Definition: Nsound.h:146
signed int int32
Definition: Nsound.h:142
float64 sr
Definition: example3.cc:24

Member Data Documentation

uint32 Nsound::FFTransform::sample_rate_
protected

Samples per second.

Definition at line 220 of file FFTransform.h.

Referenced by fft(), and ifft().

WindowType Nsound::FFTransform::type_
private

Definition at line 228 of file FFTransform.h.

Referenced by fft(), and setWindow().


The documentation for this class was generated from the following files: