Nsound  0.9.4
test_audio_stream.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: test_audio_stream.cc 912 2015-07-26 00:50:29Z weegreenblobbie $
4 //
5 // Copyright (c) 2005-2006 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/Sine.h>
32 #include <Nsound/TicToc.h>
33 
34 #include "Test.h"
35 
36 #include <cmath>
37 #include <stdlib.h>
38 #include <iostream>
39 
40 using namespace Nsound;
41 
42 using std::cerr;
43 using std::cout;
44 using std::endl;
45 using std::flush;
46 
47 static const char * THIS_FILE = "test_audio_stream.cc";
48 
49 void testAutioStream();
50 
51 int main(int argc, char ** argv)
52 {
53  cout << "////////////////////////////////////////////////////////////"
54  << endl
55  << "// Testing class Nsound::AudioStream"
56  << endl
57  << "////////////////////////////////////////////////////////////"
58  << endl
59  << flush;
60 
62 
63  return 0;
64 }
65 
66 //-----------------------------------------------------------------------------
68 {
69  Tic();
70  cout << TEST_HEADER
71  << "AudioStream::operator<<, AudioStream::operator[] ... " << flush;
72 
73  AudioStream as1(48000, 2);
74 
75  uint32 test_size = 29 * 3 + 1;
76 
77  float64 test_value = 3.14;
78 
79  for(uint32 i = 0; i < test_size; ++i)
80  {
81  as1 << test_value;
82 
83  if(as1[0][i] != test_value || as1[1][i] != test_value)
84  {
85  cerr << TEST_ERROR_HEADER
86  << "as1[0]["
87  << i
88  << "] should equal "
89  << test_value
90  << ", but it equals "
91  << as1[0][i]
92  << endl;
93  exit(1);
94  }
95  }
96 
97  cout << Toc() << " seconds: SUCCESS"
98  << endl
99  << TEST_HEADER << "testing AudioStream::getLength() ... " << flush;
100 
101  Tic();
102 
103  if(as1.getLength() != test_size)
104  {
105  cerr << TEST_ERROR_HEADER
106  << "as1.getLength() should equal "
107  << test_size
108  << ", "
109  << as1.getLength()
110  << " != "
111  << test_size
112  << endl;
113  exit(1);
114  }
115 
116  cout << Toc() << " seconds: SUCCESS"
117  << endl
118  << TEST_HEADER << "testing AudioStream::operator== ... " << flush;
119 
120  Tic();
121 
122  AudioStream as2(48000, 2);
123 
124  if(as1 == as2 || as2 == as1)
125  {
126  cerr << TEST_ERROR_HEADER
127  << "as1 should _NOT_ equal as2"
128  << endl;
129  exit(1);
130  }
131 
132  for(uint32 i = 0; i < test_size; i++)
133  {
134  as2 << test_value;
135  }
136 
137  if(as1 != as2 || as2 != as1)
138  {
139  cerr << TEST_ERROR_HEADER
140  << "as1 _SHOULD_ equal as2"
141  << endl;
142  exit(1);
143  }
144 
145  cout << Toc() << " seconds: SUCCESS"
146  << endl
147  << TEST_HEADER << "testing AudioStream::AudioStream(&) ... " << flush;
148 
149  Tic();
150 
151  AudioStream as3(as1);
152 
153  if(as1 != as3 || as3 != as1)
154  {
155  cerr << TEST_ERROR_HEADER
156  << "as1 _SHOULD_ equal as3"
157  << endl;
158  exit(1);
159  }
160 
161  cout << Toc() << " seconds: SUCCESS"
162  << endl
163  << TEST_HEADER << "testing AudioStream::operator+,-,*,/ ... " << flush;
164 
165  Tic();
166 
167  AudioStream as4;
168 
169  as4 = as1;
170 
171  if(1 + as4 * 2 != 2 * as4 + 1)
172  {
173  cerr << TEST_ERROR_HEADER
174  << "left hand side _SHOULD_ equal right hand side"
175  << endl;
176  exit(1);
177  }
178 
179  if(1 - as4 / 2 != -1 * as4 / 2 + 1)
180  {
181  cerr << TEST_ERROR_HEADER
182  << "left hand side _SHOULD_ equal right hand side"
183  << endl;
184  exit(1);
185  }
186 
187  if(2.0 / as4 != 2.0 * (1.0 / as4))
188  {
189  cerr << TEST_ERROR_HEADER
190  << "left hand side _SHOULD_ equal right hand side"
191  << endl;
192  exit(1);
193  }
194 
195  cout << Toc() << " seconds: SUCCESS"
196  << endl
197  << TEST_HEADER << "test AudioStream::operator+= ... " << flush;
198 
199  Sine sine(48000);
200 
201  AudioStream as5(48000, 2);
202  as5 << sine.generate(1.0,1.0);
203 
204  AudioStream as6 = -1.0 * as5;
205 
206  as5 += as6;
207 
208  uint32 n_samples = as5.getLength();
209  for(uint32 i = 0; i < n_samples; ++i)
210  {
211  if(as5[0][i] != 0.0 || as5[1][i] != 0.0)
212  {
213  cerr << TEST_ERROR_HEADER
214  << "as5 + as6 _SHOULD_ be all zeros!"
215  << endl;
216  exit(1);
217  }
218  }
219 
220  cout << Toc() << " seconds: SUCCESS"
221  << endl;
222 
223  // Test AudioStream::reverse()
224  cout << TEST_HEADER << "test AudioStream::reverse() ... " << flush;
225 
226  as5 = sine.generate(4.0,1.0);
227 
228  // as5 now has 4 seconds of sine data.
229 
230  Buffer envelope = sine.drawLine(4.0,1.0,0.0);
231 
232  as5 *= envelope;
233 
234  as6 = as5;
235 
236  as5.reverse();
237 
238  //as5[0].plot("as as5[0] reversed, upward envelope");
239 
240  as6.reverse();
241 
242  as5 -= as6;
243 
244  uint32 length = as6.getLength();
245  for(uint32 i = 0; i < length; ++i)
246  {
247  if(as5[0][i] != 0.0 || as5[1][i] != 0.0)
248  {
249  cerr << TEST_ERROR_HEADER
250  << "as6 should be all zeros!"
251  << endl;
252  exit(1);
253  }
254  }
255 
256  cout << Toc() << " seconds: SUCCESS"
257  << endl
258  << TEST_HEADER << "test AudioStream::pan() ... " << flush;
259 
260  AudioStream as7(48000, 2);
261 
262  as7 << sine.drawLine(1.0,1.0,1.0);
263 
264  as7.pan(0.5);
265 
266  //as7[0].plot("as7 left");
267  //as7[1].plot("as7 right");
268 
269  // -1.0------0.5-------0.0+++++++0.5+++++++++++1.0
270  // |-----------------2.0----------------------|
271  // ^
272  //
273  // Pan values are from -1.0, 100% for right channel, to 1.0, 100% for the
274  // left channel.
275  //
276  // A pan value of 0.5 is 75% of the total interval towards the left
277  // channel leaving only 25% for the right.
278 
279  for(uint32 i = 0; i < as7.getLength(); ++i)
280  {
281  if(as7[0][i] != 0.75 || as7[1][i] != 0.25)
282  {
283  cerr << TEST_ERROR_HEADER
284  << "AudioStream::pan(float64 d) is borken!"
285  << endl;
286  exit(1);
287  }
288  }
289 
290  // Set as7 back to all ones.
291 
292  as7[0] = sine.drawLine(1.0,1.0,1.0);
293  as7[1] = sine.drawLine(1.0,1.0,1.0);
294 
295  // set left channel to 25% and right to 75%
296  as7.pan(-0.5);
297 
298  for(uint32 i = 0; i < as7.getLength(); ++i)
299  {
300  if(as7[0][i] != 0.25 || as7[1][i] != 0.75)
301  {
302  cerr << TEST_ERROR_HEADER
303  << "AudioStream::pan(float64 d) is borken!"
304  << endl;
305  exit(1);
306  }
307  }
308 
309  cout << Toc() << " seconds: SUCCESS"
310  << endl
311  << TEST_HEADER << "test AudioStream::pan(Buffer b) ... " << flush;
312 
313  // Test Dynamic pan
314 
315  Buffer pan = sine.generate(1.0,1.0);
316 
317  // Set as7 back to all ones.
318 
319  as7[0] = sine.drawLine(1.0,1.0,1.0);
320  as7[1] = sine.drawLine(1.0,1.0,1.0);
321 
322  as7.pan(pan);
323 
324  //pan.plot("pan");
325 
326  //as7[0].plot("as7 left");
327  //as7[1].plot("as7 right");
328 
329  Buffer left_test = (pan + 1) / 2;
330 
331  //left_test.plot("left_test");
332 
333  if(as7[0] != left_test)
334  {
335  cerr << TEST_ERROR_HEADER
336  << "AudioStream::pan(Buffer b) is borken!"
337  << endl;
338  exit(1);
339  }
340 
341 
342  // There is some roundoff error when Nsound creates right_test. Instead
343  // of using operator != lets subtrarct the two and then check if the
344  // difference is large.
345 
346  Buffer right_test = left_test * -1.0 + 1.0;
347 
348  //right_test.plot("right_test");
349 
350  Buffer difference = as7[1] - right_test;
351 
352  cerr.precision(20);
353 
354  //difference.plot("difference");
355  //Plotter::show();
356 
357  for(uint32 i = 0; i < difference.getLength(); ++i)
358  {
359  if(difference[i] > 0.0000001 || difference[i] < -0.0000001)
360  {
361  cerr << TEST_ERROR_HEADER
362  << "AudioStream::pan(Buffer b) is borken!"
363  << endl;
364  exit(1);
365  }
366  }
367 
368  cout << Toc() << " seconds: SUCCESS"
369  << endl;
370 
371 
372  // testing substream
373 
374  cout << TEST_HEADER << "test AudioStream::substream() ... " << flush;
375 
376  Tic();
377 
378  AudioStream as8(44100, 10);
379 
380  for(uint32 i = 0; i < 44100; ++i)
381  {
382  as8 << static_cast<float64>(i);
383  }
384 
385  uint32 start_index = 0;
386  n_samples = 44100;
387 
388  AudioStream substr(as8.substream(start_index, n_samples));
389 
390  // Verify sub stream
391  for(uint32 ch = 0; ch < 10; ++ch)
392  {
393  for(uint32 i = 0; i < 44100; ++i)
394  {
395  if(static_cast<uint32>(substr[ch][i]) != i)
396  {
397  cerr << TEST_ERROR_HEADER
398  << "as8.substream() error!"
399  << endl;
400  exit(1);
401  }
402  }
403  }
404 
405  start_index = 1000;
406  n_samples = 1000;
407 
408  substr = as8.substream(1000, 1000);
409  // Verify sub stream
410  for(uint32 ch = 0; ch < 10; ++ch)
411  {
412  for(uint32 i = 1000; i < 1000; ++i)
413  {
414  if(static_cast<uint32>(substr[ch][i]) != i)
415  {
416  cerr << TEST_ERROR_HEADER
417  << "as8.substream() error!"
418  << endl;
419  exit(1);
420  }
421  }
422  }
423 
424  // use the substream(float32,float32) version
425  substr = as8.substream(0.0, 1.0);
426 
427  // Verify sub stream
428  for(uint32 ch = 0; ch < 10; ++ch)
429  {
430  for(uint32 i = 0; i < 44100; ++i)
431  {
432  if(static_cast<uint32>(substr[ch][i]) != i)
433  {
434  cerr << TEST_ERROR_HEADER
435  << "as8.substream() error!"
436  << endl;
437  exit(1);
438  }
439  }
440  }
441 
442  substr = as8.substream(1000.0 / 44100.0, 1000.0 / 44100.0);
443  // Verify sub stream
444  for(uint32 ch = 0; ch < 10; ++ch)
445  {
446  for(uint32 i = 1000; i < 1000; ++i)
447  {
448  if(static_cast<uint32>(substr[ch][i]) != i)
449  {
450  cerr << TEST_ERROR_HEADER
451  << "as8.substream() error!"
452  << endl;
453  exit(1);
454  }
455  }
456  }
457 
458  cout << Toc() << " seconds: SUCCESS" << endl;
459 }
unsigned int uint32
Definition: Nsound.h:153
static const char * THIS_FILE
uint32 getLength() const
Returns the number of samples of audio data in the stream.
Definition: AudioStream.cc:197
#define TEST_HEADER
Definition: Test.h:45
int main(int argc, char **argv)
void reverse()
Reverses the AudioStream.
Definition: AudioStream.cc:733
void testAutioStream()
AudioStream substream(uint32 start_index, uint32 n_samples=0) const
Definition: AudioStream.cc:825
double float64
Definition: Nsound.h:146
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
#define TEST_ERROR_HEADER
Definition: Test.h:49
virtual float64 generate(const float64 &frequency)
This is a real-time method for the wavetable oscillator.
Definition: Generator.cc:972
A Buffer for storing audio samples.
Definition: Buffer.h:60
Nsound::float64 Toc()
Definition: TicToc.cc:42
void pan(float64 pan)
Sets the amplitude level left vs right.
Definition: AudioStream.cc:627
void Tic()
Definition: TicToc.cc:37
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
DOXME.
Definition: Sine.h:43