@@ -87,19 +87,19 @@ using nova::wrap_argument;
8787
8888#endif
8989
90- #define RES_ID 9171 /* resource ID for assistance (we'll add that later) */
91- #define MAX_LS_SETS 100 /* maximum number of loudspeaker sets (triplets or pairs) allowed */
92- #define MAX_LS_AMOUNT 55 /* maximum amount of loudspeakers, can be increased */
9390
9491static InterfaceTable *ft;
9592
93+ static float rad2ang = 360.0 / ( 2 .0f * pi );
94+ static float atorad = (2 .0f * pi) / 360 .0f ;
95+
9696struct VBAP : Unit
9797{
9898 float x_azi; /* panning direction azimuth */
9999 float x_ele; /* panning direction elevation */
100- float x_set_inv_matx[MAX_LS_SETS][ 9 ] ; /* inverse matrice for each loudspeaker set */
101- float x_set_matx[MAX_LS_SETS][ 9 ]; /* matrice for each loudspeaker set */
102- int x_lsset[MAX_LS_SETS][ 3 ]; /* channel numbers of loudspeakers in each LS set */
100+ float * * x_set_inv_matx; /* inverse matrice for each loudspeaker set */
101+ float * * x_set_matx; /* matrice for each loudspeaker set */
102+ int * * x_lsset; /* channel numbers of loudspeakers in each LS set */
103103 int x_lsset_available; /* have loudspeaker sets been defined with define_loudspeakers */
104104 int x_lsset_amount; /* amount of loudspeaker sets */
105105 int x_ls_amount; /* amount of loudspeakers */
@@ -108,7 +108,7 @@ struct VBAP : Unit
108108 float x_spread_base[3 ]; /* used to create uniform spreading */
109109 float *final_gs;
110110
111- float m_chanamp[MAX_LS_AMOUNT]; // for smoothing amp changes max channels 55 at the moment
111+ float * m_chanamp;
112112};
113113
114114// for circular smoothing
@@ -140,7 +140,6 @@ extern "C"
140140static void angle_to_cart (float azi, float ele, float res[3 ])
141141/* converts angular coordinates to cartesian */
142142{
143- float atorad = (2 * 3.1415927 / 360 ) ;
144143 res[0 ] = cos ((float ) azi * atorad) * cos ((float ) ele * atorad);
145144 res[1 ] = sin ((float ) azi * atorad) * cos ((float ) ele * atorad);
146145 res[2 ] = sin ((float ) ele * atorad);
@@ -149,10 +148,6 @@ static void angle_to_cart(float azi, float ele, float res[3])
149148static void cart_to_angle (float cvec[3 ], float avec[3 ])
150149/* converts cartesian coordinates to angular */
151150{
152- // float tmp, tmp2, tmp3, tmp4; /* warning: unused variable */
153- float atorad = (2 * 3.1415927 / 360 ) ;
154- float pi = 3.1415927 ;
155- // float power; /* warning: unused variable */
156151 float dist, atan_y_per_x, atan_x_pl_y_per_z;
157152 float azi, ele;
158153
@@ -187,14 +182,13 @@ static void new_spread_dir(VBAP *x, float spreaddir[3], float vscartdir[3], floa
187182{
188183 float beta,gamma;
189184 float a,b;
190- float pi = 3.1415927 ;
191185 float power;
192186
193187 gamma = acos (vscartdir[0 ] * spread_base[0 ] +
194188 vscartdir[1 ] * spread_base[1 ] +
195189 vscartdir[2 ] * spread_base[2 ])/pi*180 ;
196- if (fabs (gamma) < 1 ){
197- angle_to_cart (x->x_azi +90 , 0 , spread_base);
190+ if (fabs (gamma) < 1 || fabs (gamma) > 179 || fabs (gamma) < - 179 ){
191+ angle_to_cart (x->x_azi +90.0 , 0 , spread_base);
198192 gamma = acos (vscartdir[0 ] * spread_base[0 ] +
199193 vscartdir[1 ] * spread_base[1 ] +
200194 vscartdir[2 ] * spread_base[2 ])/pi*180 ;
@@ -217,7 +211,6 @@ static void new_spread_base(VBAP *x, float spreaddir[3], float vscartdir[3])
217211/* subroutine for spreading */
218212{
219213 float d;
220- float pi = 3.1415927 ;
221214 float power;
222215
223216 d = cos (x->x_spread /180 *pi);
@@ -254,11 +247,9 @@ static void additive_vbap(float *final_gs, float cartdir[3], VBAP *x)
254247 float small_g;
255248 float big_sm_g, gtmp[3 ];
256249 int winner_set;
257- // float new_cartdir[3]; /* warning: unused variable */
258- // float new_angle_dir[3]; /* warning: unused variable */
259250 int dim = x->x_dimension ;
260251 int neg_g_am, best_neg_g_am;
261- float g[3 ];
252+ float g[3 ] = { 0 , 0 , 0 } ;
262253 int ls[3 ] = { 0 , 0 , 0 };
263254
264255 big_sm_g = -100000.0 ;
@@ -302,25 +293,19 @@ static void additive_vbap(float *final_gs, float cartdir[3], VBAP *x)
302293 if (g[i]<-0.01 ){
303294 gains_modified=1 ;
304295 }
305-
306- if (gains_modified != 1 ){
307- if (dim==3 )
308- power=sqrt (g[0 ]*g[0 ] + g[1 ]*g[1 ] + g[2 ]*g[2 ]);
309- else
310- power=sqrt (g[0 ]*g[0 ] + g[1 ]*g[1 ]);
311- g[0 ] /= power;
312- g[1 ] /= power;
313- if (dim==3 )
314- g[2 ] /= power;
315-
316- final_gs[ls[0 ]-1 ] += g[0 ];
317- final_gs[ls[1 ]-1 ] += g[1 ];
318- /* BUG FIX: this was causing negative indices with 2 dimensions so I
319- * made it only try when using 3 dimensions.
320- * 2006-08-13 <[email protected] > */ 321- if (dim==3 )
322- final_gs[ls[2 ]-1 ] += g[2 ];
323- }
296+
297+ // new from PD
298+ if (gains_modified != 1 ){
299+ power=sqrt (g[0 ]*g[0 ] + g[1 ]*g[1 ] + g[2 ]*g[2 ]);
300+ g[0 ] /= power;
301+ g[1 ] /= power;
302+ g[2 ] /= power;
303+
304+ final_gs[ls[0 ]-1 ] += g[0 ];
305+ final_gs[ls[1 ]-1 ] += g[1 ];
306+ if (dim==3 )
307+ final_gs[ls[2 ]-1 ] += g[2 ];
308+ }
324309}
325310
326311static void spread_it (VBAP *x, float *final_gs)
@@ -413,23 +398,28 @@ static void vbap(float g[3], int ls[3], VBAP *x)
413398 float new_angle_dir[3 ];
414399 int dim = x->x_dimension ;
415400 int neg_g_am, best_neg_g_am;
416-
417- /* transfering the azimuth angle to a decent value */
418- while (x->x_azi > 180 )
419- x->x_azi -= 360 ;
420- while (x->x_azi < -179 )
421- x->x_azi += 360 ;
422-
423- /* transferring the elevation to a decent value */
424- if (dim == 3 ){
425- while (x->x_ele > 180 )
426- x->x_ele -= 360 ;
427- while (x->x_ele < -179 )
428- x->x_ele += 360 ;
429- } else
430- x->x_ele = 0 ;
431-
432-
401+
402+ // new from PD
403+ // transfering the azimuth angle to a decent value
404+ if (x->x_azi > 360.0 || x->x_azi < -360.0 )
405+ x->x_azi = fmod (x->x_azi , 360.0 );
406+ if (x->x_azi > 180.0 )
407+ x->x_azi -= 360.0 ;
408+ if (x->x_azi < -179.0 )
409+ x->x_azi += 360.0 ;
410+
411+
412+ // transferring the elevation to a decent value
413+ if (dim == 3 ){
414+ if (x->x_ele > 360.0 || x->x_ele < -360.0 )
415+ x->x_ele = fmod (x->x_ele , 360.0 );
416+ if (x->x_ele > 180.0 )
417+ x->x_ele -= 360.0 ;
418+ if (x->x_ele < -179.0 )
419+ x->x_ele += 360.0 ;
420+ } else
421+ x->x_ele = 0.0 ;
422+
433423 /* go through all defined loudspeaker sets and find the set which
434424 // has all positive values. If such is not found, set with largest
435425 // minimum value is chosen. If at least one of gain factors of one LS set is negative
@@ -472,29 +462,30 @@ static void vbap(float g[3], int ls[3], VBAP *x)
472462 // calculate direction that corresponds to these new
473463 // gain values. This happens when the virtual source is outside of
474464 // all loudspeaker sets. */
475-
476- if (dim==3 ){
477- gains_modified=0 ;
478- for (i=0 ;i<dim;i++)
479- if (g[i]<-0.01 ){
480- g[i]=0.0001 ;
481- gains_modified=1 ;
482- }
483- if (gains_modified==1 ){
484- new_cartdir[0 ] = x->x_set_matx [winner_set][0 ] * g[0 ]
485- + x->x_set_matx [winner_set][1 ] * g[1 ]
486- + x->x_set_matx [winner_set][2 ] * g[2 ];
487- new_cartdir[1 ] = x->x_set_matx [winner_set][3 ] * g[0 ]
488- + x->x_set_matx [winner_set][4 ] * g[1 ]
489- + x->x_set_matx [winner_set][5 ] * g[2 ];
490- new_cartdir[2 ] = x->x_set_matx [winner_set][6 ] * g[0 ]
491- + x->x_set_matx [winner_set][7 ] * g[1 ]
492- + x->x_set_matx [winner_set][8 ] * g[2 ];
493- cart_to_angle (new_cartdir,new_angle_dir);
494- x->x_azi = (float ) (new_angle_dir[0 ] + 0.5 );
495- x->x_ele = (float ) (new_angle_dir[1 ] + 0.5 );
496- }
497- }
465+
466+ gains_modified=0 ;
467+ for (i=0 ;i<dim;i++)
468+ if (g[i]<-0.01 ){
469+ g[i]=0.0001 ;
470+ gains_modified=1 ;
471+ }
472+
473+ if (gains_modified==1 ){
474+ new_cartdir[0 ] = x->x_set_matx [winner_set][0 ] * g[0 ]
475+ + x->x_set_matx [winner_set][1 ] * g[1 ]
476+ + x->x_set_matx [winner_set][2 ] * g[2 ];
477+ new_cartdir[1 ] = x->x_set_matx [winner_set][3 ] * g[0 ]
478+ + x->x_set_matx [winner_set][4 ] * g[1 ]
479+ + x->x_set_matx [winner_set][5 ] * g[2 ];
480+ if (dim == 3 ) {
481+ new_cartdir[2 ] = x->x_set_matx [winner_set][6 ] * g[0 ]
482+ + x->x_set_matx [winner_set][7 ] * g[1 ]
483+ + x->x_set_matx [winner_set][8 ] * g[2 ];
484+ } else new_cartdir[2 ] = 0 ;
485+ cart_to_angle (new_cartdir,new_angle_dir);
486+ x->x_azi = (new_angle_dir[0 ]);
487+ x->x_ele = (new_angle_dir[1 ]);
488+ }
498489
499490 power=sqrt (g[0 ]*g[0 ] + g[1 ]*g[1 ] + g[2 ]*g[2 ]);
500491 g[0 ] /= power;
@@ -605,10 +596,14 @@ static inline_functions void VBAP_next_simd(VBAP *unit, int inNumSamples)
605596}
606597#endif
607598
599+ // needs to check that numOutputs and x_ls_amount match!!
608600static void VBAP_Ctor (VBAP* unit)
609601{
602+ // printf("VBAP-1.0.3.2\n");
610603 int numOutputs = unit->mNumOutputs , counter = 0 , datapointer=0 , setpointer=0 , i;
611-
604+
605+ unit->m_chanamp = (float *)RTAlloc (unit->mWorld , numOutputs * sizeof (float ));
606+
612607 // initialise interpolation levels and outputs
613608 for (int i=0 ; i<numOutputs; ++i) {
614609 unit->m_chanamp [i] = 0 ;
@@ -660,6 +655,15 @@ static void VBAP_Ctor(VBAP* unit)
660655// return;
661656 }
662657
658+ unit->x_set_inv_matx = (float **)RTAlloc (unit->mWorld , counter * sizeof (float *));
659+ unit->x_set_matx = (float **)RTAlloc (unit->mWorld , counter * sizeof (float *));
660+ unit->x_lsset = (int **)RTAlloc (unit->mWorld , counter * sizeof (int *));
661+
662+ for (i=0 ; i<counter; i++){
663+ unit->x_set_inv_matx [i] = (float *)RTAlloc (unit->mWorld , 9 * sizeof (float ));
664+ unit->x_set_matx [i] = (float *)RTAlloc (unit->mWorld , 9 * sizeof (float ));
665+ unit->x_lsset [i] = (int *)RTAlloc (unit->mWorld , 3 * sizeof (int ));
666+ }
663667 // probably sets should be created with rtalloc
664668 while (counter-- > 0 ){
665669 for (i=0 ; i < unit->x_dimension ; i++){
@@ -688,23 +692,52 @@ static void VBAP_Ctor(VBAP* unit)
688692#endif
689693 SETCALC (VBAP_next);
690694
691- if (unit->x_lsset_available == 1 ) {
692- unit->x_spread_base [0 ] = 0.0 ;
693- unit->x_spread_base [1 ] = 1.0 ;
694- unit->x_spread_base [2 ] = 0.0 ;
695- VBAP_next (unit, 1 ); // calculate initial gain factors && compute initial sample
696- } else {
697- ZOUT0 (0 ) = 0 ;
695+ ZOUT0 (0 ) = ZIN0 (0 );
696+ unit->x_azi = ZIN0 (2 );
697+ unit->x_ele = ZIN0 (3 );
698+ unit->x_spread_base [0 ] = 0.0 ;
699+ unit->x_spread_base [1 ] = 1.0 ;
700+ unit->x_spread_base [2 ] = 0.0 ;
701+ unit->x_spread = ZIN0 (4 );
702+
703+ // calculate initial gain factors
704+ float g[3 ];
705+ int ls[3 ];
706+ float *final_gs = unit->final_gs ;
707+
708+ if (unit->x_lsset_available ==1 ){
709+ vbap (g,ls, unit);
710+ for (i=0 ;i<unit->x_ls_amount ;i++)
711+ final_gs[i]=0.0 ;
712+ for (i=0 ;i<unit->x_dimension ;i++){
713+ final_gs[ls[i]-1 ]=g[i];
714+ }
715+ if (unit->x_spread != 0 ){
716+ spread_it (unit,final_gs);
717+ }
718+
719+ } else {
698720 // if the ls data was bad, just set every gain to 0 and bail
699721 for (i=0 ;i<unit->x_ls_amount ;i++)
700- unit-> final_gs [i]=0 .f ;
722+ final_gs[i]=0 .f ;
701723 }
702724}
703725
704726
705727static void VBAP_Dtor (VBAP* unit)
706728{
729+ int counter = unit->x_lsset_amount ;
707730 RTFree (unit->mWorld , unit->final_gs );
731+
732+ for (int i=0 ; i<counter; i++){
733+ RTFree (unit->mWorld , unit->x_set_inv_matx [i]);
734+ RTFree (unit->mWorld , unit->x_set_matx [i]);
735+ RTFree (unit->mWorld , unit->x_lsset [i]);
736+ }
737+
738+ RTFree (unit->mWorld , unit->x_set_inv_matx );
739+ RTFree (unit->mWorld , unit->x_set_matx );
740+ RTFree (unit->mWorld , unit->x_lsset );
708741}
709742
710743// ////////////////////////////////////////////////////////////////////////////////////////////////
0 commit comments