Nsound  0.9.4
Filter.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Filter.cc 916 2015-08-22 16:31:39Z weegreenblobbie $
4 //
5 // Copyright (c) 2009 to Present Nick Hilton
6 //
7 // weegreenblobbie_yahoo_com (replace '_' with '@' and '.')
8 //
9 //-----------------------------------------------------------------------------
10 
11 //-----------------------------------------------------------------------------
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation; either version 2 of the License, or
16 // (at your option) any later version.
17 //
18 // This program is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Library General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with this program; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 //
27 //-----------------------------------------------------------------------------
28 
29 #include <Nsound/AudioStream.h>
30 #include <Nsound/Buffer.h>
31 #include <Nsound/FFTransform.h>
32 #include <Nsound/Filter.h>
33 #include <Nsound/Plotter.h>
34 
35 #include <cmath>
36 #include <iostream>
37 
38 using namespace Nsound;
39 
41 Filter(const float64 & sample_rate)
42  :
43  sample_rate_(sample_rate),
44  two_pi_over_sample_rate_(2.0 * M_PI / sample_rate),
45  sample_time_(1.0 / sample_rate),
46  kernel_size_(0),
47  is_realtime_(false)
48 {
49 }
50 
53 filter(const AudioStream & x)
54 {
55  if(!is_realtime_) reset();
56 
57  uint32 n_channels = x.getNChannels();
58 
59  if(is_realtime_ && n_channels > 1)
60  {
61  M_THROW("In real-time mode, a filter per audio channel must be used!");
62  }
63 
64  AudioStream y(x.getSampleRate(), n_channels);
65 
66  for(uint32 channel = 0; channel < n_channels; ++channel)
67  {
68  y[channel] = filter(x[channel]);
69  }
70 
71  return y;
72 }
73 
76 filter(const AudioStream & x, const float64 & frequency)
77 {
78  if(!is_realtime_) reset();
79 
80  uint32 n_channels = x.getNChannels();
81 
82  if(is_realtime_ && n_channels > 1)
83  {
84  M_THROW("In real-time mode, a filter per audio channel must be used!");
85  }
86 
87  AudioStream y(x.getSampleRate(), n_channels);
88 
89  for(uint32 channel = 0; channel < n_channels; ++channel)
90  {
91  y[channel] = filter(x[channel], frequency);
92  }
93 
94  return y;
95 }
96 
99 filter(const AudioStream & x, const Buffer & frequency)
100 {
101  if(!is_realtime_) reset();
102 
103  uint32 n_channels = x.getNChannels();
104 
105  if(is_realtime_ && n_channels > 1)
106  {
107  M_THROW("In real-time mode, a filter per audio channel must be used!");
108  }
109 
110  AudioStream y(x.getSampleRate(), n_channels);
111 
112  for(uint32 channel = 0; channel < n_channels; ++channel)
113  {
114  y[channel] = filter(x[channel], frequency);
115  }
116 
117  return y;
118 }
119 
120 Buffer
121 Filter::
122 filter(const Buffer & x)
123 {
124  if(!is_realtime_) reset();
125 
126  Buffer y(x.getLength());
127 
128  uint32 x_samples = x.getLength();
129 
130  for(uint32 i = 0; i < x_samples; ++i)
131  {
132  y << filter(x[i]);
133  }
134 
135  return y;
136 }
137 
138 Buffer
139 Filter::
140 filter(const Buffer & x, const float64 & frequency)
141 {
142  if(!is_realtime_) reset();
143 
144  Buffer::const_iterator itor = x.begin();
145  Buffer::const_iterator end = x.end();
146 
147  Buffer y(x.getLength());
148 
149  while(itor != end)
150  {
151  y << filter(*itor, frequency);
152 
153  ++itor;
154  }
155 
156  return y;
157 }
158 
159 Buffer
160 Filter::
161 filter(const Buffer & x, const Buffer & frequencies)
162 {
163  if(!is_realtime_) reset();
164 
165  Buffer::const_circular_iterator freq = frequencies.cbegin();
166 
167  Buffer::const_iterator itor = x.begin();
168  Buffer::const_iterator end = x.end();
169 
170  Buffer y(x.getLength());
171 
172  while(itor != end)
173  {
174  y << filter(*itor, *freq);
175 
176  ++itor;
177  ++freq;
178  }
179 
180  return y;
181 }
182 
183 Buffer
184 Filter::
186 {
187  uint32 fft_chunk_size = FFTransform::roundUp2(
188  static_cast<int32>(n_fft));
189 
190  uint32 n_samples = fft_chunk_size / 2 + 1;
191 
192  float64 f_step = (1.0 / (static_cast<float64>(fft_chunk_size) / 2.0))
193  * (sample_rate_ / 2.0);
194 
195  Buffer f_axis;
196 
197  float64 f = 0.0;
198 
199  for(uint32 i = 0; i < n_samples; ++i)
200  {
201  f_axis << f;
202  f += f_step;
203  }
204 
205  return f_axis;
206 };
207 
208 Buffer
209 Filter::
211 {
213 
214 //~ fft.setWindow(HANNING);
215 
216  FFTChunkVector vec;
217 
218  vec = fft.fft(getImpulseResponse(), n_fft);
219 
220  return vec[0].getMagnitude();
221 }
222 
223 Buffer
224 Filter::
225 getImpulseResponse(const uint32 n_samples)
226 {
227  if(!is_realtime_) reset();
228 
229  Buffer response(n_samples);
230 
231  response << filter(1.0);
232 
233  for(uint32 i = 1; i < n_samples; ++i)
234  {
235  response << filter(0.0);
236  }
237 
238  if(!is_realtime_) reset();
239 
240  return response;
241 }
242 
243 Buffer
244 Filter::
246 {
247  uint32 n_samples = static_cast<uint32>(sample_rate_ * 2);
248 
249  FFTransform fft(n_samples);
250 
251  FFTChunkVector vec;
252 
253  vec = fft.fft(getImpulseResponse(), n_samples);
254 
255  Buffer phase = vec[0].getPhase();
256 
257  return phase.subbuffer(0, phase.getLength() / 2 + 1);
258 }
259 
260 void
261 Filter::
262 plot(boolean show_phase)
263 {
264  Buffer x = getFrequencyAxis();
266 
267  Plotter pylab;
268 
269  pylab.figure();
270 
271  uint32 n_rows = 1;
272  uint32 n_cols = 1;
273 
274  if(show_phase)
275  {
276  n_rows = 2;
277  }
278 
279  pylab.subplot(n_rows, n_cols, 1);
280 
281  // Frequency response
282  pylab.plot(x,fr, "blue");
283 
284  pylab.xlabel("Frequency (Hz)");
285  pylab.ylabel("Frequency Response (dB)");
286 
287  // Phase response
288  if(show_phase)
289  {
290  pylab.subplot(n_rows, n_cols, 2);
291 
292  Buffer pr = getPhaseResponse().getdB();
293 
294  pylab.plot(x,pr);
295 
296  pylab.xlabel("Frequency (Hz)");
297  pylab.ylabel("Phase Response (dB)");
298  }
299 
300  float64 ymax = fr.getMax();
301  float64 height = ymax - -60.0;
302 
303  pylab.ylim(-60.0, ymax + 0.05 * height);
304 }
Buffer subbuffer(uint32 start_index, uint32 n_samples=0) const
Slice the Buffer.
Definition: Buffer.cc:2073
unsigned int uint32
Definition: Nsound.h:153
void xlabel(const std::string &label, const std::string &kwargs="")
Add a label x axis.
Definition: Plotter.cc:1154
void plot(const Buffer &y, const std::string &fmt="", const std::string &kwargs="")
Plots the Buffer on the current figure.
Definition: Plotter.cc:765
float64 getSampleRate() const
Returns the sample rate of the stream.
Definition: AudioStream.h:217
#define M_PI
Definition: Nsound.h:121
void figure(const std::string &kwargs="") const
Creates a new figure window to plot in.
Definition: Plotter.cc:455
Buffer getPhaseResponse()
Definition: Filter.cc:245
double float64
Definition: Nsound.h:146
circular_iterator cbegin()
Retruns the itreator at the start of the Buffer.
Definition: Buffer.h:318
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
Buffer getImpulseResponse(const uint32 n_samples=8192)
Definition: Filter.cc:225
virtual void reset()=0
Axes subplot(const uint32 n_rows, const uint32 n_cols, const uint32 n, const std::string &kwargs="", Axes *sharex=NULL, Axes *sharey=NULL)
Creates a figure in a subplot, subplot(A, B, C, **kwargs)
Definition: Plotter.cc:1031
void ylim(const float64 &ymin, const float64 &ymax)
Definition: Plotter.cc:422
iterator end()
Retruns the itreator at the end of the Buffer.
Definition: Buffer.h:348
uint32 getNChannels(void) const
Returns the number of audio channels in the stream.
Definition: AudioStream.h:212
FloatVector::const_iterator const_iterator
Definition: Buffer.h:70
Buffer getFrequencyAxis(const uint32 n_fft=8192)
Definition: Filter.cc:185
iterator begin()
Retruns the itreator at the start of the Buffer.
Definition: Buffer.h:285
void plot(boolean show_phase=false)
Definition: Filter.cc:262
AudioStream filter(const AudioStream &x)
Definition: Filter.cc:53
#define M_THROW(message)
Definition: Macros.h:108
void ylabel(const std::string &label, const std::string &kwargs="")
Add a label y axis.
Definition: Plotter.cc:1180
bool is_realtime_
Definition: Filter.h:118
A Class that performes the Fast Fouier Transfrom on a Buffer.
Definition: FFTransform.h:57
Filter(const float64 &sample_rate)
Definition: Filter.cc:41
A Buffer for storing audio samples.
Definition: Buffer.h:60
Buffer getFrequencyResponse(const uint32 n_fft=8192)
Definition: Filter.cc:210
Buffer fft(const Buffer &time_domain) const
Transforms the time_domain signal and calculates the FFT.
Definition: FFTransform.cc:50
float64 getMax() const
Returns the maximum sample value in the Buffer.
Definition: Buffer.cc:951
std::vector< FFTChunk > FFTChunkVector
Definition: FFTChunk.h:119
Buffer getdB() const
Returns the Buffer in dB.
Definition: Buffer.h:487
float64 sample_rate_
Definition: Filter.h:113