diff --git a/externals/pd-l2ork-TODO.txt b/externals/pd-l2ork-TODO.txt index 72623d88525bfcb03e21a244123958a1b0584e4f..5a1da76da68364222eb739d79739f7150a0ad039 100644 --- a/externals/pd-l2ork-TODO.txt +++ b/externals/pd-l2ork-TODO.txt @@ -1,5 +1,5 @@ Diff status between pd-l2ork externals source tree and main community pd svn -AS OF October 7, 2014 +AS OF October 8, 2014 DONE: (*denotes unique changes) creb @@ -16,6 +16,7 @@ pdp_opencv pidip postlude sigpack +vbap zexy MERGE: diff --git a/externals/vbap/CHANGELOG.txt b/externals/vbap/CHANGELOG.txt new file mode 100644 index 0000000000000000000000000000000000000000..9956b0f3f6cadd0fe6b8409523078836d7235728 --- /dev/null +++ b/externals/vbap/CHANGELOG.txt @@ -0,0 +1,5 @@ +14 Aug. 2014 update from version 1.0.3.2 to version 1.1 + +- changed vbap to allocate memory dynamically, to eliminate crash-producing memory overwrites when larger speaker configurations were defined (e.g. on OSX for speakers > 13 in 3D) z.settel +- eliminated a post to the console reporting azimuth updates + diff --git a/externals/vbap/LICENSE.txt b/externals/vbap/LICENSE.txt index 7522f1cf706f827278d30456e28d4cc18680822e..94290493ab0591ca6de10529dc7d3811174bf7aa 100644 --- a/externals/vbap/LICENSE.txt +++ b/externals/vbap/LICENSE.txt @@ -1,4 +1,9 @@ -Copyright (c) 1998-2010 Ville Pulkki. All rights reserved. +Copyright (c) 1998-2010 Ville Pulkki + 2002, Juha Vehviläinen + 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 diff --git a/externals/vbap/Makefile b/externals/vbap/Makefile index d484487791e9b465c84f6cbac3050d59350e64b4..99be87bf86f3341cd5e9a4025be29fae683fa88f 100644 --- a/externals/vbap/Makefile +++ b/externals/vbap/Makefile @@ -1,10 +1,11 @@ -## Pd library template version 1.0.6 +## Pd library template version 1.0.14 # 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 +# 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 @@ -12,10 +13,10 @@ SOURCES = vbap.c rvbap.c define_loudspeakers.c 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 +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 = +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, @@ -23,6 +24,9 @@ MANUAL = # 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 + #------------------------------------------------------------------------------# @@ -31,9 +35,11 @@ EXTRA_DIST = define_loudspeakers.h max2pd.h vbap.h makefile.irix so_locations # #------------------------------------------------------------------------------# -CFLAGS = -I"$(PD_INCLUDE)/pd" -Wall -W -g -LDFLAGS = -LIBS = +ALL_CFLAGS = -I"$(PD_INCLUDE)" +ALL_LDFLAGS = +SHARED_LDFLAGS = +ALL_LIBS = + #------------------------------------------------------------------------------# # @@ -41,12 +47,17 @@ LIBS = # #------------------------------------------------------------------------------# +# 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) -CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' +ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' -PD_INCLUDE = $(PD_PATH)/include +PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib @@ -70,6 +81,7 @@ ifeq ($(UNAME),Darwin) 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 @@ -79,14 +91,16 @@ ifeq ($(UNAME),Darwin) 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 - CFLAGS := $(IPHONE_CFLAGS) $(OPT_CFLAGS) $(CFLAGS) - LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) - LIBS += -lc + 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 @@ -94,30 +108,74 @@ ifeq ($(UNAME),Darwin) 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) +# Starting with Xcode 4.0, the PowerPC compiler is not installed by default + ifeq ($(wildcard /usr/llvm-gcc-4.2/libexec/gcc/powerpc*), ) + FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + else + FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + endif endif - CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include - LDFLAGS += $(FAT_FLAGS) -bundle -undefined dynamic_lookup -L/sw/lib + ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include # if the 'pd' binary exists, check the linking against it to aid with stripping - LDFLAGS += $(shell test -e $(PD_PATH)/bin/pd && echo -bundle_loader $(PD_PATH)/bin/pd) - LIBS += -lc + BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) + ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -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 = so + SHARED_EXTENSION = so + OS = android + PD_PATH = /usr + NDK_BASE := /opt/android-ndk + NDK_PLATFORM_LEVEL ?= 5 + NDK_ABI=arm + NDK_COMPILER_VERSION = 4.6 + NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_LEVEL)/arch-$(NDK_ABI) + NDK_UNAME:=$(shell uname -s | tr '[A-Z]' '[a-z]') + ifeq ($(NDK_ABI),x86) + HOST = i686-linux-android + NDK_TOOLCHAIN = $(NDK_ABI)-$(NDK_COMPILER_VERSION) + else + HOST = $(NDK_ABI)-linux-androideabi + NDK_TOOLCHAIN = $(HOST)-$(NDK_COMPILER_VERSION) + endif + NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/$(NDK_TOOLCHAIN)/prebuilt/$(NDK_UNAME)-$(NDK_PROCESSOR) + CC := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-gcc --sysroot=$(NDK_SYSROOT) + LD := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-ld + 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/$(HOST)-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 - CFLAGS += -fPIC - LDFLAGS += -Wl,--export-dynamic -shared -fPIC - LIBS += -lc + 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 @@ -126,12 +184,14 @@ ifeq ($(UNAME),GNU) 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 - CFLAGS += -fPIC - LDFLAGS += -Wl,--export-dynamic -shared -fPIC - LIBS += -lc + 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 @@ -140,12 +200,14 @@ ifeq ($(UNAME),GNU/kFreeBSD) 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 - CFLAGS += -fPIC - LDFLAGS += -Wl,--export-dynamic -shared -fPIC - LIBS += -lc + 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 @@ -153,12 +215,14 @@ ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll + SHARED_EXTENSION = dll OS = cygwin - PD_PATH = $(cygpath $(PROGRAMFILES))/pd + PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer - CFLAGS += - LDFLAGS += -Wl,--export-dynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" - LIBS += -lc -lpd + 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 @@ -166,12 +230,17 @@ 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) + 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 - CFLAGS += -mms-bitfields - LDFLAGS += -s -shared -Wl,--enable-auto-import - LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 + ALL_CFLAGS += -mms-bitfields + ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import + SHARED_LDFLAGS += -shared + ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ + -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif @@ -179,42 +248,61 @@ endif # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) -CFLAGS += $(OPT_CFLAGS) +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-exec install-examples install-manual clean dist etags $(LIBRARY_NAME) +.PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) -all: $(SOURCES:.c=.$(EXTENSION)) +all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c - $(CC) $(CFLAGS) -o "$*.o" -c "$*.c" + $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" -%.$(EXTENSION): %.o - $(CC) $(LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(LIBS) +%.$(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) $(LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(LIBS) +$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o + $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ + $(LIBRARY_NAME).o lib$(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) $(ALL_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)) install-doc install-examples install-manual +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-exec +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) @@ -241,12 +329,19 @@ install-manual: $(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) + -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 @@ -262,7 +357,7 @@ $(DISTBINDIR): libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) - $(INSTALL_DATA) $(SOURCES) $(DISTBINDIR) + $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) @@ -281,6 +376,16 @@ dist: $(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 $(wildcard $(LIBRARY_NAME).c))" || \ + $(INSTALL_DATA) $(LIBRARY_NAME).c $(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))" || \ @@ -297,6 +402,11 @@ dist: $(DISTDIR) 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 @@ -309,23 +419,39 @@ dpkg-source: rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) -etags: - etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h +etags: TAGS + +TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + etags $(wildcard $(PD_INCLUDE)/*.h) + etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + 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)" + @echo "NDK_TOOLCHAIN: $(NDK_TOOLCHAIN)" + @echo "NDK_BASE: $(NDK_BASE)" + @echo "NDK_SYSROOT: $(NDK_SYSROOT)" diff --git a/externals/vbap/define_loudspeakers.c b/externals/vbap/define_loudspeakers.c index b2fd3512cc785e7eb9850d90247831e20973a5de..16c5b62bcf1c674e611f06bbe818cc43772c8fd6 100644 --- a/externals/vbap/define_loudspeakers.c +++ b/externals/vbap/define_loudspeakers.c @@ -14,14 +14,14 @@ See copyright in file with name LICENSE.txt */ // 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_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); + logpost(NULL,1, DFLS_VERSION); } # else /* Max */ void main(void) @@ -167,16 +167,21 @@ static void def_ls_read_directions(t_def_ls *x, t_symbol *s, int ac, Atom *av) static void ls_angles_to_cart(t_ls *ls) // convert angular direction to cartesian { - float azi = ls->azi; - float ele = ls->ele; - ls->x = cos((float) azi * atorad) * cos((float) ele * atorad); - ls->y = sin((float) azi * atorad) * cos((float) ele * atorad); - ls->z = sin((float) ele * atorad); + 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) { + + + //post("def_ls_new: AC = %d", ac); + + // s is object name (we ignore it) t_def_ls *x = (t_def_ls *)newobject(def_ls_class); @@ -195,6 +200,9 @@ static void *def_ls_new(t_symbol *s, int ac, Atom *av) 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 + + logpost(NULL,3, "vbap_def_ls: %ld-D configuration with %ld speakers", x->x_def_ls_dimension, x->x_def_ls_amount ); + def_ls_bang(x); // calculate and send matrix to vbap } @@ -205,7 +213,9 @@ static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av) 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 */ + + 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) @@ -227,7 +237,7 @@ static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av) int i; for(i=0; i < x->x_def_ls_amount;i++) { - float azi = 0; + 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; } @@ -236,7 +246,7 @@ static void initContent_ls_directions(t_def_ls *x,int ac,Atom*av) pointer++; - float ele = 0; // in 2d elevation is zero + 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; @@ -279,10 +289,10 @@ static void choose_ls_triplets(t_def_ls *x) int connections[MAX_LS_AMOUNT][MAX_LS_AMOUNT]; //float angles[MAX_LS_AMOUNT]; //int sorted_angles[MAX_LS_AMOUNT]; - float distance_table[((MAX_LS_AMOUNT * (MAX_LS_AMOUNT - 1)) / 2)]; + 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)]; - float distance; + 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; @@ -404,11 +414,11 @@ static void choose_ls_triplets(t_def_ls *x) 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 */ { - float invdet; + t_float invdet; t_ls *lp1, *lp2, *lp3; - float invmx[9]; + t_float invmx[9]; int i,j; - float tmp; + t_float tmp; int any_ls_inside, this_inside; lp1 = &(lss[a]); @@ -463,6 +473,9 @@ static void add_ldsp_triplet(int i, int j, int k, t_def_ls *x) trip_ptr = trip_ptr->next; } trip_ptr = (struct t_ls_set*) getbytes (sizeof (struct t_ls_set)); + + //post("add_ldsp_triplet getbytes: %ld", sizeof (struct t_ls_set)); + if(prev == NULL) x->x_ls_set = trip_ptr; else @@ -476,10 +489,10 @@ static void add_ldsp_triplet(int i, int j, int k, t_def_ls *x) -float vec_angle(t_ls v1, t_ls v2) +t_float vec_angle(t_ls v1, t_ls v2) // angle between two loudspeakers { - float inner= ((v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)/ + 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; @@ -488,26 +501,26 @@ float vec_angle(t_ls v1, t_ls v2) return fabs( acos( inner)); } -float vec_length(t_ls v1) +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)); } -float vec_prod(t_ls v1, t_ls v2) +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); } -float vol_p_side_lgth(int i, int j,int k, t_ls lss[MAX_LS_AMOUNT] ) +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. */ - float volper, lgth; + t_float volper, lgth; t_ls xprod; ls_cross_prod(lss[i], lss[j], &xprod); volper = fabsf(vec_prod(xprod, lss[k])); @@ -524,7 +537,7 @@ static void ls_cross_prod(t_ls v1,t_ls v2, t_ls *res) // vector cross product { - float length; + 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); @@ -543,9 +556,11 @@ static int lines_intersect(int i,int j,int k,int l,t_ls lss[MAX_LS_AMOUNT]) t_ls v1; t_ls v2; t_ls v3, neg_v3; - //float angle; - float dist_ij,dist_kl,dist_iv3,dist_jv3,dist_inv3,dist_jnv3; - float dist_kv3,dist_lv3,dist_knv3,dist_lnv3; + //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); @@ -567,17 +582,17 @@ static int lines_intersect(int i,int j,int k,int l,t_ls lss[MAX_LS_AMOUNT]) 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) <= 0.01 || fabsf(dist_jv3) <= 0.01 || - fabsf(dist_kv3) <= 0.01 || fabsf(dist_lv3) <= 0.01 || - fabsf(dist_inv3) <= 0.01 || fabsf(dist_jnv3) <= 0.01 || - fabsf(dist_knv3) <= 0.01 || fabsf(dist_lnv3) <= 0.01 ) + 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)) <= 0.01 ) && - (fabsf(dist_kl - (dist_kv3 + dist_lv3)) <= 0.01)) || - ((fabsf(dist_ij - (dist_inv3 + dist_jnv3)) <= 0.01) && - (fabsf(dist_kl - (dist_knv3 + dist_lnv3)) <= 0.01 ))) { + 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); @@ -587,12 +602,15 @@ 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) /* Calculates the inverse matrices for 3D */ { - float invdet; + t_float invdet; t_ls *lp1, *lp2, *lp3; - float *invmx; - //float *ptr; + 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; + + unsigned long triplet_amount = 0, /*ftable_size,*/i,pointer,list_length=0; + + Atom *at; t_ls *lss = x->x_ls; @@ -611,7 +629,8 @@ static void calculate_3x3_matrixes(t_def_ls *x) 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; @@ -654,11 +673,14 @@ static void calculate_3x3_matrixes(t_def_ls *x) 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)); + + freebytes(at, list_length*sizeof(Atom)); } @@ -667,17 +689,17 @@ 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*/ { - //float atorad = (2 * 3.1415927 / 360) ; + //t_float atorad = (2 * 3.1415927 / 360) ; int i,j; - //float w1,w2; - //float p1,p2; + //t_float w1,w2; + //t_float p1,p2; int sorted_lss[MAX_LS_AMOUNT]; int exist[MAX_LS_AMOUNT]; int amount=0; - float inv_mat[MAX_LS_AMOUNT][4]; // In 2-D ls amount == max amount of LS pairs - float mat[MAX_LS_AMOUNT][4]; - //float *ptr; - //float *ls_table; + 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; @@ -718,7 +740,8 @@ static void choose_ls_tuplets(t_def_ls *x) // Output list_length= amount * 10 + 2; at= (Atom *) getbytes(list_length*sizeof(Atom)); - + //post("choose_ls_tuplets getbytes: %ld", list_length*sizeof(Atom)); + SETLONG(&at[0], x->x_def_ls_dimension); SETLONG(&at[1], x->x_def_ls_amount); pointer=2; @@ -753,7 +776,9 @@ static void choose_ls_tuplets(t_def_ls *x) pointer++; } } - sendLoudspeakerMatrices(x,list_length, at); + //post("choose_ls_tuplets: before call to sendLoudspeakerMatrices"); + + sendLoudspeakerMatrices(x,list_length, at); //outlet_anything(x->x_outlet0, gensym("loudspeaker-matrices"), list_length, at); freebytes(at, list_length*sizeof(Atom)); } @@ -762,10 +787,10 @@ 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 { - float tmp, tmp_azi; -// float rad2ang = 360.0f / ( 2.0f * M_PI ); + t_float tmp, tmp_azi; +// t_float rad2ang = 360.0f / ( 2.0f * M_PI ); - //float x,y; + //t_float x,y; /* Transforming angles between -180 and 180 */ int i; for (i=0;i<ls_amount;i++) @@ -793,22 +818,22 @@ for (i=0;i<ls_amount;i++) } sorted_lss[i]=index; tmp_azi = (lss[index].azi); - lss[index].azi = (tmp_azi + (float) 4000.0); + lss[index].azi = (tmp_azi + (t_float) 4000.0); } for (i=0;i<ls_amount;i++) { tmp_azi = (lss[i].azi); - lss[i].azi = (tmp_azi - (float) 4000.0); + lss[i].azi = (tmp_azi - (t_float) 4000.0); } } -static int calc_2D_inv_tmatrix(float azi1,float azi2, float inv_mat[4],float mat[4]) +static int calc_2D_inv_tmatrix(t_float azi1,t_float azi2, t_float inv_mat[4],t_float mat[4]) // calculate inverse 2x2 matrix { - float x1,x2,x3,x4; /* x1 x3 */ - //float y1,y2,y3,y4; /* x2 x4 */ - float det; + t_float x1,x2,x3,x4; /* x1 x3 */ + //t_float y1,y2,y3,y4; /* x2 x4 */ + t_float det; mat[0]=x1 = cos(azi1 / rad2ang); mat[1]=x2 = sin(azi1 / rad2ang); diff --git a/externals/vbap/define_loudspeakers.h b/externals/vbap/define_loudspeakers.h index de5d0a948321e9cb4fabc95765cd28878ca868e5..afaf036f4fd2f7a76727fa30db658db864536db4 100644 --- a/externals/vbap/define_loudspeakers.h +++ b/externals/vbap/define_loudspeakers.h @@ -20,16 +20,16 @@ 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 float vec_angle(t_ls v1, t_ls v2); -static float vec_length(t_ls v1); -static float vec_prod(t_ls v1, t_ls v2); -static float vec_prod(t_ls v1, t_ls v2); -static float vol_p_side_lgth(int i, int j,int k, t_ls lss[MAX_LS_AMOUNT] ); +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(float azi1,float azi2, float inv_mat[4],float mat[4]); +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); diff --git a/externals/vbap/rvbap.c b/externals/vbap/rvbap.c index 75604b9018fdde0fb9371c2cbf63609e43ff33d8..4c7b87a8f5d571083549c825a87c3a3cd101f03c 100644 --- a/externals/vbap/rvbap.c +++ b/externals/vbap/rvbap.c @@ -14,6 +14,7 @@ See copyright in file with name LICENSE.txt */ #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 @@ -33,22 +34,22 @@ typedef struct vbap /* This defines the object as an entity made up t_object x_ob; long x_azi; // panning direction azimuth long x_ele; // panning direction elevation - float x_dist; // sound source distance (1.0-infinity) + t_float x_dist; // sound source distance (1.0-infinity) void *x_outlet0; /* outlet creation - inlets are automatic */ void *x_outlet1; void *x_outlet2; void *x_outlet3; void *x_outlet4; - float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set - float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set + 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) - float x_spread_base[3]; // used to create uniform spreading - float x_reverb_gs[MAX_LS_SETS]; // correction value for each loudspeaker set to get equal volume + t_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 @@ -65,23 +66,23 @@ typedef struct vbap /* This defines the object as an entity made up void *x_outlet2; void *x_outlet3; void *x_outlet4; - float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set - t_float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set + 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) - float x_spread_base[3]; // used to create uniform spreading - float x_reverb_gs[MAX_LS_SETS]; // correction value for each loudspeaker set to get equal volume + t_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, float spreaddir[3], float vscartdir[3], float spread_base[3]); -static void new_spread_base(t_rvbap *x, float spreaddir[3], float vscartdir[3]); +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); @@ -97,17 +98,17 @@ static void rvbap_ft4(t_rvbap *x, double n); #ifdef PD static t_class *rvbap_class; #endif -static void cross_prod(float v1[3], float v2[3], - float v3[3]); -static void additive_vbap(float *final_gs, float cartdir[3], t_rvbap *x); +static void 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, float *final_gs); +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(float g[3], long ls[3], t_rvbap *x); -static void angle_to_cart(long azi, long ele, float res[3]); -static void cart_to_angle(float cvec[3], float avec[3]); -static void equal_reverb(t_rvbap *x, float *final_gs); +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 */ @@ -137,7 +138,7 @@ int main(void) 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"); + post("rvbap v1.1, © 2003-2007 by Olaf Matthes, based on vbap by Ville Pulkki"); return 0; } @@ -159,7 +160,7 @@ static void rvbap_assist(t_rvbap *x, void *b, long m, long a, char *s) sprintf(s, "(int) spreading"); break; case 4: - sprintf(s, "(float) distance"); + sprintf(s, "(t_float) distance"); break; } break; @@ -178,7 +179,7 @@ static void rvbap_assist(t_rvbap *x, void *b, long m, long a, char *s) sprintf(s, "(int) actual spreading"); break; case 4: - sprintf(s, "(float) actual distance"); + sprintf(s, "(t_float) actual distance"); break; } break; @@ -187,24 +188,24 @@ static void rvbap_assist(t_rvbap *x, void *b, long m, long a, char *s) #endif /* end MAXMSP */ -static void angle_to_cart(long azi, long ele, float res[3]) +static void angle_to_cart(long azi, long ele, t_float res[3]) /* converts angular coordinates to cartesian */ { - float atorad = (2.0 * 3.1415927 / 360.0) ; - res[0] = cos((float) azi * atorad) * cos((float) ele * atorad); - res[1] = sin((float) azi * atorad) * cos((float) ele * atorad); - res[2] = sin((float) ele * atorad); + 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(float cvec[3], float avec[3]) +static void cart_to_angle(t_float cvec[3], t_float avec[3]) // converts cartesian coordinates to angular { - float tmp, tmp2, tmp3, tmp4; - float atorad = (float)(2.0 * 3.1415927 / 360.0) ; - float pi = (float)3.1415927; - float power; - float dist, atan_y_per_x, atan_x_pl_y_per_z; - float azi, ele; + 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; @@ -224,24 +225,24 @@ static void cart_to_angle(float cvec[3], float avec[3]) else atan_x_pl_y_per_z = pi/2.0; ele = atan_x_pl_y_per_z / atorad; - dist = sqrtf(cvec[0] * cvec[0] +cvec[1] * cvec[1] +cvec[2]*cvec[2]); + 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(float g[3], long ls[3], t_rvbap *x) +static void vbap(t_float g[3], long ls[3], t_rvbap *x) { /* calculates gain factors using loudspeaker setup and given direction */ - float power; + t_float power; int i,j,k, gains_modified; - float small_g; - float big_sm_g, gtmp[3]; + t_float small_g; + t_float big_sm_g, gtmp[3]; long winner_set=0; - float cartdir[3]; - float new_cartdir[3]; - float new_angle_dir[3]; + 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; @@ -334,11 +335,11 @@ static void vbap(float g[3], long ls[3], t_rvbap *x) } -static void cross_prod(float v1[3], float v2[3], - float v3[3]) +static void cross_prod(t_float v1[3], t_float v2[3], + t_float v3[3]) // vector cross product { - float length; + 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]); @@ -349,20 +350,20 @@ static void cross_prod(float v1[3], float v2[3], v3[2] /= length; } -static void additive_vbap(float *final_gs, float cartdir[3], t_rvbap *x) +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) { - float power; + t_float power; int i,j,k, gains_modified; - float small_g; - float big_sm_g, gtmp[3]; + t_float small_g; + t_float big_sm_g, gtmp[3]; long winner_set; - float new_cartdir[3]; - float new_angle_dir[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; - float g[3]; + t_float g[3]; long ls[3] = { 0, 0, 0 }; big_sm_g = -100000.0; @@ -423,13 +424,13 @@ static void additive_vbap(float *final_gs, float cartdir[3], t_rvbap *x) } -static void new_spread_dir(t_rvbap *x, float spreaddir[3], float vscartdir[3], float spread_base[3]) +static void new_spread_dir(t_rvbap *x, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3]) // subroutine for spreading { - float beta,m_gamma; - float a,b; - float pi = 3.1415927; - float power; + 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] + @@ -454,12 +455,12 @@ static void new_spread_dir(t_rvbap *x, float spreaddir[3], float vscartdir[3], f spreaddir[2] /= power; } -static void new_spread_base(t_rvbap *x, float spreaddir[3], float vscartdir[3]) +static void new_spread_base(t_rvbap *x, t_float spreaddir[3], t_float vscartdir[3]) // subroutine for spreading { - float d; - float pi = 3.1415927; - float power; + 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]; @@ -472,18 +473,18 @@ static void new_spread_base(t_rvbap *x, float spreaddir[3], float vscartdir[3]) x->x_spread_base[2] /= power; } -static void spread_it(t_rvbap *x, float *final_gs) +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 { - float vscartdir[3]; - float spreaddir[16][3]; - float spreadbase[16][3]; + t_float vscartdir[3]; + t_float spreaddir[16][3]; + t_float spreadbase[16][3]; long i, spreaddirnum; - float power; + t_float power; if(x->x_dimension == 3){ spreaddirnum=16; angle_to_cart(x->x_azi,x->x_ele,vscartdir); @@ -547,18 +548,18 @@ static void spread_it(t_rvbap *x, float *final_gs) } -static void equal_reverb(t_rvbap *x, float *final_gs) +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 { - float vscartdir[3]; - float spreaddir[16][3]; - float spreadbase[16][3]; + t_float vscartdir[3]; + t_float spreaddir[16][3]; + t_float spreadbase[16][3]; long i, spreaddirnum; - float power; + t_float power; if(x->x_dimension == 3){ spreaddirnum=5; @@ -606,11 +607,11 @@ static void rvbap_bang(t_rvbap *x) // top level, vbap gains are calculated and outputted { t_atom at[MAX_LS_AMOUNT]; - float g[3]; + t_float g[3]; long ls[3]; long i; - float *final_gs, overdist, oversqrtdist; - final_gs = (float *) getbytes(x->x_ls_amount * sizeof(float)); + 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;i<x->x_ls_amount;i++) @@ -666,7 +667,7 @@ static void rvbap_bang(t_rvbap *x) } else post("rvbap: Configure loudspeakers first!"); - freebytes(final_gs, x->x_ls_amount * sizeof(float)); // bug fix added 9/00 + freebytes(final_gs, x->x_ls_amount * sizeof(t_float)); // bug fix added 9/00 } /*--------------------------------------------------------------------------*/ @@ -682,7 +683,7 @@ static void rvbap_matrix(t_rvbap *x, t_symbol *s, int ac, t_atom *av) long i; long deb=0; long azi = x->x_azi, ele = x->x_ele; // store original values - float g[3]; + t_float g[3]; long ls[3]; if(ac>0) @@ -824,7 +825,7 @@ static void rvbap_in4(t_rvbap *x, long n) /* x = the instance of // distance { if (n<1) n = 1; - x->x_dist = (float)n; /* store n in a global variable */ + x->x_dist = (t_float)n; /* store n in a global variable */ } @@ -858,7 +859,7 @@ static void rvbap_ft4(t_rvbap *x, double n) /* x = the instance of // distance { if (n<1.0) n = 1.0; - x->x_dist = (float)n; /* store n in a global variable */ + x->x_dist = (t_float)n; /* store n in a global variable */ } @@ -871,7 +872,7 @@ static void *rvbap_new(t_symbol *s, int ac, t_atom *av) #ifdef MAXMSP x = (t_rvbap *)newobject(rvbap_class); - floatin(x,4); /* takes the distance */ + 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 */ diff --git a/externals/vbap/unittests/define-loudspeaker-unittest.wav b/externals/vbap/unittests/define-loudspeaker-unittest.wav new file mode 100644 index 0000000000000000000000000000000000000000..d0e52daa52ef33c5d893acff4e614cd949d32af9 Binary files /dev/null and b/externals/vbap/unittests/define-loudspeaker-unittest.wav differ diff --git a/externals/vbap/unittests/define_loudspeakers-unittest.pd b/externals/vbap/unittests/define_loudspeakers-unittest.pd new file mode 100644 index 0000000000000000000000000000000000000000..9d1f0a614c1733a45b1d0edb286480216739b0ba --- /dev/null +++ b/externals/vbap/unittests/define_loudspeakers-unittest.pd @@ -0,0 +1,43 @@ +#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; diff --git a/externals/vbap/unittests/rvbap-unittest.pd b/externals/vbap/unittests/rvbap-unittest.pd new file mode 100644 index 0000000000000000000000000000000000000000..728fa5d00c1df86ae23f00dfdc5ffafb6ca9c5b2 --- /dev/null +++ b/externals/vbap/unittests/rvbap-unittest.pd @@ -0,0 +1,75 @@ +#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; diff --git a/externals/vbap/unittests/rvbap-unittest.wav b/externals/vbap/unittests/rvbap-unittest.wav new file mode 100644 index 0000000000000000000000000000000000000000..7c54c74de21592d3e64033d7c336ffc4c765be99 Binary files /dev/null and b/externals/vbap/unittests/rvbap-unittest.wav differ diff --git a/externals/vbap/unittests/vbap-unittest.pd b/externals/vbap/unittests/vbap-unittest.pd new file mode 100644 index 0000000000000000000000000000000000000000..ba5e8d833a8208c9a8dbe3c1e57d188078003d05 --- /dev/null +++ b/externals/vbap/unittests/vbap-unittest.pd @@ -0,0 +1,140 @@ +#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; diff --git a/externals/vbap/unittests/vbap-unittest.wav b/externals/vbap/unittests/vbap-unittest.wav new file mode 100644 index 0000000000000000000000000000000000000000..1a92557d3fefb2e89ad7ca79c032090a3508910d Binary files /dev/null and b/externals/vbap/unittests/vbap-unittest.wav differ diff --git a/externals/vbap/unittests/vbap.wav b/externals/vbap/unittests/vbap.wav new file mode 100644 index 0000000000000000000000000000000000000000..9d10273ddd8cec22c7b63332b3468f10c8f8d943 Binary files /dev/null and b/externals/vbap/unittests/vbap.wav differ diff --git a/externals/vbap/vbap-meta.pd b/externals/vbap/vbap-meta.pd index d95168b3dacb8789cae853ccb3c0f83882115690..8077fd7e9a6c087e985bbaf0d0953420cd90a52e 100644 --- a/externals/vbap/vbap-meta.pd +++ b/externals/vbap/vbap-meta.pd @@ -1,7 +1,8 @@ -#N canvas 10 10 200 200 10; -#N canvas 20 20 420 300 META 0; +#N canvas 140 22 200 200 10; +#N canvas 20 22 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 text 10 70 DESCRIPTION spatialization using Vector Based Amplitude +Panning; +#X text 10 107 VERSION 1.1; #X restore 10 10 pd META; diff --git a/externals/vbap/vbap.c b/externals/vbap/vbap.c index 3bf09fd7ab1e2409c28071e9ef0b4b7117bef759..f1e4052ebd971c17a4813705452ecd05801871f0 100644 --- a/externals/vbap/vbap.c +++ b/externals/vbap/vbap.c @@ -14,25 +14,27 @@ See copyright in file with name LICENSE.txt */ #include "s_stuff.h" // Function prototypes -static void new_spread_dir(t_vbap *x, float spreaddir[3], float vscartdir[3], float spread_base[3]); -static void new_spread_base(t_vbap *x, float spreaddir[3], float vscartdir[3]); +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(float v1[3], float v2[3],float v3[3]); -static void additive_vbap(float *final_gs, float cartdir[3], t_vbap *x); +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 int vbap_getmem(t_vbap *x, int lsSetCount ); +static void vbap_free(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 floatinlet_new() in new() */ +/* 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, float *final_gs); -static void *vbap_new(float azi, float ele, float spread); -static void vbap(float g[3], long ls[3], t_vbap *x); -static void angle_to_cart(float azi, float ele, float res[3]); -static void cart_to_angle(float cvec[3], float avec[3]); +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 @@ -77,7 +79,7 @@ void vbap_assist(t_vbap *x, void *b, long m, long a, char *s) #ifdef PD void vbap_setup(void) { - vbap_class = class_new(gensym("vbap"), (t_newmethod)vbap_new, 0, (short)sizeof(t_vbap), 0, + vbap_class = class_new(gensym("vbap"), (t_newmethod)vbap_new, (t_method) vbap_free, (short)sizeof(t_vbap), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(vbap_class, (t_method)vbap_bang); @@ -95,7 +97,9 @@ void vbap_setup(void) 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); - post(VBAP_VERSION); + logpost(NULL, 1, VBAP_VERSION); + //post(VBAP_VERSION); + } #else /* MAX */ void main(void) @@ -152,6 +156,14 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread) 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); + + + + // allocate space for the runtime matricies +// if (!vbap_getmem(x, MAX_LS_SETS)) +// return( NULL ); +// + #else /* Max */ t_vbap *x = (t_vbap *)newobject(vbap_class); @@ -167,7 +179,9 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread) x->x_outlet0 = listout(x); #endif /* PD */ - x->x_spread_base[0] = 0.0; + x->x_ls_setCount = 0; // refers to memory dynamically allocated when a define_loudspeakers config is received + + 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; @@ -180,7 +194,90 @@ static void *vbap_new(t_float azi, t_float ele, t_float spread) } -static void angle_to_cart(float azi, float ele, float res[3]) +// currently can allocate upto 256K to support up to 44 channels in 3D +// note: to save memory, the required memory for a given configuration could instead, be dynamically allocated by calling this method from the vbap_matrix() method +static int vbap_getmem(t_vbap *x, int lsSetCount ) +{ + +#ifdef PD + + int i; + + if ( x->x_ls_setCount ) vbap_free(x); + + //was t_float x_set_inv_matx[MAX_LS_SETS][9]; + x->x_set_inv_matx = getbytes( sizeof( t_float* ) * lsSetCount); + + if(!x->x_set_inv_matx) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( t_float* ) * lsSetCount); return(0);} + + for (i = 0; i < lsSetCount; i++) + { + x->x_set_inv_matx[i] = getbytes( sizeof(t_float) * MATRIX_DIM ); + if(!x->x_set_inv_matx[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(t_float) * MATRIX_DIM ); return(0);} + } + + + //was t_float x_set_matx[MAX_LS_SETS][9]; + x->x_set_matx = getbytes( sizeof( t_float* ) * lsSetCount); + + if(!x->x_set_matx) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( t_float* ) * lsSetCount); return(0);} + + for (i = 0; i < lsSetCount; i++) + { + x->x_set_matx[i] = getbytes( sizeof(t_float) * MATRIX_DIM ); + if(!x->x_set_matx[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(t_float) * MATRIX_DIM ); return(0);} + } + + + //was long x_lsset[MAX_LS_SETS][3]; + x->x_lsset = getbytes( sizeof( long * ) * lsSetCount); + + if(!x->x_lsset) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof( long * ) * lsSetCount); return(0);} + + for (i = 0; i < lsSetCount; i++) + { + x->x_lsset[i] = getbytes( sizeof( long ) * SPEAKER_SET_DIM ); + if(!x->x_lsset[i]) {error("vbap_getmem: can't allocate additional %ld bytes", sizeof(long) * SPEAKER_SET_DIM ); return(0);} + } + + unsigned long memallocd = 2 * ( sizeof(t_float *) * lsSetCount * sizeof(t_float) * MATRIX_DIM) + ( sizeof(long *) * lsSetCount * sizeof(long) * SPEAKER_SET_DIM); + + logpost(NULL, 3, "vbap_new: %ldK bytes allocated for instance", memallocd /1000); + + x->x_ls_setCount = lsSetCount; + +#endif + return(1); + +} + + +// free any allocated memory for instance +static void vbap_free(t_vbap *x) +{ + int i; + + if (! x->x_ls_setCount) return; + + for (i = 0; i < x->x_ls_setCount; i++) + { + freebytes( x->x_set_inv_matx[i], (sizeof(t_float) * MATRIX_DIM )); // = getbytes( sizeof(t_float) * MATRIX_DIM ); + freebytes( x->x_set_matx[i], sizeof(t_float) * MATRIX_DIM); + } + + freebytes(x->x_set_inv_matx, (sizeof( t_float* ) * x->x_ls_setCount)); + freebytes(x->x_set_matx, sizeof( t_float* ) * x->x_ls_setCount); + + + for (i = 0; i < x->x_ls_setCount; i++) + { + freebytes(x->x_lsset[i], sizeof( long ) * SPEAKER_SET_DIM ); + } + + freebytes( x->x_lsset, sizeof( long * ) * x->x_ls_setCount); +} + +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); @@ -188,13 +285,13 @@ static void angle_to_cart(float azi, float ele, float res[3]) res[2] = sin( ele * atorad); } -static void cart_to_angle(float cvec[3], float avec[3]) +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; - float dist, atan_y_per_x, atan_x_pl_y_per_z; - float azi, ele; + 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; @@ -223,17 +320,17 @@ static void cart_to_angle(float cvec[3], float avec[3]) } -static void vbap(float g[3], long ls[3], t_vbap *x) +static void vbap(t_float g[3], long ls[3], t_vbap *x) { /* calculates gain factors using loudspeaker setup and given direction */ - float power; + t_float power; int i,j,k, gains_modified; - float small_g; - float big_sm_g, gtmp[3]; + t_float small_g; + t_float big_sm_g, gtmp[3]; long winner_set = 0; - float cartdir[3]; - float new_cartdir[3]; - float new_angle_dir[3]; + 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; @@ -327,7 +424,7 @@ static void vbap(float g[3], long ls[3], t_vbap *x) } 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 ); + //post("[vbap] use azimuth %g",x->x_azi ); x->x_ele = (new_angle_dir[1]); } //} @@ -339,11 +436,11 @@ static void vbap(float g[3], long ls[3], t_vbap *x) } -static void vect_cross_prod(float v1[3], float v2[3], - float v3[3]) +static void vect_cross_prod(t_float v1[3], t_float v2[3], + t_float v3[3]) // vector cross product { - float length; + 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]); @@ -354,20 +451,20 @@ static void vect_cross_prod(float v1[3], float v2[3], v3[2] /= length; } -static void additive_vbap(float *final_gs, float cartdir[3], t_vbap *x) +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) { - float power; + t_float power; int i,j,k, gains_modified; - float small_g; - float big_sm_g, gtmp[3]; + 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; - float g[3] = {0,0,0}; + t_float g[3] = {0,0,0}; long ls[3] = {0,0,0}; big_sm_g = -100000.0; @@ -415,17 +512,18 @@ static void additive_vbap(float *final_gs, float cartdir[3], t_vbap *x) final_gs[ls[0]-1] += g[0]; final_gs[ls[1]-1] += g[1]; - final_gs[ls[2]-1] += g[2]; + if (dim==3) + final_gs[ls[2]-1] += g[2]; } } -static void new_spread_dir(t_vbap *x, float spreaddir[3], float vscartdir[3], float spread_base[3]) +static void new_spread_dir(t_vbap *x, t_float spreaddir[3], t_float vscartdir[3], t_float spread_base[3]) // subroutine for spreading { - float beta,gamma; - float a,b; - float power; + t_float beta,gamma; + t_float a,b; + t_float power; gamma = acos(vscartdir[0] * spread_base[0] + vscartdir[1] * spread_base[1] + @@ -450,11 +548,11 @@ static void new_spread_dir(t_vbap *x, float spreaddir[3], float vscartdir[3], fl spreaddir[2] /= power; } -static void new_spread_base(t_vbap *x, float spreaddir[3], float vscartdir[3]) +static void new_spread_base(t_vbap *x, t_float spreaddir[3], t_float vscartdir[3]) // subroutine for spreading { - float d; - float power; + t_float d; + t_float power; d = cos(x->x_spread/180*M_PI); x->x_spread_base[0] = spreaddir[0] - d * vscartdir[0]; @@ -467,18 +565,18 @@ static void new_spread_base(t_vbap *x, float spreaddir[3], float vscartdir[3]) x->x_spread_base[2] /= power; } -static void spread_it(t_vbap *x, float *final_gs) +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 { - float vscartdir[3]; - float spreaddir[16][3]; - float spreadbase[16][3]; + t_float vscartdir[3]; + t_float spreaddir[16][3]; + t_float spreadbase[16][3]; long i, spreaddirnum; - float power; + t_float power; if(x->x_dimension == 3){ spreaddirnum=16; angle_to_cart(x->x_azi,x->x_ele,vscartdir); @@ -546,10 +644,11 @@ static void vbap_bang(t_vbap *x) // top level, vbap gains are calculated and outputted { Atom at[MAX_LS_AMOUNT]; - float g[3]; + t_float g[3]; long ls[3]; long i; - float *final_gs = (float *) getbytes(x->x_ls_amount * sizeof(float)); + + t_float *final_gs = (t_float *) getbytes(x->x_ls_amount * sizeof(t_float)); if(x->x_lsset_available ==1) { @@ -558,7 +657,8 @@ static void vbap_bang(t_vbap *x) final_gs[i]=0.0; for(i=0;i<x->x_dimension;i++) { - final_gs[ls[i]-1]=g[i]; + final_gs[ls[i]-1]=g[i]; + //post("VBAP: PRE_SPREAD: %f", (t_float)final_gs[i]); } if(x->x_spread != 0) { @@ -567,7 +667,9 @@ static void vbap_bang(t_vbap *x) for(i=0;i<x->x_ls_amount;i++) { #ifdef PD - SETFLOAT(&at[0], (t_float)i); + + + 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 */ @@ -584,7 +686,7 @@ static void vbap_bang(t_vbap *x) else error("vbap: Configure loudspeakers first!"); - freebytes(final_gs, x->x_ls_amount * sizeof(float)); // bug fix added 9/00 + freebytes(final_gs, x->x_ls_amount * sizeof(t_float)); // bug fix added 9/00 } /*--------------------------------------------------------------------------*/ @@ -597,8 +699,14 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av) { 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; } + 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; } @@ -616,25 +724,40 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av) 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-1 > MAX_LS_SETS) { error("vbap %s: loudspeaker definitions exceed maximum number of speakers",s->s_name); x->x_lsset_available=0; return; } + + vbap_getmem(x, counter); // PD only: allocate memory (frees any previously allocated memory automatically) + + 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) + + long db_dim = x->x_dimension; + + while(counter-- > 0) { - for(i=0; i < x->x_dimension; i++) + + for(i=0; i < x->x_dimension; i++) { # ifdef PD - if(av[datapointer].a_type == A_FLOAT) + + 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 { error("vbap AA %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) { @@ -643,26 +766,35 @@ static void vbap_matrix(t_vbap *x, Symbol *s, int ac, Atom *av) 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++) + + + for(i=0; i < x->x_dimension*x->x_dimension; i++) { - if(av[datapointer].a_type == A_FLOAT) + + 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; } + else { error("vbap BB %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; } + 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!"); -} + } diff --git a/externals/vbap/vbap.h b/externals/vbap/vbap.h index dd588ac3f4a472f70b81f885f50c8b0e110a72cb..ecd388c40757f4d8605e50b5ee5b89678bc31181 100644 --- a/externals/vbap/vbap.h +++ b/externals/vbap/vbap.h @@ -10,21 +10,38 @@ #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 +#ifdef PD +// Revised by Z. Settel to dynamically allocate memory + #define MAX_LS_SETS 745 // maximum number of loudspeaker sets (triplets or pairs) allowed -- allows for up to 44 speakers in 3D config +//#define MAX_LS_SETS 100 // former maximum value crashed for 3D speaker configurations with more than 13 speakers +//#define MAX_LS_SETS 571 // example: for up to 32 speakers in 3D config + +#else // Max + +#define MAX_LS_SETS 100 // maximum number of loudspeaker sets (triplets or pairs) allowed - This can crash when too many speakers are defined + +#endif + +#define MATRIX_DIM 9 // hard-coded matrx dimension for the algorithm +#define SPEAKER_SET_DIM 3 // hard-coded speaker set dimension for the algorithm + +#define MAX_LS_AMOUNT 55 // maximum amount of loudspeakers, can be increased, but see comments next to MAX_LS_SETS above #define MIN_VOL_P_SIDE_LGTH 0.01 -#define VBAP_VERSION "vbap - v1.0.3.1 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006 (Pd port by HCS)" -#define DFLS_VERSION "define_loudspeakers - v1.0.3.1 - 20 Nov 2010 - (c) Ville Pulkki 1999-2006" +#define VBAP_VERSION "vbap - v1.1 - 14 Aug. 2014 - (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 float rad2ang = 360.0 / ( 2.0f * M_PI ); -static float atorad = (2.0f * M_PI) / 360.0f ; +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) + +//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) \ @@ -35,11 +52,11 @@ static float atorad = (2.0f * M_PI) / 360.0f ; /* A struct for a loudspeaker instance */ typedef struct { // distance value is 1.0 == unit vectors - float x; // cartesian coordinates - float y; - float z; - float azi; // polar coordinates - float ele; + 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; @@ -47,7 +64,7 @@ typedef struct typedef struct t_ls_set { int ls_nos[3]; // channel numbers - float inv_mx[9]; // inverse 3x3 or 2x2 matrix + t_float inv_mx[9]; // inverse 3x3 or 2x2 matrix struct t_ls_set *next; // next set (triplet or pair) } t_ls_set; @@ -55,27 +72,40 @@ typedef struct t_ls_set typedef struct vbap /* This defines the object as an entity made up of other things */ { t_object x_obj; - float x_azi; // panning direction azimuth - float x_ele; // panning direction elevation + 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; - float x_set_inv_matx[MAX_LS_SETS][9]; // inverse matrice for each loudspeaker set - float x_set_matx[MAX_LS_SETS][9]; // matrice for each loudspeaker set - long x_lsset[MAX_LS_SETS][3]; // channel numbers of loudspeakers in each LS set + void *x_outlet4; + 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_ls_amount; // amount of loudspeakers long x_dimension; // 2 or 3 + # ifdef PD + // memory for data sets is now allocated dynamically in each instance + // WAS t_float x_set_inv_matx[MAX_LS_SETS][9]; + t_float **x_set_inv_matx; // inverse matrice for each loudspeaker set + // WAS t_float x_set_matx[MAX_LS_SETS][9]; + t_float **x_set_matx; // matrice for each loudspeaker set + // WAS long x_lsset[MAX_LS_SETS][3]; + long **x_lsset; // channel numbers of loudspeakers in each LS set + t_float x_spread; // speading amount of virtual source (0-100) -# else /* Max */ - long x_spread; // speading amount of virtual source (0-100) + +# else /* Max */ // memory allocation not tested for max, so it is allocated in the struct, as it was before + + 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_spread; // speading amount of virtual source (0-100) double x_gain; // general gain control (0-2) # endif /* PD */ - float x_spread_base[3]; // used to create uniform spreading + 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 @@ -84,6 +114,7 @@ typedef struct t_ls_set 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) + long x_ls_setCount; // the number of Loudspeaker sets used for an instance's current loudspeaker configuration } t_vbap; // define loudspeaker data type...