vbap-1.0.3.2/0000755000076500007650000000000011772150730011264 5ustar hanshansvbap-1.0.3.2/LICENSE.txt0000644000076500007650000000316411643120401013100 0ustar hanshansCopyright (c) 1998-2010 Ville Pulkki 2002, Juha Vehvilinen 2003, Olaf Matthes 2006-2010, Hans-Christoph Steiner 2007, Frank Barknecht All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY VILLE PULKKI ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL VILLE PULKKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Ville Pulkki. vbap-1.0.3.2/Makefile0000644000076500007650000004005211661514775012737 0ustar hanshans## Pd library template version 1.0.12 # For instructions on how to use this template, see: # http://puredata.info/docs/developer/MakefileTemplate LIBRARY_NAME = vbap # add your .c source files, one object per file, to the SOURCES # variable, help files will be included automatically, and for GUI # objects, the matching .tcl file too SOURCES = vbap.c rvbap.c define_loudspeakers.c # list all pd objects (i.e. myobject.pd) files here, and their helpfiles will # be included automatically PDOBJECTS = # example patches and related files, in the 'examples' subfolder EXAMPLES = graph-to-aziele.pd high.pd playsample~.pd recent.pd vbap-demo.pd vbap-level-config.pd vbapmodule.pd vbapsnd.pd rvbap-demo.pd vbap.main.pd # manuals and related files, in the 'manual' subfolder MANUAL = # if you want to include any other files in the source and binary tarballs, # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included EXTRA_DIST = define_loudspeakers.h max2pd.h vbap.h makefile.irix so_locations # unit tests and related files here, in the 'unittests' subfolder UNITTESTS = define-loudspeaker-unittest.wav define_loudspeakers-unittest.pd rvbap-unittest.pd rvbap-unittest.wav vbap-unittest.pd vbap-unittest.wav vbap.wav #------------------------------------------------------------------------------# # # things you might need to edit if you are using other C libraries # #------------------------------------------------------------------------------# ALL_CFLAGS = -I"$(PD_INCLUDE)" ALL_LDFLAGS = SHARED_LDFLAGS = ALL_LIBS = #------------------------------------------------------------------------------# # # you shouldn't need to edit anything below here, if we did it right :) # #------------------------------------------------------------------------------# # these can be set from outside without (usually) breaking the build CFLAGS = -Wall -W -g LDFLAGS = LIBS = # get library version from meta file LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd) ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 644 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION) ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION) UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch SOURCES += $(SOURCES_iphoneos) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS) ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT) ALL_LIBS += -lc $(LIBS_iphoneos) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) else # Mac OS X SOURCES += $(SOURCES_macosx) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4 else FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 SOURCES += $(SOURCES_iphoneos) endif ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include # if the 'pd' binary exists, check the linking against it to aid with stripping BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) ALL_LDFLAGS += $(FAT_FLAGS) -bundle $(BUNDLE_LOADER) -undefined dynamic_lookup -L/sw/lib SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0 ALL_LIBS += -lc $(LIBS_macosx) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif # Tho Android uses Linux, we use this fake uname to provide an easy way to # setup all this things needed to cross-compile for Android using the NDK ifeq ($(UNAME),ANDROID) CPU := arm SOURCES += $(SOURCES_android) EXTENSION = pd_linux SHARED_EXTENSION = so OS = android PD_PATH = /usr NDK_BASE := /usr/local/android-ndk NDK_PLATFORM_VERSION := 5 NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]') NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86 CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT) OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -rdynamic -shared SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared LIBS += -lc $(LIBS_android) STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \ --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU) # GNU/Hurd, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU/kFreeBSD) # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll SHARED_EXTENSION = dll OS = cygwin PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc -lpd $(LIBS_cygwin) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_windows) EXTENSION = dll SHARED_EXTENSION = dll OS = windows PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd) # MinGW doesn't seem to include cc so force gcc CC=gcc OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -mms-bitfields ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" SHARED_LDFLAGS += -shared ALL_LIBS += -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS) ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS) ALL_LIBS := $(LIBS) $(ALL_LIBS) SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c) SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h) SHARED_LIB = $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) .PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" %.$(EXTENSION): %.o $(SHARED_LIB) $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB) chmod a-x "$*.$(EXTENSION)" # this links everything into a single binary file $(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(ALL_LIBS) chmod a-x $(LIBRARY_NAME).$(EXTENSION) $(SHARED_LIB): $(SHARED_SOURCE:.c=.o) $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(LIBS) install: libdir_install # The meta and help files are explicitly installed to make sure they are # actually there. Those files are not optional, then need to be there. libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES))" || (\ $(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION)))) test -z "$(strip $(SHARED_LIB))" || \ $(INSTALL_DATA) $(SHARED_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) # install library linked as single binary single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) install-doc: $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \ $(INSTALL_DATA) $(HELPPATCHES) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt install-examples: test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \ done install-manual: test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \ done install-unittests: test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ done clean: -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o) -rm -f -- $(SOURCES:.c=.$(EXTENSION)) -rm -f -- $(LIBRARY_NAME).o -rm -f -- $(LIBRARY_NAME).$(EXTENSION) -rm -f -- $(SHARED_LIB) distclean: clean -rm -f -- $(DISTBINDIR).tar.gz -rm -rf -- $(DISTBINDIR) -rm -f -- $(DISTDIR).tar.gz -rm -rf -- $(DISTDIR) -rm -f -- $(ORIGDIR).tar.gz -rm -rf -- $(ORIGDIR) $(DISTBINDIR): $(INSTALL_DIR) $(DISTBINDIR) libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) # tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR) $(DISTDIR): $(INSTALL_DIR) $(DISTDIR) $(ORIGDIR): $(INSTALL_DIR) $(ORIGDIR) dist: $(DISTDIR) $(INSTALL_DATA) Makefile $(DISTDIR) $(INSTALL_DATA) README.txt $(DISTDIR) $(INSTALL_DATA) LICENSE.txt $(DISTDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR) test -z "$(strip $(ALLSOURCES))" || \ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR) test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) test -z "$(strip $(SHARED_HEADER))" || \ $(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR) test -z "$(strip $(SHARED_SOURCE))" || \ $(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) $(DISTDIR) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR) test -z "$(strip $(HELPPATCHES))" || \ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR) test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DISTDIR)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \ done test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DISTDIR)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \ done test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DISTDIR)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ done tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR) # make a Debian source package dpkg-source: debclean make distclean dist mv $(DISTDIR) $(ORIGDIR) tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR) rm -f -- $(DISTDIR).tar.gz rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) etags: etags $(wildcard $(PD_INCLUDE)/*.h) etags -a *.h $(SOURCES) etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl showsetup: @echo "CC: $(CC)" @echo "CFLAGS: $(CFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)" @echo "ALL_CFLAGS: $(ALL_CFLAGS)" @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)" @echo "ALL_LIBS: $(ALL_LIBS)" @echo "PD_INCLUDE: $(PD_INCLUDE)" @echo "PD_PATH: $(PD_PATH)" @echo "objectsdir: $(objectsdir)" @echo "LIBRARY_NAME: $(LIBRARY_NAME)" @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)" @echo "SOURCES: $(SOURCES)" @echo "SHARED_HEADER: $(SHARED_HEADER)" @echo "SHARED_SOURCE: $(SHARED_SOURCE)" @echo "SHARED_LIB: $(SHARED_LIB)" @echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)" @echo "PDOBJECTS: $(PDOBJECTS)" @echo "ALLSOURCES: $(ALLSOURCES)" @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))" @echo "UNAME: $(UNAME)" @echo "CPU: $(CPU)" @echo "pkglibdir: $(pkglibdir)" @echo "DISTDIR: $(DISTDIR)" @echo "ORIGDIR: $(ORIGDIR)" vbap-1.0.3.2/README.txt0000644000076500007650000000350711472766367013007 0ustar hanshans A Pd port of the VBAP object for Max/MSP Written by Ville Pulkki Helsinki University of Technology Laboratory of acoustics and audio signal processing http://www.acoustics.hut.fi/research/cat/vbap/ This is a library for Pure Data for sound spatialization using the vector base amplitude panning (VBAP) method. VBAP is an amplitude panning method to position virtual sources in arbitrary 2-D or 3-D loudspeaker setups. In amplitude panning the same sound signal is applied to a number of loudspeakers with appropriate non-zero amplitudes. With 2-D setups VBAP is a reformulation of the existing pair-wise panning method. However, differing from earlier solutions it can be generalized for 3-D loudspeaker setups as a triplet-wise panning method. A sound signal is then applied to one, two, or three loudspeakers simultaneously. VBAP has certain advantages compared to earlier virtual source positioning methods in arbitrary layouts. Previous methods either used all loudspeakers to produce virtual sources, which results in some artefacts, or they used loudspeaker triplets with a non-generalizable 2-D user interface. The directional qualities of virtual sources generated with VBAP can be stated as follows. Directional coordinates used for this purpose are the angle between a position vector and the median plane (θcc), and the angle between a projection of a position vector to the median plane and frontal direction (Φcc). The perceived θcc direction of a virtual source coincides well with the VBAP panning direction when a loudspeaker set is near the median plane. When the loudspeaker set is moved towards a side of a listener, the perceived θcc direction is biased towards the median plane. The perceived Φcc direction of an amplitude-panned virtual source is individual and cannot be predicted with any panning law. vbap-1.0.3.2/define_loudspeakers-help.pd0000644000076500007650000000300311661514775016560 0ustar hanshans#N canvas 95 333 792 481 10; #X text 22 149 In two dimensions \, only specify the azimuth. (for example "define_loudspeakers 2 -45 45 0 180"; #X obj 48 228 define_loudspeakers 3 -45 0 45 0 0 45 180 45; #X msg 48 207 bang; #X obj 148 280 define_loudspeakers 2 -45 45 0 180; #X obj 112 322 vbap 0 0; #X text 23 19 [define_loudspeakers] works with; #X obj 255 19 vbap; #X text 18 50 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:; #X text 36 355 (see [vbap] for more details); #X msg 410 336 ls-directions 3 -30 0 30 0 -90 0 90 0 0 0 -150 0 150 0 180 45 -45 45 45 45; #X msg 399 273 ls-triplets 1 2 7 2 7 8 1 3 7; #X obj 399 418 define_loudspeakers 2 -40 0 40 80 130 180 -130 -80; #X text 395 228 If you are not happy with triangle selections of define_loudspeakers \, you can define your own. (for experts only); #X text 415 383 2-D setup -> only loudspeaker azimuths specified:; #X text 414 398 (2 azi1 azi2 azi3 azi4...); #X text 411 302 3-D setup -> (azimuth elevation) pairs are specified: ; #X text 411 317 (3 azi1 ele1 azi2 ele2 ...); #X msg 148 259 bang; #X text 190 259 a 2D setup; #X text 93 212 a 3D setup; #X connect 1 0 4 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 9 0 11 0; #X connect 10 0 11 0; #X connect 17 0 3 0; vbap-1.0.3.2/define_loudspeakers.c0000644000076500007650000005627311704111220015442 0ustar hanshans/* define_loudspeakers.c 1.00b1----> x-max4.2 written by Ville Pulkki 1999-2003 Helsinki University of Technology and Unversity of California at Berkeley See copyright in file with name LICENSE.txt */ #include "define_loudspeakers.h" #ifndef VBAP_OBJECT # ifdef PD // If we are within VBAP (which includes define_loudspeakers), then don't create a main for define_loudspeakres void define_loudspeakers_setup(void) { def_ls_class = class_new(gensym("define_loudspeakers"), (t_newmethod)def_ls_new, 0, (short)sizeof(t_def_ls), 0, A_GIMME, 0); /* def_ls_new = creation function, A_DEFLONG = its (optional) arguement is a long (32-bit) int */ class_addbang(def_ls_class, (t_method)def_ls_bang); /* the procedure it uses when it gets a bang in the left inlet */ class_addmethod(def_ls_class, (t_method)def_ls_read_directions, gensym("ls-directions"), A_GIMME, 0); class_addmethod(def_ls_class, (t_method)def_ls_read_triplets, gensym("ls-triplets"), A_GIMME, 0); post(DFLS_VERSION); } # else /* Max */ void main(void) { setup((t_messlist **)&def_ls_class, (method)def_ls_new, 0L, (short)sizeof(t_def_ls), 0L, A_GIMME, 0); /* def_ls_new = creation function, A_DEFLONG = its (optional) arguement is a long (32-bit) int */ addbang((method)def_ls_bang); /* the procedure it uses when it gets a bang in the left inlet */ addmess((method)def_ls_read_directions, "ls-directions", A_GIMME, 0); addmess((method)def_ls_read_triplets, "ls-triplets", A_GIMME, 0); addmess((method)traces, "enabletrace", A_LONG, 0); post(DFLS_VERSION); } # endif /* PD */ #endif /* ! VBAP_OBJECT */ static void def_ls_bang(t_def_ls *x) /* x = reference to this instance of the object */ { // calculate and print out chosen loudspeaker sets and corresponding matrices if(x->x_ls_read == 1) { if(x->x_def_ls_amount < x->x_def_ls_dimension) { error("define-loudspeakers: Too few loudspeakers!"); return; } else { if(x->x_def_ls_dimension == 3) { if(x->x_triplets_specified==0) choose_ls_triplets(x); calculate_3x3_matrixes(x); } else if(x->x_def_ls_dimension == 2) { choose_ls_tuplets(x); } else { error("define-loudspeakers: Error in loudspeaker direction data"); error("dimension azimuth1 [elevation1] azimuth2 [elevation2]..."); error("dimension == 2 for horizontal ls arrays"); error("dimension == 3 for 3-D ls arrays (speakers also upward and/or downward "); } } } else { error("define-loudspeakers: Error in loudspeaker direction data"); error("dimension azimuth1 [elevation1] azimuth2 [elevation2]..."); error("dimension == 2 for horizontal ls arrays"); error("dimension == 3 for 3-D ls arrays (speakers also upward and/or downward "); } } /*--------------------------------------------------------------------------*/ /* void def_ls_int(t_def_ls *x, long n) // x = the instance of the object, n = the int received in the right inlet { // do something if an int comes in the left inlet??? } */ static void def_ls_read_triplets(t_def_ls *x, t_symbol *s, int ac, Atom *av) // when loudspeaker triplets come in a message { t_ls_set *trip_ptr, *tmp_ptr, *prev; if(x->x_ls_read == 0) { error("define_loudspeakers: Define loudspeaker directions first!"); return; } if(x->x_def_ls_dimension == 2) { error("define_loudspeakers: Can't specify loudspeaker triplets in 2-D setup!"); return; } trip_ptr = x->x_ls_set; prev = NULL; while (trip_ptr != NULL) { tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } x->x_ls_set = NULL; int i; for(i=0;ix_triplets_specified=1; } static void def_ls_read_directions(t_def_ls *x, t_symbol *s, int ac, Atom *av) // when loudspeaker directions come in a message { if (x->x_ls_read) { // Remove old matrices t_ls_set* trip_ptr = x->x_ls_set; while (trip_ptr != NULL) { // remove old matrices t_ls_set* tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } } x->x_ls_set = NULL; initContent_ls_directions(x,ac,av); } /*--------------------------------------------------------------------------*/ static void ls_angles_to_cart(t_ls *ls) // convert angular direction to cartesian { t_float azi = ls->azi; t_float ele = ls->ele; ls->x = cos((t_float) azi * atorad) * cos((t_float) ele * atorad); ls->y = sin((t_float) azi * atorad) * cos((t_float) ele * atorad); ls->z = sin((t_float) ele * atorad); } /* create new instance of object... MUST send it an int even if you do nothing with this int!! */ static void *def_ls_new(t_symbol *s, int ac, Atom *av) { // s is object name (we ignore it) t_def_ls *x = (t_def_ls *)newobject(def_ls_class); #ifdef PD x->x_outlet0 = outlet_new(&x->x_obj, gensym("list")); /* create a (list) outlet */ #else /* Max */ x->x_outlet0 = outlet_new(x, 0L); /* create a (list) outlet */ #endif /* PD */ initContent_ls_directions(x,ac,av); // Initialize object internal data from a ls-directions list return x; /* return a reference to the object instance */ } /* define-loudspeakers message integrated into vbap object */ void vbap_def_ls(t_def_ls *x, t_symbol *s, int ac, Atom *av) { initContent_ls_directions(x,ac,av); // Initialize object internal data from a ls-directions list def_ls_bang(x); // calculate and send matrix to vbap } /** Initialize the object content from parameters : ls-directions list */ static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av) { x->x_ls_read = 0; long d = 0; /* if (av[0].a_type == A_LONG) d = av[0].a_w.w_long; else */ if(av[0].a_type == A_FLOAT) d = (long)av[0].a_w.w_float; else { error("define-loudspeakers: dimension NaN"); return; } if (d==2 || d==3) { x->x_def_ls_dimension= d; x->x_ls_read = 1; } else { x->x_def_ls_dimension= 0; error("define-loudspeakers: Dimension has to be 2 or 3!"); return; } int pointer = 1; x->x_def_ls_amount= (ac-1) / (x->x_def_ls_dimension - 1); // read loudspeaker direction angles int i; for(i=0; i < x->x_def_ls_amount;i++) { t_float azi = 0; /* if(av[pointer].a_type == A_LONG) azi = (float) av[pointer].a_w.w_long; else */ if(av[pointer].a_type == A_FLOAT) azi = av[pointer].a_w.w_float; else { error("define-loudspeakers: direction angle #%d NaN",i+1); x->x_ls_read = 0; return; } x->x_ls[i].azi = azi; pointer++; t_float ele = 0; // in 2d elevation is zero if(x->x_def_ls_dimension == 3) { // 3-D /* if(av[pointer].a_type == A_LONG) ele = (float) av[pointer].a_w.w_long; else */ if(av[pointer].a_type == A_FLOAT) ele = av[pointer].a_w.w_float; else { error("define-loudspeakers: elevation #%d NaN",i+1); x->x_ls_read = 0; return; } pointer++; } x->x_ls[i].ele = ele; } if(x->x_ls_read == 1) { int i; for(i=0;ix_def_ls_amount;i++) { ls_angles_to_cart(&x->x_ls[i]); } } x->x_triplets_specified=0; x->x_ls_set = NULL; } static void choose_ls_triplets(t_def_ls *x) /* Selects the loudspeaker triplets, and calculates the inversion matrices for each selected triplet. A line (connection) is drawn between each loudspeaker. The lines denote the sides of the triangles. The triangles should not be intersecting. All crossing connections are searched and the longer connection is erased. This yields non-intesecting triangles, which can be used in panning. See theory in paper Pulkki, V. Lokki, T. "Creating Auditory Displays with Multiple Loudspeakers Using VBAP: A Case Study with DIVA Project" in International Conference on Auditory Displays -98.*/ { int i,j,k,l,/*m,li,*/ table_size; //int *i_ptr; //t_ls vb1,vb2,tmp_vec; int connections[MAX_LS_AMOUNT][MAX_LS_AMOUNT]; //float angles[MAX_LS_AMOUNT]; //int sorted_angles[MAX_LS_AMOUNT]; t_float distance_table[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_i[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; int distance_table_j[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; t_float distance; t_ls_set *trip_ptr, *prev, *tmp_ptr; int ls_amount = x->x_def_ls_amount; t_ls *lss = x->x_ls; if (ls_amount == 0) { post("define-loudspeakers: Number of loudspeakers is zero"); return; } for(i=0;ix_ls) > MIN_VOL_P_SIDE_LGTH) { connections[i][j]=1; connections[j][i]=1; connections[i][k]=1; connections[k][i]=1; connections[j][k]=1; connections[k][j]=1; add_ldsp_triplet(i,j,k,x); } } /*calculate distancies between all lss and sorting them*/ table_size =(((ls_amount - 1) * (ls_amount)) / 2); for(i=0;i k ;l--) { distance_table[l] = distance_table[l-1]; distance_table_i[l] = distance_table_i[l-1]; distance_table_j[l] = distance_table_j[l-1]; } distance_table[k] = distance; distance_table_i[k] = i; distance_table_j[k] = j; } else { table_size--; } } } /* disconnecting connections which are crossing shorter ones, starting from shortest one and removing all that cross it, and proceeding to next shortest */ for(i=0; i<(table_size); i++) { int fst_ls = distance_table_i[i]; int sec_ls = distance_table_j[i]; if(connections[fst_ls][sec_ls] == 1) { for(j=0; jx_ls) == 1) { connections[j][k] = 0; connections[k][j] = 0; } } } } } } /* remove triangles which had crossing sides with smaller triangles or include loudspeakers*/ trip_ptr = x->x_ls_set; prev = NULL; while (trip_ptr != NULL) { i = trip_ptr->ls_nos[0]; j = trip_ptr->ls_nos[1]; k = trip_ptr->ls_nos[2]; if(connections[i][j] == 0 || connections[i][k] == 0 || connections[j][k] == 0 || any_ls_inside_triplet(i,j,k,x->x_ls,ls_amount) == 1 ) { if(prev != NULL) { prev->next = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } else { x->x_ls_set = trip_ptr->next; tmp_ptr = trip_ptr; trip_ptr = trip_ptr->next; freebytes(tmp_ptr, sizeof (struct t_ls_set)); } } else { prev = trip_ptr; trip_ptr = trip_ptr->next; } } x->x_triplets_specified=1; } int any_ls_inside_triplet(int a, int b, int c,t_ls lss[MAX_LS_AMOUNT],int ls_amount) /* returns 1 if there is loudspeaker(s) inside given ls triplet */ { t_float invdet; t_ls *lp1, *lp2, *lp3; t_float invmx[9]; int i,j; t_float tmp; int any_ls_inside, this_inside; lp1 = &(lss[a]); lp2 = &(lss[b]); lp3 = &(lss[c]); /* matrix inversion */ invdet = 1.0 / ( lp1->x * ((lp2->y * lp3->z) - (lp2->z * lp3->y)) - lp1->y * ((lp2->x * lp3->z) - (lp2->z * lp3->x)) + lp1->z * ((lp2->x * lp3->y) - (lp2->y * lp3->x))); invmx[0] = ((lp2->y * lp3->z) - (lp2->z * lp3->y)) * invdet; invmx[3] = ((lp1->y * lp3->z) - (lp1->z * lp3->y)) * -invdet; invmx[6] = ((lp1->y * lp2->z) - (lp1->z * lp2->y)) * invdet; invmx[1] = ((lp2->x * lp3->z) - (lp2->z * lp3->x)) * -invdet; invmx[4] = ((lp1->x * lp3->z) - (lp1->z * lp3->x)) * invdet; invmx[7] = ((lp1->x * lp2->z) - (lp1->z * lp2->x)) * -invdet; invmx[2] = ((lp2->x * lp3->y) - (lp2->y * lp3->x)) * invdet; invmx[5] = ((lp1->x * lp3->y) - (lp1->y * lp3->x)) * -invdet; invmx[8] = ((lp1->x * lp2->y) - (lp1->y * lp2->x)) * invdet; any_ls_inside = 0; for(i=0; i< ls_amount; i++) { if (i != a && i!=b && i != c) { this_inside = 1; for(j=0; j< 3; j++) { tmp = lss[i].x * invmx[0 + j*3]; tmp += lss[i].y * invmx[1 + j*3]; tmp += lss[i].z * invmx[2 + j*3]; if(tmp < -0.001) this_inside = 0; } if(this_inside == 1) any_ls_inside=1; } } return any_ls_inside; } static void add_ldsp_triplet(int i, int j, int k, t_def_ls *x) /* adds i,j,k triplet to structure*/ { struct t_ls_set *trip_ptr, *prev; trip_ptr = x->x_ls_set; prev = NULL; while (trip_ptr != NULL) { prev = trip_ptr; trip_ptr = trip_ptr->next; } trip_ptr = (struct t_ls_set*) getbytes (sizeof (struct t_ls_set)); if(prev == NULL) x->x_ls_set = trip_ptr; else prev->next = trip_ptr; trip_ptr->next = NULL; trip_ptr->ls_nos[0] = i; trip_ptr->ls_nos[1] = j; trip_ptr->ls_nos[2] = k; } t_float vec_angle(t_ls v1, t_ls v2) // angle between two loudspeakers { t_float inner= ((v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)/ (vec_length(v1) * vec_length(v2))); if(inner > 1.0) inner= 1.0; if (inner < -1.0) inner = -1.0; return fabs( acos( inner)); } t_float vec_length(t_ls v1) // length of a vector { return (sqrt(v1.x*v1.x + v1.y*v1.y + v1.z*v1.z)); } t_float vec_prod(t_ls v1, t_ls v2) // vector dot product { return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); } t_float vol_p_side_lgth(int i, int j,int k, t_ls lss[MAX_LS_AMOUNT] ) { /* calculate volume of the parallelepiped defined by the loudspeaker direction vectors and divide it with total length of the triangle sides. This is used when removing too narrow triangles. */ t_float volper, lgth; t_ls xprod; ls_cross_prod(lss[i], lss[j], &xprod); volper = fabsf(vec_prod(xprod, lss[k])); lgth = (fabsf(vec_angle(lss[i],lss[j])) + fabsf(vec_angle(lss[i],lss[k])) + fabsf(vec_angle(lss[j],lss[k]))); if(lgth>0.00001) return volper / lgth; else return 0.0; } static void ls_cross_prod(t_ls v1,t_ls v2, t_ls *res) // vector cross product { t_float length; res->x = (v1.y * v2.z ) - (v1.z * v2.y); res->y = (v1.z * v2.x ) - (v1.x * v2.z); res->z = (v1.x * v2.y ) - (v1.y * v2.x); length= vec_length(*res); res->x /= length; res->y /= length; res->z /= length; } static int lines_intersect(int i,int j,int k,int l,t_ls lss[MAX_LS_AMOUNT]) /* checks if two lines intersect on 3D sphere */ { t_ls v1; t_ls v2; t_ls v3, neg_v3; //t_float angle; t_float dist_ij,dist_kl,dist_iv3,dist_jv3,dist_inv3,dist_jnv3; t_float dist_kv3,dist_lv3,dist_knv3,dist_lnv3; // TODO epsilon needs to be updated for 64-bit/double precision t_float epsilon = 1e-9; ls_cross_prod(lss[i],lss[j],&v1); ls_cross_prod(lss[k],lss[l],&v2); ls_cross_prod(v1,v2,&v3); neg_v3.x= 0.0 - v3.x; neg_v3.y= 0.0 - v3.y; neg_v3.z= 0.0 - v3.z; dist_ij = (vec_angle(lss[i],lss[j])); dist_kl = (vec_angle(lss[k],lss[l])); dist_iv3 = (vec_angle(lss[i],v3)); dist_jv3 = (vec_angle(v3,lss[j])); dist_inv3 = (vec_angle(lss[i],neg_v3)); dist_jnv3 = (vec_angle(neg_v3,lss[j])); dist_kv3 = (vec_angle(lss[k],v3)); dist_lv3 = (vec_angle(v3,lss[l])); dist_knv3 = (vec_angle(lss[k],neg_v3)); dist_lnv3 = (vec_angle(neg_v3,lss[l])); /* if one of loudspeakers is close to crossing point, don't do anything*/ if(fabsf(dist_iv3) <= epsilon || fabsf(dist_jv3) <= epsilon || fabsf(dist_kv3) <= epsilon || fabsf(dist_lv3) <= epsilon || fabsf(dist_inv3) <= epsilon || fabsf(dist_jnv3) <= epsilon || fabsf(dist_knv3) <= epsilon || fabsf(dist_lnv3) <= epsilon ) return(0); // if crossing point is on line between both loudspeakers return 1 if (((fabsf(dist_ij - (dist_iv3 + dist_jv3)) <= epsilon) && (fabsf(dist_kl - (dist_kv3 + dist_lv3)) <= epsilon)) || ((fabsf(dist_ij - (dist_inv3 + dist_jnv3)) <= epsilon) && (fabsf(dist_kl - (dist_knv3 + dist_lnv3)) <= epsilon))) { return (1); } else { return (0); } } static void calculate_3x3_matrixes(t_def_ls *x) /* Calculates the inverse matrices for 3D */ { t_float invdet; t_ls *lp1, *lp2, *lp3; t_float *invmx; //t_float *ptr; struct t_ls_set *tr_ptr = x->x_ls_set; int triplet_amount = 0, /*ftable_size,*/i,pointer,list_length=0; Atom *at; t_ls *lss = x->x_ls; if (tr_ptr == NULL) { error("define-loudspeakers: Not valid 3-D configuration\n"); return; } /* counting triplet amount */ while(tr_ptr != NULL) { triplet_amount++; tr_ptr = tr_ptr->next; } tr_ptr = x->x_ls_set; list_length= triplet_amount * 21 + 3; at= (Atom *) getbytes(list_length*sizeof(Atom)); SETLONG(&at[0], x->x_def_ls_dimension); SETLONG(&at[1], x->x_def_ls_amount); pointer=2; while(tr_ptr != NULL){ lp1 = &(lss[tr_ptr->ls_nos[0]]); lp2 = &(lss[tr_ptr->ls_nos[1]]); lp3 = &(lss[tr_ptr->ls_nos[2]]); /* matrix inversion */ invmx = tr_ptr->inv_mx; invdet = 1.0 / ( lp1->x * ((lp2->y * lp3->z) - (lp2->z * lp3->y)) - lp1->y * ((lp2->x * lp3->z) - (lp2->z * lp3->x)) + lp1->z * ((lp2->x * lp3->y) - (lp2->y * lp3->x))); invmx[0] = ((lp2->y * lp3->z) - (lp2->z * lp3->y)) * invdet; invmx[3] = ((lp1->y * lp3->z) - (lp1->z * lp3->y)) * -invdet; invmx[6] = ((lp1->y * lp2->z) - (lp1->z * lp2->y)) * invdet; invmx[1] = ((lp2->x * lp3->z) - (lp2->z * lp3->x)) * -invdet; invmx[4] = ((lp1->x * lp3->z) - (lp1->z * lp3->x)) * invdet; invmx[7] = ((lp1->x * lp2->z) - (lp1->z * lp2->x)) * -invdet; invmx[2] = ((lp2->x * lp3->y) - (lp2->y * lp3->x)) * invdet; invmx[5] = ((lp1->x * lp3->y) - (lp1->y * lp3->x)) * -invdet; invmx[8] = ((lp1->x * lp2->y) - (lp1->y * lp2->x)) * invdet; for(i=0;i<3;i++){ SETLONG(&at[pointer], tr_ptr->ls_nos[i]+1); pointer++; } for(i=0;i<9;i++){ SETFLOAT(&at[pointer], invmx[i]); pointer++; } SETFLOAT(&at[pointer], lp1->x); pointer++; SETFLOAT(&at[pointer], lp2->x); pointer++; SETFLOAT(&at[pointer], lp3->x); pointer++; SETFLOAT(&at[pointer], lp1->y); pointer++; SETFLOAT(&at[pointer], lp2->y); pointer++; SETFLOAT(&at[pointer], lp3->y); pointer++; SETFLOAT(&at[pointer], lp1->z); pointer++; SETFLOAT(&at[pointer], lp2->z); pointer++; SETFLOAT(&at[pointer], lp3->z); pointer++; tr_ptr = tr_ptr->next; } sendLoudspeakerMatrices(x,list_length, at); // outlet_anything(x->x_outlet0, gensym("loudspeaker-matrices"), list_length, at); freebytes(at, list_length*sizeof(Atom)); } static void choose_ls_tuplets(t_def_ls *x) /* selects the loudspeaker pairs, calculates the inversion matrices and stores the data to a global array*/ { //t_float atorad = (2 * 3.1415927 / 360) ; int i,j; //t_float w1,w2; //t_float p1,p2; int sorted_lss[MAX_LS_AMOUNT]; int exist[MAX_LS_AMOUNT]; int amount=0; t_float inv_mat[MAX_LS_AMOUNT][4]; // In 2-D ls amount == max amount of LS pairs t_float mat[MAX_LS_AMOUNT][4]; //t_float *ptr; //t_float *ls_table; t_ls *lss = x->x_ls; long ls_amount=x->x_def_ls_amount; long list_length; Atom *at; long pointer; for(i=0;ix_ls,sorted_lss,ls_amount); /* adjacent loudspeakers are the loudspeaker pairs to be used.*/ for(i=0;i<(ls_amount-1);i++){ if((lss[sorted_lss[i+1]].azi - lss[sorted_lss[i]].azi) <= (180 - 10)){ if (calc_2D_inv_tmatrix( lss[sorted_lss[i]].azi, lss[sorted_lss[i+1]].azi, inv_mat[i],mat[i]) != 0){ exist[i]=1; amount++; } } } if(((360 - lss[sorted_lss[ls_amount-1]].azi) +lss[sorted_lss[0]].azi) <= (180 - 10)) { if(calc_2D_inv_tmatrix(lss[sorted_lss[ls_amount-1]].azi, lss[sorted_lss[0]].azi, inv_mat[ls_amount-1],mat[ls_amount-1]) != 0) { exist[ls_amount-1]=1; amount++; } } // Output list_length= amount * 10 + 2; at= (Atom *) getbytes(list_length*sizeof(Atom)); SETLONG(&at[0], x->x_def_ls_dimension); SETLONG(&at[1], x->x_def_ls_amount); pointer=2; for (i=0;ix_outlet0, gensym("loudspeaker-matrices"), list_length, at); freebytes(at, list_length*sizeof(Atom)); } void sort_2D_lss(t_ls lss[MAX_LS_AMOUNT], int sorted_lss[MAX_LS_AMOUNT], int ls_amount) // sort loudspeakers according to azimuth angle { t_float tmp, tmp_azi; // t_float rad2ang = 360.0f / ( 2.0f * M_PI ); //t_float x,y; /* Transforming angles between -180 and 180 */ int i; for (i=0;i x-max4.2 written by Ville Pulkki 1999-2003 Helsinki University of Technology and Unversity of California at Berkeley See copyright in file with name LICENSE.txt */ #include "vbap.h" static t_class *def_ls_class; /* so max can identify your object */ static void def_ls_bang(t_def_ls *x); //static void def_ls_int(t_def_ls *x, long n); static void def_ls_read_directions(t_def_ls *x, t_symbol *s, int ac, Atom *av); static void def_ls_read_triplets(t_def_ls *x, t_symbol *s, int ac, Atom *av); static void *def_ls_new(t_symbol *s, int ac, Atom *av); //static void def_ls(float g[3], long ls[3], t_def_ls *x); static void ls_angles_to_cart(t_ls *ls); static void choose_ls_triplets(t_def_ls *x); static int any_ls_inside_triplet(int a, int b, int c,t_ls lss[MAX_LS_AMOUNT],int ls_amount); static void add_ldsp_triplet(int i, int j, int k, t_def_ls *x); static t_float vec_angle(t_ls v1, t_ls v2); static t_float vec_length(t_ls v1); static t_float vec_prod(t_ls v1, t_ls v2); static t_float vec_prod(t_ls v1, t_ls v2); static t_float vol_p_side_lgth(int i, int j,int k, t_ls lss[MAX_LS_AMOUNT] ); static void ls_cross_prod(t_ls v1,t_ls v2, t_ls *res); static int lines_intersect(int i,int j,int k,int l,t_ls lss[MAX_LS_AMOUNT]); static void calculate_3x3_matrixes(t_def_ls *x); static void choose_ls_tuplets(t_def_ls *x); static int calc_2D_inv_tmatrix(t_float azi1,t_float azi2, t_float inv_mat[4],t_float mat[4]); static void sort_2D_lss(t_ls lss[MAX_LS_AMOUNT], int sorted_lss[MAX_LS_AMOUNT], int ls_amount); static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av); void vbap_def_ls(t_def_ls *x, t_symbol *s, int ac, Atom *av); vbap-1.0.3.2/examples/0000755000076500007650000000000011772150730013102 5ustar hanshansvbap-1.0.3.2/examples/graph-to-aziele.pd0000644000076500007650000000225511472120731016416 0ustar hanshans#N canvas 549 17 647 652 12; #X obj 42 505 expr acos($f1/$f3) * 180 / 3.1415 * $f2; #X obj 323 366 expr sqrt($f1); #X obj 323 338 + 0; #X obj 78 313 * 0; #X obj 343 276 * 0; #X msg 460 505 0; #X msg 233 265 -1; #X msg 268 265 1; #X obj 42 249 expr ($f1-0.5)/0.5; #X obj 233 145 expr ($f1-0.5)/0.5; #X obj 42 16 inlet; #X obj 42 570 outlet; #X obj 488 569 outlet; #X obj 407 431 expr 90 - ($f1*90.0); #X obj 460 479 moses 0; #X obj 233 238 moses 0; #X obj 42 279 t f f f; #X obj 233 179 t f f f; #X obj 42 99 unpack f f; #X msg 42 67 \$2 \$1; #X text 101 66 reverse order; #X text 101 16 float x \, float y; #X obj 323 393 t f f; #X connect 0 0 11 0; #X connect 1 0 22 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 2 1; #X connect 5 0 12 0; #X connect 6 0 0 1; #X connect 7 0 0 1; #X connect 8 0 16 0; #X connect 9 0 17 0; #X connect 10 0 19 0; #X connect 13 0 14 0; #X connect 14 0 5 0; #X connect 14 1 12 0; #X connect 15 0 6 0; #X connect 15 1 7 0; #X connect 16 0 0 0; #X connect 16 1 3 0; #X connect 16 2 3 1; #X connect 17 0 15 0; #X connect 17 1 4 0; #X connect 17 2 4 1; #X connect 18 0 8 0; #X connect 18 1 9 0; #X connect 19 0 18 0; #X connect 22 0 0 2; #X connect 22 1 13 0; vbap-1.0.3.2/examples/high.pd0000644000076500007650000000111211472120731014334 0ustar hanshans#N canvas 0 0 576 425 10; #X obj 102 43 inlet; #X obj 124 188 f 0; #X obj 102 239 >; #X obj 102 281 sel 1; #X obj 201 158 f; #X obj 203 354 outlet; #X obj 203 267 f; #X obj 292 42 inlet; #X text 339 42 reset to float; #X text 148 44 test against high; #X obj 102 91 t b f b f; #X obj 292 89 t b f; #X connect 0 0 10 0; #X connect 1 0 2 1; #X connect 1 0 6 1; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 1 0; #X connect 6 0 5 0; #X connect 7 0 11 0; #X connect 10 0 6 0; #X connect 10 1 2 0; #X connect 10 2 1 0; #X connect 10 3 4 1; #X connect 11 0 6 0; #X connect 11 1 1 0; vbap-1.0.3.2/examples/playsample~.pd0000644000076500007650000000244411472120731015773 0ustar hanshans#N canvas 27 300 849 403 10; #X obj 38 354 table \$0music; #X obj 148 160 soundfiler; #X floatatom 148 183 5 0 0; #X obj 243 207 phasor~ 1; #X floatatom 266 181 8 0 0; #X obj 243 237 *~ 0; #X msg 148 137 read -resize \$1 \$2; #X obj 199 83 symbol \$0music; #X obj 148 110 pack s s; #X obj 199 48 loadbang; #X obj 12 13 inlet; #X text 59 12 .aiff file name; #X obj 311 15 inlet; #X text 356 15 phasor speed; #X obj 243 334 outlet~; #X obj 243 267 tabread4~ \$0music; #X obj 302 83 samplerate~; #X floatatom 310 107 5 0 0; #X obj 460 14 inlet; #X text 505 14 gain; #X obj 243 306 *~ 1; #X obj 148 210 t b f; #X obj 148 232 f; #X obj 148 254 /; #X obj 419 334 outlet~; #X text 303 333 sample signal; #X text 483 334 phasor signal; #X msg 557 41 0; #X obj 557 16 inlet; #X text 601 16 restart; #X connect 1 0 2 0; #X connect 2 0 5 1; #X connect 2 0 21 0; #X connect 3 0 5 0; #X connect 3 0 24 0; #X connect 4 0 3 0; #X connect 5 0 15 0; #X connect 6 0 1 0; #X connect 7 0 8 1; #X connect 8 0 6 0; #X connect 9 0 7 0; #X connect 9 0 16 0; #X connect 10 0 8 0; #X connect 12 0 3 0; #X connect 15 0 20 0; #X connect 16 0 17 0; #X connect 16 0 22 1; #X connect 18 0 20 1; #X connect 20 0 14 0; #X connect 21 0 22 0; #X connect 21 1 23 1; #X connect 22 0 23 0; #X connect 23 0 4 0; #X connect 27 0 3 1; #X connect 28 0 27 0; vbap-1.0.3.2/examples/recent.pd0000644000076500007650000000050611472121635014707 0ustar hanshans#N canvas 399 148 452 302 12; #X obj 56 55 inlet; #X msg 91 123 clear; #X obj 59 252 outlet; #X obj 166 54 inlet; #X text 8 5 output only most "recent" messages; #X obj 56 89 t a b; #X obj 59 202 pipe \$1; #X connect 0 0 5 0; #X connect 1 0 6 0; #X connect 3 0 6 1; #X connect 5 0 6 0; #X connect 5 1 1 0; #X connect 6 0 2 0; vbap-1.0.3.2/examples/rvbap-demo.pd0000644000076500007650000004017411472307702015471 0ustar hanshans#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; vbap-1.0.3.2/examples/vbap-demo.pd0000644000076500007650000000222711472120756015306 0ustar hanshans#N canvas 11 22 871 352 10; #X obj 50 80 playsample~; #X obj 50 55 openpanel; #X msg 50 31 bang; #X text 96 30 click to load and play a sample; #X floatatom 133 80 5 0 0 0 - - -; #X floatatom 133 101 5 0 0 0 - - -; #X text 182 80 pitch; #X text 182 102 volume; #X floatatom 76 142 5 0 0 0 - - -; #X floatatom 122 142 5 0 0 0 - - -; #X floatatom 168 142 5 0 0 0 - - -; #X text 218 143 set azimuth \, elevation \, spread; #N canvas 152 420 615 353 using 0; #X obj 59 258 graph-to-aziele; #X obj 59 233 pack f f; #X floatatom 59 281 5 0 0 0 - - -; #X obj 59 78 grid grid1 144 0 1 144 0 1 0 0.001 0.001 10 10 103 91 ; #X floatatom 159 281 5 0 0 0 - - -; #X text 21 17 To use Yves Degoyon's GRID (http://ydegoyon.free.fr) use graph-to-aziele.pd to count the azimuth and elevation.; #X text 25 49 (note: GRID must output values between 0 - 1); #X connect 0 0 2 0; #X connect 0 1 4 0; #X connect 1 0 0 0; #X connect 3 0 1 0; #X connect 3 1 1 1; #X restore 506 112 pd using GRID with vbap; #X obj 50 174 vbapmodule 1; #X connect 0 0 13 0; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 4 0 0 1; #X connect 5 0 0 2; #X connect 8 0 13 1; #X connect 9 0 13 2; #X connect 10 0 13 3; vbap-1.0.3.2/examples/vbap-level-config.pd0000644000076500007650000000170611026723012016722 0ustar hanshans#N canvas 334 22 636 372 10; #X obj 19 100 noise~; #X obj 19 153 *~ 0.01; #X obj 61 128 hsl 128 15 0.01 1 1 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X floatatom 71 149 5 0 0 0 - - -; #X obj 19 183 cyclone/reson~ 1 1000 20; #X obj 18 269 dac~ 1 2 3 4 5 6 7 8; #X text 217 131 B. Measure loudspeaker distances. Delay all loudspeakers to mimic the distance between listener and farthest loudspeaker. The amount of delay can be calculated as t = ((d - x) / 330) * 1000 \, where d is the distance in metres between listener and one particular loudspeaker \, and t is the amount of delay in milliseconds. Apply the delay to function function ls-delays to corresponding channel. ; #X text 217 80 A. Adjust gain each speaker's channel same level sweet spot using this file. You use a sound pressure meter or your ears. ; #X text 265 287 based on an example by Ville Pulkki 1999-2006; #X connect 0 0 1 0; #X connect 1 0 4 0; #X connect 2 0 1 1; #X connect 2 0 3 0; vbap-1.0.3.2/examples/vbap.main.pd0000644000076500007650000000476111472307702015312 0ustar hanshans#N canvas 153 122 664 665 10; #X obj 22 149 bng 15 250 50 0 empty empty empty 20 8 32 8 -262144 -1 -1; #X floatatom 353 470 5 0 0; #X obj 166 579 dac~ 1 2 3 4 5 6 7 8; #X obj 109 535 *~ 1; #X obj 142 535 *~ 1; #X obj 175 535 *~ 1; #X obj 207 535 *~ 1; #X obj 239 535 *~ 1; #X obj 271 535 *~ 1; #X obj 304 535 *~ 1; #X obj 336 535 *~ 1; #X floatatom 382 504 5 0 0; #X text 401 470 crossfade; #X obj 22 208 send speaker_setup; #X obj 22 169 define_loudspeakers 3 -30 0 30 0 -90 0 90 0 180 0 180 45 -45 45 45 45; #X obj 326 443 matrix 4 8; #X obj 269 470 matrix~ 4 8; #X obj 39 146 loadbang; #X msg 471 169 \; pd dsp 1; #X text 540 175 turn on audio; #X text 430 504 gain; #X obj 467 496 vsl 15 128 0 1 0 0 empty empty empty 20 8 32 8 -262144 -1 -1 0 1; #X msg 422 452 50; #X obj 438 413 loadbang; #X obj 484 494 r master; #X obj 21 89 inlet; #X text 66 89 no meaning; #X obj 326 340 receive matrix; #X text 30 22 define loudspeakers \, receive signals and data from vbap \, output audio; #X obj 99 146 receive define_ls; #X obj 52 318 catch~ 1chan; #X obj 162 318 catch~ 2chan; #X obj 272 318 catch~ 3chan; #X obj 382 318 catch~ 4chan; #N canvas 229 245 540 236 parameters.readme 0; #X text 37 35 define_loudspeakers <..>; #X text 37 70 dimensions is 2 or 3 \, followed by list of azimuths (in 2d) or pairs (in 3d) \, defining the number and positions of loudspeakers.; #X text 38 122 azimuth is -180 to 180 \, where -90 is left \, 0 front \, 90 right and 180 back.; #X text 38 161 elevation is -90 to 90 \, where -90 is down \, 0 is not elevated and 90 is up.; #X restore 258 206 pd parameters.readme; #X connect 0 0 14 0; #X connect 1 0 16 5; #X connect 3 0 2 0; #X connect 4 0 2 1; #X connect 5 0 2 2; #X connect 6 0 2 3; #X connect 7 0 2 4; #X connect 8 0 2 5; #X connect 9 0 2 6; #X connect 10 0 2 7; #X connect 11 0 10 1; #X connect 11 0 9 1; #X connect 11 0 8 1; #X connect 11 0 7 1; #X connect 11 0 6 1; #X connect 11 0 5 1; #X connect 11 0 4 1; #X connect 11 0 3 1; #X connect 11 0 9 1; #X connect 11 0 10 1; #X connect 14 0 13 0; #X connect 15 0 16 4; #X connect 16 0 3 0; #X connect 16 1 4 0; #X connect 16 2 5 0; #X connect 16 3 6 0; #X connect 16 4 7 0; #X connect 16 5 8 0; #X connect 16 6 9 0; #X connect 16 7 10 0; #X connect 17 0 0 0; #X connect 21 0 11 0; #X connect 22 0 1 0; #X connect 23 0 22 0; #X connect 23 0 18 0; #X connect 24 0 21 0; #X connect 27 0 15 0; #X connect 29 0 0 0; #X connect 30 0 16 0; #X connect 31 0 16 1; #X connect 32 0 16 2; #X connect 33 0 16 3; vbap-1.0.3.2/examples/vbapmodule.pd0000644000076500007650000000104311472121635015562 0ustar hanshans#N canvas 94 380 450 300 10; #X obj 30 44 inlet~; #X obj 62 158 send matrix; #X obj 46 183 throw~ \$1chan; #X floatatom 180 186 5 0 0; #X floatatom 225 186 5 0 0; #X floatatom 270 186 5 0 0; #X text 137 217 actual azi / ele / spread; #X obj 82 44 inlet; #X obj 122 44 inlet; #X obj 162 44 inlet; #X text 210 44 azi / ele / spread; #X obj 46 112 vbapsnd \$1; #X connect 0 0 11 0; #X connect 7 0 11 1; #X connect 8 0 11 2; #X connect 9 0 11 3; #X connect 11 0 2 0; #X connect 11 1 1 0; #X connect 11 2 3 0; #X connect 11 3 4 0; #X connect 11 4 5 0; vbap-1.0.3.2/examples/vbapsnd.pd0000644000076500007650000000303711472307702015067 0ustar hanshans#N canvas 33 53 661 597 10; #X obj 133 20 inlet; #X obj 189 171 vbap 0 0; #X obj 240 20 inlet; #X obj 359 20 inlet; #X text 176 19 azimuth; #X text 285 19 elevation; #X text 405 19 spread; #X obj 233 460 pack f f f; #X obj 298 437 float \$1; #X obj 298 414 loadbang; #X msg 233 495 element \$3 \$1 \$2; #X text 287 536 to matrix object; #X obj 441 535 outlet; #X obj 488 535 outlet; #X obj 535 535 outlet; #X obj 359 78 t b f; #X obj 240 80 t b f; #X obj 133 80 t b f; #X obj 189 106 receive speaker_setup; #X obj 189 256 unpack f f; #X obj 189 279 + 1; #X obj 167 429 ==; #X obj 167 453 sel 1; #X obj 189 303 t f f f; #X obj 195 429 high; #X obj 233 536 outlet; #X obj 31 20 inlet~; #X obj 31 83 outlet~; #X text 28 113 for convenience; #X floatatom 489 62 5 0 0; #X obj 359 49 recent 10; #X obj 240 51 recent 10; #X obj 133 51 recent 10; #X connect 0 0 32 0; #X connect 1 0 19 0; #X connect 1 1 12 0; #X connect 1 2 13 0; #X connect 1 3 14 0; #X connect 2 0 31 0; #X connect 3 0 30 0; #X connect 7 0 10 0; #X connect 8 0 7 2; #X connect 9 0 8 0; #X connect 10 0 25 0; #X connect 15 0 1 0; #X connect 15 1 1 3; #X connect 16 0 1 0; #X connect 16 1 1 2; #X connect 17 0 1 0; #X connect 17 1 1 1; #X connect 18 0 1 0; #X connect 19 0 20 0; #X connect 19 1 7 1; #X connect 20 0 23 0; #X connect 21 0 22 0; #X connect 22 0 25 0; #X connect 23 0 21 0; #X connect 23 1 24 0; #X connect 23 2 7 0; #X connect 24 0 21 1; #X connect 26 0 27 0; #X connect 29 0 30 1; #X connect 29 0 31 1; #X connect 29 0 32 1; #X connect 30 0 15 0; #X connect 31 0 16 0; #X connect 32 0 17 0; vbap-1.0.3.2/makefile.irix0000644000076500007650000000062510755130230013732 0ustar hanshansFLAGS = -DPD -DUNIX -DIRIX -DN32 -O2 -w INCLUDE = -I../pd/src -I /usr/local/include all: vbap_irix6 definels_irix6 vbap_irix6: cc $(FLAGS) $(INCLUDE) -o vbap.o -c vbap.c ld -elf -shared -rdata_shared -o vbap.pd_irix6 vbap.o definels_irix6: cc $(FLAGS) $(INCLUDE) -o define_loudspeakers.o -c define_loudspeakers.c ld -elf -shared -rdata_shared -o define_loudspeakers.pd_irix6 define_loudspeakers.o vbap-1.0.3.2/max2pd.h0000644000076500007650000000223711472120365012632 0ustar hanshans/* * this header aims to make it easy to port Max objects to Pd */ /* name changes */ #define SETSYM SETSYMBOL /* Pd doesn't have longs */ #define SETLONG SETFLOAT /* different names for the same thing */ #define Atom t_atom #define Symbol t_symbol /* allocate memory */ #define sysmem_newptr(size) getbytes(128) #define sysmem_freeptr(ptr) freebytes(ptr, 128) /* standard object API functions */ #define atom_getlong(atom) atom_getfloatarg(0, 1, atom) #define atom_getsym(atom) atom_getsymbolarg(0, 1, atom) #define object_alloc(obj_class) pd_new(obj_class) #define object_free(obj) pd_free((t_pd*)obj) #define newobject(class) pd_new(class) #define outlet_int(outlet, number) outlet_float(outlet, number) /* debug things */ #define _enable_trace sys_verbose /* these are NOT included here because they would cause more problems than * they would solve. Usually, they are used in the setup() and new() * functions, where most of the differences are between the Max and PD APIs */ /* macros */ // A_DEFLONG /* types */ // method // Object /* functions */ // addint() // addmess() // newobject() // outlet_new() // setup() vbap-1.0.3.2/rvbap-help.pd0000644000076500007650000001761211727002623013655 0ustar hanshans#N canvas 143 28 813 728 10; #X declare -lib hexloader -lib iemmatrix; #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 231 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 368 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 141 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 22 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 22 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 22 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 45 rvbap is almost compatible to; #X obj 33 82 define_loudspeakers 2 -45 45 0 180; #X obj 115 599 mtx_*~ 8 1 20; #X text 431 65 Additionally it generates additional commands for controlling a reverberated signal and has control to set the radial distance of a sound.; #X text 430 427 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 285 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 619 See rvbap-demo.pd for a more complex setup.; #X text 429 497 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 obj 633 7 import hexloader iemmatrix; #X obj 610 45 pddp/helplink vbap; #X connect 0 0 10 0; #X connect 1 0 32 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 33 1; #X connect 22 0 21 0; #X connect 23 0 33 0; #X connect 24 0 23 0; #X connect 26 0 33 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 32 0 10 0; #X connect 33 0 20 0; #X connect 33 1 20 1; #X connect 33 2 20 2; #X connect 33 3 20 3; #X connect 33 4 30 0; #X connect 33 5 30 1; #X connect 33 6 30 2; #X connect 33 7 30 3; vbap-1.0.3.2/rvbap.c0000644000076500007650000007740411661104502012547 0ustar hanshans/* 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 LICENSE.txt */ #include #ifdef MAXMSP #include "ext.h" /* you must include this - it contains the external object's link to max */ #define t_float float #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 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; t_float x_set_inv_matx[MAX_LS_SETS][9];// inverse matrice for each loudspeaker set t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set long x_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) t_float x_spread_base[3]; // used to create uniform spreading t_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; t_float x_set_inv_matx[MAX_LS_SETS][9];// inverse matrice for each loudspeaker set t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set long x_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) t_float x_spread_base[3]; // used to create uniform spreading t_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, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3]); static void new_spread_base(t_rvbap *x, t_float spreaddir[3], t_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(t_float v1[3], t_float v2[3], t_float v3[3]); static void additive_vbap(t_float *final_gs, t_float cartdir[3], t_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, t_float *final_gs); static void *rvbap_new(t_symbol *s, int ac, t_atom *av); // using A_GIMME - typed message list static void vbap(t_float g[3], long ls[3], t_rvbap *x); static void angle_to_cart(long azi, long ele, t_float res[3]); static void cart_to_angle(t_float cvec[3], t_float avec[3]); static void equal_reverb(t_rvbap *x, t_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, "(t_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, "(t_float) actual distance"); break; } break; } } #endif /* end MAXMSP */ static void angle_to_cart(long azi, long ele, t_float res[3]) /* converts angular coordinates to cartesian */ { t_float atorad = (2.0 * 3.141592653589793 / 360.0) ; res[0] = cos((t_float) azi * atorad) * cos((t_float) ele * atorad); res[1] = sin((t_float) azi * atorad) * cos((t_float) ele * atorad); res[2] = sin((t_float) ele * atorad); } static void cart_to_angle(t_float cvec[3], t_float avec[3]) // converts cartesian coordinates to angular { t_float tmp, tmp2, tmp3, tmp4; t_float atorad = (t_float)(2.0 * 3.141592653589793 / 360.0) ; t_float pi = (t_float)3.141592653589793; t_float power; t_float dist, atan_y_per_x, atan_x_pl_y_per_z; t_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 = sqrt(cvec[0] * cvec[0] +cvec[1] * cvec[1] +cvec[2]*cvec[2]); avec[0]=azi; avec[1]=ele; avec[2]=dist; } static void vbap(t_float g[3], long ls[3], t_rvbap *x) { /* calculates gain factors using loudspeaker setup and given direction */ t_float power; int i,j,k, gains_modified; t_float small_g; t_float big_sm_g, gtmp[3]; long winner_set=0; t_float cartdir[3]; t_float new_cartdir[3]; t_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;ix_lsset_amount;i++){ small_g = 10000000.0; neg_g_am = 3; for(j=0;jx_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;ix_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(t_float v1[3], t_float v2[3], t_float v3[3]) // vector cross product { t_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(t_float *final_gs, t_float cartdir[3], t_rvbap *x) // calculates gains to be added to previous gains, used in // multiple direction panning (source spreading) { t_float power; int i,j,k, gains_modified; t_float small_g; t_float big_sm_g, gtmp[3]; long winner_set; t_float new_cartdir[3]; t_float new_angle_dir[3]; long dim = x->x_dimension; long neg_g_am, best_neg_g_am; t_float g[3]; long ls[3] = { 0, 0, 0 }; big_sm_g = -100000.0; best_neg_g_am=3; for(i=0;ix_lsset_amount;i++){ small_g = 10000000.0; neg_g_am = 3; for(j=0;jx_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 */ if(dim==3) final_gs[ls[2]-1] += g[2]; } } static void new_spread_dir(t_rvbap *x, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3]) // subroutine for spreading { t_float beta,m_gamma; t_float a,b; t_float pi = 3.141592653589793; t_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, t_float spreaddir[3], t_float vscartdir[3]) // subroutine for spreading { t_float d; t_float pi = 3.141592653589793; t_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, t_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 { t_float vscartdir[3]; t_float spreaddir[16][3]; t_float spreadbase[16][3]; long i, spreaddirnum; t_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;ix_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;ix_spread > 70) for(i=0;ix_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;ix_ls_amount;i++){ power += final_gs[i] * final_gs[i]; } power = sqrt(power); for(i=0;ix_ls_amount;i++){ final_gs[i] /= power; } } static void equal_reverb(t_rvbap *x, t_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 { t_float vscartdir[3]; t_float spreaddir[16][3]; t_float spreadbase[16][3]; long i, spreaddirnum; t_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;ix_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;ix_reverb_gs,spreaddir[i],x); } else return; for(i=0,power=0.0;ix_ls_amount;i++){ power += x->x_reverb_gs[i] * x->x_reverb_gs[i]; } power = sqrt(power); for(i=0;ix_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]; t_float g[3]; long ls[3]; long i; t_float *final_gs, overdist, oversqrtdist; final_gs = (t_float *) getbytes(x->x_ls_amount * sizeof(t_float)); if(x->x_lsset_available ==1){ vbap(g, ls, x); for(i=0;ix_ls_amount;i++) final_gs[i]=0.0; for(i=0;ix_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;ix_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(t_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 t_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;ix_ls_amount;i++){ x->x_reverb_gs[i]=0.0; } for(i=0;ix_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; ix_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 = (t_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 = (t_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); t_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 */ } vbap-1.0.3.2/so_locations0000644000076500007650000000031110755130230013667 0ustar hanshansvbap.pd_irix6 \ :st = .text 0x5ffe0000, 0x00010000:\ :st = .data 0x5fff0000, 0x00010000: define_loudspeakers.pd_irix6 \ :st = .text 0x5ffc0000, 0x00010000:\ :st = .data 0x5ffd0000, 0x00010000: vbap-1.0.3.2/unittests/0000755000076500007650000000000011772150730013326 5ustar hanshansvbap-1.0.3.2/unittests/define-loudspeaker-unittest.wav0000644000076500007650000000405411661104502021464 0ustar hanshansRIFF$WAVEfmt D data@@?@@??5?5?@@@???5?5?@@Ie4??5?5?i!"4@?Iei!"45?5@@@?@@@5?555?5?5?5?5?5?55?5??@@@c3c5?5?5?555?5?5?55c5?5?@@@@d?d35?55?55?5?5?5?55?c5?5?vbap-1.0.3.2/unittests/define_loudspeakers-unittest.pd0000644000076500007650000000325611710345153021546 0ustar hanshans#N canvas 177 32 793 647 10; #X text 19 210 In two dimensions \, only specify the azimuth. (for example "define_loudspeakers 2 -45 45 0 180"; #X text 20 80 [define_loudspeakers] works with; #X obj 252 80 vbap; #X text 15 111 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:; #X msg 428 221 ls-directions 3 -30 0 30 0 -90 0 90 0 0 0 -150 0 150 0 180 45 -45 45 45 45; #X msg 411 158 ls-triplets 1 2 7 2 7 8 1 3 7; #X text 431 113 If you are not happy with triangle selections of define_loudspeakers \, you can define your own. (for experts only); #X text 427 268 2-D setup -> only loudspeaker azimuths specified:; #X text 426 283 (2 azi1 azi2 azi3 azi4...); #X text 425 184 3-D setup -> (azimuth elevation) pairs are specified: ; #X text 423 202 (3 azi1 ele1 azi2 ele2 ...); #X text 637 47 a 2D setup; #X text 679 77 a 3D setup; #X obj 56 355 testtools/unit-test-frame; #X obj 377 14 t b b b b; #X msg 56 322 define-loudspeaker-unittest; #X obj 56 296 loadbang; #X obj 377 79 vbap/define_loudspeakers 3 -45 0 45 0 0 45 180 45; #X obj 394 49 vbap/define_loudspeakers 2 -45 45 0 180; #X obj 411 303 vbap/define_loudspeakers 2 -40 0 40 80 130 180 -130 -80; #X connect 4 0 19 0; #X connect 5 0 19 0; #X connect 13 3 14 0; #X connect 14 0 17 0; #X connect 14 1 18 0; #X connect 14 2 5 0; #X connect 14 3 4 0; #X connect 15 0 13 0; #X connect 16 0 15 0; #X connect 17 0 13 1; #X connect 18 0 13 1; #X connect 19 0 13 1; vbap-1.0.3.2/unittests/rvbap-unittest.pd0000644000076500007650000000360011710345153016636 0ustar hanshans#N canvas 90 22 726 609 10; #X obj 38 -190 testtools/unit-test-frame; #X text 383 -369 azimuth \, elevation \, spread and distance; #N canvas 0 22 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 407 -341 pd tba; #X obj 342 -494 t b b b b; #X obj 446 -415 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X msg 407 -385 60; #X msg 446 -385 15; #X msg 524 -386 20; #X obj 38 -248 loadbang; #X obj 393 -440 vbap/define_loudspeakers 3 -45 0 45 0 0 45 180 45; #X obj 359 -307 vbap/rvbap 0 0; #X msg 485 -385 0; #X floatatom 379 -212 5 0 0 0 - - -; #X floatatom 399 -235 5 0 0 0 - - -; #X floatatom 419 -256 5 0 0 0 - - -; #X floatatom 440 -280 5 0 0 0 - - -; #X obj 359 -464 vbap/define_loudspeakers 3 -45 45 45 45 0 0 180 0; #X text 15 -474 In Pd-extended 0.42 \, [rvbap] crashes when using 2 dimensional setup.; #X msg 38 -219 rvbap-unittest; #X connect 0 3 3 0; #X connect 2 0 10 0; #X connect 2 1 10 1; #X connect 2 2 10 2; #X connect 2 3 10 3; #X connect 2 4 10 4; #X connect 3 0 4 0; #X connect 3 1 16 0; #X connect 3 2 4 0; #X connect 3 3 9 0; #X connect 4 0 5 0; #X connect 4 0 6 0; #X connect 4 0 11 0; #X connect 4 0 7 0; #X connect 5 0 2 0; #X connect 6 0 2 1; #X connect 7 0 2 3; #X connect 8 0 18 0; #X connect 9 0 10 0; #X connect 10 0 0 1; #X connect 10 1 12 0; #X connect 10 2 13 0; #X connect 10 3 14 0; #X connect 10 4 15 0; #X connect 11 0 2 2; #X connect 16 0 10 0; #X connect 18 0 0 0; vbap-1.0.3.2/unittests/rvbap-unittest.wav0000644000076500007650000000405411661104502017030 0ustar hanshansRIFF$WAVEfmt D data8@>??@?@@>@@@?@>?Fw?@?@g;>@>@@g;>@?@>?Fw?@?@g;>@>@@g;>@?@-;?VE=@JW>@<@"6=@@<@"6=7ޝ6@P;?3yD=@qS>@6g<@=@@@ <6@Q;?=@#>@QJ =@>@@@ <r9@6;?3>=@4!>@> =@W>@@@ <r9@6;?3>=@4!>@> =@W>@@@ <vbap-1.0.3.2/unittests/vbap-unittest.pd0000644000076500007650000001112611710345153016456 0ustar hanshans#N canvas 225 22 809 680 10; #X text 21 122 In two dimensions \, only specify the azimuth. (for example "define_loudspeakers 2 -45 45 0 180"; #X text 417 17 VBAP and define_loudspeakers; #X text 22 166 2 For vbap \, give azimuth and elevation 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 418 46 loudspeaker position definition can also be sent directly to a vbap object. This changes the setup information only in a single vbap object.; #X text 419 94 For an example of how to use vbap with [matrix~] from zexy-library \, see vbap-demo.pd.; #X text 21 22 1 Use the define_loudspeakers object or message 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.; #N canvas 283 22 628 620 simple 0; #X floatatom 159 198 5 0 0 2 - - -; #X floatatom 112 425 10 0 0 0 - - -; #X floatatom 181 425 10 0 0 0 - - -; #X floatatom 209 349 0 0 0 3 actual_azimuth - -; #X floatatom 221 315 0 0 0 3 actual_elevation - -; #X floatatom 231 294 7 0 0 1 actual_spreading - -; #X obj 162 182 hsl 100 13 -180 180 0 1 empty empty azimuth 10 7 0 10 -262144 -1 -1 1500 1; #X floatatom 237 237 5 0 0 2 - - -; #X obj 240 220 hsl 100 13 0 100 0 1 empty empty spread 10 7 0 10 -262144 -1 -1 700 1; #X text 130 134 to output updated values; #X obj 112 155 metro 100; #X obj 112 133 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X text 197 200 (ignore elevation in 2D \, that's for 3D); #X obj 63 524 *~; #X obj 92 525 *~; #X msg 454 145 dsp 1; #X obj 454 169 send pd; #X floatatom 250 425 10 0 0 0 - - -; #X floatatom 319 425 10 0 0 0 - - -; #X obj 123 524 *~; #X obj 152 525 *~; #X msg 17 48 define_loudspeakers 2 -135 -45 0 45 135; #X text 263 37 Define 2D speaker arrangement with speakers at -135 \, -45 \, 0 \, 45 and 135 degree positions (0 degrees is the center front). This is a classic 5.1 setup.; #X floatatom 389 425 10 0 0 0 - - -; #X obj 72 558 dac~ 1 2 3 4 5; #X obj 182 525 *~; #X obj 112 267 vbap 0 0 30; #X obj 112 376 route 0 1 2 3 4; #X obj 13 396 *~ 0.2; #X obj 13 374 noise~; #X connect 1 0 13 1; #X connect 2 0 14 1; #X connect 6 0 0 0; #X connect 8 0 7 0; #X connect 10 0 26 0; #X connect 11 0 10 0; #X connect 13 0 24 0; #X connect 14 0 24 1; #X connect 15 0 16 0; #X connect 17 0 19 1; #X connect 18 0 20 1; #X connect 19 0 24 2; #X connect 20 0 24 3; #X connect 21 0 26 0; #X connect 23 0 25 1; #X connect 25 0 24 4; #X connect 26 0 27 0; #X connect 27 0 1 0; #X connect 27 1 2 0; #X connect 27 2 17 0; #X connect 27 3 18 0; #X connect 27 4 23 0; #X connect 28 0 13 0; #X connect 28 0 14 0; #X connect 28 0 19 0; #X connect 28 0 20 0; #X connect 28 0 25 0; #X connect 29 0 28 0; #X restore 421 139 pd simple 5.1 example; #X obj 421 277 vbap/vbap 90 0 30; #X obj 100 371 testtools/unit-test-frame; #X msg 100 342 vbap; #X floatatom 454 342 5 0 0 0 - - -; #X floatatom 487 322 5 0 0 0 - - -; #X floatatom 520 300 5 0 0 0 - - -; #X text 22 244 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 496 344 azimuth; #X text 524 324 elevation; #X text 556 300 spread; #X obj 100 315 loadbang; #N canvas 0 22 504 332 define-loudspeakers 0; #X msg 51 87 define_loudspeakers 2 -135 -45 0 45 135; #X msg 106 121 define_loudspeakers 3 -45 0 45 0 0 45 180 45; #X obj 51 21 inlet; #X obj 51 284 outlet; #X obj 188 283 outlet; #X obj 106 148 t b a; #X obj 51 112 t b a; #X obj 51 53 t b b b b; #X obj 161 199 t b a; #X obj 208 245 t b a; #X msg 161 172 define_loudspeakers 3 -30 0 30 0 0 45 180 45; #X msg 207 217 define_loudspeakers 3 -45 0 45 0 0 30 180 30; #X connect 0 0 6 0; #X connect 1 0 5 0; #X connect 2 0 7 0; #X connect 5 0 3 0; #X connect 5 1 4 0; #X connect 6 0 3 0; #X connect 6 1 4 0; #X connect 7 0 0 0; #X connect 7 1 1 0; #X connect 7 2 10 0; #X connect 7 3 11 0; #X connect 8 0 3 0; #X connect 8 1 4 0; #X connect 9 0 3 0; #X connect 9 1 4 0; #X connect 10 0 8 0; #X connect 11 0 9 0; #X restore 421 237 pd define-loudspeakers; #X obj 421 208 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X connect 7 0 8 1; #X connect 7 1 10 0; #X connect 7 2 11 0; #X connect 7 3 12 0; #X connect 8 3 19 0; #X connect 9 0 8 0; #X connect 17 0 9 0; #X connect 18 0 7 0; #X connect 18 1 7 0; #X connect 19 0 18 0; vbap-1.0.3.2/unittests/vbap-unittest.wav0000644000076500007650000000405411661104502016646 0ustar hanshansRIFF$WAVEfmt D data.O=?ln?@@@>pB4BY>?'K?@>@@!!>@z>xB3A4B.O=?ln?@@@>pB4Bvbap-1.0.3.2/unittests/vbap.wav0000644000076500007650000000405411661104502014771 0ustar hanshansRIFF$WAVEfmt D data?]?@v>@@o>?]?@v>@@o>?3R?@iı>@@>?3R?@iı>@@><?V?@fI>@@.><?V?@fI>@@.>?@m>@@71v?@U>?@m>@@71v?@U>vbap-1.0.3.2/vbap-help.pd0000644000076500007650000001200011726776660013477 0ustar hanshans#N canvas 260 22 824 533 10; #X floatatom 149 218 5 0 0 2 - - -; #X floatatom 187 237 5 0 0 2 - - -; #X msg 115 163 bang; #X obj 102 396 route 0 1 2 3; #X floatatom 102 445 10 0 0 0 - - -; #X floatatom 181 445 10 0 0 0 - - -; #X floatatom 260 445 10 0 0 0 - - -; #X floatatom 339 445 10 0 0 0 - - -; #X text 441 159 In two dimensions \, only specify the azimuth. (for example "define_loudspeakers 2 -45 45 0 180"; #X text 53 21 VBAP and define_loudspeakers; #X text 442 281 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 floatatom 199 369 0 0 0 3 actual_azimuth - -; #X floatatom 211 335 0 0 0 3 actual_elevation - -; #X floatatom 221 314 7 0 0 1 actual_spreading - -; #X text 443 202 2 For vbap \, give azimuth and elevation 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 msg 25 115 define_loudspeakers 2 -45 45 -135 135; #X text 24 64 loudspeaker position definition can also be sent directly to a vbap object. This changes the setup information only in a single vbap object.; #X text 441 59 1 Use the define_loudspeakers object or message 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 msg 51 135 define_loudspeakers 3 -45 45 -135 135 32 5 94 34 34 11 ; #X obj 152 202 hsl 100 13 0 360 0 0 empty empty azimuth 10 7 0 10 -262144 -1 -1 0 1; #X obj 190 220 hsl 100 13 0 360 0 0 empty empty elevation 10 7 0 10 -262144 -1 -1 0 1; #X floatatom 227 257 5 0 0 2 - - -; #X obj 230 240 hsl 100 13 0 100 0 0 empty empty spread 10 7 0 10 -262144 -1 -1 0 1; #X text 149 163 to output updated values; #X obj 102 287 vbap 90 0 30; #X obj 83 185 metro 100; #X obj 83 163 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #N canvas 283 22 628 620 simple 0; #X floatatom 159 198 5 0 0 2 - - -; #X floatatom 112 425 10 0 0 0 - - -; #X floatatom 181 425 10 0 0 0 - - -; #X floatatom 209 349 0 0 0 3 actual_azimuth - -; #X floatatom 221 315 0 0 0 3 actual_elevation - -; #X floatatom 231 294 7 0 0 1 actual_spreading - -; #X obj 162 182 hsl 100 13 -180 180 0 1 empty empty azimuth 10 7 0 10 -262144 -1 -1 1500 1; #X floatatom 237 237 5 0 0 2 - - -; #X obj 240 220 hsl 100 13 0 100 0 1 empty empty spread 10 7 0 10 -262144 -1 -1 700 1; #X text 130 134 to output updated values; #X obj 112 155 metro 100; #X obj 112 133 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X text 197 200 (ignore elevation in 2D \, that's for 3D); #X obj 63 524 *~; #X obj 92 525 *~; #X msg 454 145 dsp 1; #X obj 454 169 send pd; #X floatatom 250 425 10 0 0 0 - - -; #X floatatom 319 425 10 0 0 0 - - -; #X obj 123 524 *~; #X obj 152 525 *~; #X msg 17 48 define_loudspeakers 2 -135 -45 0 45 135; #X text 263 37 Define 2D speaker arrangement with speakers at -135 \, -45 \, 0 \, 45 and 135 degree positions (0 degrees is the center front). This is a classic 5.1 setup.; #X floatatom 389 425 10 0 0 0 - - -; #X obj 72 558 dac~ 1 2 3 4 5; #X obj 182 525 *~; #X obj 112 267 vbap 0 0 30; #X obj 112 376 route 0 1 2 3 4; #X obj 13 396 *~ 0.2; #X obj 13 374 noise~; #X connect 0 0 26 1; #X connect 1 0 13 1; #X connect 2 0 14 1; #X connect 6 0 0 0; #X connect 7 0 26 3; #X connect 8 0 7 0; #X connect 10 0 26 0; #X connect 11 0 10 0; #X connect 13 0 24 0; #X connect 14 0 24 1; #X connect 15 0 16 0; #X connect 17 0 19 1; #X connect 18 0 20 1; #X connect 19 0 24 2; #X connect 20 0 24 3; #X connect 21 0 26 0; #X connect 23 0 25 1; #X connect 25 0 24 4; #X connect 26 0 27 0; #X connect 26 1 3 0; #X connect 26 2 4 0; #X connect 26 3 5 0; #X connect 27 0 1 0; #X connect 27 1 2 0; #X connect 27 2 17 0; #X connect 27 3 18 0; #X connect 27 4 23 0; #X connect 28 0 13 0; #X connect 28 0 14 0; #X connect 28 0 19 0; #X connect 28 0 20 0; #X connect 28 0 25 0; #X connect 29 0 28 0; #X restore 539 378 pd simple 5.1 example; #X text 337 238 (0-100); #X text 297 217 (0-360); #X text 257 199 (0-360); #X text 21 490 Vector Base Amplitude Panning; #X text 241 489 (C) 1998-2003 \, 2006 Ville Pulkki; #X obj 669 417 pddp/helplink cyclone/matrix~; #X text 448 417 You can also use [vbap] to control:; #X text 443 351 see:; #X text 443 332 For an example of how to use vbap with; #X obj 473 351 pddp/pddplink examples/vbap-demo.pd; #X obj 678 332 pddp/helplink iemmatrix/matrix~; #X connect 0 0 24 1; #X connect 1 0 24 2; #X connect 2 0 24 0; #X connect 3 0 4 0; #X connect 3 1 5 0; #X connect 3 2 6 0; #X connect 3 3 7 0; #X connect 15 0 24 0; #X connect 18 0 24 0; #X connect 19 0 0 0; #X connect 20 0 1 0; #X connect 21 0 24 3; #X connect 22 0 21 0; #X connect 24 0 3 0; #X connect 24 1 11 0; #X connect 24 2 12 0; #X connect 24 3 13 0; #X connect 25 0 24 0; #X connect 26 0 25 0; vbap-1.0.3.2/vbap-meta.pd0000644000076500007650000000040011717347355013471 0ustar hanshans#N canvas 10 10 200 200 10; #N canvas 20 20 420 300 META 0; #X text 10 30 NAME vbap; #X text 10 50 AUTHOR Ville Pulkki; #X text 10 70 DESCRIPTION spatialization using Vector Based Amplitude Panning; #X text 10 90 VERSION 1.0.3.2; #X restore 10 10 pd META; vbap-1.0.3.2/vbap.c0000644000076500007650000005054111772146602012370 0ustar hanshans/* vbap.c written by Ville Pulkki 1999-2003 Helsinki University of Technology and University of California at Berkeley See copyright in file with name LICENSE.txt */ // Indicate that we are within VBAP object (specific to include define_loudspeakers content within vbap) #define VBAP_OBJECT #include "vbap.h" #include "s_stuff.h" // Function prototypes static void new_spread_dir(t_vbap *x, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3]); static void new_spread_base(t_vbap *x, t_float spreaddir[3], t_float vscartdir[3]); static void *vbap_class; static void vect_cross_prod(t_float v1[3], t_float v2[3],t_float v3[3]); static void additive_vbap(t_float *final_gs, t_float cartdir[3], t_vbap *x); static void vbap_bang(t_vbap *x); static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av); #ifndef PD /* Max */ /* these are for getting data from a cold inlet on Max/MSP, in Pd you use t_floatinlet_new() in new() */ void vbap_ft1(t_vbap *x, double n); void vbap_ft2(t_vbap *x, double n); void vbap_in3(t_vbap *x, long n); void vbap_ft4(t_vbap *x, double g); #endif static void spread_it(t_vbap *x, t_float *final_gs); static void *vbap_new(t_float azi, t_float ele, t_float spread); static void vbap(t_float g[3], long ls[3], t_vbap *x); static void angle_to_cart(t_float azi, t_float ele, t_float res[3]); static void cart_to_angle(t_float cvec[3], t_float avec[3]); /***************************************************** INCLUDE ALL define_loudspeakers functions directly into VBAP ******************************************************/ #include "define_loudspeakers.c" /***************************************************** Max Object Assist ******************************************************/ #ifndef PD /* Max */ void vbap_assist(t_vbap *x, void *b, long m, long a, char *s) { char*mess = "unknown"; if (m == ASSIST_INLET) { switch(a) { case 0 : mess = "bang to calc and output vbap gains. loudspeakers definition"; break; case 1 : mess = "panning angle azimuth"; break; case 2 : mess = "panning angle elevation"; break; case 3 : mess = "spread amount"; break; case 4 : mess = "gain control"; break; } } else { switch(a) { case 0 : mess = "vbap gains"; break; case 1 : mess = "panning angle azimuth"; break; case 2 : mess = "panning angle elevation"; break; case 3 : mess = "spread amount"; break; case 4 : mess = "gain control"; break; } } sprintf(s,mess); } #endif /* Max */ /* above are the prototypes for the methods/procedures/functions you will use */ /*--------------------------------------------------------------------------*/ #ifdef PD void vbap_setup(void) { vbap_class = class_new(gensym("vbap"), (t_newmethod)vbap_new, 0, (short)sizeof(t_vbap), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(vbap_class, (t_method)vbap_bang); /* these are for getting data from a cold inlet on Max/MSP, in Pd you use floatinlet_new() in new() addftx((t_method)vbap_ft1, 1); addftx((t_method)vbap_ft2, 2); addftx((t_method)vbap_in3, 3); addftx((t_method)vbap_ft4, 4); */ class_addmethod(vbap_class, (t_method)vbap_matrix, gensym("loudspeaker-matrices"), A_GIMME, 0); // define_loudspeaker messages class_addmethod(vbap_class, (t_method)vbap_def_ls, gensym("define-loudspeakers"), A_GIMME, 0); class_addmethod(vbap_class, (t_method)vbap_def_ls, gensym("define_loudspeakers"), A_GIMME, 0); class_addmethod(vbap_class, (t_method)def_ls_read_directions, gensym("ls-directions"), A_GIMME, 0); class_addmethod(vbap_class, (t_method)def_ls_read_triplets, gensym("ls-triplets"), A_GIMME, 0); logpost(NULL, 4, VBAP_VERSION); } #else /* MAX */ void main(void) { setup((t_messlist **)&vbap_class, (method)vbap_new, 0L, (short)sizeof(t_vbap), 0L, A_DEFLONG,A_DEFLONG,A_DEFLONG, 0); addbang((method)vbap_bang); addftx((method)vbap_ft1, 1); addftx((method)vbap_ft2, 2); addftx((method)vbap_in3, 3); addftx((method)vbap_ft4, 4); addmess((method)vbap_matrix, "loudspeaker-matrices", A_GIMME, 0); addmess((method)traces, "enabletrace", A_LONG, 0); // define_loudspeaker messages addmess((method)vbap_def_ls, "define-loudspeakers", A_GIMME, 0); addmess((method)vbap_def_ls, "define_loudspeakers", A_GIMME, 0); addmess((method)def_ls_read_directions, "ls-directions", A_GIMME, 0); addmess((method)def_ls_read_triplets, "ls-triplets", A_GIMME, 0); addmess((method)vbap_assist,"assist",A_CANT,0); post(VBAP_VERSION); } /* these are for getting data from a cold inlet on Max/MSP, in Pd you use floatinlet_new() in new() */ /*--------------------------------------------------------------------------*/ // panning angle azimuth void vbap_ft1(t_vbap *x, double n) { x->x_azi = (float) n; } /*--------------------------------------------------------------------------*/ // panning angle elevation void vbap_ft2(t_vbap *x, double n) { x->x_ele = (float) n; } /*--------------------------------------------------------------------------*/ // spread amount void vbap_in3(t_vbap *x, long n) { x->x_spread = (n<0) ? 0 : (n>100) ? 100 : n; } /*--------------------------------------------------------------------------*/ // gain control void vbap_ft4(t_vbap *x, double g) { x->x_gain = g; } #endif /* MAX */ /*--------------------------------------------------------------------------*/ // create new instance of object... static void *vbap_new(t_float azi, t_float ele, t_float spread) { #ifdef PD t_vbap *x = (t_vbap *)newobject(vbap_class); floatinlet_new(&x->x_obj, &x->x_azi); floatinlet_new(&x->x_obj, &x->x_ele); floatinlet_new(&x->x_obj, &x->x_spread); x->x_outlet0 = outlet_new(&x->x_obj, &s_float); x->x_outlet1 = outlet_new(&x->x_obj, &s_float); x->x_outlet2 = outlet_new(&x->x_obj, &s_float); x->x_outlet3 = outlet_new(&x->x_obj, &s_float); #else /* Max */ t_vbap *x = (t_vbap *)newobject(vbap_class); floatin(x,4); floatin(x,3); floatin(x,2); floatin(x,1); x->x_outlet4 = floatout(x); x->x_outlet3 = floatout(x); x->x_outlet2 = floatout(x); x->x_outlet1 = floatout(x); x->x_outlet0 = listout(x); #endif /* PD */ x->x_spread_base[0] = 0.0; x->x_spread_base[1] = 1.0; x->x_spread_base[2] = 0.0; x->x_lsset_available =0; x->x_azi = azi; x->x_ele = ele; x->x_spread = spread; return(x); /* return a reference to the object instance */ } static void angle_to_cart(t_float azi, t_float ele, t_float res[3]) // converts angular coordinates to cartesian { res[0] = cos(azi * atorad) * cos( ele * atorad); res[1] = sin( azi * atorad) * cos( ele * atorad); res[2] = sin( ele * atorad); } static void cart_to_angle(t_float cvec[3], t_float avec[3]) // converts cartesian coordinates to angular { //float tmp, tmp2, tmp3, tmp4; //float power; t_float dist, atan_y_per_x, atan_x_pl_y_per_z; t_float azi, ele; if(cvec[0]==0.0) atan_y_per_x = M_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.0; 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 = -M_PI/2.0; else atan_x_pl_y_per_z = M_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(t_float g[3], long ls[3], t_vbap *x) { /* calculates gain factors using loudspeaker setup and given direction */ t_float power; int i,j,k, gains_modified; t_float small_g; t_float big_sm_g, gtmp[3]; long winner_set = 0; t_float cartdir[3]; t_float new_cartdir[3]; t_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 if(x->x_azi > 360.0 || x->x_azi < -360.0) x->x_azi = fmod(x->x_azi, 360.0); if(x->x_azi > 180.0) x->x_azi -= 360.0; if(x->x_azi < -179.0) x->x_azi += 360.0; // transferring the elevation to a decent value if(dim == 3){ if(x->x_ele > 360.0 || x->x_ele < -360.0) x->x_ele = fmod(x->x_ele, 360.0); if(x->x_ele > 180.0) x->x_ele -= 360.0; if(x->x_ele < -179.0) x->x_ele += 360.0; } else x->x_ele = 0.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;ix_lsset_amount;i++) { small_g = 10000000.0; neg_g_am = 3; for(j=0;jx_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. // gains_modified=0; for(i=0;ix_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]; if(dim==3){ 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]; } else new_cartdir[2] = 0; cart_to_angle(new_cartdir,new_angle_dir); x->x_azi = (new_angle_dir[0] ); post("[vbap] use azimuth %g",x->x_azi ); x->x_ele = (new_angle_dir[1]); } //} 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 vect_cross_prod(t_float v1[3], t_float v2[3], t_float v3[3]) // vector cross product { t_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(t_float *final_gs, t_float cartdir[3], t_vbap *x) // calculates gains to be added to previous gains, used in // multiple direction panning (source spreading) { t_float power; int i,j,k, gains_modified; t_float small_g; t_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; t_float g[3] = {0,0,0}; long ls[3] = {0,0,0}; big_sm_g = -100000.0; best_neg_g_am=3; for(i=0;ix_lsset_amount;i++){ small_g = 10000000.0; neg_g_am = 3; for(j=0;jx_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;ix_azi+90.0, 0, spread_base); gamma = acos(vscartdir[0] * spread_base[0] + vscartdir[1] * spread_base[1] + vscartdir[2] * spread_base[2])/M_PI*180; } beta = 180 - gamma; b=sin(x->x_spread * M_PI / 180) / sin(beta * M_PI / 180); a=sin((180- x->x_spread - beta) * M_PI / 180) / sin (beta * M_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_vbap *x, t_float spreaddir[3], t_float vscartdir[3]) // subroutine for spreading { t_float d; t_float power; d = cos(x->x_spread/180*M_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_vbap *x, t_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 { t_float vscartdir[3]; t_float spreaddir[16][3]; t_float spreadbase[16][3]; long i, spreaddirnum; t_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); vect_cross_prod(x->x_spread_base, vscartdir, spreadbase[1]); // four orthogonal dirs vect_cross_prod(spreadbase[1], vscartdir, spreadbase[2]); vect_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;ix_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;ix_spread > 70) for(i=0;ix_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;ix_ls_amount;i++){ power += final_gs[i] * final_gs[i]; } power = sqrt(power); for(i=0;ix_ls_amount;i++){ final_gs[i] /= power; } } static void vbap_bang(t_vbap *x) // top level, vbap gains are calculated and outputted { Atom at[MAX_LS_AMOUNT]; t_float g[3]; long ls[3]; long i; t_float *final_gs = (t_float *) getbytes(x->x_ls_amount * sizeof(t_float)); if(x->x_lsset_available ==1) { vbap(g,ls, x); for(i=0;ix_ls_amount;i++) final_gs[i]=0.0; for(i=0;ix_dimension;i++) { final_gs[ls[i]-1]=g[i]; } if(x->x_spread != 0) { spread_it(x,final_gs); } for(i=0;ix_ls_amount;i++) { #ifdef PD SETFLOAT(&at[0], (t_float)i); SETFLOAT(&at[1], (t_float)final_gs[i]); outlet_list(x->x_obj.ob_outlet, &s_list, 2, at); #else /* Max */ SETLONG(&at[0], i); SETFLOAT(&at[1], final_gs[i]*x->x_gain); // freeverb gain is applied here outlet_list(x->x_outlet0, 0L, 2, at); #endif /* PD */ } outlet_float(x->x_outlet1, x->x_azi); outlet_float(x->x_outlet2, x->x_ele); outlet_int(x->x_outlet3, x->x_spread); //outlet_int(x->x_outlet4, x->x_gain); } else error("vbap: Configure loudspeakers first!"); freebytes(final_gs, x->x_ls_amount * sizeof(t_float)); // bug fix added 9/00 } /*--------------------------------------------------------------------------*/ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av) // read in loudspeaker matrices { int datapointer = 0; if(ac>0) { int d = 0; /*if(av[datapointer].a_type == A_LONG) d = av[datapointer++].a_w.w_long; else*/ if(av[datapointer].a_type == A_FLOAT) d = (long)av[datapointer++].a_w.w_float; else { error("vbap: Dimension NaN"); x->x_lsset_available=0; return; } if (d!=2 && d!=3) { error("vbap %s: Dimension can be only 2 or 3",s->s_name); x->x_lsset_available=0; return; } x->x_dimension = d; x->x_lsset_available=1; } else { error("vbap %s: bad empty parameter list",s->s_name); x->x_lsset_available=0; return; } if(ac>1) { long a = 0; /*if(av[datapointer].a_type == A_LONG) a = av[datapointer++].a_w.w_long; else*/ if(av[datapointer].a_type == A_FLOAT) a = (long) av[datapointer++].a_w.w_float; else { error("vbap: ls_amount NaN"); x->x_lsset_available=0; return; } x->x_ls_amount = a; } long counter = (ac - 2) / ((x->x_dimension * x->x_dimension*2) + x->x_dimension); x->x_lsset_amount=counter; if(counter==0) { error("vbap %s: not enough parameters",s->s_name); x->x_lsset_available=0; return; } long setpointer=0; long i; while(counter-- > 0) { for(i=0; i < x->x_dimension; i++) { # ifdef PD if(av[datapointer].a_type == A_FLOAT) { x->x_lsset[setpointer][i]=(long)av[datapointer++].a_w.w_float; } else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; } # else /* Max */ if(av[datapointer].a_type == A_LONG) { x->x_lsset[setpointer][i]=av[datapointer++].a_w.w_long; } else { error("vbap %s: param %d is not an in",s->s_name,datapointer); x->x_lsset_available=0; return; } # endif /* PD */ } for(i=0; i < x->x_dimension*x->x_dimension; i++) { if(av[datapointer].a_type == A_FLOAT) { x->x_set_inv_matx[setpointer][i]=av[datapointer++].a_w.w_float; } else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; } } for(i=0; i < x->x_dimension*x->x_dimension; i++) { if(av[datapointer].a_type == A_FLOAT) { x->x_set_matx[setpointer][i]=av[datapointer++].a_w.w_float; } else { error("vbap %s: param %d is not a float",s->s_name,datapointer); x->x_lsset_available=0; return; } } setpointer++; } if (_enable_trace) post("vbap: Loudspeaker setup configured!"); } vbap-1.0.3.2/vbap.h0000644000076500007650000001032511661104502012357 0ustar hanshans#ifndef VBAP_H #define VBAP_H #include #include "m_pd.h" #include "max2pd.h" #ifndef M_PI // don't know where it is in win32, so add it here #define M_PI 3.14159265358979323846264338327950288 /* pi */ #endif #define MAX_LS_SETS 100 // maximum number of loudspeaker sets (triplets or pairs) allowed #define MAX_LS_AMOUNT 55 // maximum amount of loudspeakers, can be increased #define MIN_VOL_P_SIDE_LGTH 0.01 #define VBAP_VERSION "vbap - v1.0.3.2 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006 (Pd port by HCS)" #define DFLS_VERSION "define_loudspeakers - v1.0.3.2 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006" static t_float rad2ang = 360.0 / ( 2.0f * M_PI ); static t_float atorad = (2.0f * M_PI) / 360.0f ; #ifdef VBAP_OBJECT // We are inside vbap object, so sending matrix from define_loudspeakers is a simple call to the vbap receiver... #define sendLoudspeakerMatrices(x,list_length, at) \ vbap_matrix(x, gensym("loudspeaker-matrices"),list_length, at); \ vbap_bang(x) #else // We are inside define_loudspeaker object, send matrix to outlet #define sendLoudspeakerMatrices(x,list_length, at) \ outlet_anything(x->x_outlet0, gensym("loudspeaker-matrices"), list_length, at); #endif /* A struct for a loudspeaker instance */ typedef struct { // distance value is 1.0 == unit vectors t_float x; // cartesian coordinates t_float y; t_float z; t_float azi; // polar coordinates t_float ele; int channel_nbr; // which speaker channel number } t_ls; /* A struct for all loudspeaker sets */ typedef struct t_ls_set { int ls_nos[3]; // channel numbers t_float inv_mx[9]; // inverse 3x3 or 2x2 matrix struct t_ls_set *next; // next set (triplet or pair) } t_ls_set; #ifdef VBAP_OBJECT typedef struct vbap /* This defines the object as an entity made up of other things */ { t_object x_obj; t_float x_azi; // panning direction azimuth t_float x_ele; // panning direction elevation void *x_outlet0; /* outlet creation - inlets are automatic */ void *x_outlet1; void *x_outlet2; void *x_outlet3; void *x_outlet4; t_float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set 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 # ifdef PD t_float x_spread; // speading amount of virtual source (0-100) # else /* Max */ long x_spread; // speading amount of virtual source (0-100) double x_gain; // general gain control (0-2) # endif /* PD */ t_float x_spread_base[3]; // used to create uniform spreading // define_loudspeaker data long x_ls_read; // 1 if loudspeaker directions have been read long x_triplets_specified; // 1 if loudspeaker triplets have been chosen t_ls x_ls[MAX_LS_AMOUNT]; // loudspeakers t_ls_set *x_ls_set; // loudspeaker sets long x_def_ls_amount; // number of loudspeakers long x_def_ls_dimension; // 2 (horizontal arrays) or 3 (3d setups) } t_vbap; // define loudspeaker data type... typedef t_vbap t_def_ls; #else /* define_loudspeakers maxmsp object */ typedef struct { t_object x_obj; /* gotta say this... it creates a reference to your object */ long x_ls_read; // 1 if loudspeaker directions have been read long x_triplets_specified; // 1 if loudspeaker triplets have been chosen t_ls x_ls[MAX_LS_AMOUNT]; // loudspeakers t_ls_set *x_ls_set; // loudspeaker sets void *x_outlet0; /* outlet creation - inlets are automatic */ long x_def_ls_amount; // number of loudspeakers long x_def_ls_dimension; // 2 (horizontal arrays) or 3 (3d setups) } t_def_ls; #endif /* VBAP_OBJECT */ # ifndef PD /** Enable/Disable traces */ static bool _enable_trace = false; void traces(t_def_ls *x, long n) { _enable_trace = n ? true : false;} #endif /* ! PD */ #endif