void choose_ls_triplets(ls lss[MAX_LS_AMOUNT], struct ls_triplet_chain **ls_triplets, int ls_amount) /* Selects the loudspeaker triplets, and calculates the inversion matrices for each selected triplet. A line (connection) is drawn between each loudspeaker. The lines denote the sides of the triangles. The triangles should not be intersecting. All crossing connections are searched and the longer connection is erased. This yields non-intesecting triangles, which can be used in panning.*/ { int i,j,k,l,m,li, table_size; int *i_ptr; cart_vec vb1,vb2,tmp_vec; int connections[MAX_LS_AMOUNT][MAX_LS_AMOUNT]; float angles[MAX_LS_AMOUNT]; int sorted_angles[MAX_LS_AMOUNT]; float distance_table[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_i[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_j[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; float distance; struct ls_triplet_chain *trip_ptr, *prev, *tmp_ptr; if (ls_amount == 0) { fprintf(stderr,"Number of loudspeakers is zero\nExiting\n"); exit(-1); } for(i=0;i<ls_amount;i++) for(j=i+1;j<ls_amount;j++) for(k=j+1;k<ls_amount;k++){ if(vol_p_side_lgth(i,j, k, lss) > MIN_VOL_P_SIDE_LGTH){ connections[i][j]=1; connections[j][i]=1; connections[i][k]=1; connections[k][i]=1; connections[j][k]=1; connections[k][j]=1; add_ldsp_triplet(i,j,k,ls_triplets, lss); } } /*calculate distancies between all lss and sorting them*/ table_size =(((ls_amount - 1) * (ls_amount)) / 2); for(i=0;i<table_size; i++) distance_table[i] = 100000.0; for(i=0;i<ls_amount;i++){ for(j=(i+1);j<ls_amount; j++){ if(connections[i][j] == 1) { distance = fabs(vec_angle(lss[i].coords,lss[j].coords)); k=0; while(distance_table[k] < distance) k++; for(l=(table_size - 1);l > k ;l--){ distance_table[l] = distance_table[l-1]; distance_table_i[l] = distance_table_i[l-1]; distance_table_j[l] = distance_table_j[l-1]; } distance_table[k] = distance; distance_table_i[k] = i; distance_table_j[k] = j; } else table_size--; } } /* disconnecting connections which are crossing shorter ones, starting from shortest one and removing all that cross it, and proceeding to next shortest */ for(i=0; i<(table_size); i++){ int fst_ls = distance_table_i[i]; int sec_ls = distance_table_j[i]; if(connections[fst_ls][sec_ls] == 1) for(j=0; j<ls_amount ; j++) for(k=j+1; k<ls_amount; k++) if( (j!=fst_ls) && (k != sec_ls) && (k!=fst_ls) && (j != sec_ls)){ if(lines_intersect(fst_ls, sec_ls, j,k,lss) == 1){ connections[j][k] = 0; connections[k][j] = 0; } } } /* remove triangles which had crossing sides with smaller triangles or include loudspeakers*/ trip_ptr = *ls_triplets; prev = NULL; while (trip_ptr != NULL){ i = trip_ptr->ls_nos[0]; j = trip_ptr->ls_nos[1]; k = trip_ptr->ls_nos[2]; if(connections[i][j] == 0 || connections[i][k] == 0 || connections[j][k] == 0 || any_ls_inside_triplet(i,j,k,lss,ls_amount) == 1 ){ if(prev != NULL) { prev->next = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; free(tmp_ptr); } else { *ls_triplets = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; free(tmp_ptr); } } else { prev = trip_ptr; trip_ptr = trip_ptr->next; } } }
static void choose_ls_triplets(t_def_ls *x) /* Selects the loudspeaker triplets, and calculates the inversion matrices for each selected triplet. A line (connection) is drawn between each loudspeaker. The lines denote the sides of the triangles. The triangles should not be intersecting. All crossing connections are searched and the longer connection is erased. This yields non-intesecting triangles, which can be used in panning. See theory in paper Pulkki, V. Lokki, T. "Creating Auditory Displays with Multiple Loudspeakers Using VBAP: A Case Study with DIVA Project" in International Conference on Auditory Displays -98.*/ { int i,j,k,l,/*m,li,*/ table_size; //int *i_ptr; //t_ls vb1,vb2,tmp_vec; int connections[MAX_LS_AMOUNT][MAX_LS_AMOUNT]; //float angles[MAX_LS_AMOUNT]; //int sorted_angles[MAX_LS_AMOUNT]; t_float distance_table[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_i[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_j[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; t_float distance; t_ls_set *trip_ptr, *prev, *tmp_ptr; int ls_amount = x->x_def_ls_amount; t_ls *lss = x->x_ls; if (ls_amount == 0) { post("define-loudspeakers: Number of loudspeakers is zero"); return; } for(i=0;i<ls_amount;i++) for(j=i+1;j<ls_amount;j++) for(k=j+1;k<ls_amount;k++) { if(vol_p_side_lgth(i,j,k, x->x_ls) > MIN_VOL_P_SIDE_LGTH) { connections[i][j]=1; connections[j][i]=1; connections[i][k]=1; connections[k][i]=1; connections[j][k]=1; connections[k][j]=1; add_ldsp_triplet(i,j,k,x); } } /*calculate distancies between all lss and sorting them*/ table_size =(((ls_amount - 1) * (ls_amount)) / 2); for(i=0;i<table_size; i++) distance_table[i] = 100000.0; for(i=0;i<ls_amount;i++) { for(j=(i+1);j<ls_amount; j++) { if(connections[i][j] == 1) { distance = fabs(vec_angle(lss[i],lss[j])); k=0; while(distance_table[k] < distance) k++; for(l=(table_size - 1);l > k ;l--) { distance_table[l] = distance_table[l-1]; distance_table_i[l] = distance_table_i[l-1]; distance_table_j[l] = distance_table_j[l-1]; } distance_table[k] = distance; distance_table_i[k] = i; distance_table_j[k] = j; } else { table_size--; } } } /* disconnecting connections which are crossing shorter ones, starting from shortest one and removing all that cross it, and proceeding to next shortest */ for(i=0; i<(table_size); i++) { int fst_ls = distance_table_i[i]; int sec_ls = distance_table_j[i]; if(connections[fst_ls][sec_ls] == 1) { for(j=0; j<ls_amount ; j++) { for(k=j+1; k<ls_amount; k++) { if( (j!=fst_ls) && (k != sec_ls) && (k!=fst_ls) && (j != sec_ls)) { if(lines_intersect(fst_ls, sec_ls, j,k,x->x_ls) == 1) { connections[j][k] = 0; connections[k][j] = 0; } } } } } } /* remove triangles which had crossing sides with smaller triangles or include loudspeakers*/ trip_ptr = x->x_ls_set; prev = NULL; while (trip_ptr != NULL) { i = trip_ptr->ls_nos[0]; j = trip_ptr->ls_nos[1]; k = trip_ptr->ls_nos[2]; if(connections[i][j] == 0 || connections[i][k] == 0 || connections[j][k] == 0 || any_ls_inside_triplet(i,j,k,x->x_ls,ls_amount) == 1 ) { if(prev != NULL) { prev->next = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } else { x->x_ls_set = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } } else { prev = trip_ptr; trip_ptr = trip_ptr->next; } } x->x_triplets_specified=1; }