Jamoma API  0.6.0.a19
TTSoundfileLoader.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspSoundFileLib
4  *
5  * @brief Loads soundfile data into a sample matrix
6  *
7  * @details This object collaborates with #TTSampleMatrix to load values from a sound file into the sample matrix.
8  *
9  * @see TTSampleMatrix
10  *
11  * @authors Nathan Wolek
12  *
13  * @copyright Copyright © 2013 by Nathan Wolek @n
14  * This code is licensed under the terms of the "New BSD License" @n
15  * http://creativecommons.org/licenses/BSD/
16  */
17 
18 #include "TTSoundfileLoader.h"
19 
20 #define thisTTClass TTSoundfileLoader
21 #define thisTTClassName "soundfile.loader"
22 #define thisTTClassTags "dspSoundFileLib, audio, soundfile, buffer"
23 
24 TTObjectBasePtr TTSoundfileLoader::instantiate(TTSymbol name, TTValue arguments)
25 {
26  return new TTSoundfileLoader(arguments);
27 }
28 
29 
30 extern "C" void TTSoundfileLoader::registerClass()
31 {
32  TTClassRegister(thisTTClassName, thisTTClassTags, TTSoundfileLoader::instantiate);
33 }
34 
35 
36 TTSoundfileLoader::TTSoundfileLoader(const TTValue& arguments) :
37  TTSoundfile(arguments),
38  mTargetMatrix(NULL)
39 {
40  this->mTargetMatrixLengthInSamples = 0;
41  this->mTargetMatrixNumChannels = 0;
42  this->mTargetMatrixSampleRate = 0.;
43  this->mStartCopyAtSampleIndex = 0;
44  this->mEndCopyAtSampleIndex = 0;
45  this->mCopyFromChannelIndex = 0;
46 
47  // add the attributes and messages here
49  addMessageWithArguments(resizeThenLoad);
50 
51  // initialize happens as part of the load
52 }
53 
54 TTSoundfileLoader::~TTSoundfileLoader()
55 {
56  mTargetMatrix = NULL; // reset to NULL for reference counting
57 }
58 
59 // target a new TTSampleMatrix
61 {
62  TTErr err = kTTErrNone;
63 
64  mTargetMatrix = (TTSampleMatrixPtr)newTargetMatrix.instance();
65  mTargetMatrixLengthInSamples = newTargetMatrix.getRowCount();
66  mTargetMatrixNumChannels = newTargetMatrix.getColumnCount();
67  newTargetMatrix.get("sampleRate", mTargetMatrixSampleRate);
68 
69  return err;
70 }
71 
72 // target a new TTObjectBase if it proves to be a TTSampleMatrix
74 {
75  TTSampleMatrixPtr newTargetMatrix = NULL;
76 
77  if (newTargetObjectPtr->getName() != TT("samplematrix"))
78  {
79  return kTTErrInvalidValue;
80  } else {
81  // get a generic TTPtr, then cast to TTSampleMatrixPtr
82  newTargetMatrix = (TTSampleMatrixPtr)(TTPtr(newTargetObjectPtr));
83  return setTargetMatrix(newTargetMatrix);
84  }
85 }
86 
87 // copy values from sound file until TTSampleMartix is completely full.
89 {
90  // NOTE: this method assumes that sampleRates match.
91  // we are using class variables in the code here.
92 
93  if ((mEndCopyAtSampleIndex - mStartCopyAtSampleIndex) < mTargetMatrixLengthInSamples)
94  {
95  // if the soundfile is shorter than the samplemartix...
96  // we will throw an error because we are only interested in completely filling the SampleMartix, for now
97  return kTTErrGeneric;
98  } else {
99  // if the soundfile is longer than the samplemartix...
100  TTSampleValue valueToMove;
101 
102  // to deal with multi-channel differences, we copy the minimum
103  // number of channels present in either the source or target
104  TTColumnID numChannelsToCopy = std::min(mTargetMatrixNumChannels, this->getNumChannels());
105  numChannelsToCopy = std::min(numChannelsToCopy, (this->getNumChannels() - mCopyFromChannelIndex));
106  //TTTestLog("we will copy %i channels", numChannelsToCopy);
107 
108  for (TTRowID sample=0;sample<mTargetMatrixLengthInSamples;sample++)
109  {
110  for (TTColumnID channel=0; channel<numChannelsToCopy; channel++)
111  {
112 
113  this->peek( (sample + mStartCopyAtSampleIndex),
114  (channel + mCopyFromChannelIndex),
115  valueToMove);
116  //TTTestLog("peek sample %i returned the value %f", sample, valueToMove);
117 
118  mTargetMatrix->poke( sample,
119  channel,
120  valueToMove);
121  }
122  }
123 
124  return kTTErrNone;
125  }
126 }
127 
128 // copy values from sound file into TTSampleMartix with a different sampleRate until it is completely full.
130 {
131  // NOTE: this method does not assumes that sampleRates match.
132  // we are using class variables in the code here.
133 
134  TTFloat64 targetToSourceFactor = this->mSampleRate/mTargetMatrixSampleRate;
135  TTFloat64 sourceToTargetFactor = mTargetMatrixSampleRate/this->mSampleRate;
136 
137  if (((mEndCopyAtSampleIndex - mStartCopyAtSampleIndex) * sourceToTargetFactor) < mTargetMatrixLengthInSamples)
138  {
139  // if the soundfile is shorter than the samplemartix...
140  // we will throw an error because we are only interested in completely filling the SampleMartix, for now
141  return kTTErrGeneric;
142  } else {
143  // if the soundfile is longer than the samplemartix...
144  TTSampleValue valueToMove;
145  TTFloat64 sourceFloatIndex;
146 
147  // to deal with multi-channel differences, we copy the minimum
148  // number of channels present in either the source or target
149  TTColumnID numChannelsToCopy = std::min(mTargetMatrixNumChannels, this->getNumChannels());
150  numChannelsToCopy = std::min(numChannelsToCopy, (this->getNumChannels() - mCopyFromChannelIndex));
151  //TTTestLog("we will copy %i channels", numChannelsToCopy);
152 
153  for ( TTRowID targetIndex=0;
154  targetIndex<mTargetMatrixLengthInSamples;
155  targetIndex++ )
156  {
157 
158  sourceFloatIndex = mStartCopyAtSampleIndex +
159  (targetIndex * targetToSourceFactor);
160 
161  for (TTColumnID channel=0; channel<numChannelsToCopy; channel++)
162  {
163 
164  this->peeki( sourceFloatIndex,
165  (channel + mCopyFromChannelIndex),
166  valueToMove);
167  //TTTestLog("peek sample %i returned the value %f", sample, valueToMove); // temp
168 
169  mTargetMatrix->poke( targetIndex,
170  channel,
171  valueToMove);
172  }
173  }
174 
175  return kTTErrNone;
176  }
177 }
178 
179 // override this method from superclass to set additional parameters
181 {
182  TTErr err = kTTErrNone;
183 
184  err = TTSoundfile::setFilePath(newValue);
185  this->mStartCopyAtSampleIndex = 0;
186  if (!err)
187  {
188  this->mEndCopyAtSampleIndex = this->getLengthInSamples();
189  } else {
190  this->mEndCopyAtSampleIndex = 0;
191  }
192  this->mCopyFromChannelIndex = 0;
193 
194  return err;
195 }
196 
197 
198 // load new sound file into a SampleMatrix
199 TTErr TTSoundfileLoader::load(const TTValue& input, TTValue& unusedOutput)
200 {
201  // sort out the two input values
202  TTMatrix newTargetMatrix = input[0];
203  TTSymbol newFilePath = input[1];
204  TTErr err = kTTErrNone;
205 
206  // set the mTargetMatrix
207  err = setTargetMatrix(newTargetMatrix);
208 
209  // set the mFilePath, which also sets default values for
210  // mStartCopyAtSampleIndex, mEndCopyAtSampleIndex & mCopyFromChannelIndex
211  if (!err)
212  err = setFilePath(newFilePath);
213 
214  // set optional input parameters
215  if (!err)
216  {
217  if (input.size() > 2) mCopyFromChannelIndex = input[2];
218  if (input.size() > 3) mStartCopyAtSampleIndex = input[3];
219  if (input.size() > 4) mEndCopyAtSampleIndex = input[4];
220  }
221 
222  if (!err)
223  {
224  // compare sample rates
225  TTBoolean sameSampleRate = TTTestFloatEquivalence(mTargetMatrixSampleRate, this->mSampleRate, true, 0.0000001);
226 
227  if (sameSampleRate)
228  {
229  // copy the samples (one at a time initially, could be optimized later)
230  err = copyUntilFilled();
231  } else {
232  // copy the samples with resampling (one at a time initially, could be optimized later)
234  }
235  }
236 
237  // reset? should mFilePath & mTargetMatrix be reset at the conclusion?
238 
239  return err;
240 }
241 
242 // load new sound file into a SampleMatrix, but resize target first
244 {
245  // sort out the two input values
246  TTMatrix newTargetMatrix = input[0];
247  TTSymbol newFilePath = input[1];
248  TTErr err = kTTErrNone;
249 
250  // set the mTargetMatrix
251  err = setTargetMatrix(newTargetMatrix);
252 
253  // set the mFilePath, which also sets default values for
254  // mStartCopyAtSampleIndex, mEndCopyAtSampleIndex & mCopyFromChannelIndex
255  if (!err)
256  err = setFilePath(newFilePath);
257 
258  // resize target to match source
259  if (!err)
260  {
261  TTUInt32 newNumChannels = this->getNumChannels(); // needed to avoid 'ambiguity' errors
262  mTargetMatrix->setAttributeValue("numChannels",newNumChannels);
263  mTargetMatrix->setAttributeValue("lengthInSeconds",this->getLengthInSeconds());
264  // we do NOT change the sample rate
265  /*std::cout << "this part of the code ran " << this->getNumChannels() << " " << this->getLengthInSeconds() << "\n";*/
266  }
267 
268  if (!err)
269  {
270  // compare sample rates
271  TTBoolean sameSampleRate = TTTestFloatEquivalence(mTargetMatrixSampleRate, this->mSampleRate, true, 0.0000001);
272 
273  if (sameSampleRate)
274  {
275  // copy the samples (one at a time initially, could be optimized later)
276  err = copyUntilFilled();
277  } else {
278  // copy the samples with resampling (one at a time initially, could be optimized later)
280  }
281  }
282 
283  // reset? should mFilePath & mTargetMatrix be reset at the conclusion?
284 
285  return err;
286 }
TTErr load(const TTValue &input, TTValue &unusedOutput)
Public method used to trigger the load process.
TTErr copyUntilFilledWithResampling()
Internal method that copies values from the source TTSoundfile to the targetted TTSampleMatrix with t...
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
Creates an interface to data in a soundfile from disk.
TTRowID getLengthInSamples()
Simple data accessor.
Definition: TTSoundfile.h:71
TTFloat64 mSampleRate
samples per second
Definition: TTSoundfile.h:36
TTSymbol getName() const
Return the name of this class.
size_type size() const noexcept
Return the number of elements.
TTInt32 TTColumnID
Datatype for any number used to indicate a column index within the matrix.
Definition: TTBase.h:216
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.
TTMatrixBase * instance() const
Get a pointer to the wrapped TTMatrixBase instance.
Definition: TTMatrix.h:37
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
TTInt32 TTRowID
Datatype for any number used to indicate a row index within a matrix.
Definition: TTBase.h:207
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
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
Container object that holds some audio in a chunk of memory.
TTRowID getRowCount() const
Number of rows in the matrix.
Definition: TTMatrix.cpp:42
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTColumnID getColumnCount() const
Number of columns in the matrix.
Definition: TTMatrix.cpp:48
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTColumnID getNumChannels()
Simple data accessor.
Definition: TTSoundfile.h:57
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
TTErr setFilePath(const TTValue &newValue)
Atribute accessor.
Wrap TTMatrixBase instances.
Definition: TTMatrix.h:27
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTFloat64 getLengthInSeconds()
Simple data accessor.
Definition: TTSoundfile.h:78
TTErr resizeThenLoad(const TTValue &input, TTValue &unusedOutput)
Public method similar to load(), except that it will resize the target matrix to match the source sou...
Creates an interface to data in a soundfile from disk.
Definition: TTSoundfile.h:30
TTErr setFilePath(const TTValue &newValue)
Atribute accessor.
Definition: TTSoundfile.cpp:68
TTErr peeki(const TTFloat64 frame, const TTColumnID channel, TTSampleValue &value)
Interpolate a value using a floating-point frame and integer channel.
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
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.