aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Barknecht <fbar@users.sourceforge.net>2007-01-12 18:47:38 +0000
committerFrank Barknecht <fbar@users.sourceforge.net>2007-01-12 18:47:38 +0000
commit702e421b51e451dbc7e4780a1cd1f862492b4f17 (patch)
treeceffd3dea174014a21d1fb0b1ad177984a0c1fc9
parentdfd0fa9004935b3e0bea32994a7ae9f9371bdb82 (diff)
Added Olaf Matthes' extension of vbap called rvbap, ported from Max to Pd, plus
help and demo file. svn path=/trunk/externals/vbap/; revision=7311
-rw-r--r--rvbap-demo.pd662
-rw-r--r--rvbap-help.pd278
-rw-r--r--rvbap.c935
3 files changed, 1875 insertions, 0 deletions
diff --git a/rvbap-demo.pd b/rvbap-demo.pd
new file mode 100644
index 0000000..94442d4
--- /dev/null
+++ b/rvbap-demo.pd
@@ -0,0 +1,662 @@
+#N canvas 243 71 893 632 10;
+#X obj 345 85 define_loudspeakers 3 -45 0 45 0 0 45 180 45;
+#X msg 34 63 bang;
+#X obj 34 83 define_loudspeakers 2 -45 45 135 -135;
+#X msg 345 60 bang;
+#X floatatom 196 497 5 0 100 1 dB_after_1sec - -;
+#X obj 34 591 dac~ 1 2 3 4;
+#N canvas 0 0 699 527 sig 0;
+#X obj 58 72 line~;
+#X msg 58 49 0 \, 10000 5;
+#X obj 58 118 cos~;
+#X msg 146 70 1;
+#X obj 146 47 loadbang;
+#X obj 58 95 clip~ 0 0.25;
+#X obj 251 134 line~;
+#X obj 251 157 cos~;
+#X msg 324 54 -0.25 \, 0.25 100;
+#X obj 251 8 loadbang;
+#X msg 251 31 -0.25;
+#X obj 251 203 *~;
+#X obj 58 140 hip~ 5;
+#X msg 324 77 -0.25 \, 0.25 400;
+#X floatatom 151 126 0 0 0 0 freq - -;
+#X obj 324 191 osc~ 440;
+#X obj 324 168 mtof;
+#X msg 324 31 -0.25 \, 0.25 20;
+#X obj 251 180 *~ 0.1;
+#X msg 324 100 -0.25 \, 0.25 1000;
+#X msg 324 122 -0.25 \, 0.25 2000;
+#X obj 324 226 *~;
+#X obj 342 252 *~;
+#X msg 324 8 0;
+#X obj 308 257 *~;
+#X obj 58 26 metro 2000;
+#X floatatom 58 4 0 0 0 0 - - -;
+#X text 1 51 impulse;
+#X text 362 7 tone;
+#X obj 59 184 outlet~;
+#X obj 170 6 inlet;
+#X obj 442 18 metro 500;
+#X obj 91 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X connect 0 0 5 0;
+#X connect 1 0 0 0;
+#X connect 2 0 12 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 18 0;
+#X connect 8 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 11 0 12 0;
+#X connect 12 0 29 0;
+#X connect 13 0 6 0;
+#X connect 14 0 16 0;
+#X connect 15 0 11 1;
+#X connect 15 0 21 0;
+#X connect 15 0 21 1;
+#X connect 15 0 22 0;
+#X connect 16 0 15 0;
+#X connect 17 0 6 0;
+#X connect 18 0 11 0;
+#X connect 19 0 6 0;
+#X connect 20 0 6 0;
+#X connect 21 0 22 1;
+#X connect 21 0 11 1;
+#X connect 21 0 24 0;
+#X connect 21 0 24 1;
+#X connect 22 0 11 1;
+#X connect 23 0 6 0;
+#X connect 24 0 11 1;
+#X connect 25 0 1 0;
+#X connect 26 0 25 0;
+#X connect 30 0 31 0;
+#X connect 31 0 8 0;
+#X connect 32 0 25 0;
+#X coords 0 -1 1 1 85 60 1 100 100;
+#X restore 63 415 pd sig;
+#X obj 63 387 tgl 24 0 empty empty test-sigs 26 7 1 10 -262144 -1 -1
+0 1;
+#X msg 216 522 clear;
+#N canvas 0 0 766 594 four-reverbs 0;
+#X obj 67 179 rev1~;
+#X obj 114 179 rev1~;
+#X obj 160 179 rev1~;
+#X obj 210 179 rev1~;
+#X obj 282 55 inlet;
+#X obj 67 54 inlet~;
+#X obj 113 54 inlet~;
+#X obj 160 53 inlet~;
+#X obj 211 53 inlet~;
+#X obj 67 286 outlet~;
+#X obj 114 268 outlet~;
+#X obj 159 246 outlet~;
+#X obj 209 226 outlet~;
+#X obj 339 55 inlet;
+#X obj 339 76 b;
+#X connect 0 0 9 0;
+#X connect 1 0 10 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 4 0 3 1;
+#X connect 4 0 2 1;
+#X connect 4 0 1 1;
+#X connect 4 0 0 1;
+#X connect 5 0 0 0;
+#X connect 6 0 1 0;
+#X connect 7 0 2 0;
+#X connect 8 0 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 3 2;
+#X connect 14 0 2 2;
+#X connect 14 0 1 2;
+#X connect 14 0 0 2;
+#X restore 116 544 pd four-reverbs;
+#N canvas 0 0 699 527 sig 0;
+#X obj 58 72 line~;
+#X msg 58 49 0 \, 10000 5;
+#X obj 58 118 cos~;
+#X msg 146 70 1;
+#X obj 146 47 loadbang;
+#X obj 58 95 clip~ 0 0.25;
+#X obj 251 134 line~;
+#X obj 251 157 cos~;
+#X msg 324 54 -0.25 \, 0.25 100;
+#X obj 251 8 loadbang;
+#X msg 251 31 -0.25;
+#X obj 251 203 *~;
+#X obj 58 140 hip~ 5;
+#X msg 324 77 -0.25 \, 0.25 400;
+#X floatatom 134 122 0 0 0 0 freq - -;
+#X obj 324 191 osc~ 440;
+#X obj 324 168 mtof;
+#X msg 324 31 -0.25 \, 0.25 20;
+#X obj 251 180 *~ 0.1;
+#X msg 324 100 -0.25 \, 0.25 1000;
+#X msg 324 122 -0.25 \, 0.25 2000;
+#X obj 324 226 *~;
+#X obj 342 252 *~;
+#X msg 324 8 0;
+#X obj 308 257 *~;
+#X obj 58 26 metro 2000;
+#X floatatom 58 4 0 0 0 0 - - -;
+#X text 1 51 impulse;
+#X text 362 7 tone;
+#X obj 59 184 outlet~;
+#X obj 170 6 inlet;
+#X obj 442 18 metro 500;
+#X obj 91 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X connect 0 0 5 0;
+#X connect 1 0 0 0;
+#X connect 2 0 12 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 18 0;
+#X connect 8 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 11 0 12 0;
+#X connect 12 0 29 0;
+#X connect 13 0 6 0;
+#X connect 14 0 16 0;
+#X connect 15 0 11 1;
+#X connect 15 0 21 0;
+#X connect 15 0 21 1;
+#X connect 15 0 22 0;
+#X connect 16 0 15 0;
+#X connect 17 0 6 0;
+#X connect 18 0 11 0;
+#X connect 19 0 6 0;
+#X connect 20 0 6 0;
+#X connect 21 0 22 1;
+#X connect 21 0 11 1;
+#X connect 21 0 24 0;
+#X connect 21 0 24 1;
+#X connect 22 0 11 1;
+#X connect 23 0 6 0;
+#X connect 24 0 11 1;
+#X connect 25 0 1 0;
+#X connect 26 0 25 0;
+#X connect 30 0 31 0;
+#X connect 31 0 8 0;
+#X connect 32 0 25 0;
+#X coords 0 -1 1 1 85 60 1 100 100;
+#X restore 156 414 pd sig;
+#X obj 156 386 tgl 24 0 empty empty test-sigs 26 7 1 10 -262144 -1
+-1 0 1;
+#X obj 34 364 mtx 8 3;
+#X obj 35 498 mtx_*~ 8 3 20;
+#N canvas 0 0 699 527 sig 0;
+#X obj 58 72 line~;
+#X msg 58 49 0 \, 10000 5;
+#X obj 58 118 cos~;
+#X msg 146 70 1;
+#X obj 146 47 loadbang;
+#X obj 58 95 clip~ 0 0.25;
+#X obj 251 134 line~;
+#X obj 251 157 cos~;
+#X msg 324 54 -0.25 \, 0.25 100;
+#X obj 251 8 loadbang;
+#X msg 251 31 -0.25;
+#X obj 251 203 *~;
+#X obj 58 140 hip~ 5;
+#X msg 324 77 -0.25 \, 0.25 400;
+#X floatatom 134 122 0 0 0 0 freq - -;
+#X obj 324 191 osc~ 440;
+#X obj 324 168 mtof;
+#X msg 324 31 -0.25 \, 0.25 20;
+#X obj 251 180 *~ 0.1;
+#X msg 324 100 -0.25 \, 0.25 1000;
+#X msg 324 122 -0.25 \, 0.25 2000;
+#X obj 324 226 *~;
+#X obj 342 252 *~;
+#X msg 324 8 0;
+#X obj 308 257 *~;
+#X obj 58 26 metro 2000;
+#X floatatom 58 4 0 0 0 0 - - -;
+#X text 1 51 impulse;
+#X text 362 7 tone;
+#X obj 59 184 outlet~;
+#X obj 170 6 inlet;
+#X obj 442 18 metro 500;
+#X obj 91 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X connect 0 0 5 0;
+#X connect 1 0 0 0;
+#X connect 2 0 12 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 18 0;
+#X connect 8 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 11 0 12 0;
+#X connect 12 0 29 0;
+#X connect 13 0 6 0;
+#X connect 14 0 16 0;
+#X connect 15 0 11 1;
+#X connect 15 0 21 0;
+#X connect 15 0 21 1;
+#X connect 15 0 22 0;
+#X connect 16 0 15 0;
+#X connect 17 0 6 0;
+#X connect 18 0 11 0;
+#X connect 19 0 6 0;
+#X connect 20 0 6 0;
+#X connect 21 0 22 1;
+#X connect 21 0 11 1;
+#X connect 21 0 24 0;
+#X connect 21 0 24 1;
+#X connect 22 0 11 1;
+#X connect 23 0 6 0;
+#X connect 24 0 11 1;
+#X connect 25 0 1 0;
+#X connect 26 0 25 0;
+#X connect 30 0 31 0;
+#X connect 31 0 8 0;
+#X connect 32 0 25 0;
+#X coords 0 -1 1 1 85 60 1 100 100;
+#X restore 250 416 pd sig;
+#X obj 250 388 tgl 24 0 empty empty test-sigs 26 7 1 10 -262144 -1
+-1 0 1;
+#X obj 196 353 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#N canvas 0 0 818 424 rvbap-module0 0;
+#X floatatom 104 128 5 0 0 2 azi - -;
+#X floatatom 148 128 5 0 0 2 ele - -;
+#X floatatom 192 128 5 0 100 2 spread - -;
+#X text 199 262 actual location;
+#X obj 83 202 rvbap 0 0;
+#X floatatom 245 129 5 1 20 2 dist - -;
+#X floatatom 127 233 5 0 0 3 azi - -;
+#X floatatom 171 233 5 0 0 3 ele - -;
+#X floatatom 215 233 5 0 0 3 spread - -;
+#X floatatom 268 234 5 0 0 3 dist - -;
+#N canvas 352 196 547 360 set-element 0;
+#X obj 70 81 unpack 0 0;
+#X obj 70 104 + 1;
+#X obj 70 137 pack 0 1 0;
+#X obj 70 179 list trim;
+#X obj 70 158 list prepend element;
+#X obj 70 59 inlet;
+#X obj 70 261 outlet;
+#X obj 70 221 t b a;
+#X text 48 33 transforms rvbap-output to be used with [mtx] from iemmatrix
+;
+#X obj 168 80 inlet;
+#X connect 0 0 1 0;
+#X connect 0 1 2 2;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X connect 7 0 6 0;
+#X connect 7 1 6 0;
+#X connect 9 0 2 1;
+#X restore 83 316 pd set-element;
+#N canvas 203 642 802 273 peek 0;
+#X floatatom 55 198 10 0 0 0 - - -;
+#X floatatom 134 198 10 0 0 0 - - -;
+#X floatatom 213 198 10 0 0 0 - - -;
+#X floatatom 292 198 10 0 0 0 - - -;
+#X obj 55 74 route 0 1 2 3 4 5 6 7;
+#X floatatom 366 197 10 0 0 0 - - -;
+#X floatatom 445 197 10 0 0 0 - - -;
+#X floatatom 524 197 10 0 0 0 - - -;
+#X floatatom 603 197 10 0 0 0 - - -;
+#X obj 55 49 inlet;
+#X connect 4 0 0 0;
+#X connect 4 1 1 0;
+#X connect 4 2 2 0;
+#X connect 4 3 3 0;
+#X connect 4 4 5 0;
+#X connect 4 5 6 0;
+#X connect 4 6 7 0;
+#X connect 4 7 8 0;
+#X connect 9 0 4 0;
+#X restore 97 290 pd peek;
+#N canvas 0 0 450 300 tba 0;
+#X obj 143 51 inlet;
+#X obj 96 49 inlet;
+#X obj 191 51 inlet;
+#X obj 238 51 inlet;
+#X obj 173 180 outlet;
+#X obj 61 178 outlet;
+#X obj 221 180 outlet;
+#X obj 268 180 outlet;
+#X obj 126 180 outlet;
+#X obj 96 73 t b a;
+#X obj 143 72 t b a;
+#X obj 191 72 t b a;
+#X obj 238 72 t b a;
+#X connect 0 0 10 0;
+#X connect 1 0 9 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 9 0 5 0;
+#X connect 9 1 8 0;
+#X connect 10 0 5 0;
+#X connect 10 1 4 0;
+#X connect 11 0 5 0;
+#X connect 11 1 6 0;
+#X connect 12 0 5 0;
+#X connect 12 1 7 0;
+#X restore 104 168 pd tba;
+#X obj 281 114 hsl 64 15 1 20 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 386 102 loadbang;
+#X obj 83 345 outlet;
+#X obj 83 39 inlet;
+#X obj 304 140 hradio 15 1 0 3 empty empty id: -20 8 1 10 -262144 -1
+-1 0;
+#X obj 386 123 0;
+#X obj 539 151 f \$1;
+#X text 378 152 in an abstraction \, use;
+#X text 575 154 topass id as argument.;
+#X obj 338 272 + 1;
+#X connect 0 0 12 0;
+#X connect 1 0 12 1;
+#X connect 2 0 12 2;
+#X connect 4 0 10 0;
+#X connect 4 0 11 0;
+#X connect 4 1 6 0;
+#X connect 4 2 7 0;
+#X connect 4 3 8 0;
+#X connect 4 4 9 0;
+#X connect 5 0 12 3;
+#X connect 10 0 15 0;
+#X connect 12 0 4 0;
+#X connect 12 1 4 1;
+#X connect 12 2 4 2;
+#X connect 12 3 4 3;
+#X connect 12 4 4 4;
+#X connect 13 0 5 0;
+#X connect 14 0 18 0;
+#X connect 16 0 4 0;
+#X connect 17 0 22 0;
+#X connect 18 0 17 0;
+#X connect 22 0 10 1;
+#X coords 0 -1 1 1 260 60 1 100 100;
+#X restore 34 229 pd rvbap-module0;
+#N canvas 0 0 858 488 rvbap-module1 0;
+#X floatatom 104 128 5 0 0 2 azi - -;
+#X floatatom 148 128 5 0 0 2 ele - -;
+#X floatatom 192 128 5 0 100 2 spread - -;
+#X text 199 262 actual location;
+#X obj 83 202 rvbap 0 0;
+#X floatatom 245 129 5 1 20 2 dist - -;
+#X floatatom 127 233 5 0 0 3 azi - -;
+#X floatatom 171 233 5 0 0 3 ele - -;
+#X floatatom 215 233 5 0 0 3 spread - -;
+#X floatatom 268 234 5 0 0 3 dist - -;
+#N canvas 352 196 547 360 set-element 0;
+#X obj 70 81 unpack 0 0;
+#X obj 70 104 + 1;
+#X obj 70 137 pack 0 1 0;
+#X obj 70 179 list trim;
+#X obj 70 158 list prepend element;
+#X obj 70 59 inlet;
+#X obj 70 261 outlet;
+#X obj 70 221 t b a;
+#X text 48 33 transforms rvbap-output to be used with [mtx] from iemmatrix
+;
+#X obj 168 80 inlet;
+#X connect 0 0 1 0;
+#X connect 0 1 2 2;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X connect 7 0 6 0;
+#X connect 7 1 6 0;
+#X connect 9 0 2 1;
+#X restore 83 316 pd set-element;
+#N canvas 203 642 802 273 peek 0;
+#X floatatom 55 198 10 0 0 0 - - -;
+#X floatatom 134 198 10 0 0 0 - - -;
+#X floatatom 213 198 10 0 0 0 - - -;
+#X floatatom 292 198 10 0 0 0 - - -;
+#X obj 55 74 route 0 1 2 3 4 5 6 7;
+#X floatatom 366 197 10 0 0 0 - - -;
+#X floatatom 445 197 10 0 0 0 - - -;
+#X floatatom 524 197 10 0 0 0 - - -;
+#X floatatom 603 197 10 0 0 0 - - -;
+#X obj 55 49 inlet;
+#X connect 4 0 0 0;
+#X connect 4 1 1 0;
+#X connect 4 2 2 0;
+#X connect 4 3 3 0;
+#X connect 4 4 5 0;
+#X connect 4 5 6 0;
+#X connect 4 6 7 0;
+#X connect 4 7 8 0;
+#X connect 9 0 4 0;
+#X restore 97 290 pd peek;
+#N canvas 0 0 450 300 tba 0;
+#X obj 143 51 inlet;
+#X obj 96 49 inlet;
+#X obj 191 51 inlet;
+#X obj 238 51 inlet;
+#X obj 173 180 outlet;
+#X obj 61 178 outlet;
+#X obj 221 180 outlet;
+#X obj 268 180 outlet;
+#X obj 126 180 outlet;
+#X obj 96 73 t b a;
+#X obj 143 72 t b a;
+#X obj 191 72 t b a;
+#X obj 238 72 t b a;
+#X connect 0 0 10 0;
+#X connect 1 0 9 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 9 0 5 0;
+#X connect 9 1 8 0;
+#X connect 10 0 5 0;
+#X connect 10 1 4 0;
+#X connect 11 0 5 0;
+#X connect 11 1 6 0;
+#X connect 12 0 5 0;
+#X connect 12 1 7 0;
+#X restore 104 168 pd tba;
+#X obj 281 114 hsl 64 15 1 20 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 386 102 loadbang;
+#X obj 83 345 outlet;
+#X obj 83 39 inlet;
+#X obj 304 140 hradio 15 1 0 3 empty empty id: -20 8 1 10 -262144 -1
+-1 1;
+#X obj 386 123 1;
+#X obj 544 152 f \$1;
+#X text 383 153 in an abstraction \, use;
+#X text 580 155 topass id as argument.;
+#X obj 338 272 + 1;
+#X connect 0 0 12 0;
+#X connect 1 0 12 1;
+#X connect 2 0 12 2;
+#X connect 4 0 10 0;
+#X connect 4 0 11 0;
+#X connect 4 1 6 0;
+#X connect 4 2 7 0;
+#X connect 4 3 8 0;
+#X connect 4 4 9 0;
+#X connect 5 0 12 3;
+#X connect 10 0 15 0;
+#X connect 12 0 4 0;
+#X connect 12 1 4 1;
+#X connect 12 2 4 2;
+#X connect 12 3 4 3;
+#X connect 12 4 4 4;
+#X connect 13 0 5 0;
+#X connect 14 0 18 0;
+#X connect 16 0 4 0;
+#X connect 17 0 22 0;
+#X connect 18 0 17 0;
+#X connect 22 0 10 1;
+#X coords 0 -1 1 1 260 60 1 100 100;
+#X restore 303 229 pd rvbap-module1;
+#N canvas 0 0 798 493 rvbap-module3 0;
+#X floatatom 104 128 5 0 0 2 azi - -;
+#X floatatom 148 128 5 0 0 2 ele - -;
+#X floatatom 192 128 5 0 100 2 spread - -;
+#X text 199 262 actual location;
+#X obj 83 202 rvbap 0 0;
+#X floatatom 245 129 5 1 20 2 dist - -;
+#X floatatom 127 233 5 0 0 3 azi - -;
+#X floatatom 171 233 5 0 0 3 ele - -;
+#X floatatom 215 233 5 0 0 3 spread - -;
+#X floatatom 268 234 5 0 0 3 dist - -;
+#N canvas 352 196 547 360 set-element 0;
+#X obj 70 81 unpack 0 0;
+#X obj 70 104 + 1;
+#X obj 70 137 pack 0 1 0;
+#X obj 70 179 list trim;
+#X obj 70 158 list prepend element;
+#X obj 70 59 inlet;
+#X obj 70 261 outlet;
+#X obj 70 221 t b a;
+#X text 48 33 transforms rvbap-output to be used with [mtx] from iemmatrix
+;
+#X obj 168 80 inlet;
+#X connect 0 0 1 0;
+#X connect 0 1 2 2;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X connect 7 0 6 0;
+#X connect 7 1 6 0;
+#X connect 9 0 2 1;
+#X restore 83 316 pd set-element;
+#N canvas 203 642 802 273 peek 0;
+#X floatatom 55 198 10 0 0 0 - - -;
+#X floatatom 134 198 10 0 0 0 - - -;
+#X floatatom 213 198 10 0 0 0 - - -;
+#X floatatom 292 198 10 0 0 0 - - -;
+#X obj 55 74 route 0 1 2 3 4 5 6 7;
+#X floatatom 366 197 10 0 0 0 - - -;
+#X floatatom 445 197 10 0 0 0 - - -;
+#X floatatom 524 197 10 0 0 0 - - -;
+#X floatatom 603 197 10 0 0 0 - - -;
+#X obj 55 49 inlet;
+#X connect 4 0 0 0;
+#X connect 4 1 1 0;
+#X connect 4 2 2 0;
+#X connect 4 3 3 0;
+#X connect 4 4 5 0;
+#X connect 4 5 6 0;
+#X connect 4 6 7 0;
+#X connect 4 7 8 0;
+#X connect 9 0 4 0;
+#X restore 97 290 pd peek;
+#N canvas 0 0 450 300 tba 0;
+#X obj 143 51 inlet;
+#X obj 96 49 inlet;
+#X obj 191 51 inlet;
+#X obj 238 51 inlet;
+#X obj 173 180 outlet;
+#X obj 61 178 outlet;
+#X obj 221 180 outlet;
+#X obj 268 180 outlet;
+#X obj 126 180 outlet;
+#X obj 96 73 t b a;
+#X obj 143 72 t b a;
+#X obj 191 72 t b a;
+#X obj 238 72 t b a;
+#X connect 0 0 10 0;
+#X connect 1 0 9 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 9 0 5 0;
+#X connect 9 1 8 0;
+#X connect 10 0 5 0;
+#X connect 10 1 4 0;
+#X connect 11 0 5 0;
+#X connect 11 1 6 0;
+#X connect 12 0 5 0;
+#X connect 12 1 7 0;
+#X restore 104 168 pd tba;
+#X obj 281 114 hsl 64 15 1 20 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 546 102 loadbang;
+#X obj 83 345 outlet;
+#X obj 83 39 inlet;
+#X obj 304 140 hradio 15 1 0 3 empty empty id: -20 8 1 10 -262144 -1
+-1 2;
+#X obj 546 123 2;
+#X obj 547 186 f \$1;
+#X text 386 187 in an abstraction \, use;
+#X text 583 189 topass id as argument.;
+#X obj 338 272 + 1;
+#X connect 0 0 12 0;
+#X connect 1 0 12 1;
+#X connect 2 0 12 2;
+#X connect 4 0 10 0;
+#X connect 4 0 11 0;
+#X connect 4 1 6 0;
+#X connect 4 2 7 0;
+#X connect 4 3 8 0;
+#X connect 4 4 9 0;
+#X connect 5 0 12 3;
+#X connect 10 0 15 0;
+#X connect 12 0 4 0;
+#X connect 12 1 4 1;
+#X connect 12 2 4 2;
+#X connect 12 3 4 3;
+#X connect 12 4 4 4;
+#X connect 13 0 5 0;
+#X connect 14 0 18 0;
+#X connect 16 0 4 0;
+#X connect 17 0 22 0;
+#X connect 18 0 17 0;
+#X connect 22 0 10 1;
+#X coords 0 -1 1 1 260 60 1 100 100;
+#X restore 566 230 pd rvbap-module3;
+#X text 594 203 put this into an abstraction:;
+#X text 63 21 RVBAP - Demo how to use [mtx_*~];
+#X connect 0 0 19 0;
+#X connect 0 0 18 0;
+#X connect 0 0 17 0;
+#X connect 1 0 2 0;
+#X connect 2 0 17 0;
+#X connect 2 0 18 0;
+#X connect 2 0 19 0;
+#X connect 3 0 0 0;
+#X connect 4 0 9 4;
+#X connect 6 0 13 1;
+#X connect 7 0 6 0;
+#X connect 8 0 9 5;
+#X connect 9 0 5 0;
+#X connect 9 1 5 1;
+#X connect 9 2 5 2;
+#X connect 9 3 5 3;
+#X connect 10 0 13 2;
+#X connect 11 0 10 0;
+#X connect 12 0 13 0;
+#X connect 13 0 5 0;
+#X connect 13 1 5 1;
+#X connect 13 2 5 2;
+#X connect 13 3 5 3;
+#X connect 13 4 9 0;
+#X connect 13 5 9 1;
+#X connect 13 6 9 2;
+#X connect 13 7 9 3;
+#X connect 14 0 13 3;
+#X connect 15 0 14 0;
+#X connect 16 0 11 0;
+#X connect 16 0 15 0;
+#X connect 16 0 7 0;
+#X connect 17 0 12 0;
+#X connect 18 0 12 0;
+#X connect 19 0 12 0;
diff --git a/rvbap-help.pd b/rvbap-help.pd
new file mode 100644
index 0000000..e9365c6
--- /dev/null
+++ b/rvbap-help.pd
@@ -0,0 +1,278 @@
+#N canvas 243 71 910 727 10;
+#X obj 98 144 define_loudspeakers 3 -45 0 45 0 0 45 180 45;
+#X msg 32 62 bang;
+#X floatatom 136 276 5 0 0 2 azi - -;
+#X floatatom 180 276 5 0 0 2 ele - -;
+#X floatatom 224 276 5 0 100 2 spread - -;
+#X msg 115 173 bang;
+#X text 428 201 In two dimensions \, only specify the azimuth. (for
+example "define_loudspeakers 2 -45 45 0 180";
+#X text 63 21 VBAP and define_loudspeakers;
+#X text 430 338 The spread-parameter can be used to prevent a situation
+where sound is coming from one speaker only \, which would make speaker
+positions "visible". The range is 0 to 100;
+#X text 231 410 actual location;
+#X obj 115 350 rvbap 0 0;
+#X floatatom 277 277 5 1 20 2 dist - -;
+#X text 131 241 azimuth \, elevation \, spread and distance;
+#X msg 98 119 bang;
+#X text 428 111 1) Use define_loudspeakers to list the speaker positions.
+The example here defines loudspeakers in three dimensions (the first
+parameter). For each speaker \, define its azimuth and elevation. Here
+we have speakers front left and right with no elevation (-45 0 45 0)
+and front and back with 45 degrees of elevation (0 45 180 45). Send
+the data to vbap.;
+#X floatatom 159 381 5 0 0 3 azi - -;
+#X floatatom 203 381 5 0 0 3 ele - -;
+#X floatatom 247 381 5 0 0 3 spread - -;
+#X floatatom 300 382 5 0 0 3 dist - -;
+#X floatatom 277 597 5 0 100 1 dB_after_1sec - -;
+#X obj 114 691 dac~ 1 2 3 4;
+#N canvas 0 0 699 527 sig 0;
+#X obj 58 72 line~;
+#X msg 58 49 0 \, 10000 5;
+#X obj 58 118 cos~;
+#X msg 146 70 1;
+#X obj 146 47 loadbang;
+#X obj 58 95 clip~ 0 0.25;
+#X obj 251 134 line~;
+#X obj 251 157 cos~;
+#X msg 324 54 -0.25 \, 0.25 100;
+#X obj 251 8 loadbang;
+#X msg 251 31 -0.25;
+#X obj 251 203 *~;
+#X obj 58 140 hip~ 5;
+#X msg 324 77 -0.25 \, 0.25 400;
+#X floatatom 324 145 0 0 0 0 - - -;
+#X obj 324 191 osc~ 440;
+#X obj 324 168 mtof;
+#X msg 324 31 -0.25 \, 0.25 20;
+#X obj 251 180 *~ 0.1;
+#X msg 324 100 -0.25 \, 0.25 1000;
+#X msg 324 122 -0.25 \, 0.25 2000;
+#X obj 324 226 *~;
+#X obj 342 252 *~;
+#X msg 324 8 0;
+#X obj 308 257 *~;
+#X obj 58 26 metro 2000;
+#X floatatom 58 4 0 0 0 0 - - -;
+#X text 1 51 impulse;
+#X text 362 7 tone;
+#X obj 59 184 outlet~;
+#X obj 170 6 inlet;
+#X obj 442 18 metro 500;
+#X obj 91 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X connect 0 0 5 0;
+#X connect 1 0 0 0;
+#X connect 2 0 12 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 18 0;
+#X connect 8 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 11 0 12 0;
+#X connect 12 0 29 0;
+#X connect 13 0 6 0;
+#X connect 14 0 16 0;
+#X connect 15 0 11 1;
+#X connect 15 0 21 0;
+#X connect 15 0 21 1;
+#X connect 15 0 22 0;
+#X connect 16 0 15 0;
+#X connect 17 0 6 0;
+#X connect 18 0 11 0;
+#X connect 19 0 6 0;
+#X connect 20 0 6 0;
+#X connect 21 0 22 1;
+#X connect 21 0 11 1;
+#X connect 21 0 24 0;
+#X connect 21 0 24 1;
+#X connect 22 0 11 1;
+#X connect 23 0 6 0;
+#X connect 24 0 11 1;
+#X connect 25 0 1 0;
+#X connect 26 0 25 0;
+#X connect 30 0 31 0;
+#X connect 31 0 8 0;
+#X connect 32 0 25 0;
+#X restore 159 545 pd sig;
+#X obj 159 517 tgl 24 0 empty empty test-sigs 26 7 1 10 -262144 -1
+-1 0 1;
+#X obj 115 488 mtx 8 1;
+#N canvas 352 196 547 360 set-element 0;
+#X obj 70 81 unpack 0 0;
+#X obj 70 104 + 1;
+#X obj 70 137 pack 0 1 0;
+#X obj 70 179 list trim;
+#X obj 70 158 list prepend element;
+#X obj 70 59 inlet;
+#X obj 70 261 outlet;
+#X obj 70 221 t b a;
+#X text 48 33 transforms rvbap-output to be used with [mtx] from iemmatrix
+;
+#X connect 0 0 1 0;
+#X connect 0 1 2 2;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X connect 7 0 6 0;
+#X connect 7 1 6 0;
+#X restore 115 464 pd set-element;
+#N canvas 203 642 802 273 peek 0;
+#X floatatom 55 198 10 0 0 0 - - -;
+#X floatatom 134 198 10 0 0 0 - - -;
+#X floatatom 213 198 10 0 0 0 - - -;
+#X floatatom 292 198 10 0 0 0 - - -;
+#X obj 55 74 route 0 1 2 3 4 5 6 7;
+#X floatatom 366 197 10 0 0 0 - - -;
+#X floatatom 445 197 10 0 0 0 - - -;
+#X floatatom 524 197 10 0 0 0 - - -;
+#X floatatom 603 197 10 0 0 0 - - -;
+#X obj 55 49 inlet;
+#X connect 4 0 0 0;
+#X connect 4 1 1 0;
+#X connect 4 2 2 0;
+#X connect 4 3 3 0;
+#X connect 4 4 5 0;
+#X connect 4 5 6 0;
+#X connect 4 6 7 0;
+#X connect 4 7 8 0;
+#X connect 9 0 4 0;
+#X restore 129 438 pd peek;
+#X floatatom 201 567 5 0 0 1 interp - -;
+#X msg 297 622 clear;
+#N canvas 0 0 450 300 tba 0;
+#X obj 143 51 inlet;
+#X obj 96 49 inlet;
+#X obj 191 51 inlet;
+#X obj 238 51 inlet;
+#X obj 173 180 outlet;
+#X obj 61 178 outlet;
+#X obj 221 180 outlet;
+#X obj 268 180 outlet;
+#X obj 126 180 outlet;
+#X obj 96 73 t b a;
+#X obj 143 72 t b a;
+#X obj 191 72 t b a;
+#X obj 238 72 t b a;
+#X connect 0 0 10 0;
+#X connect 1 0 9 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 9 0 5 0;
+#X connect 9 1 8 0;
+#X connect 10 0 5 0;
+#X connect 10 1 4 0;
+#X connect 11 0 5 0;
+#X connect 11 1 6 0;
+#X connect 12 0 5 0;
+#X connect 12 1 7 0;
+#X restore 136 316 pd tba;
+#X obj 318 262 hsl 64 15 1 20 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#N canvas 0 0 766 594 four-reverbs 0;
+#X obj 67 179 rev1~;
+#X obj 114 179 rev1~;
+#X obj 160 179 rev1~;
+#X obj 210 179 rev1~;
+#X obj 282 55 inlet;
+#X obj 67 54 inlet~;
+#X obj 113 54 inlet~;
+#X obj 160 53 inlet~;
+#X obj 211 53 inlet~;
+#X obj 67 286 outlet~;
+#X obj 114 268 outlet~;
+#X obj 159 246 outlet~;
+#X obj 209 226 outlet~;
+#X obj 339 55 inlet;
+#X obj 339 76 b;
+#X connect 0 0 9 0;
+#X connect 1 0 10 0;
+#X connect 2 0 11 0;
+#X connect 3 0 12 0;
+#X connect 4 0 3 1;
+#X connect 4 0 2 1;
+#X connect 4 0 1 1;
+#X connect 4 0 0 1;
+#X connect 5 0 0 0;
+#X connect 6 0 1 0;
+#X connect 7 0 2 0;
+#X connect 8 0 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 3 2;
+#X connect 14 0 2 2;
+#X connect 14 0 1 2;
+#X connect 14 0 0 2;
+#X restore 197 644 pd four-reverbs;
+#X text 429 15 rvbap is almost compatible to;
+#X obj 644 15 vbap 0 0;
+#X obj 33 82 define_loudspeakers 2 -45 45 0 180;
+#X obj 115 599 mtx_*~ 8 1 20;
+#X text 711 17 see help for this \, too.;
+#X text 429 36 Additionally it generates additional commands for controlling
+a reverberated signal and has control to set the radial distance of
+a sound.;
+#X text 430 397 3) rvbap also will generate messages to control the
+amount of reverberated signal to generate. This is meant to be used
+with [matrix~] or [mtx_*~] from the IEMmatrix collection of externals.
+;
+#X text 431 255 2) For rvbap \, give azimuth and elevation and a distance
+(1-inf \, default 1) for the desired location. Bang the first inlet
+and vbap will output gain-factors for each speaker and the actual location
+produced. This can be different from the desired one depending where
+your speakers are.;
+#X text 433 589 See rvbap-demo.pd for a more complex setup.;
+#X text 429 467 To use it \, create a [mtx_*~] object that has double
+the amount of outlets as you have speakers. Send the first half of
+the matrix-signals to the speakers and the second half through a reverbarator
+and add them to the respective speaker outs. The example shows this
+in action for four speakers. Pay attention to the "set-element" subpatch
+which translates the [rvbap] output to set matrix elements correctly.
+;
+#X text 193 439 <= here's the output of [rvbap];
+#X connect 0 0 10 0;
+#X connect 1 0 33 0;
+#X connect 2 0 28 0;
+#X connect 3 0 28 1;
+#X connect 4 0 28 2;
+#X connect 5 0 10 0;
+#X connect 10 0 24 0;
+#X connect 10 0 25 0;
+#X connect 10 1 15 0;
+#X connect 10 2 16 0;
+#X connect 10 3 17 0;
+#X connect 10 4 18 0;
+#X connect 11 0 28 3;
+#X connect 13 0 0 0;
+#X connect 19 0 30 4;
+#X connect 21 0 34 1;
+#X connect 22 0 21 0;
+#X connect 23 0 34 0;
+#X connect 24 0 23 0;
+#X connect 26 0 34 2;
+#X connect 27 0 30 5;
+#X connect 28 0 10 0;
+#X connect 28 1 10 1;
+#X connect 28 2 10 2;
+#X connect 28 3 10 3;
+#X connect 28 4 10 4;
+#X connect 29 0 11 0;
+#X connect 30 0 20 0;
+#X connect 30 1 20 1;
+#X connect 30 2 20 2;
+#X connect 30 3 20 3;
+#X connect 33 0 10 0;
+#X connect 34 0 20 0;
+#X connect 34 1 20 1;
+#X connect 34 2 20 2;
+#X connect 34 3 20 3;
+#X connect 34 4 30 0;
+#X connect 34 5 30 1;
+#X connect 34 6 30 2;
+#X connect 34 7 30 3;
diff --git a/rvbap.c b/rvbap.c
new file mode 100644
index 0000000..9b023c3
--- /dev/null
+++ b/rvbap.c
@@ -0,0 +1,935 @@
+/* rvbap.c vers 1.1
+
+written by Ville Pulkki 1999-2003
+Helsinki University of Technology
+and
+Unversity of California at Berkeley
+and written by Olaf Matthes 2003, 2007
+Pd port by Frank Barknecht
+
+See copyright in file with name COPYRIGHT */
+
+
+#include <math.h>
+
+#ifdef MAXMSP
+#include "ext.h" /* you must include this - it contains the external object's link to max */
+#endif
+
+#ifdef PD
+#include "m_pd.h" /* you must include this - it contains the external object's link to pure data */
+#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 _WINDOWS
+#define sqrtf sqrt
+#endif
+
+#ifdef MAXMSP
+typedef struct vbap /* This defines the object as an entity made up of other things */
+{
+ t_object x_ob;
+ long x_azi; // panning direction azimuth
+ long x_ele; // panning direction elevation
+ float x_dist; // sound source distance (1.0-infinity)
+ void *x_outlet0; /* outlet creation - inlets are automatic */
+ void *x_outlet1;
+ void *x_outlet2;
+ void *x_outlet3;
+ void *x_outlet4;
+ float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set
+ 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_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_dimension; // 2 or 3
+ long x_spread; // speading amount of virtual source (0-100)
+ float x_spread_base[3]; // used to create uniform spreading
+ float x_reverb_gs[MAX_LS_SETS]; // correction value for each loudspeaker set to get equal volume
+} t_rvbap;
+#endif
+
+
+#ifdef PD
+typedef struct vbap /* This defines the object as an entity made up of other things */
+{
+ t_object x_ob;
+ t_float x_azi; // panning direction azimuth
+ t_float x_ele; // panning direction elevation
+ t_float x_dist; // sound source distance (1.0-infinity)
+ void *x_outlet0; /* outlet creation - inlets are automatic */
+ void *x_outlet1;
+ void *x_outlet2;
+ void *x_outlet3;
+ void *x_outlet4;
+ 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_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_dimension; // 2 or 3
+ t_float x_spread; // speading amount of virtual source (0-100)
+ float x_spread_base[3]; // used to create uniform spreading
+ float x_reverb_gs[MAX_LS_SETS]; // correction value for each loudspeaker set to get equal volume
+} t_rvbap;
+#endif
+
+// Globals
+
+static void new_spread_dir(t_rvbap *x, float spreaddir[3], float vscartdir[3], float spread_base[3]);
+static void new_spread_base(t_rvbap *x, float spreaddir[3], float vscartdir[3]);
+#ifdef MAXMSP
+static void *rvbap_class;
+static void rvbap_assist(t_rvbap *x, void *b, long m, long a, char *s);
+static void rvbap_in1(t_rvbap *x, long n);
+static void rvbap_in2(t_rvbap *x, long n);
+static void rvbap_in3(t_rvbap *x, long n);
+static void rvbap_in4(t_rvbap *x, long n);
+static void rvbap_ft1(t_rvbap *x, double n);
+static void rvbap_ft2(t_rvbap *x, double n);
+static void rvbap_ft3(t_rvbap *x, double n);
+static void rvbap_ft4(t_rvbap *x, double n);
+#endif
+#ifdef PD
+static t_class *rvbap_class;
+#endif
+static void cross_prod(float v1[3], float v2[3],
+ float v3[3]);
+static void additive_vbap(float *final_gs, float cartdir[3], t_rvbap *x);
+static void rvbap_bang(t_rvbap *x);
+static void rvbap_matrix(t_rvbap *x, t_symbol *s, int ac, t_atom *av);
+static void spread_it(t_rvbap *x, float *final_gs);
+static void *rvbap_new(t_symbol *s, int ac, t_atom *av); // using A_GIMME - typed message list
+static void vbap(float g[3], long ls[3], t_rvbap *x);
+static void angle_to_cart(long azi, long ele, float res[3]);
+static void cart_to_angle(float cvec[3], float avec[3]);
+static void equal_reverb(t_rvbap *x, float *final_gs);
+
+/* above are the prototypes for the methods/procedures/functions you will use */
+
+#ifdef PD
+void rvbap_setup(void)
+{
+ rvbap_class = class_new(gensym("rvbap"), (t_newmethod)rvbap_new, 0, (short)sizeof(t_rvbap), 0, A_GIMME, 0);
+ /* rvbap_new = creation function, A_DEFLONG = its (optional) arguement is a long (32-bit) int */
+ class_addbang(rvbap_class, rvbap_bang);
+ class_addmethod(rvbap_class, (t_method)rvbap_matrix, gensym("loudspeaker-matrices"), A_GIMME, 0);
+}
+#endif
+
+#ifdef MAXMSP
+int main(void)
+{
+ setup((t_messlist **)&rvbap_class, (method)rvbap_new, 0L, (short)sizeof(t_rvbap), 0L, A_GIMME, 0);
+ /* rvbap_new = creation function, A_DEFLONG = its (optional) arguement is a long (32-bit) int */
+ addmess((method)rvbap_assist, "assist", A_CANT, 0);
+ addbang((method)rvbap_bang); /* the procedure it uses when it gets a bang in the left inlet */
+ addinx((method)rvbap_in1, 1); /* the rocedure for an int in the right inlet (inlet 1) */
+ addinx((method)rvbap_in2, 2); /* the rocedure for an int in the right inlet (inlet 2) */
+ addinx((method)rvbap_in3, 3);
+ addinx((method)rvbap_in4, 4);
+ addftx((method)rvbap_ft1, 1); /* the rocedure for an int in the right inlet (inlet 1) */
+ addftx((method)rvbap_ft2, 2); /* the rocedure for an int in the right inlet (inlet 2) */
+ addftx((method)rvbap_ft3, 3);
+ addftx((method)rvbap_ft4, 4);
+ addmess((method)rvbap_matrix, "loudspeaker-matrices", A_GIMME, 0);
+ post("rvbap v1.1, © 2003-2007 by Olaf Matthes, based on vbap by Ville Pulkki");
+ return 0;
+}
+
+static void rvbap_assist(t_rvbap *x, void *b, long m, long a, char *s)
+{
+ switch(m) {
+ case 1: // inlet
+ switch(a) {
+ case 0:
+ sprintf(s, "define_loudspeakers / Bang to output actual values.");
+ break;
+ case 1:
+ sprintf(s, "(int) azimuth");
+ break;
+ case 2:
+ sprintf(s, "(int) elevation");
+ break;
+ case 3:
+ sprintf(s, "(int) spreading");
+ break;
+ case 4:
+ sprintf(s, "(float) distance");
+ break;
+ }
+ break;
+ case 2: // outlet
+ switch(a) {
+ case 0:
+ sprintf(s, "(list) matrix~ values");
+ break;
+ case 1:
+ sprintf(s, "(int) actual azimuth");
+ break;
+ case 2:
+ sprintf(s, "(int) actual elevation");
+ break;
+ case 3:
+ sprintf(s, "(int) actual spreading");
+ break;
+ case 4:
+ sprintf(s, "(float) actual distance");
+ break;
+ }
+ break;
+ }
+}
+#endif
+/* end MAXMSP */
+
+static void angle_to_cart(long azi, long ele, float res[3])
+/* converts angular coordinates to cartesian */
+{
+ float atorad = (2.0 * 3.1415927 / 360.0) ;
+ res[0] = cos((float) azi * atorad) * cos((float) ele * atorad);
+ res[1] = sin((float) azi * atorad) * cos((float) ele * atorad);
+ res[2] = sin((float) ele * atorad);
+}
+
+static void cart_to_angle(float cvec[3], float avec[3])
+// converts cartesian coordinates to angular
+{
+ float tmp, tmp2, tmp3, tmp4;
+ float atorad = (float)(2.0 * 3.1415927 / 360.0) ;
+ float pi = (float)3.1415927;
+ float power;
+ float dist, atan_y_per_x, atan_x_pl_y_per_z;
+ float azi, ele;
+
+ if(cvec[0]==0.0)
+ atan_y_per_x = pi / 2;
+ else
+ atan_y_per_x = atan(cvec[1] / cvec[0]);
+ azi = atan_y_per_x / atorad;
+ if(cvec[0]<0.0)
+ azi +=180;
+ dist = sqrt(cvec[0]*cvec[0] + cvec[1]*cvec[1]);
+ if(cvec[2]==0.0)
+ atan_x_pl_y_per_z = 0.0;
+ else
+ atan_x_pl_y_per_z = atan(cvec[2] / dist);
+ if(dist == 0.0)
+ if(cvec[2]<0.0)
+ atan_x_pl_y_per_z = -pi/2.0;
+ else
+ atan_x_pl_y_per_z = pi/2.0;
+ ele = atan_x_pl_y_per_z / atorad;
+ dist = sqrtf(cvec[0] * cvec[0] +cvec[1] * cvec[1] +cvec[2]*cvec[2]);
+ avec[0]=azi;
+ avec[1]=ele;
+ avec[2]=dist;
+}
+
+
+static void vbap(float g[3], long ls[3], t_rvbap *x)
+{
+ /* calculates gain factors using loudspeaker setup and given direction */
+ float power;
+ int i,j,k, gains_modified;
+ float small_g;
+ float big_sm_g, gtmp[3];
+ long winner_set=0;
+ float cartdir[3];
+ float new_cartdir[3];
+ float new_angle_dir[3];
+ long dim = x->x_dimension;
+ long neg_g_am, best_neg_g_am;
+
+ // transfering the azimuth angle to a decent value
+ while(x->x_azi > 180)
+ x->x_azi -= 360;
+ while(x->x_azi < -179)
+ x->x_azi += 360;
+
+ // transferring the elevation to a decent value
+ if(dim == 3){
+ while(x->x_ele > 180)
+ x->x_ele -= 360;
+ while(x->x_ele < -179)
+ x->x_ele += 360;
+ } else
+ x->x_ele = 0;
+
+
+ // go through all defined loudspeaker sets and find the set which
+ // has all positive values. If such is not found, set with largest
+ // minimum value is chosen. If at least one of gain factors of one LS set is negative
+ // it means that the virtual source does not lie in that LS set.
+
+ angle_to_cart(x->x_azi,x->x_ele,cartdir);
+ big_sm_g = -100000.0; // initial value for largest minimum gain value
+ best_neg_g_am=3; // how many negative values in this set
+
+
+ for(i=0;i<x->x_lsset_amount;i++){
+ small_g = 10000000.0;
+ neg_g_am = 3;
+ for(j=0;j<dim;j++){
+ gtmp[j]=0.0;
+ for(k=0;k<dim;k++)
+ gtmp[j]+=cartdir[k]* x->x_set_inv_matx[i][k+j*dim];
+ if(gtmp[j] < small_g)
+ small_g = gtmp[j];
+ if(gtmp[j]>= -0.01)
+ neg_g_am--;
+ }
+ if(small_g > big_sm_g && neg_g_am <= best_neg_g_am){
+ big_sm_g = small_g;
+ best_neg_g_am = neg_g_am;
+ winner_set=i;
+ g[0]=gtmp[0]; g[1]=gtmp[1];
+ ls[0]= x->x_lsset[i][0]; ls[1]= x->x_lsset[i][1];
+ if(dim==3){
+ g[2]=gtmp[2];
+ ls[2]= x->x_lsset[i][2];
+ } else {
+ g[2]=0.0;
+ ls[2]=0;
+ }
+ }
+ }
+
+ // If chosen set produced a negative value, make it zero and
+ // calculate direction that corresponds to these new
+ // gain values. This happens when the virtual source is outside of
+ // all loudspeaker sets.
+
+ if(dim==3){
+ gains_modified=0;
+ for(i=0;i<dim;i++)
+ if(g[i]<-0.01){
+ g[i]=0.0001;
+ gains_modified=1;
+ }
+ if(gains_modified==1){
+ new_cartdir[0] = x->x_set_matx[winner_set][0] * g[0]
+ + x->x_set_matx[winner_set][1] * g[1]
+ + x->x_set_matx[winner_set][2] * g[2];
+ new_cartdir[1] = x->x_set_matx[winner_set][3] * g[0]
+ + x->x_set_matx[winner_set][4] * g[1]
+ + x->x_set_matx[winner_set][5] * g[2];
+ new_cartdir[2] = x->x_set_matx[winner_set][6] * g[0]
+ + x->x_set_matx[winner_set][7] * g[1]
+ + x->x_set_matx[winner_set][8] * g[2];
+ cart_to_angle(new_cartdir,new_angle_dir);
+ x->x_azi = (long) (new_angle_dir[0] + 0.5);
+ x->x_ele = (long) (new_angle_dir[1] + 0.5);
+ }
+ }
+
+ power=sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]);
+ g[0] /= power;
+ g[1] /= power;
+ g[2] /= power;
+}
+
+
+static void cross_prod(float v1[3], float v2[3],
+ float v3[3])
+// vector cross product
+{
+ float length;
+ v3[0] = (v1[1] * v2[2] ) - (v1[2] * v2[1]);
+ v3[1] = (v1[2] * v2[0] ) - (v1[0] * v2[2]);
+ v3[2] = (v1[0] * v2[1] ) - (v1[1] * v2[0]);
+
+ length= sqrt(v3[0]*v3[0] + v3[1]*v3[1] + v3[2]*v3[2]);
+ v3[0] /= length;
+ v3[1] /= length;
+ v3[2] /= length;
+}
+
+static void additive_vbap(float *final_gs, float cartdir[3], t_rvbap *x)
+// calculates gains to be added to previous gains, used in
+// multiple direction panning (source spreading)
+{
+ float power;
+ int i,j,k, gains_modified;
+ float small_g;
+ float big_sm_g, gtmp[3];
+ long winner_set;
+ float new_cartdir[3];
+ float new_angle_dir[3];
+ long dim = x->x_dimension;
+ long neg_g_am, best_neg_g_am;
+ float g[3];
+ long ls[3] = { 0, 0, 0 };
+
+ big_sm_g = -100000.0;
+ best_neg_g_am=3;
+
+ for(i=0;i<x->x_lsset_amount;i++){
+ small_g = 10000000.0;
+ neg_g_am = 3;
+ for(j=0;j<dim;j++){
+ gtmp[j]=0.0;
+ for(k=0;k<dim;k++)
+ gtmp[j]+=cartdir[k]* x->x_set_inv_matx[i][k+j*dim];
+ if(gtmp[j] < small_g)
+ small_g = gtmp[j];
+ if(gtmp[j]>= -0.01)
+ neg_g_am--;
+ }
+ if(small_g > big_sm_g && neg_g_am <= best_neg_g_am){
+ big_sm_g = small_g;
+ best_neg_g_am = neg_g_am;
+ winner_set=i;
+ g[0]=gtmp[0]; g[1]=gtmp[1];
+ ls[0]= x->x_lsset[i][0]; ls[1]= x->x_lsset[i][1];
+ if(dim==3){
+ g[2]=gtmp[2];
+ ls[2]= x->x_lsset[i][2];
+ } else {
+ g[2]=0.0;
+ ls[2]=0;
+ }
+ }
+ }
+
+ gains_modified=0;
+ for(i=0;i<dim;i++)
+ if(g[i]<-0.01){
+ gains_modified=1;
+ }
+
+ if(gains_modified != 1){
+ if(dim==3)
+ power=sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]);
+ else
+ power=sqrt(g[0]*g[0] + g[1]*g[1]);
+ g[0] /= power;
+ g[1] /= power;
+ if(dim==3)
+ g[2] /= power;
+
+ final_gs[ls[0]-1] += g[0];
+ final_gs[ls[1]-1] += g[1];
+ /* BUG FIX: this was causing negative indices with 2 dimensions so I
+ * made it only try when using 3 dimensions.
+ * 2006-08-13 <hans@at.or.at> */
+ if(dim==3)
+ final_gs[ls[2]-1] += g[2];
+ }
+}
+
+
+static void new_spread_dir(t_rvbap *x, float spreaddir[3], float vscartdir[3], float spread_base[3])
+// subroutine for spreading
+{
+ float beta,m_gamma;
+ float a,b;
+ float pi = 3.1415927;
+ float power;
+
+ m_gamma = acos(vscartdir[0] * spread_base[0] +
+ vscartdir[1] * spread_base[1] +
+ vscartdir[2] * spread_base[2])/pi*180;
+ if(fabs(m_gamma) < 1){
+ angle_to_cart(x->x_azi+90, 0, spread_base);
+ m_gamma = acos(vscartdir[0] * spread_base[0] +
+ vscartdir[1] * spread_base[1] +
+ vscartdir[2] * spread_base[2])/pi*180;
+ }
+ beta = 180 - m_gamma;
+ b=sin(x->x_spread * pi / 180) / sin(beta * pi / 180);
+ a=sin((180- x->x_spread - beta) * pi / 180) / sin (beta * pi / 180);
+ spreaddir[0] = a * vscartdir[0] + b * spread_base[0];
+ spreaddir[1] = a * vscartdir[1] + b * spread_base[1];
+ spreaddir[2] = a * vscartdir[2] + b * spread_base[2];
+
+ power=sqrt(spreaddir[0]*spreaddir[0] + spreaddir[1]*spreaddir[1]
+ + spreaddir[2]*spreaddir[2]);
+ spreaddir[0] /= power;
+ spreaddir[1] /= power;
+ spreaddir[2] /= power;
+}
+
+static void new_spread_base(t_rvbap *x, float spreaddir[3], float vscartdir[3])
+// subroutine for spreading
+{
+ float d;
+ float pi = 3.1415927;
+ float power;
+
+ d = cos(x->x_spread/180*pi);
+ x->x_spread_base[0] = spreaddir[0] - d * vscartdir[0];
+ x->x_spread_base[1] = spreaddir[1] - d * vscartdir[1];
+ x->x_spread_base[2] = spreaddir[2] - d * vscartdir[2];
+ power=sqrt(x->x_spread_base[0]*x->x_spread_base[0] + x->x_spread_base[1]*x->x_spread_base[1]
+ + x->x_spread_base[2]*x->x_spread_base[2]);
+ x->x_spread_base[0] /= power;
+ x->x_spread_base[1] /= power;
+ x->x_spread_base[2] /= power;
+}
+
+static void spread_it(t_rvbap *x, float *final_gs)
+// apply the sound signal to multiple panning directions
+// that causes some spreading.
+// See theory in paper V. Pulkki "Uniform spreading of amplitude panned
+// virtual sources" in WASPAA 99
+
+{
+ float vscartdir[3];
+ float spreaddir[16][3];
+ float spreadbase[16][3];
+ long i, spreaddirnum;
+ float power;
+ if(x->x_dimension == 3){
+ spreaddirnum=16;
+ angle_to_cart(x->x_azi,x->x_ele,vscartdir);
+ new_spread_dir(x, spreaddir[0], vscartdir, x->x_spread_base);
+ new_spread_base(x, spreaddir[0], vscartdir);
+ cross_prod(x->x_spread_base, vscartdir, spreadbase[1]); // four orthogonal dirs
+ cross_prod(spreadbase[1], vscartdir, spreadbase[2]);
+ cross_prod(spreadbase[2], vscartdir, spreadbase[3]);
+
+ // four between them
+ for(i=0;i<3;i++) spreadbase[4][i] = (x->x_spread_base[i] + spreadbase[1][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[5][i] = (spreadbase[1][i] + spreadbase[2][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[6][i] = (spreadbase[2][i] + spreadbase[3][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[7][i] = (spreadbase[3][i] + x->x_spread_base[i]) / 2.0;
+
+ // four at half spreadangle
+ for(i=0;i<3;i++) spreadbase[8][i] = (vscartdir[i] + x->x_spread_base[i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[9][i] = (vscartdir[i] + spreadbase[1][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[10][i] = (vscartdir[i] + spreadbase[2][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[11][i] = (vscartdir[i] + spreadbase[3][i]) / 2.0;
+
+ // four at quarter spreadangle
+ for(i=0;i<3;i++) spreadbase[12][i] = (vscartdir[i] + spreadbase[8][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[13][i] = (vscartdir[i] + spreadbase[9][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[14][i] = (vscartdir[i] + spreadbase[10][i]) / 2.0;
+ for(i=0;i<3;i++) spreadbase[15][i] = (vscartdir[i] + spreadbase[11][i]) / 2.0;
+
+ additive_vbap(final_gs,spreaddir[0],x);
+ for(i=1;i<spreaddirnum;i++){
+ new_spread_dir(x, spreaddir[i], vscartdir, spreadbase[i]);
+ additive_vbap(final_gs,spreaddir[i],x);
+ }
+ } else if (x->x_dimension == 2) {
+ spreaddirnum=6;
+
+ angle_to_cart(x->x_azi - x->x_spread, 0, spreaddir[0]);
+ angle_to_cart(x->x_azi - x->x_spread/2, 0, spreaddir[1]);
+ angle_to_cart(x->x_azi - x->x_spread/4, 0, spreaddir[2]);
+ angle_to_cart(x->x_azi + x->x_spread/4, 0, spreaddir[3]);
+ angle_to_cart(x->x_azi + x->x_spread/2, 0, spreaddir[4]);
+ angle_to_cart(x->x_azi + x->x_spread, 0, spreaddir[5]);
+
+ for(i=0;i<spreaddirnum;i++)
+ additive_vbap(final_gs,spreaddir[i],x);
+ } else
+ return;
+
+ if(x->x_spread > 70)
+ for(i=0;i<x->x_ls_amount;i++){
+ final_gs[i] += (x->x_spread - 70) / 30.0 * (x->x_spread - 70) / 30.0 * 10.0;
+ }
+
+ for(i=0,power=0.0;i<x->x_ls_amount;i++){
+ power += final_gs[i] * final_gs[i];
+ }
+
+ power = sqrt(power);
+ for(i=0;i<x->x_ls_amount;i++){
+ final_gs[i] /= power;
+ }
+}
+
+
+static void equal_reverb(t_rvbap *x, float *final_gs)
+// calculate constant reverb gains for equally distributed
+// reverb levels
+// this is achieved by calculating gains for a sound source
+// that is everywhere, i.e. present in all directions
+
+{
+ float vscartdir[3];
+ float spreaddir[16][3];
+ float spreadbase[16][3];
+ long i, spreaddirnum;
+ float power;
+ if(x->x_dimension == 3){
+ spreaddirnum=5;
+
+ // horizontal plane
+ angle_to_cart(90, 0, spreaddir[0]);
+ angle_to_cart(180, 0, spreaddir[1]);
+ angle_to_cart(270, 0, spreaddir[2]);
+
+ // above, below
+ angle_to_cart(0, 90, spreaddir[3]);
+ angle_to_cart(0, -90, spreaddir[4]);
+
+ for(i=1;i<spreaddirnum;i++){
+ additive_vbap(x->x_reverb_gs,spreaddir[i],x);
+ }
+ } else if (x->x_dimension == 2) {
+ // for 2-D we claculate virtual sources
+ // every 45 degrees in a horizontal plane
+ spreaddirnum=7;
+
+ angle_to_cart(90, 0, spreaddir[0]);
+ angle_to_cart(180, 0, spreaddir[1]);
+ angle_to_cart(270, 0, spreaddir[2]);
+ angle_to_cart(45, 0, spreaddir[3]);
+ angle_to_cart(135, 0, spreaddir[4]);
+ angle_to_cart(225, 0, spreaddir[5]);
+ angle_to_cart(315, 0, spreaddir[6]);
+
+ for(i=0;i<spreaddirnum;i++)
+ additive_vbap(x->x_reverb_gs,spreaddir[i],x);
+ } else
+ return;
+
+ for(i=0,power=0.0;i<x->x_ls_amount;i++){
+ power += x->x_reverb_gs[i] * x->x_reverb_gs[i];
+ }
+
+ power = sqrt(power);
+ for(i=0;i<x->x_ls_amount;i++){
+ final_gs[i] /= power;
+ }
+}
+
+static void rvbap_bang(t_rvbap *x)
+// top level, vbap gains are calculated and outputted
+{
+ t_atom at[MAX_LS_AMOUNT];
+ float g[3];
+ long ls[3];
+ long i;
+ float *final_gs, overdist, oversqrtdist;
+ final_gs = (float *) getbytes(x->x_ls_amount * sizeof(float));
+ if(x->x_lsset_available ==1){
+ vbap(g, ls, x);
+ for(i=0;i<x->x_ls_amount;i++)
+ final_gs[i]=0.0;
+ for(i=0;i<x->x_dimension;i++){
+ final_gs[ls[i]-1]=g[i];
+ }
+ if(x->x_spread != 0){
+ spread_it(x,final_gs);
+ }
+ overdist = 1 / x->x_dist;
+ oversqrtdist = 1 / sqrt(x->x_dist);
+ // build output for every loudspeaker
+ for(i=0;i<x->x_ls_amount;i++)
+ {
+ // first, we output the gains for the direct (unreverberated) signals
+ // these just decrease as the distance increases
+#ifdef MAXMSP
+ SETLONG(&at[0], i);
+ SETFLOAT(&at[1], (final_gs[i] / x->x_dist));
+ outlet_list(x->x_outlet0, NULL, 2, at);
+#endif
+#ifdef PD
+ SETFLOAT(&at[0], i);
+ SETFLOAT(&at[1], (final_gs[i] / x->x_dist));
+ outlet_list(x->x_outlet0, gensym("list"), 2, at);
+#endif
+ // second, we output the gains for the reverberated signals
+ // these are made up of a global (all speakers) and a local part
+#ifdef MAXMSP
+ SETLONG(&at[0], i+x->x_ls_amount); // direct signals come first in matrix~
+ SETFLOAT(&at[1], (((oversqrtdist / x->x_dist) * x->x_reverb_gs[i]) + (oversqrtdist * (1 - overdist) * final_gs[i])));
+ outlet_list(x->x_outlet0, NULL, 2, at);
+#endif
+#ifdef PD
+ SETFLOAT(&at[0], (i+x->x_ls_amount)); // direct signals come first in matrix~
+ SETFLOAT(&at[1], (((oversqrtdist / x->x_dist) * x->x_reverb_gs[i]) + (oversqrtdist * (1 - overdist) * final_gs[i])));
+ outlet_list(x->x_outlet0, gensym("list"), 2, at);
+#endif
+ }
+#ifdef MAXMSP
+ outlet_int(x->x_outlet1, x->x_azi);
+ outlet_int(x->x_outlet2, x->x_ele);
+ outlet_int(x->x_outlet3, x->x_spread);
+ outlet_float(x->x_outlet4, (double)x->x_dist);
+#endif
+#ifdef PD
+ outlet_float(x->x_outlet1, x->x_azi);
+ outlet_float(x->x_outlet2, x->x_ele);
+ outlet_float(x->x_outlet3, x->x_spread);
+ outlet_float(x->x_outlet4, x->x_dist);
+#endif
+ }
+ else
+ post("rvbap: Configure loudspeakers first!");
+ freebytes(final_gs, x->x_ls_amount * sizeof(float)); // bug fix added 9/00
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void rvbap_matrix(t_rvbap *x, t_symbol *s, int ac, t_atom *av)
+// read in loudspeaker matrices
+// and calculate the gains for the equally distributed
+// reverb signal part (i.e. global reverb)
+{
+ long counter=0;
+ long datapointer=0;
+ long setpointer=0;
+ long i;
+ long deb=0;
+ long azi = x->x_azi, ele = x->x_ele; // store original values
+ float g[3];
+ long ls[3];
+
+ if(ac>0)
+#ifdef MAXMSP
+ if(av[datapointer].a_type == A_LONG){
+ x->x_dimension = av[datapointer++].a_w.w_long;
+ x->x_lsset_available=1;
+ } else
+#endif
+ if(av[datapointer].a_type == A_FLOAT){
+ x->x_dimension = (long) av[datapointer++].a_w.w_float;
+ x->x_lsset_available=1;
+ } else {
+ post("Error in loudspeaker data!");
+ x->x_lsset_available=0;
+ return;
+ }
+ //post("%d",deb++);
+ if(ac>1)
+#ifdef MAXMSP
+ if(av[datapointer].a_type == A_LONG)
+ x->x_ls_amount = av[datapointer++].a_w.w_long;
+ else
+#endif
+ if(av[datapointer].a_type == A_FLOAT)
+ x->x_ls_amount = (long) av[datapointer++].a_w.w_float;
+ else {
+ post("rvbap: Error in loudspeaker data!");
+ x->x_lsset_available=0;
+ return;
+ }
+ else
+ x->x_lsset_available=0;
+
+ if(x->x_dimension == 3)
+ counter = (ac - 2) / ((x->x_dimension * x->x_dimension*2) + x->x_dimension);
+ if(x->x_dimension == 2)
+ counter = (ac - 2) / ((x->x_dimension * x->x_dimension) + x->x_dimension);
+ x->x_lsset_amount=counter;
+
+ if(counter<=0) {
+ post("rvbap: Error in loudspeaker data!");
+ x->x_lsset_available=0;
+ return;
+ }
+
+
+ while(counter-- > 0){
+ for(i=0; i < x->x_dimension; i++){
+#ifdef MAXMSP
+ if(av[datapointer].a_type == A_LONG)
+#endif
+#ifdef PD
+ if(av[datapointer].a_type == A_FLOAT)
+#endif
+ {
+ x->x_lsset[setpointer][i]=(long)av[datapointer++].a_w.w_float;
+ }
+ else{
+ post("rvbap: Error in loudspeaker data!");
+ 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_inv_matx[setpointer][i]=av[datapointer++].a_w.w_float;
+ }
+ else {
+ post("rvbap: Error in loudspeaker data!");
+ x->x_lsset_available=0;
+ return;
+ }
+ }
+ if(x->x_dimension == 3){
+ 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 {
+ post("rvbap: Error in loudspeaker data!");
+ x->x_lsset_available=0;
+ return;
+ }
+ }
+ }
+
+ setpointer++;
+ }
+ // now configure static reverb correction values...
+ x->x_azi = x->x_ele = 0;
+ vbap(g,ls, x);
+ for(i=0;i<x->x_ls_amount;i++){
+ x->x_reverb_gs[i]=0.0;
+ }
+ for(i=0;i<x->x_dimension;i++){
+ x->x_reverb_gs[ls[i]-1]=g[i];
+ // post("reverb gs #%d = %f", i, x->x_reverb_gs[i]);
+ }
+ equal_reverb(x,x->x_reverb_gs);
+
+/* for(i=0; i<x->x_ls_amount; i++) // do this for every speaker
+ {
+ post("reverb gs #%d = %f", i, x->x_reverb_gs[i]);
+ } */
+ post("rvbap: Loudspeaker setup configured!");
+ x->x_azi = azi; // restore original panning directions
+ x->x_ele = ele;
+}
+
+#ifdef MAXMSP
+static void rvbap_in1(t_rvbap *x, long n) /* x = the instance of the object, n = the int received in the right inlet */
+// panning angle azimuth
+{
+ x->x_azi = n; /* store n in a global variable */
+
+}
+
+static void rvbap_in2(t_rvbap *x, long n) /* x = the instance of the object, n = the int received in the right inlet */
+// panning angle elevation
+{
+ x->x_ele = n; /* store n in a global variable */
+
+}
+/*--------------------------------------------------------------------------*/
+
+static void rvbap_in3(t_rvbap *x, long n) /* x = the instance of the object, n = the int received in the right inlet */
+// spread amount
+{
+ if (n<0) n = 0;
+ if (n>100) n = 100;
+ x->x_spread = n; /* store n in a global variable */
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void rvbap_in4(t_rvbap *x, long n) /* x = the instance of the object, n = the int received in the right inlet */
+// distance
+{
+ if (n<1) n = 1;
+ x->x_dist = (float)n; /* store n in a global variable */
+
+}
+
+static void rvbap_ft1(t_rvbap *x, double n) /* x = the instance of the object, n = the int received in the right inlet */
+// panning angle azimuth
+{
+ x->x_azi = (long) n; /* store n in a global variable */
+
+}
+
+static void rvbap_ft2(t_rvbap *x, double n) /* x = the instance of the object, n = the int received in the right inlet */
+// panning angle elevation
+{
+ x->x_ele = (long) n; /* store n in a global variable */
+
+}
+/*--------------------------------------------------------------------------*/
+
+static void rvbap_ft3(t_rvbap *x, double n) /* x = the instance of the object, n = the int received in the right inlet */
+// spreading
+{
+ if (n<0.0) n = 0.0;
+ if (n>100.0) n = 100.0;
+ x->x_spread = (long) n; /* store n in a global variable */
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void rvbap_ft4(t_rvbap *x, double n) /* x = the instance of the object, n = the int received in the right inlet */
+// distance
+{
+ if (n<1.0) n = 1.0;
+ x->x_dist = (float)n; /* store n in a global variable */
+}
+
+
+#endif
+
+static void *rvbap_new(t_symbol *s, int ac, t_atom *av)
+/* create new instance of object... MUST send it an int even if you do nothing with this int!! */
+{
+ t_rvbap *x;
+#ifdef MAXMSP
+ x = (t_rvbap *)newobject(rvbap_class);
+
+ floatin(x,4); /* takes the distance */
+ intin(x,3);
+ intin(x,2); /* create a second (int) inlet... remember right-to-left ordering in Max */
+ intin(x,1); /* create a second (int) inlet... remember right-to-left ordering in Max */
+ x->x_outlet4 = floatout(x); /* distance */
+ x->x_outlet3 = intout(x);
+ x->x_outlet2 = intout(x); /* create an (int) outlet - rightmost outlet first... */
+ x->x_outlet1 = intout(x); /* create an (int) outlet */
+ x->x_outlet0 = listout(x); /* create a (list) outlet */
+#endif
+#ifdef PD
+ x = (t_rvbap *)pd_new(rvbap_class);
+ floatinlet_new(&x->x_ob, &x->x_azi);
+ floatinlet_new(&x->x_ob, &x->x_ele);
+ floatinlet_new(&x->x_ob, &x->x_spread);
+ floatinlet_new(&x->x_ob, &x->x_dist);
+
+ x->x_outlet0 = outlet_new(&x->x_ob, gensym("list"));
+ x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));
+ x->x_outlet2 = outlet_new(&x->x_ob, gensym("float"));
+ x->x_outlet3 = outlet_new(&x->x_ob, gensym("float"));
+ x->x_outlet4 = outlet_new(&x->x_ob, gensym("float"));
+#endif
+
+ x->x_azi = 0;
+ x->x_ele = 0;
+ x->x_dist = 1.0;
+ x->x_spread_base[0] = 0.0;
+ x->x_spread_base[1] = 1.0;
+ x->x_spread_base[2] = 0.0;
+ x->x_spread = 0;
+ x->x_lsset_available =0;
+ if (ac>0) {
+#ifdef MAXMSP
+ if (av[0].a_type == A_LONG)
+ x->x_azi = av[0].a_w.w_long;
+ else
+#endif
+ if (av[0].a_type == A_FLOAT)
+ x->x_azi = av[0].a_w.w_float;
+ }
+ if (ac>1) {
+#ifdef MAXMSP
+ if (av[1].a_type == A_LONG)
+ x->x_ele = av[1].a_w.w_long;
+ else
+#endif
+ if (av[1].a_type == A_FLOAT)
+ x->x_ele = av[1].a_w.w_float;
+ }
+ if (ac>2) {
+#ifdef MAXMSP
+ if (av[2].a_type == A_LONG)
+ x->x_dist = (float)av[2].a_w.w_long;
+ else
+#endif
+ if (av[2].a_type == A_FLOAT)
+ x->x_dist = av[2].a_w.w_float;
+ }
+ return(x); /* return a reference to the object instance */
+}
+