Jamoma API  0.6.0.a19
TTFreeHandFunction.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup dspFunctionLib
4  *
5  * @brief #TTFreeHandFunction Unit for Jamoms DSP
6  *
7  * @details A piecewise function unit that allows to load a function unit per defined domain. @n
8  * The default configuration is a linear function for X[0::1], Y[0::1] domain. @n
9  * Setup the curveList attribute to change the configuration. @n
10  * For example setting curveList to the < 0.3 0.6 exponential base 0.5 1. 1. logarithm base 0.8 > value @n
11  * you will imply the following behavior :
12  * - if x belongs to [0::0.3] domain, it will use the exponential function and the result will belong to [0.::0.6] domain.
13  * - if x belongs to ]0.3::1.] domain, it will use the logarithm function and the result will belong to ]0.6::1.] domain.
14  *
15  * @authors Théo de la Hogue, Trond Lossius
16  *
17  * @copyright Copyright © 2013 by Théo de la Hogue @n
18  * This code is licensed under the terms of the "New BSD License" @n
19  * http://creativecommons.org/licenses/BSD/
20  */
21 
22 
23 #include "TTFreeHandFunction.h"
24 #include <math.h>
25 
26 #define thisTTClass TTFreeHandFunction
27 #define thisTTClassName "freehand"
28 #define thisTTClassTags "dspFunctionLib, audio, processor, function"
29 
30 
31 TT_AUDIO_CONSTRUCTOR
32 {
34 
35  setProcessMethod(processAudio);
36  setCalculateMethod(calculateValue);
37 
38  Clear();
39 }
40 
41 TTFreeHandFunction::~TTFreeHandFunction()
42 {
43  ;
44 }
45 
47 {
48  TTBoolean firstFunction = YES;
49 
50  mFunctions.begin();
51 
52  // for each point
53  for (mPoints.begin(); mPoints.end(); mPoints.next()) {
54 
55  // append the point coordinate
56  value.append(mPoints.current());
57 
58  // the first function is always an exponential base 1. function
59  if (firstFunction) {
60 
61  value.append(TTSymbol("exponential"));
62  value.append(TTSymbol("base"));
63  value.append(1.);
64 
65  firstFunction = NO;
66  continue;
67  }
68 
69  // append function info
70  if (mFunctions.end()) {
71 
72  TTObject aFunction = mFunctions.current()[0];
73 
74  if (aFunction.valid()) {
75 
76  TTValue attributeNames;
77  TTUInt8 i;
78 
79  // append function name
80  value.append(aFunction.name());
81 
82  // for all attributes
83  aFunction.attributes(attributeNames);
84 
85  for (i = 0; i < attributeNames.size(); i++) {
86 
87  TTSymbol aName = attributeNames[i];
88 
89  if (aName == kTTSym_bypass || aName == TTSymbol("mute") || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
90  continue; // don't publish these datas
91 
92  // append attribute name
93  value.append(aName);
94 
95  // append attribute value
96  TTValue v;
97  aFunction.get(aName, v);
98  value.append(v);
99  }
100  }
101 
102  mFunctions.next();
103  }
104  }
105 
106  return kTTErrNone;
107 }
108 
110 {
111  TTUInt8 curveId;
112  TTUInt32 i, next, size;
113  TTFloat64 x, y;
114  TTSymbol function, parameterName;
115  TTObject aFunction;
116  TTValue v;
117  TTErr err = kTTErrNone;
118 
119  locked = YES;
120 
121  // clear all existing points
122  mPoints.clear();
123 
124  // clear all existing functions
125  mFunctions.clear();
126 
127  // set all points and curves
128  size = value.size();
129  curveId = 0;
130  for (i = 0; i < size; i = i + next) {
131 
132  // check size
133  if (i+1 >= size)
134  err = kTTErrGeneric;
135 
136  // append a point : x y
137  if (value[i].type() == kTypeFloat64 && value[i+1].type() == kTypeFloat64) {
138 
139  x = value[i];
140  y = value[i+1];
141 
142  v = TTValue(x);
143  v.append(y);
144  mPoints.append(v);
145 
146  next = 2;
147  }
148  else
149  err = kTTErrGeneric;
150 
151  // create a function
152  aFunction = NULL;
153 
154  // check size
155  if (i+2 >= size) {
156  aFunction = TTObject("linear", 1); // 1 is the numChannel
157 
158  // set function type
159  } else if (value[i+2].type() == kTypeSymbol) {
160 
161  function = value[i+2];
162  aFunction = TTObject(function, 1); // 1 is the numChannel
163 
164  next = 3;
165 
166  // check size
167  if (i+5 > size)
168  ;
169 
170  // set function parameter
171  else if (value[i+3].type() == kTypeSymbol) {
172 
173  parameterName = value[i+3];
174 
175  v.copyRange(value, i+4, i+5);
176  aFunction.set(parameterName, v);
177 
178  next = 5;
179  }
180  else
181  err = kTTErrGeneric;
182  }
183  else
184  aFunction = TTObject("linear", 1); // 1 is the numChannel
185 
186  // for the first point : release the function
187  if (!curveId)
188  aFunction = TTObject();
189 
190  // append the function
191  else
192  mFunctions.append(aFunction);
193 
194  curveId++;
195  }
196 
197  locked = NO;
198 
199  return err;
200 }
201 
203 {
204  TTValue init;
205 
206  init.append(0.);
207  init.append(0.);
208 
209  init.append(1.);
210  init.append(1.);
211 
212  return setCurveList(init);
213 }
214 
216 {
217  TTFloat64 lastX, lastY;
218  TTFloat64 currentX, currentY;
219  TTFloat64 scaledX, scaledY;
220  TTObject aFunction;
221  TTErr err;
222 
223  if (locked)
224  return kTTErrGeneric;
225 
226  if (mPoints.isEmpty())
227  return kTTErrNone;
228 
229  mPoints.begin();
230  lastX = mPoints.current()[0];
231  lastY = mPoints.current()[1];
232 
233  if (x < lastX) {
234  y = lastY;
235  return kTTErrNone;
236  }
237 
238  mPoints.next();
239 
240  // select the function to use
241  for (mFunctions.begin(); mFunctions.end(); mFunctions.next()) {
242 
243  currentX = mPoints.current()[0];
244  currentY = mPoints.current()[1];
245 
246  if (x < currentX) {
247 
248  aFunction = mFunctions.current()[0];
249 
250  // scale x
251  scaledX = (x - lastX) / (currentX - lastX);
252 
253  // use function
254  err = TTAudioObjectBasePtr(aFunction.instance())->calculate(scaledX, scaledY);
255 
256  // scale y
257  y = (currentY - lastY) * scaledY + lastY;
258 
259  return err;
260  }
261 
262  lastX = currentX;
263  lastY = currentY;
264  mPoints.next();
265  }
266 
267  y = lastY;
268 
269  return kTTErrNone;
270 }
271 
272 
274 {
275  TT_WRAP_CALCULATE_METHOD(calculateValue);
276 }
277 
TTErr(TTObjectBase::* TTSetterMethod)(const TTAttribute &attribute, const TTValue &value)
A type that can be used to store a pointer to a message for an object.
Definition: TTObjectBase.h:78
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTErr Clear()
Clear all functions.
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
TTErr calculate(const TTFloat64 &x, TTFloat64 &y)
Calculate a single sample of output for a single sample of input.
#define setProcessMethod(methodName)
A convenience macro to be used by subclasses for setting the process method.
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
This is a special type used by TTAttribute to indicate that a value is a TTValue and is locally maint...
Definition: TTBase.h:286
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
#define setCalculateMethod(methodName)
A convenience macro to be used by subclasses for setting the calculate method.
TTAudioObjectBase * TTAudioObjectBasePtr
Pointer to a TTAudioObjectBase.
64-bit floating point
Definition: TTBase.h:272
TTSymbol name() const
Return the name of this class.
Definition: TTObject.cpp:129
TTFreeHandFunction Unit for Jamoms DSP
TTErr calculateValue(const TTFloat64 &x, TTFloat64 &y, TTPtrSizedInt data)
y = f(x) for a single value
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTErr setCurveList(const TTValue &value)
Set all points and functions using a list of < x y function parameterName parameterValue > ...
A simple container for an array of TTAudioSignal pointers.
long TTPtrSizedInt
An integer that is the same size as a pointer.
Definition: TTBase.h:240
TTErr getCurveList(TTValue &value)
Get all points and functions as a list of < x y function parameterName parameterValue > ...
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
void attributes(TTValue &returnedAttributeNames) const
Return a list of names of the available attributes.
Definition: TTObject.cpp:111
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
TTErr processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
A standard audio processing method as used by Jamoma DSP objects.
void copyRange(const TTValue &obj, TTUInt16 startIndex, TTUInt16 endIndex)
Copy a value starting from an index until another index.
Definition: TTValue.h:138
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
TTErr(TTObjectBase::* TTGetterMethod)(const TTAttribute &attribute, TTValue &value)
A type that can be used to store a pointer to a message for an object.
Definition: TTObjectBase.h:73
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174