Jamoma API  0.6.0.a19
TTAudioSignal.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspLibrary
4  *
5  * @brief Represents M channels containing N vectors of audio samples.
6  *
7  * @details TODO: put more info here
8  *
9  * @authors Tim Place
10  *
11  * @copyright Copyright © 2008 by Timothy Place @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 #include "TTDSP.h"
17 
18 #define thisTTClass TTAudioSignal
19 #define thisTTClassName "audiosignal"
20 #define thisTTClassTags "dspLibrary, audio, processor, dynamics, envelope"
21 
22 
23 /****************************************************************************************************/
24 
26  mIsLocallyOwned(false),
27  mMaxNumChannels(0),
28  mVectorSize(0),
29  mNumChannels(0),
30  mBitdepth(0),
31  mSampleRate(0),
32  mSampleVectors(NULL)
33 {
34  TTChannelCount initialMaxNumChannels = arguments;
35 
36  addAttributeWithSetter( VectorSize, kTypeUInt16);
37  addAttributeWithSetter( NumChannels, kTypeUInt16);
38  addAttributeWithSetter( MaxNumChannels, kTypeUInt16);
39  addAttribute( Bitdepth, kTypeUInt8);
40  addAttributeProperty( Bitdepth, readOnly, 1);
41 
42  addMessage(clear);
43 
44  addMessage(alloc);
45  addMessageWithArguments(allocWithNewVectorSize);
46 // addMessageWithArguments(setVector32);
47 // addMessageWithArguments(getVector32);
48 // addMessageWithArguments(setVector64);
49 // addMessageWithArguments(getVector64);
50 
51  addMessageProperty(alloc, hidden, YES);
52  addMessageProperty(allocWithNewVectorSize, hidden, YES);
53 // addMessageProperty(setVector32, hidden, YES);
54 // addMessageProperty(getVector32, hidden, YES);
55 // addMessageProperty(setVector64, hidden, YES);
56 // addMessageProperty(getVector64, hidden, YES);
57 
58  setAttributeValue(kTTSym_maxNumChannels, initialMaxNumChannels);
59  setAttributeValue(kTTSym_numChannels, initialMaxNumChannels);
60 }
61 
62 
64  TTDataObjectBase(kTTValNONE),
65  mIsLocallyOwned(original.mIsLocallyOwned),
66  mMaxNumChannels(0),
67  mVectorSize(0),
68  mNumChannels(0),
69  mBitdepth(0),
70  mSampleRate(0),
71  mSampleVectors(NULL)
72 {
73  addAttributeWithSetter( VectorSize, kTypeUInt16);
74  addAttributeWithSetter( NumChannels, kTypeUInt16);
75  addAttributeWithSetter( MaxNumChannels, kTypeUInt16);
76  addAttribute( Bitdepth, kTypeUInt8);
77  addAttributeProperty( Bitdepth, readOnly, 1);
78 
80 
82  addMessageWithArguments(allocWithNewVectorSize);
83 
84  addMessageProperty(alloc, hidden, YES);
85  addMessageProperty(allocWithNewVectorSize, hidden, YES);
86 
87 // setAttributeValue(kTTSym_maxNumChannels, original.maxNumChannels);
88 // setAttributeValue(kTTSym_numChannels, original.mNumChannels);
89  (*this) = original;
90 }
91 
92 
93 TTAudioSignal::~TTAudioSignal()
94 {
95  chuck();
96 }
97 
98 
99 void TTAudioSignal::chuck()
100 {
101  TTUInt32 i;
102 
103  if (mIsLocallyOwned) {
104  for (i=0; i<mMaxNumChannels; i++) {
106  mSampleVectors[i] = NULL;
107  }
108  mIsLocallyOwned = false;
109  }
111  mMaxNumChannels = 0;
112  mSampleVectors = NULL;
113 }
114 
115 
117 {
118  TTUInt32 i;
119  TTBoolean wasLocallyOwned = mIsLocallyOwned;
120  TTChannelCount newMaxNumChannels = newValue;
121 
122  TTLimitMin<TTChannelCount>(newMaxNumChannels, 1);
123  if (TTChannelCount(newMaxNumChannels) != mMaxNumChannels) {
124  chuck();
125  mMaxNumChannels = newMaxNumChannels;
126  if (mMaxNumChannels) {
127  mSampleVectors = (TTSampleValue**)TTMalloc16(sizeof(TTSampleValue*) * mMaxNumChannels);
128  for (i=0; i<mMaxNumChannels; i++)
129  mSampleVectors[i] = NULL;
130  }
131  if (wasLocallyOwned)
132  alloc();
133  }
134  return kTTErrNone;
135 }
136 
137 
138 TTChannelCount TTAudioSignal::getMaxNumChannelsAsInt()
139 {
140  return mMaxNumChannels;
141 }
142 
143 
144 TTErr TTAudioSignal::setVector(const TTChannelCount channel, const TTUInt16 newVectorSize, const TTSampleValuePtr newVector)
145 {
146  TTUInt32 i;
147 
148  // could check against maxnumchannels here
149 
150  mBitdepth = 64;
151  mVectorSize = newVectorSize;
152 
153  if (mIsLocallyOwned) {
154  for (i=0; i<mMaxNumChannels; i++) {
156  mSampleVectors[i] = NULL;
157  }
158  mIsLocallyOwned = false;
159  }
160  mSampleVectors[channel] = newVector;
161  return kTTErrNone;
162 }
163 
164 /*
165 TTErr TTAudioSignal::setVector64(const TTValue& v, TTValue&)
166 {
167  TTChannelCount channel;
168  TTUInt16 newVectorSize;
169  TTPtr newVector;
170 
171  if (v.size() == 3) {
172  channel = v[0];
173  newVectorSize = v[1];
174  newVector = v[2];
175 // v.get(0, channel);
176 // v.get(1, newVectorSize);
177 // v.get(2, &newVector);
178  return setVector(channel, newVectorSize, (TTSampleValue*)(newVector));
179  }
180  return kTTErrWrongNumValues;
181 }
182  */
183 
184 TTErr TTAudioSignal::setVector64Copy(const TTChannelCount channel, const TTUInt16 vectorSize, const TTSampleValuePtr newVector)
185 {
186  if (mBitdepth != 64 || !mIsLocallyOwned || vectorSize != mVectorSize) {
187  mBitdepth = 64;
188  mVectorSize = vectorSize;
189  alloc();
190  }
191  memcpy(mSampleVectors[channel], newVector, sizeof(TTSampleValue) * mVectorSize);
192 
193  return kTTErrNone;
194 }
195 
196 /*
197  It sucks if someone sets a 32-bit audio vector, since we have translate it into a 64-bit buffer.
198  There may be a better way to do this...
199 
200  For now, we don't simply reference the data passed in. Instead we allocate our own buffer and copy the data.
201  Unfortunately, this is very slow.
202 
203  Also note that we are relying on the vector size already being set!
204 
205  If we passed the vs in to this method, we could avoid having to realloc the memory every single time.
206  This would probably be a very good idea.
207 */
208 TTErr TTAudioSignal::setVector(const TTChannelCount channel, const TTUInt16 newVectorSize, const TTFloat32* newVector)
209 {
210  TTUInt32 i;
211 
212  // 1. could check against maxnumchannels here
213 
214  // 2. allocate the vector if need be
215  if (mBitdepth != 32 || !mIsLocallyOwned || newVectorSize != mVectorSize) {
216  mBitdepth = 32;
217  mVectorSize = newVectorSize;
218  alloc();
219  }
220 
221  // 3. copy the vector (from 32-bits to 64-bits)
222  for (i=0; i<mVectorSize; i++)
223  mSampleVectors[channel][i] = newVector[i];
224 
225  return kTTErrNone;
226 }
227 
228 
229 TTErr TTAudioSignal::getVectorCopy(const TTChannelCount channel, const TTUInt16 theVectorSize, TTSampleValue* returnedVector)
230 {
231  TTUInt16 i;
232 
233  for (i=0; i<theVectorSize; i++)
234  returnedVector[i] = mSampleVectors[channel][i];
235  return kTTErrNone;
236 }
237 
238 
239 
240 TTErr TTAudioSignal::getVector(const TTChannelCount channel, const TTUInt16 theVectorSize, TTFloat32* returnedVector)
241 {
242  TTUInt16 i;
243 
244  for (i=0; i<theVectorSize; i++)
245  returnedVector[i] = (TTFloat32)mSampleVectors[channel][i];
246  return kTTErrNone;
247 }
248 
249 
251 {
252  TTUInt32 i;
253  if (mIsLocallyOwned) {
254  for (i=0; i<mMaxNumChannels; i++) {
256  mSampleVectors[i] = NULL;
257  }
258  }
259 
260  for (i=0; i<mMaxNumChannels; i++) {
261  mSampleVectors[i] = (TTSampleValue*)TTMalloc16(sizeof(TTSampleValue) * mVectorSize);
262  }
263  mIsLocallyOwned = mMaxNumChannels > 0 ? true : false;
264  // we can't do this here! we are called by the setVector method for 32bit signals!
265  //bitdepth = 64;
266  return kTTErrNone;
267 }
268 
269 
271 {
272  if (newChannelCount < mMaxNumChannels) // we don't both allocating memory for fewer channels, only when more channels are requested
273  return kTTErrNone;
274 
275  TTLimitMin<TTChannelCount>(newChannelCount, 1); // limit minimum number of channels to 1
276 
277  // Alloc new memory for the array of channels
278  TTSampleValue** newSampleVectors = (TTSampleValue**)TTMalloc16(sizeof(TTSampleValue*) * newChannelCount);
279 
280  for (int i=0; i<newChannelCount; i++) { // alloc a vector for each channel
281  newSampleVectors[i] = (TTSampleValue*)TTMalloc16(sizeof(TTSampleValue) * mVectorSize);
282  if (i < mMaxNumChannels) // copy the contents from the existing audio signal
283  memcpy(newSampleVectors[i], mSampleVectors[i], sizeof(TTSampleValue) * mVectorSize);
284  else
285  memset(newSampleVectors[i], 0, sizeof(TTSampleValue) * mVectorSize);
286  }
287 
288  // Switch the pointers for our object to the new channels and free the old memory afterward
289  TTSampleValue** oldSampleVectors = mSampleVectors;
290  int oldChannelCount = mMaxNumChannels;
291 
292  mSampleVectors = newSampleVectors;
293  mMaxNumChannels = newChannelCount;
294  mNumChannels = newChannelCount;
295 
296  for (int i=0; i<oldChannelCount; i++) {
297  TTFree16(oldSampleVectors[i]);
298  oldSampleVectors[i] = NULL;
299  }
300  TTFree16(oldSampleVectors);
301 
302  mIsLocallyOwned = true;
303  return kTTErrNone;
304 }
305 
306 
307 
309 {
310  // NOTE: we once tried removing the check for !mIsLocallyOwned
311  // doing so causes Plugtastic plug-ins to crash in auval
312  if ((newVectorSize != mVectorSize) || !mIsLocallyOwned) {
313  mVectorSize = newVectorSize;
314  return alloc();
315  }
316  else
317  return kTTErrNone;
318 }
319 
320 TTErr TTAudioSignal::allocWithNewVectorSize(const TTValue& newVectorSize, TTValue&)
321 {
322  return allocWithVectorSize(TTUInt16(newVectorSize));
323 }
324 
325 
327 {
328  dest.chuck(); // sets isLocallyOwned to false
329  dest.mSampleVectors = source.mSampleVectors;
330 
331  dest.mVectorSize = source.mVectorSize;
332  dest.mMaxNumChannels = source.mMaxNumChannels;
333  dest.mNumChannels = source.mNumChannels;
334  dest.mBitdepth = source.mBitdepth;
335  dest.mSampleRate = source.mSampleRate;
336 
337  return kTTErrNone;
338 }
339 
340 
342 {
343  TTUInt16 vs;
344  TTSampleValue* inSample;
345  TTSampleValue* outSample;
346  TTChannelCount maxDestChannels = dest.mMaxNumChannels;
347  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(source, dest);
348  TTChannelCount additionalOutputChannels = dest.mNumChannels - numchannels;
349  TTChannelCount channel;
350 
351  for (channel=0; channel<numchannels; channel++) {
352  inSample = source.mSampleVectors[channel];
353  outSample = dest.mSampleVectors[ TTClip(channel+channelOffset, 0, maxDestChannels-1) ];
354  vs = source.getVectorSizeAsInt();
355  //while (vs--)
356  // *outSample++ = *inSample++;
357 
358  memcpy(outSample, inSample, sizeof(TTSampleValue) * vs);
359  }
360  for (/*channel*/; channel<(numchannels+additionalOutputChannels-channelOffset); channel++) {
361  outSample = dest.mSampleVectors[channel];
362  vs = dest.getVectorSizeAsInt();
363  memset(outSample, 0, sizeof(TTSampleValue) * vs);
364  //while (vs--)
365  // *outSample++ = 0.0;
366  }
367  return kTTErrNone;
368 }
369 
370 
372 {
373  TTUInt16 vs;
374  TTSampleValue* inSample;
375  TTSampleValue* outSample;
376  TTChannelCount maxDestChannels = dest.mMaxNumChannels;
377  TTChannelCount numchannels = TTAudioSignal::getMinChannelCount(source, dest);
378  TTChannelCount channel;
379 
380  for (channel=0; channel<numchannels; channel++) {
381  inSample = source.mSampleVectors[channel];
382  outSample = dest.mSampleVectors[ TTClip(channel+channelOffset, 0, maxDestChannels-1) ];
383  vs = source.getVectorSizeAsInt();
384  //while (vs--)
385  // *outSample++ = *inSample++;
386  memcpy(outSample, inSample, sizeof(TTSampleValue) * vs);
387  }
388  return kTTErrNone;
389 }
390 
391 
392 TTErr TTAudioSignal::copySubset(const TTAudioSignal& source, TTAudioSignal& dest, TTChannelCount startingChannel, TTChannelCount endingChannel)
393 {
394  TTUInt16 vs;
395  TTSampleValue* inSample;
396  TTSampleValue* outSample;
397  TTChannelCount sourceChannel;
398  TTChannelCount destChannel;
399 
400  for (sourceChannel=startingChannel, destChannel=0; sourceChannel<=endingChannel; sourceChannel++, destChannel++) {
401  inSample = source.mSampleVectors[sourceChannel];
402  outSample = dest.mSampleVectors[destChannel];
403  vs = source.getVectorSizeAsInt();
404  //while (vs--)
405  // *outSample++ = *inSample++;
406  memcpy(outSample, inSample, sizeof(TTSampleValue) * vs);
407  }
408  return kTTErrNone;
409 }
410 
411 TTChannelCount TTAudioSignal::getMaxChannelCount(const TTAudioSignal& signal1, const TTAudioSignal& signal2)
412 {
413  if (signal1.mNumChannels < signal2.mNumChannels)
414  return signal2.mNumChannels;
415  else
416  return signal1.mNumChannels;
417 }
418 
419 TTChannelCount TTAudioSignal::getMaxChannelCount(const TTAudioSignal& signal1, const TTAudioSignal& signal2, const TTAudioSignal& signal3)
420 {
421  TTChannelCount numChannels = signal1.mNumChannels;
422 
423  if (signal2.mNumChannels > numChannels)
424  numChannels = signal2.mNumChannels;
425  if (signal3.mNumChannels > numChannels)
426  numChannels = signal3.mNumChannels;
427 
428  return numChannels;
429 }
430 
431 
433 {
434  return signal.mNumChannels;
435 }
436 
437 
438 // TODO: implement fill() method --- SET ALL VALUES IN THE SIGNAL TO A CONSTANT
439 
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
void TTFOUNDATION_EXPORT TTFree16(TTPtr ptr)
Free memory allocated using TTMalloc16().
Definition: TTBase.cpp:647
TTErr allocWithNewChannelCount(TTChannelCount newChannelCount)
Allocate memory for a given number of channels, setting MaxChannelCount, at the current vector size...
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
static TTErr copySubset(const TTAudioSignal &source, TTAudioSignal &dest, TTChannelCount startingChannel=0, TTChannelCount endingChannel=0)
Copy the audio from one signal into another.
8-bit unsigned integer, range is 0 through 255.
Definition: TTBase.h:274
static TTErr copyDirty(const TTAudioSignal &source, TTAudioSignal &dest, TTChannelCount channelOffset=0)
Copy the audio from one signal into another, but not taking care to zero channels that aren't used...
TTPtr TTFOUNDATION_EXPORT TTMalloc16(size_t numBytes)
Allocate memory from the heap aligned to 16-byte boundaries.
Definition: TTBase.cpp:641
TTDataObjectBase is the base class for all data generating and processing objects.
Jamoma DSP Library.
static TTChannelCount getNumChannels(const TTAudioSignal &signal)
Use this class method to determine the number of channels of an input or output signal.
16-bit unsigned integer, range is 0 through 65,535.
Definition: TTBase.h:276
TTErr setVector(const TTChannelCount channel, const TTUInt16 vectorSize, const TTSampleValuePtr newVector)
[doxygenAppendixC_methodExample]
TTErr clear()
Zero out all of the sample values in the audio signal.
TTErr setMaxNumChannels(const TTValue &newMaxNumChannels)
Attribute accessor.
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
Definition: TTAttribute.h:68
float TTFloat32
32 bit floating point number
Definition: TTBase.h:187
static TTChannelCount getMinChannelCount(const TTAudioSignal &signal1, const TTAudioSignal &signal2)
Use this class method to determine the least number of channels the two signals have in common...
The TTAudioSignal class represents N vectors of audio samples for M channels.
Definition: TTAudioSignal.h:57
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
TTSampleValue ** mSampleVectors
An array of pointers to the first sample in each vector. Declared Public for fast access...
Definition: TTAudioSignal.h:74
TTUInt16 TTChannelCount
Data type used when counting the number of channels in multi-channel audio signals and processes...
Definition: TTAudioSignal.h:31
static TTErr reference(const TTAudioSignal &source, TTAudioSignal &dest)
Reference the audio from one signal in another.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTErr setVector64Copy(const TTChannelCount channel, const TTUInt16 vectorSize, const TTSampleValuePtr newVector)
[doxygenAppendixC_methodExample]
TTAudioSignal(const TTAudioSignal &original)
Copy constructor.
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
Definition: TTAttribute.h:47
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
No Error.
Definition: TTBase.h:343
static TTErr copy(const TTAudioSignal &source, TTAudioSignal &dest, TTChannelCount channelOffset=0)
Copy the audio from one signal into another.
TTErr allocWithVectorSize(const TTUInt16 newVectorSize)
Allocate memory for all channels at the specified vectorsize, if the vectorsize is different from the...
TT_OBJECT_CONSTRUCTOR
Constructor macro.
TTFloat64 TTSampleValue
A value representing a single audio sample.
Definition: TTBase.h:230
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr alloc()
Allocate memory for all channels at the current vectorsize.
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37