Jamoma API  0.6.0.a19
TTMultiMixer.cpp
1 /*
2  * DSP Multi-Signal Mixer Object
3  * Copyright © 2009, Timothy Place
4  *
5  * License: This code is licensed under the terms of the "New BSD License"
6  * http://creativecommons.org/licenses/BSD/
7  */
8 
9 #include "TTMultiMixer.h"
10 #ifdef TT_PLATFORM_WIN
11 #include <algorithm>
12 #endif
13 
14 #define thisTTClass TTMultiMixer
15 #define thisTTClassName "multimixer"
16 #define thisTTClassTags "audio, mixer, matrix"
17 
18 
19 TT_AUDIO_CONSTRUCTOR,
20  mNumInputs(1),
21  mNumOutputs(1)
22 {
23 
24  addAttribute(NumInputs, kTypeUInt16);
25  addAttributeProperty(NumInputs, readOnly, TTValue(YES));
26  addAttribute(NumOutputs, kTypeUInt16);
27  addAttributeProperty(NumOutputs, readOnly, TTValue(YES));
28 
29  addMessageWithArguments(setGain);
30  addMessageWithArguments(setLinearGain);
31  addMessageWithArguments(setMidiGain);
32  //registerMessageWithArgument(updateMaxNumChannels);
33  addMessage(clear);
34 
35  //setAttributeValue(TT("MaxNumChannels"), newMaxNumChannels);
36  setProcessMethod(processAudio);
37  mGainMatrix.set("type", "float64");
38  tempGainMatrix.set("type", "float64");
39  TTValue v(1, 1); // we need to make the mGainMatrix at least 1x1 otherwise we have problems with adapting to tempGainMatrix
40  mGainMatrix.set("dimensions", v);
41  tempGainMatrix.set("dimensions", v);
42  clear();
43 }
44 
45 
46 TTMultiMixer::~TTMultiMixer()
47 {
48 }
49 
50 
51 // conceptually:
52 // columns == inputs
53 // rows == outputs
54 
55 
56 // TODO: the next two methods should never decrease their size
57 
58 TTErr TTMultiMixer::setNumInputs(const TTUInt16 newValue)
59 {
60  TTUInt16 numInputs = newValue;
61  TTValue v(numInputs, mNumOutputs);
62 
63  if (newValue != mNumInputs) {
64  TTMatrixBase::copy(*mGainMatrix.instance(), *tempGainMatrix.instance()); //1. copy mGainMtrix to tempGainMatrix;
65  mNumInputs = numInputs;
66  mGainMatrix.set("dimensions", v);
67  clear(); //2. clear mGainMatrix
68  restoreMatrix(); //3. element-wise copy tempGainMatrix content over to mGainMatrix
69  }
70  return kTTErrNone;
71 }
72 
73 
74 TTErr TTMultiMixer::setNumOutputs(const TTUInt16 newValue)
75 {
76  TTUInt16 numOutputs = newValue;
77  TTValue v(mNumInputs, numOutputs);
78 
79  if (newValue != mNumOutputs) {
80  TTMatrixBase::copy(*mGainMatrix.instance(), *tempGainMatrix.instance()); //1. copy mGainMtrix to tempGainMatrix;
81  mNumOutputs = newValue;
82  mGainMatrix.set("dimensions", v);
83  clear(); //2. clear mGainMatrix
84  restoreMatrix(); //3. element-wise copy tempGainMatrix content over to mGainMatrix
85 
86  }
87  return kTTErrNone;
88 }
89 
90 TTErr TTMultiMixer::restoreMatrix()
91 {
92 
93  TTValue v;
94  TTFloat64 tempValue;
95  TTUInt16 xx, yy;
96  tempGainMatrix.get("dimensions", v);
97  xx = v[0];
98  yy = v[1];
99  TTLimit(xx,(TTUInt16) 1, mNumInputs); // in case xx or yy is greater than the current mGainMatrix ...
100  TTLimit(yy,(TTUInt16) 1, mNumOutputs);
101  for (TTUInt16 y=0; y < yy; y++) {
102  for (TTUInt16 x=0; x < xx; x++) {
103  tempGainMatrix.get2d(x, y, tempValue);
104  mGainMatrix.set2d(x, y, tempValue);
105  }
106  }
107  return kTTErrNone;
108 }
109 
110 
111 TTErr TTMultiMixer::clear()
112 {
113  mGainMatrix.clear();
114  return kTTErrNone;
115 }
116 
117 
119 {
120  TTUInt16 x;
121  TTUInt16 y;
122  TTFloat64 gainValue;
123 
124  if (newValue.size() != 3)
125  return kTTErrWrongNumValues;
126 
127  x = newValue[0];
128  y = newValue[1];
129  gainValue = newValue[2];
130  checkMatrixSize(x,y);
131 
132  mGainMatrix.set2d(x, y, TTDecibelsToLinearGain(gainValue));
133  return kTTErrNone;
134 }
135 
136 
137 TTErr TTMultiMixer::setLinearGain(const TTValue& newValue, TTValue&)
138 {
139  TTUInt16 x;
140  TTUInt16 y;
141  TTFloat64 gainValue;
142 
143  if (newValue.size() != 3)
144  return kTTErrWrongNumValues;
145 
146 
147  x = newValue[0];
148  y = newValue[1];
149  gainValue = newValue[2];
150  checkMatrixSize(x,y);
151 
152  mGainMatrix.set2d(x, y, gainValue);
153  return kTTErrNone;
154 }
155 
156 
157 TTErr TTMultiMixer::setMidiGain(const TTValue& newValue, TTValue&e)
158 {
159  TTUInt16 x;
160  TTUInt16 y;
161  TTFloat64 gainValue;
162 
163  if (newValue.size() != 3)
164  return kTTErrWrongNumValues;
165 
166  x = newValue[0];
167  y = newValue[1];
168  gainValue = newValue[2];
169  checkMatrixSize(x,y);
170 
171  mGainMatrix.set2d(x, y, TTMidiToLinearGain(gainValue));
172  return kTTErrNone;
173 }
174 
175 TTErr TTMultiMixer::checkMatrixSize(TTUInt16 x, TTUInt16 y)
176 //this function will resize mGainMatrix if necessary while preserving its content
177 {
178  if (x > (mNumInputs-1)){
179  if (y > (mNumOutputs-1))
180  mNumOutputs = y+1;
181  setNumInputs(x+1);
182  }
183  else{
184  if (y > (mNumOutputs-1))
185  setNumOutputs(y+1);
186  }
187  return kTTErrNone;
188 }
189 
190 void TTMultiMixer::processOne(TTAudioSignal& in, TTAudioSignal& out, TTFloat64 gain)
191 {
192  TTUInt16 vs, channel;
193  TTSampleValuePtr inSample, outSample;
194  TTUInt16 numchannels = TTAudioSignal::getMinChannelCount(in, out);
195 
196  for (channel=0; channel<numchannels; channel++) {
197  inSample = in.mSampleVectors[channel];
198  outSample = out.mSampleVectors[channel];
199  vs = in.getVectorSizeAsInt();
200 
201  while (vs--)
202  *outSample++ += (*inSample++) * gain;
203  }
204 }
205 
206 
207 /* We are trying to calculate audio output from multiple audio inputs.
208  So for each audio output:
209  1. Start with a zero signal
210  2. Then += each input signal, multiplied by its gain
211 
212  We may need to speed up this operation by iterating through the signals using direct access of the structs.
213 */
215 { //TODO: if mGainMatrix is sparse (i.e. it has a lot of zeros), we can do better than this algorithm which iterates through the entire matrix
216  TTChannelCount minChannelIn = std::min(mNumInputs,inputs->numAudioSignals);
217  TTFloat64 gain;
218 
219  for (TTUInt16 y=0; y < outputs->numAudioSignals; y++) {
220  TTAudioSignal& out = outputs->getSignal(y);
221  out.clear(); // zeroing output memory
222  if (y < (mNumOutputs)){
223  for (TTChannelCount x=0; x < minChannelIn; x++) {
224  mGainMatrix.get2d(x, y, gain);
225  if (gain){ //if the gain value is zero, just pass processOne
226  TTAudioSignal& in = inputs->getSignal(x);
227  processOne(in, out, gain);
228  }
229  }
230  }
231  }
232  return kTTErrNone;
233 }
234 
TTFloat64 TTDecibelsToLinearGain(TTFloat64 value)
Convert decibels into linear ampliude.
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTErr get2d(TTRowID i, TTColumnID j, T &data) const
Get the value of a component located at (i,j) in a 2-dimensional matrix.
TTErr setGain(const TTValue &newValue, TTValue &e)
setter for converting gain input from db to linear.
TTErr set2d(TTRowID i, TTColumnID j, T data)
Set the value of a component located at (i,j) in a 2-dimensional matrix.
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
size_type size() const noexcept
Return the number of elements.
static TTErr copy(const TTMatrixBase &source, TTMatrixBase &dest)
Copy the data from one matrix into another.
The wrong number of values were passed to a method or attribute.
Definition: TTBase.h:350
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
TTMatrixBase * instance() const
Get a pointer to the wrapped TTMatrixBase instance.
Definition: TTMatrix.h:37
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
16-bit unsigned integer, range is 0 through 65,535.
Definition: TTBase.h:276
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
A standard audio processing method as used by TTBlue objects.
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTErr clear()
Zero out all of the sample values in the audio signal.
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
Definition: TTAttribute.h:68
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
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
TTFloat64 TTMidiToLinearGain(TTFloat64 value)
Convert midi into linear amplitude.
A simple container for an array of TTAudioSignal pointers.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
No Error.
Definition: TTBase.h:343
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTChannelCount numAudioSignals
The number of audio signal pointers which are actually valid.
void clear()
Set all components of a matrix to zero.
Definition: TTMatrix.cpp:18