diff options
| author | Tim <tim@Admins-Mac-Pro-2.local> | 2013-06-19 20:03:17 +0100 |
|---|---|---|
| committer | Tim <tim@Admins-Mac-Pro-2.local> | 2013-06-19 20:03:17 +0100 |
| commit | cdd0e0b630bd3a5a8ba15dbce7f5e03221b72f92 (patch) | |
| tree | 4ada26f9bf3d4e0bdb97889472e95729433518a6 /06_performance/src | |
| parent | 4fdd082d9a5657b0f9c613d47c2c58cea366a2e6 (diff) | |
working on performance version
Diffstat (limited to '06_performance/src')
| -rw-r--r-- | 06_performance/src/FFTOctaveAnalyzer.cpp | 98 | ||||
| -rw-r--r-- | 06_performance/src/FFTOctaveAnalyzer.h | 45 | ||||
| -rw-r--r-- | 06_performance/src/fft.cpp | 489 | ||||
| -rw-r--r-- | 06_performance/src/fft.h | 33 | ||||
| -rw-r--r-- | 06_performance/src/main.cpp | 17 | ||||
| -rw-r--r-- | 06_performance/src/oni.cpp | 1 | ||||
| -rw-r--r-- | 06_performance/src/oni.h | 1 | ||||
| -rw-r--r-- | 06_performance/src/testApp.cpp | 776 | ||||
| -rw-r--r-- | 06_performance/src/testApp.h | 163 |
9 files changed, 1623 insertions, 0 deletions
diff --git a/06_performance/src/FFTOctaveAnalyzer.cpp b/06_performance/src/FFTOctaveAnalyzer.cpp new file mode 100644 index 0000000..4c91eeb --- /dev/null +++ b/06_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/06_performance/src/FFTOctaveAnalyzer.h b/06_performance/src/FFTOctaveAnalyzer.h new file mode 100644 index 0000000..8fef773 --- /dev/null +++ b/06_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/06_performance/src/fft.cpp b/06_performance/src/fft.cpp new file mode 100644 index 0000000..ca3217e --- /dev/null +++ b/06_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/06_performance/src/fft.h b/06_performance/src/fft.h new file mode 100644 index 0000000..bae5b37 --- /dev/null +++ b/06_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/06_performance/src/main.cpp b/06_performance/src/main.cpp new file mode 100644 index 0000000..58263a2 --- /dev/null +++ b/06_performance/src/main.cpp @@ -0,0 +1,17 @@ +#include "ofMain.h" +#include "testApp.h" + +//======================================================================== +int main( ){ + + ofSetupOpenGL(4080,768, OF_WINDOW); // <-------- setup the GL context + + + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + + ofRunApp(new testApp); + +} diff --git a/06_performance/src/oni.cpp b/06_performance/src/oni.cpp new file mode 100644 index 0000000..a202f41 --- /dev/null +++ b/06_performance/src/oni.cpp @@ -0,0 +1 @@ +#include "oni.h"
\ No newline at end of file diff --git a/06_performance/src/oni.h b/06_performance/src/oni.h new file mode 100644 index 0000000..ccb1417 --- /dev/null +++ b/06_performance/src/oni.h @@ -0,0 +1 @@ +#include "ofxOpenNI.h"
\ No newline at end of file diff --git a/06_performance/src/testApp.cpp b/06_performance/src/testApp.cpp new file mode 100644 index 0000000..d41071a --- /dev/null +++ b/06_performance/src/testApp.cpp @@ -0,0 +1,776 @@ +#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 + midiIn.addListener(this); + + midiOut.listPorts(); + midiOut.openPort(0); //this was 1 on linux + + // 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(0); + soundStream.setup(this, 0, 2, 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 + + ofSetFrameRate(60); + + ofBackground(0,0,0); + + F_movieSpeed=0.0; + + //blendImage.loadImage("blend01.png"); + blendImage.loadMovie("blend01.mov"); + blendImage.play(); + blendImage.setLoopState(OF_LOOP_NORMAL); + blendImage.setSpeed(F_movieSpeed); + + I_movieSource=0; + I_moviePlaying=0; + + renderImage.allocate(ofGetWidth(),ofGetHeight(),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; + F_drawAxis=90; //Y + + + F_xRotate=0; + F_yRotate=0; + F_zRotate=0; + + F_xRotation=0; + F_yRotation=180; + F_zRotation=0; + + F_particleAmount=100; + F_particleLife=0.5; + + 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(); +} + + + +//-------------------------------------------------------------- +void testApp::update(){ + + + 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(); +} + +//-------------------------------------------------------------- +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*interval); + F_zRotation+=(F_zRotate*interval); + F_drawFrames=max(1.99f,min(F_drawFrames+(F_drawStep*interval),(float)BUFFER_FRAMES)); + + ofPushMatrix(); + ofTranslate(hw,hh); + ofRotateX(F_xRotation); + ofRotateY(F_yRotation); + 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, ofGetWidth()*(0.25+F_drawDecay)); + glFogf(GL_FOG_END, ofGetWidth()*(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(); + } + 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) { + ofDrawBitmapString(ofToString(ofGetFrameRate(), 2),20,20); + ofDrawBitmapString(ofToString(F_xRotation, 4)+" "+ofToString(F_yRotation, 4)+" "+ofToString(F_zRotation, 4),20,30); + ofDrawBitmapString(ofToString(F_yseg, 4),20,40); + } +} + + +//-------------------------------------------------------------- +void testApp::keyPressed (int key){ + if(key == 'f'){ + showFPS=!showFPS; + } + if(key == ' '){ + fullScreen=!fullScreen; + ofSetFullscreen(fullScreen); + } +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +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)*.2; + break; + case 2: + F_lineWidth=(float)eventArgs.byteTwo*0.1; + break; + case 3: + F_drawAxis=((float) eventArgs.byteTwo-64)*(360.0/127); + break; + case 4: + F_particleAmount=((float) eventArgs.byteTwo)*(2000.0f/127.0f); + break; + case 5: + F_particleLife=((float) eventArgs.byteTwo)*(3.0f/127.0f); + break; + case 6: + F_particleX=(((float) eventArgs.byteTwo)-64)*.1f; + break; + case 7: + F_particleY=(((float) eventArgs.byteTwo)-64)*.1f; + break; + case 8: + F_particleZ=(((float) eventArgs.byteTwo)-64)*.1f; + 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; + 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_lineWidth*10); + knobs[2]=(F_drawAxis/(360.0/127))+64; + + knobs[3]=F_particleAmount/(2000.0f/127); + knobs[4]=F_particleLife/(3.0f/127); + knobs[5]=(F_particleX*10)+64; + knobs[6]=(F_particleY*10)+64; + knobs[7]=(F_particleZ*10)+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_movieSpeed*127; + + 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/06_performance/src/testApp.h b/06_performance/src/testApp.h new file mode 100644 index 0000000..cca9e20 --- /dev/null +++ b/06_performance/src/testApp.h @@ -0,0 +1,163 @@ +#ifndef _TEST_APP +#define _TEST_APP + +#include "ofMain.h" +#include "fft.h" +#include "FFTOctaveAnalyzer.h" + +#define BUFFER_SIZE 1024 +#define BUFFER_FRAMES 512 + +/* +ok seriously lets make this good + +recording - storage for a bunch of fft + +average them on the fly? seems likely + +*/ + +#define OF_ADDON_USING_OFXMIDIIN + +#include "ofxMidi.h" + +#define FFT_AVG 1 +#define FFT_RAW 2 +#define WAVEFORM 3 + +#define PICTURE 1 +#define GRABBER 2 + + +class testApp : public ofBaseApp, 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_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; +}; + +#endif + |
