aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzacksettel <zacksettel@users.sourceforge.net>2014-05-18 18:02:49 +0000
committerzacksettel <zacksettel@users.sourceforge.net>2014-05-18 18:02:49 +0000
commit33cfd66d36e9ec07b80fc0a4675c5073494ced27 (patch)
tree8d27f31836b56b9ff171df14e86e681e5013cc8a
parentb56970a1e951187ed2839a6a56c233b5329b127b (diff)
changed vbap to allocate memory dynamically, to eliminate crash-producing memory overwrites when larger speaker configurations were defined. Added CHANGELOG too
svn path=/trunk/externals/vbap/; revision=17307
-rw-r--r--CHANGELOG.txt5
-rw-r--r--define_loudspeakers.c41
-rw-r--r--vbap.c164
-rw-r--r--vbap.h58
4 files changed, 225 insertions, 43 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
new file mode 100644
index 0000000..132c66d
--- /dev/null
+++ b/CHANGELOG.txt
@@ -0,0 +1,5 @@
+from version 1.0.3.2 to version 1.0.3.3
+
+- changed vbap to allocate memory dynamically, to eliminate crash-producing memory overwrites when larger speaker configurations were defined (e.g. on OSX for speakers > 13 in 3D)
+- eliminated a post to the console reporting azimuth updates
+
diff --git a/define_loudspeakers.c b/define_loudspeakers.c
index 5c7e478..2d826c0 100644
--- a/define_loudspeakers.c
+++ b/define_loudspeakers.c
@@ -14,14 +14,14 @@ See copyright in file with name LICENSE.txt */
// If we are within VBAP (which includes define_loudspeakers), then don't create a main for define_loudspeakres
void define_loudspeakers_setup(void)
{
- def_ls_class = class_new(gensym("define_loudspeakers"), (t_newmethod)def_ls_new, 0, (short)sizeof(t_def_ls), 0, A_GIMME, 0);
+ def_ls_class = class_new(gensym("define_loudspeakers"), (t_newmethod)def_ls_new, 0, (short)sizeof(t_def_ls), 0, A_GIMME, 0);
/* def_ls_new = creation function, A_DEFLONG = its (optional) arguement is a long (32-bit) int */
class_addbang(def_ls_class, (t_method)def_ls_bang); /* the procedure it uses when it gets a bang in the left inlet */
class_addmethod(def_ls_class, (t_method)def_ls_read_directions, gensym("ls-directions"), A_GIMME, 0);
class_addmethod(def_ls_class, (t_method)def_ls_read_triplets, gensym("ls-triplets"), A_GIMME, 0);
- post(DFLS_VERSION);
+ logpost(NULL,1, DFLS_VERSION);
}
# else /* Max */
void main(void)
@@ -177,6 +177,11 @@ static void ls_angles_to_cart(t_ls *ls)
/* create new instance of object... MUST send it an int even if you do nothing with this int!! */
static void *def_ls_new(t_symbol *s, int ac, Atom *av)
{
+
+
+ //post("def_ls_new: AC = %d", ac);
+
+
// s is object name (we ignore it)
t_def_ls *x = (t_def_ls *)newobject(def_ls_class);
@@ -195,6 +200,9 @@ static void *def_ls_new(t_symbol *s, int ac, Atom *av)
void vbap_def_ls(t_def_ls *x, t_symbol *s, int ac, Atom *av)
{
initContent_ls_directions(x,ac,av); // Initialize object internal data from a ls-directions list
+
+ logpost(NULL,3, "vbap_def_ls: %ld-D configuration with %ld speakers", x->x_def_ls_dimension, x->x_def_ls_amount );
+
def_ls_bang(x); // calculate and send matrix to vbap
}
@@ -205,7 +213,9 @@ static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av)
long d = 0;
/* if (av[0].a_type == A_LONG) d = av[0].a_w.w_long;
- else */ if(av[0].a_type == A_FLOAT) d = (long)av[0].a_w.w_float;
+ else */
+
+ if(av[0].a_type == A_FLOAT) d = (long)av[0].a_w.w_float;
else { error("define-loudspeakers: dimension NaN"); return; }
if (d==2 || d==3)
@@ -463,6 +473,9 @@ static void add_ldsp_triplet(int i, int j, int k, t_def_ls *x)
trip_ptr = trip_ptr->next;
}
trip_ptr = (struct t_ls_set*) getbytes (sizeof (struct t_ls_set));
+
+ //post("add_ldsp_triplet getbytes: %ld", sizeof (struct t_ls_set));
+
if(prev == NULL)
x->x_ls_set = trip_ptr;
else
@@ -594,7 +607,10 @@ static void calculate_3x3_matrixes(t_def_ls *x)
t_float *invmx;
//t_float *ptr;
struct t_ls_set *tr_ptr = x->x_ls_set;
- int triplet_amount = 0, /*ftable_size,*/i,pointer,list_length=0;
+
+ unsigned long triplet_amount = 0, /*ftable_size,*/i,pointer,list_length=0; // zack
+
+
Atom *at;
t_ls *lss = x->x_ls;
@@ -613,7 +629,8 @@ static void calculate_3x3_matrixes(t_def_ls *x)
tr_ptr = x->x_ls_set;
list_length= triplet_amount * 21 + 3;
at= (Atom *) getbytes(list_length*sizeof(Atom));
-
+
+
SETLONG(&at[0], x->x_def_ls_dimension);
SETLONG(&at[1], x->x_def_ls_amount);
pointer=2;
@@ -656,11 +673,14 @@ static void calculate_3x3_matrixes(t_def_ls *x)
SETFLOAT(&at[pointer], lp2->z); pointer++;
SETFLOAT(&at[pointer], lp3->z); pointer++;
+
+
tr_ptr = tr_ptr->next;
}
+
sendLoudspeakerMatrices(x,list_length, at);
-// outlet_anything(x->x_outlet0, gensym("loudspeaker-matrices"), list_length, at);
- freebytes(at, list_length*sizeof(Atom));
+
+ freebytes(at, list_length*sizeof(Atom));
}
@@ -720,7 +740,8 @@ static void choose_ls_tuplets(t_def_ls *x)
// Output
list_length= amount * 10 + 2;
at= (Atom *) getbytes(list_length*sizeof(Atom));
-
+ //post("choose_ls_tuplets getbytes: %ld", list_length*sizeof(Atom));
+
SETLONG(&at[0], x->x_def_ls_dimension);
SETLONG(&at[1], x->x_def_ls_amount);
pointer=2;
@@ -755,7 +776,9 @@ static void choose_ls_tuplets(t_def_ls *x)
pointer++;
}
}
- sendLoudspeakerMatrices(x,list_length, at);
+ //post("choose_ls_tuplets: before call to sendLoudspeakerMatrices");
+
+ sendLoudspeakerMatrices(x,list_length, at);
//outlet_anything(x->x_outlet0, gensym("loudspeaker-matrices"), list_length, at);
freebytes(at, list_length*sizeof(Atom));
}
diff --git a/vbap.c b/vbap.c
index ecd7ccb..d83fe02 100644
--- a/vbap.c
+++ b/vbap.c
@@ -20,6 +20,8 @@ static void *vbap_class;
static void vect_cross_prod(t_float v1[3], t_float v2[3],t_float v3[3]);
static void additive_vbap(t_float *final_gs, t_float cartdir[3], t_vbap *x);
static void vbap_bang(t_vbap *x);
+static int vbap_getmem(t_vbap *x, int lsSetCount );
+static void vbap_free(t_vbap *x);
static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av);
#ifndef PD /* Max */
/* these are for getting data from a cold inlet on Max/MSP, in Pd you use t_floatinlet_new() in new() */
@@ -77,7 +79,7 @@ void vbap_assist(t_vbap *x, void *b, long m, long a, char *s)
#ifdef PD
void vbap_setup(void)
{
- vbap_class = class_new(gensym("vbap"), (t_newmethod)vbap_new, 0, (short)sizeof(t_vbap), 0,
+ vbap_class = class_new(gensym("vbap"), (t_newmethod)vbap_new, (t_method) vbap_free, (short)sizeof(t_vbap), 0,
A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
class_addbang(vbap_class, (t_method)vbap_bang);
@@ -95,7 +97,9 @@ void vbap_setup(void)
class_addmethod(vbap_class, (t_method)def_ls_read_directions, gensym("ls-directions"), A_GIMME, 0);
class_addmethod(vbap_class, (t_method)def_ls_read_triplets, gensym("ls-triplets"), A_GIMME, 0);
- logpost(NULL, 4, VBAP_VERSION);
+ logpost(NULL, 1, VBAP_VERSION);
+ //post(VBAP_VERSION);
+
}
#else /* MAX */
void main(void)
@@ -152,6 +156,14 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread)
x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
+
+
+
+ // allocate space for the runtime matricies
+// if (!vbap_getmem(x, MAX_LS_SETS))
+// return( NULL );
+//
+
#else /* Max */
t_vbap *x = (t_vbap *)newobject(vbap_class);
@@ -167,7 +179,9 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread)
x->x_outlet0 = listout(x);
#endif /* PD */
- x->x_spread_base[0] = 0.0;
+ x->x_ls_setCount = 0; // refers to memory dynamically allocated when a define_loudspeakers config is received
+
+ x->x_spread_base[0] = 0.0;
x->x_spread_base[1] = 1.0;
x->x_spread_base[2] = 0.0;
x->x_lsset_available =0;
@@ -180,6 +194,85 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread)
}
+// currently can allocate upto 256K to support up to 44 channels in 3D
+// note: to save memory, the required memory for a given configuration could instead, be dynamically allocated by calling this method from the vbap_matrix() method
+static int vbap_getmem(t_vbap *x, int lsSetCount )
+{
+
+#ifdef PD
+
+ if ( x->x_ls_setCount ) vbap_free(x);
+
+ //was t_float x_set_inv_matx[MAX_LS_SETS][9];
+ x->x_set_inv_matx = getbytes( sizeof( t_float* ) * lsSetCount);
+
+ if(!x->x_set_inv_matx) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( t_float* ) * lsSetCount); return(0);}
+
+ for (int i = 0; i < lsSetCount; i++)
+ {
+ x->x_set_inv_matx[i] = getbytes( sizeof(t_float) * MATRIX_DIM );
+ if(!x->x_set_inv_matx[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(t_float) * MATRIX_DIM ); return(0);}
+ }
+
+
+ //was t_float x_set_matx[MAX_LS_SETS][9];
+ x->x_set_matx = getbytes( sizeof( t_float* ) * lsSetCount);
+
+ if(!x->x_set_matx) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( t_float* ) * lsSetCount); return(0);}
+
+ for (int i = 0; i < lsSetCount; i++)
+ {
+ x->x_set_matx[i] = getbytes( sizeof(t_float) * MATRIX_DIM );
+ if(!x->x_set_matx[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(t_float) * MATRIX_DIM ); return(0);}
+ }
+
+
+ //was long x_lsset[MAX_LS_SETS][3];
+ x->x_lsset = getbytes( sizeof( long * ) * lsSetCount);
+
+ if(!x->x_lsset) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( long * ) * lsSetCount); return(0);}
+
+ for (int i = 0; i < lsSetCount; i++)
+ {
+ x->x_lsset[i] = getbytes( sizeof( long ) * SPEAKER_SET_DIM );
+ if(!x->x_lsset[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(long) * SPEAKER_SET_DIM ); return(0);}
+ }
+
+ unsigned long memallocd = 2 * ( sizeof(t_float *) * lsSetCount * sizeof(t_float) * MATRIX_DIM) + ( sizeof(long *) * lsSetCount * sizeof(long) * SPEAKER_SET_DIM);
+
+ logpost(NULL, 3, "vbap_new: %ldK bytes allocated for instance", memallocd /1000);
+
+ x->x_ls_setCount = lsSetCount;
+
+#endif
+ return(1);
+
+}
+
+
+// free any allocated memory for instance
+static void vbap_free(t_vbap *x)
+{
+ if (! x->x_ls_setCount) return;
+
+ for (int i = 0; i < x->x_ls_setCount; i++)
+ {
+ freebytes( x->x_set_inv_matx[i], (sizeof(t_float) * MATRIX_DIM )); // = getbytes( sizeof(t_float) * MATRIX_DIM );
+ freebytes( x->x_set_matx[i], sizeof(t_float) * MATRIX_DIM);
+ }
+
+ freebytes(x->x_set_inv_matx, (sizeof( t_float* ) * x->x_ls_setCount));
+ freebytes(x->x_set_matx, sizeof( t_float* ) * x->x_ls_setCount);
+
+
+ for (int i = 0; i < x->x_ls_setCount; i++)
+ {
+ freebytes(x->x_lsset[i], sizeof( long ) * SPEAKER_SET_DIM );
+ }
+
+ freebytes( x->x_lsset, sizeof( long * ) * x->x_ls_setCount);
+}
+
static void angle_to_cart(t_float azi, t_float ele, t_float res[3])
// converts angular coordinates to cartesian
{
@@ -327,7 +420,7 @@ static void vbap(t_float g[3], long ls[3], t_vbap *x)
} else new_cartdir[2] = 0;
cart_to_angle(new_cartdir,new_angle_dir);
x->x_azi = (new_angle_dir[0] );
- // post("[vbap] use azimuth %g",x->x_azi );
+ //post("[vbap] use azimuth %g",x->x_azi );
x->x_ele = (new_angle_dir[1]);
}
//}
@@ -550,6 +643,7 @@ static void vbap_bang(t_vbap *x)
t_float g[3];
long ls[3];
long i;
+
t_float *final_gs = (t_float *) getbytes(x->x_ls_amount * sizeof(t_float));
if(x->x_lsset_available ==1)
@@ -598,8 +692,14 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av)
{
int d = 0;
/*if(av[datapointer].a_type == A_LONG) d = av[datapointer++].a_w.w_long;
- else*/ if(av[datapointer].a_type == A_FLOAT) d = (long)av[datapointer++].a_w.w_float;
- else { error("vbap: Dimension NaN"); x->x_lsset_available=0; return; }
+ else*/
+ if (av[datapointer].a_type == A_FLOAT)
+ d = (long)av[datapointer++].a_w.w_float;
+ else
+ {
+ error("vbap: Dimension NaN"); x->x_lsset_available=0;
+ return;
+ }
if (d!=2 && d!=3) { error("vbap %s: Dimension can be only 2 or 3",s->s_name); x->x_lsset_available=0; return; }
@@ -617,25 +717,40 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av)
x->x_ls_amount = a;
}
-
+
long counter = (ac - 2) / ((x->x_dimension * x->x_dimension*2) + x->x_dimension);
- x->x_lsset_amount=counter;
+
+
+
+ if (counter-1 > MAX_LS_SETS) { error("vbap %s: loudspeaker definitions exceed maximum number of speakers",s->s_name); x->x_lsset_available=0; return; }
+
+ vbap_getmem(x, counter); // PD only: allocate memory (frees any previously allocated memory automatically)
+
+ x->x_lsset_amount=counter;
+
if(counter==0) { error("vbap %s: not enough parameters",s->s_name); x->x_lsset_available=0; return; }
long setpointer=0;
long i;
-
- while(counter-- > 0)
+
+ long db_dim = x->x_dimension;
+
+ while(counter-- > 0)
{
- for(i=0; i < x->x_dimension; i++)
+
+ for(i=0; i < x->x_dimension; i++)
{
# ifdef PD
- if(av[datapointer].a_type == A_FLOAT)
+
+ if(av[datapointer].a_type == A_FLOAT)
{
x->x_lsset[setpointer][i]=(long)av[datapointer++].a_w.w_float;
- }
- else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; }
+ }
+ else { error("vbap AA %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; }
+
+
+
# else /* Max */
if(av[datapointer].a_type == A_LONG)
{
@@ -644,26 +759,35 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av)
else { error("vbap %s: param %d is not an in",s->s_name,datapointer); x->x_lsset_available=0; return; }
# endif /* PD */
}
- for(i=0; i < x->x_dimension*x->x_dimension; i++)
+
+
+ for(i=0; i < x->x_dimension*x->x_dimension; i++)
{
- if(av[datapointer].a_type == A_FLOAT)
+
+ if(av[datapointer].a_type == A_FLOAT)
{
x->x_set_inv_matx[setpointer][i]=av[datapointer++].a_w.w_float;
}
- else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; }
+ else { error("vbap BB %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; }
}
+
for(i=0; i < x->x_dimension*x->x_dimension; i++)
{
+
+
if(av[datapointer].a_type == A_FLOAT)
{
x->x_set_matx[setpointer][i]=av[datapointer++].a_w.w_float;
}
- else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; }
+ else {
+ error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0;
+ return;
+ }
}
-
+
setpointer++;
}
if (_enable_trace) post("vbap: Loudspeaker setup configured!");
-}
+ }
diff --git a/vbap.h b/vbap.h
index 0429b0d..57146ac 100644
--- a/vbap.h
+++ b/vbap.h
@@ -10,21 +10,37 @@
#define M_PI 3.14159265358979323846264338327950288 /* pi */
#endif
-#define MAX_LS_SETS 100 // maximum number of loudspeaker sets (triplets or pairs) allowed
-#define MAX_LS_AMOUNT 55 // maximum amount of loudspeakers, can be increased
+#ifdef PD
+ #define MAX_LS_SETS 745 // maximum number of loudspeaker sets (triplets or pairs) allowed -- allows for up to 44 speakers in 3D config
+//#define MAX_LS_SETS 100 // former maximum value, allowed for up to 13 speakers in 3D config
+//#define MAX_LS_SETS 571 // example: for up to 32 speakers in 3D config
+
+#else // Max
+
+#define MAX_LS_SETS 100 // maximum number of loudspeaker sets (triplets or pairs) allowed - This can crash when too many speakers are defined
+
+#endif
+
+#define MATRIX_DIM 9 // hard-coded matrx dimension for the algorithm
+#define SPEAKER_SET_DIM 3 // hard-coded speaker set dimension for the algorithm
+
+#define MAX_LS_AMOUNT 55 // maximum amount of loudspeakers, can be increased, but see comments next to MAX_LS_SETS above
#define MIN_VOL_P_SIDE_LGTH 0.01
-#define VBAP_VERSION "vbap - v1.0.3.2 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006 (Pd port by HCS)"
+#define VBAP_VERSION "pdsheefa_vbap - v1.0.3.3 - 15 May 2014 - (c) Ville Pulkki 1999-2006 (Pd port by HCS, updated by ZS)"
#define DFLS_VERSION "define_loudspeakers - v1.0.3.2 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006"
static t_float rad2ang = 360.0 / ( 2.0f * M_PI );
static t_float atorad = (2.0f * M_PI) / 360.0f ;
#ifdef VBAP_OBJECT
- // We are inside vbap object, so sending matrix from define_loudspeakers is a simple call to the vbap receiver...
- #define sendLoudspeakerMatrices(x,list_length, at) \
- vbap_matrix(x, gensym("loudspeaker-matrices"),list_length, at); \
- vbap_bang(x)
+
+//We are inside vbap object, so sending matrix from define_loudspeakers is a simple call to the vbap receiver...
+
+#define sendLoudspeakerMatrices(x,list_length, at) \
+ vbap_matrix(x, gensym("loudspeaker-matrices"),list_length, at); \
+ vbap_bang(x)
+
#else
// We are inside define_loudspeaker object, send matrix to outlet
#define sendLoudspeakerMatrices(x,list_length, at) \
@@ -61,18 +77,31 @@ typedef struct t_ls_set
void *x_outlet1;
void *x_outlet2;
void *x_outlet3;
- void *x_outlet4;
- t_float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set
- t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set
- long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set
+ void *x_outlet4;
+
long x_lsset_available; // have loudspeaker sets been defined with define_loudspeakers
long x_lsset_amount; // amount of loudspeaker sets
- long x_ls_amount; // amount of loudspeakers
+ long x_ls_amount; // amount of loudspeakers
long x_dimension; // 2 or 3
+
# ifdef PD
+ // memory for data sets is now allocated dynamically in each instance
+ // WAS t_float x_set_inv_matx[MAX_LS_SETS][9];
+ t_float **x_set_inv_matx; // inverse matrice for each loudspeaker set
+ // WAS t_float x_set_matx[MAX_LS_SETS][9];
+ t_float **x_set_matx; // matrice for each loudspeaker set
+ // WAS long x_lsset[MAX_LS_SETS][3];
+ long **x_lsset; // channel numbers of loudspeakers in each LS set
+
t_float x_spread; // speading amount of virtual source (0-100)
-# else /* Max */
- long x_spread; // speading amount of virtual source (0-100)
+
+# else /* Max */ // memory allocation not tested for max, so it is allocated in the struct, as it was before
+
+ t_float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set
+ t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set
+ long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set
+
+ long x_spread; // speading amount of virtual source (0-100)
double x_gain; // general gain control (0-2)
# endif /* PD */
t_float x_spread_base[3]; // used to create uniform spreading
@@ -84,6 +113,7 @@ typedef struct t_ls_set
t_ls_set *x_ls_set; // loudspeaker sets
long x_def_ls_amount; // number of loudspeakers
long x_def_ls_dimension; // 2 (horizontal arrays) or 3 (3d setups)
+ long x_ls_setCount; // the number of Loudspeaker sets used for an instance's current loudspeaker configuration
} t_vbap;
// define loudspeaker data type...