diff options
| author | Comment <tim@gray.(none)> | 2013-06-28 23:32:10 +0100 |
|---|---|---|
| committer | Comment <tim@gray.(none)> | 2013-06-28 23:32:10 +0100 |
| commit | 1a7e15a63d78a6351028d977b90052f6b0d6bf7d (patch) | |
| tree | 8345507e9c4dd871cd08eb884fe8b9fe2816137d /07_performance | |
| parent | fd8dc2aa23c4bbc297e835e4f920aaf5342aba5e (diff) | |
first performance version
Diffstat (limited to '07_performance')
| -rw-r--r-- | 07_performance/Makefile | 2 | ||||
| -rw-r--r-- | 07_performance/Makfile | 244 | ||||
| -rw-r--r-- | 07_performance/addons.make | 6 | ||||
| -rw-r--r-- | 07_performance/config.mak | 56 | ||||
| -rw-r--r-- | 07_performance/config.make | 56 | ||||
| -rw-r--r-- | 07_performance/src/FFTOctaveAnalyzer.cpp | 98 | ||||
| -rw-r--r-- | 07_performance/src/FFTOctaveAnalyzer.h | 45 | ||||
| -rw-r--r-- | 07_performance/src/fft.cpp | 489 | ||||
| -rw-r--r-- | 07_performance/src/fft.h | 33 | ||||
| -rw-r--r-- | 07_performance/src/main.cpp | 18 | ||||
| -rw-r--r-- | 07_performance/src/oni.cpp | 267 | ||||
| -rw-r--r-- | 07_performance/src/oni.h | 104 | ||||
| -rw-r--r-- | 07_performance/src/testApp.cpp | 1039 | ||||
| -rw-r--r-- | 07_performance/src/testApp.h | 202 |
14 files changed, 2659 insertions, 0 deletions
diff --git a/07_performance/Makefile b/07_performance/Makefile new file mode 100644 index 0000000..2d83a77 --- /dev/null +++ b/07_performance/Makefile @@ -0,0 +1,2 @@ +include config.make +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/Makefile.examples diff --git a/07_performance/Makfile b/07_performance/Makfile new file mode 100644 index 0000000..0ae1f0e --- /dev/null +++ b/07_performance/Makfile @@ -0,0 +1,244 @@ +# openFrameworks OS X makefile +# +# make help : shows this message +# make Debug: makes the application with debug symbols +# make Release: makes the app with optimizations +# make: the same as make Release +# make CleanDebug: cleans the Debug target +# make CleanRelease: cleans the Release target +# make clean: cleans everything +# +# +# this should work with any OF app, just copy any example +# change the name of the folder and it should compile +# only .cpp support, don't use .c files +# it will look for files in any folder inside the application +# folder except that in the EXCLUDE_FROM_SOURCE variable +# it doesn't autodetect include paths yet +# add the include paths in the USER_CFLAGS variable +# using the gcc syntax: -Ipath +# +# to add addons to your application, edit the addons.make file +# in this directory and add the names of the addons you want to +# include +# +# edit the following vars to customize the makefile + +include config.mak +ARCH = i386 + +COMPILER_OPTIMIZATION = $(USER_COMPILER_OPTIMIZATION) + +EXCLUDE_FROM_SOURCE="bin,.xcodeproj,obj" + +# you shouldn't modify anything below this line +SHELL = /bin/sh +CXX = g++ +LIBSPATH=osx + +NODEPS = clean +SED_EXCLUDE_FROM_SRC = $(shell echo $(EXCLUDE_FROM_SOURCE) | sed s/\,/\\\\\|/g) +SOURCE_DIRS = src +#$(shell find . -maxdepth 1 -mindepth 1 -type d | grep -v $(SED_EXCLUDE_FROM_SRC) | sed s/.\\///) +SOURCES = $(shell find $(SOURCE_DIRS) -name "*.cpp" -or -name "*.c") +OBJFILES = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES))) +APPNAME = $(shell basename `pwd`) +CORE_INCLUDES = $(shell find $(OF_ROOT)/libs/openFrameworks/ -type d) +CORE_INCLUDE_FLAGS = $(addprefix -I,$(CORE_INCLUDES)) +INCLUDES = $(shell find $(OF_ROOT)/libs/*/include -type d | grep -v glu | grep -v quicktime | grep -v poco) +INCLUDES_FLAGS = $(addprefix -I,$(INCLUDES)) +INCLUDES_FLAGS += -I$(OF_ROOT)/libs/poco/include +INCLUDES_FLAGS += -I$(OF_ROOT)/libs/glu/include +#INCLUDES_FLAGS += -I$(OF_ROOT)/libs/quicktime/include + +LIB_STATIC = $(shell ls $(OF_ROOT)/libs/*/lib/$(LIBSPATH)/*.a | grep -v openFrameworksCompiled | grep -v poco) +LIB_STATIC += $(OF_ROOT)/libs/fmodex/lib/osx/libfmodex.dylib +LIB_SHARED = $(shell ls $(OF_ROOT)/libs/*/lib/$(LIBSPATH)/*.so | grep -v openFrameworksCompiled | grep -v poco) +LIB_STATIC += $(OF_ROOT)/libs/poco/lib/$(LIBSPATH)/PocoNet.a $(OF_ROOT)/libs/poco/lib/$(LIBSPATH)/PocoXML.a $(OF_ROOT)/libs/poco/lib/$(LIBSPATH)/PocoUtil.a $(OF_ROOT)/libs/poco/lib/$(LIBSPATH)/PocoFoundation.a +LIB_PATHS_FLAGS = $(shell ls -d $(OF_ROOT)/libs/*/lib/$(LIBSPATH) | sed "s/\(\.*\)/-L\1/") + +CFLAGS += -Wall -fexceptions +CFLAGS += -I. +CFLAGS += $(INCLUDES_FLAGS) +CFLAGS += $(CORE_INCLUDE_FLAGS) +CFLAGS += -x c++ -arch $(ARCH) -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -Os -fasm-blocks -Wno-deprecated-declarations -Wno-invalid-offsetof -gdwarf-2 -msse3 -mssse3 + +LIBS += $(LIB_SHARED) +LIBS += $(LIB_STATIC) + +LDFLAGS = $(LIB_PATHS_FLAGS) -Wl +LIBS += -F$(OF_ROOT)/libs/glut/lib/osx -framework AppKit -framework Cocoa -framework IOKit -framework AGL -framework AudioToolbox -framework Carbon -framework CoreAudio -CoreFoundation -framework CoreServices -framework GLUT -framework OpenGL -framework Quicktime -framework CoreMidi -framework QTKit -framework QuartzCore -framework CoreVideo -framework Accelerate + +#Targets +ifeq ($(findstring Debug,$(MAKECMDGOALS)),Debug) + TARGET_CFLAGS = -g + TARGET_LIBS = $(OF_ROOT)/libs/openFrameworksCompiled/lib/osx/openFrameworksDebug.a + TARGET_NAME = Debug +endif + +ifeq ($(findstring Release,$(MAKECMDGOALS)),Release) + TARGET_CFLAGS = $(COMPILER_OPTIMIZATION) + TARGET_LIBS = $(OF_ROOT)/libs/openFrameworksCompiled/lib/osx/openFrameworks.a + TARGET_NAME = Release +endif + +ifeq ($(findstring Debug,$(MAKECMDGOALS)),Debug) + BIN_NAME = $(APPNAME)_debug + TARGET = bin/$(BIN_NAME) +endif + +ifeq ($(findstring Release,$(MAKECMDGOALS)),Release) + BIN_NAME = $(APPNAME) + TARGET = bin/$(BIN_NAME) +endif + +ifeq ($(findstring Release,$(MAKECMDGOALS)),clang) + CXX = clang +endif + +ifeq ($(MAKECMDGOALS),) + TARGET_NAME = Release + BIN_NAME = $(APPNAME) + TARGET = bin/$(BIN_NAME) + TARGET_LIBS = $(OF_ROOT)/libs/openFrameworksCompiled/lib/osx/openFrameworks.a +endif + +ifeq ($(MAKECMDGOALS),clean) + TARGET = bin/$(APPNAME)_debug bin/$(APPNAME) +endif + + +#Output +OBJ_OUTPUT = obj/$(TARGET_NAME)/ +CLEANTARGET = clean$(TARGET_NAME) +OBJS = $(addprefix $(OBJ_OUTPUT), $(OBJFILES)) +DEPFILES = $(patsubst %.o,%.d,$(OBJS)) +ifeq ($(findstring addons.make,$(wildcard *.make)),addons.make) + ADDONS = $(shell cat addons.make) + ADDONS_REL_DIRS = $(addsuffix /src, $(ADDONS)) + ADDONS_LIBS_REL_DIRS = $(addsuffix /libs, $(ADDONS)) + ADDONS_DIRS = $(addprefix $(OF_ROOT)/addons/, $(ADDONS_REL_DIRS) ) + ADDONS_LIBS_DIRS = $(addprefix $(OF_ROOT)/addons/, $(ADDONS_LIBS_REL_DIRS) ) + ADDONS_BIN_LIBS_DIRS = $(addsuffix /*/lib/$(LIBSPATH), $(ADDONS_LIBS_DIRS) ) + ADDONS_INCLUDES = $(ADDONS_DIRS) + ADDONS_INCLUDES = $(ADDONS_LIBS_DIRS) + ADDONS_INCLUDES += $(shell find $(ADDONS_DIRS) -type d 2> /dev/null) + ADDONS_INCLUDES += $(shell find $(ADDONS_LIBS_DIRS) -type d 2> /dev/null) + ADDONSCFLAGS = $(addprefix -I,$(ADDONS_INCLUDES)) +ifeq ($(findstring libsorder.make,$(shell find $(ADDONS_BIN_LIBS_DIRS) -name libsorder.make 2> /dev/null)),libsorder.make) + ADDONS_LIBS_W_ORDER = $(shell cat $(shell find $(ADDONS_BIN_LIBS_DIRS) -name libsorder.make 2> /dev/null)) + SED_EXCLUDE_LIBS = $(addsuffix \|,$(ADDONS_LIBS_W_ORDER)) + ADDONS_LIBS_STATICS = $(shell find $(ADDONS_BIN_LIBS_DIRS) -name *.a 2> /dev/null | grep -v '$(SED_EXCLUDE_LIBS)') + else + ADDONS_LIBS_STATICS = $(shell find $(ADDONS_BIN_LIBS_DIRS) -name *.a 2> /dev/null) + endif + + ADDONS_LIBS_STATICS += $(addprefix -l, $(ADDONS_LIBS_W_ORDER)) + ADDONS_LIBS_STATICS += $(addprefix -L, $(shell find $(ADDONS_BIN_LIBS_DIRS) -name libsorder.make 2> /dev/null | sed s/libsorder.make//g)) + ADDONS_LIBS_SHARED = $(shell find $(ADDONS_BIN_LIBS_DIRS) -name *.so 2> /dev/null) + ADDONSLIBS = $(ADDONS_LIBS_STATICS) + ADDONSLIBS += $(ADDONS_LIBS_SHARED) + + + ADDONS_SOURCES = $(shell find $(ADDONS_DIRS) -name "*.cpp" -or -name "*.c" 2> /dev/null) + ADDONS_SOURCES += $(shell find $(ADDONS_LIBS_DIRS) -name "*.cpp" -or -name "*.c" -or -name "*.cc" 2>/dev/null) + ADDONS_OBJFILES = $(subst $(OF_ROOT)/, ,$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(ADDONS_SOURCES))))) + ADDONS_OBJS = $(addprefix $(OBJ_OUTPUT), $(ADDONS_OBJFILES)) + DEPFILES += $(patsubst %.o,%.d,$(ADDONS_OBJS)) +endif + +.PHONY: Debug Release all after + +Release: $(TARGET) after + +Debug: $(TARGET) after + +all: + $(MAKE) Release + + + +#This rule does the compilation +#$(OBJS): $(SOURCES) +$(OBJ_OUTPUT)%.o: %.cpp + @echo "compiling object for: " $< + mkdir -p $(@D) + $(CXX) -c $(TARGET_CFLAGS) $(CFLAGS) $(ADDONSCFLAGS) $(USER_CFLAGS) -MMD -MP -MF$(OBJ_OUTPUT)$*.d -MT$(OBJ_OUTPUT)$*.d -o$@ -c $< + +$(OBJ_OUTPUT)%.o: %.c + @echo "compiling object for: " $< + mkdir -p $(@D) + $(CXX) -c $(TARGET_CFLAGS) $(CFLAGS) $(ADDONSCFLAGS) $(USER_CFLAGS) -MMD -MP -MF$(OBJ_OUTPUT)$*.d -MT$(OBJ_OUTPUT)$*.d -o$@ -c $< + + +$(OBJ_OUTPUT)%.o: $(OF_ROOT)/%.cpp + @echo "compiling addon object for" $< + mkdir -p $(@D) + $(CXX) $(TARGET_CFLAGS) $(CFLAGS) $(ADDONSCFLAGS) $(USER_CFLAGS) -MMD -MP -MF$(OBJ_OUTPUT)$*.d -MT$(OBJ_OUTPUT)$*.d -o $@ -c $< + +$(OBJ_OUTPUT)%.o: $(OF_ROOT)/%.c + @echo "compiling addon object for" $< + mkdir -p $(@D) + $(CXX) $(TARGET_CFLAGS) $(CFLAGS) $(ADDONSCFLAGS) $(USER_CFLAGS) -MMD -MP -MF$(OBJ_OUTPUT)$*.d -MT$(OBJ_OUTPUT)$*.d -o $@ -c $< + +$(TARGET): $(OBJS) $(ADDONS_OBJS) + @echo "linking" $(TARGET) $(GTK) + $(CXX) -arch $(ARCH) -v -o $@ $(OBJS) $(ADDONS_OBJS) $(USER_CFLAGS) $(LDFLAGS) $(USER_LDFLAGS) $(TARGET_LIBS) $(ADDONSLIBS) $(USER_LIBS) $(LIBS) + +-include $(DEPFILES) + +.PHONY: clean cleanDebug cleanRelease +clean: + rm -Rf obj + rm -f -v $(TARGET) + rm -Rf -v bin/libs + +$(CLEANTARGET): + rm -Rf -v $(OBJ_OUTPUT) + rm -f -v $(TARGET) + +after:$(TARGET) + @echo Preparing MacOS .app + #-rm -rf -v $(TARGET).app + mkdir -p $(TARGET).app/Contents/Frameworks + mkdir -p $(TARGET).app/Contents/MacOS + cp -r $(OF_ROOT)/libs/glut/lib/osx/* $(TARGET).app/Contents/Frameworks/ + cp -r $(OF_ROOT)/libs/fmodex/lib/osx/* $(TARGET).app/Contents/MacOS/ + cp $(TARGET) $(TARGET).app/Contents/MacOS/ + install_name_tool -change ./libfmodex.dylib @executable_path/libfmodex.dylib $(TARGET).app/Contents/MacOS/$(BIN_NAME) + @echo + @echo " compiling done" + @echo " to launch the application" + @echo + @echo " open $(TARGET).app" + @echo + + +.PHONY: help +help: + @echo + @echo openFrameworks universal makefile + @echo + @echo targets: + @echo "make Debug: builds the application with debug symbols" + @echo "make Release: builds the app with optimizations" + @echo "make: = make Release" + @echo "make all: = make Release" + @echo "make CleanDebug: cleans the Debug target" + @echo "make CleanRelease: cleans the Release target" + @echo "make clean: cleans everything" + @echo + @echo this should work with any OF app, just copy any example + @echo change the name of the folder and it should compile + @echo "only .cpp support, don't use .c files" + @echo it will look for files in any folder inside the application + @echo folder except that in the EXCLUDE_FROM_SOURCE variable. + @echo "it doesn't autodetect include paths yet" + @echo "add the include paths editing the var USER_CFLAGS" + @echo at the beginning of the makefile using the gcc syntax: + @echo -Ipath + @echo + @echo to add addons to your application, edit the addons.make file + @echo in this directory and add the names of the addons you want to + @echo include + @echo diff --git a/07_performance/addons.make b/07_performance/addons.make new file mode 100644 index 0000000..900ed64 --- /dev/null +++ b/07_performance/addons.make @@ -0,0 +1,6 @@ +ofxOpenNI
+ofxXmlSettings
+ofxMidi
+ofxOsc
+ofxFenster
+
diff --git a/07_performance/config.mak b/07_performance/config.mak new file mode 100644 index 0000000..c370c3f --- /dev/null +++ b/07_performance/config.mak @@ -0,0 +1,56 @@ +# add custom variables to this file + +# OF_ROOT allows to move projects outside apps/* just set this variable to the +# absoulte path to the OF root folder + +OF_ROOT = ../../../../../ + + +# USER_CFLAGS allows to pass custom flags to the compiler +# for example search paths like: +# USER_CFLAGS = -I src/objects + +USER_CFLAGS = -I $(OF_ROOT)/addons/ofxOpenNI/include/openni -I $(OF_ROOT)/addons/ofxOpenNI/include/nite -I $(OF_ROOT)/addons/ofxOpenNI/src + + +# USER_LDFLAGS allows to pass custom flags to the linker +# for example libraries like: +# USER_LDFLAGS = libs/libawesomelib.a + +#USER_LDFLAGS = -lOpenNI +USER_LDFLAGS = -L bin/data/openni/lib -L ../../../data/openni/lib -lOpenNI $(OF_ROOT)/addons/ofxFenster/libs/ghost/lib/osx32/libGhost32.a + +EXCLUDE_FROM_SOURCE="bin,.xcodeproj,obj" + +# change this to add different compiler optimizations to your project + +USER_COMPILER_OPTIMIZATION = -march=native -mtune=native -Os + + +# android specific, in case you want to use different optimizations +USER_LIBS_ARM = +USER_LIBS_ARM7 = +USER_LIBS_NEON = + +# android optimizations + +ANDROID_COMPILER_OPTIMIZATION = -Os + +NDK_PLATFORM = android-8 + +# uncomment this for custom application name (if the folder name is different than the application name) +#APPNAME = folderName + +# uncomment this for custom package name, must be the same as the java package that contains OFActivity +#PKGNAME = cc.openframeworks.$(APPNAME) + + + + + +# linux arm flags + +LINUX_ARM7_COMPILER_OPTIMIZATIONS = -march=armv7-a -mtune=cortex-a8 -finline-functions -funroll-all-loops -O3 -funsafe-math-optimizations -mfpu=neon -ftree-vectorize -mfloat-abi=hard -mfpu=vfp + + + diff --git a/07_performance/config.make b/07_performance/config.make new file mode 100644 index 0000000..e8ff248 --- /dev/null +++ b/07_performance/config.make @@ -0,0 +1,56 @@ +# add custom variables to this file + +# OF_ROOT allows to move projects outside apps/* just set this variable to the +# absoulte path to the OF root folder + +OF_ROOT = ../../openFrameworks + + +# USER_CFLAGS allows to pass custom flags to the compiler +# for example search paths like: +# USER_CFLAGS = -I src/objects + +USER_CFLAGS = -I $(OF_ROOT)/addons/ofxOpenNI/include/openni -I $(OF_ROOT)/addons/ofxOpenNI/include/nite -I $(OF_ROOT)/addons/ofxOpenNI/src + + +# USER_LDFLAGS allows to pass custom flags to the linker +# for example libraries like: +# USER_LDFLAGS = libs/libawesomelib.a + +USER_LDFLAGS = -lusb-1.0 -lOpenNI + + +EXCLUDE_FROM_SOURCE="bin,.xcodeproj,obj" + +# change this to add different compiler optimizations to your project + +USER_COMPILER_OPTIMIZATION = -march=native -mtune=native -Os + + +# android specific, in case you want to use different optimizations +USER_LIBS_ARM = +USER_LIBS_ARM7 = +USER_LIBS_NEON = + +# android optimizations + +ANDROID_COMPILER_OPTIMIZATION = -Os + +NDK_PLATFORM = android-8 + +# uncomment this for custom application name (if the folder name is different than the application name) +#APPNAME = folderName + +# uncomment this for custom package name, must be the same as the java package that contains OFActivity +#PKGNAME = cc.openframeworks.$(APPNAME) + + + + + +# linux arm flags + +LINUX_ARM7_COMPILER_OPTIMIZATIONS = -march=armv7-a -mtune=cortex-a8 -finline-functions -funroll-all-loops -O3 -funsafe-math-optimizations -mfpu=neon -ftree-vectorize -mfloat-abi=hard -mfpu=vfp + + +CXX=colorgcc diff --git a/07_performance/src/FFTOctaveAnalyzer.cpp b/07_performance/src/FFTOctaveAnalyzer.cpp new file mode 100644 index 0000000..4c91eeb --- /dev/null +++ b/07_performance/src/FFTOctaveAnalyzer.cpp @@ -0,0 +1,98 @@ +#include "ofMain.h" +#include "FFTOctaveAnalyzer.h" + + +void FFTOctaveAnalyzer::setup(float samplingRate, int nBandsInTheFFT, int nAveragesPerOctave){ + + samplingRate = samplingRate; + nSpectrum = nBandsInTheFFT; + spectrumFrequencySpan = (samplingRate / 2.0f) / (float)(nSpectrum); + nAverages = nBandsInTheFFT; + // fe: 2f for octave bands, sqrt(2) for half-octave bands, cuberoot(2) for third-octave bands, etc + if (nAveragesPerOctave==0) // um, wtf? + nAveragesPerOctave = 1; + nAveragesPerOctave = nAveragesPerOctave; + averageFrequencyIncrement = pow(2.0f, 1.0f/(float)(nAveragesPerOctave)); + // this isn't currently configurable (used once here then no effect), but here's some reasoning: + // 43 is a good value if you want to approximate "computer" octaves: 44100/2/2/2/2/2/2/2/2/2/2 + // 55 is a good value if you'd rather approximate A-440 octaves: 440/2/2/2 + // 65 is a good value if you'd rather approximate "middle-C" octaves: ~262/2/2 + // you could easily double it if you felt the lowest band was just rumble noise (as it probably is) + // but don't go much smaller unless you have a huge fft window size (see below for more why) + // keep in mind, if you change it, that the number of actual bands may change +/-1, and + // for some values, the last averaging band may not be very useful (may extend above nyquist) + firstOctaveFrequency = 55.0f; + // for each spectrum[] bin, calculate the mapping into the appropriate average[] bin. + // this gives us roughly log-sized averaging bins, subject to how "fine" the spectrum bins are. + // with more spectrum bins, you can better map into the averaging bins (especially at low + // frequencies) or use more averaging bins per octave. with an fft window size of 2048, + // sampling rate of 44100, and first octave around 55, that's about enough to do half-octave + // analysis. if you don't have enough spectrum bins to map adequately into averaging bins + // at the requested number per octave then you'll end up with "empty" averaging bins, where + // there is no spectrum available to map into it. (so... if you have "nonreactive" averages, + // either increase fft buffer size, or decrease number of averages per octave, etc) + spe2avg = new int[nSpectrum]; + int avgidx = 0; + float averageFreq = firstOctaveFrequency; // the "top" of the first averaging bin + // we're looking for the "top" of the first spectrum bin, and i'm just sort of + // guessing that this is where it is (or possibly spectrumFrequencySpan/2?) + // ... either way it's probably close enough for these purposes + float spectrumFreq = spectrumFrequencySpan; + for (int speidx=0; speidx < nSpectrum; speidx++) { + while (spectrumFreq > averageFreq) { + avgidx++; + averageFreq *= averageFrequencyIncrement; + } + spe2avg[speidx] = avgidx; + spectrumFreq += spectrumFrequencySpan; + } + nAverages = avgidx; + averages = new float[nAverages]; + peaks = new float[nAverages]; + peakHoldTimes = new int[nAverages]; + peakHoldTime = 0; // arbitrary + peakDecayRate = 0.9f; // arbitrary + linearEQIntercept = 1.0f; // unity -- no eq by default + linearEQSlope = 0.0f; // unity -- no eq by default +} + +void FFTOctaveAnalyzer::calculate(float * fftData){ + + int last_avgidx = 0; // tracks when we've crossed into a new averaging bin, so store current average + float sum = 0.0f; // running total of spectrum data + int count = 0; // count of spectrums accumulated (for averaging) + for (int speidx=0; speidx < nSpectrum; speidx++) { + count++; + sum += fftData[speidx] * (linearEQIntercept + (float)(speidx) * linearEQSlope); + int avgidx = spe2avg[speidx]; + if (avgidx != last_avgidx) { + + for (int j = last_avgidx; j < avgidx; j++){ + averages[j] = sum / (float)(count); + } + count = 0; + sum = 0.0f; + } + last_avgidx = avgidx; + } + // the last average was probably not calculated... + if ((count > 0) && (last_avgidx < nAverages)){ + averages[last_avgidx] = sum / (float)(count); + } + + // update the peaks separately + for (int i=0; i < nAverages; i++) { + if (averages[i] >= peaks[i]) { + // save new peak level, also reset the hold timer + peaks[i] = averages[i]; + peakHoldTimes[i] = peakHoldTime; + } else { + // current average does not exceed peak, so hold or decay the peak + if (peakHoldTimes[i] > 0) { + peakHoldTimes[i]--; + } else { + peaks[i] *= peakDecayRate; + } + } + } +} diff --git a/07_performance/src/FFTOctaveAnalyzer.h b/07_performance/src/FFTOctaveAnalyzer.h new file mode 100644 index 0000000..8fef773 --- /dev/null +++ b/07_performance/src/FFTOctaveAnalyzer.h @@ -0,0 +1,45 @@ + +#ifndef _FFTANALYZER +#define _FFTANALYZER + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + + +class FFTOctaveAnalyzer { + +public: + + //FFT fft; // a reference to the FFT instance + + float samplingRate; // sampling rate in Hz (needed to calculate frequency spans) + int nSpectrum; // number of spectrum bins in the fft + int nAverages; // number of averaging bins here + int nAveragesPerOctave; // number of averages per octave as requested by user + float spectrumFrequencySpan; // the "width" of an fft spectrum bin in Hz + float firstOctaveFrequency; // the "top" of the first averaging bin here in Hz + float averageFrequencyIncrement; // the root-of-two multiplier between averaging bin frequencies + float * averages; // the actual averages + float * peaks; // peaks of the averages, aka "maxAverages" in other implementations + int * peakHoldTimes; // how long to hold THIS peak meter? decay if == 0 + int peakHoldTime; // how long do we hold peaks? (in fft frames) + float peakDecayRate; // how quickly the peaks decay: 0f=instantly .. 1f=not at all + int * spe2avg; // the mapping between spectrum[] indices and averages[] indices + // the fft's log equalizer() is no longer of any use (it would be nonsense to log scale + // the spectrum values into log-sized average bins) so here's a quick-and-dirty linear + // equalizer instead: + float linearEQSlope; // the rate of linear eq + float linearEQIntercept; // the base linear scaling used at the first averaging bin + // the formula is: spectrum[i] * (linearEQIntercept + i * linearEQSlope) + // so.. note that clever use of it can also provide a "gain" control of sorts + // (fe: set intercept to 2f and slope to 0f to double gain) + + void setup(float samplingRate, int nBandsInTheFFT, int nAveragesPerOctave); + + void calculate(float * fftData); + +}; + + +#endif diff --git a/07_performance/src/fft.cpp b/07_performance/src/fft.cpp new file mode 100644 index 0000000..ca3217e --- /dev/null +++ b/07_performance/src/fft.cpp @@ -0,0 +1,489 @@ +/********************************************************************** + + fft.cpp + + + This class is a C++ wrapper for original code + written by Dominic Mazzoni in September 2000 + + This file contains a few FFT routines, including a real-FFT + routine that is almost twice as fast as a normal complex FFT, + and a power spectrum routine which is more convenient when + you know you don't care about phase information. It now also + contains a few basic windowing functions. + + Some of this code was based on a free implementation of an FFT + by Don Cross, available on the web at: + + http://www.intersrv.com/~dcross/fft.html + + The basic algorithm for his code was based on Numerical Recipes + in Fortran. I optimized his code further by reducing array + accesses, caching the bit reversal table, and eliminating + float-to-double conversions, and I added the routines to + calculate a real FFT and a real power spectrum. + + Note: all of these routines use single-precision floats. + I have found that in practice, floats work well until you + get above 8192 samples. If you need to do a larger FFT, + you need to use doubles. + +**********************************************************************/ + +#include "fft.h" +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +int **gFFTBitTable = NULL; +const int MaxFastBits = 16; + +int IsPowerOfTwo(int x) +{ + if (x < 2) + return false; + + if (x & (x - 1)) /* Thanks to 'byang' for this cute trick! */ + return false; + + return true; +} + +int NumberOfBitsNeeded(int PowerOfTwo) +{ + int i; + + if (PowerOfTwo < 2) { + fprintf(stderr, "Error: FFT called with size %d\n", PowerOfTwo); + exit(1); + } + + for (i = 0;; i++) + if (PowerOfTwo & (1 << i)) + return i; +} + +int ReverseBits(int index, int NumBits) +{ + int i, rev; + + for (i = rev = 0; i < NumBits; i++) { + rev = (rev << 1) | (index & 1); + index >>= 1; + } + + return rev; +} + +void InitFFT() +{ + gFFTBitTable = new int *[MaxFastBits]; + + int len = 2; + for (int b = 1; b <= MaxFastBits; b++) { + + gFFTBitTable[b - 1] = new int[len]; + + for (int i = 0; i < len; i++) + gFFTBitTable[b - 1][i] = ReverseBits(i, b); + + len <<= 1; + } +} + +inline int FastReverseBits(int i, int NumBits) +{ + if (NumBits <= MaxFastBits) + return gFFTBitTable[NumBits - 1][i]; + else + return ReverseBits(i, NumBits); +} + +/* + * Complex Fast Fourier Transform + */ + +void FFT(int NumSamples, + bool InverseTransform, + float *RealIn, float *ImagIn, float *RealOut, float *ImagOut) +{ + int NumBits; /* Number of bits needed to store indices */ + int i, j, k, n; + int BlockSize, BlockEnd; + + double angle_numerator = 2.0 * M_PI; + float tr, ti; /* temp real, temp imaginary */ + + if (!IsPowerOfTwo(NumSamples)) { + fprintf(stderr, "%d is not a power of two\n", NumSamples); + exit(1); + } + + if (!gFFTBitTable) + InitFFT(); + + if (InverseTransform) + angle_numerator = -angle_numerator; + + NumBits = NumberOfBitsNeeded(NumSamples); + + /* + ** Do simultaneous data copy and bit-reversal ordering into outputs... + */ + + for (i = 0; i < NumSamples; i++) { + j = FastReverseBits(i, NumBits); + RealOut[j] = RealIn[i]; + ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; + } + + /* + ** Do the FFT itself... + */ + + BlockEnd = 1; + for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { + + double delta_angle = angle_numerator / (double) BlockSize; + + float sm2 = sin(-2 * delta_angle); + float sm1 = sin(-delta_angle); + float cm2 = cos(-2 * delta_angle); + float cm1 = cos(-delta_angle); + float w = 2 * cm1; + float ar0, ar1, ar2, ai0, ai1, ai2; + + for (i = 0; i < NumSamples; i += BlockSize) { + ar2 = cm2; + ar1 = cm1; + + ai2 = sm2; + ai1 = sm1; + + for (j = i, n = 0; n < BlockEnd; j++, n++) { + ar0 = w * ar1 - ar2; + ar2 = ar1; + ar1 = ar0; + + ai0 = w * ai1 - ai2; + ai2 = ai1; + ai1 = ai0; + + k = j + BlockEnd; + tr = ar0 * RealOut[k] - ai0 * ImagOut[k]; + ti = ar0 * ImagOut[k] + ai0 * RealOut[k]; + + RealOut[k] = RealOut[j] - tr; + ImagOut[k] = ImagOut[j] - ti; + + RealOut[j] += tr; + ImagOut[j] += ti; + } + } + + BlockEnd = BlockSize; + } + + /* + ** Need to normalize if inverse transform... + */ + + if (InverseTransform) { + float denom = (float) NumSamples; + + for (i = 0; i < NumSamples; i++) { + RealOut[i] /= denom; + ImagOut[i] /= denom; + } + } +} + +/* + * Real Fast Fourier Transform + * + * This function was based on the code in Numerical Recipes in C. + * In Num. Rec., the inner loop is based on a single 1-based array + * of interleaved real and imaginary numbers. Because we have two + * separate zero-based arrays, our indices are quite different. + * Here is the correspondence between Num. Rec. indices and our indices: + * + * i1 <-> real[i] + * i2 <-> imag[i] + * i3 <-> real[n/2-i] + * i4 <-> imag[n/2-i] + */ + +void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut) +{ + int Half = NumSamples / 2; + int i; + + float theta = M_PI / Half; + + float *tmpReal = new float[Half]; + float *tmpImag = new float[Half]; + + for (i = 0; i < Half; i++) { + tmpReal[i] = RealIn[2 * i]; + tmpImag[i] = RealIn[2 * i + 1]; + } + + FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut); + + float wtemp = float (sin(0.5 * theta)); + + float wpr = -2.0 * wtemp * wtemp; + float wpi = float (sin(theta)); + float wr = 1.0 + wpr; + float wi = wpi; + + int i3; + + float h1r, h1i, h2r, h2i; + + for (i = 1; i < Half / 2; i++) { + + i3 = Half - i; + + h1r = 0.5 * (RealOut[i] + RealOut[i3]); + h1i = 0.5 * (ImagOut[i] - ImagOut[i3]); + h2r = 0.5 * (ImagOut[i] + ImagOut[i3]); + h2i = -0.5 * (RealOut[i] - RealOut[i3]); + + RealOut[i] = h1r + wr * h2r - wi * h2i; + ImagOut[i] = h1i + wr * h2i + wi * h2r; + RealOut[i3] = h1r - wr * h2r + wi * h2i; + ImagOut[i3] = -h1i + wr * h2i + wi * h2r; + + wr = (wtemp = wr) * wpr - wi * wpi + wr; + wi = wi * wpr + wtemp * wpi + wi; + } + + RealOut[0] = (h1r = RealOut[0]) + ImagOut[0]; + ImagOut[0] = h1r - ImagOut[0]; + + delete[]tmpReal; + delete[]tmpImag; +} + +/* + * PowerSpectrum + * + * This function computes the same as RealFFT, above, but + * adds the squares of the real and imaginary part of each + * coefficient, extracting the power and throwing away the + * phase. + * + * For speed, it does not call RealFFT, but duplicates some + * of its code. + */ + +void PowerSpectrum(int NumSamples, float *In, float *Out) +{ + int Half = NumSamples / 2; + int i; + + float theta = M_PI / Half; + + float *tmpReal = new float[Half]; + float *tmpImag = new float[Half]; + float *RealOut = new float[Half]; + float *ImagOut = new float[Half]; + + for (i = 0; i < Half; i++) { + tmpReal[i] = In[2 * i]; + tmpImag[i] = In[2 * i + 1]; + } + + FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut); + + float wtemp = float (sin(0.5 * theta)); + + float wpr = -2.0 * wtemp * wtemp; + float wpi = float (sin(theta)); + float wr = 1.0 + wpr; + float wi = wpi; + + int i3; + + float h1r, h1i, h2r, h2i, rt, it; + //float total=0; + + for (i = 1; i < Half / 2; i++) { + + i3 = Half - i; + + h1r = 0.5 * (RealOut[i] + RealOut[i3]); + h1i = 0.5 * (ImagOut[i] - ImagOut[i3]); + h2r = 0.5 * (ImagOut[i] + ImagOut[i3]); + h2i = -0.5 * (RealOut[i] - RealOut[i3]); + + rt = h1r + wr * h2r - wi * h2i; //printf("Realout%i = %f",i,rt);total+=fabs(rt); + it = h1i + wr * h2i + wi * h2r; // printf(" Imageout%i = %f\n",i,it); + + Out[i] = rt * rt + it * it; + + rt = h1r - wr * h2r + wi * h2i; + it = -h1i + wr * h2i + wi * h2r; + + Out[i3] = rt * rt + it * it; + + wr = (wtemp = wr) * wpr - wi * wpi + wr; + wi = wi * wpr + wtemp * wpi + wi; + } + //printf("total = %f\n",total); + rt = (h1r = RealOut[0]) + ImagOut[0]; + it = h1r - ImagOut[0]; + Out[0] = rt * rt + it * it; + + rt = RealOut[Half / 2]; + it = ImagOut[Half / 2]; + Out[Half / 2] = rt * rt + it * it; + + delete[]tmpReal; + delete[]tmpImag; + delete[]RealOut; + delete[]ImagOut; +} + +/* + * Windowing Functions + */ + +int NumWindowFuncs() +{ + return 4; +} + +char *WindowFuncName(int whichFunction) +{ + switch (whichFunction) { + default: + case 0: + return "Rectangular"; + case 1: + return "Bartlett"; + case 2: + return "Hamming"; + case 3: + return "Hanning"; + } +} + +void WindowFunc(int whichFunction, int NumSamples, float *in) +{ + int i; + + if (whichFunction == 1) { + // Bartlett (triangular) window + for (i = 0; i < NumSamples / 2; i++) { + in[i] *= (i / (float) (NumSamples / 2)); + in[i + (NumSamples / 2)] *= + (1.0 - (i / (float) (NumSamples / 2))); + } + } + + if (whichFunction == 2) { + // Hamming + for (i = 0; i < NumSamples; i++) + in[i] *= 0.54 - 0.46 * cos(2 * M_PI * i / (NumSamples - 1)); + } + + if (whichFunction == 3) { + // Hanning + for (i = 0; i < NumSamples; i++) + in[i] *= 0.50 - 0.50 * cos(2 * M_PI * i / (NumSamples - 1)); + } +} + +/* constructor */ +fft::fft() { +} + +/* destructor */ +fft::~fft() { + + +} + +/* Calculate the power spectrum */ +void fft::powerSpectrum(int start, int half, float *data, int windowSize,float *magnitude,float *phase, float *power, float *avg_power) { + int i; + int windowFunc = 3; + float total_power = 0.0f; + + /* processing variables*/ + float *in_real = new float[windowSize]; + float *in_img = new float[windowSize]; + float *out_real = new float[windowSize]; + float *out_img = new float[windowSize]; + + for (i = 0; i < windowSize; i++) { + in_real[i] = data[start + i]; + } + + WindowFunc(windowFunc, windowSize, in_real); + RealFFT(windowSize, in_real, out_real, out_img); + + for (i = 0; i < half; i++) { + /* compute power */ + power[i] = out_real[i]*out_real[i] + out_img[i]*out_img[i]; + total_power += power[i]; + /* compute magnitude and phase */ + magnitude[i] = 2.0*sqrt(power[i]); + + if (magnitude[i] < 0.000001){ // less than 0.1 nV + magnitude[i] = 0; // out of range + } else { + magnitude[i] = 20.0*log10(magnitude[i] + 1); // get to to db scale + } + + + phase[i] = atan2(out_img[i],out_real[i]); + } + /* calculate average power */ + *(avg_power) = total_power / (float) half; + + delete[]in_real; + delete[]in_img; + delete[]out_real; + delete[]out_img; +} + + +void fft::inversePowerSpectrum(int start, int half, int windowSize, float *finalOut,float *magnitude,float *phase) { + int i; + int windowFunc = 3; + + /* processing variables*/ + float *in_real = new float[windowSize]; + float *in_img = new float[windowSize]; + float *out_real = new float[windowSize]; + float *out_img = new float[windowSize]; + + /* get real and imag part */ + for (i = 0; i < half; i++) { + in_real[i] = magnitude[i]*cos(phase[i]); + in_img[i] = magnitude[i]*sin(phase[i]); + } + + /* zero negative frequencies */ + for (i = half; i < windowSize; i++) { + in_real[i] = 0.0; + in_img[i] = 0.0; + } + + FFT(windowSize, 1, in_real, in_img, out_real, out_img); // second parameter indicates inverse transform + WindowFunc(windowFunc, windowSize, out_real); + + for (i = 0; i < windowSize; i++) { + finalOut[start + i] += out_real[i]; + } + + delete[]in_real; + delete[]in_img; + delete[]out_real; + delete[]out_img; +} + + diff --git a/07_performance/src/fft.h b/07_performance/src/fft.h new file mode 100644 index 0000000..bae5b37 --- /dev/null +++ b/07_performance/src/fft.h @@ -0,0 +1,33 @@ + +#ifndef _FFT +#define _FFT + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + + +class fft { + + public: + + fft(); + ~fft(); + + /* Calculate the power spectrum */ + void powerSpectrum(int start, int half, float *data, int windowSize,float *magnitude,float *phase, float *power, float *avg_power); + /* ... the inverse */ + void inversePowerSpectrum(int start, int half, int windowSize, float *finalOut,float *magnitude,float *phase); + + void processLogXScale(const float * data,unsigned int insize, double fMax, + float * avout, float * pkout, unsigned int outsize, + float f1, float f2); + + + float avout[15]; + float pkout[15]; + +}; + + +#endif diff --git a/07_performance/src/main.cpp b/07_performance/src/main.cpp new file mode 100644 index 0000000..71c3117 --- /dev/null +++ b/07_performance/src/main.cpp @@ -0,0 +1,18 @@ +#include "ofMain.h" +#include "testApp.h" + +//======================================================================== +int main( ){ + + //ofSetupOpenGL(4080,768, OF_WINDOW); // <-------- setup the GL context + //ofSetupOpenGL(2400,450, OF_WINDOW); // <-------- setup the GL context + ofSetupOpenGL(ofxFensterManager::get(),4080,768, OF_WINDOW); //2048,768 + + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + + ofRunFensterApp(new testApp); + +} diff --git a/07_performance/src/oni.cpp b/07_performance/src/oni.cpp new file mode 100644 index 0000000..1fbd096 --- /dev/null +++ b/07_performance/src/oni.cpp @@ -0,0 +1,267 @@ +#include "oni.h" + +void syncOniPlayer::addPlayer(string name){ + //ofxOpenNI *o=new ofxOpenNI; + //o->setupFromONI(name,true); + //o->setPaused(true); + //players.push_back(o); + players.push_back(NULL); + filenames.push_back(name); + soundplayer.setLoop(false); + //players[players.size()-1]->setSpeed(0.0f); + //players[players.size()-1]->setup(true); + //players[players.size()-1]->start(); + //players[players.size()-1]->startPlayer(name); +} +void syncOniPlayer::play(){ + for (int i=0;i<players.size();i++) { + players[i]=new ofxOpenNI(); + //players[i]->setSafeThreading(true); + players[i]->setupFromONI(filenames[i],true); + //players[i]->setSafeThreading(true); + //players[i]->addDepthGenerator(); + //players[i]->addImageGenerator(); + //players[i]->setRegister(true); + players[i]->setLooped(false); + //players[i]->setBaseUserClass(user); + players[i]->start(); + //players[players.size()-1]->setSpeed(1.0f); + if (audio!="") { + soundplayer.loadSound(audio); + soundplayer.play(); + }; + //sleep(2); + drawable=true; + startTime=ofGetElapsedTimef(); + playerActive=true; + } +} +void syncOniPlayer::update(){ + for (int i=0;i<players.size();i++) { + if (playerActive) players[i]->update(); + } +} +void syncOniPlayer::pause(){ + for (int i=0;i<players.size();i++) { + //players[players.size()-1]->setSpeed(0.0f); + players[i]->setPaused(true); + } +} +bool syncOniPlayer::isPlaying(){ + if (players.size()) return players[0]->isPlaying(); + else return false; +} +int syncOniPlayer::getCurrentFrame(){ + if (players.size()) return players[0]->getCurrentFrame(); + else return -1; +} +float syncOniPlayer::getPosition(){ + if (players.size()) return players[0]->getPosition(); + else return -1.0f; +} +void syncOniPlayer::drawWindows(){ + if (!drawable) return; + for (int i=0;i<players.size();i++) { + if (players[i]==NULL) break; + ofTranslate(0, i * 400); + players[i]->drawDepth(50, 0,520,390); + players[i]->drawImage(600, 0,520,390); + + + } +} +void syncOniPlayer::drawCloud(int step){ + int count; + for (int n=0;n<players.size();n++) { + + + const XnDepthPixel* depthmap=players[n]->getDepthGenerator().GetDepthMap(); + //uint16_t* depthpixels=depthmap.getPixels(); + int range=1700; + + int depthW=players[n]->getWidth(); + int depthH=players[n]->getHeight(); + + for (int i=0;i<depthW;i+=step) { + + glBegin(GL_LINES); + + for (int j=0;j<depthH;j+=step) { + + + ofPoint p= players[n]->projectiveToWorld(ofPoint(i,j,(float)(depthmap[j*depthW+i]))); + //ofPoint p= projectiveToWorld(ofPoint(i,j,(float)depthmap[j*dmw+i])); + + if (p.z == 0 || p.z>range) continue; // gets rid of background + + + glColor4ub((unsigned char)255, (unsigned char)255, (unsigned char)255, (unsigned char)255); + glVertex3f(p.x, p.y, p.z); + //if (i==320&&j==160) cerr<<"world point: "<<p.x<<","<<p.y<<","<<p.z<<endl; + } + + glEnd(); + } + + } + + return; +} +void syncOniPlayer::drawPoints(float _birth,float life,float dx,float dy, float dz,float size){ + if (!drawable) return; + + //glEnable(GL_PROGRAM_POINT_SIZE); + //glEnable(GL_POINT_SMOOTH); + //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + //glPointSize( size); + //glBegin(GL_POINTS); + + if (playerActive){ + //apply envelope + float attackSeconds=0.5f; + float playOutFraction=0.9f; + float birth; + float clipTime=ofGetElapsedTimef()-startTime; + if (clipTime<attackSeconds) { + //ramp in + birth=_birth*(clipTime/attackSeconds); + } + else if (players[0]->getPosition()>playOutFraction) { + //cerr<<"playing out!"<<endl; + birth=_birth*(1.0f-((players[0]->getPosition()-playOutFraction)/(1.0f-playOutFraction))); + //if it reaches the end stop creating points but allow old points to play out + if (players[0]->getPosition()>0.99) playerActive=false; + } + else birth=_birth; + + //cerr<<birth<<" "<<clipTime<<" "<<players[0]->getPosition()<<endl; + + const XnDepthPixel* depthmap=players[0]->getDepthGenerator().GetDepthMap(); + const ofPixels& pixels=players[0]->getImagePixels(); + int range=1700; + int dmw=players[0]->getWidth(); + int dmh=players[0]->getHeight(); + if (dmw&&dmh){ + int step=pixels.getWidth()/dmw; + for (int o=0;o<birth;o++) { + int i=ofRandom(dmw); + int j=ofRandom(dmh); + ofPoint p= players[0]->projectiveToWorld(ofPoint(i,j,(float)depthmap[j*dmw+i])); + if (p.z <100 || p.z>range) continue; + //points.push_back(fpoint(p.x, p.y, p.z,pixels[((j*step*dmw)+(i*step))*3],pixels[((j*step*dmw)+(i*step))*3]+1,pixels[((j*step*dmw)+(i*step))*3]+2)); + //fpoint f=fpoint(p.x, p.y, p.z,pixels[((j*step*dmw)+(i*step))*3],pixels[((j*step*dmw)+(i*step))*3]+1,pixels[((j*step*dmw)+(i*step))*3]+2); + //f.draw(life,dx,dy,dz); + if (pointPool.size()) {//take 1st dead particle + points[(*pointPool.begin())].setup(p.x, p.y, p.z, + LUT[pixels[((j*step*dmw)+(i*step))*3]], + LUT[pixels[((j*step*dmw)+(i*step))*3]+1], + LUT[pixels[((j*step*dmw)+(i*step))*3]+2] + ); + pointPool.erase(pointPool.begin()); + } + else {//make a new one + points.push_back(fpoint(p.x, p.y, p.z,pixels[((j*step*dmw)+(i*step))*3],pixels[((j*step*dmw)+(i*step))*3]+1,pixels[((j*step*dmw)+(i*step))*3]+2)); + } + } + } + } + for (int i=0;i<points.size();i++){ + if (!points[i].draw(life,dx,dy,dz,size)) { + pointPool.insert(i); + } + } + //glEnd(); + glDisable( GL_BLEND ); + //glDisable(GL_PROGRAM_POINT_SIZE); +} +int syncOniPlayer::getNumParticles(){ + return points.size()-pointPool.size(); +} +string syncOniPlayer::getCurrentFile(){ + return filenames[0]+" "+audio; +} +void syncOniPlayer::stop(){ + soundplayer.stop(); + for (int i=0;i<players.size();i++) { + if (players[i]!=NULL) { + players[i]->stop(); + delete players[i]; + players[i]=NULL; + } + } + drawable=false; + playerActive=false; +} +//================= +void oniManager::init(const char* filename){ + playing=-1; + int numDevices=1; + string f=string(filename); + if( !XML.loadFile(f) ){ + printf("unable to load recordings, check data/ folder\n"); + }else{ + if(XML.pushTag("TRSS")) { + int num=XML.getNumTags("rec"); + if(num) { + for (int i=0;i<num;i++) { + players.push_back(syncOniPlayer()); + players[i].addPlayer(XML.getAttribute("rec","left","",i)); + if (numDevices==2) { + players[i].addPlayer(XML.getAttribute("rec","right","",i)); + } + players[i].audio=XML.getAttribute("rec","audio","",i); + } + } + else printf("no recordings found!\n"); + } + } +} +void oniManager::startPlayer(int newplayer){ + if (players.size()>newplayer){ + if (playing>-1) players[playing].stop(); + usleep(5000); + playing=newplayer; + players[playing].play(); + } +} +string oniManager::getCurrentFile(){ + if (players.size()>playing&&playing>-1) return players[playing].getCurrentFile(); + else return ""; +} +int oniManager::getNumClips(){ + return players.size(); +} +void oniManager::update(){ + //if (playing>-1&&!players[playing].isPlaying()) players[playing].play(); + if (players.size()>playing&&playing>-1) players[playing].update(); +} +void oniManager::drawWindows(){ + if (players.size()>playing&&playing>-1) players[playing].drawWindows(); +} +void oniManager::drawCloud(int step){ + if (players.size()>playing&&playing>-1) players[playing].drawCloud(step); +} +void oniManager::next(){ + int newp=(playing+1)%players.size(); + startPlayer(newp); +} +void oniManager::previous(){ + int newp=playing-1<0?players.size()-1:playing-1; + startPlayer(newp); +} +int oniManager::getNumParticles(){ + if (players.size()>playing&&playing>-1) return players[playing].getNumParticles(); + else return 0; +} +void oniManager::drawPoints(float size,float birth,float life,float dx,float dy, float dz){ + if (players.size()>playing&&playing>-1) { + players[playing].drawPoints(birth,life,dx,dy,dz,size); + } +} +syncOniPlayer* oniManager::getCurrentPlayer(){ + if (players.size()>playing&&playing>-1) return &players[playing]; + else return NULL; +} + diff --git a/07_performance/src/oni.h b/07_performance/src/oni.h new file mode 100644 index 0000000..4483a35 --- /dev/null +++ b/07_performance/src/oni.h @@ -0,0 +1,104 @@ +#include "ofMain.h" +#include "ofxXmlSettings.h" +#include "ofxOpenNI.h" + +//a colour video particle +class fpoint{ + public: + fpoint(float _x,float _y, float _z, unsigned char _r,unsigned char _g,unsigned char _b){ + setup(x,y,z,r,g,b); + } + void setup(float _x,float _y, float _z, unsigned char _r,unsigned char _g,unsigned char _b){ + x=_x;y=_y;z=_z;r=_r;g=_g;b=_b;st=ofGetElapsedTimef();active=true; + } + float x,y,z; + float st; + unsigned char r,g,b; + bool active; + bool draw(float life,float dx,float dy,float dz,float size=5.0f){ + if (!active) { + return true; + } + float l=ofGetElapsedTimef()-st; + if (life>l) { + glPointSize((1.0f-(l/life))*size); + glBegin(GL_POINTS); + glColor3ub(r,g,b); + //glColor4ub(r,g,b,(unsigned char)255); // ((l/life)*255.0f)); + glVertex3f(x-(pow(l,2)*dx),y-(pow(l,2)*dy),z-(pow(l,2)*dz)); + glEnd(); + return true; + } + else { + active=false; + return false; + } + } +}; +class syncOniPlayer{ + public: + syncOniPlayer() { + drawable=false; + gamma=3.0f; + LUT=NULL; + makeLUT(); + playerActive=false; + } + ~syncOniPlayer(){ + stop(); + //if (LUT) delete[] LUT; + } + void makeLUT(){ + if (NULL==LUT){ + LUT=new uint8_t[0xff]; + } + for (int i=0;i<0xFF;i++) { + LUT[i]=(uint8_t)(pow(((float)i)/255.0f,gamma)*255.0f); + } + } + void addPlayer(string name); + void play(); + void update(); + void pause(); + bool isPlaying(); + int getCurrentFrame(); + float getPosition(); + int getNumParticles(); + string getCurrentFile(); + void drawWindows(); + void drawCloud(int step); + void drawPoints(float birth,float life,float dx,float dy, float dz,float size); + void stop(); + string audio; + + private: + vector<ofxOpenNI*> players; + vector<string> filenames; + ofSoundPlayer soundplayer; + bool drawable; + vector<fpoint> points; + set<int> pointPool; + float gamma; + uint8_t *LUT; + float startTime; + bool playerActive; +}; +//======================================== +class oniManager{ + public: + void init(const char* filename); + void startPlayer(int num); + int getNumClips(); + int getNumParticles(); + syncOniPlayer* getCurrentPlayer(); + string getCurrentFile(); + void update(); + void drawWindows(); + void drawCloud(int step); + void drawPoints(float size,float birth,float life,float dx,float dy, float dz); + void previous(); + void next(); + int playing; + ofxXmlSettings XML; + vector<syncOniPlayer> players; +};
\ No newline at end of file diff --git a/07_performance/src/testApp.cpp b/07_performance/src/testApp.cpp new file mode 100644 index 0000000..a5cbf55 --- /dev/null +++ b/07_performance/src/testApp.cpp @@ -0,0 +1,1039 @@ +#include "testApp.h" + + /* + maybe draw pixel lines to a range of buffers and then play them in various 3D directions + pixel lines can have nice, missing corners and be nicely smoothed + + is it insane not to do this in vvvv + + can there be an editing interface + + have a play with vvvv/ max and try to replicate this idea QUICKLY? + */ + + +//-------------------------------------------------------------- +void testApp::setup(){ + + midiIn.listPorts(); + + midiIn.openPort(0); //this was 1 on linux, 0 on OSX + midiIn.addListener(this); + + midiOut.listPorts(); + midiOut.openPort(0); //this was 1 on linux, 0 on OSX + + // 0 output channeLs, + // 2 input channels + // 44100 samples per second + // BUFFER_SIZE samples per buffer + // 4 num buffers (latency) + + soundStream.listDevices(); + + left = new float[BUFFER_SIZE]; + right = new float[BUFFER_SIZE]; + + //soundStream.setDeviceID(7); //ignore to use default? + soundStream.setup(this, 0, 2, 44100, BUFFER_SIZE, 4); + //soundStream.setup(this, 0, 4, 44100, BUFFER_SIZE, 4); + + ofSetHexColor(0x666666); + + lFFTanalyzer.setup(44100, BUFFER_SIZE/2,32); + + lFFTanalyzer.peakHoldTime = 15; // hold longer + lFFTanalyzer.peakDecayRate = 0.95f; // decay slower + lFFTanalyzer.linearEQIntercept = 0.9f; // reduced gain at lowest frequency + lFFTanalyzer.linearEQSlope = 0.01f; // increasing gain at higher frequencies + + rFFTanalyzer.setup(44100, BUFFER_SIZE/2,32); + + rFFTanalyzer.peakHoldTime = 15; // hold longer + rFFTanalyzer.peakDecayRate = 0.95f; // decay slower + rFFTanalyzer.linearEQIntercept = 0.9f; // reduced gain at lowest frequency + rFFTanalyzer.linearEQSlope = 0.01f; // increasing gain at higher frequencies + +/* + if (4chan) + { + lFFTanalyzer2.setup(44100, BUFFER_SIZE/2,32); + + lFFTanalyzer2.peakHoldTime = 15; // hold longer + lFFTanalyzer2.peakDecayRate = 0.95f; // decay slower + lFFTanalyzer2.linearEQIntercept = 0.9f; // reduced gain at lowest frequency + lFFTanalyzer2.linearEQSlope = 0.01f; // increasing gain at higher frequencies + + rFFTanalyzer2.setup(44100, BUFFER_SIZE/2,32); + + rFFTanalyzer2.peakHoldTime = 15; // hold longer + rFFTanalyzer2.peakDecayRate = 0.95f; // decay slower + rFFTanalyzer2.linearEQIntercept = 0.9f; // reduced gain at lowest frequency + rFFTanalyzer2.linearEQSlope = 0.01f; // increasing gain at higher frequencies + } + */ + + ofSetFrameRate(60); + + ofBackground(0,0,0); + + F_movieSpeed=0.0; + + //blendImage.loadImage("blend01.png"); + blendImage.loadMovie("blend.mp4"); + blendImage.play(); + blendImage.setLoopState(OF_LOOP_NORMAL); + blendImage.setSpeed(F_movieSpeed); + + I_movieSource=0; + I_moviePlaying=0; + + //renderImage.allocate(ofGetWidth(),ofGetHeight(),GL_RGB); + renderImage.allocate(4080,768,GL_RGB); + maskShader.load("composite"); + + //testImage.loadImage("mask.png"); + + + maskShader.begin(); + maskShader.setUniformTexture("Tex0", blendImage.getTextureReference(), 0); + maskShader.setUniformTexture("Tex1", renderImage.getTextureReference(), 1); + maskShader.end(); + + showFPS=false; + + //defaults + + F_scale=0; + F_drawFrames=10; + F_drawStep=0; + F_drawDecay=0.95; + F_lineWidth=1.0; //1.0; + F_drawAxis=90; //Y + + + F_xRotate=0; + F_yRotate=0; + F_zRotate=0; + + F_xRotation=180; + F_yRotation=180; //was 180 + F_zRotation=0; + + F_particleAmount=2000; //100 + F_particleLife=0.75; //0.5 + F_particleSize=16.0; //1.0; + + I_fade1=0; + I_fade2=0; + + thisFFTbuffer=0; + + lastFrameTime=ofGetElapsedTimef(); + + draworder=true; //forwards; + + visMode=WAVEFORM; + + B_vSync=true; + B_fill=true; + + inputMode=PICTURE; + + + gammamap=new unsigned char[256]; + + + whitePt=0.9; + blackPt=0.3; + gamma=1.0; + + //calc gamma map + for (int i=0;i<256;i++){ + float ewp=max(whitePt,blackPt+0.1f); //limit range to 0.1 + gammamap[i]=(unsigned char)(pow(min(1.0f,max(0.0f,(((float(i)/255.0f)-blackPt)/(ewp-blackPt)))),gamma)*255.0); + } + + B_glitch=false; + + blanker.allocate(64,64,OF_IMAGE_COLOR); + // blanker.loadImage("black.png"); + + + fullScreen=false; + + setMidiState(); + + receiver.setup(OSCPORT); + + target.setPosition(0,0,0); + camera.setPosition(0,0,-700); + camera.lookAt(target,ofVec3f(0,1,0)); + narrator.init("TRSS_nesbitt_recordings.xml"); + + if( !XML.loadFile("videos.xml") ){ + printf("unable to load videos, check data/ folder\n"); + }else{ + if(XML.pushTag("TRSS")) { + int num=XML.getNumTags("video"); + if(num) { + int i; + for (i=0;i<num;i++) { + videoclips.push_back(ofVideoPlayer()); + videoclips[i].loadMovie(XML.getAttribute("video","file","",i)); + videoclips[i].setLoopState(OF_LOOP_NONE); + videoclips[i].stop(); + } + cerr<<"loaded "<<i<<" video clips"<<endl; + } + else printf("no video clips found!\n"); + } + } + + xOffs=startX=yOffs=startY=0; + xModel=0; + yModel=0; + zModel=-1050; + sModel=4.0f; +}; + + + + +//-------------------------------------------------------------- +void testApp::update(){ + + // check for waiting messages + while(receiver.hasWaitingMessages()){ + // get the next message + ofxOscMessage m; + receiver.getNextMessage(&m); + + + ///mrmr/pushbutton/6/Pauls-iPad 1000 + + + vector<string> path; + explode(m.getAddress(),'/', back_inserter(path)); + + cerr<<"OSC: "<<m.getAddress()<<endl; + + if (path.size()>1) { + if (path[1]=="mrmr"){ + if (path.size()>3){ + if (path[2]=="pushbutton"){ + int channel=ofToInt(path[3]); + if (channel>12) channel--; //12 is missing + if (m.getArgAsInt32(0)==1000) { + for (int i=0;i<videoclips.size();i++) { + videoclips[i].stop(); + videoclips[i].setPosition(0.01f); + } + videoclips[channel].play(); + } + } + } + } + else { + string type=path[1]; + if (type=="narrator"||type=="video") { + int channel=ofToInt(path[2])-1; + int data=m.getArgAsInt32(0); + + cerr<<"type: "<<type<<" channel: "<<channel<<" data: "<<data<<endl; + + if (type=="video"){ + if ((channel > -1)&&videoclips.size()>channel) { + if (data>0) { + cerr<<"playing video "<<channel<<endl; + videoclips[channel].play(); + } + } + } + if (type=="narrator"){ + if ((channel > -1)&&narrator.getNumClips()>channel) { + if (data>0) { //???doesn't seem to work + cerr<<"playing narrator "<<channel<<endl; + narrator.startPlayer(channel); + } + } + } + } + } + } + } + + + if (I_movieSource!=I_moviePlaying) { + blendImage.stop(); + switch(I_movieSource){ + case 0: + blendImage.loadMovie("gradblend.mov"); + break; + case 1: + blendImage.loadMovie("gradblend01.mov"); + break; + case 2: + blendImage.loadMovie("ll_waltz1.mov"); + break; + case 3: + blendImage.loadMovie("ll_longtrains.avi"); + break; + + } + blendImage.play(); + blendImage.setLoopState(OF_LOOP_NORMAL); + I_moviePlaying=I_movieSource; + } + blendImage.setSpeed(F_movieSpeed); + //blendImage.idleMovie(); + + for (int i=0;i<videoclips.size();i++) { + videoclips[i].update(); + if (videoclips[i].getPosition()>0.99f) videoclips[i].stop(); + } + + narrator.update(); + + xOffs*=.95; + yOffs*=.95; + +} + +//-------------------------------------------------------------- +void testApp::draw(){ + ofSetVerticalSync(B_vSync); + + + + static int index=0; + float lavg_power = 0.0f; + float ravg_power = 0.0f; + + if (visMode==FFT_RAW||visMode==FFT_AVG) { + myfft.powerSpectrum(0,(int)BUFFER_SIZE/2, left,BUFFER_SIZE,&lmagnitude[0],&lphase[0],&lpower[0],&lavg_power); + myfft.powerSpectrum(0,(int)BUFFER_SIZE/2, right,BUFFER_SIZE,&rmagnitude[0],&rphase[0],&rpower[0],&ravg_power); + } + if (visMode==FFT_AVG) { + lFFTanalyzer.calculate(lmagnitude); + rFFTanalyzer.calculate(rmagnitude); + } + + thisFFTbuffer=(thisFFTbuffer-1); + thisFFTbuffer=thisFFTbuffer<0?BUFFER_FRAMES-1:thisFFTbuffer; + + switch(visMode) { + case FFT_AVG: + for (int i=0;i<rFFTanalyzer.nAverages;i++) { + FFTbuffer[0][i][thisFFTbuffer]=lFFTanalyzer.averages[i]; + FFTbuffer[1][i][thisFFTbuffer]=rFFTanalyzer.averages[i]; + } + break; + case FFT_RAW: + for (int i=0;i<BUFFER_SIZE;i++) { + FFTbuffer[0][i][thisFFTbuffer]=lmagnitude[i]*3; + FFTbuffer[1][i][thisFFTbuffer]=rmagnitude[i]*3; + } + break; + case WAVEFORM: + for (int i=0;i<BUFFER_SIZE/2;i++) { + FFTbuffer[0][i][thisFFTbuffer]=left[i]*100; + FFTbuffer[1][i][thisFFTbuffer]=right[i]*100; + } + break; + } + + //ofDisableAlphaBlending(); + + renderImage.begin(); //render to FOB + glDisable(GL_BLEND); + + float hw=ofGetWidth()/2; + float hh=ofGetHeight()/2; + float xStep = ((float)ofGetWidth())/(lFFTanalyzer.nAverages*2); + float zStep = ((float)ofGetWidth())/F_drawFrames; + + float newTime=ofGetElapsedTimef(); + float interval=newTime-lastFrameTime; + lastFrameTime=newTime; + + + if (B_glitch) { + //glEnable(GL_BLEND); + //glBlendFunc(GL_CONSTANT_COLOR,GL_ONE); + //glBlendColor(1.0f,1.0f,1.0f,0.9f); + //blanker.draw(0,0,ofGetWidth(),ofGetHeight()); + } + else { + glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); + } + + + + + F_xRotation+=(F_xRotate*interval); + F_yRotation+=((F_yRotate+xOffs)*interval); + F_zRotation+=((F_zRotate+yOffs)*interval); + F_drawFrames=max(1.99f,min(F_drawFrames+(F_drawStep*interval),(float)BUFFER_FRAMES)); + + ofPushMatrix(); + //ofTranslate(hw,hh); + camera.begin(); + ofRotateY(F_yRotation); + ofRotateX(F_xRotation); + ofRotateZ(F_zRotation); + + /* + if (inputMode==GRABBER) { + ofSetColor(I_fade2,I_fade2,I_fade2); + ofPushMatrix(); + ofRotateX(90); + ofRotateZ(-90); + outTexture.draw(hw,-hh,-ofGetWidth(),ofGetHeight()); + ofPopMatrix(); + } + */ + GLfloat fogColor[4] = {0,0,0, 1.0}; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY,1.0 ); + glHint(GL_FOG_HINT, GL_DONT_CARE); + glFogf(GL_FOG_START, ofGetHeight()*(0.25+F_drawDecay)); + glFogf(GL_FOG_END, ofGetHeight()*(0.75+F_drawDecay)); + glEnable(GL_FOG); + + //reverse draw order when looking from back + int jStart=0; + int jEnd=F_drawFrames-1; + int jStep=1; + float F_yseg=F_yRotation; + while (F_yseg<-90) F_yseg+=360; + while (F_yseg>270) F_yseg-=360; + if (F_yseg>90) { + jStart=jEnd; + jEnd=0; + jStep=-1; + if (draworder) { + draworder=false; + //printf("switched to reverse order\n"); + } + } + else if (!draworder) { + draworder=true; + //printf("switched to normal order\n"); + } + + for (int j=jStart;j!=jEnd;j+=jStep) { + int fB=(thisFFTbuffer+j)%BUFFER_FRAMES; + + ofPushMatrix(); //coordinate transform for FFT draw direction + ofTranslate(0,0,(j*zStep)-hw); + ofRotateX(F_drawAxis); + + ofFill(); + ofSetColor(0,0,0); + if (B_fill) { + glBegin(GL_QUAD_STRIP); + for (int i = 0; i < lFFTanalyzer.nAverages-1; i++){ + glVertex3f((i*xStep)-hw,(FFTbuffer[0][i][fB] * F_scale),0); + glVertex3f((i*xStep)-hw,0,0); + } + for (int i =lFFTanalyzer.nAverages, k=lFFTanalyzer.nAverages-1; i < lFFTanalyzer.nAverages+rFFTanalyzer.nAverages; i++, k--){ + glVertex3f((i*xStep)-hw,(FFTbuffer[1][(lFFTanalyzer.nAverages+rFFTanalyzer.nAverages)-(i+1)][fB] * F_scale),0); + glVertex3f((i*xStep)-hw,0,0); + } + glEnd(); + } + + ofNoFill(); + ofSetLineWidth(F_lineWidth); + ofSetColor(I_fade1,I_fade1,I_fade1); + glBegin(GL_LINE_STRIP); + for (int i = 0; i < lFFTanalyzer.nAverages; i++){ + glVertex3f((i*xStep)-hw,(FFTbuffer[0][i][fB] * F_scale),0); + } + for (int i =lFFTanalyzer.nAverages, k=lFFTanalyzer.nAverages-1; i < lFFTanalyzer.nAverages+rFFTanalyzer.nAverages; i++, k--){ + glVertex3f((i*xStep)-hw,(FFTbuffer[1][(lFFTanalyzer.nAverages+rFFTanalyzer.nAverages)-(i+1)][fB] * F_scale),0); + } + glEnd(); + ofPopMatrix(); + } + camera.end(); + + ofPopMatrix(); + + for (int i=0;i<videoclips.size();i++) { + if (videoclips[i].isPlaying()) { + if (videoclips[i].getPosition()<0.1f) { + glEnable(GL_BLEND); + uint8_t b=uint8_t((videoclips[i].getPosition()/0.1f)*255); + ofSetColor(255,255,255,b); + } + else if (videoclips[i].getPosition()>0.8f) { + glEnable(GL_BLEND); + uint8_t b=uint8_t((1.0f-((videoclips[i].getPosition()-0.8f)/0.2f))*255); + ofSetColor(255,255,255,b); + } + else ofSetColor(255,255,255); + videoclips[i].draw(0,0,renderImage.getWidth()/3,renderImage.getHeight()); + videoclips[i].draw(renderImage.getWidth()*0.666666667,0,renderImage.getWidth()/3,renderImage.getHeight()); + glDisable(GL_BLEND); + } + } + + ofPushMatrix(); + //ofTranslate(hw,hh); + camera.begin(); + ofRotateY(F_yRotation); + ofRotateX(F_xRotation); + ofRotateZ(F_zRotation); + + ofPushMatrix(); + //ofTranslate(0,-100,-1050); + ofScale(sModel,sModel,sModel); + //ofTranslate(xModel*sModel,yModel*sModel,zModel*sModel); + ofTranslate(xModel,yModel,zModel); + + //narrator.drawCloud(2); + narrator.drawPoints(F_particleSize,F_particleAmount,F_particleLife,F_particleX,F_particleY,F_particleZ); + ofPopMatrix(); + + ofSetColor(255,255,255); + + + camera.end(); + + ofPopMatrix(); + renderImage.end(); + + + + + //ofEndShape(false); + + + //fbImage.grabScreen(0,0,ofGetWidth(),ofGetHeight()); +/* + + + + + ofSetHexColor(0xaaaaaa); + int width=2048/FFTanalyzer.nAverages; + for (int i = 0; i < FFTanalyzer.nAverages; i++){ + ofRect(i*width,768,width,-FFTanalyzer.averages[i] * 20); + } + ofSetHexColor(0xffffff); + for (int i = 0; i < (int)(BUFFER_SIZE/2 - 1); i++){ + ofRect(i,768-freq[i]*10.0f,1,1); + } + + ofSetHexColor(0xff0000); + for (int i = 0; i < FFTanalyzer.nAverages; i++){ + ofRect(i*width,768-FFTanalyzer.peaks[i] * 20,width,-1); + } + + float avgStep = 1024/FFTanalyzer.nAverages; + + + ofNoFill(); + ofSetLineWidth(1); + + ofSetColor(223, 218, 218); + ofDrawBitmapString("FFT average", 4, 18); + ofBeginShape(); + for (int i = 0; i < FFTanalyzer.nAverages; i++){ + ofVertex(i*avgStep, 284 -FFTanalyzer.averages[i] * 20); + } + ofEndShape(false); + + + ofSetColor(97,181,243); + ofDrawBitmapString("FFT magnitude", 4, 38); + ofBeginShape(); + for (int i = 0; i < BUFFER_SIZE; i++){ + ofVertex(i*avgStep, 384 -magnitude[i] * 20); + } + ofEndShape(false); + + + ofSetColor(97,243,174); + ofDrawBitmapString("FFT phase", 4, 58); + ofBeginShape(); + for (int i = 0; i < BUFFER_SIZE; i++){ + ofVertex(i*avgStep, 484 -phase[i] * 20); + } + ofEndShape(false); + + ofSetColor(243,174,94); + ofDrawBitmapString("FFT power", 4, 78); + ofBeginShape(); + for (int i = 0; i < BUFFER_SIZE; i++){ + ofVertex(i*avgStep, 584 -power[i] * 20); + } + ofEndShape(false); + + + //float * averages; // the actual averages + //float * peaks; // peaks of the averages, aka "maxAverages" in other implementations + +*/ + + + + ofEnableAlphaBlending(); + + maskShader.begin(); + + glActiveTexture(GL_TEXTURE0_ARB); + blendImage.getTextureReference().bind(); + glActiveTexture(GL_TEXTURE1_ARB); + renderImage.getTextureReference().bind(); + + glBegin(GL_QUADS); + + glMultiTexCoord2d(GL_TEXTURE0_ARB, 0, 0); + glMultiTexCoord2d(GL_TEXTURE1_ARB, 0, 0); + glVertex2f( 0, 0); + + glMultiTexCoord2d(GL_TEXTURE0_ARB, blendImage.getWidth(), 0); + glMultiTexCoord2d(GL_TEXTURE1_ARB, renderImage.getWidth(), 0); + glVertex2f( ofGetWidth(), 0); + + glMultiTexCoord2d(GL_TEXTURE0_ARB, blendImage.getWidth(), blendImage.getHeight()); + glMultiTexCoord2d(GL_TEXTURE1_ARB, renderImage.getWidth(), renderImage.getHeight() ); + glVertex2f( ofGetWidth(), ofGetHeight()); + + glMultiTexCoord2d(GL_TEXTURE0_ARB, 0, blendImage.getHeight()); + glMultiTexCoord2d(GL_TEXTURE1_ARB, 0, renderImage.getHeight() ); + glVertex2f( 0, ofGetHeight() ); + + glEnd(); + + glActiveTexture(GL_TEXTURE1_ARB); + renderImage.getTextureReference().unbind(); + + glActiveTexture(GL_TEXTURE0_ARB); + blendImage.getTextureReference().unbind(); + + maskShader.end(); +/* + glPushMatrix(); + glTranslatef(ofGetWidth()*0.5,ofGetHeight()*0.5,0); + glRotatef((float)ofGetFrameNum(),0,1.0,0); + renderImage.draw(ofGetWidth()*-0.5,ofGetHeight()*-0.5); + glPopMatrix(); + */ + + + + if (showFPS) { + string msg=ofToString(ofGetFrameRate(), 2); + msg+="\n"+ofToString(F_xRotation, 4)+" "+ofToString(F_yRotation, 4)+" "+ofToString(F_zRotation, 4); + msg+="\n"+ofToString(F_yseg, 4); + msg+="\n"+ofToString(narrator.getNumParticles())+" size "+ofToString(F_lineWidth); + msg+="\n"+ofToString(xModel)+","+ofToString(yModel)+","+ofToString(zModel)+" * "+ofToString(sModel); + syncOniPlayer *player=narrator.getCurrentPlayer(); + if (player) { + msg+="\n"+ofToString(player->getCurrentFrame())+","+ofToString(player->getPosition(),2); + msg+=player->getCurrentFile(); + } + ofDrawBitmapString(msg,20,20); + } +} + + +//-------------------------------------------------------------- +void testApp::keyPressed (int key){ + if(key == 'f'){ + showFPS=!showFPS; + } + if(key == ' '){ + fullScreen=!fullScreen; + ofSetFullscreen(fullScreen); + } + if(key == '/'){ + narrator.startPlayer(23); + } + if(key == ','){ + narrator.previous(); + } + if(key == '.'){ + narrator.next(); + } + if(key>='1'&key<='9'){ + int clip=key-'1'; + cerr<<"playing video clip "<<clip<<endl; + if (videoclips.size()>clip) videoclips[clip].play(); + } + if(key == 't'){ + for (int i=0;i<videoclips.size();i++) { + if (videoclips[i].isPlaying()) { + cerr<<"videoclip "<<i<<" is playing"<<endl; + } + } + } + if(key == 'r'){ + yModel+=25; + } + if(key == 'v'){ + yModel-=25; + } + if(key == 'd'){ + xModel+=25; + } + if(key == 'g'){ + xModel-=25; + } + if(key == 't'){ + zModel+=25; + } + if(key == 'c'){ + zModel-=25; + } + if(key == 'w'){ + sModel*=1.02; + } + if(key == 's'){ + sModel/=1.02; + } + if(key == 'q'){ + I_fade1=min(I_fade1+1,255); + } + if(key == 'a'){ + I_fade1=max(I_fade1-1,0); + } + if(key == 'h'){ + F_particleX-=1; + } + if(key == 'k'){ + + F_particleX+=1; + } + if(key == 'm'){ + F_particleY-=1; + } + if(key == 'u'){ + + F_particleY+=1; + } + if(key == 'i'){ + F_particleZ+=1; + } + if(key == 'n'){ + + F_particleZ-=1; + } + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + xOffs=x-startX; + yOffs=y-startY; +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + startX=x; + startY=y; +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(){ +} + + +//-------------------------------------------------------------- +void testApp::audioIn(float * input, int bufferSize, int nChannels){ + /*if (sampnum<10) { + printf("size %i, channels %i\n",bufferSize,nChannels); + sampnum++; + } + */ + // samples are "interleaved" + //if (nChannels==2) { + for (int i = 0; i < bufferSize; i++){ + left[i] = input[i*2]; + right[i] = input[i*2+1]; + } + //} + +} + +void testApp::newMidiMessage(ofxMidiEventArgs& eventArgs){ + + //newMessage(eventArgs.port, eventArgs.channel, eventArgs.byteTwo, eventArgs.timestamp); + +//byteOne : message type + + /* + int port; + int channel; + int status; + int byteOne; + int byteTwo; + double timestamp; + */ + + //printf("%d %d %d %d %d\n",eventArgs.port,eventArgs.channel,eventArgs.status,eventArgs.byteOne,eventArgs.byteTwo); + + bool noteOn; //this old thing! + + switch(eventArgs.status) { + case 144: //noteon-off + + break; + case 176: //control change 1-8 x 4 banks + switch(eventArgs.byteOne) { + case 1: + F_scale = ((float)eventArgs.byteTwo)*.25; + break; + case 2: + F_particleSize=(float)eventArgs.byteTwo*0.25; + break; + case 3: + F_drawAxis=((float) eventArgs.byteTwo-64)*(360.0/127); + break; + case 4: + F_particleAmount=((float) eventArgs.byteTwo)*(10000.0f/127.0f); + break; + case 5: + F_particleLife=((float) eventArgs.byteTwo)*(3.0f/127.0f); + break; + case 6: + F_particleX=(((float) eventArgs.byteTwo)-64)*10.0f; + break; + case 7: + F_particleY=(((float) eventArgs.byteTwo)-64)*10.0f; + break; + case 8: + F_particleZ=(((float) eventArgs.byteTwo)-64)*10.0f; + break; + + //65-80 buttons + + //radio button set + case 65: + if (eventArgs.byteTwo==127) { + visMode=FFT_AVG; + midiOut.sendControlChange(1, 66, 0); + midiOut.sendControlChange(1, 67, 0); + } + else midiOut.sendControlChange(1, 65, 127); + break; + case 66: + if (eventArgs.byteTwo==127) { + visMode=FFT_RAW; + midiOut.sendControlChange(1, 65, 0); + midiOut.sendControlChange(1, 67, 0); + } + else midiOut.sendControlChange(1, 66, 127); + break; + case 67: + if (eventArgs.byteTwo==127) { + visMode=WAVEFORM; + midiOut.sendControlChange(1, 65, 0); + midiOut.sendControlChange(1, 66, 0); + } + else midiOut.sendControlChange(1, 67, 127); + break; + + //radio button set + case 68: + if (eventArgs.byteTwo==127) { + inputMode=PICTURE; + midiOut.sendControlChange(1, 69, 0); + + } + else midiOut.sendControlChange(1, 68, 127); + break; + case 69: + if (eventArgs.byteTwo==127) { + inputMode=GRABBER; + midiOut.sendControlChange(1, 68, 0); + + } + else midiOut.sendControlChange(1, 69, 127); + break; + case 70: + B_glitch=(eventArgs.byteTwo==127); + break; + case 71: + B_fill=(eventArgs.byteTwo==127); + break; + case 72: + B_vSync=(eventArgs.byteTwo==127); + break; + + //buttons to zero rotations + case 73: + F_xRotate=0; + midiOut.sendControlChange(1, 73, 0); + midiOut.sendControlChange(1, 81, 64); + break; + case 74: + F_yRotate=0; + midiOut.sendControlChange(1, 74, 0); + midiOut.sendControlChange(1, 82, 64); + break; + case 75: + F_zRotate=0; + midiOut.sendControlChange(1, 75, 0); + midiOut.sendControlChange(1, 83, 64); + break; + case 76: + F_drawStep=0; + midiOut.sendControlChange(1, 76, 0); + midiOut.sendControlChange(1, 84, 64); + break; + case 77: + if (eventArgs.byteTwo==127) { + I_movieSource=0; + midiOut.sendControlChange(1, 78, 0); + midiOut.sendControlChange(1, 79, 0); + midiOut.sendControlChange(1, 80, 0); + + } + else midiOut.sendControlChange(1, 77, 127); + break; + case 78: + if (eventArgs.byteTwo==127) { + I_movieSource=1; + midiOut.sendControlChange(1, 77, 0); + midiOut.sendControlChange(1, 79, 0); + midiOut.sendControlChange(1, 80, 0); + } + else midiOut.sendControlChange(1, 78, 127); + break; + case 79: + if (eventArgs.byteTwo==127) { + I_movieSource=2; + midiOut.sendControlChange(1, 77, 0); + midiOut.sendControlChange(1, 78, 0); + midiOut.sendControlChange(1, 80, 0); + } + else midiOut.sendControlChange(1, 79, 127); + break; + case 80: + if (eventArgs.byteTwo==127) { + I_movieSource=3; + midiOut.sendControlChange(1, 77, 0); + midiOut.sendControlChange(1, 78, 0); + midiOut.sendControlChange(1, 79, 0); + } + else midiOut.sendControlChange(1, 80, 127); + break; + + // probably make controls logarithmic + case 81: + F_xRotate=(((float) eventArgs.byteTwo)-64)*.1; + break; + case 82: + F_yRotate=(((float) eventArgs.byteTwo)-64)*.1; + break; + case 83: + F_zRotate=(((float) eventArgs.byteTwo)-64)*.1; + break; + case 84: + F_drawStep=(((float) eventArgs.byteTwo)-64)*.1; + break; + case 85: + //F_movieSpeed=((float)eventArgs.byteTwo)/64.0; + F_lineWidth=((float)eventArgs.byteTwo)/8.0; + break; + case 86: + F_drawDecay=((float)eventArgs.byteTwo)/127.0; + break; + case 87: + I_fade2=((float)eventArgs.byteTwo)*2; + break; + case 88: + I_fade1=((float)eventArgs.byteTwo)*2; + //printf("fog- %f\n", F_drawDecay); + break; + + case 91: //top + F_xRotation=90; + F_yRotation=90; + F_zRotation=0; + midiOut.sendControlChange(1, 91, 0); + break; + case 92: //front + F_xRotation=0; + F_yRotation=180; + F_zRotation=0; + midiOut.sendControlChange(1, 92, 0); + break; + + //89-92 bottom 4 + + } + //printf("rotation- %f %f %f\n",F_xRotate,F_yRotate,F_zRotate); + //printf(inputMode==PICTURE?"PICTURE mode\n":"GRABBER mode\n"); + } +} +void testApp::setMidiState(){ + int knobs[32]; + int buttons[16]; + int faders[8]; + for (int i=0;i<32;i++) knobs[i]=0; + for (int i=0;i<16;i++) buttons[i]=0; + for (int i=0;i<8;i++) faders[i]=0; + + knobs[0] = (F_scale * 5); + knobs[1]=(F_particleSize*4); + knobs[2]=(F_drawAxis/(360.0/127))+64; + + knobs[3]=F_particleAmount/(10000.0f/127); + knobs[4]=F_particleLife/(3.0f/127); + knobs[5]=(F_particleX*.1)+64; + knobs[6]=(F_particleY*.1)+64; + knobs[7]=(F_particleZ*.1)+64; + + + //radio button set + buttons[0]=(visMode==FFT_AVG?127:0); + buttons[1]=(visMode==FFT_RAW?127:0); + buttons[2]=(visMode==WAVEFORM?127:0); + + //radio button set + buttons[3]=(inputMode==PICTURE?127:0); + buttons[4]=(inputMode==GRABBER?127:0); + buttons[5]=B_glitch?127:0; + buttons[6]=B_fill?127:0; + buttons[7]=B_vSync?127:0; + + buttons[12]=I_movieSource==0?127:0; + buttons[13]=I_movieSource==1?127:0; + buttons[14]=I_movieSource==2?127:0; + buttons[15]=I_movieSource==3?127:0; + + faders[0]=(F_xRotate*10)+64; + faders[1]=(F_yRotate*10)+64; + faders[2]=(F_zRotate*10)+64; + faders[3]=(F_drawStep*10)+64; + faders[4]=F_lineWidth*8; + + faders[5]=(F_drawDecay*127); + + faders[6]=I_fade1/2; + faders[7]=I_fade1/2; + + for (int i=0;i<32;i++) midiOut.sendControlChange(1, i+1, knobs[i]); + for (int i=0;i<16;i++) midiOut.sendControlChange(1, i+65, buttons[i]); + for (int i=0;i<8;i++) midiOut.sendControlChange(1, i+81, faders[i]); +} + +/* +void sendNoteOn(int channel, int id, int value); +void sendNoteOff(int channel, int id, int value); +void sendControlChange(int channel, int id, int value); +*/ + + diff --git a/07_performance/src/testApp.h b/07_performance/src/testApp.h new file mode 100644 index 0000000..88795cc --- /dev/null +++ b/07_performance/src/testApp.h @@ -0,0 +1,202 @@ +#ifndef _TEST_APP +#define _TEST_APP + +#include "ofMain.h" +#include "fft.h" +#include "FFTOctaveAnalyzer.h" +#include "ofxOsc.h" + +#define OSCPORT 12345 + +#include "oni.h" + +#define BUFFER_SIZE 1024 //was 1024 +#define BUFFER_FRAMES 512 + +/* +alter particle object memory scheme, preallocate +higher res FFT drawing +videos. +1- alter playback speed +2- draw with particles +3- draw seperately in between +4- strategy for drawing split screen - 3 copies + +videos at side of screen covering audio but not narrator + +envelope for particle generation +paticles change size etc during lifetime + + 1- sound multi landscape mode + 2- more midi controls on 2nd bank + 3- try higher res FFT +*/ + +#define OF_ADDON_USING_OFXMIDIIN + +#include "ofxMidi.h" +#include "ofxFensterManager.h" + +#define FFT_AVG 1 +#define FFT_RAW 2 +#define WAVEFORM 3 + +#define PICTURE 1 +#define GRABBER 2 + +template <typename OutputIterator> +int explode(const string &s, const char c, OutputIterator output) { + stringstream data(s); + string line; + int i=0; + while(std::getline(data,line,c)) { *output++ = line; i++; } + return i; +} + + +class testApp : public ofxFensterListener, public ofxMidiListener{ + + public: + + void setup(); + void update(); + void draw(); + + void keyPressed (int key); + void mouseMoved(int x, int y ); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(); + + void audioIn(float * input, int bufferSize, int nChannels); + + FFTOctaveAnalyzer lFFTanalyzer; + FFTOctaveAnalyzer rFFTanalyzer; + + ofxMidiIn midiIn; + ofxMidiOut midiOut; + void newMidiMessage(ofxMidiEventArgs& eventArgs); + + void setMidiState(); + + + private: + + float * left; + float * right; + int bufferCounter; + fft myfft; + + float FFTbuffer[2][BUFFER_SIZE][BUFFER_FRAMES]; + + int thisFFTbuffer; + + float lmagnitude[BUFFER_SIZE]; + float lphase[BUFFER_SIZE]; + float lpower[BUFFER_SIZE]; + float lfreq[BUFFER_SIZE/2]; + + float rmagnitude[BUFFER_SIZE]; + float rphase[BUFFER_SIZE]; + float rpower[BUFFER_SIZE]; + float rfreq[BUFFER_SIZE/2]; + + ofSoundStream soundStream; + + ofImage fbImage; + + //ofImage blendImage; + + ofVideoPlayer blendImage; + + ofFbo renderImage; + ofShader maskShader; + + bool showFPS; + bool fullScreen; + + ofImage testImage; + + //controllable variables + float F_scale; + float F_drawFrames; + float F_drawStep; + + float F_drawDecay; + float F_lineWidth; + float F_drawAxis; + + float F_xRotation; + float F_yRotation; + float F_zRotation; + + float F_xRotate; + float F_yRotate; + float F_zRotate; + + float lastFrameTime; + + bool draworder; + bool B_vSync; + bool B_fill; + + int visMode; + int inputMode; + + int I_fade1; + int I_fade2; + + int I_movieSource; + int I_moviePlaying; + + bool B_glitch; + + + + unsigned char *gammamap; + unsigned char *line1; + unsigned char *line2; + unsigned char *outBuffer; + + float F_particleAmount; + float F_particleLife; + float F_particleSize; + float F_particleX; + float F_particleY; + float F_particleZ; + + + + float whitePt; + float blackPt; + float gamma; + + bool field2; //flag that there is a 2nd field waiting to be processed + bool use2fields; + int frameTime,grabTime; //keep track of field timing + + + bool deInterlace; + ofTexture outTexture; + + float F_movieSpeed; + + + ofImage blanker; + + ofCamera camera; + ofNode target; + oniManager narrator; + + ofxXmlSettings XML; + vector<ofVideoPlayer> videoclips; + + ofxOscReceiver receiver; + + float xOffs,startX,yOffs,startY; + float xModel,yModel,zModel,sModel; +}; + +#endif + + |
