Nsound  0.9.4
FilterBandRejectFIR.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------////
2 //
3 // $Id: FilterBandRejectFIR.cc 874 2014-09-08 02:21:29Z weegreenblobbie $
4 //
5 // Copyright (c) 2006 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>
32 #include <Nsound/Plotter.h>
33 
34 #include <cmath>
35 #include <cstdio>
36 #include <cstring>
37 #include <iostream>
38 
39 using namespace Nsound;
40 
41 using std::cerr;
42 using std::endl;
43 
44 #define CERR_HEADER __FILE__ << ":" << __LINE__ << ": "
45 
48  const float64 & sample_rate,
49  uint32 kernel_size,
50  const float64 & frequency_Hz_low,
51  const float64 & frequency_Hz_high)
52  :
53  FilterHighPassFIR(sample_rate, kernel_size, frequency_Hz_high),
54  frequency_2_Hz_(frequency_Hz_high),
55  kernel_cache_()
56 {
57  frequency_1_Hz_ = frequency_Hz_low;
58 
59  reset();
60 }
61 
64 {
65  FilterBandRejectFIR::KernelCache::iterator itor =
67 
68  FilterBandRejectFIR::KernelCache::iterator end =
70 
71  while(itor != end)
72  {
73  delete [] itor->b_;
74  ++itor;
75  }
76 }
77 
78 float64
81 {
82  return frequency_1_Hz_;
83 }
84 
85 float64
88 {
89  return frequency_2_Hz_;
90 }
91 
92 
95 filter(const AudioStream & x)
96 {
97  return Filter::filter(x);
98 }
99 
103  const AudioStream & x,
104  const float64 & f_low,
105  const float64 & f_high)
106 {
107  uint32 n_channels = x.getNChannels();
108 
109  AudioStream y(x.getSampleRate(), n_channels);
110 
111  for(uint32 channel = 0; channel < n_channels; ++channel)
112  {
113  y[channel] = FilterBandRejectFIR::filter(x[channel], f_low, f_high);
114  }
115 
116  return y;
117 }
118 
122  const AudioStream & x,
123  const Buffer & frequencies_Hz_low,
124  const Buffer & frequencies_Hz_high)
125 {
126  if(!is_realtime_) reset();
127 
128  uint32 n_channels = x.getNChannels();
129 
130  AudioStream y(x.getSampleRate(), n_channels);
131 
132  for(uint32 channel = 0; channel < n_channels; ++channel)
133  {
134  y[channel] = FilterBandRejectFIR::filter(
135  x[channel],
136  frequencies_Hz_low,
137  frequencies_Hz_high);
138  }
139 
140  return y;
141 }
142 
143 Buffer
145 filter(const Buffer & x)
146 {
147  return FilterLowPassFIR::filter(x);
148 }
149 
150 Buffer
153  const Buffer & x,
154  const float64 & f_low,
155  const float64 & f_high)
156 {
157  if(!is_realtime_) reset();
158 
159  // Instead of calling filter(x,f_low, f_high), we implement this function
160  // here to avoid calling makeKernel(f) for each sample.
161 
162  FilterBandRejectFIR::makeKernel(f_low, f_high);
163 
164  Buffer::const_iterator itor = x.begin();
165  Buffer::const_iterator end = x.end();
166 
167  Buffer y(x.getLength());
168  while(itor != end)
169  {
170  y << FilterLowPassFIR::filter(*itor);
171  ++itor;
172  }
173 
174  return y;
175 }
176 
177 Buffer
180  const Buffer & x,
181  const Buffer & frequencies_Hz_low,
182  const Buffer & frequencies_Hz_high)
183 {
184  if(!is_realtime_) reset();
185 
186  uint32 n_high_freqs = frequencies_Hz_high.getLength();
187  uint32 n_low_freqs = frequencies_Hz_low.getLength();
188 
189  Buffer y;
190 
191  uint32 x_samples = x.getLength();
192 
193  for(uint32 i = 0; i < x_samples; ++i)
194  {
196  x[i],
197  frequencies_Hz_low [i % n_low_freqs],
198  frequencies_Hz_high[i % n_high_freqs]);
199  }
200 
201  return y;
202 }
203 
204 float64
206 filter(const float64 & x)
207 {
208  return FilterLowPassFIR::filter(x);
209 }
210 
211 float64
213 filter(const float64 & x, const float64 & frequency_Hz)
214 {
215  return FilterLowPassFIR::filter(x);
216 }
217 
218 float64
221  const float64 & x,
222  const float64 & frequencies_Hz_low,
223  const float64 & frequencies_Hz_high)
224 {
225  makeKernel(frequencies_Hz_low, frequencies_Hz_high);
226  return FilterLowPassFIR::filter(x);
227 }
228 
229 void
231 makeKernel(const float64 & low_frequency, const float64 & high_frequency)
232 {
233  // Here we create a key into the kernel cache. I'm only storing kernels
234  // with freqs chopped off to the 10th Hz. So filtering with a kernel
235  // designed at 440.1567 Hz will get stored as 440.1. Any other frequency
236  // that starts at 440.1 will not get a kernel calculated and just use the
237  // one in the cache. So the max diff between what's passed in and what's
238  // stored in the cache is 0.09999 Hz.
239 
240  FilterBandRejectFIR::Kernel new_kernel(
241  static_cast<uint32>(low_frequency),
242  static_cast<uint32>(high_frequency));
243 
244  // See if the kernel is in the cache.
245 
246  FilterBandRejectFIR::KernelCache::const_iterator itor =
247  FilterBandRejectFIR::kernel_cache_.find(new_kernel);
248 
249  if(itor != FilterBandRejectFIR::kernel_cache_.end())
250  {
251  // The kernel was found in the cache.
252  b_ = itor->b_;
253  return;
254  }
255 
256  // The filter wasn't in the cache, need to make it.
257  new_kernel.b_ = new float64[kernel_size_];
258 
259  if(low_frequency < 0.10 && high_frequency >= 0.10)
260  {
261  // Create simple high pass filter.
262  FilterHighPassFIR::makeKernel(high_frequency);
263 
264 //~ // b_ is now pointing at a high pass kernel held in the high pass cache
265 //~ memcpy(new_kernel.b_, b_, kernel_size_ * sizeof(float64));
266 
267  return;
268 
269  }
270  else if(low_frequency >= 0.10 && high_frequency < 0.10)
271  {
272  // Create simple low pass filter.
273  FilterLowPassFIR::makeKernel(low_frequency);
274 
275 //~ // b_ is now pointing at a high pass kernel held in the low pass cache
276 //~ memcpy(new_kernel.b_, b_, kernel_size_ * sizeof(float64));
277 
278  return;
279 
280  }
281  else if(low_frequency <= 0.10 && high_frequency < 0.10)
282  {
283  // Create simple All pass filter
284  new_kernel.b_[0] = 1.0;
285 
286  for(uint32 i = 1; i < kernel_size_; ++i)
287  {
288  new_kernel.b_[i] = 0.00000;
289  }
290  }
291  else // non-zero frequencies
292  {
293  FilterLowPassFIR::makeKernel(low_frequency);
294 
295  // Now b_ is pointing to a low pass kernel held in the low pass cache.
296  memcpy(new_kernel.b_, b_, kernel_size_ * sizeof(float64));
297 
298  FilterHighPassFIR::makeKernel(high_frequency);
299 
300  // b_ is now pointing at a high pass kernel held in the high pass cache
301 
302  // To create the band reject, simply add the low pass and high pass
303  // kernels.
304 
305  for(uint32 i = 0; i < kernel_size_; ++i)
306  {
307  // low kernel += high kernel
308  new_kernel.b_[i] += b_[i];
309  }
310  }
311 
312  // point at the new kernel
313  b_ = new_kernel.b_;
314 
315  // insert into cache
316  FilterBandRejectFIR::kernel_cache_.insert(new_kernel);
317 }
318 
319 void
321 plot(boolean show_fc,boolean show_phase)
322 {
323  char title[128];
324  sprintf(title,
325  "Band Reject FIR Frequency Response\n"
326  "order = %d, fl = %0.1f Hz, fl = %0.1f Hz, sr = %0.1f Hz",
327  kernel_size_ - 1,
330  sample_rate_);
331 
332  Filter::plot(show_phase);
333 
334  Plotter pylab;
335 
336  uint32 n_rows = 1;
337 
338  if(show_phase)
339  {
340  n_rows = 2;
341  }
342 
343  if(show_fc)
344  {
345  pylab.subplot(n_rows, 1, 1);
346 
347  pylab.axvline(frequency_1_Hz_,"color='red'");
348  pylab.axvline(frequency_2_Hz_,"color='red'");
349 
350  pylab.title(title);
351  }
352 }
353 
354 void
357 {
360 }
361 
362 //-----------------------------------------------------------------------------
364 Kernel::
365 Kernel(const uint32 & f1, const uint32 & f2)
366  :
367  b_(NULL),
368  frequency_1_(f1),
369  frequency_2_(f2)
370 {
371 }
372 
373 bool
375 Kernel::
376 operator<(const Kernel & rhs) const
377 {
378  return frequency_1_ < rhs.frequency_1_ ||
379  (frequency_1_ == rhs.frequency_1_ &&
380  frequency_2_ < rhs.frequency_2_);
381 }
382 
383 
unsigned int uint32
Definition: Nsound.h:153
float64 getSampleRate() const
Returns the sample rate of the stream.
Definition: AudioStream.h:217
void axvline(const float64 &x_pos=0.0, const std::string &kwargs="")
Draws a vertical line at x and spans ymin to ymax (ralitive).
Definition: Plotter.cc:358
AudioStream filter(const AudioStream &x)
void title(const std::string &title, const std::string &kwargs="")
Add a title to the plot at the top and centered.
Definition: Plotter.cc:1127
A class to store calculated kernels.
Kernel(const uint32 &f1, const uint32 &f2)
double float64
Definition: Nsound.h:146
void makeKernel(const float64 &frequency_Hz_low, const float64 &frequency_Hz_high)
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
void makeKernel(const float64 &frequency1)
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
iterator end()
Retruns the itreator at the end of the Buffer.
Definition: Buffer.h:348
void makeKernel(const float64 &frequency)
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
void plot(boolean show_fc=true, boolean show_phase=false)
uint32 kernel_size_
Definition: Filter.h:116
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
bool is_realtime_
Definition: Filter.h:118
A Buffer for storing audio samples.
Definition: Buffer.h:60
bool operator<(const Kernel &rhs) const
FilterBandRejectFIR(const float64 &sample_rate, uint32 kernel_size, const float64 &frequency_Hz_low, const float64 &frequency_Hz_high)
AudioStream filter(const AudioStream &x)
float64 sample_rate_
Definition: Filter.h:113