Jamoma API  0.6.0.a19
HiMidLow.cpp
1 // HiMidLow.cpp
2 /***************************************************/
3 /*! \class HiMidLow
4  \brief HiMidLow filter class
5 
6  A High Mid Low shelf filter. Shelf centre frequencies are mutable.
7 
8  Based on:
9  Biquad.h by Gary Scavone and Perry Cook, and
10  hml_shelf~.c by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2006
11 
12  by Tristan Matthews and Nils Peters, 2007-2008.
13  */
14 /***************************************************/
15 
16 #include "Filter.h"
17 #include "HiMidLow.h"
18 #include "Properties.h"
19 
20 extern bool globWarningFlag;
21 extern bool globReportFlag;
22 
24  lf_(450.0),
25  hf_(3500.0),
26  mf_(sqrt(hf_) * sqrt(lf_)), // mf_ depends on hf_ and lf_
27  lg_(MAX_), // was initialized to 0.0 (dB) in original
28  mg_(MAX_),
29  hg_(MAX_)
30 {
31  init();
32 }
33 
35 {
36  if (lf < hf_)
37  {
38  if (lf >= 10.0 && lf <= 10000.0)
39  {
40  lf_ = lf;
41  mf_ = sqrt(hf_) * sqrt(lf_); // mf_ depends on hf_ and lf_
42  init();
43  }
44  else if (globWarningFlag)
45  error("HiMidLow: Low shelf frequency must be between 10 and 10000 hz.");
46  }
47  else if (globWarningFlag)
48  error("HiMidLow: Low shelf frequency must be less than high shelf frequency %f.", hf_);
49 }
50 
52 {
53  if (hf > lf_)
54  {
55  if (hf >= 10.0 && hf <= 10000.0)
56  {
57  hf_ = hf;
58  mf_ = sqrt(hf_) * sqrt(lf_); // mf_ depends on hf_ and lf_
59  init();
60  }
61  else if (globWarningFlag)
62  error("HiMidLow: High shelf frequency must be between 10 and 10000 hz.");
63  }
64  else if (globWarningFlag)
65  error("HiMidLow: High shelf frequency must be greater than low shelf frequency %f.", lf_);
66 }
67 
68 void HiMidLow::lowGain(double newLg)
69 {
70  newLg = percentToGain(newLg); // convert from percentage to gain
71  bool capped = false;
72  if (newLg > MAX_)
73  {
74  newLg = MAX_;
75  capped = true;
76  }
77  else if (newLg < MIN_)
78  {
79  newLg = MIN_;
80  capped = true;
81  }
82 
83  if (lg_ != newLg)
84  {
85  lg_ = newLg;
86  init();
87  }
88 
89  if (capped && globWarningFlag)
90  post("Filter: Low gain capped at %f", lg_);
91 }
92 
93 void HiMidLow::midGain(double newMg)
94 {
95  newMg = percentToGain(newMg); // convert from percentage to gain
96  bool capped = false;
97  if (newMg > MAX_)
98  {
99  newMg = MAX_;
100  capped = true;
101  }
102  else if (newMg < MIN_)
103  {
104  newMg = MIN_;
105  capped = true;
106  }
107 
108  if (mg_ != newMg)
109  {
110  mg_ = newMg;
111  init();
112  }
113 
114  if (capped && globWarningFlag)
115  post("HiMidLow: Mid gain capped at %f", mg_);
116 }
117 
118 void HiMidLow::highGain(double newHg)
119 {
120  newHg = percentToGain(newHg); // convert from percentage to gain
121  bool capped = false;
122  if (newHg > MAX_)
123  {
124  newHg = MAX_;
125  capped = true;
126  }
127  else if (newHg < MIN_)
128  {
129  newHg = MIN_;
130  capped = true;
131  }
132 
133  if (hg_ != newHg)
134  {
135  hg_ = newHg;
136  init();
137  }
138 
139  if (capped && globWarningFlag)
140  post("HiMidLow: High gain capped at %f", hg_);
141 }
142 
143 void HiMidLow::init()
144 {
145  double f = mf_ * sr_; //ok
146  double rf = sqrt(hf_) / sqrt(lf_); //ok
147  double l = cos(f) / sin(f);//ok
148  double invHg = 1.0 / hg_;
149  double invLg = 1.0 / lg_;
150  double invMg = 1.0 / mg_;
151  double k1 = rf * l;
152  double k2 = l / rf;
153  double k3 = l * l;
154  double k4 = k3 * hg_;
155  double k5 = k3 * invHg;
156  double k6 = invLg + k5;
157  double k7 = invMg * k1 + k2 * invLg * invHg * mg_;
158  double k8 = lg_ + k4;
159  double k9 = (mg_ * k1) + (k2 * lg_ * hg_ * invMg);
160  double k10 = 1.0 / (k6 + k7);
161 
162  double tempb2 = k10 * (k7 - k6);
163  double tempb1 = k10 * 2.0 * (k5 - invLg);
164  double tempa2 = k10 * (k8 - k9);
165  double tempa1 = k10 * 2.0 * (lg_ - k4);
166  double tempa0 = k10 * (k8 + k9);
167 
168  //this->clear();
169 
170  /* stability check */
171 
172  double discriminant = tempb1 * tempb1 + 4.0 * tempb2;
173  if (tempb1 <= -1.9999996)
174  tempb1 = -1.9999996;
175  else if (tempb1 >= 1.9999996)
176  tempb1 = 1.9999996;
177 
178  if (tempb2 <= -0.9999998)
179  tempb2 = -0.9999998;
180  else if (tempb2 >= 0.9999998)
181  tempb2 = 0.9999998;
182 
183  if (discriminant >= 0.0)
184  {
185  if (0.9999998 - tempb1 - tempb2 < 0.0)
186  tempb2 = 0.9999998 - tempb1;
187  if (0.9999998 + tempb1 - tempb2 < 0.0)
188  tempb2 = 0.9999998 + tempb1;
189  }
190 
191  a0_ = tempa0;
192  a1_ = tempa1;
193  a2_ = tempa2;
194  b1_ = tempb1;
195  b2_ = tempb2;
196 }
197 
198 void HiMidLow::print() const
199 {
200  post("b1: %f, b2: %f, a0: %f, a1: %f, a2: %f, lg: %f, mg: %f, hg: %f", b1_, b2_, a0_, a1_, a2_, lg_, mg_, hg_);
201 }
202 
203 // vim:sw=4:et:cindent:
virtual void print() const
Prints information about this filter.
Definition: HiMidLow.cpp:198
void midGain(double newMg)
Sets mid gain.
Definition: HiMidLow.cpp:93
static const double MAX_
Max gain value.
Definition: Filter.h:44
double a2_
Filter coefficient.
Definition: Filter.h:40
double sr_
Pi divided by the sample rate.
Definition: Filter.h:30
HiMidLow()
Class constructor.
Definition: HiMidLow.cpp:23
Filter class.
Definition: Filter.h:22
void highGain(double newHg)
Set high gain.
Definition: HiMidLow.cpp:118
void highShelfFrequency(double hf)
Set high shelf's center frequency.
Definition: HiMidLow.cpp:51
double percentToGain(double gainPercentage)
Convert percentage to linear gain.
Definition: Filter.cpp:40
static const double MIN_
Min gain value.
Definition: Filter.h:46
void lowGain(double newLg)
Sets low gain.
Definition: HiMidLow.cpp:68
void lowShelfFrequency(double lf)
Set low shelf's center frequency.
Definition: HiMidLow.cpp:34
double b1_
Filter coefficient.
Definition: Filter.h:32
double b2_
Filter coefficient.
Definition: Filter.h:34
double a1_
Filter coefficient.
Definition: Filter.h:38
double a0_
Filter coefficient.
Definition: Filter.h:36