Jamoma API  0.6.0.a19
j.xfade~.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternalsDSP
4  *
5  * @brief j.xfade~ : wraps the #TTCrossfade class as a Jamoma external for MSP
6  *
7  * @details
8  *
9  * @authors Tim Place, Trond Lossius
10  *
11  * @copyright © 2005 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 
17 #include "TTClassWrapperMax.h"
18 #include "ext.h" // Max Header
19 #include "z_dsp.h" // MSP Header
20 #include "ext_strings.h" // String Functions
21 #include "commonsyms.h" // Common symbols used by the Max 4.5 API
22 #include "ext_obex.h" // Max Object Extensions (attributes) Header
23 
24 #include "TTDSP.h" // Jamoma DSP Interfaces...
25 
26 #define MAX_NUM_CHANNELS 32
27 
28 // Data Structure for this object
29 typedef struct _fade{
30  t_pxobject x_obj;
31  long attr_shape;
32  long attr_mode;
33  float attr_position;
34  TTUInt16 numChannels;
35  TTAudioObjectBase* xfade; // crossfade object from the Jamoma DSP library
36  TTAudioSignal* audioIn1;
37  TTAudioSignal* audioIn2;
38  TTAudioSignal* audioInControl;
39  TTAudioSignal* audioOut;
40 } t_fade;
41 
42 // Prototypes for methods
43 void *fade_new(t_symbol *s, long argc, t_atom *argv); // New Object Creation Method
44 t_int *fade_perform1(t_int *w); // An MSP Perform (signal) Method
45 t_int *fade_perform2(t_int *w); // An MSP Perform (signal) Method
46 void fade_dsp(t_fade *x, t_signal **sp, short *count); // DSP Method
47 void fade_dsp64(t_fade *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags); // DSP64 Method
48 void fade_assist(t_fade *x, void *b, long m, long a, char *s); // Assistance Method
49 void fade_float(t_fade *x, double value ); // Float Method
50 void fade_free(t_fade *x);
51 t_max_err attr_set_position(t_fade *x, void *attr, long argc, t_atom *argv);
52 t_max_err attr_set_shape(t_fade *x, void *attr, long argc, t_atom *argv);
53 t_max_err attr_set_mode(t_fade *x, void *attr, long argc, t_atom *argv);
54 t_int *fade_perform_stereo_1(t_int *w);
55 t_int *fade_perform_stereo_2(t_int *w);
56 void fade_perform64_1(t_fade *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
57 void fade_perform64_2(t_fade *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
58 
59 // Globals
60 static t_class *s_fade_class;
61 
62 
63 /************************************************************************************/
64 // Main() Function
65 
66 int C74_EXPORT main(void) // main recieves a copy of the Max function macros table
67 {
68  t_class *c;
69 
70  TTDSPInit();
71  common_symbols_init();
72 
73  // Define our class
74  c = class_new("j.xfade~", (method)fade_new, (method)fade_free, sizeof(t_fade), (method)0L, A_GIMME, 0);
75 
76  // Make methods accessible for our class:
77  class_addmethod(c, (method)fade_float, "float", A_FLOAT,0L);
78  class_addmethod(c, (method)fade_dsp, "dsp", A_CANT, 0L);
79  class_addmethod(c, (method)fade_dsp64, "dsp64", A_CANT, 0);
80  class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
81  class_addmethod(c, (method)fade_assist, "assist", A_CANT, 0L);
82 
83  // Add attributes to our class:
84  CLASS_ATTR_LONG(c, "shape", 0, t_fade, attr_shape);
85  CLASS_ATTR_ACCESSORS(c, "shape", NULL, attr_set_shape);
86  CLASS_ATTR_ENUMINDEX(c, "shape", 0, "EqualPower Linear SquareRoot");
87 
88  CLASS_ATTR_LONG(c, "mode", 0, t_fade, attr_mode);
89  CLASS_ATTR_ACCESSORS(c, "mode", NULL, attr_set_mode);
90  CLASS_ATTR_ENUMINDEX(c, "mode", 0, "LookupTable Calculate");
91 
92  CLASS_ATTR_FLOAT(c, "position", 0, t_fade, attr_position);
93  CLASS_ATTR_ACCESSORS(c, "position", NULL, attr_set_position);
94 
95  // Setup our class to work with MSP
96  class_dspinit(c);
97 
98  // Finalize our class
99  class_register(CLASS_BOX, c);
100  s_fade_class = c;
101  return 0;
102 }
103 
104 
105 /************************************************************************************/
106 // Object Life
107 
108 // Create
109 void *fade_new(t_symbol *s, long argc, t_atom *argv)
110 {
111  long attrstart = attr_args_offset(argc, argv); // support normal arguments
112  short i;
113 
114  t_fade *x = (t_fade *)object_alloc(s_fade_class);
115  if (x) {
116  object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x, NULL)); // dumpout
117 
118  x->numChannels = 1;
119  if (attrstart && argv) {
120  int argument = atom_getlong(argv);
121  x->numChannels = TTClip(argument, 1, MAX_NUM_CHANNELS);
122  }
123 
124  dsp_setup((t_pxobject *)x, (x->numChannels * 2) + 1); // Create Object and N Inlets (last argument)
125  x->x_obj.z_misc = Z_NO_INPLACE; // ESSENTIAL!
126  for (i=0; i< (x->numChannels); i++)
127  outlet_new((t_pxobject *)x, "signal"); // Create a signal Outlet
128 
129  //x->xfade = new TTCrossfade(x->numChannels); // Constructors
130  TTObjectBaseInstantiate(TT("crossfade"), &x->xfade, x->numChannels);
131  TTObjectBaseInstantiate(kTTSym_audiosignal, &x->audioIn1, x->numChannels);
132  TTObjectBaseInstantiate(kTTSym_audiosignal, &x->audioIn2, x->numChannels);
133  TTObjectBaseInstantiate(kTTSym_audiosignal, &x->audioInControl, x->numChannels);
134  TTObjectBaseInstantiate(kTTSym_audiosignal, &x->audioOut, x->numChannels);
135 
136  x->xfade->setAttributeValue(TT("mode"), TT("lookup"));
137  x->xfade->setAttributeValue(TT("shape"), TT("equalPower"));
138  x->xfade->setAttributeValue(TT("position"), 0.5);
139 
140  attr_args_process(x, argc, argv); // handle attribute args
141  }
142  return (x); // Return the pointer
143 }
144 
145 // Destroy
146 void fade_free(t_fade *x)
147 {
148  dsp_free((t_pxobject *)x); // Always call dsp_free first in this routine
149 
150  TTObjectBaseRelease(&x->xfade);
151  TTObjectBaseRelease(&x->audioIn1);
152  TTObjectBaseRelease(&x->audioIn2);
153  TTObjectBaseRelease(&x->audioInControl);
154  TTObjectBaseRelease(&x->audioOut);
155 }
156 
157 
158 /************************************************************************************/
159 // Methods bound to input/inlets
160 
161 // Method for Assistance Messages
162 void fade_assist(t_fade *x, void *b, long msg, long arg, char *dst)
163 {
164  if (msg==1) { // Inlets
165  if (arg < x->numChannels)
166  snprintf(dst, 256, "(signal) Input A - channel %ld", arg + 1);
167  else if (arg < x->numChannels*2)
168  snprintf(dst, 256, "(signal) Input B - channel %ld", arg - x->numChannels + 1);
169  else
170  strcpy(dst, "(float/signal) Crossfade Position");
171  }
172  else if (msg==2) { // Outlets
173  if (arg < x->numChannels)
174  snprintf(dst, 256, "(signal) Mix between A and B - channel %ld", arg + 1);
175  else
176  strcpy(dst, "dumpout");
177  }
178 }
179 
180 
181 // Float Method
182 void fade_float(t_fade *x, double value)
183 {
184  x->attr_position = value;
185  x->xfade->setAttributeValue(TT("position"), value);
186 }
187 
188 
189 // ATTRIBUTE: position
190 t_max_err attr_set_position(t_fade *x, void *attr, long argc, t_atom *argv)
191 {
192  fade_float(x, atom_getfloat(argv));
193  return MAX_ERR_NONE;
194 }
195 
196 
197 // ATTRIBUTE: shape
198 t_max_err attr_set_shape(t_fade *x, void *attr, long argc, t_atom *argv)
199 {
200  x->attr_shape = atom_getlong(argv);
201  if (x->attr_shape == 0)
202  x->xfade->setAttributeValue(TT("shape"), TT("equalPower"));
203  else if (x->attr_shape == 2)
204  x->xfade->setAttributeValue(TT("shape"), TT("squareRoot"));
205  else
206  x->xfade->setAttributeValue(TT("shape"), TT("linear"));
207 
208  return MAX_ERR_NONE;
209 }
210 
211 
212 // ATTRIBUTE: mode
213 t_max_err attr_set_mode(t_fade *x, void *attr, long argc, t_atom *argv)
214 {
215  x->attr_mode = atom_getlong(argv);
216  if (x->attr_mode == 0)
217  x->xfade->setAttributeValue(TT("Mode"), TT("lookup"));
218  else
219  x->xfade->setAttributeValue(TT("Mode"), TT("calculate"));
220 
221  return MAX_ERR_NONE;
222 }
223 
224 
225 // control rate fading
226 t_int *fade_perform1(t_int *w)
227 {
228  t_fade *x = (t_fade *)(w[1]);
229  short i, j;
230  TTUInt8 numChannels = x->audioIn1->getNumChannelsAsInt();
231  TTUInt16 vs = x->audioIn1->getVectorSizeAsInt();
232 
233  for (i=0; i<numChannels; i++) {
234  j = (i*3) + 1;
235  x->audioIn1->setVector(i, vs, (t_float *)(w[j+1]));
236  x->audioIn2->setVector(i, vs, (t_float *)(w[j+2]));
237  }
238 
239  x->xfade->process(*x->audioIn1, *x->audioIn2, *x->audioOut);
240 
241  for (i=0; i<numChannels; i++) {
242  j = (i*3) + 1;
243  x->audioOut->getVector(i, vs, (t_float *)(w[j+3]));
244  }
245 
246  return w + ((numChannels*3)+2);
247 }
248 
249 void fade_perform64_1(t_fade *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
250 {
251  short i;
252  TTUInt8 numChannels = x->audioIn1->getNumChannelsAsInt();
253  TTUInt16 vs = x->audioIn1->getVectorSizeAsInt();
254 
255  for (i=0; i<numChannels; i++) {
256  x->audioIn1->setVector(i, vs, ins[i]);
257  x->audioIn2->setVector(i, vs, ins[i+numChannels]);
258  }
259 
260  x->xfade->process(*x->audioIn1, *x->audioIn2, *x->audioOut);
261 
262  for (i=0; i<numChannels; i++)
263  x->audioOut->getVectorCopy(i, vs, outs[i]);
264 }
265 
266 // signal rate fading
267 t_int *fade_perform2(t_int *w)
268 {
269  t_fade *x = (t_fade *)(w[1]);
270  short i, j;
271  TTUInt16 numChannels = x->audioIn1->getNumChannelsAsInt();
272  TTUInt16 vs = x->audioIn1->getVectorSizeAsInt();
273 
274  for (i=0; i<numChannels; i++) {
275  j = (i*3) + 1;
276  x->audioIn1->setVector(i, vs, (t_float *)(w[j+1]));
277  x->audioIn2->setVector(i, vs, (t_float *)(w[j+2]));
278  }
279  object_attr_setfloat(x, _sym_position, *((t_float *)(w[(numChannels*3)+2])));
280 
281  x->xfade->process(*x->audioIn1, *x->audioIn2, *x->audioOut);
282 
283  for (i=0; i<numChannels; i++) {
284  j = (i*3) + 1;
285  x->audioOut->getVector(i, vs, (t_float *)(w[j+3]));
286  }
287 
288  return w + ((numChannels*3)+3);
289 
290 }
291 
292 void fade_perform64_2(t_fade *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
293 {
294  short i;
295  TTUInt16 numChannels = x->audioIn1->getNumChannelsAsInt();
296  TTUInt16 vs = x->audioIn1->getVectorSizeAsInt();
297 
298  for (i=0; i<numChannels; i++) {
299  x->audioIn1->setVector(i, vs, ins[i]);
300  x->audioIn2->setVector(i, vs, ins[i+numChannels]);
301  }
302  //TOOO: we cast the signal to a float, if Max can handle 64bit attributes, we should change that
303  object_attr_setfloat(x, _sym_position, (t_float)*ins[numChannels*2]);
304 
305  x->xfade->process(*x->audioIn1, *x->audioIn2, *x->audioOut);
306 
307  for (i=0; i<numChannels; i++)
308  x->audioOut->getVectorCopy(i, vs, outs[i]);
309 }
310 
311 // DSP Method
312 void fade_dsp(t_fade *x, t_signal **sp, short *count)
313 {
314  short i, j, k, l=0;
315  void **audioVectors = NULL;
316  TTUInt8 numChannels = 0;
317  TTUInt16 vs = 0;
318 
319  if (count[x->numChannels * 2]) // SIGNAL RATE CROSSFADE CONNECTED
320  audioVectors = (void**)sysmem_newptr(sizeof(void*) * ((x->numChannels * 3) + 2));
321  else // CONTROL RATE CROSSFADE
322  audioVectors = (void**)sysmem_newptr(sizeof(void*) * ((x->numChannels * 3) + 1));
323  audioVectors[l] = x;
324  l++;
325 
326  // audioVectors[] passed to balance_perform() as {x, audioInL[0], audioInR[0], audioOut[0], audioInL[1], audioInR[1], audioOut[1],...}
327  for (i=0; i < x->numChannels; i++) {
328  j = x->numChannels + i;
329  k = x->numChannels*2 + i + 1; // + 1 to account for the position input
330  if (count[i] && count[j] && count[k]) {
331  numChannels++;
332  if (sp[i]->s_n > vs)
333  vs = sp[i]->s_n;
334 
335  audioVectors[l] = sp[i]->s_vec;
336  l++;
337  audioVectors[l] = sp[j]->s_vec;
338  l++;
339  audioVectors[l] = sp[k]->s_vec;
340  l++;
341  }
342  }
343 
344  if (count[x->numChannels * 2]) { // SIGNAL RATE CROSSFADE CONNECTED
345  audioVectors[l] = sp[x->numChannels*2]->s_vec;
346  l++;
347  }
348 
349  x->audioIn1->setNumChannels(numChannels);
350  x->audioIn2->setNumChannels(numChannels);
351  x->audioOut->setNumChannels(numChannels);
352  x->audioIn1->setVectorSizeWithInt(vs);
353  x->audioIn2->setVectorSizeWithInt(vs);
354  x->audioOut->setVectorSizeWithInt(vs);
355  //audioIn will be set in the perform method
356  x->audioOut->alloc();
357 
358  x->xfade->setAttributeValue(kTTSym_sampleRate, sp[0]->s_sr);
359 
360  if (count[x->numChannels * 2]) // SIGNAL RATE CROSSFADE CONNECTED
361  dsp_addv(fade_perform2, l, audioVectors);
362  else
363  dsp_addv(fade_perform1, l, audioVectors);
364 
365  sysmem_freeptr(audioVectors);
366 }
367 
368 void fade_dsp64(t_fade *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
369 {
370  /*short i, j, k;
371  TTUInt8 numChannels = 0;
372 
373  // audioVectors[] passed to balance_perform() as {x, audioInL[0], audioInR[0], audioOut[0], audioInL[1], audioInR[1], audioOut[1],...}
374  for (i=0; i < x->numChannels; i++) {
375  j = x->numChannels + i;
376  k = x->numChannels*2 + i + 1; // + 1 to account for the position input
377  if (count[i] && count[j] && count[k])
378  numChannels++;
379  }
380  x->audioIn1->setNumChannels(numChannels);
381  x->audioIn2->setNumChannels(numChannels);
382  x->audioOut->setNumChannels(numChannels);*/
383 
384  x->audioIn1->setNumChannels(x->numChannels);
385  x->audioIn2->setNumChannels(x->numChannels);
386  x->audioOut->setNumChannels(x->numChannels);
387  x->audioIn1->setVectorSizeWithInt((TTUInt16)maxvectorsize);
388  x->audioIn2->setVectorSizeWithInt((TTUInt16)maxvectorsize);
389  x->audioOut->setVectorSizeWithInt((TTUInt16)maxvectorsize);
390  //audioIn will be set in the perform method
391  x->audioOut->alloc();
392 
393  x->xfade->setAttributeValue(kTTSym_sampleRate, samplerate);
394 
395  if (count[x->numChannels * 2]) // SIGNAL RATE CROSSFADE CONNECTED
396  object_method(dsp64, gensym("dsp_add64"), x, fade_perform64_2, 0, NULL);
397  else
398  object_method(dsp64, gensym("dsp_add64"), x, fade_perform64_1, 0, NULL);
399 }
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTErr TTObjectBaseRelease(TTObjectBasePtr *anObject)
DEPRECATED.
TTAudioObjectBase is the base class for all audio generating and processing objects in Jamoma DSP...
Jamoma DSP Library.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr *returnedObjectPtr, const TTValue arguments)
DEPRECATED.
The TTAudioSignal class represents N vectors of audio samples for M channels.
Definition: TTAudioSignal.h:57
void TTDSP_EXPORT TTDSPInit(const char *pathToBinaries=NULL)
Initialise the Jamoma DSP library, as well as Jamoma Foundation foundation if needed.
Definition: TTDSP.cpp:30
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
Definition: j.xfade~.cpp:66
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174