Nsound  0.9.4
Vocoder.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Vocoder.cc 878 2014-11-23 04:51:23Z weegreenblobbie $
4 //
5 // Copyright (c) 2008 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>
34 #include <Nsound/Plotter.h>
35 #include <Nsound/Vocoder.h>
36 
37 using namespace Nsound;
38 
39 using std::cerr;
40 using std::cout;
41 using std::endl;
42 
43 #define CERR_HEADER __FILE__ << ":" << __LINE__ << ": "
44 
45 // Convert Hz to mel scale.
46 //
47 // mels = 1127 * ln(1 + hz/700)
48 //
49 // http://en.wikipedia.org/wiki/Mel_scale
50 //
51 
53 {
54  M_ASSERT_VALUE(f, >, 0.0);
55 
56  return 2595.0 * log10(1.0 + f / 700.0);
57 }
58 
60 {
61  M_ASSERT_VALUE(m, >, 0.0);
62  m = pow(10.0, m / 2595.0);
63  return (m - 1.0) * 700.0;
64 }
65 
66 
67 //-----------------------------------------------------------------------------
70  const float64 & sample_rate,
71  const float64 & window_length,
72  const uint32 & n_bands,
73  const float64 & freq_max,
74  const bool use_mel_scale,
75  const bool plot_filter_bank)
76  :
77  sample_rate_(sample_rate),
78  window_size_(static_cast<uint32>(window_length * sample_rate_)),
79  n_bands_(n_bands),
80  freq_max_(freq_max),
81  filters_input_(),
82  filters_output_(),
83  moving_average_()
84 {
86 
87  uint32 min_window_size = static_cast<uint32>(sample_rate_ * 0.005);
88 
89  M_ASSERT_VALUE(window_size_, >=, min_window_size);
90 
91  uint32 min_n_bands = 4;
92 
93  M_ASSERT_VALUE(n_bands_, >=, min_n_bands);
94 
95  float64 min_freq_max = 0.05 * sample_rate_;
96 
97  M_ASSERT_VALUE(freq_max_, >=, min_freq_max);
98 
99  float64 hi = freq_max_;
100 
101  // convert to mel scale
102 
103  if(use_mel_scale)
104  {
105  hi = f_to_mel(hi);
106  }
107 
108  // linear space from lo to hi.
109 
110  float64 band_width = hi / static_cast<float64>(n_bands_);
111 
112  Buffer freq_centers(n_bands_);
113 
114  for(uint32 i = 0; i <= n_bands_; ++i)
115  {
116  freq_centers << (i + 1) * band_width;
117  }
118 
119  // Shift to the center of each window.
120  freq_centers -= band_width / 2.0;
121 
122  // convert back to Hz scale.
123  if(use_mel_scale)
124  {
125  for(uint32 i = 0; i < freq_centers.getLength(); ++i)
126  {
127  freq_centers[i] = mel_to_f(freq_centers[i]);
128  }
129  }
130 
131  uint32 start = 0;
132  uint32 order = 6;
133  float64 ripple = 0.01;
134 
135  for(uint32 i = start; i < n_bands_; ++i)
136  {
137  float64 freq = freq_centers[i];
138 
139  // Cut offs are halfway between the filters.
140 
141  float64 f_lo = 0.0;
142 
143  if(i > 0)
144  {
145  f_lo = (freq + freq_centers[i - 1]) / 2.0;
146  }
147 
148  float64 f_hi = freq_max_;
149 
150  if(i + 1 < n_bands_)
151  {
152  f_hi = (freq + freq_centers[i + 1]) / 2.0;
153  }
154 
156  sample_rate_,
157  order,
158  f_lo,
159  f_hi,
160  ripple);
161 
162  M_CHECK_PTR(bp);
163 
164  filters_input_.push_back(bp);
165 
166  bp = new FilterBandPassIIR(
167  sample_rate_,
168  order,
169  f_lo,
170  f_hi,
171  ripple);
172 
173  M_CHECK_PTR(bp);
174 
175  filters_output_.push_back(bp);
176 
178 
179  M_CHECK_PTR(ma);
180 
181  moving_average_.push_back(ma);
182  }
183 
184  if(plot_filter_bank)
185  {
186  Plotter pylab;
187 
188  pylab.figure();
189  pylab.hold(true);
190 
191  for(size_t i = 0; i < filters_input_.size(); ++i)
192  {
193  Buffer x = filters_input_[i]->getFrequencyAxis();
194  Buffer y = filters_input_[i]->getFrequencyResponse().getdB();
195 
196  pylab.plot(x, y);
197  }
198 
199  pylab.xlim(0.0, freq_max_);
200  pylab.ylim(-40.0, 10.0);
201  pylab.xlabel("Frequency (Hz)");
202  pylab.ylabel("Filter Frequency Response (dB)");
203  pylab.grid(true);
204 
205 //~ pylab.show();
206  }
207 
208 }
209 
210 //-----------------------------------------------------------------------------
211 Vocoder::
213 {
214  FilterVector::iterator fi = filters_input_.begin();
215  FilterVector::iterator fo = filters_output_.begin();
216  FilterVector::iterator ma = moving_average_.begin();
217 
218  FilterVector::iterator end = filters_input_.end();
219 
220  while(fi != end)
221  {
222  delete *fi;
223  delete *fo;
224  delete *ma;
225 
226  ++fi;
227  ++fo;
228  ++ma;
229  }
230 }
231 
232 Buffer
233 Vocoder::
234 filter(const Buffer & voice, const Buffer & x)
235 {
236  Buffer y;
237 
239 
240  uint32 n_samples = x.getLength();
241 
242  for(uint32 n = 0; n < n_samples; ++n, ++v)
243  {
244  y << Vocoder::filter(*v, x[n]);
245  }
246 
247  return y;
248 }
249 
250 float64
251 Vocoder::
252 filter(const float64 & voice, const float64 & x)
253 {
254  FilterVector::iterator fi = filters_input_.begin();
255  FilterVector::iterator fo = filters_output_.begin();
256  FilterVector::iterator ma = moving_average_.begin();
257 
258  FilterVector::iterator end = filters_input_.end();
259 
260  float64 y = 0.0;
261 
262  while(fi != end)
263  {
264  // Filter the voice to use as an envelope..
265  float64 envelope = (*fi)->filter(voice);
266 
267  // Use the abs of the envelope.
268  envelope = std::fabs(envelope);
269 
270  // Smooth the filtered envelope.
271  envelope = (*ma)->filter(envelope);
272 
273  // Shape the filtered input signal.
274  y += envelope * (*fo)->filter(x);
275 
276  ++fi;
277  ++fo;
278  ++ma;
279  }
280 
281  return y;
282 }
283 
284 void
285 Vocoder::
287 {
288  FilterVector::iterator fi = filters_input_.begin();
289  FilterVector::iterator fo = filters_output_.begin();
290  FilterVector::iterator ma = moving_average_.begin();
291 
292  FilterVector::iterator end = filters_input_.end();
293 
294  while(fi != end)
295  {
296  (*fi)->reset();
297  (*fo)->reset();
298  (*ma)->reset();
299 
300  ++fi;
301  ++fo;
302  ++ma;
303  }
304 }
305 
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 grid(boolean flag)
Sets the grid state.
Definition: Plotter.cc:496
#define M_ASSERT_VALUE(a, op, value)
Definition: Macros.h:76
void plot(const Buffer &y, const std::string &fmt="", const std::string &kwargs="")
Plots the Buffer on the current figure.
Definition: Plotter.cc:765
void figure(const std::string &kwargs="") const
Creates a new figure window to plot in.
Definition: Plotter.cc:455
#define M_CHECK_PTR(ptr)
Definition: Macros.h:64
static float64 mel_to_f(float64 m)
Definition: Vocoder.cc:59
void xlim(const float64 &xmin, const float64 &xmax)
Sets the limit for the x & y axis.
Definition: Plotter.cc:389
uint32 n_bands_
Definition: Vocoder.h:81
double float64
Definition: Nsound.h:146
circular_iterator cbegin()
Retruns the itreator at the start of the Buffer.
Definition: Buffer.h:318
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
uint32 window_size_
Definition: Vocoder.h:80
void ylim(const float64 &ymin, const float64 &ymax)
Definition: Plotter.cc:422
virtual ~Vocoder()
Definition: Vocoder.cc:212
void reset()
Definition: Vocoder.cc:286
FilterVector filters_input_
Definition: Vocoder.h:86
void hold(boolean flag)
Sets the hold state.
Definition: Plotter.cc:554
FilterVector filters_output_
Definition: Vocoder.h:87
static float64 f_to_mel(float64 f)
Definition: Vocoder.cc:52
float64 freq_max_
Definition: Vocoder.h:82
void ylabel(const std::string &label, const std::string &kwargs="")
Add a label y axis.
Definition: Plotter.cc:1180
float64 sample_rate_
Definition: Vocoder.h:79
A Buffer for storing audio samples.
Definition: Buffer.h:60
FilterVector moving_average_
Definition: Vocoder.h:88
Vocoder(const float64 &sample_rate, const float64 &window_length, const uint32 &n_bands, const float64 &freq_max=4000.0, const bool use_mel_scale=true, const bool plot_filter_bank=false)
Default Constructor.
Definition: Vocoder.cc:69
Buffer filter(const Buffer &voice, const Buffer &carrier)
Definition: Vocoder.cc:234