Jamoma API  0.6.0.a19
TTSoundfileLoader.test.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspSoundFileLib
4  *
5  * @brief Tests for the #TTSoundfileLoader class
6  *
7  * @details Tests the core functions of the TTSoundfileLoader class in order to ensure that things are working after a build. It also demostrate how to make calls to common methods within the class.@n
8  * IMPORTANT NOTE: Because POSIX filepaths will be specific to your system, this test will attempt to find the path to the SoundfileLib extension using the TTFoundationBinaryPath environment variable. If you wish to test with a different sound file, you will need to place in that extension folder and change the relevant macros in the header of this class.
9  *
10  * @authors Nathan Wolek
11  *
12  * @copyright Copyright © 2013 by Nathan Wolek @n
13  * This code is licensed under the terms of the "New BSD License" @n
14  * http://creativecommons.org/licenses/BSD/
15  */
16 
17 #include "TTSoundfileLoader.h"
18 #include "TTUnitTest.h"
19 #include "TTBuffer.h"
20 
21 /*
22 
23  It is possible to change the target sound file for this test using the macros below.
24  Both sound files are included in the Jamoma respository at the following path:
25  {JAMOMA_ROOT}/Core/DSP/extensions/SoundfileLib/
26 
27  The test should look for the named TESTFILE at this path.
28 
29  */
30 
31 /* */
32  #define TESTFILE "geese_clip.aif"
33  #define TESTNUMCHANNELS 2
34  #define TESTSAMPLERATE 44100
35  #define TESTDURATIONINSAMPLES 88202
36  #define TESTDURATIONINSECONDS 2.00004535
37  #define TESTTITLE ""
38  #define TESTARTIST ""
39  #define TESTDATE ""
40  #define TESTANNOTATION ""
41 /* */
42 
43 /*
44 #define TESTFILE "ding_b2.aiff"
45 #define TESTNUMCHANNELS 1
46 #define TESTSAMPLERATE 44100
47 #define TESTDURATIONINSAMPLES 39493
48 #define TESTDURATIONINSECONDS 0.89553288
49 #define TESTTITLE ""
50 #define TESTARTIST ""
51 #define TESTDATE ""
52 #define TESTANNOTATION ""
53  */
54 
56 {
57  int errorCount = 0;
58  int testAssertionCount = 0;
59 
60  // assemble the full path of the target sound file
61 
62  TTString testSoundPath = TTFoundationBinaryPath;
63  int pos = testSoundPath.find_last_of('/');
64  testSoundPath = testSoundPath.substr(0,pos+1);
65  testSoundPath += TESTFILE;
66 
67  std::cout << "We will be using the following path for testing: " << testSoundPath << "\n";
68 
69  try {
70 
71  TTTestLog("\n");
72  TTTestLog("Testing TTSoundfileLoader Basics...");
73 
74  // TEST 0: establish our objects & pointers
75  TTObject* testTargetMatrix = new TTObject("samplematrix");
76  TTObject* testNonSampleMatrix = new TTObject("delay");
77  TTObjectBase* objectBasePtrToSampleMatrix;
78  TTObjectBase* ptrToNonSampleMatrix;
79 
80  // TEST 1: set the filepath
81  TTBoolean result1 = { this->setFilePath(TT(testSoundPath)) == kTTErrNone };
82 
83  TTTestAssertion("setFilePath operates successfully",
84  result1,
85  testAssertionCount,
86  errorCount);
87 
88  // TEST 2: set up the samplematrix first
89  int channelsSend = 1; // compiler complained about TTInt32 being ambiguous here
90  int lengthSend = 22050; // compiler complained about TTInt32 being ambiguous here
91  testTargetMatrix->set("numChannels", channelsSend);
92  testTargetMatrix->set("lengthInSamples", lengthSend);
93 
94  TTInt32 channelsReturn, lengthReturn;
95 
96  testTargetMatrix->get("numChannels", channelsReturn);
97  testTargetMatrix->get("lengthInSamples", lengthReturn);
98 
99  // now for the actual test
100  TTBoolean result2a = { channelsSend == channelsReturn };
101 
102  TTTestAssertion("numChannels attribute set successfully",
103  result2a,
104  testAssertionCount,
105  errorCount);
106 
107  TTBoolean result2b = { lengthSend == lengthReturn };
108 
109  TTTestAssertion("lengthInSamples attribute set successfully",
110  result2b,
111  testAssertionCount,
112  errorCount);
113  //
114 
115  // TEST 3: set the target via an objectBasePtr
116  objectBasePtrToSampleMatrix = testTargetMatrix->instance(); // is there a better syntax for this?
117 
118  TTBoolean result3 = { this->setTargetMatrix(objectBasePtrToSampleMatrix) == kTTErrNone };
119 
120  TTTestAssertion("setTargetMatrix via ObjectBasePtr operates successfully",
121  result3,
122  testAssertionCount,
123  errorCount);
124 
125  // TEST 4: set the target to a non-SampleMatrix, should FAIL
126  ptrToNonSampleMatrix = testNonSampleMatrix->instance();
127 
128  TTBoolean result4 = { this->setTargetMatrix(ptrToNonSampleMatrix) == kTTErrInvalidValue };
129 
130  TTTestAssertion("setTargetMatrix returns error when not a SampleMatrix",
131  result4,
132  testAssertionCount,
133  errorCount);
134 
135  // TEST 5: copy samplevalues until samplematrix is filled
136 
137  TTBoolean result5 = { this->copyUntilFilled() == kTTErrNone };
138 
139  TTTestAssertion("copyUntilFilled operates successfully",
140  result5,
141  testAssertionCount,
142  errorCount);
143 
144  // releasing objects
145  objectBasePtrToSampleMatrix = NULL;
146  ptrToNonSampleMatrix = NULL;
147  delete testTargetMatrix;
148  delete testNonSampleMatrix;
149 
150 
151  // TEST 6: use TTSampleMatrix's load message, then compare 5 random sample values for equivalence
152 
153  // create a new TTSampleMatrix
154  TTObject newTargetMatrix("samplematrix");
155 
156  // set the length and channel count
157  newTargetMatrix.set("numChannels", TESTNUMCHANNELS);
158  newTargetMatrix.set("lengthInSamples", TESTDURATIONINSAMPLES);
159 
160  // prepare necessary TTValues
161  TTValue loadInput6 = TT(testSoundPath); // we cannot pass the naked TTString, it needs to be part of a TTValue
162  TTValue aReturnWeDontCareAbout6;
163 
164  // send message
165  TTBoolean result6a = { newTargetMatrix.send("load", loadInput6, aReturnWeDontCareAbout6) == kTTErrNone };
166 
167  TTTestAssertion("TTSampleMatrix load operates successfully",
168  result6a,
169  testAssertionCount,
170  errorCount);
171 
172  // now let's test some values!
173  int randomIndex6, randomChannel6;
174  TTSampleValue testValueSoundFile6;
175  TTBoolean result6b = true;
176 
177  for (int i = 0; i<10; i++)
178  {
179  randomIndex6 = lengthReturn * TTRandom64();
180  randomChannel6 = i % TESTNUMCHANNELS;
181  //std::cout << "let's look at index " << randomIndex6 << " & channel " << randomChannel6 << "\n";
182 
183  TTValue peekInput6(randomIndex6);
184  peekInput6.append(randomChannel6);
185  TTValue peekOutput6;
186 
187  this->peek(randomIndex6,randomChannel6,testValueSoundFile6);
188  newTargetMatrix.send("peek",peekInput6,peekOutput6);
189  //std::cout << "Does " << testValueSoundFile6 << " = " << double(peekOutput6) << " ?\n";
190 
191  if (result6b) // allows test to keep variable false once it is false
192  result6b = TTTestFloatEquivalence(testValueSoundFile6, double(peekOutput6), true, 0.0000001);
193  }
194 
195 
196  TTTestAssertion("comparing values @ 10 random indexes for equivalence",
197  result6b,
198  testAssertionCount,
199  errorCount);
200 
201 
202  // TEST 7: now use TTBuffer's load message, and again compare 5 random sample values for equivalence
203 
204  // create a new TTBuffer with convenience syntax
205  TTAudioBuffer aBufferByAnyOtherName(TESTNUMCHANNELS, TESTDURATIONINSAMPLES);
206 
207  // prepare necessary TTValues
208  TTValue loadInput7 = TT(testSoundPath); // we cannot pass the naked TTString, it needs to be part of a TTValue
209 
210  // send message
211  TTBoolean result7a = { aBufferByAnyOtherName.load(loadInput7) == kTTErrNone };
212 
213  TTTestAssertion("TTBuffer load operates successfully",
214  result7a,
215  testAssertionCount,
216  errorCount);
217 
218  // setup pointer to samplematrix
219  TTSampleMatrixPtr myMatrix7;
220 
221  // check out samplematrix
222  TTBoolean result7b = { aBufferByAnyOtherName.checkOutMatrix(myMatrix7) == kTTErrNone };
223 
224  TTTestAssertion("TTBuffer checks out SampleMatrix successfully",
225  result7b,
226  testAssertionCount,
227  errorCount);
228 
229  TTValue testChannel, testSample;
230  myMatrix7->getNumChannels(testChannel);
231  myMatrix7->getLengthInSamples(testSample);
232 
233  //std::cout << "Samplematrix has " << int(testChannel) << " channels & " << int(testSample) << " samples\n";
234 
235  // now let's test some values!
236  int randomIndex7, randomChannel7;
237  double testValueSoundFile7, testValueSampleMatrix7;
238  TTBoolean result7c = true;
239 
240  for (int i = 0; i<10; i++)
241  {
242  randomIndex7 = lengthReturn * TTRandom64();
243  randomChannel7 = i % TESTNUMCHANNELS;
244  //std::cout << "let's look at index " << randomIndex7 << " & channel " << randomChannel7 << "\n";
245 
246  this->peek(randomIndex7,randomChannel7,testValueSoundFile7);
247  myMatrix7->peek(randomIndex7,randomChannel7,testValueSampleMatrix7);
248  //std::cout << "Does " << testValueSoundFile7 << " = " << testValueSampleMatrix7 << " ?\n";
249 
250  if (result7c) // allows test to keep variable false once it is false
251  result7c = TTTestFloatEquivalence(testValueSoundFile7, testValueSampleMatrix7, true, 0.0000001);
252  }
253 
254  TTTestAssertion("comparing values @ 10 random indexes for equivalence",
255  result7c,
256  testAssertionCount,
257  errorCount);
258 
259  // check in samplematrix
260  TTBoolean result7d = { aBufferByAnyOtherName.checkInMatrix(myMatrix7) == kTTErrNone };
261 
262  TTTestAssertion("TTBuffer checks in SampleMatrix successfully",
263  result7d,
264  testAssertionCount,
265  errorCount);
266 
267 
268  // TEST 8: use optional load parameters to copy samples 5 to 15 from channel 0
269 
270  // resize
271  aBufferByAnyOtherName.set("numChannels", 1);
272  aBufferByAnyOtherName.set("lengthInSamples", 10);
273 
274  // prepare necessary TTValues
275  int copyChannel8 = 0; // first channel
276  int startIndex8 = 5; // start @ sample 5
277  int endIndex8 = 15; // end @ sample 15
278 
279  TTValue loadInput8 = TT(testSoundPath); // we cannot pass the naked TTString, it needs to be part of a TTValue
280  loadInput8.append(copyChannel8);
281  loadInput8.append(startIndex8);
282  loadInput8.append(endIndex8);
283 
284  // send message
285  TTBoolean result8a = { aBufferByAnyOtherName.load(loadInput8) == kTTErrNone };
286 
287  TTTestAssertion("TTBuffer load operates successfully w optional parameters",
288  result8a,
289  testAssertionCount,
290  errorCount);
291 
292  // setup pointer to samplematrix
293  TTSampleMatrixPtr myMatrix8;
294 
295  // check out samplematrix
296  TTBoolean result8b = { aBufferByAnyOtherName.checkOutMatrix(myMatrix8) == kTTErrNone };
297 
298  TTTestAssertion("TTBuffer checks out SampleMatrix successfully",
299  result8b,
300  testAssertionCount,
301  errorCount);
302 
303  // now let's test some values!
304  double testValueSoundFile8, testValueSampleMatrix8;
305  TTBoolean result8c = true;
306 
307  for (int i = 0; i<10; i++)
308  {
309  //std::cout << "let's look at index " << i << "\n";
310 
311  this->peek(i+startIndex8,copyChannel8,testValueSoundFile8);
312  myMatrix8->peek(i,copyChannel8,testValueSampleMatrix8);
313  //std::cout << "Does " << testValueSoundFile8 << " = " << testValueSampleMatrix8 << " ?\n";
314 
315  if (result8c) // allows test to keep variable false once it is false
316  result8c = TTTestFloatEquivalence(testValueSoundFile8, testValueSampleMatrix8, true, 0.0000001);
317  }
318 
319  TTTestAssertion("comparing all 10 copied values for equivalence",
320  result8c,
321  testAssertionCount,
322  errorCount);
323 
324  // check in samplematrix
325  TTBoolean result8d = { aBufferByAnyOtherName.checkInMatrix(myMatrix8) == kTTErrNone };
326 
327  TTTestAssertion("TTBuffer checks in SampleMatrix successfully",
328  result8d,
329  testAssertionCount,
330  errorCount);
331 
332  // TEST 9: load soundfile into buffer/samplematrix with different sample rate
333 
334  TTValue testChannel9in = 2;
335  TTValue testSampleRate9in = 88200;
336  TTValue testLengthSec9in = 0.25;
337 
338 
339  aBufferByAnyOtherName.set("numChannels", testChannel9in);
340  aBufferByAnyOtherName.set("sampleRate", testSampleRate9in);
341  aBufferByAnyOtherName.set("lengthInSeconds", testLengthSec9in);
342 
343  TTValue loadInput9 = TT(testSoundPath); // we cannot pass the naked TTString, it needs to be part of a TTValue
344 
345  // send message
346  TTBoolean result9a = { aBufferByAnyOtherName.load(loadInput9) == kTTErrNone };
347 
348  TTTestAssertion("TTBuffer load operates successfully when sample rates differ",
349  result9a,
350  testAssertionCount,
351  errorCount);
352 
353  // setup pointer to samplematrix
354  TTSampleMatrixPtr myMatrix9;
355 
356  // check out samplematrix
357  TTBoolean result9b = { aBufferByAnyOtherName.checkOutMatrix(myMatrix9) == kTTErrNone };
358 
359  TTTestAssertion("TTBuffer checks out SampleMatrix successfully",
360  result9b,
361  testAssertionCount,
362  errorCount);
363 
364  TTValue testChannel9, testSampleCount9, testSampleRate9;
365  myMatrix9->getAttributeValue("numChannels", testChannel9);
366  myMatrix9->getAttributeValue("lengthInSamples", testSampleCount9);
367  myMatrix9->getAttributeValue("sampleRate", testSampleRate9);
368 
369  /*std::cout << "Samplematrix has " << TTInt32(testChannel9) << " channels & " << TTInt32(testSampleCount9) << " samples @ " << TTInt32(testSampleRate9) << " Hz\n";*/
370 
371  // check out samplematrix
372  TTBoolean result9c = { TTInt32(testChannel9) == TTInt32(testChannel9in) &&
373  TTInt32(testSampleRate9) == TTInt32(testSampleRate9in) &&
374  TTInt32(testSampleCount9) == (TTInt32(testSampleRate9in) * TTFloat64(testLengthSec9in)) };
375 
376  TTTestAssertion("SampleMatrix has same attributes set via TTBuffer",
377  result9c,
378  testAssertionCount,
379  errorCount);
380 
381 
382  // let's test some values
383  int randomIndex9, randomChannel9;
384  TTSampleValue testSoundFileValue9, testSampleMatrixValue9;
385  TTBoolean result9d = true;
386 
387  for (int i = 0; i<10; i++)
388  {
389  randomIndex9 = int(testSampleCount9) * TTRandom64();
390  randomChannel9 = i % TESTNUMCHANNELS;
391  //std::cout << "let's look at index " << randomIndex9 << " & channel " << randomChannel9 << "\n";
392 
393  this->peeki(float(randomIndex9)/2.0, randomChannel9, testSoundFileValue9);
394  myMatrix9->peek(randomIndex9, randomChannel9, testSampleMatrixValue9);
395  //std::cout << "Does " << testSoundFileValue9 << " = " << testSampleMatrixValue9 << " ?\n";
396 
397  if (result9d) // allows test to keep variable false once it is false
398  result9d = TTTestFloatEquivalence(testSoundFileValue9, testSampleMatrixValue9, true, 0.0000001);
399  }
400 
401  TTTestAssertion("comparing values @ 10 random indexes for equivalence",
402  result9d,
403  testAssertionCount,
404  errorCount);
405 
406  // check in samplematrix
407  TTBoolean result9e = { aBufferByAnyOtherName.checkInMatrix(myMatrix9) == kTTErrNone };
408 
409  TTTestAssertion("TTBuffer checks in SampleMatrix successfully",
410  result9e,
411  testAssertionCount,
412  errorCount);
413 
414  // TEST 10: use resizeThenLoad message and test that TTSampleMatrix conforms to sound file loaded
415 
416  TTAudioBuffer bufferForTest10(1,1); // start by making the buffer really tiny
417 
418  TTValue loadInput10 = TT(testSoundPath);
419 
420  // send message
421  TTBoolean result10a = { bufferForTest10.resizeThenLoad(loadInput10) == kTTErrNone };
422 
423  TTTestAssertion("TTBuffer resizeThenLoad operates successfully",
424  result10a,
425  testAssertionCount,
426  errorCount);
427 
428  // setup pointer to samplematrix
429  TTSampleMatrixPtr myMatrix10;
430 
431  // check out samplematrix
432  TTBoolean result10b = { bufferForTest10.checkOutMatrix(myMatrix10) == kTTErrNone };
433 
434  TTTestAssertion("TTBuffer checks out SampleMatrix successfully",
435  result10b,
436  testAssertionCount,
437  errorCount);
438 
439  // do some more tests here
440  TTValue testChannel10, testLengthSec10, testLengthSample10;
441  myMatrix10->getAttributeValue("numChannels", testChannel10);
442  myMatrix10->getAttributeValue("lengthInSeconds", testLengthSec10);
443  myMatrix10->getAttributeValue("lengthInSamples", testLengthSample10);
444 
445  /*std::cout << "Samplematrix has " << TTInt32(testChannel10) << " channels & " << TTInt32(testLengthSample10) << " samples and is " << TTFloat64(testLengthSec10) << " secs long\n";*/
446 
447  TTBoolean result10c = { TTInt32(testChannel10) == TESTNUMCHANNELS &&
448  TTInt32(testLengthSample10) == TESTDURATIONINSAMPLES };
449 
450  TTTestAssertion("TTBuffer.resizeThenLoad results in properly sized TTSampleMatrix",
451  result10c,
452  testAssertionCount,
453  errorCount);
454 
455  // check in samplematrix
456  TTBoolean result10e = { bufferForTest10.checkInMatrix(myMatrix10) == kTTErrNone };
457 
458  TTTestAssertion("TTBuffer checks in SampleMartix successfully",
459  result10e,
460  testAssertionCount,
461  errorCount);
462 
463  } catch (...) {
464  TTTestAssertion("FAILED to run tests -- likely that necessary objects did not instantiate",
465  0,
466  testAssertionCount,
467  errorCount);
468 
469  }
470 
471  return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
472 }
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
An inappropriate value was specified for an attribute or variable.
Definition: TTBase.h:349
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
Wrap TTBuffer instances for convenience.
Definition: TTBuffer.h:199
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTErr copyUntilFilled()
Internal method that copies values from the source TTSoundfile to the targetted TTSampleMatrix.
TTErr peek(const TTRowID frame, const TTColumnID channel, TTSampleValue &value)
Get the value stored at a specified frame and channel.
TTErr getAttributeValue(const TTSymbol name, TTValue &value)
Get an attribute value for an object.
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
Container object that holds some audio in a chunk of memory.
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
TTErr setFilePath(const TTValue &newValue)
Atribute accessor.
TTString substr(size_t pos=0, size_t n=1) const
Returns a string object with its contents initialized to a substring of the current object...
Definition: TTString.h:342
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
virtual TTErr test(TTValue &returnedTestInfo)
Unit test for this object.
size_t find_last_of(const char aChar)
Return the index of the last instance of a specified char in the string.
Definition: TTString.h:316
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTErr peeki(const TTFloat64 frame, const TTColumnID channel, TTSampleValue &value)
Interpolate a value using a floating-point frame and integer channel.
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
TTErr setTargetMatrix(const TTMatrix newTargetMatrix)
Internal method that sets the class's pointer to the target sample matrix for loading sound file data...
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
TTBuffer manages the check-in/out of TTSampleMatrix pointers.
TTFloat64 TTSampleValue
A value representing a single audio sample.
Definition: TTBase.h:230
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
Loads soundfile data into a sample matrix.
TTFOUNDATION_EXPORT TTFloat64 TTRandom64()
Produces a random-valued 64-bit floating-point number in the range [0.0, 1.0].
Definition: TTBase.cpp:611