Jamoma API  0.6.0.a19
j.dbap_bformat.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.dbap_bformat - Distance Based Amplitude Panning using 4-channel ambisonic Bformat signals as sources.
6  *
7  * @details
8  *
9  * @authors Trond Lossius
10  *
11  * @copyright Copyright © 2011, Trond Lossius @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 "JamomaForMax.h"
17 #include "j.dbap_bformat.h"
18 
19 // Globals
20 t_class *this_class = 0; // Required. Global pointing to this class
21 
22 /************************************************************************************/
23 // Main() Function
24 
25 int JAMOMA_EXPORT_MAXOBJ main(void)
26 {
27  t_class *c;
28 
29  common_symbols_init();
30  psRollOff = gensym("rolloff");
31  psSourcePosition = gensym("source_position");
32  psSourceGain = gensym("source_gain");
33  psSourceMute = gensym("src_mute");
34  psSourceBlur = gensym("blur");
35  psDestinationPosition = gensym("destination_position");
36  psNumberOfSources = gensym("num_sources");
37  psNumberOfDestinations = gensym("num_destinations");
38 
39  // Define our class
40  c = class_new("j.dbap_bformat",(method)dbap_bformatNew, (method)0L, sizeof(t_dbap_bformat),
41  (method)0L, A_GIMME, 0);
42 
43  // Make methods accessible for our class:
44  class_addmethod(c, (method)dbap_bformatBlur, "blur", A_GIMME, 0);
45  class_addmethod(c, (method)dbap_bformatBlurAll, "blurall", A_FLOAT, 0);
46  class_addmethod(c, (method)dbap_bformatPolarity, "polarity", A_GIMME, 0);
47  class_addmethod(c, (method)dbap_bformatPolarityAll, "polarityall", A_FLOAT, 0);
48  class_addmethod(c, (method)dbap_bformatSource, "src_position", A_GIMME, 0);
49  class_addmethod(c, (method)dbap_bformatDestination, "dst_position", A_GIMME, 0);
50  class_addmethod(c, (method)dbap_bformatSourceGain, "src_gain", A_GIMME, 0);
51  class_addmethod(c, (method)dbap_bformatSourceWeight, "src_weight", A_GIMME, 0);
52  class_addmethod(c, (method)dbap_bformatMasterGain, "master_gain", A_FLOAT, 0);
53  class_addmethod(c, (method)dbap_bformatSourceMute, "src_mute", A_GIMME, 0);
54 
55  class_addmethod(c, (method)dbap_bformatAssist, "assist", A_CANT, 0);
56  class_addmethod(c, (method)dbap_bformatInfo, "info", 0);
57  class_addmethod(c, (method)object_obex_dumpout, "dumpout", 0);
58 
59  // Add attributes to our class:
60  CLASS_ATTR_LONG(c, "num_sources", 0, t_dbap_bformat, attrNumberOfSources);
61  CLASS_ATTR_ACCESSORS(c, "num_sources", NULL, dbap_bformatAttrSetNumberOfSources);
62 
63  CLASS_ATTR_LONG(c, "num_destinations", 0, t_dbap_bformat, attrNumberOfDestinations);
64  CLASS_ATTR_ACCESSORS(c, "num_destinations", NULL, dbap_bformatAttrSetNumberOfDestinations);
65 
66  CLASS_ATTR_DOUBLE(c, "rolloff", 0, t_dbap_bformat, attrRollOff);
67  CLASS_ATTR_ACCESSORS(c, "rolloff", NULL, dbap_bformatAttrSetRollOff);
68 
69  CLASS_ATTR_DOUBLE(c, "vicinity", 0, t_dbap_bformat, attrVicinity);
70  CLASS_ATTR_ACCESSORS(c, "vicinity", NULL, dbap_bformatAttrSetVicinity);
71 
72  // Finalize our class
73  class_register(CLASS_BOX, c);
74  this_class = c;
75  return 0;
76 }
77 
78 
79 /************************************************************************************/
80 // Object Life
81 #pragma mark -
82 #pragma mark object life
83 
84 void *dbap_bformatNew(t_symbol *msg, long argc, t_atom *argv)
85 {
86  t_dbap_bformat *x;
87  long i,j;
88 
89  x = (t_dbap_bformat *)object_alloc(this_class); // create the new instance and return a pointer to it
90 
91  if (x) {
92  object_obex_store(x, _sym_dumpout, (object *)outlet_new(x,NULL)); // dumpout
93  x->outlet = outlet_new(x, 0); // Left outlet: Feed to matrix~
94 
95  // Initializing and setting defaults for attributes.
96  x->masterGain = 1.; // default value
97  x->attrNumberOfSources = 1; // default value
98  x->attrNumberOfDestinations = 1; // default value
99  x->attrRollOff = 6; // 6 dB rolloff by default
100  x->attrVicinity = 0.15; // Radius of 0.15 by default
101 
102  for (i=0; i<MAX_NUM_SOURCES; i++) {
103  x->sourcePosition[i].x = 0.;
104  x->sourcePosition[i].y = 0.;
105  x->sourcePosition[i].z = 0.;
106  x->blur[i] = 0.000001;
107  x->sourceGain[i] = 1.0;
108  x->sourceNotMuted[i] = 1.0;
109  x->polarity[i] = 1.0;
110  }
111 
112  for (i=0; i<MAX_NUM_DESTINATIONS; i++) {
113  x->destinationPosition[i].x = 0.;
114  x->destinationPosition[i].y = 0.;
115  x->destinationPosition[i].z = 0.;
116  }
117 
118  for (i=0;i<MAX_NUM_SOURCES;i++) {
119  for (j=0;j<MAX_NUM_DESTINATIONS;j++) {
120  x->sourceWeight[i][j] = 1.;
121  // TODO: The following initialisation is preliminary
122  x->decodeCoefficients[i][j].w = 0.;
123  x->decodeCoefficients[i][j].x = 0.;
124  x->decodeCoefficients[i][j].y = 0.;
125  x->decodeCoefficients[i][j].z = 0.;
126  }
127  }
128 
129  attr_args_process(x, argc, argv); // Handle attribute args
130  dbap_bformatCalculateA(x); // Calculate expo0nent coefficiant used for rolloff
131  dbap_bformatCalculateVariance(x); // This implisitly also calculate all matrix values
132  }
133  return (x); // Return the pointer
134 }
135 
136 
137 
138 /********************************************************************************************/
139 // Methods bound to input/inlets
140 
141 #pragma mark -
142 #pragma mark methods
143 
144 
145 // set spatial blur for nth source
146 void dbap_bformatBlur(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
147 {
148  long n;
149  double f;
150 
151  if ((argc>=2) && argv) {
152  n = atom_getlong(argv)-1; // we start counting from 1 for sources
153  if ( (n<0) || (n>=MAX_NUM_SOURCES) ) {
154  error("Invalid argument(s) for blur");
155  return;
156  }
157  argv++;
158  f = atom_getfloat(argv);
159  if (f<0.000001)
160  f = 0.000001;
161  x->blur[n] = f;
162  dbap_bformatCalculate(x, n);
163  }
164  else
165  error("Invalid argument(s) for blur");
166 }
167 
168 // set spatial blur for all sources
170 {
171  long i;
172 
173  if (f<0.000001)
174  f = 0.000001;
175  for (i=0; i<x->attrNumberOfSources; i++) {
176  x->blur[i] = f;
177  dbap_bformatCalculate(x, i);
178  }
179 }
180 
181 // set polarity for nth source
182 void dbap_bformatPolarity(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
183 {
184  long n;
185  double f;
186 
187  if ((argc>=2) && argv) {
188  n = atom_getlong(argv)-1; // we start counting from 1 for sources
189  if ( (n<0) || (n>=MAX_NUM_SOURCES) ) {
190  error("Invalid argument(s) for blur");
191  return;
192  }
193  argv++;
194  f = atom_getfloat(argv);
195  if (f<0.0)
196  f = 0.0;
197  if (f>1.0)
198  f = 1.0;
199  x->polarity[n] = f;
200  dbap_bformatCalculate(x, n);
201  }
202  else
203  error("Invalid argument(s) for blur");
204 }
205 
206 
207 // Set polarity for all sources
209 {
210  long i;
211 
212  if (f<0.0)
213  f = 0.0;
214  if (f>1.0)
215  f = 1.0;
216  for (i=0; i<x->attrNumberOfSources; i++) {
217  x->polarity[i] = f;
218  dbap_bformatCalculate(x, i);
219  }
220 }
221 
222 // set source position and calculate output
223 void dbap_bformatSource(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
224 {
225  long n;
226 
227  if (argc >= 4) {
228  n = atom_getlong(argv)-1; // we start counting from 1 for sources
229  if ( (n<0) || (n>=MAX_NUM_DESTINATIONS) ) {
230  error("Invalid arguments for source.");
231  return;
232  }
233 
234  x->sourcePosition[n].x = atom_getfloat(argv+1);
235  x->sourcePosition[n].y = atom_getfloat(argv+2);
236  x->sourcePosition[n].z = atom_getfloat(argv+3);
237 
238  dbap_bformatCalculate(x, n);
239  }
240  else
241  error("Invalid arguments for source.");
242 }
243 
244 
245 // set position of a destination
246 void dbap_bformatDestination(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
247 {
248  long n;
249 
250  if (argc >= 4) {
251  n = atom_getlong(argv)-1; // we start counting from 1 for destinations
252  if ( (n<0) || (n>=MAX_NUM_DESTINATIONS) ) {
253  error("Invalid arguments for destination.");
254  return;
255  }
256  x->destinationPosition[n].x = atom_getfloat(argv+1);
257  x->destinationPosition[n].y = atom_getfloat(argv+2);
258  x->destinationPosition[n].z = atom_getfloat(argv+3);
259 
260  // The set of destination points has been changed - recalculate variance.
261  dbap_bformatCalculateVariance(x); // implicitely updates all matrix values
262  }
263  else
264  error("Invalid arguments for speaker.");
265 }
266 
267 
268 void dbap_bformatSourceGain(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
269 {
270  long n;
271  double f;
272 
273  if ((argc>=2) && argv) {
274  n = atom_getlong(argv)-1; // we start counting from 1 for sources
275  if ( (n<0) || (n>=MAX_NUM_SOURCES) ) {
276  error("Invalid argument(s) for source_gain");
277  return;
278  }
279  argv++;
280  f = atom_getfloat(argv);
281  if (f<0.0)
282  f = 0.0;
283  x->sourceGain[n] = f;
284  dbap_bformatCalculate(x, n);
285  }
286  else
287  error("Invalid argument(s) for source_gain");
288 }
289 
290 
291 
293 {
294  long i;
295 
296  x->masterGain = f;
297  if (x->masterGain<0.)
298  x->masterGain = 0;
299 
300  // Update all matrix values
301  for (i=0; i<x->attrNumberOfSources; i++)
302  dbap_bformatCalculate(x, i);
303 }
304 
305 void dbap_bformatSourceWeight(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
306 {
307  long source, i;
308  double weight;
309 
310  if (argc && argv) {
311 
312  if (atom_gettype(argv) == A_LONG) { // the first argument is the source number
313  source = atom_getlong(argv)-1; // we start counting from 1 for sources
314 
315  if ((source < 0)||(source >= x->attrNumberOfSources)) {
316  object_error((t_object*)x, "sourceWeight : the source n°%d doesn't exist", source+1);
317  return;
318  }
319  }
320  else {
321  object_error((t_object*)x, "sourceWeight : no source id");
322  return;
323  }
324 
325  for (i=0; i<x->attrNumberOfDestinations; i++) { // the rest is the list of weights for each destination
326 
327  if (i+1 < argc) {
328  if (atom_gettype(&argv[i+1]) == A_LONG)
329  weight = (float)atom_getlong(&argv[i+1]);
330 
331  if (atom_gettype(&argv[i+1]) == A_FLOAT)
332  weight = atom_getfloat(&argv[i+1]);
333  }
334  else
335  weight = 0.0; // if the list is smaller than the sourceWeight array, fill sourceWeight with 0.0
336 
337  if (weight < 0.0)
338  weight = 0.0;
339 
340  x->sourceWeight[source][i] = weight;
341  }
342 
343  dbap_bformatCalculate(x, source);
344  }
345  else
346  object_error((t_object*)x, "sourceWeight : needs arguments");
347 }
348 
349 void dbap_bformatSourceMute(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
350 {
351  long n;
352 
353  if ((argc>=2) && argv) {
354  n = atom_getlong(argv)-1; // we start counting from 1 for sources
355  if ( (n<0) || (n>=MAX_NUM_SOURCES) ) {
356  error("Invalid argument(s) for source_gain");
357  return;
358  }
359  argv++;
360  x->sourceNotMuted[n] = (atom_getfloat(argv)==0.0);
361  dbap_bformatCalculate(x, n);
362  }
363  else
364  error("Invalid argument(s) for source_gain");
365 }
366 
368 {
369  t_atom a[4];
370  long i;
371 
372  atom_setfloat(&a[0], x->attrRollOff);
373  object_obex_dumpout(x, psRollOff, 1, a);
374 
375  atom_setlong(&a[0], x->attrNumberOfSources);
376  object_obex_dumpout(x, psNumberOfSources, 1, a);
377 
378  for (i=0; i<x->attrNumberOfSources; i++) {
379  atom_setlong(&a[0], i+1);
380  atom_setfloat(&a[1], x->sourcePosition[i].x);
381  atom_setfloat(&a[2], x->sourcePosition[i].y);
382  atom_setfloat(&a[3], x->sourcePosition[i].z);
383  object_obex_dumpout(x, psSourcePosition, 4, a);
384  atom_setfloat(&a[1], x->sourceGain[i]);
385  object_obex_dumpout(x, psSourceGain, 2, a);
386  atom_setlong(&a[1], (x->sourceNotMuted[i]==0));
387  object_obex_dumpout(x, psSourceMute, 2, a);
388  atom_setfloat(&a[1], x->blur[i]);
389  object_obex_dumpout(x, psSourceBlur, 1, a);
390  }
391 
392  atom_setlong(&a[0], x->attrNumberOfDestinations);
393  object_obex_dumpout(x, psNumberOfDestinations, 1, a);
394 
395  for (i=0; i<x->attrNumberOfDestinations; i++) {
396  atom_setlong(&a[0], i+1);
397  atom_setfloat(&a[1], x->destinationPosition[i].x);
398  atom_setfloat(&a[2], x->destinationPosition[i].y);
399  atom_setfloat(&a[3], x->destinationPosition[i].z);
400  object_obex_dumpout(x, psDestinationPosition, 4, a);
401  }
402 }
403 
404 
405 // Method for Assistance Messages
406 void dbap_bformatAssist(t_dbap_bformat *x, void *b, long msg, long arg, char *dst) // Display assistance messages
407 {
408  if (msg==1)
409  {
410  switch(arg)
411  {
412  case 0:
413  strcpy(dst, "set source and speaker positions");
414  break;
415  }
416  }
417  else if (msg==2)
418  {
419  switch(arg)
420  {
421  case 0:
422  strcpy(dst, "(list) messages for matrix~");
423  break;
424  case 1:
425  strcpy(dst, "dumpout");
426  break;
427  }
428  }
429 }
430 
431 
432 /************************************************************************************/
433 // Methods bound to attributes
434 #pragma mark -
435 #pragma mark attribute accessors
436 
437 
438 // ATTRIBUTE: number of sources
439 t_max_err dbap_bformatAttrSetNumberOfSources(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
440 {
441  long n;
442 
443  if (argc && argv) {
444  n = atom_getlong(argv);
445  if (n<0)
446  n = 0;
447  if (n>MAX_NUM_SOURCES)
448  n = MAX_NUM_SOURCES;
449  x->attrNumberOfSources = n;
450  // The set of destination points has been changed - recalculate blur radius.
451  }
452  return MAX_ERR_NONE;
453 }
454 
455 // ATTRIBUTE: number of destinations
456 t_max_err dbap_bformatAttrSetNumberOfDestinations(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
457 {
458  long n;
459 
460  if (argc && argv) {
461  n = atom_getlong(argv);
462  if (n<0)
463  n = 0;
464  if (n>MAX_NUM_DESTINATIONS)
465  n = MAX_NUM_DESTINATIONS;
467  // The set of destination points has been changed - recalculate blur radius.
469  }
470  return MAX_ERR_NONE;
471 }
472 
473 
474 // ATTRIBUTE: rolloff
475 t_max_err dbap_bformatAttrSetRollOff(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
476 {
477  double f;
478  long i;
479 
480  if (argc && argv) {
481  f = atom_getfloat(argv);
482  if (f<=0.0) {
483  error("Invalid argument for rolloff. Must be > 0");
484  return MAX_ERR_NONE;;
485  }
486  x->attrRollOff = f;
488  // Update all matrix values
489  for (i=0; i<x->attrNumberOfSources; i++)
490  dbap_bformatCalculate(x, i);
491  }
492  return MAX_ERR_NONE;
493 }
494 
495 // ATTRIBUTE: vicinity
496 t_max_err dbap_bformatAttrSetVicinity(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
497 {
498  double f;
499  long i;
500 
501  if (argc && argv) {
502  f = atom_getfloat(argv);
503  if (f<=0.0) {
504  error("Invalid argument for vicinity. Must be > 0");
505  return MAX_ERR_NONE;;
506  }
507  x->attrVicinity = f;
508  // Update all matrix values
509  for (i=0; i<x->attrNumberOfSources; i++)
510  dbap_bformatCalculate(x, i);
511  }
512  return MAX_ERR_NONE;
513 }
514 
515 
516 /************************************************************************************/
517 // Methods bound to calculations
518 #pragma mark -
519 #pragma mark calculations
520 
521 
523 {
524  double scalingCoefficient; // Scaling coefficient
525  double scalingCoefficientSquareInverse; // Inverse square of the scaling coefficient
526  double dx, dy, dz; // Distance vector
527  double blurSquared; // Bluriness ratio squared
528  double distanceAdjusted
529  [MAX_NUM_DESTINATIONS]; // Distance to ith speaker to the power of x->a, adjusted to prevent division by zero
530 
531  double sourceSpeakerWeight; // Calculated weight for current pair of source and speaker
532 
533  long i;
534 
535  // Required for ambisonic decoding
536  double horisontalDistance; // Distance from source to destination in the horizontal plane
537  double distance; // Distance from source to destination in 3D
538  double cosAzimuth; // cos(azimuth)
539  double sinAzimuth; // sin(azimuth)
540  double cosElevation; // cos(elevation)
541  double sinElevation; // sin(elevation)
542  double k0, k1; // Polarity coefficients
543  double d; // Distance relative to attrVicinity
544 
545  t_atom a[3]; // Output array of atoms
546 
547  blurSquared = x->blur[n] * x->variance;
548  blurSquared = blurSquared*blurSquared;
549 
550 
551 
552  scalingCoefficientSquareInverse = 0;
553 
554  for (i=0; i<x->attrNumberOfDestinations; i++) {
555 
556  // Calculations of dx and dy might seem strange, but are due to the rotation
557  // of spherical vs. Cartesian coordinate systems in SpatDIF
558  dx = x->destinationPosition[i].y - x->sourcePosition[n].y;
559  dy = x->sourcePosition[n].x - x->destinationPosition[i].x;
560  dz = x->destinationPosition[i].z - x->sourcePosition[n].z;
561 
562  // Absolute and horisontal distance
563  horisontalDistance = sqrt(dx*dx + dy*dy);
564  distance = sqrt(dx*dx + dy*dy + dz*dz);
565 
566  // Calculate ambisonics decoding coefficients
567  if (distance<=0.0) {
568  // If source is positioned at exact same location as speaker, we use only omni signal
569  x->decodeCoefficients[n][i].w = sqrt(3.);
570  x->decodeCoefficients[n][i].x = 0.0;
571  x->decodeCoefficients[n][i].y = 0.0;
572  x->decodeCoefficients[n][i].z = 0.0;
573  }
574  else {
575  k1 = x->polarity[n];
576 
577  // And now we converge to omni if the source is in the vicinity of the speaker
578  if (distance<x->attrVicinity) {
579  d = distance/x->attrVicinity;
580  d = (d*d*d*(d*(6*d-15)+10)); // This is a function that change smoothly from 1 to 0 as source approach the speaker
581  k1 = k1 * (d*d*d*(d*(6*d-15)+10));
582 
583  }
584 
585  // Control polarity while keeping intensity constant:
586  // If polarity = 1: k0=sqrt(2), k1=1 : This is standard in-phase FuMa decoding coefficients
587  // If polarity = 0: k0=sqrt(3), k1=0 : Removes all directivity and decodes omni signal only
588  k0 = sqrt(3.0-k1);
589 
590  // Get cos and sin of azimuth and elevation
591  if (horisontalDistance>0.0) {
592  cosAzimuth = dx/horisontalDistance;
593  sinAzimuth = dy/horisontalDistance;
594  }
595  else {
596  // Avoid dividing by zero (the following two values will be cancelled out anyway)
597  cosAzimuth = 1.0;
598  sinAzimuth = 0.0;
599  }
600  cosElevation = horisontalDistance/distance;
601  sinElevation = dz/distance;
602 
603  x->decodeCoefficients[n][i].w = k0;
604  x->decodeCoefficients[n][i].x = k1 * cosAzimuth * cosElevation;
605  x->decodeCoefficients[n][i].y = k1 * sinAzimuth * cosElevation;
606  x->decodeCoefficients[n][i].z = k1 * sinElevation;
607  }
608 
609  // Now move on to calculations required for DBAP
610 
611  // Distance adjusted to prevent division by zero
612  distanceAdjusted[i] = pow(double(dx*dx + dy*dy + dz*dz + blurSquared), double(0.5*x->a));
613 
614  scalingCoefficientSquareInverse = scalingCoefficientSquareInverse + (x->sourceWeight[n][i]*x->sourceWeight[n][i])/(distanceAdjusted[i]*distanceAdjusted[i]);
615  }
616 
617  scalingCoefficient = sqrt(1./scalingCoefficientSquareInverse);
618  scalingCoefficient = scalingCoefficient * x->masterGain * x->sourceGain[n] * x->sourceNotMuted[n];
619 
620  for (i=0; i<x->attrNumberOfDestinations; i++) {
621  sourceSpeakerWeight = x->sourceWeight[n][i] * scalingCoefficient / distanceAdjusted[i];
622  atom_setlong(&a[1], i);
623 
624  // W signal
625  atom_setlong(&a[0], n*4);
626  atom_setfloat(&a[2], sourceSpeakerWeight * x->decodeCoefficients[n][i].w);
627  outlet_anything(x->outlet, _sym_list, 3, a);
628 
629  // X signal
630  atom_setlong(&a[0], n*4+1);
631  atom_setfloat(&a[2], sourceSpeakerWeight * x->decodeCoefficients[n][i].x);
632  outlet_anything(x->outlet, _sym_list, 3, a);
633 
634  // Y signal
635  atom_setlong(&a[0], n*4+2);
636  atom_setfloat(&a[2], sourceSpeakerWeight * x->decodeCoefficients[n][i].y);
637  outlet_anything(x->outlet, _sym_list, 3, a);
638 
639  // Z signal
640  atom_setlong(&a[0], n*4+3);
641  atom_setfloat(&a[2], sourceSpeakerWeight * x->decodeCoefficients[n][i].z);
642  outlet_anything(x->outlet, _sym_list, 3, a);
643  }
644 }
645 
646 
648 {
649  x->a = log(pow(10., (x->attrRollOff / 20.)))/log(2.);
650 }
651 
652 
654 {
655  long i;
656  double a,b,c;
657 
658  a = 0;
659  b = 0;
660  c = 0;
661  for (i=0; i<x->attrNumberOfDestinations; i++) {
662  a += x->destinationPosition[i].x;
663  b += x->destinationPosition[i].y;
664  c += x->destinationPosition[i].z;
665  }
669 }
670 
671 
673 {
674  long i;
675  double dx, dy, dz;
676  double d2=0;
677 
678 
680 
681  for (i=0; i<x->attrNumberOfDestinations; i++) {
685  d2 += dx*dx + dy*dy + dz*dz;
686  }
687 
688  x->variance = sqrt(d2/(x->attrNumberOfDestinations-1));
689 
690  // Update all matrix values
691  for (i=0; i<x->attrNumberOfSources; i++)
692  dbap_bformatCalculate(x, i);
693 }
t_max_err dbap_bformatAttrSetNumberOfSources(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
Set the number of sources of the system.
t_xyz destinationPosition[MAX_NUM_DESTINATIONS]
Array of speaker positions.
t_xyz meanDestinationPosition
Mean position of the field of destination points.
void dbap_bformatAssist(t_dbap_bformat *x, void *b, long msg, long arg, char *dst)
Display assist strings while patching.
void dbap_bformatInfo(t_dbap_bformat *x)
Get info on destination setup ++.
void dbap_bformatSource(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
Set the position of the nth virtual source.
long attrNumberOfDestinations
Number of active destinations.
Structure for the j.dbap_bformat Max object.
double blur[MAX_NUM_SOURCES]
Spatial bluriness ratio in percents for each source.
t_xyz sourcePosition[MAX_NUM_SOURCES]
Positions of the virtual source.
t_max_err dbap_bformatAttrSetVicinity(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
Set radius of vicinity field around speaker where decoding will converge towards omni.
void dbap_bformatMasterGain(t_dbap_bformat *x, double f)
Set master gain for all values passed from the object to matrix~.
void dbap_bformatCalculateA(t_dbap_bformat *x)
Calculation of exponent coefficient based on rolloff.
double w
Zero order W coefficient.
double x
x position
Definition: j.dbap.h:44
double masterGain
Mater gain for all of the algorithm.
double attrVicinity
Set radius of field of vicinity around speaker where decoding gets increasingly omni.
double y
First order Y coefficient.
void dbap_bformatBlurAll(t_dbap_bformat *x, double f)
Set spatial blur for all sources.
Various utilities for interfacing with Max that are not specific to JamomaModular as such...
void dbap_bformatSourceGain(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
Set input gain for nth source.
void dbap_bformatSourceWeight(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
Set weight for nth source by passing a list to balance each destination.
double attrRollOff
Set rolloff with distance in dB.
double z
z position
Definition: j.dbap.h:46
double sourceNotMuted[MAX_NUM_SOURCES]
Mute and unmute sources.
void dbap_bformatPolarityAll(t_dbap_bformat *x, double f)
Set polarity for all sources.
t_decodeCoefficients decodeCoefficients[MAX_NUM_SOURCES][MAX_NUM_DESTINATIONS]
Ambisonics decoding coefficients for each source for each destination.
t_max_err dbap_bformatAttrSetRollOff(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
Set rolloff in dB.
void dbap_bformatSourceMute(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
Mute and unmute sources.
double x
First order X coefficient.
double a
Constant: Exponent controlling amplitude dependance on distance. Depends on attrRollOff.
double y
y position
Definition: j.dbap.h:45
j.dbap_bformat - Distance Based Amplitude Panning using 4-channel ambisonic Bformat signals as source...
void dbap_bformatPolarity(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
Set polarity of the nth virtual source.
double sourceGain[MAX_NUM_SOURCES]
Linear gain for each source, not yet used.
void dbap_bformatBlur(t_dbap_bformat *x, t_symbol *msg, long argc, t_atom *argv)
Set spatial blur for nth source.
double polarity[MAX_NUM_SOURCES]
Polarity for each source, from 0 (omni) to 1 (in-phase) decoding.
int JAMOMA_EXPORT_MAXOBJ main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
void dbap_bformatCalculateVariance(t_dbap_bformat *x)
Calculate bias-corrected variance of distance from destination points to mean destination point...
double z
First order Z coefficient.
void dbap_bformatCalculateMeanDestinationPosition(t_dbap_bformat *x)
Calculate mean position of the destination points.
double variance
Bias-corrected variance of distance from destination points to mean destination point.
t_class * this_class
Required. Global pointing to this class.
Definition: j.envexp.cpp:108
long attrNumberOfSources
number of active sources
t_max_err dbap_bformatAttrSetNumberOfDestinations(t_dbap_bformat *x, void *attr, long argc, t_atom *argv)
Set the number of destinations of the system.
double sourceWeight[MAX_NUM_SOURCES][MAX_NUM_DESTINATIONS]
Weight for each source for each destination.
void dbap_bformatCalculate(t_dbap_bformat *x, long n)
General method for calculation of matrix coefficient for nth source.
void dbap_bformatDestination(t_dbap_bformat *x, void *msg, long argc, t_atom *argv)
Set the position of the nth speaker.