Nsound  0.9.4
Granulator.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Granulator.cc 874 2014-09-08 02:21:29Z weegreenblobbie $
4 //
5 // Nsound is a C++ library and Python module for audio synthesis featuring
6 // dynamic digital filters. Nsound lets you easily shape waveforms and write
7 // to disk or plot them. Nsound aims to be as powerful as Csound but easy to
8 // use.
9 //
10 // Copyright (c) 2005-2006 Nick Hilton
11 //
12 // weegreenblobbie_yahoo_com (replace '_' with '@' and '.')
13 //
14 //-----------------------------------------------------------------------------
15 
16 //-----------------------------------------------------------------------------
17 //
18 // This program is free software; you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation; either version 2 of the License, or
21 // (at your option) any later version.
22 //
23 // This program is distributed in the hope that it will be useful,
24 // but WITHOUT ANY WARRANTY; without even the implied warranty of
25 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 // GNU Library General Public License for more details.
27 //
28 // You should have received a copy of the GNU General Public License
29 // along with this program; if not, write to the Free Software
30 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 //
32 //-----------------------------------------------------------------------------
33 
34 #include <Nsound/Nsound.h>
35 #include <Nsound/Buffer.h>
36 #include <Nsound/Generator.h>
37 #include <Nsound/Granulator.h>
38 #include <Nsound/Sine.h>
39 
40 #include <iostream>
41 
42 using namespace Nsound;
43 
44 using std::cerr;
45 using std::endl;
46 
50  const float64 & sample_rate,
51  EnvelopeType_e env_type,
52  const float64 & envelope_noise,
53  const Buffer * custom_envelope)
54  :
55  sample_rate_(sample_rate),
56  envelope_generator_(NULL)
57 // sine_(new Sine(sample_rate_)),
58 // current_time_(0.0),
59 // next_grain_time_(0.0),
60 // last_grain_time_(0.0),
61 // time_step_(1.0 / sample_rate_)
62 {
64 
65  switch(env_type)
66  {
67  case Granulator::CUSTOM:
68  {
69  if(custom_envelope == NULL
70  || custom_envelope->getLength() != sample_rate_)
71  {
72  M_THROW("custom_envelope->getLength() must equal "
73  << sample_rate_
74  << ", length is "
75  << custom_envelope->getLength());
76 
78  new Generator(
80  gen.drawGaussian(1.0, 0.5, 0.33333)
81  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
82  }
83  else
84  {
86  new Generator(
88  (*custom_envelope)
89  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
90  }
91  break;
92  }
93 
95  {
98  gen.drawGaussian(1.0, 0.5, 0.33333)
99  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
100  break;
101  }
102 
104  {
106  sample_rate_,
107  gen.drawFatGaussian(1.0, 0.90)
108  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
109  break;
110  }
111 
113  {
115  sample_rate_,
116  gen.drawFatGaussian(1.0, 0.70)
117  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
118  break;
119  }
120 
122  {
124  sample_rate_,
125  gen.drawFatGaussian(1.0, 0.50)
126  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
127  break;
128  }
129 
131  {
133  sample_rate_,
134  gen.drawFatGaussian(1.0, 0.30)
135  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
136  break;
137  }
138 
140  {
142  sample_rate_,
143  gen.drawFatGaussian(1.0, 0.10)
144  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
145  break;
146  }
147 
148  case Granulator::DECAY:
149  {
150  Buffer waveform(static_cast<uint32>(sample_rate_));
151 
152  waveform << gen.drawDecay(1.0);
153 
154  Buffer noise = 1.0 + envelope_noise * gen.whiteNoise(1.0);
155 
157  sample_rate_,
158  gen.drawDecay(1.0)
159  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
160  break;
161  }
162 
164  {
166  sample_rate_,
167  gen.drawDecay(1.0).getReverse()
168  * (1.0 + envelope_noise * gen.whiteNoise(1.0)));
169  break;
170  }
171  }
172 }
173 
177  :
178  sample_rate_(gran.sample_rate_),
179  envelope_generator_(NULL)
180 {
181  *this = gran;
182 }
183 
187 {
188  delete envelope_generator_;
189 }
190 
191 Buffer
194  const float64 & duration,
195  const float64 & grain_frequency,
196  const float64 & waves_per_grain,
197  const float64 & grains_per_second)
198 {
199  Sine sin(sample_rate_);
200 
201  float64 time_step = 1.0 / sample_rate_;
202 
203  Buffer y(4096);
204 
205  for(float64 last_g_time = 0.0, current_time = 0.0, next_grain_time = 0.0;
206  current_time < duration;
207  current_time += time_step)
208  {
209  // Output a pulse.
210  if(next_grain_time - current_time < time_step)
211  {
212  float64 g_duration = waves_per_grain / grain_frequency;
213 
214  Buffer grain(4096);
215 
216  grain << sin.generate(g_duration, grain_frequency)
217  * envelope_generator_->generate(g_duration, 1.0 / g_duration);
218 
219  y.add(grain, static_cast<uint32>(current_time * sample_rate_));
220 
221  last_g_time = current_time;
222  }
223 
224  next_grain_time = last_g_time + (1.0 / grains_per_second);
225  }
226 
227  return y;
228 }
229 
230 Buffer
233  const float64 & duration,
234  const Buffer & grain_frequency,
235  const Buffer & waves_per_grain,
236  const Buffer & grains_per_second) const
237 {
238  Sine sin(sample_rate_);
239 
240  uint32 gf_length = grain_frequency.getLength();
241  uint32 wpg_length = waves_per_grain.getLength();
242  uint32 gps_length = grains_per_second.getLength();
243 
244  uint32 gf_index = 0;
245  uint32 wpg_index = 0;
246  uint32 gps_index = 0;
247 
248  float64 time_step = 1.0 / sample_rate_;
249 
250  Buffer y;
251 
252  for(float64 last_g_time = 0.0, current_time = 0.0, next_grain_time = 0.0;
253  current_time < duration;
254  current_time += time_step)
255  {
256 
257  float64 gps =
258  grains_per_second[gps_index++ % gps_length];
259 
260  // Output a pulse.
261  if(next_grain_time - current_time < time_step)
262  {
263  float64 g_frequency = grain_frequency[gf_index++ % gf_length];
264  float64 wpg = waves_per_grain[wpg_index++ % wpg_length];
265 
266  float64 g_duration = wpg / g_frequency;
267 
268  Buffer grain =
269  sin.generate(g_duration,g_frequency)
270  * envelope_generator_->generate(g_duration, 1.0 / g_duration);
271 
272  y.add(grain, static_cast<uint32>(current_time * sample_rate_));
273 
274  last_g_time = current_time;
275  }
276 
277  next_grain_time = last_g_time + (1.0 / gps);
278  }
279 
280  return y;
281 }
282 
283 
285 Granulator &
287 operator=(const Granulator & rhs)
288 {
289  delete envelope_generator_;
290 
293 
294  return *this;
295 }
296 
297 
unsigned int uint32
Definition: Nsound.h:153
Generator * envelope_generator_
Definition: Granulator.h:125
Buffer drawFatGaussian(const float64 &duration, const float64 &pass_band_percent=0.01) const
This method draws a standard Gaussian curve over duration seconds, with a specified pass band...
Definition: Generator.cc:434
Nsound::Buffer generate(const float64 &duration, const float64 &grain_frequency, const float64 &waves_per_grain, const float64 &grains_per_second)
Definition: Granulator.cc:193
float64 sample_rate_
Definition: Granulator.h:123
virtual ~Granulator()
Definition: Granulator.cc:186
Buffer drawGaussian(const float64 &duration, const float64 &mu, const float64 &sigma, const boolean &normalize=true) const
This method draws a Gaussian curve over duration seconds.
Definition: Generator.cc:403
double float64
Definition: Nsound.h:146
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
virtual float64 generate(const float64 &frequency)
This is a real-time method for the wavetable oscillator.
Definition: Generator.cc:972
Buffer drawDecay(const float64 &duration, const float64 &alpha=2.0 *M_PI) const
This method draws an exponential curve that decays from 1.0 to 0.0 over the duration.
Definition: Generator.cc:388
#define M_THROW(message)
Definition: Macros.h:108
A Buffer for storing audio samples.
Definition: Buffer.h:60
Buffer whiteNoise(const float64 &duration) const
This method generates noise from a uniform distribution.
Definition: Generator.cc:1325
void add(const Buffer &buffer, uint32 offset=0, uint32 n_samples=0)
This method adds buffer to *this.
Definition: Buffer.cc:225
Buffer getReverse() const
Reverses the samples in a copy of this Buffer.
Definition: Buffer.h:1558
DOXME.
Definition: Sine.h:43
A class the provides draw utilities and a wavetable oscillator.
Definition: Generator.h:50
Nsound::Granulator & operator=(const Nsound::Granulator &rhs)
Assignment operator.
Definition: Granulator.cc:287