Update of /cvsroot/pure-data/externals/vbap
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20058
Added Files:
Tag: branch-v0-39-2-extended
rvbap-demo.pd rvbap-help.pd rvbap.c
Log Message:
backported Frank's port of rvbap to Pd-0.39.3-extended
--- NEW FILE: rvbap-demo.pd ---
#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;
--- NEW FILE: rvbap-help.pd ---
#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;
--- NEW FILE: rvbap.c ---
/* 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(a)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 */
}