mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
steps toward a working VBAP panner
git-svn-id: svn://localhost/ardour2/branches/3.0@8055 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
6ce5dc2dc9
commit
e50bd9e653
7 changed files with 377 additions and 170 deletions
|
|
@ -1,34 +1,19 @@
|
|||
/*
|
||||
This software is being provided to you, the licensee, by Ville Pulkki,
|
||||
under the following license. By obtaining, using and/or copying this
|
||||
software, you agree that you have read, understood, and will comply
|
||||
with these terms and conditions: Permission to use, copy, modify and
|
||||
distribute, including the right to grant others rights to distribute
|
||||
at any tier, this software and its documentation for any purpose and
|
||||
without fee or royalty is hereby granted, provided that you agree to
|
||||
comply with the following copyright notice and statements, including
|
||||
the disclaimer, and that the same appear on ALL copies of the software
|
||||
and documentation, including modifications that you make for internal
|
||||
use or for distribution:
|
||||
|
||||
Copyright 1998 by Ville Pulkki, Helsinki University of Technology. All
|
||||
rights reserved.
|
||||
|
||||
The software may be used, distributed, and included to commercial
|
||||
products without any charges. When included to a commercial product,
|
||||
the method "Vector Base Amplitude Panning" and its developer Ville
|
||||
Pulkki must be referred to in documentation.
|
||||
|
||||
This software is provided "as is", and Ville Pulkki or Helsinki
|
||||
University of Technology make no representations or warranties,
|
||||
expressed or implied. By way of example, but not limitation, Helsinki
|
||||
University of Technology or Ville Pulkki make no representations or
|
||||
warranties of merchantability or fitness for any particular purpose or
|
||||
that the use of the licensed software or documentation will not
|
||||
infringe any third party patents, copyrights, trademarks or other
|
||||
rights. The name of Ville Pulkki or Helsinki University of Technology
|
||||
may not be used in advertising or publicity pertaining to distribution
|
||||
of the software.
|
||||
/*
|
||||
Copyright (C) 2010 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __libardour_vbap_h__
|
||||
|
|
@ -37,83 +22,13 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <pbd/signals.h>
|
||||
|
||||
#include "ardour/panner.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class VBAPSpeakers {
|
||||
public:
|
||||
struct cart_vec {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct ang_vec {
|
||||
float azi;
|
||||
float ele;
|
||||
float length;
|
||||
};
|
||||
|
||||
static const int MAX_TRIPLET_AMOUNT = 60;
|
||||
|
||||
VBAPSpeakers ();
|
||||
~VBAPSpeakers ();
|
||||
|
||||
int add_speaker (double direction, double elevation = 0.0);
|
||||
void remove_speaker (int id);
|
||||
void move_speaker (int id, double direction, double elevation = 0.0);
|
||||
|
||||
const double* matrix (int tuple) const { return _matrices[tuple]; }
|
||||
int speaker_for_tuple (int tuple, int which) const { return _speaker_tuples[tuple][which]; }
|
||||
|
||||
int n_tuples () const { return _matrices.size(); }
|
||||
int dimension() const { return _dimension; }
|
||||
|
||||
static void angle_to_cart(ang_vec *from, cart_vec *to);
|
||||
|
||||
private:
|
||||
static const double MIN_VOL_P_SIDE_LGTH = 0.01;
|
||||
int _dimension;
|
||||
|
||||
/* A struct for a loudspeaker instance */
|
||||
struct Speaker {
|
||||
int id;
|
||||
cart_vec coords;
|
||||
ang_vec angles;
|
||||
|
||||
Speaker (int, double azimuth, double elevation);
|
||||
|
||||
void move (double azimuth, double elevation);
|
||||
};
|
||||
|
||||
std::vector<Speaker> _speakers;
|
||||
std::vector<double[9]> _matrices; /* holds matrices for a given speaker combinations */
|
||||
std::vector<int[3]> _speaker_tuples; /* holds speakers IDs for a given combination */
|
||||
|
||||
/* A struct for all loudspeakers */
|
||||
struct ls_triplet_chain {
|
||||
int ls_nos[3];
|
||||
float inv_mx[9];
|
||||
struct ls_triplet_chain *next;
|
||||
};
|
||||
|
||||
static float vec_angle(cart_vec v1, cart_vec v2);
|
||||
static float vec_length(cart_vec v1);
|
||||
static float vec_prod(cart_vec v1, cart_vec v2);
|
||||
static float vol_p_side_lgth(int i, int j,int k, const std::vector<Speaker>&);
|
||||
static void cross_prod(cart_vec v1,cart_vec v2, cart_vec *res);
|
||||
|
||||
void update ();
|
||||
int any_ls_inside_triplet (int a, int b, int c);
|
||||
void add_ldsp_triplet (int i, int j, int k, struct ls_triplet_chain **ls_triplets);
|
||||
int lines_intersect (int i,int j,int k,int l);
|
||||
void calculate_3x3_matrixes (struct ls_triplet_chain *ls_triplets);
|
||||
void choose_ls_triplets (struct ls_triplet_chain **ls_triplets);
|
||||
void choose_ls_pairs ();
|
||||
void sort_2D_lss (int* sorted_lss);
|
||||
int calc_2D_inv_tmatrix (double azi1,double azi2, double* inv_mat);
|
||||
};
|
||||
class VBAPSpeakers;
|
||||
|
||||
class VBAPanner : public StreamPanner {
|
||||
public:
|
||||
|
|
@ -124,20 +39,23 @@ class VBAPanner : public StreamPanner {
|
|||
|
||||
void set_azimuth_elevation (double azimuth, double elevation);
|
||||
|
||||
/* a utility function to convert azimuth+elevation into cartesian coordinates
|
||||
as used by the StreamPanner API
|
||||
*/
|
||||
|
||||
void azi_ele_to_cart (int azi, int ele, double* c);
|
||||
|
||||
private:
|
||||
double _azimuth; /* direction for the signal source */
|
||||
double _elevation; /* elevation of the signal source */
|
||||
VBAPSpeakers& _speakers;
|
||||
double _azimuth; /* direction for the signal source */
|
||||
double _elevation; /* elevation of the signal source */
|
||||
bool _dirty;
|
||||
double gains[3];
|
||||
double desired_gains[3];
|
||||
int outputs[3];
|
||||
int desired_outputs[3];
|
||||
|
||||
PBD::ScopedConnection speaker_connection;
|
||||
|
||||
VBAPSpeakers& _speakers;
|
||||
|
||||
void compute_gains (double g[3], int ls[3], int azi, int ele);
|
||||
|
||||
void update ();
|
||||
void mark_dirty ();
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
|
|
|||
109
libs/ardour/ardour/vbap_speakers.h
Normal file
109
libs/ardour/ardour/vbap_speakers.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright (C) 2010 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __libardour_vbap_speakers_h__
|
||||
#define __libardour_vbap_speakers_h__
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <pbd/signals.h>
|
||||
|
||||
#include "ardour/panner.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class VBAPSpeakers {
|
||||
public:
|
||||
struct cart_vec {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct ang_vec {
|
||||
float azi;
|
||||
float ele;
|
||||
float length;
|
||||
};
|
||||
|
||||
static const int MAX_TRIPLET_AMOUNT = 60;
|
||||
|
||||
VBAPSpeakers ();
|
||||
~VBAPSpeakers ();
|
||||
|
||||
int add_speaker (double direction, double elevation = 0.0);
|
||||
void remove_speaker (int id);
|
||||
void move_speaker (int id, double direction, double elevation = 0.0);
|
||||
|
||||
const double* matrix (int tuple) const { return _matrices[tuple]; }
|
||||
int speaker_for_tuple (int tuple, int which) const { return _speaker_tuples[tuple][which]; }
|
||||
|
||||
int n_tuples () const { return _matrices.size(); }
|
||||
int dimension() const { return _dimension; }
|
||||
|
||||
static void angle_to_cart(ang_vec *from, cart_vec *to);
|
||||
|
||||
PBD::Signal0<void> Changed;
|
||||
|
||||
private:
|
||||
static const double MIN_VOL_P_SIDE_LGTH = 0.01;
|
||||
int _dimension;
|
||||
|
||||
/* A struct for a loudspeaker instance */
|
||||
struct Speaker {
|
||||
int id;
|
||||
cart_vec coords;
|
||||
ang_vec angles;
|
||||
|
||||
Speaker (int, double azimuth, double elevation);
|
||||
|
||||
void move (double azimuth, double elevation);
|
||||
};
|
||||
|
||||
std::vector<Speaker> _speakers;
|
||||
std::vector<double[9]> _matrices; /* holds matrices for a given speaker combinations */
|
||||
std::vector<int[3]> _speaker_tuples; /* holds speakers IDs for a given combination */
|
||||
|
||||
/* A struct for all loudspeakers */
|
||||
struct ls_triplet_chain {
|
||||
int ls_nos[3];
|
||||
float inv_mx[9];
|
||||
struct ls_triplet_chain *next;
|
||||
};
|
||||
|
||||
static float vec_angle(cart_vec v1, cart_vec v2);
|
||||
static float vec_length(cart_vec v1);
|
||||
static float vec_prod(cart_vec v1, cart_vec v2);
|
||||
static float vol_p_side_lgth(int i, int j,int k, const std::vector<Speaker>&);
|
||||
static void cross_prod(cart_vec v1,cart_vec v2, cart_vec *res);
|
||||
|
||||
void update ();
|
||||
int any_ls_inside_triplet (int a, int b, int c);
|
||||
void add_ldsp_triplet (int i, int j, int k, struct ls_triplet_chain **ls_triplets);
|
||||
int lines_intersect (int i,int j,int k,int l);
|
||||
void calculate_3x3_matrixes (struct ls_triplet_chain *ls_triplets);
|
||||
void choose_ls_triplets (struct ls_triplet_chain **ls_triplets);
|
||||
void choose_ls_pairs ();
|
||||
void sort_2D_lss (int* sorted_lss);
|
||||
int calc_2D_inv_tmatrix (double azi1,double azi2, double* inv_mat);
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
#endif /* __libardour_vbap_speakers_h__ */
|
||||
|
|
@ -38,14 +38,24 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "ardour/vbap.h"
|
||||
#include "pbd/cartesian.h"
|
||||
|
||||
#include "ardour/vbap.h"
|
||||
#include "ardour/vbap_speakers.h"
|
||||
#include "ardour/audio_buffer.h"
|
||||
#include "ardour/buffer_set.h"
|
||||
|
||||
using namespace PBD;
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
||||
VBAPanner::VBAPanner (Panner& parent, Evoral::Parameter param, VBAPSpeakers& s)
|
||||
: StreamPanner (parent, param)
|
||||
, _dirty (false)
|
||||
, _speakers (s)
|
||||
|
||||
{
|
||||
_speakers.Changed.connect_same_thread (speaker_connection, boost::bind (&VBAPanner::mark_dirty, this));
|
||||
}
|
||||
|
||||
VBAPanner::~VBAPanner ()
|
||||
|
|
@ -53,21 +63,16 @@ VBAPanner::~VBAPanner ()
|
|||
}
|
||||
|
||||
void
|
||||
VBAPanner::azi_ele_to_cart (int azi, int ele, double* c)
|
||||
VBAPanner::mark_dirty ()
|
||||
{
|
||||
static const double atorad = (2.0 * M_PI / 360.0) ;
|
||||
c[0] = cos (azi * atorad) * cos (ele * atorad);
|
||||
c[1] = sin (azi * atorad) * cos (ele * atorad);
|
||||
c[2] = sin (ele * atorad);
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void
|
||||
VBAPanner::update ()
|
||||
{
|
||||
double g[3];
|
||||
int ls[3];
|
||||
|
||||
compute_gains (g, ls, _azimuth, _elevation);
|
||||
cart_to_azi_ele (_x, _y, _z, _azimuth, _elevation);
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -80,23 +85,33 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele)
|
|||
double small_g;
|
||||
double big_sm_g, gtmp[3];
|
||||
|
||||
azi_ele_to_cart (azi,ele, cartdir);
|
||||
azi_ele_to_cart (azi,ele, cartdir[0], cartdir[1], cartdir[2]);
|
||||
big_sm_g = -100000.0;
|
||||
|
||||
for (i = 0; i < _speakers.n_tuples(); i++){
|
||||
for (i = 0; i < _speakers.n_tuples(); i++) {
|
||||
|
||||
small_g = 10000000.0;
|
||||
|
||||
for (j = 0; j < _speakers.dimension(); j++) {
|
||||
|
||||
gtmp[j]=0.0;
|
||||
for (k = 0; k < _speakers.dimension(); k++)
|
||||
gtmp[j]+=cartdir[k]*_speakers.matrix(i)[j*_speakers.dimension()+k];
|
||||
if (gtmp[j] < small_g)
|
||||
|
||||
for (k = 0; k < _speakers.dimension(); k++) {
|
||||
gtmp[j] += cartdir[k] * _speakers.matrix(i)[j*_speakers.dimension()+k];
|
||||
}
|
||||
|
||||
if (gtmp[j] < small_g) {
|
||||
small_g = gtmp[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (small_g > big_sm_g) {
|
||||
|
||||
big_sm_g = small_g;
|
||||
gains[0]=gtmp[0];
|
||||
gains[1]=gtmp[1];
|
||||
|
||||
gains[0] = gtmp[0];
|
||||
gains[1] = gtmp[1];
|
||||
|
||||
speaker_ids[0]= _speakers.speaker_for_tuple (i, 0);
|
||||
speaker_ids[1]= _speakers.speaker_for_tuple (i, 1);
|
||||
|
||||
|
|
@ -105,7 +120,7 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele)
|
|||
speaker_ids[2] = _speakers.speaker_for_tuple (i, 2);
|
||||
} else {
|
||||
gains[2] = 0.0;
|
||||
speaker_ids[2] = 0;
|
||||
speaker_ids[2] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -115,9 +130,64 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele)
|
|||
gains[0] /= power;
|
||||
gains[1] /= power;
|
||||
gains[2] /= power;
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
void
|
||||
VBAPanner::do_distribute (AudioBuffer& bufs, BufferSet& obufs, gain_t gain_coefficient, nframes_t nframes)
|
||||
VBAPanner::do_distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coefficient, nframes_t nframes)
|
||||
{
|
||||
if (_muted) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sample* const src = srcbuf.data();
|
||||
Sample* dst;
|
||||
pan_t pan;
|
||||
uint32_t n_audio = obufs.count().n_audio();
|
||||
bool was_dirty;
|
||||
|
||||
if ((was_dirty = _dirty)) {
|
||||
compute_gains (desired_gains, desired_outputs, _azimuth, _elevation);
|
||||
}
|
||||
|
||||
bool todo[n_audio];
|
||||
|
||||
for (uint32_t o = 0; o < n_audio; ++o) {
|
||||
todo[o] = true;
|
||||
}
|
||||
|
||||
/* VBAP may distribute the signal across up to 3 speakers depending on
|
||||
the configuration of the speakers.
|
||||
*/
|
||||
|
||||
for (int o = 0; o < 3; ++o) {
|
||||
if (outputs[o] != -1) {
|
||||
|
||||
nframes_t n = 0;
|
||||
|
||||
/* XXX TODO: interpolate across changes in gain and/or outputs
|
||||
*/
|
||||
|
||||
dst = obufs.get_audio(outputs[o]).data();
|
||||
|
||||
pan = gain_coefficient * desired_gains[o];
|
||||
mix_buffers_with_gain (dst+n,src+n,nframes-n,pan);
|
||||
|
||||
todo[o] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t o = 0; o < n_audio; ++o) {
|
||||
if (todo[o]) {
|
||||
/* VBAP decided not to deliver any audio to this output, so we write silence */
|
||||
dst = obufs.get_audio(o).data();
|
||||
memset (dst, 0, sizeof (Sample) * nframes);
|
||||
}
|
||||
}
|
||||
|
||||
if (was_dirty) {
|
||||
memcpy (gains, desired_gains, sizeof (gains));
|
||||
memcpy (outputs, desired_outputs, sizeof (outputs));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <cmath>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ardour/vbap.h"
|
||||
#include "ardour/vbap_speakers.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
|
@ -113,12 +113,14 @@ VBAPSpeakers::update ()
|
|||
_dimension = dim;
|
||||
|
||||
if (_dimension == 3) {
|
||||
ls_triplet_chain *ls_triplets = NULL;
|
||||
ls_triplet_chain *ls_triplets = 0;
|
||||
choose_ls_triplets (&ls_triplets);
|
||||
calculate_3x3_matrixes (ls_triplets);
|
||||
} else {
|
||||
choose_ls_pairs ();
|
||||
}
|
||||
|
||||
Changed (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -160,9 +162,9 @@ VBAPSpeakers::choose_ls_triplets(struct ls_triplet_chain **ls_triplets)
|
|||
fprintf(stderr,"Number of loudspeakers is zero\nExiting\n");
|
||||
exit(-1);
|
||||
}
|
||||
for(i=0;i<n_speakers;i++)
|
||||
for(j=i+1;j<n_speakers;j++)
|
||||
for(k=j+1;k<n_speakers;k++){
|
||||
for (i = 0; i < n_speakers; i++) {
|
||||
for (j = i+1; j < n_speakers; j++) {
|
||||
for(k=j+1;k<n_speakers;k++) {
|
||||
if (vol_p_side_lgth(i,j, k, _speakers) > MIN_VOL_P_SIDE_LGTH){
|
||||
connections[i][j]=1;
|
||||
connections[j][i]=1;
|
||||
|
|
@ -173,18 +175,24 @@ VBAPSpeakers::choose_ls_triplets(struct ls_triplet_chain **ls_triplets)
|
|||
add_ldsp_triplet(i,j,k,ls_triplets);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*calculate distancies between all speakers and sorting them*/
|
||||
table_size =(((n_speakers - 1) * (n_speakers)) / 2);
|
||||
for(i=0;i<table_size; i++)
|
||||
for (i = 0; i < table_size; i++) {
|
||||
distance_table[i] = 100000.0;
|
||||
for(i=0;i<n_speakers;i++){
|
||||
for(j=(i+1);j<n_speakers; j++){
|
||||
if(connections[i][j] == 1) {
|
||||
}
|
||||
|
||||
for (i = 0;i < n_speakers; i++) {
|
||||
for (j = i+1; j < n_speakers; j++) {
|
||||
if (connections[i][j] == 1) {
|
||||
distance = fabs(vec_angle(_speakers[i].coords,_speakers[j].coords));
|
||||
k=0;
|
||||
while(distance_table[k] < distance)
|
||||
while(distance_table[k] < distance) {
|
||||
k++;
|
||||
for(l=(table_size - 1);l > k ;l--){
|
||||
}
|
||||
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];
|
||||
|
|
@ -200,33 +208,36 @@ VBAPSpeakers::choose_ls_triplets(struct ls_triplet_chain **ls_triplets)
|
|||
/* 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++){
|
||||
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<n_speakers ; j++)
|
||||
for(k=j+1; k<n_speakers; k++)
|
||||
if( (j!=fst_ls) && (k != sec_ls) && (k!=fst_ls) && (j != sec_ls)){
|
||||
if(lines_intersect(fst_ls, sec_ls, j,k) == 1){
|
||||
if (connections[fst_ls][sec_ls] == 1) {
|
||||
for (j = 0; j < n_speakers; j++) {
|
||||
for (k = j+1; k < n_speakers; k++) {
|
||||
if ((j!=fst_ls) && (k != sec_ls) && (k!=fst_ls) && (j != sec_ls)){
|
||||
if (lines_intersect(fst_ls, sec_ls, j,k) == 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){
|
||||
prev = 0;
|
||||
while (trip_ptr != 0){
|
||||
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) == 1 ){
|
||||
if(prev != NULL) {
|
||||
if (connections[i][j] == 0 ||
|
||||
connections[i][k] == 0 ||
|
||||
connections[j][k] == 0 ||
|
||||
any_ls_inside_triplet(i,j,k) == 1 ){
|
||||
if (prev != 0) {
|
||||
prev->next = trip_ptr->next;
|
||||
tmp_ptr = trip_ptr;
|
||||
trip_ptr = trip_ptr->next;
|
||||
|
|
@ -306,20 +317,20 @@ VBAPSpeakers::add_ldsp_triplet(int i, int j, int k, struct ls_triplet_chain **ls
|
|||
|
||||
struct ls_triplet_chain *trip_ptr, *prev;
|
||||
trip_ptr = *ls_triplets;
|
||||
prev = NULL;
|
||||
prev = 0;
|
||||
|
||||
while (trip_ptr != NULL){
|
||||
while (trip_ptr != 0){
|
||||
prev = trip_ptr;
|
||||
trip_ptr = trip_ptr->next;
|
||||
}
|
||||
trip_ptr = (struct ls_triplet_chain*)
|
||||
malloc (sizeof (struct ls_triplet_chain));
|
||||
if (prev == NULL) {
|
||||
if (prev == 0) {
|
||||
*ls_triplets = trip_ptr;
|
||||
} else {
|
||||
prev->next = trip_ptr;
|
||||
}
|
||||
trip_ptr->next = NULL;
|
||||
trip_ptr->next = 0;
|
||||
trip_ptr->ls_nos[0] = i;
|
||||
trip_ptr->ls_nos[1] = j;
|
||||
trip_ptr->ls_nos[2] = k;
|
||||
|
|
@ -463,7 +474,7 @@ VBAPSpeakers::calculate_3x3_matrixes(struct ls_triplet_chain *ls_triplets)
|
|||
|
||||
/* counting triplet amount */
|
||||
|
||||
while (tr_ptr != NULL) {
|
||||
while (tr_ptr != 0) {
|
||||
triplet_count++;
|
||||
tr_ptr = tr_ptr->next;
|
||||
}
|
||||
|
|
@ -476,7 +487,7 @@ VBAPSpeakers::calculate_3x3_matrixes(struct ls_triplet_chain *ls_triplets)
|
|||
_matrices.reserve (triplet_count);
|
||||
_speaker_tuples.reserve (triplet_count);
|
||||
|
||||
while (tr_ptr != NULL) {
|
||||
while (tr_ptr != 0) {
|
||||
lp1 = &(_speakers[tr_ptr->ls_nos[0]].coords);
|
||||
lp2 = &(_speakers[tr_ptr->ls_nos[1]].coords);
|
||||
lp3 = &(_speakers[tr_ptr->ls_nos[2]].coords);
|
||||
|
|
@ -509,9 +520,9 @@ VBAPSpeakers::calculate_3x3_matrixes(struct ls_triplet_chain *ls_triplets)
|
|||
_matrices[triplet][7] = invmx[7];
|
||||
_matrices[triplet][8] = invmx[8];
|
||||
|
||||
_speaker_tuples[triplet][0] = tr_ptr->ls_nos[0]+1;
|
||||
_speaker_tuples[triplet][1] = tr_ptr->ls_nos[1]+1;
|
||||
_speaker_tuples[triplet][2] = tr_ptr->ls_nos[2]+1;
|
||||
_speaker_tuples[triplet][0] = tr_ptr->ls_nos[0];
|
||||
_speaker_tuples[triplet][1] = tr_ptr->ls_nos[1];
|
||||
_speaker_tuples[triplet][2] = tr_ptr->ls_nos[2];
|
||||
|
||||
triplet++;
|
||||
|
||||
|
|
@ -553,7 +564,7 @@ VBAPSpeakers::choose_ls_pairs (){
|
|||
}
|
||||
}
|
||||
|
||||
if(((6.283 - _speakers[sorted_speakers[n_speakers-1]].angles.azi)
|
||||
if (((6.283 - _speakers[sorted_speakers[n_speakers-1]].angles.azi)
|
||||
+_speakers[sorted_speakers[0]].angles.azi) <= (M_PI - 0.175)) {
|
||||
if(calc_2D_inv_tmatrix(_speakers[sorted_speakers[n_speakers-1]].angles.azi,
|
||||
_speakers[sorted_speakers[0]].angles.azi,
|
||||
|
|
@ -578,8 +589,8 @@ VBAPSpeakers::choose_ls_pairs (){
|
|||
_matrices[pair][2] = inverse_matrix[speaker][2];
|
||||
_matrices[pair][3] = inverse_matrix[speaker][3];
|
||||
|
||||
_speaker_tuples[pair][0] = sorted_speakers[speaker]+1;
|
||||
_speaker_tuples[pair][1] = sorted_speakers[speaker+1]+1;
|
||||
_speaker_tuples[pair][0] = sorted_speakers[speaker];
|
||||
_speaker_tuples[pair][1] = sorted_speakers[speaker+1];
|
||||
|
||||
pair++;
|
||||
}
|
||||
|
|
@ -591,8 +602,8 @@ VBAPSpeakers::choose_ls_pairs (){
|
|||
_matrices[pair][2] = inverse_matrix[speaker][2];
|
||||
_matrices[pair][3] = inverse_matrix[speaker][3];
|
||||
|
||||
_speaker_tuples[pair][0] = sorted_speakers[n_speakers-1]+1;
|
||||
_speaker_tuples[pair][1] = sorted_speakers[0]+1;
|
||||
_speaker_tuples[pair][0] = sorted_speakers[n_speakers-1];
|
||||
_speaker_tuples[pair][1] = sorted_speakers[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
71
libs/pbd/cartesian.cc
Normal file
71
libs/pbd/cartesian.cc
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
Copyright (C) 2010 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "pbd/cartesian.h"
|
||||
|
||||
void
|
||||
PBD::azi_ele_to_cart (double azi, double ele, double& x, double& y, double& z)
|
||||
{
|
||||
static const double atorad = 2.0 * M_PI / 360.0 ;
|
||||
x = cos (azi * atorad) * cos (ele * atorad);
|
||||
y = sin (azi * atorad) * cos (ele * atorad);
|
||||
z = sin (ele * atorad);
|
||||
}
|
||||
|
||||
void
|
||||
PBD::cart_to_azi_ele (double x, double y, double z, double& azimuth, double& elevation)
|
||||
{
|
||||
/* converts cartesian coordinates to angular */
|
||||
const double atorad = 2.0 * M_PI / 360.0;
|
||||
double atan_y_per_x, atan_x_pl_y_per_z;
|
||||
double distance;
|
||||
|
||||
if(x == 0.0) {
|
||||
atan_y_per_x = M_PI / 2;
|
||||
} else {
|
||||
atan_y_per_x = atan(y / x);
|
||||
}
|
||||
|
||||
azimuth = atan_y_per_x / atorad;
|
||||
|
||||
if (x < 0.0) {
|
||||
azimuth +=180.0;
|
||||
}
|
||||
|
||||
distance = sqrt (x*x + y*y);
|
||||
|
||||
if (z == 0.0) {
|
||||
atan_x_pl_y_per_z = 0.0;
|
||||
} else {
|
||||
atan_x_pl_y_per_z = atan (z/distance);
|
||||
}
|
||||
|
||||
if (distance == 0.0) {
|
||||
if (z < 0.0) {
|
||||
atan_x_pl_y_per_z = -M_PI/2.0;
|
||||
} else {
|
||||
atan_x_pl_y_per_z = M_PI/2.0;
|
||||
}
|
||||
}
|
||||
|
||||
elevation = atan_x_pl_y_per_z / atorad;
|
||||
|
||||
// distance = sqrtf (x*x + y*y + z*z);
|
||||
}
|
||||
|
||||
27
libs/pbd/pbd/cartesian.h
Normal file
27
libs/pbd/pbd/cartesian.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (C) 2010 Paul Davis
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __libpbd_cartesian_h__
|
||||
#define __libpbd_cartesian_h__
|
||||
|
||||
namespace PBD {
|
||||
void azi_ele_to_cart (double azi, double ele, double& x, double& y, double& z);
|
||||
void cart_to_azi_ele (double x, double y, double z, double& azi, double& ele);
|
||||
}
|
||||
|
||||
#endif /* __libpbd_cartesian_h__ */
|
||||
|
|
@ -58,6 +58,7 @@ def build(bld):
|
|||
basename.cc
|
||||
base_ui.cc
|
||||
boost_debug.cc
|
||||
cartesian.cc
|
||||
command.cc
|
||||
convert.cc
|
||||
controllable.cc
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue