Nsound  0.9.4
FilterIIR.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: FilterIIR.cc 874 2014-09-08 02:21:29Z 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/FilterIIR.h>
32 #include <Nsound/FFTransform.h>
33 #include <Nsound/Kernel.h>
34 #include <Nsound/Plotter.h>
35 #include <Nsound/RngTausworthe.h>
36 
37 //~#include <cmath>
38 #include <cstdio>
39 #include <cstring>
40 #include <iomanip>
41 #include <iostream>
42 
43 #include <stdlib.h>
44 #include <math.h> // isnan, isinf
45 
46 using namespace Nsound;
47 
48 using std::cerr;
49 using std::cout;
50 using std::endl;
51 
52 //~using std::isnan;
53 //~using std::isinf;
54 
55 #define PRINT_LINE "FilterIIR.cc:" << __LINE__ << ": "
56 
57 //-----------------------------------------------------------------------------
60  const float64 & sample_rate,
61  uint32 n_poles)
62  :
63  Filter(sample_rate),
64  n_poles_(n_poles),
65  kernel_(NULL),
66  x_history_(NULL),
67  x_ptr_(NULL),
68  x_end_ptr_(NULL),
69  y_history_(NULL),
70  y_ptr_(NULL),
71  y_end_ptr_(NULL),
72  rng_(NULL)
73 {
75 
76  x_history_ = new float64 [n_poles_ + 1];
79 
80  y_history_ = new float64 [n_poles_ + 1];
82  y_end_ptr_ = y_history_ + n_poles_ + 1;
83 
84  rng_ = new RngTausworthe();
85 
86  reset();
87 }
88 
89 //-----------------------------------------------------------------------------
91 FilterIIR(const FilterIIR & copy)
92  :
93  Filter(copy.sample_rate_),
94  n_poles_(copy.n_poles_),
95  kernel_(NULL),
96  x_history_(NULL),
97  x_ptr_(NULL),
98  x_end_ptr_(NULL),
99  y_history_(NULL),
100  y_ptr_(NULL),
101  y_end_ptr_(NULL),
102  rng_(NULL)
103 {
104  x_history_ = new float64 [n_poles_];
105  y_history_ = new float64 [n_poles_];
106 
107  rng_ = new RngTausworthe();
108 
109  *this = copy;
110 
111  reset();
112 }
113 
114 //-----------------------------------------------------------------------------
117 {
118  delete kernel_;
119  delete [] x_history_;
120  delete [] y_history_;
121 
122  delete rng_;
123 }
124 
125 Buffer
128  const Buffer & frequency_response,
129  const float64 & max_error,
130  const int32 max_iterations)
131 {
132  return designKernel(
133  frequency_response,
134  max_error,
135  max_iterations,
137 }
138 
139 Buffer
142  const Buffer & impulse_response,
143  const float64 & max_error,
144  const int32 max_iterations)
145 {
146  return designKernel(
147  impulse_response,
148  max_error,
149  max_iterations,
151 }
152 //~
153 //~ ///////////////////////////////////////////////////////////////////////////////
154 //~ float64
155 //~ FilterIIR::
156 //~ findZScore(
157 //~ const Kernel & k,
158 //~ const Buffer & response,
159 //~ const SignalType type)
160 //~ {
161 //~ Kernel * orig_k = kernel_;
162 //~
163 //~ kernel_ = const_cast<Kernel *>(&k);
164 //~
165 //~ reset();
166 //~
167 //~ Buffer r;
168 //~
169 //~ if(type == FREQUENCY_RESSPONSE)
170 //~ {
171 //~ r = getFrequencyResponse();
172 //~ }
173 //~ else
174 //~ {
175 //~ r = getImpulseResponse();
176 //~ }
177 //~
178 //~ kernel_ = orig_k;
179 //~
180 //~ //~ // Check for nans or infs or really big values
181 //~ //~ for(Buffer::const_iterator itor = r.begin();
182 //~ //~ itor != r.end();
183 //~ //~ ++itor)
184 //~ //~ {
185 //~ //~ if(isnan(*itor) || isinf(*itor) || -100.0 > *itor || *itor > 100.0)
186 //~ //~ {
187 //~ //~ return 1.0;
188 //~ //~ }
189 //~ //~ }
190 //~
191 //~ Buffer diff(response);
192 //~
193 //~ while(diff.getLength() < r.getLength())
194 //~ diff << 0.0;
195 //~ //~
196 //~ //~ diff -= r;
197 //~ //~
198 //~ //~ diff *= diff;
199 //~ //~
200 //~ //~ return diff.getSum();
201 //~
202 //~ diff.zNorm();
203 //~ r.zNorm();
204 //~
205 //~ return (diff * r).getSum();
206 //~
207 //~ }
208 
209 float64
212  const Kernel & k,
213  const Buffer & ref_response,
214  const SignalType type)
215 {
216  Kernel * orig_k = kernel_;
217 
218  kernel_ = const_cast<Kernel *>(&k);
219 
220  reset();
221 
222  Buffer r;
223 
224  if(type == FREQUENCY_RESSPONSE)
225  {
226  r = getFrequencyResponse(ref_response.getLength() * 2);
227  }
228  else
229  {
230  r = getImpulseResponse(ref_response.getLength() * 2);
231  }
232 
233  kernel_ = orig_k;
234 
235  Buffer delta = ref_response - r;
236  delta *= delta;
237 
238  float64 rms = delta.getSum() / static_cast<float64>(delta.getLength());
239 
240  rms = ::sqrt(rms);
241 
242  return rms;
243 }
244 
245 //-----------------------------------------------------------------------------
247 Buffer
250  const Buffer & ref_response,
251  const float64 & max_rms_error,
252  const int32 max_iterations,
253  const SignalType type)
254 {
255  // The reference response curve must be a power of two to guarentee correct
256  // comparision to the designed kernel response.
257 
258  uint32 p2 = 2;
259  uint32 ref_size = ref_response.getLength();
260 
261  while( p2 < ref_size )
262  {
263  p2 <<= 1;
264  }
265 
266  M_ASSERT_VALUE(ref_size, ==, p2);
267 
268  if(ref_size != p2) ::exit(1);
269 
270  // Create the initial 2 parents
271  Kernel * mom = new Kernel(n_poles_, n_poles_);
272 
273  float64 LARGE_RMS = 1.0;
274  float64 STALE_RMS = 0.001;
275 
276  float64 rms_error = LARGE_RMS;
277  int32 dead_count = 0;
278  while(rms_error > LARGE_RMS && dead_count < 1000)
279  {
280  mom->randomize(-0.1, 0.1);
281  rms_error = getRMS(*mom, ref_response, type);
282  dead_count++;
283  }
284 
285  M_ASSERT_VALUE(rms_error, <=, LARGE_RMS);
286 
287  if(rms_error > LARGE_RMS) ::exit(1);
288 
289  Kernel * dad = new Kernel(n_poles_, n_poles_);
290 
291  dad->randomize(-0.1, 0.1);
292 
293  int32 N_CHILDREN = 14;
294 
295  // Allocate N children
296  Kernel ** child = new Kernel * [N_CHILDREN];
297 
298  for(int32 i = 0; i < N_CHILDREN; ++i)
299  {
300  child[i] = new Kernel(n_poles_, n_poles_);
301  }
302 
303  Buffer rms_history;
304 
305  rms_history << rms_error;
306 
307  float64 dad_rms_error = getRMS(*dad, ref_response, type);
308 
309  cout << std::setprecision(10)
310  << "mom's RMS = " << rms_error << endl
311  << "dad's RMS = " << dad_rms_error << endl;
312 
313  float64 rms_error1 = LARGE_RMS;
314  float64 rms_error2 = LARGE_RMS;
315 
316  Kernel * low1 = NULL;
317  Kernel * low2 = NULL;
318 
319  float64 last_rms_error = rms_error;
320  int32 stale_count = 0;
321  int32 major_stale_count = 0;
322  int32 count = 0;
323 
324  while(count < max_iterations && rms_error > max_rms_error)
325  {
326  ++count;
327 
328  // First two children just swap mom & dads a & b coeffs;
329  *child[0] = *mom;
330  *child[1] = *dad;
331  child[0]->ga_swap_ab(*child[1]);
332 
333  #ifdef GA_DEBUG
334  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
335  << "\terror = " << error << endl << endl;
336  #endif
337 
338  // Next two children interleave coeffs
339  *child[2] = *mom;
340  *child[3] = *dad;
341 
342  child[2]->ga_interleave(*child[3]);
343 
344  #ifdef GA_DEBUG
345  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
346  << "\terror = " << error << endl << endl;
347  #endif
348 
349  // The next two children randomly mutate one coeff from mom & dad
350  *child[4] = *mom;
351  *child[5] = *dad;
352 
353  for(uint32 i = 4; i < 6; ++i)
354  {
355  float64 delta = rng_->get(-0.1f, 0.1f);
356 
357  uint32 index = rng_->get(0, n_poles_);
358 
359  child[i]->setB(child[i]->getB(index) + delta, index);
360 
361  delta = rng_->get(-0.1f, 0.1f);
362 
363  index = rng_->get(0, n_poles_);
364 
365  child[i]->setA(child[i]->getA(index) + delta, index);
366  }
367 
368  #ifdef GA_DEBUG
369  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
370  << "\terror = " << error << endl << endl;
371  #endif
372 
373  // The next two children randomly mutate sign
374  *child[6] = *mom;
375  *child[7] = *dad;
376 
377  for(uint32 i = 6; i < 8; ++i)
378  {
379  uint32 index = rng_->get(0, n_poles_);
380 
381  float64 a_or_b = rng_->get(-1.0f, 1.0f);
382 
383  if(a_or_b > 0.0)
384  {
385  child[i]->setB(child[i]->getB(index) * -1.0, index);
386  }
387  else
388  {
389  child[i]->setA(child[i]->getA(index) * -1.0, index);
390  }
391  }
392 
393  #ifdef GA_DEBUG
394  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
395  << "\terror = " << error << endl << endl;
396  #endif
397 
398  // These two children randomly multiply one coef.
399  *child[8] = *mom;
400  *child[9] = *dad;
401 
402  for(uint32 i = 8; i < 10; ++i)
403  {
404  uint32 index = rng_->get(0, n_poles_);
405 
406  float64 a_or_b = rng_->get(-1.0f, 1.0f);
407 
408  float64 delta = rng_->get(-0.1f, 0.1f);
409 
410  if(a_or_b > 0.0)
411  {
412  child[i]->setB(child[i]->getB(index) * delta, index);
413  }
414  else
415  {
416  child[i]->setA(child[i]->getA(index) * delta, index);
417  }
418  }
419 
420  #ifdef GA_DEBUG
421  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
422  << "\terror = " << error << endl << endl;
423  #endif
424 
425  // These two children randomly swap mom & dad coeffs
426  *child[10] = *mom;
427  *child[11] = *dad;
428 
429  uint32 start_index = rng_->get(0, n_poles_);
430  uint32 stop_index = rng_->get(0, n_poles_);
431 
432  if(stop_index >= n_poles_) stop_index = n_poles_ - 1;
433 
434  if(start_index > stop_index)
435  {
436  uint32 temp = start_index;
437  start_index = stop_index;
438  stop_index = temp;
439  }
440 
441  for(uint32 j = start_index; j < stop_index; ++j)
442  {
443  child[10]->setB(dad->getB(j), j);
444  child[11]->setB(mom->getB(j), j);
445  }
446 
447  #ifdef GA_DEBUG
448  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
449  << "\terror = " << error << endl << endl;
450  #endif
451 
452  start_index = rng_->get(0, n_poles_);
453  stop_index = rng_->get(0, n_poles_);
454 
455  if(stop_index >= n_poles_) stop_index = n_poles_ - 1;
456 
457  if(start_index > stop_index)
458  {
459  int32 temp = start_index;
460  start_index = stop_index;
461  stop_index = temp;
462  }
463 
464  for(uint32 j = start_index; j < stop_index; ++j)
465  {
466  child[10]->setA(dad->getA(j), j);
467  child[11]->setA(mom->getA(j), j);
468  }
469 
470  #ifdef GA_DEBUG
471  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
472  << "\terror = " << error << endl << endl;
473  #endif
474 
475  // These two children randomly add mom & dad coeffs
476  *child[12] = *mom;
477  *child[13] = *dad;
478 
479  for(uint32 i = 12; i < 14; ++i)
480  {
481  for(uint32 j = 0; j < n_poles_; ++j)
482  {
483  child[i]->setB(child[i]->getB(j) + rng_->get(-0.1f, 0.1f), j);
484  child[i]->setA(child[i]->getA(j) + rng_->get(-0.1f, 0.1f), j);
485  }
486  }
487 
488  // Score the kiddies.
489 
490  rms_error1 = getRMS(*mom, ref_response, type);
491  rms_error2 = getRMS(*dad, ref_response, type);
492 
493  low1 = mom;
494  low2 = dad;
495 
496  for(int32 i = 0; i < N_CHILDREN; ++i)
497  {
498  float64 rms = getRMS(*child[i], ref_response, type);
499 
500  if(rms > LARGE_RMS) continue;
501 
502  if(rms < rms_error1)
503  {
504  rms_error1 = rms;
505  low1 = child[i];
506  }
507  else if(rms < rms_error2)
508  {
509  rms_error2 = rms;
510  low2 = child[i];
511  }
512  }
513 
514  #ifdef GA_DEBUG
515  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
516  << "\terror = " << error << endl << endl;
517  #endif
518 
519  *mom = *low1;
520  *dad = *low2;
521 
522  rms_error = getRMS(*mom, ref_response, type);
523  dad_rms_error = getRMS(*dad, ref_response, type);
524 
525  rms_history << rms_error;
526 
527  #ifdef GA_DEBUG
528  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
529  << "\terror = " << error << endl;
530  #endif
531 
532  // Check if dad is unstable.
533  if(dad_rms_error > LARGE_RMS)
534  {
535  cout << PRINT_LINE << "dad's RMS > 10, ballistic!" << endl;
536  dad->randomize(-0.01f, 0.01f);
537  }
538 
539  // Check if our evolution is getting stale
540  if(std::fabs(rms_error - last_rms_error) < STALE_RMS)
541  {
542  ++stale_count;
543  }
544  else
545  {
546  stale_count = 0;
547  }
548 
549  last_rms_error = rms_error;
550 
551  if(count % 200 == 0)
552  {
553  cout << "Generation " << count << endl
554  << " 1st maximum RMS = " << rms_error << endl
555  << " 2nd maximum RMS = " << dad_rms_error << endl;
556 //~ << " major_stale_count = " << major_stale_count << endl;
557  }
558 
559  if(stale_count > 6)
560  {
561  for(uint32 i = 0; i < n_poles_; ++i)
562  {
563  dad->setB(dad->getB(i) + rng_->get(-0.10501f, 0.10501f), i);
564  dad->setA(dad->getA(i) + rng_->get(-0.10501f, 0.10501f), i);
565  }
566 
567  stale_count = 0;
568  ++major_stale_count;
569 
570  if(major_stale_count > 1)
571  {
572  for(uint32 i = 0; i < n_poles_; ++i)
573  {
574  dad->setB(dad->getB(i) * rng_->get(-0.501f, 0.501f), i);
575  dad->setA(dad->getA(i) * rng_->get(-0.501f, 0.501f), i);
576  }
577 
578  major_stale_count = 0;
579  }
580  }
581 
582  #ifdef GA_DEBUG
583  cout << __LINE__ << "\tmom.getSum() = " << mom->getSum()
584  << "\terror = " << error << endl;
585  #endif
586 
587  }
588 
589  cout << "count = " << count << " RMS = " << rms_error << endl;
590 
591  // copy mom into the filter.
592  *kernel_ = *mom;
593 
594  for(int32 i = 0; i < N_CHILDREN; ++i)
595  {
596  delete child[i];
597  }
598 
599  delete [] child;
600  delete mom;
601  delete dad;
602 
603  return rms_history;
604 }
605 
606 
607 float64
609 filter(const float64 & x)
610 {
611  // Write x to history
612  *x_ptr_ = x;
613 
614  // Increment history pointer
615  ++x_ptr_;
616 
617  // Bounds check
618  if(x_ptr_ >= x_end_ptr_)
619  {
620  x_ptr_ = x_history_;
621  }
622 
623  float64 y = 0.0;
624  float64 * x_hist = x_ptr_;
625  const float64 * bb = kernel_->getB();
626  const float64 * b_end = bb + n_poles_;
627  for(const float64 * b = bb; b < b_end; ++b)
628  {
629  // When we enter this loop, x_hist is pointing at x[n + 1]
630  --x_hist;
631 
632  // Bounds check
633  if(x_hist < x_history_)
634  {
635  x_hist = x_end_ptr_ - 1;
636  }
637 
638  y += *b * *x_hist;
639  }
640 
641  float64 * y_hist = y_ptr_;
642  const float64 * aa = kernel_->getA();
643  const float64 * a_end = aa + n_poles_;
644  for(const float64 * a = aa + 1; a < a_end; ++a)
645  {
646  // When we enter this loop, y_hist is pointing at y[n + 1]
647  --y_hist;
648 
649  // Bounds check
650  if(y_hist < y_history_)
651  {
652  y_hist = y_end_ptr_ - 1;
653  }
654 
655  y += *a * *y_hist;
656  }
657 
658  // insert output into history buffer
659  *y_ptr_ = y;
660 
661  // Increment history pointer
662  ++y_ptr_;
663 
664  // Bounds check
665  if(y_ptr_ >= y_end_ptr_)
666  {
667  y_ptr_ = y_history_;
668  }
669 
670  return y;
671 }
672 
673 float64
675 filter(const float64 & x, const float64 & frequency)
676 {
677  return FilterIIR::filter(x);
678 }
679 
680 //-----------------------------------------------------------------------------
681 FilterIIR &
683 operator=(const FilterIIR & rhs)
684 {
685  if(this == &rhs)
686  {
687  return *this;
688  }
689 
691 
692  if(n_poles_ != rhs.n_poles_)
693  {
694  delete [] x_history_;
695  delete [] y_history_;
696 
697  n_poles_ = rhs.n_poles_;
698 
699  x_history_ = new float64 [n_poles_];
700  y_history_ = new float64 [n_poles_];
701  }
702 
703  memcpy(x_history_, rhs.x_history_, sizeof(float64) * n_poles_);
704  memcpy(y_history_, rhs.y_history_, sizeof(float64) * n_poles_);
705 
706  *kernel_ = *rhs.kernel_;
707  *rng_ = *rhs.rng_;
708 
709  return *this;
710 }
711 
712 //-----------------------------------------------------------------------------
713 std::ostream &
714 Nsound::
715 operator<<(std::ostream & out,const FilterIIR & rhs)
716 {
717  out << "kernel_.b_length_ = " << rhs.kernel_->getBLength() << endl
718  << "kernel_.a_length_ = " << rhs.kernel_->getALength() << endl;
719  return out << *rhs.kernel_;
720 }
721 
722 void
725 {
726  memset(x_history_, 0, sizeof(float64) * (n_poles_ + 1));
727  memset(y_history_, 0, sizeof(float64) * (n_poles_ + 1));
728 
729  x_ptr_ = x_history_;
730  y_ptr_ = y_history_;
731 }
732 
733 void
736  const Kernel & k,
737  const Buffer & fr_reference,
738  uint32 n,
739  const float64 & error)
740 {
741  Kernel * orig_k = kernel_;
742 
743  kernel_ = const_cast<Kernel *>(&k);
744 
745  Buffer fr_ref = fr_reference;
747  Buffer faxis = getFrequencyAxis();
748 
749  while(fr_ref.getLength() < fr.getLength())
750  {
751  fr_ref << 0.0;
752  }
753 
754  float64 max = fr_ref.getMax();
755 
756  Plotter pylab;
757 
758  pylab.figure();
759  pylab.plot(faxis, fr_ref);
760  pylab.plot(faxis, fr);
761 
762  pylab.xlabel("Frequency Hz");
763  pylab.ylabel("Frequency Response");
764 
765  char buffer[256];
766 
767  sprintf(buffer, "Generation %06d", n);
768 
769  pylab.title(std::string(buffer));
770 
771  pylab.xlim(0.0, faxis[fr_reference.getLength() - 1]);
772  pylab.ylim(0.0, 1.1 * max);
773 
774  sprintf(buffer, "Error = %5.2f", error);
775 
776  pylab.text(
777  faxis[static_cast<uint32>(faxis.getLength() * 0.66)],
778  0.66,
779  std::string(buffer));
780 
781  sprintf(buffer, "generation_%06d.png", n);
782 
783 //~ pylab.savefig(std::string(buffer));
784 
785  kernel_ = orig_k;
786 
787  reset();
788 }
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 ga_interleave(Kernel &rhs)
Genitic Algorithm Helper Function: interleave B coefs with B, A with A.
Definition: Kernel.cc:296
#define M_ASSERT_VALUE(a, op, value)
Definition: Macros.h:76
std::ostream & operator<<(std::ostream &out, const Buffer &rhs_buffer)
Definition: Buffer.cc:1338
virtual ~FilterIIR()
Definition: FilterIIR.cc:116
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 * x_ptr_
Definition: FilterIIR.h:169
#define PRINT_LINE
Definition: FilterIIR.cc:55
float64 getB(uint32 i)
Returns kernel 'b[i]' coef.
Definition: Kernel.h:86
float64 getSum() const
Definition: Kernel.cc:154
void figure(const std::string &kwargs="") const
Creates a new figure window to plot in.
Definition: Plotter.cc:455
float64 * x_history_
Definition: FilterIIR.h:168
FilterIIR & operator=(const FilterIIR &rhs)
Definition: FilterIIR.cc:683
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
void setB(const float64 *b)
Copy getBLength() values from the array a into the Kernel. Use setLength() to set the number of value...
Definition: Kernel.cc:233
AudioStream filter(const AudioStream &x)
Definition: FilterIIR.h:89
void xlim(const float64 &xmin, const float64 &xmax)
Sets the limit for the x & y axis.
Definition: Plotter.cc:389
double float64
Definition: Nsound.h:146
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
Buffer designFrequencyResponse(const Buffer &frequency_response, const float64 &max_error=0.01, const int32 max_iterations=1000)
Designs a filter kernel using a genetic algorithm that trys to match the provided frequency response...
Definition: FilterIIR.cc:127
void ga_swap_ab(Kernel &rhs)
Genitic Algorithm Helper Function: swaps the A & B coefs.
Definition: Kernel.cc:275
float64 getRMS(const Kernel &kernel, const Buffer &response, const SignalType type)
Definition: FilterIIR.cc:211
float64 * y_history_
Definition: FilterIIR.h:172
Base class for IIR Filters, defines the interface.
Definition: Filter.h:49
void ylim(const float64 &ymin, const float64 &ymax)
Definition: Plotter.cc:422
Kernel * kernel_
Definition: FilterIIR.h:166
Buffer getFrequencyAxis(const uint32 n_fft=8192)
Definition: Filter.cc:185
uint32 getALength() const
Definition: Kernel.h:101
void randomize(const float64 &min=-1.0, const float64 &max=1.0)
Sets all coefs to random float64 values between min & max.
Definition: Kernel.cc:194
void text(const float64 &x, const float64 &y, const std::string &text, const std::string &kwargs="")
Adds text at the x, y data point.
Definition: Plotter.cc:1092
RngTausworthe * rng_
Definition: FilterIIR.h:176
float64 * x_end_ptr_
Definition: FilterIIR.h:170
Buffer getImpulseResponse(const uint32 n_samples=8192)
Definition: FilterIIR.h:114
uint32 getBLength() const
Definition: Kernel.h:104
void ylabel(const std::string &label, const std::string &kwargs="")
Add a label y axis.
Definition: Plotter.cc:1180
void savePlot(const Kernel &k, const Buffer &response, uint32 n, const float64 &error)
Definition: FilterIIR.cc:735
float64 getSum() const
Returns the sum of all samples.
Definition: Buffer.cc:1118
A Buffer for storing audio samples.
Definition: Buffer.h:60
float64 * y_end_ptr_
Definition: FilterIIR.h:174
Buffer designImpulseResponse(const Buffer &impulse_response, const float64 &max_error=0.01, const int32 max_iterations=1000)
Designs a filter kernel using a genetic algorithm that trys to match the provided impulse response...
Definition: FilterIIR.cc:141
signed int int32
Definition: Nsound.h:142
FilterIIR(const float64 &sample_rate, uint32 n_poles)
Definition: FilterIIR.cc:59
Buffer getFrequencyResponse(const uint32 n_fft=8192)
Definition: Filter.cc:210
float64 getMax() const
Returns the maximum sample value in the Buffer.
Definition: Buffer.cc:951
uint32 get()
Get a random number.
float64 getA(uint32 i)
Returns kernel 'a[i]' coef.
Definition: Kernel.h:70
Buffer designKernel(const Buffer &response, const float64 &max_rms_error, const int32 max_iterations, const SignalType type)
Designs a filter kernel that trys to match the provide frequency response.
Definition: FilterIIR.cc:249
float64 * y_ptr_
Definition: FilterIIR.h:173
float64 sample_rate_
Definition: Filter.h:113
void setA(const float64 *a)
Copy getALength() values from the array a into the Kernel. Use setLength() to set the number of value...
Definition: Kernel.cc:211