Jamoma API  0.6.0.a19
TTMapper.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A Mapper Object
6  *
7  * @details
8  *
9  * @authors Théo de la Hogue
10  *
11  * @copyright © 2010, Théo de la Hogue @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 #include "TTMapper.h"
18 
19 #define thisTTClass TTMapper
20 #define thisTTClassName "Mapper"
21 #define thisTTClassTags "mapper"
22 
23 TT_MODULAR_CONSTRUCTOR,
24 mInput(kTTAdrsEmpty),
25 mInputMin(0.),
26 mInputMax(1.),
27 mInputIndex(0),
28 mInputThresholdDown(0.),
29 mInputThresholdUp(1.),
30 mInputGoingDown(NO),
31 mInputGoingUp(NO),
32 mOutput(kTTAdrsEmpty),
33 mOutputMin(0.),
34 mOutputMax(1.),
35 mOutputThresholdDown(0.),
36 mOutputThresholdUp(1.),
37 mOutputGoingDown(NO),
38 mOutputGoingUp(NO),
39 mActive(YES),
40 mInverse(NO),
41 #ifndef TT_NO_DSP
42 mFunction(kTTSymEmpty),
43 #endif
44 mClipmode(kTTSym_none),
45 mRamp(0)
46 {
47  if(arguments.size() >= 1)
48  mReturnValueCallback = arguments[0];
49 
50  if(arguments.size() >= 2)
51  mReturnInputGoingDownCallback = arguments[1];
52 
53  if(arguments.size() >= 3)
54  mReturnInputGoingUpCallback = arguments[2];
55 
56  if(arguments.size() >= 4)
57  mReturnOutputGoingDownCallback = arguments[3];
58 
59  if(arguments.size() >= 5)
60  mReturnOutputGoingUpCallback = arguments[4];
61 
63 
66 
67  addAttribute(InputIndex, kTypeUInt32);
68 
69  addAttribute(InputThresholdDown, kTypeFloat64);
70  addAttribute(InputThresholdUp, kTypeFloat64);
71 
73 
76 
77  addAttribute(OutputThresholdDown, kTypeFloat64);
78  addAttribute(OutputThresholdUp, kTypeFloat64);
79 
81 
83 
84  addAttribute(Inverse, kTypeBoolean);
85 #ifndef TT_NO_DSP
86  addAttributeWithGetter(FunctionLibrary, kTypeLocalValue);
87  addAttributeProperty(FunctionLibrary, readOnly, YES);
88 
90 
91  addAttribute(FunctionParameters, kTypeLocalValue);
92  addAttributeProperty(FunctionParameters, readOnly, YES);
93 
94  addAttributeWithGetter(FunctionSamples, kTypeLocalValue);
95  addAttributeProperty(FunctionSamples, readOnly, YES);
96 #endif
98 
100  addMessageProperty(Map, hidden, YES);
101 
102  scaleInput();
103  scaleOutput();
104 
105  TTObject::GetRegisteredClassNamesForTags(mFunctionLibrary, kTTSym_function);
106 }
107 
108 TTMapper::~TTMapper() // TODO : delete things...
109 {
110  TTSymbol aName;
111 #ifndef TT_NO_DSP
112  long n;
113 
114  if (mFunctionUnit.valid()) {
115 
116  // Remove former datas
117  n = mFunctionParameters.size();
118  for (int i = 0; i < n; i++) {
119  aName = mFunctionParameters[i];
120  this->removeAttribute(aName);
121  }
122 
123  mFunction = kTTSymEmpty;
124  mFunctionParameters.clear();
125  }
126 #endif
127 }
128 
129 TTErr TTMapper::Map(TTValue& inputValue, TTValue& outputValue)
130 {
131  if (mActive) {
132 
133  TTValue none;
134 
135  processMapping(inputValue, outputValue);
136 
137  // return value (+ ramp)
138  if (mSender.valid()) {
139 
140  // if there is a ramp value, edit the command here
141  if (mRamp > 0) {
142 
143  TTDictionaryBasePtr command;
144  TTValue valueAndRamp;
145 
146  command = new TTDictionaryBase();
147  command->setSchema(kTTSym_command);
148  command->setValue(outputValue);
149  command->append(kTTSym_ramp, mRamp);
150 
151  valueAndRamp = TTValue((TTPtr)command);
152 
153  mSender.send(kTTSym_Send, valueAndRamp);
154 
155  delete command;
156  }
157  else
158  mSender.send(kTTSym_Send, outputValue);
159  }
160 
161  mReturnValueCallback.send("notify", outputValue);
162 
163  // notify if input going down
164  TTBoolean newInputGoingDown = inputValue <= TTValue(mInputThresholdDown);
165  if (newInputGoingDown != mInputGoingDown) {
166 
167  mInputGoingDown = newInputGoingDown;
168  mReturnInputGoingDownCallback.send("notify", mInputGoingDown);
169  }
170 
171  // notify if input going up
172  TTBoolean newInputGoingUp = inputValue >= TTValue(mInputThresholdUp);
173  if (newInputGoingUp != mInputGoingUp) {
174 
175  mInputGoingUp = newInputGoingUp;
176  mReturnInputGoingUpCallback.send("notify", mInputGoingUp);
177  }
178 
179  // notify if output going down
180  TTBoolean newOutputGoingDown = outputValue <= TTValue(mOutputThresholdDown);
181  if (newOutputGoingDown != mOutputGoingDown) {
182 
183  mOutputGoingDown = newOutputGoingDown;
184  mReturnOutputGoingDownCallback.send("notify", mOutputGoingDown);
185  }
186 
187  // notify if output going up
188  TTBoolean newOutputGoingUp = outputValue >= TTValue(mOutputThresholdUp);
189  if (newOutputGoingUp != mOutputGoingUp) {
190 
191  mOutputGoingUp = newOutputGoingUp;
192  mReturnOutputGoingUpCallback.send("notify", mOutputGoingUp);
193  }
194  }
195 
196  return kTTErrNone;
197 }
198 #ifndef TT_NO_DSP
199 TTErr TTMapper::getFunctionLibrary(TTValue& value)
200 {
201  TTObject::GetRegisteredClassNamesForTags(mFunctionLibrary, kTTSym_function);
202 
203  value = mFunctionLibrary;
204  return kTTErrNone;
205 }
206 
207 TTErr TTMapper::getFunctionSamples(TTValue& value)
208 {
209  TTValue inputSamples;
210  TTFloat64 s, resolution;
211 
212  resolution = (mInputMax - mInputMin) / 100; // TODO : add an attribute for the number of samples (default : 100)
213 
214  for (s = mInputMin; s < mInputMax; s += resolution)
215  inputSamples.append(s);
216 
217  processMapping(inputSamples, value);
218 
219  return kTTErrNone;
220 }
221 #endif
222 TTErr TTMapper::setInput(const TTValue& value)
223 {
224  TTValue v, min, max, none;
225  TTNodePtr aNode;
226  TTObject returnValueCallback, anObject;
227  TTErr err;
228 
229  mInput = value[0];
230 
231  mObserveInputRange = YES;
232 
233  if (mInput == kTTAdrsEmpty) {
234 
235  if (mReceiver.valid()) {
236  mReceiver.set(kTTSym_address, kTTAdrsEmpty);
237  mReceiver = TTObject();
238  }
239 
240  if (mInputObserver.valid()) {
241  mInputObserver.set(kTTSym_address, kTTAdrsEmpty);
242  mInputObserver = TTObject();
243  }
244 
245  if (mInputRangeObserver.valid()) {
246  mInputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
247  mInputRangeObserver = TTObject();
248  }
249 
250  return kTTErrGeneric;
251  }
252 
253  // create a receiver if needed
254  if (!mReceiver.valid()) {
255 
256  TTValue args;
257  TTObject empty;
258 
259  args.append(empty);
260 
261  returnValueCallback = TTObject("callback");
262 
263  returnValueCallback.set(kTTSym_baton, TTObject(this));
264  returnValueCallback.set(kTTSym_function, TTPtr(&TTMapperReceiveValueCallback));
265  args.append(returnValueCallback);
266 
267  mReceiver = TTObject(kTTSym_Receiver, args);
268  }
269 
270  mReceiver.set(kTTSym_address, mInput.appendAttribute(kTTSym_value));
271 
272  // Trying to get the Data at this address
273  // and get some infos about range bounds
274  // and if the mapper was created before we observe the input address
275  if (accessApplicationDirectoryFrom(mInput)) {
276  err = accessApplicationDirectoryFrom(mInput)->getTTNode(mInput, &aNode);
277 
278  if (!err) {
279 
280  anObject = aNode->getObject();
281  if (anObject.valid()) {
282 
283  if (anObject.name() == kTTSym_Data) {
284 
285  anObject.get(kTTSym_rangeBounds, v);
286 
287  mInputMin = TTFloat64(v[0]);
288  mInputMax = TTFloat64(v[1]);
289  mInputThresholdDown = TTFloat64(v[0]);
290  mInputThresholdUp = TTFloat64(v[1]);
291 
292  scaleInput();
293 
294  observeInputRange();
295  }
296  }
297  return kTTErrNone;
298  }
299  }
300 
301  return observeInput();
302 }
303 
304 TTErr TTMapper::observeInput()
305 {
306  TTObject returnInputCreationCallback;
307 
308  // create a receiver if needed
309  if (!mInputObserver.valid()) {
310 
311  TTValue args;
312  TTObject empty;
313 
314  returnInputCreationCallback = TTObject("callback");
315 
316  returnInputCreationCallback.set(kTTSym_baton, TTObject(this));
317  returnInputCreationCallback.set(kTTSym_function, TTPtr(&TTMapperInputCreationCallback));
318  args.append(returnInputCreationCallback);
319 
320  args.append(empty);
321 
322  mInputObserver = TTObject(kTTSym_Receiver, args);
323  }
324 
325  mInputObserver.set(kTTSym_address, mInput.appendAttribute(kTTSym_created));
326 
327  return kTTErrNone;
328 }
329 
330 TTErr TTMapper::observeInputRange()
331 {
332  TTObject returnInputRangeCallback;
333 
334  if (!mInputRangeObserver.valid()) {
335 
336  TTValue args;
337  TTObject empty;
338 
339  args.append(empty);
340 
341  returnInputRangeCallback = TTObject("callback");
342 
343  returnInputRangeCallback.set(kTTSym_baton, TTObject(this));
344  returnInputRangeCallback.set(kTTSym_function, TTPtr(&TTMapperInputRangeCallback));
345  args.append(returnInputRangeCallback);
346 
347  mInputRangeObserver = TTObject(kTTSym_Receiver, args);
348  }
349 
350  mInputRangeObserver.set(kTTSym_address, mInput.appendAttribute(kTTSym_rangeBounds));
351 
352  return kTTErrNone;
353 }
354 
355 TTErr TTMapper::setOutput(const TTValue& value)
356 {
357  TTValue args, v, min, max;
358  TTNodePtr aNode;
359  TTObject anObject;
360  TTErr err;
361 
362  mOutput = value[0];
363 
364  mObserveOutputRange = YES;
365 
366  if (mOutput == kTTAdrsEmpty) {
367 
368  if (mSender.valid()) {
369  mSender.set(kTTSym_address, kTTAdrsEmpty);
370  mSender = TTObject();
371  }
372 
373  if (mOutputObserver.valid()) {
374  mOutputObserver.set(kTTSym_address, kTTAdrsEmpty);
375  mOutputObserver = TTObject();
376  }
377 
378  if (mOutputRangeObserver.valid()) {
379  mOutputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
380  mOutputRangeObserver = TTObject();
381  }
382 
383  return kTTErrGeneric;
384  }
385 
386  // Make a sender if needed
387  if (!mSender.valid())
388  mSender = TTObject(kTTSym_Sender);
389 
390  mSender.set(kTTSym_address, mOutput.appendAttribute(kTTSym_value));
391 
392  // Trying to get the Data at this address
393  // and get some infos about range bounds
394  // and if the mapper created before we observe the output address
395  if (accessApplicationDirectoryFrom(mOutput)) {
396  err = accessApplicationDirectoryFrom(mOutput)->getTTNode(mOutput, &aNode);
397 
398  if (!err) {
399 
400  anObject = aNode->getObject();
401  if (anObject.valid()) {
402 
403  if (anObject.name() == kTTSym_Data) {
404 
405  anObject.get(kTTSym_rangeBounds, v);
406 
407  mOutputMin = TTFloat64(v[0]);
408  mOutputMax = TTFloat64(v[1]);
409  mOutputThresholdDown = TTFloat64(v[0]);
410  mOutputThresholdUp = TTFloat64(v[1]);
411 
412  scaleOutput();
413 
414  observeOutputRange();
415  }
416  }
417  return kTTErrNone;
418  }
419  }
420 
421  return observeOutput();
422 }
423 
424 TTErr TTMapper::observeOutput()
425 {
426  TTObject returnOutputCreationCallback;
427 
428  if (!mOutputObserver.valid()) {
429 
430  TTValue args;
431  TTObject empty;
432 
433  returnOutputCreationCallback = TTObject("callback");
434 
435  returnOutputCreationCallback.set(kTTSym_baton, TTObject(this));
436  returnOutputCreationCallback.set(kTTSym_function, TTPtr(&TTMapperOutputCreationCallback));
437  args.append(returnOutputCreationCallback);
438 
439  args.append(empty);
440 
441  mOutputObserver = TTObject(kTTSym_Receiver, args);
442  }
443 
444  mOutputObserver.set(kTTSym_address, mOutput.appendAttribute(kTTSym_created));
445 
446  return kTTErrNone;
447 }
448 
449 TTErr TTMapper::observeOutputRange()
450 {
451  TTObject returnOutputRangeCallback;
452 
453  if (!mOutputRangeObserver.valid()) {
454 
455  TTValue args;
456  TTObject empty;
457 
458  args.append(empty);
459 
460  returnOutputRangeCallback = TTObject("callback");
461  returnOutputRangeCallback.set(kTTSym_baton, TTObject(this));
462  returnOutputRangeCallback.set(kTTSym_function, TTPtr(&TTMapperOutputRangeCallback));
463  args.append(returnOutputRangeCallback);
464 
465  mOutputRangeObserver = TTObject(kTTSym_Receiver, args);
466  }
467 
468  mOutputRangeObserver.set(kTTSym_address, mOutput.appendAttribute(kTTSym_rangeBounds));
469 
470  return kTTErrNone;
471 }
472 #ifndef TT_NO_DSP
473 TTErr TTMapper::setFunction(const TTValue& value)
474 {
475  long n;
476  TTValue names;
477  TTSymbol aName;
478  TTBoolean found = NO;
479 
480  if (mFunctionUnit.valid()) {
481 
482  // Remove former datas
483  n = mFunctionParameters.size();
484  for (int i = 0; i < n; i++) {
485  aName = mFunctionParameters[i];
486  this->removeAttribute(aName);
487  }
488 
489  mFunctionUnit = TTObject();
490  mFunction = kTTSymEmpty;
491  mFunctionParameters.clear();
492  }
493 
494  // Check the unit exist and create a new function unit
495  mFunction = value;
496 
497  for (TTElementIter it = mFunctionLibrary.begin() ; it != mFunctionLibrary.end() ; it++)
498  {
499  TTSymbol unitName = TTElement(*it);
500  if (unitName == mFunction)
501  found = YES;
502  }
503 
504  if (!found)
505  return kTTErrGeneric;
506 
507  mFunctionUnit = TTObject(mFunction, 1);
508 
509  // Extend function unit attributes as attributes of this mapper
510  // and set mFunctionParameters attribute
511  if (mFunctionUnit.valid()) {
512 
513  mFunctionUnit.attributes(names);
514  n = names.size();
515 
516  if (n) {
517  for (int i = 0; i < n; i++) {
518 
519  aName = names[i];
520 
521  // don't publish these datas
522  if (aName == kTTSym_bypass || aName == kTTSym_mute || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
523  continue;
524 
525  // extend attribute with the same name
526  this->extendAttribute(aName, mFunctionUnit.instance(), aName);
527  mFunctionParameters.append(aName);
528  }
529  }
530  else
531  mFunctionParameters.append(kTTSym_none);
532 
533  notifyObservers(kTTSym_function, value);
534  notifyObservers(TTSymbol("functionParameters"), mFunctionParameters);
535  return kTTErrNone;
536  }
537 
538  return kTTErrGeneric;
539 }
540 #endif
541 
542 TTErr TTMapper::setInputMin(const TTValue& value)
543 {
544  mInputMin = value;
545 
546  // stop input range observation
547  mObserveInputRange = false;
548 
549  if (mInputRangeObserver.valid())
550  {
551  mInputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
552  mInputRangeObserver = TTObject();
553  }
554 
555  notifyObservers(TTSymbol("inputMin"), value);
556  return scaleInput();
557 }
558 
559 TTErr TTMapper::setInputMax(const TTValue& value)
560 {
561  mInputMax = value;
562 
563  // stop input range observation
564  mObserveInputRange = false;
565 
566  if (mInputRangeObserver.valid())
567  {
568  mInputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
569  mInputRangeObserver = TTObject();
570  }
571 
572  notifyObservers(TTSymbol("inputMax"), value);
573  return scaleInput();
574 }
575 
576 TTErr TTMapper::setOutputMin(const TTValue& value)
577 {
578  mOutputMin = value;
579 
580  // stop output range observation
581  mObserveOutputRange = false;
582 
583  if (mOutputRangeObserver.valid())
584  {
585  mOutputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
586  mOutputRangeObserver = TTObject();
587  }
588 
589  notifyObservers(TTSymbol("outputMin"), value);
590  return scaleOutput();
591 }
592 
593 TTErr TTMapper::setOutputMax(const TTValue& value)
594 {
595  mOutputMax = value;
596 
597  // stop output range observation
598  mObserveOutputRange = false;
599 
600  if (mOutputRangeObserver.valid())
601  {
602  mOutputRangeObserver.set(kTTSym_address, kTTAdrsEmpty);
603  mOutputRangeObserver = TTObject();
604  }
605 
606  notifyObservers(TTSymbol("outputMax"), value);
607  return scaleOutput();
608 }
609 
610 TTErr TTMapper::setActive(const TTValue& value)
611 {
612  mActive = value;
613 
614  notifyObservers(kTTSym_active, value);
615  return kTTErrNone;
616 }
617 
618 TTErr TTMapper::setClipmode(const TTValue& value)
619 {
620  TTValue n = value; // use new value to protect the attribute
621  mClipmode = value;
622  notifyObservers(kTTSym_clipmode, n);
623  return kTTErrNone;
624 }
625 
626 // Recalculate values to use for scaling of input values
627 TTErr TTMapper::scaleInput()
628 {
629  // Prevent dividing by 0
630  if (mInputMin == mInputMax)
631  mA = 1;
632  else
633  mA = 1./(mInputMax - mInputMin);
634  mB = -1 * mA * mInputMin;
635 
636  return kTTErrNone;
637 }
638 
639 // Recalculate values to use for scaling of output values
640 TTErr TTMapper::scaleOutput()
641 {
642  mC = mOutputMax - mOutputMin;
643  mD = mOutputMin;
644  return kTTErrNone;
645 }
646 
647 TTErr TTMapper::processMapping(const TTValue& inputValue, TTValue& outputValue)
648 {
649  TTValue inputCopy, in, out;
650  TTFloat64 f;
651  TTInt32 i, size;
652 
653  // we need to copy to protect the inputValue
654  inputCopy = inputValue;
655 
656  size = inputCopy.size();
657 
658  // clip input value
659  if (mClipmode != kTTSym_none) {
660  if (mClipmode == kTTSym_low)
661  inputCopy.cliplow(mInputMin);
662  else if (mClipmode == kTTSym_high)
663  inputCopy.cliphigh(mInputMax);
664  else if (mClipmode == kTTSym_both)
665  inputCopy.clip(mInputMin, mInputMax);
666  // Invalid values for mClipmode will result in no clipping
667  }
668 
669  // scale input value
670  for (i = 0; i < size; i++) {
671  f = inputCopy[i];
672  in.append(mA * f + mB);
673  }
674 
675  // select index if needed
676  if (mInputIndex > 0 && mInputIndex <= (TTUInt32) size) {
677  in = in[mInputIndex-1];
678  size = 1;
679  }
680 
681 #ifndef TT_NO_DSP
682  // process function
683  if (mFunctionUnit.valid())
684  TTAudioObjectBasePtr(mFunctionUnit.instance())->calculate(in, out);
685  else
686 #endif
687  out = in;
688 
689  // scale output value
690  for (i = 0; i < size; i++) {
691  f = out[i];
692 
693  if (!mInverse)
694  outputValue.append(mC * f + mD);
695  else
696  outputValue.append(mC * (1. - f) + mD);
697  }
698 
699  // If input value has been clipped, there is generally no need to clip output value
700  // Some easing functions are going beyond boundaries (e.g. the easeBack functions), but we assume that if the user opt for one of these easing functions, this is desired behaviour.
701  //outputValue.clip(mOutputMin, mOutputMax);
702 
703  return kTTErrNone;
704 }
705 
706 TTErr TTMapper::notifyObservers(TTSymbol attrName, const TTValue& value)
707 {
708  TTAttributePtr anAttribute = NULL;
709  TTErr err;
710 
711  err = this->findAttribute(attrName, &anAttribute);
712 
713  if (!err)
714  anAttribute->sendNotification(kTTSym_notify, value); // we use kTTSym_notify because we know that observers are TTCallback
715 
716  return kTTErrNone;
717 }
718 
719 #if 0
720 #pragma mark -
721 #pragma mark Some Methods
722 #endif
723 
725 {
726  TTObject o;
727  TTMapperPtr aMapper;
728  TTValue v;
729  TTAddress address;
730  TTNodePtr aNode;
731 
732  // unpack baton (a TTMapper)
733  o = baton[0];
734  aMapper = (TTMapperPtr)o.instance();
735 
736  // unpack data (an address)
737  address = data[0];
738 
739  // get the Data at this address
740  // and get some infos about range bounds
741  TTErr err = accessApplicationDirectoryFrom(address)->getTTNode(address, &aNode);
742 
743  if (!err) {
744 
745  o = aNode->getObject();
746  if (o.valid()) {
747 
748  if (o.name() == kTTSym_Data || o.name() == kTTSym_Mirror) {
749 
750  o.get(kTTSym_rangeBounds, v);
751 
752  if (v.size() == 2) {
753 
754  // if inputMin isn't a specific value or observation is active
755  if (aMapper->mInputMin == 0. || aMapper->mObserveInputRange)
756  aMapper->mInputMin = TTFloat64(v[0]);
757 
758  // if inputMax isn't a specific value or observation is active
759  if (aMapper->mInputMax == 1. || aMapper->mObserveInputRange)
760  aMapper->mInputMax = TTFloat64(v[1]);
761 
762  aMapper->scaleInput();
763  }
764 
765  aMapper->observeInputRange();
766  }
767  }
768  }
769 
770  return err;
771 }
772 
774 {
775  TTObject o;
776  TTMapperPtr aMapper;
777  TTValue v;
778  TTAddress address;
779  TTNodePtr aNode;
780 
781  // unpack baton (a TTMapper)
782  o = baton[0];
783  aMapper = (TTMapperPtr)o.instance();
784 
785  // unpack data (an address)
786  address = data[0];
787 
788  // get the Data at this address
789  // and get some infos about range bounds
790  TTErr err = accessApplicationDirectoryFrom(address)->getTTNode(address, &aNode);
791 
792  if (!err) {
793 
794  o = aNode->getObject();
795  if (o.valid()) {
796 
797  if (o.name() == kTTSym_Data || o.name() == kTTSym_Mirror) {
798 
799  o.get(kTTSym_rangeBounds, v);
800 
801  if (v.size() == 2) {
802 
803  // if outputMin isn't a specific value or observation is active
804  if (aMapper->mOutputMin == 0. || aMapper->mObserveOutputRange)
805  aMapper->mOutputMin = TTFloat64(v[0]);
806 
807  // if outputMax isn't a specific value or observation is active
808  if (aMapper->mOutputMax == 1. || aMapper->mObserveOutputRange)
809  aMapper->mOutputMax = TTFloat64(v[1]);
810 
811  aMapper->scaleOutput();
812  }
813 
814  aMapper->observeOutputRange();
815  }
816  }
817  }
818 
819  return err;
820 }
821 
823 {
824  TTObject o;
825  TTMapperPtr aMapper;
826 
827  // unpack baton (a TTMapper)
828  o = baton[0];
829  aMapper = (TTMapperPtr)o.instance();
830 
831  if (aMapper->mObserveInputRange) {
832  // unpack data (min, max)
833  aMapper->mInputMin = data[0];
834  aMapper->mInputMax = data[1];
835  aMapper->mInputThresholdDown = data[0];
836  aMapper->mInputThresholdUp = data[1];
837 
838  aMapper->scaleInput();
839  }
840 
841  return kTTErrNone;
842 }
843 
845 {
846  TTObject o;
847  TTMapperPtr aMapper;
848 
849  // unpack baton (a TTMapper)
850  o = baton[0];
851  aMapper = (TTMapperPtr)o.instance();
852 
853  if (aMapper->mObserveOutputRange) {
854  // unpack data (min, max)
855  aMapper->mOutputMin = data[0];
856  aMapper->mOutputMax = data[1];
857  aMapper->mOutputThresholdDown = data[0];
858  aMapper->mOutputThresholdUp = data[1];
859 
860  aMapper->scaleOutput();
861  }
862 
863  return kTTErrNone;
864 }
865 
866 TTErr TTMapperReceiveValueCallback(const TTValue& baton, const TTValue& inputValue)
867 {
868  TTObject o;
869  TTMapperPtr aMapper;
870  TTValue outputValue;
871  TTValue none;
872 
873  // unpack baton (a TTMapper)
874  o = baton[0];
875  aMapper = (TTMapperPtr)o.instance();
876 
877  if (aMapper->mActive) {
878 
879  // process the mapping
880  aMapper->processMapping(inputValue, outputValue);
881 
882  // return value (+ ramp)
883  if (aMapper->mSender.valid()) {
884 
885  // if there is a ramp value, edit the command here
886  if (aMapper->mRamp > 0) {
887 
888  TTDictionaryBasePtr command;
889  TTValue valueAndRamp;
890 
891  command = new TTDictionaryBase();
892  command->setSchema(kTTSym_command);
893  command->setValue(outputValue);
894  command->append(kTTSym_ramp, aMapper->mRamp);
895 
896  valueAndRamp = TTValue((TTPtr)command);
897 
898  aMapper->mSender.send(kTTSym_Send, valueAndRamp);
899 
900  delete command;
901  }
902  else
903  aMapper->mSender.send(kTTSym_Send, outputValue);
904  }
905 
906  aMapper->mReturnValueCallback.send("notify", outputValue);
907 
908  // notify if input going down
909  TTBoolean newInputGoingDown = inputValue <= TTValue(aMapper->mInputThresholdDown);
910  if (newInputGoingDown != aMapper->mInputGoingDown) {
911 
912  aMapper->mInputGoingDown = newInputGoingDown;
913  aMapper->mReturnInputGoingDownCallback.send("notify", aMapper->mInputGoingDown);
914  }
915 
916  // notify if input going up
917  TTBoolean newInputGoingUp = inputValue >= TTValue(aMapper->mInputThresholdUp);
918  if (newInputGoingUp != aMapper->mInputGoingUp) {
919 
920  aMapper->mInputGoingUp = newInputGoingUp;
921  aMapper->mReturnInputGoingUpCallback.send("notify", aMapper->mInputGoingUp);
922  }
923 
924  // notify if output going down
925  TTBoolean newOutputGoingDown = outputValue <= TTValue(aMapper->mOutputThresholdDown);
926  if (newOutputGoingDown != aMapper->mOutputGoingDown) {
927 
928  aMapper->mOutputGoingDown = newOutputGoingDown;
929  aMapper->mReturnOutputGoingDownCallback.send("notify", aMapper->mOutputGoingDown);
930  }
931 
932  // notify if output going up
933  TTBoolean newOutputGoingUp = outputValue >= TTValue(aMapper->mOutputThresholdUp);
934  if (newOutputGoingUp != aMapper->mOutputGoingUp) {
935 
936  aMapper->mOutputGoingUp = newOutputGoingUp;
937  aMapper->mReturnOutputGoingUpCallback.send("notify", aMapper->mOutputGoingUp);
938  }
939  }
940 
941  return kTTErrNone;
942 }
943 
TTErr setSchema(const TTSymbol schemaName)
TODO: Add documentation schemaName TODO: Add documentation.
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
#define accessApplicationDirectoryFrom(anAddress)
Access to an application directory using an address.
TTErr TTMapperInputRangeCallback(const TTValue &baton, const TTValue &data)
Definition: TTMapper.cpp:822
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
A type that contains a key and a value.
TTErr setValue(const TTValue &newValue)
TODO: Add documentation.
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTObject & getObject()
Get the object binded by this node.
Definition: TTNode.cpp:468
size_type size() const noexcept
Return the number of elements.
static TTErr GetRegisteredClassNamesForTags(TTValue &classNames, const TTValue &searchTags)
Query TTEnvironment for names of all registered TTObjectBase classes that share specific tags...
Definition: TTObject.cpp:78
TTErr TTMapperReceiveValueCallback(const TTValue &baton, const TTValue &inputValue)
Definition: TTMapper.cpp:866
TTErr sendNotification(const TTSymbol name, const TTValue &arguments)
Send a notification.
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
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
TTErr TTMapperOutputCreationCallback(const TTValue &baton, const TTValue &data)
Definition: TTMapper.cpp:773
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
#define addAttributeWithGetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:38
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
void cliplow(const TTFloat64 &aLowBound)
Clip numerical values below a specified boundary.
Definition: TTValue.h:289
TTAudioObjectBase * TTAudioObjectBasePtr
Pointer to a TTAudioObjectBase.
A Mapper Object.
64-bit floating point
Definition: TTBase.h:272
TTSymbol name() const
Return the name of this class.
Definition: TTObject.cpp:129
#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.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTErr TTMapperInputCreationCallback(const TTValue &baton, const TTValue &data)
Definition: TTMapper.cpp:724
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
void cliphigh(const TTFloat64 &aHighBound)
Clip numerical values above a specified boundary.
Definition: TTValue.h:299
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
Individual items found in a TTValue.
Definition: TTElement.h:89
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
void clip(const TTFloat64 &aLowBound, const TTFloat64 &aHighBound)
Clip numerical values between low and high boundaries.
Definition: TTValue.h:279
void set(const TTUInt16 index, const T &anElementValue)
DEPRECATED.
Definition: TTValue.h:569
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
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
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
32-bit unsigned integer, range is 0 through 4,294,967,295.
Definition: TTBase.h:278
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
TTErr TTMapperOutputRangeCallback(const TTValue &baton, const TTValue &data)
Definition: TTMapper.cpp:844
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37