Nsound  0.9.4
Mesh2D.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Mesh2D.cc 904 2015-06-15 03:26:19Z weegreenblobbie $
4 //
5 // Copyright (c) 2008 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/Generator.h>
32 #include <Nsound/Mesh2D.h>
33 #include <Nsound/MeshJunction.h>
34 
35 #include <cmath>
36 #include <cstdio>
37 #include <iostream>
38 #include <sstream>
39 
40 using namespace Nsound;
41 
42 using std::cout;
43 using std::cerr;
44 using std::endl;
45 
46 //-----------------------------------------------------------------------------
49  const float64 & sample_rate,
50  uint32 width,
51  uint32 height,
52  const float64 & leak_gain,
53  const float64 & tau,
54  const float64 & delta,
55  const float64 & gamma)
56  :
57  sample_rate_(sample_rate),
58  X_(width),
59  Y_(height),
60  leak_gain_(leak_gain),
61  tau_(tau),
62  delta_(delta),
63  gamma_(gamma),
64  mesh_(NULL),
65  center_(NULL),
66  dump_mesh_(false),
67  dirname_("."),
68  prefix_("mesh")
69 {
70  // Range check
71  if(tau_ < 0.0)
72  {
73  tau_ = 1e-6;
74  }
75  else if(tau_ > 0.5)
76  {
77  tau_ = 0.5;
78  }
79 
80  allocMemory();
81 }
82 
83 //-----------------------------------------------------------------------------
85 Mesh2D(const Mesh2D & copy)
86  :
87  sample_rate_(0.0),
88  X_(0),
89  Y_(0),
90  leak_gain_(0.0),
91  tau_(0.0),
92  delta_(0.0),
93  gamma_(0.0),
94  mesh_(NULL),
95  center_(NULL),
96  dump_mesh_(false),
97  dirname_("."),
98  prefix_("mesh")
99 {
100  *this = copy;
101 }
102 
103 //-----------------------------------------------------------------------------
104 Mesh2D::
106 {
107  freeMemory();
108 }
109 
110 void
111 Mesh2D::
113 {
114  mesh_ = new MeshJunction * [X_ * Y_];
115 
116  // Allocate new MeshJunctions
117  for(uint32 i = 0; i < X_ * Y_; ++i)
118  {
120  }
121 
122  // Set neighbors.
123  for(uint32 x = 0; x < X_; ++x)
124  {
125  for(uint32 y = 0; y < Y_; ++y)
126  {
127  // Set north neighbor.
128  if(y + 1 < Y_)
129  {
130  mesh(x,y)->setNeighborNorth(mesh(x,y+1));
131  }
132 
133  // Set south neighbor.
134  if(y >= 1)
135  {
136  mesh(x,y)->setNeighborSouth(mesh(x,y-1));
137  }
138 
139  // Set east neighbor.
140  if(x + 1 < X_)
141  {
142  mesh(x,y)->setNeighborEast(mesh(x+1,y));
143  }
144 
145  // Set west neighbor.
146  if(x >= 1)
147  {
148  mesh(x,y)->setNeighborWest(mesh(x-1,y));
149  }
150  }
151  }
152 
153  // Set the center pointer.
154  center_ = mesh(X_ / 2, Y_ / 2);
155 }
156 
157 void
158 Mesh2D::
160 {
161  for(uint32 i = 0; i < X_ * Y_; ++i)
162  {
163  mesh_[i]->clear();
164  }
165 }
166 
167 void
168 Mesh2D::
170 {
171  // delete junctions
172  for(uint32 i = 0; i < X_ * Y_; ++i)
173  {
174  delete mesh_[i];
175  }
176 
177  delete [] mesh_;
178 }
179 
180 float64
181 Mesh2D::
182 getEnergy() const
183 {
184  float64 energy = 0.0;
185 
186  for(uint32 i = 0; i < X_ * Y_; ++i)
187  {
188  float64 v = mesh_[i]->getVelocity();
189  energy += v * v;
190  }
191 
192  return energy / static_cast<float64>(X_ * Y_);
193 }
194 
195 //-----------------------------------------------------------------------------
196 MeshJunction *
197 Mesh2D::
199 {
200  // -----------------
201  // || array index ||
202  // || x, y ||
203  // -----------------
204 
205  // -----------------------
206  // || 9 || 10 || 11 ||
207  // || 0,3 || 1,3 || 2,3 ||
208  // -----------------------
209  // || 6 || 7 || 8 ||
210  // || 0,2 || 1,2 || 2,2 ||
211  // -----------------------
212  // || 3 || 4 || 5 ||
213  // || 0,1 || 1,1 || 2,1 ||
214  // -----------------------
215  // || 0 || 1 || 2 ||
216  // || 0,0 || 1,0 || 2,0 ||
217  // -----------------------
218 
219  return mesh_[y * X_ + x];
220 }
221 
222 //-----------------------------------------------------------------------------
223 Mesh2D &
224 Mesh2D::
225 operator=(const Mesh2D & rhs)
226 {
227  if(this == & rhs)
228  {
229  return *this;
230  }
231 
232  leak_gain_ = rhs.leak_gain_;
233  tau_ = rhs.tau_;
234  delta_ = rhs.delta_;
235  gamma_ = rhs.gamma_;
236 
237  freeMemory();
238 
239  X_ = rhs.X_;
240  Y_ = rhs.Y_;
241 
242  allocMemory();
243 
244  return *this;
245 }
246 
247 Buffer
248 Mesh2D::
250  const Buffer & x_pos,
251  const Buffer & y_pos,
252  const Buffer & velocity)
253 {
254  Buffer output;
255 
256  uint32 x_size = x_pos.getLength();
257  uint32 y_size = y_pos.getLength();
258 
259  for(uint32 i = 0; i < velocity.getLength(); ++i)
260  {
261  output << tick(x_pos[i % x_size], y_pos[i % y_size], velocity[i]);
262  }
263 
264  return output;
265 }
266 
267 void
268 Mesh2D::
270 {
271  if(!dump_mesh_)
272  {
273  return;
274  }
275 
276  std::stringstream ss;
277 
278  ss << dirname_ << "/" << prefix_ << "_map.txt";
279 
280  FILE * f_out = fopen(ss.str().c_str(), "w");
281 
282  if(!f_out)
283  {
284  M_THROW("Unable to open '" << ss.str().c_str() << "' for writing.");
285  return;
286  }
287 
288  for(int32 y = Y_ - 1; y >= 0; --y)
289  {
290  for(uint32 x = 0; x < X_; ++x)
291  {
292  if(mesh(x,y) != NULL)
293  {
294  fprintf(f_out, " %5d", x + y * X_);
295  }
296  else
297  {
298  fprintf(f_out, " -1");
299  }
300  }
301  fprintf(f_out, "\n");
302  }
303  fclose(f_out);
304 }
305 
306 
307 void
308 Mesh2D::
309 writeMeshFile(const std::string & mode)
310 {
311  if(!dump_mesh_)
312  {
313  return;
314  }
315 
316  std::stringstream ss;
317 
318  ss << dirname_ << "/" << prefix_ << ".txt";
319 
320  FILE * f_out = fopen(ss.str().c_str(), mode.c_str());
321 
322  if(!f_out)
323  {
324  M_THROW("Unable to open '" << ss.str().c_str() << "' for writing.");
325  return;
326  }
327 
328  for(int32 y = Y_ - 1; y >= 0; --y)
329  {
330  for(uint32 x = 0; x < X_; ++x)
331  {
332  fprintf(f_out, "%6.3f ", mesh(x,y)->getVelocity());
333  }
334  }
335  fprintf(f_out, "\n");
336  fclose(f_out);
337 }
338 
339 void
340 Mesh2D::
342  boolean flag,
343  const std::string & dirname,
344  const std::string & prefix)
345 {
346  dump_mesh_ = flag;
347  dirname_ = dirname;
348  prefix_ = prefix;
349 }
350 
351 Buffer
352 Mesh2D::
354  const float64 & x_pos,
355  const float64 & y_pos,
356  const float64 & velocity)
357 {
358  Buffer output;
359 
360  clear();
361 
362  output << tick(x_pos, y_pos, velocity);
363 
364  writeMeshMap();
365  writeMeshFile("w");
366 
367  for(uint32 i = 0; i < 44100; ++i)
368  {
369  output << tick(x_pos, y_pos, 0.0);
370 
371  writeMeshFile("a");
372 
373  center_->getVelocity();
374  }
375 
376  // Shape the attack
377  Generator gen(sample_rate_);
378 
379  Buffer attack = gen.drawLine(0.0025, 0.0, 1.0);
380 
381  return output * attack;
382 }
383 
384 float64
385 Mesh2D::
387  const float64 & x_pos,
388  const float64 & y_pos,
389  const float64 & velocity)
390 {
391  float64 x_max = static_cast<float64>(X_);
392  float64 y_max = static_cast<float64>(Y_);
393 
394  float64 x_strike = x_pos * x_max;
395  float64 y_strike = y_pos * y_max;
396 
397  if(velocity > 0.0)
398  {
399  float64 dx = 0.5 / (X_ - 1);
400 
401  x_strike = 0.5 / 3.0;
402  y_strike = 0.5 / 3.0;
403 
404  for(uint32 x = 2; x < X_; ++x)
405  {
406  for(uint32 y = 2; y < Y_; ++y)
407  {
408  float64 x_pos = (static_cast<float64>(x) - 1.0) * dx;
409  float64 y_pos = (static_cast<float64>(y) - 1.0) * dx;
410 
411  float64 xx = x_pos - x_strike;
412  xx *= xx;
413 
414  float64 yy = y_pos - y_strike;
415  yy *= yy;
416 
417  float64 power = velocity * std::exp(-200.0 * (xx + yy));
418 
419  mesh(x, y)->strike(power);
420  }
421  }
422  }
423 
424  for(uint32 i = 0; i < X_ * Y_; ++i)
425  {
426  mesh_[i]->saveState();
427  }
428 
429  for(uint32 i = 0; i < X_ * Y_; ++i)
430  {
431  mesh_[i]->updateVelocity();
432  }
433 
434  return center_->getVelocity();
435 }
436 
437 
unsigned int uint32
Definition: Nsound.h:153
float64 sample_rate_
Definition: Mesh2D.h:131
uint32 X_
Definition: Mesh2D.h:133
Mesh2D(const float64 &sample_rate, uint32 width, uint32 height, const float64 &leak_gain, const float64 &tau, const float64 &delta=6.0, const float64 &gamma=8.0)
Constructor.
Definition: Mesh2D.cc:48
float64 getEnergy() const
Calculate total energy in the mesh.
Definition: Mesh2D.cc:182
void updateVelocity()
updates junction velocity.
void strike(const float64 &velocity)
Adds velocity to this junction.
Buffer strike(const Buffer &x_pos, const Buffer &y_pos, const Buffer &velocity)
Hit the mesh many times at different locations.
Definition: Mesh2D.cc:249
~Mesh2D()
Destructor.
Definition: Mesh2D.cc:105
float64 gamma_
MeshJunction delta.
Definition: Mesh2D.h:139
void clear()
Clears all MeshJunctions to zero.
Definition: Mesh2D.cc:159
void setNeighborNorth(MeshJunction *ptr)
void setMeshDumping(boolean flag, const std::string &dirname=".", const std::string &prefix="mesh")
Enables the dumping of mesh values to disk for use with mesh2blender.py.
Definition: Mesh2D.cc:341
void allocMemory()
Allocates memory for the mesh.
Definition: Mesh2D.cc:112
void writeMeshMap()
Write to disk the mesh map, used with mesh2blender.py.
Definition: Mesh2D.cc:269
void freeMemory()
Frees memory from the mesh.
Definition: Mesh2D.cc:169
uint32 Y_
The number of MeshJunctions columns.
Definition: Mesh2D.h:134
Mesh2D & operator=(const Mesh2D &rhs)
Assignment operator.
Definition: Mesh2D.cc:225
double float64
Definition: Nsound.h:146
void setNeighborEast(MeshJunction *ptr)
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
float64 tau_
MeshJunction leak gain.
Definition: Mesh2D.h:137
void setNeighborSouth(MeshJunction *ptr)
boolean dump_mesh_
Center MeshJunction where final sound is collected.
Definition: Mesh2D.h:145
MeshJunction * center_
Array of pointers.
Definition: Mesh2D.h:143
float64 leak_gain_
The number of MeshJunctions rows.
Definition: Mesh2D.h:136
void writeMeshFile(const std::string &mode)
Definition: Mesh2D.cc:309
MeshJunction ** mesh_
MeshJunction gamma.
Definition: Mesh2D.h:141
#define M_THROW(message)
Definition: Macros.h:108
float64 delta_
MeshJunction tau.
Definition: Mesh2D.h:138
void setNeighborWest(MeshJunction *ptr)
std::string dirname_
Definition: Mesh2D.h:147
float64 getVelocity() const
std::string prefix_
Definition: Mesh2D.h:148
A Buffer for storing audio samples.
Definition: Buffer.h:60
signed int int32
Definition: Nsound.h:142
MeshJunction * mesh(uint32 x, uint32 y)
Definition: Mesh2D.cc:198
Buffer drawLine(const float64 &duration, const float64 &amplitude_start, const float64 &amplitude_finish) const
This method draws a linear line beteween 2 points.
Definition: Generator.cc:464
void saveState()
Saves previous south and east velocities.
void clear()
Clears all velicityes in the junctino.
A class the provides draw utilities and a wavetable oscillator.
Definition: Generator.h:50
float64 tick(const float64 &x_pos, const float64 &y_pos, const float64 &velocity)
Calculate one sample.
Definition: Mesh2D.cc:386