aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.cpp4
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.h4
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.cpp193
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.h191
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.cpp328
-rwxr-xr-xofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.h76
-rw-r--r--ofxMaxim/ofMaxim007Example/ofxMaxim/src/ofxMaxim.h2
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.cpp60
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.h8
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.cpp43
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.h14
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.cpp6
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.h443
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.cpp78
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.h204
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.cpp517
-rwxr-xr-xofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.h171
-rw-r--r--ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/src/ofxMaxim.h13
18 files changed, 1893 insertions, 462 deletions
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.cpp b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.cpp
index 346b653..36034b2 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.cpp
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.cpp
@@ -120,8 +120,8 @@ float maxiFFT::spectralCentroid() {
maxiFFT::~maxiFFT() {
delete _fft;
- delete[] buffer,magnitudes,phases,window;
- delete avgPower;
+ if (buffer)
+ delete[] buffer,magnitudes,phases,window, avgPower;
}
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.h b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.h
index 6c07089..d099e84 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.h
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiFFT.h
@@ -37,12 +37,14 @@
#include "fft.h"
+#include "stddef.h"
class maxiFFT {
public:
maxiFFT(){
- _fft = 0;
+ _fft = NULL;
+ buffer = magnitudes = phases = window = avgPower = NULL;
};
~maxiFFT();
void setup(int fftSize, int windowSize, int hopSize);
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.cpp b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.cpp
index befa5f4..e72fd75 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.cpp
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.cpp
@@ -8,51 +8,53 @@
*/
#include "maxiMFCC.h"
-#include <math.h>
-#include <iostream>
-#ifdef __APPLE_CC__
-#include <Accelerate/Accelerate.h>
-#endif
-using namespace std;
-void maxiMFCC::setup(unsigned int numBins, unsigned int numFilters, unsigned int numCoeffs, double minFreq, double maxFreq, unsigned int sampleRate)
-{
- this->numFilters = numFilters;
- this->numCoeffs = numCoeffs;
- this->minFreq = minFreq;
- this->maxFreq = maxFreq;
- this->sampleRate = sampleRate;
- this->numBins = numBins;
- melFilters = NULL;
- melBands = (double*) malloc(sizeof(double) * numFilters);
-#ifdef __APPLE_CC__
- doubleSpec = (double*)malloc(sizeof(double) * numBins);
-#endif
- //create new matrix
- dctMatrix = (double*)malloc(sizeof(double) * numCoeffs * numFilters);
- calcMelFilterBank(sampleRate, numBins);
- createDCTCoeffs();
-}
-void maxiMFCC::mfcc(float* powerSpectrum, double *mfccs) {
- melFilterAndLogSquare(powerSpectrum);
- dct(mfccs);
+template <>
+void maxiMFCCAnalyser<double>::dct(double *mfccs) {
+ vDSP_mmulD(melBands, 1, dctMatrix, 1, mfccs, 1, 1, numCoeffs, numFilters);
+ double n = (double) numCoeffs;
+ vDSP_vsdivD(mfccs, 1, &n, mfccs, 1, numCoeffs);
}
+template <>
+void maxiMFCCAnalyser<float>::dct(float *mfccs) {
+ vDSP_mmul(melBands, 1, dctMatrix, 1, mfccs, 1, 1, numCoeffs, numFilters);
+ float n = (float) numCoeffs;
+ vDSP_vsdiv(mfccs, 1, &n, mfccs, 1, numCoeffs);
+}
-void maxiMFCC::melFilterAndLogSquare(float* powerSpectrum){
+template <>
+void maxiMFCCAnalyser<double>::melFilterAndLogSquare(float* powerSpectrum) {
#ifdef __APPLE_CC__
//conv to double
vDSP_vspdp(powerSpectrum, 1, doubleSpec, 1, numBins);
- vDSP_mmulD(doubleSpec, 1, melFilters, 1, melBands, 1, 1, 42, 512);
+ // vDSP_mmulD(doubleSpec, 1, melFilters, 1, melBands, 1, 1, 42, 512);
+ vDSP_mmulD(doubleSpec, 1, melFilters, 1, melBands, 1, 1, numFilters, numBins);
+#endif
+ melFilterAndLogSq_Part2();
+}
+
+
+template <>
+void maxiMFCCAnalyser<float>::melFilterAndLogSquare(float* powerSpectrum) {
+#ifdef __APPLE_CC__
+ vDSP_mmul(powerSpectrum, 1, melFilters, 1, melBands, 1, 1, numFilters, numBins);
+#endif
+ melFilterAndLogSq_Part2();
+}
+
+template <class T>
+void maxiMFCCAnalyser<T>::melFilterAndLogSq_Part2() {
+#ifdef __APPLE_CC__
#else
for (int filter = 0;filter < numFilters;filter++) {
melBands[filter] = 0.0;
for (int bin=0;bin<numBins;bin++) {
-// int idx = (numBins * filter) + bin;
+ // int idx = (numBins * filter) + bin;
int idx = filter + (bin * numFilters);
-// melBands[filter] += (melFilters[filter][bin] * powerSpectrum[bin]);
+ // melBands[filter] += (melFilters[filter][bin] * powerSpectrum[bin]);
melBands[filter] += (melFilters[idx] * powerSpectrum[bin]);
}
}
@@ -63,143 +65,14 @@ void maxiMFCC::melFilterAndLogSquare(float* powerSpectrum){
}
}
-void maxiMFCC::dct(double *mfccs){
-#ifdef __APPLE_CC__
- vDSP_mmulD(melBands, 1, dctMatrix, 1, mfccs, 1, 1, numCoeffs, numFilters);
- double n = (double) numCoeffs;
- vDSP_vsdivD(mfccs, 1, &n, mfccs, 1, numCoeffs);
-#else
- for(int i=0; i < numCoeffs; i++) {
- mfccs[i] = 0.0;
- }
- for(int i=0; i < numCoeffs; i++ ) {
- for(int j=0; j < numFilters; j++) {
- int idx = i + (j * numCoeffs);
-// mfccs[i] += (dctMatrix[i][j] * melBands[j]);
- mfccs[i] += (dctMatrix[idx] * melBands[j]);
- }
- }
- for(int i=0; i < numCoeffs; i++) {
- mfccs[i] /= numCoeffs;
- }
-#endif
-}
-
-void maxiMFCC::createDCTCoeffs() {
- double k = 3.14159265358979323846/numFilters;
- double w1 = 1.0/(sqrt(numFilters));
- double w2 = sqrt(2.0/numFilters);
-
-
- //generate dct matrix
- for(int i = 0; i < numCoeffs; i++)
- {
- for(int j = 0; j < numFilters; j++)
- {
- int idx = i + (j * numCoeffs);
- // if(i == 0)
- // dctMatrix[i][j]= w1 * cos(k * (i+1) * (j + 0.5));
- // else
- // dctMatrix[i][j] = w2 * cos(k * (i+1) * (j + 0.5));
- if(i == 0)
- dctMatrix[idx]= w1 * cos(k * (i+1) * (j + 0.5));
- else
- dctMatrix[idx] = w2 * cos(k * (i+1) * (j + 0.5));
- }
- }
-
-
-}
-// implements this formula:
-// mel = 2595 log10(Hz/700 + 1)
-inline double hzToMel(double hz){
- return 2595.0 * (log10(hz/700.0 + 1.0));
-}
-// implements this formula
-// Hz = 700 (10^(mel/2595) - 1)
-inline double melToHz(double mel){
- return 700.0 * (pow(10, mel/2595.0) - 1.0);
-}
-void maxiMFCC::calcMelFilterBank(double sampleRate, int numBins){
- double mel, dMel, maxMel, minMel, nyquist, binFreq, start, end, thisF, nextF, prevF;
- int numValidBins;
-
- // ignore bins over nyquist
- numValidBins = numBins;
-
- nyquist = sampleRate/2;
- if (maxFreq > nyquist) {
- maxFreq = nyquist;
- }
-
- maxMel = hzToMel(maxFreq);
- minMel = hzToMel(minFreq);
-
- dMel = (maxMel - minMel) / (numFilters + 2 - 1);
-
- double *filtPos = (double*) malloc(sizeof(double) * (numFilters + 2));
-
- // first generate an array of start and end freqs for each triangle
- mel = minMel;
- for (int i=0;i<numFilters + 2;i++) {
- // start of the triangle
- filtPos[i] = melToHz(mel);
-// std::cout << "[" << i << "] MFCC: centre is at " <<filtPos[i]<<"hz "<<mel<<" mels" << endl;
- mel += dMel;
- }
- // now generate the coefficients for the mag spectrum
- melFilters = (double*) malloc(sizeof(double) * numFilters * numValidBins);
-
- for (int filter = 1; filter < numFilters; filter++) {
- for (int bin=0;bin<numValidBins;bin++) {
- // frequency this bin represents
- binFreq = (double) sampleRate / (double) numValidBins * (double) bin;
- thisF = filtPos[filter];
- nextF = filtPos[filter+1];
- prevF = filtPos[filter-1];
- int idx = filter + (bin * numFilters);
- if (binFreq > nextF || binFreq < prevF) {
- // outside this filter
- melFilters[idx] = 0;
- //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
- }
- else {
- double height = 2.0 / (nextF - prevF);
- if (binFreq < thisF) {
- // up
- start = prevF;
- end = thisF;
- melFilters[idx] = (binFreq - start) * (height / (thisF - start));
- }
- else {
- // down
- start = thisF;
- end = nextF;
- melFilters[idx] = height + ((binFreq - thisF) * (-height /(nextF - thisF)));
- }
-// cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
- //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[idx] << endl;
- }
- }
- }
-}
-maxiMFCC::~maxiMFCC() {
- delete[] melFilters;
- delete[] melBands;
- delete[] dctMatrix;
-#ifdef __APPLE_CC__
- delete doubleSpec;
-#endif
-
-}
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.h b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.h
index 1a2b3a3..60bfe04 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.h
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maxiMFCC.h
@@ -13,33 +13,192 @@
#pragma pack(16)
#include "maxiFFT.h"
+#include <math.h>
+#include <iostream>
+#ifdef __APPLE_CC__
+#include <Accelerate/Accelerate.h>
+#endif
-class maxiMFCC {
-public:
- maxiMFCC(){};
- ~maxiMFCC();
- void setup(unsigned int numBins, unsigned int numFilters, unsigned int numCoeffs, double minFreq, double maxFreq, unsigned int sampleRate);
- void mfcc(float* powerSpectrum, double *mfccs);
- double *melBands;
+using namespace std;
+
+
+// implements this formula:
+// mel = 2595 log10(Hz/700 + 1)
+inline double hzToMel(double hz){
+ return 2595.0 * (log10(hz/700.0 + 1.0));
+}
+
+// implements this formula
+// Hz = 700 (10^(mel/2595) - 1)
+inline double melToHz(double mel){
+ return 700.0 * (pow(10, mel/2595.0) - 1.0);
+}
+template <class T>
+class maxiMFCCAnalyser {
+public:
+ T *melBands;
+ maxiMFCCAnalyser():melFilters(NULL),dctMatrix(NULL), melBands(NULL){};
+ ~maxiMFCCAnalyser() {
+ if (melFilters) {
+ delete[] melFilters;
+ delete[] melBands;
+ delete[] dctMatrix;
+#ifdef __APPLE_CC__
+ delete doubleSpec;
+#endif
+ }
+ }
+
+ void setup(unsigned int numBins, unsigned int numFilters, unsigned int numCoeffs, double minFreq, double maxFreq, unsigned int sampleRate)
+ {
+ this->numFilters = numFilters;
+ this->numCoeffs = numCoeffs;
+ this->minFreq = minFreq;
+ this->maxFreq = maxFreq;
+ this->sampleRate = sampleRate;
+ this->numBins = numBins;
+ melFilters = NULL;
+ melBands = (T*) malloc(sizeof(T) * numFilters);
+#ifdef __APPLE_CC__
+ doubleSpec = (T*)malloc(sizeof(T) * numBins);
+#endif
+ //create new matrix
+ dctMatrix = (T*)malloc(sizeof(T) * numCoeffs * numFilters);
+ calcMelFilterBank(sampleRate, numBins);
+ createDCTCoeffs();
+ }
+ void mfcc(float* powerSpectrum, T *mfccs) {
+ melFilterAndLogSquare(powerSpectrum);
+ dct(mfccs);
+ }
+
private:
unsigned int numFilters, numCoeffs;
double minFreq, maxFreq;
unsigned int sampleRate;
-// double **melFilters;
- double *melFilters;
+ T *melFilters;
unsigned int numBins;
-// double **dctMatrix;
- double *dctMatrix;
+ T *dctMatrix;
+#ifdef __APPLE_CC__
+ T *doubleSpec;
+#endif
+
#ifdef __APPLE_CC__
- double *doubleSpec;
+ void dct(T *mfccs); //define later
+#else
+ void dct(T *mfccs) {
+ for(int i=0; i < numCoeffs; i++) {
+ mfccs[i] = 0.0;
+ }
+ for(int i=0; i < numCoeffs; i++ ) {
+ for(int j=0; j < numFilters; j++) {
+ int idx = i + (j * numCoeffs);
+ mfccs[i] += (dctMatrix[idx] * melBands[j]);
+ }
+ }
+ for(int i=0; i < numCoeffs; i++) {
+ mfccs[i] /= numCoeffs;
+ }
+ }
#endif
void melFilterAndLogSquare(float* powerSpectrum);
- void dct(double *mfccs);
- void calcMelFilterBank(double sampleRate, int numBins);
- void createDCTCoeffs();
+ void melFilterAndLogSq_Part2();
+ void calcMelFilterBank(double sampleRate, int numBins) {
+
+ double mel, dMel, maxMel, minMel, nyquist, binFreq, start, end, thisF, nextF, prevF;
+ int numValidBins;
+
+ // ignore bins over nyquist
+ numValidBins = numBins;
+
+ nyquist = sampleRate/2;
+ if (maxFreq > nyquist) {
+ maxFreq = nyquist;
+ }
+
+ maxMel = hzToMel(maxFreq);
+ minMel = hzToMel(minFreq);
+
+ dMel = (maxMel - minMel) / (numFilters + 2 - 1);
+
+ T *filtPos = (T*) malloc(sizeof(double) * (numFilters + 2));
+
+ // first generate an array of start and end freqs for each triangle
+ mel = minMel;
+ for (int i=0;i<numFilters + 2;i++) {
+ // start of the triangle
+ filtPos[i] = melToHz(mel);
+ // std::cout << "[" << i << "] MFCC: centre is at " <<filtPos[i]<<"hz "<<mel<<" mels" << endl;
+ mel += dMel;
+ }
+ // now generate the coefficients for the mag spectrum
+ melFilters = (T*) malloc(sizeof(T) * numFilters * numValidBins);
+
+ for (int filter = 1; filter < numFilters; filter++) {
+ for (int bin=0;bin<numValidBins;bin++) {
+ // frequency this bin represents
+ binFreq = (T) sampleRate / (T) numValidBins * (T) bin;
+ thisF = filtPos[filter];
+ nextF = filtPos[filter+1];
+ prevF = filtPos[filter-1];
+ int idx = filter + (bin * numFilters);
+ if (binFreq > nextF || binFreq < prevF) {
+ // outside this filter
+ melFilters[idx] = 0;
+ //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
+ }
+ else {
+ T height = 2.0 / (nextF - prevF);
+
+ if (binFreq < thisF) {
+ // up
+ start = prevF;
+ end = thisF;
+ melFilters[idx] = (binFreq - start) * (height / (thisF - start));
+ }
+ else {
+ // down
+ start = thisF;
+ end = nextF;
+ melFilters[idx] = height + ((binFreq - thisF) * (-height /(nextF - thisF)));
+ }
+ // cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
+ //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[idx] << endl;
+ }
+ }
+ }
+ }
+ void createDCTCoeffs() {
+ T k = 3.14159265358979323846/numFilters;
+ T w1 = 1.0/(sqrt(numFilters));
+ T w2 = sqrt(2.0/numFilters);
+
+
+ //generate dct matrix
+ for(int i = 0; i < numCoeffs; i++)
+ {
+ for(int j = 0; j < numFilters; j++)
+ {
+ int idx = i + (j * numCoeffs);
+ if(i == 0)
+ dctMatrix[idx]= w1 * cos(k * (i+1) * (j + 0.5));
+ else
+ dctMatrix[idx] = w2 * cos(k * (i+1) * (j + 0.5));
+ }
+ }
+
+
+ }
+
+
-}; \ No newline at end of file
+};
+
+
+
+typedef maxiMFCCAnalyser<double> maxiMFCC;
+//typedef maxiMFCCAnalyser<float> maxiFloatMFCC;
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.cpp
index 7c61174..3741173 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.cpp
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.cpp
@@ -47,14 +47,16 @@ int maxiSettings::bufferSize = 1024;
double sineBuffer[514]={0,0.012268,0.024536,0.036804,0.049042,0.06131,0.073547,0.085785,0.097992,0.1102,0.12241,0.13455,0.1467,0.15884,0.17093,0.18301,0.19507,0.20709,0.21909,0.23105,0.24295,0.25485,0.26669,0.2785,0.29025,0.30197,0.31366,0.32529,0.33685,0.34839,0.35986,0.37128,0.38266,0.39395,0.40521,0.41641,0.42752,0.4386,0.44958,0.46051,0.47137,0.48215,0.49286,0.50351,0.51407,0.52457,0.53497,0.54529,0.55554,0.5657,0.57578,0.58575,0.59567,0.60547,0.6152,0.62482,0.63437,0.6438,0.65314,0.66238,0.67151,0.68057,0.68951,0.69833,0.70706,0.7157,0.72421,0.7326,0.74091,0.74908,0.75717,0.76514,0.77298,0.7807,0.7883,0.79581,0.80316,0.81042,0.81754,0.82455,0.83142,0.8382,0.84482,0.85132,0.8577,0.86392,0.87006,0.87604,0.88187,0.8876,0.89319,0.89862,0.90396,0.90912,0.91415,0.91907,0.92383,0.92847,0.93295,0.93729,0.9415,0.94556,0.94949,0.95325,0.95691,0.96039,0.96375,0.96692,0.97,0.9729,0.97565,0.97827,0.98074,0.98306,0.98523,0.98724,0.98914,0.99084,0.99243,0.99387,0.99515,0.99628,0.99725,0.99808,0.99875,0.99927,0.99966,0.99988,0.99997,0.99988,0.99966,0.99927,0.99875,0.99808,0.99725,0.99628,0.99515,0.99387,0.99243,0.99084,0.98914,0.98724,0.98523,0.98306,0.98074,0.97827,0.97565,0.9729,0.97,0.96692,0.96375,0.96039,0.95691,0.95325,0.94949,0.94556,0.9415,0.93729,0.93295,0.92847,0.92383,0.91907,0.91415,0.90912,0.90396,0.89862,0.89319,0.8876,0.88187,0.87604,0.87006,0.86392,0.8577,0.85132,0.84482,0.8382,0.83142,0.82455,0.81754,0.81042,0.80316,0.79581,0.7883,0.7807,0.77298,0.76514,0.75717,0.74908,0.74091,0.7326,0.72421,0.7157,0.70706,0.69833,0.68951,0.68057,0.67151,0.66238,0.65314,0.6438,0.63437,0.62482,0.6152,0.60547,0.59567,0.58575,0.57578,0.5657,0.55554,0.54529,0.53497,0.52457,0.51407,0.50351,0.49286,0.48215,0.47137,0.46051,0.44958,0.4386,0.42752,0.41641,0.40521,0.39395,0.38266,0.37128,0.35986,0.34839,0.33685,0.32529,0.31366,0.30197,0.29025,0.2785,0.26669,0.25485,0.24295,0.23105,0.21909,0.20709,0.19507,0.18301,0.17093,0.15884,0.1467,0.13455,0.12241,0.1102,0.097992,0.085785,0.073547,0.06131,0.049042,0.036804,0.024536,0.012268,0,-0.012268,-0.024536,-0.036804,-0.049042,-0.06131,-0.073547,-0.085785,-0.097992,-0.1102,-0.12241,-0.13455,-0.1467,-0.15884,-0.17093,-0.18301,-0.19507,-0.20709,-0.21909,-0.23105,-0.24295,-0.25485,-0.26669,-0.2785,-0.29025,-0.30197,-0.31366,-0.32529,-0.33685,-0.34839,-0.35986,-0.37128,-0.38266,-0.39395,-0.40521,-0.41641,-0.42752,-0.4386,-0.44958,-0.46051,-0.47137,-0.48215,-0.49286,-0.50351,-0.51407,-0.52457,-0.53497,-0.54529,-0.55554,-0.5657,-0.57578,-0.58575,-0.59567,-0.60547,-0.6152,-0.62482,-0.63437,-0.6438,-0.65314,-0.66238,-0.67151,-0.68057,-0.68951,-0.69833,-0.70706,-0.7157,-0.72421,-0.7326,-0.74091,-0.74908,-0.75717,-0.76514,-0.77298,-0.7807,-0.7883,-0.79581,-0.80316,-0.81042,-0.81754,-0.82455,-0.83142,-0.8382,-0.84482,-0.85132,-0.8577,-0.86392,-0.87006,-0.87604,-0.88187,-0.8876,-0.89319,-0.89862,-0.90396,-0.90912,-0.91415,-0.91907,-0.92383,-0.92847,-0.93295,-0.93729,-0.9415,-0.94556,-0.94949,-0.95325,-0.95691,-0.96039,-0.96375,-0.96692,-0.97,-0.9729,-0.97565,-0.97827,-0.98074,-0.98306,-0.98523,-0.98724,-0.98914,-0.99084,-0.99243,-0.99387,-0.99515,-0.99628,-0.99725,-0.99808,-0.99875,-0.99927,-0.99966,-0.99988,-0.99997,-0.99988,-0.99966,-0.99927,-0.99875,-0.99808,-0.99725,-0.99628,-0.99515,-0.99387,-0.99243,-0.99084,-0.98914,-0.98724,-0.98523,-0.98306,-0.98074,-0.97827,-0.97565,-0.9729,-0.97,-0.96692,-0.96375,-0.96039,-0.95691,-0.95325,-0.94949,-0.94556,-0.9415,-0.93729,-0.93295,-0.92847,-0.92383,-0.91907,-0.91415,-0.90912,-0.90396,-0.89862,-0.89319,-0.8876,-0.88187,-0.87604,-0.87006,-0.86392,-0.8577,-0.85132,-0.84482,-0.8382,-0.83142,-0.82455,-0.81754,-0.81042,-0.80316,-0.79581,-0.7883,-0.7807,-0.77298,-0.76514,-0.75717,-0.74908,-0.74091,-0.7326,-0.72421,-0.7157,-0.70706,-0.69833,-0.68951,-0.68057,-0.67151,-0.66238,-0.65314,-0.6438,-0.63437,-0.62482,-0.6152,-0.60547,-0.59567,-0.58575,-0.57578,-0.5657,-0.55554,-0.54529,-0.53497,-0.52457,-0.51407,-0.50351,-0.49286,-0.48215,-0.47137,-0.46051,-0.44958,-0.4386,-0.42752,-0.41641,-0.40521,-0.39395,-0.38266,-0.37128,-0.35986,-0.34839,-0.33685,-0.32529,-0.31366,-0.30197,-0.29025,-0.2785,-0.26669,-0.25485,-0.24295,-0.23105,-0.21909,-0.20709,-0.19507,-0.18301,-0.17093,-0.15884,-0.1467,-0.13455,-0.12241,-0.1102,-0.097992,-0.085785,-0.073547,-0.06131,-0.049042,-0.036804,-0.024536,-0.012268,0,0.012268
};
+int mtofarray[129]={0, 8.661957, 9.177024, 9.722718, 10.3, 10.913383, 11.562325, 12.25, 12.978271, 13.75, 14.567617, 15.433853, 16.351599, 17.323914, 18.354048, 19.445436, 20.601723, 21.826765, 23.124651, 24.5, 25.956543, 27.5, 29.135235, 30.867706, 32.703197, 34.647827, 36.708096, 38.890873, 41.203445, 43.65353, 46.249302, 49., 51.913086, 55., 58.27047, 61.735413, 65.406395, 69.295654, 73.416191, 77.781746, 82.406891, 87.30706, 92.498604, 97.998856, 103.826172, 110., 116.540939, 123.470825, 130.81279, 138.591309, 146.832382, 155.563492, 164.813782, 174.61412, 184.997208, 195.997711, 207.652344, 220., 233.081879, 246.94165, 261.62558, 277.182617,293.664764, 311.126984, 329.627563, 349.228241, 369.994415, 391.995422, 415.304688, 440., 466.163757, 493.883301, 523.25116, 554.365234, 587.329529, 622.253967, 659.255127, 698.456482, 739.988831, 783.990845, 830.609375, 880., 932.327515, 987.766602, 1046.502319, 1108.730469, 1174.659058, 1244.507935, 1318.510254, 1396.912964, 1479.977661, 1567.981689, 1661.21875, 1760., 1864.655029, 1975.533203, 2093.004639, 2217.460938, 2349.318115, 2489.015869, 2637.020508, 2793.825928, 2959.955322, 3135.963379, 3322.4375, 3520., 3729.31, 3951.066406, 4186.009277, 4434.921875, 4698.63623, 4978.031738, 5274.041016, 5587.651855, 5919.910645, 6271.926758, 6644.875, 7040., 7458.620117, 7902.132812, 8372.018555, 8869.84375, 9397.272461, 9956.063477, 10548.082031, 11175.303711, 11839.821289, 12543.853516, 13289.75};
+
void setup();//use this to do any initialisation if you want.
void play(double *channels);//run dac!
maxiOsc::maxiOsc(){
phase = 0.0;
-// memset(phases,0,500);
-// memset(freqs,0,500);
+ // memset(phases,0,500);
+ // memset(freqs,0,500);
}
double maxiOsc::noise() {
@@ -64,6 +66,11 @@ double maxiOsc::noise() {
return(output);
}
+void maxiOsc::phaseReset(double phaseIn) {
+ phase=phaseIn;
+
+}
+
double maxiOsc::sinewave(double frequency) {
output=sin (phase*(TWOPI));
if ( phase >= 1.0 ) phase -= 1.0;
@@ -162,14 +169,13 @@ double maxiOsc::saw(double frequency) {
}
-double maxiOsc::triangle(double frequency, double phase) {
- output=tri*2;
+double maxiOsc::triangle(double frequency) {
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(maxiSettings::sampleRate/(frequency*chandiv)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
if (phase <= 0.5 ) {
- tri = phase;
- } else {
- tri =(1-phase);
+ output =((phase)*4)-1;
+ } else {
+ output =((0.5-phase)*4)-1;
}
return(output);
@@ -177,36 +183,54 @@ double maxiOsc::triangle(double frequency, double phase) {
//I like this.
double maxiEnvelope::line(int numberofsegments,double segments[1000]) {
- period=2./(segments[valindex+1]*0.004);
- nextval=segments[valindex+2];
- currentval=segments[valindex];
- if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) {
- amplitude += ((currentval-startval)/(maxiSettings::sampleRate/period));
- } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) {
- amplitude -= (((currentval-startval)*(-1))/(maxiSettings::sampleRate/period));
- } else if (valindex >numberofsegments-1) {
- valindex=numberofsegments-2;
- } else {
- valindex=valindex+2;
- startval=currentval;
+ if (isPlaying==1) {//only make a sound once you've been triggered
+
+ period=2./(segments[valindex+1]*0.004);
+ nextval=segments[valindex+2];
+ currentval=segments[valindex];
+ if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) {
+ amplitude += ((currentval-startval)/(maxiSettings::sampleRate/period));
+ } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) {
+ amplitude -= (((currentval-startval)*(-1))/(maxiSettings::sampleRate/period));
+ } else if (valindex >numberofsegments-1) {
+ valindex=numberofsegments-2;
+ } else {
+ valindex=valindex+2;
+ startval=currentval;
+ }
+ output=amplitude;
+
+ }
+ else {
+ output=0;
+
}
- output=amplitude;
- return(output);
+ return(output);
}
//and this
void maxiEnvelope::trigger(int index, double amp) {
+ isPlaying=1;//ok the envelope is being used now.
valindex=index;
amplitude=amp;
}
//and this
+
+maxiDelayline::maxiDelayline() {
+ memory[88200]=NULL;
+
+}
+
+
double maxiDelayline::dl(double input, int size, double feedback) {
- if ( phase >=size ) phase = 0;
+ if ( phase >=size ) {
+ phase = 0;
+ }
memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5;
phase+=1;
- output=memory[phase+1];
+ output=memory[phase];
return(output);
}
@@ -237,7 +261,7 @@ double maxiFilter::hipass(double input, double cutoff) {
double maxiFilter::lores(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
- if (cutoff>(maxiSettings::sampleRate*0.25)) cutoff=(maxiSettings::sampleRate*0.25);
+ if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
@@ -253,7 +277,7 @@ double maxiFilter::lores(double input,double cutoff1, double resonance) {
double maxiFilter::hires(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
- if (cutoff>(maxiSettings::sampleRate*0.25)) cutoff=(maxiSettings::sampleRate*0.25);
+ if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
@@ -323,8 +347,9 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double
}
-bool maxiSample::load(string fileName) {
+bool maxiSample::load(string fileName, int channel) {
myPath = fileName;
+ readChannel=channel;
return read();
}
@@ -337,10 +362,8 @@ bool maxiSample::read()
bool result;
ifstream inFile( myPath.c_str(), ios::in | ios::binary);
result = inFile;
-
if (inFile) {
bool datafound = false;
-
inFile.seekg(4, ios::beg);
inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize
@@ -389,6 +412,16 @@ bool maxiSample::read()
length=myDataSize*(0.5/myChannels);
inFile.close(); // close the input file
+ if (myChannels>1) {
+ int position=0;
+ int channel=readChannel*2;
+ for (int i=channel;i<myDataSize+6;i+=(myChannels*2)) {
+ myData[position]=myData[i];
+ myData[position+1]=myData[i+1];
+ position+=2;
+ }
+ }
+
}else {
cout << "ERROR: Could not load sample: " <<myPath << endl;
}
@@ -399,18 +432,19 @@ bool maxiSample::read()
double maxiSample::play() {
- long length=myDataSize*(1./myChannels);
+ // long length=myDataSize*(1./myChannels);
double remainder;
short* buffer = (short *)myData;
position=(position+1);
remainder = position - (long) position;
if ((long) position>length) position=0;
- output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ output =
+ (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
return(output);
}
double maxiSample::playOnce() {
-// long length=myDataSize*(0.5/myChannels);
+ // long length=myDataSize*(0.5/myChannels);
double remainder;
short* buffer = (short *)myData;
position=(position+1);
@@ -419,14 +453,27 @@ double maxiSample::playOnce() {
output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
else
output=0;
+
+ return(output);
+}
+double maxiSample::playOnce(double speed) {
+ double remainder;
+ //long a,b;
+ // long length=myDataSize*0.5;
+ short* buffer = (short *)myData;
+ position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate));
+ if ((long) position<length)
+ output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ else
+ output=0;
return(output);
}
double maxiSample::play(double speed) {
double remainder;
long a,b;
-// long length=myDataSize*0.5;
+ // long length=myDataSize*0.5;
short* buffer = (short *)myData;
position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate));
if (speed >=0) {
@@ -442,29 +489,29 @@ double maxiSample::play(double speed) {
}
if (position+2<length)
{
- b=position+2;
+ b=position+2;
}
else {
- b=length-1;
+ b=length-1;
}
output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation
-} else {
+ } else {
if ((long) position<0) position=length;
remainder = position - floor(position);
if (position-1>=0) {
a=position-1;
-
- }
- else {
- a=0;
- }
- if (position-2>=0) {
- b=position-2;
- }
- else {
- b=0;
- }
+
+ }
+ else {
+ a=0;
+ }
+ if (position-2>=0) {
+ b=position-2;
+ }
+ else {
+ b=0;
+ }
output = (double) ((-1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation
}
return(output);
@@ -477,7 +524,7 @@ double maxiSample::play(double frequency, double start, double end) {
double maxiSample::play(double frequency, double start, double end, double &pos) {
double remainder;
// long length=myDataSize;
-
+
if (end>=length) end=length-1;
long a,b;
short* buffer = (short *)myData;
@@ -503,7 +550,7 @@ double maxiSample::play(double frequency, double start, double end, double &pos)
else {
b=length-1;
}
-
+
output = (double) ((1-remainder) * buffer[a] +
remainder * buffer[b])/32767;//linear interpolation
} else {
@@ -547,7 +594,7 @@ double maxiSample::play4(double frequency, double start, double end) {
remainder = position - floor(position);
if (position>0) {
a=buffer[(int)(floor(position))-1];
-
+
} else {
a=buffer[0];
@@ -556,14 +603,14 @@ double maxiSample::play4(double frequency, double start, double end) {
b=buffer[(long) position];
if (position<end-2) {
c=buffer[(long) position+1];
-
+
} else {
c=buffer[0];
-
+
}
if (position<end-3) {
d=buffer[(long) position+2];
-
+
} else {
d=buffer[0];
}
@@ -803,3 +850,178 @@ void maxiSample::getLength() {
}
+/* OK this compressor and gate are now ready to use. The envelopes, like all the envelopes in this recent update, use stupid algorithms for
+ incrementing - consequently a long attack is something like 0.0001 and a long release is like 0.9999.
+ Annoyingly, a short attack is 0.1, and a short release is 0.99. I'll sort this out laters */
+
+double maxiDyn::gate(double input, double threshold, long holdtime, double attack, double release) {
+
+ if (fabs(input)>threshold && attackphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ if(amplitude==0) amplitude=0.01;
+ }
+
+ if (attackphase==1 && amplitude<1) {
+ amplitude*=(1+attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ attackphase=0;
+ holdphase=1;
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+
+double maxiDyn::compressor(double input, double ratio, double threshold, double attack, double release) {
+
+ if (fabs(input)>threshold && attackphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ if(currentRatio==0) currentRatio=ratio;
+ }
+
+ if (attackphase==1 && currentRatio<ratio-1) {
+ currentRatio*=(1+attack);
+ }
+
+ if (currentRatio>=ratio-1) {
+ attackphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && currentRatio>0.) {
+ currentRatio*=release;
+ }
+
+ if (input>0.) {
+ output = input/(1.+currentRatio);
+ } else {
+ output = input/(1.+currentRatio);
+ }
+
+ return output*(1+log(ratio));
+}
+
+
+/* Lots of people struggle with the envelope generators so here's a new easy one.
+ It takes mental numbers for attack and release tho. Basically, they're exponentials.
+ I'll map them out later so that it's a bit more intuitive */
+double maxiEnv::ar(double input, double attack, double release, long holdtime, int trigger) {
+
+ if (trigger==1 && attackphase!=1 && holdphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ }
+
+ if (attackphase==1) {
+ amplitude+=(1*attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ amplitude=1;
+ attackphase=0;
+ holdphase=1;
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime && trigger==1) {
+ output=input;
+ }
+
+ if (holdcount==holdtime && trigger!=1) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+/* and here's a new adsr. It's not bad, very simple to use*/
+
+double maxiEnv::adsr(double input, double attack, double decay, double sustain, double release, long holdtime, int trigger) {
+
+ if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){
+ holdcount=0;
+ decayphase=0;
+ sustainphase=0;
+ releasephase=0;
+ attackphase=1;
+ }
+
+ if (attackphase==1) {
+ amplitude+=(1*attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ amplitude=1;
+ attackphase=0;
+ decayphase=1;
+ }
+
+ if (decayphase==1) {
+ output=input*(amplitude*=decay);
+ if (amplitude<=sustain) {
+ decayphase=0;
+ holdphase=1;
+ }
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input*amplitude;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime && trigger==1) {
+ output=input*amplitude;
+ }
+
+ if (holdcount==holdtime && trigger!=1) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+double convert::mtof(int midinote) {
+
+ return mtofarray[midinote];
+} \ No newline at end of file
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.h b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.h
index 3304bac..102d552 100755
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.h
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/libs/maximilian.h
@@ -70,7 +70,7 @@ class maxiOsc {
double endphase;
double output;
double tri;
-
+
public:
maxiOsc();
@@ -79,12 +79,13 @@ public:
double phasor(double frequency);
double phasor(double frequency, double startphase, double endphase);
double saw(double frequency);
- double triangle(double frequency,double phase);
+ double triangle(double frequency);
double square(double frequency);
double pulse(double frequency, double duty);
double noise();
double sinebuf(double frequency);
double sinebuf4(double frequency);
+ void phaseReset(double phaseIn);
};
@@ -96,6 +97,7 @@ class maxiEnvelope {
double startval;
double currentval;
double nextval;
+ int isPlaying;
public:
double line(int numberofsegments,double segments[100]);
@@ -115,9 +117,10 @@ class maxiDelayline {
double memory[88200];
public:
+ maxiDelayline();
double dl(double input, int size, double feedback);
double dl(double input, int size, double feedback, int position);
-
+
};
@@ -134,6 +137,7 @@ class maxiFilter {
double z;//pole
double c;//filter coefficient
public:
+ maxiFilter():x(0.0), y(0.0), z(0.0), c(0.0){};
double cutoff;
double resonance;
double lores(double input,double cutoff1, double resonance);
@@ -159,35 +163,36 @@ public:
};
-
class maxiSample {
private:
string myPath;
int myChunkSize;
int mySubChunk1Size;
+ int readChannel;
short myFormat;
int myByteRate;
short myBlockAlign;
short myBitsPerSample;
- int myDataSize;
double position;
double speed;
double output;
public:
+ int myDataSize;
short myChannels;
int mySampleRate;
long length;
void getLength();
-
+
+
char* myData;
// get/set for the Path property
-
+
~maxiSample()
{
- delete myData;
+ if (myData) delete[] myData;
myChunkSize = NULL;
mySubChunk1Size = NULL;
myFormat = NULL;
@@ -199,9 +204,9 @@ public:
myDataSize = NULL;
}
-// maxiSample();
-
- bool load(string fileName);
+ maxiSample():myData(NULL){};
+
+ bool load(string fileName, int channel=0);
void trigger();
@@ -212,12 +217,14 @@ public:
double playOnce();
+ double playOnce(double speed);
+
double play(double speed);
double play(double frequency, double start, double end, double &pos);
double play(double frequency, double start, double end);
-
+
double play4(double frequency, double start, double end);
double bufferPlay(unsigned char &bufferin,long length);
@@ -303,7 +310,7 @@ public:
val = max(min(val, inMax), inMin);
return pow((outMax / outMin), (val - inMin) / (inMax - inMin)) * outMin;
}
-
+
static double inline explin(double val, double inMin, double inMax, double outMin, double outMax) {
//clipping
val = max(min(val, inMax), inMin);
@@ -313,4 +320,47 @@ public:
};
+class maxiDyn {
+
+
+public:
+ double gate(double input, double threshold=0.9, long holdtime=1, double attack=1, double release=0.9995);
+ double compressor(double input, double ratio, double threshold=0.9, double attack=1, double release=0.9995);
+ double input;
+ double ratio;
+ double currentRatio;
+ double threshold;
+ double output;
+ double attack;
+ double release;
+ double amplitude;
+ long holdtime;
+ long holdcount;
+ int attackphase,holdphase,releasephase;
+};
+
+class maxiEnv {
+
+
+public:
+ double ar(double input, double attack=1, double release=0.9, long holdtime=1, int trigger=0);
+ double adsr(double input, double attack=1, double decay=0.99, double sustain=0.125, double release=0.9, long holdtime=1, int trigger=0);
+ double input;
+ double output;
+ double attack;
+ double decay;
+ double sustain;
+ double release;
+ double amplitude;
+ int trigger;
+ long holdtime;
+ long holdcount;
+ int attackphase,decayphase,sustainphase,holdphase,releasephase;
+};
+
+class convert {
+public:
+ double mtof(int midinote);
+};
+
#endif
diff --git a/ofxMaxim/ofMaxim007Example/ofxMaxim/src/ofxMaxim.h b/ofxMaxim/ofMaxim007Example/ofxMaxim/src/ofxMaxim.h
index 3b5e3c5..ec8c539 100644
--- a/ofxMaxim/ofMaxim007Example/ofxMaxim/src/ofxMaxim.h
+++ b/ofxMaxim/ofMaxim007Example/ofxMaxim/src/ofxMaxim.h
@@ -36,6 +36,7 @@
#include "maximilian.h"
#include "maxiFFT.h"
#include "maxiGrains.h"
+#include "maxiMFCC.h"
typedef maxiMix ofxMaxiMix;
@@ -48,6 +49,7 @@ typedef maxiFFT ofxMaxiFFT;
typedef maxiIFFT ofxMaxiIFFT;
typedef maxiFFTOctaveAnalyzer ofxMaxiFFTOctaveAnalyzer;
typedef maxiSettings ofxMaxiSettings;
+typedef maxiMFCC ofxMaxiMFCC;
#endif
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.cpp b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.cpp
index e19498d..3f13bd2 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.cpp
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.cpp
@@ -469,10 +469,8 @@ fft::~fft() {
}
/* Calculate the power spectrum */
-void fft::powerSpectrum(int start, float *data, float *window, float *magnitude,float *phase, float *power, float *avg_power) {
+void fft::powerSpectrum(int start, float *data, float *window, float *magnitude,float *phase) {
int i;
- float total_power = 0.0f;
-
//windowing
for (i = 0; i < n; i++) {
@@ -484,23 +482,31 @@ void fft::powerSpectrum(int start, float *data, float *window, float *magnitude,
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];
+ float power = out_real[i]*out_real[i] + out_img[i]*out_img[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
- }
+ magnitude[i] = sqrt(power);
phase[i] = atan2(out_img[i],out_real[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
+// }
}
- /* calculate average power */
- *(avg_power) = total_power / (float) half;
}
+void fft::convToDB(float *in, float *out) {
+ for (int i = 0; i < half; i++) {
+ if (in[i] < 0.000001){ // less than 0.1 nV
+ out[i] = 0; // out of range
+ } else {
+ out[i] = 20.0*log10(in[i] + 1); // get to to db scale
+ }
+ }
+}
+
+
#ifdef __APPLE_CC__
/* Calculate the power spectrum */
@@ -519,7 +525,7 @@ void fft::powerSpectrum_vdsp(int start, float *data, float *window, float *magni
vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_FORWARD);
//scale by 2 (see vDSP docs)
- static float scale=0.5;
+ static float scale=0.5 ;
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, half);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, half);
@@ -533,13 +539,20 @@ void fft::powerSpectrum_vdsp(int start, float *data, float *window, float *magni
magnitude[i]=polar[2*i]+1.0;
phase[i]=polar[2*i + 1];
}
- float ref = 1.0;
- vDSP_vdbcon(magnitude, 1, &ref, magnitude, 1, half, 1);
}
+void fft::convToDB_vdsp(float *in, float *out) {
+ float ref = 1.0;
+ vDSP_vdbcon(in, 1, &ref, out, 1, half, 1);
+ //get rid of any -infs
+ float vmin=0.0;
+ float vmax=9999999.0;
+ vDSP_vclip(out, 1, &vmin, &vmax, out, 1, half);
+}
+
#endif
void fft::inversePowerSpectrum(int start, float *finalOut, float *window, float *magnitude,float *phase) {
@@ -547,9 +560,11 @@ void fft::inversePowerSpectrum(int start, float *finalOut, float *window, float
/* get real and imag part */
for (i = 0; i < half; i++) {
- float mag = pow(10.0, magnitude[i] / 20.0) - 1.0;
- in_real[i] = mag *cos(phase[i]);
- in_img[i] = mag *sin(phase[i]);
+// float mag = pow(10.0, magnitude[i] / 20.0) - 1.0;
+// in_real[i] = mag *cos(phase[i]);
+// in_img[i] = mag *sin(phase[i]);
+ in_real[i] = magnitude[i] *cos(phase[i]);
+ in_img[i] = magnitude[i] *sin(phase[i]);
}
/* zero negative frequencies */
@@ -571,7 +586,8 @@ void fft::inversePowerSpectrum_vdsp(int start, float *finalOut, float *window, f
uint32_t i;
for (i = 0; i < half; i++) {
- polar[2*i] = pow(10.0, magnitude[i] / 20.0) - 1.0;
+// polar[2*i] = pow(10.0, magnitude[i] / 20.0) - 1.0;
+ polar[2*i] = magnitude[i] - 1.0;
polar[2*i + 1] = phase[i];
}
@@ -581,7 +597,7 @@ void fft::inversePowerSpectrum_vdsp(int start, float *finalOut, float *window, f
vDSP_fft_zrip(setupReal, &A, 1, log2n, FFT_INVERSE);
vDSP_ztoc(&A, 1, (COMPLEX*) out_real, 2, half);
- static float scale = 1./(2. * n);
+ static float scale = 1./n;
vDSP_vsmul(out_real, 1, &scale, out_real, 1, n);
//multiply by window
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.h
index 77aa777..f7e1947 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.h
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/fft.h
@@ -38,10 +38,12 @@
#endif
#ifdef __APPLE_CC__
-#include <Accelerate/Accelerate.h>
+ #include <Accelerate/Accelerate.h>
+ #warning Please link against the Accelerate framework
#endif
+
class fft {
public:
@@ -61,12 +63,14 @@ public:
float *polar;
void powerSpectrum_vdsp(int start, float *data, float *window, float *magnitude,float *phase);
void inversePowerSpectrum_vdsp(int start, float *finalOut, float *window, float *magnitude,float *phase);
+ void convToDB_vdsp(float *in, float *out);
#endif;
/* Calculate the power spectrum */
- void powerSpectrum(int start, float *data, float *window, float *magnitude, float *phase, float *power, float *avg_power);
+ void powerSpectrum(int start, float *data, float *window, float *magnitude, float *phase);
/* ... the inverse */
void inversePowerSpectrum(int start, float *finalOut, float *window, float *magnitude,float *phase);
+ void convToDB(float *in, float *out);
static void genWindow(int whichFunction, int NumSamples, float *window);
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.cpp b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.cpp
index eee8ee8..36034b2 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.cpp
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.cpp
@@ -31,6 +31,7 @@
*/
#include "maxiFFT.h"
+#include "maximilian.h"
#include <iostream>
#include "math.h"
@@ -49,13 +50,13 @@ void maxiFFT::setup(int _fftSize, int _windowSize, int _hopSize) {
hopSize = _hopSize;
buffer = (float *) malloc(fftSize * sizeof(float));
magnitudes = (float *) malloc(bins * sizeof(float));
+ magnitudesDB = (float *) malloc(bins * sizeof(float));
phases = (float *) malloc(bins * sizeof(float));
- powers = (float *) malloc(bins * sizeof(float));
avgPower = new float;
memset(buffer, 0, fftSize * sizeof(float));
memset(magnitudes, 0, bins * sizeof(float));
+ memset(magnitudesDB, 0, bins * sizeof(float));
memset(phases, 0, bins * sizeof(float));
- memset(powers, 0, bins * sizeof(float));
*avgPower = 0;
pos =windowSize - hopSize;
newFFT = 0;
@@ -73,7 +74,7 @@ bool maxiFFT::process(float value) {
#if defined(__APPLE_CC__) && !defined(_NO_VDSP)
_fft->powerSpectrum_vdsp(0, buffer, window, magnitudes, phases);
#else
- _fft->powerSpectrum(0, buffer, window, magnitudes, phases, powers, avgPower);
+ _fft->powerSpectrum(0, buffer, window, magnitudes, phases);
#endif
//shift buffer back by one hop size
memcpy(buffer, buffer + hopSize, (windowSize - hopSize) * sizeof(float));
@@ -85,10 +86,42 @@ bool maxiFFT::process(float value) {
return newFFT;
}
+float* maxiFFT::magsToDB() {
+#if defined(__APPLE_CC__) && !defined(_NO_VDSP)
+ _fft->convToDB_vdsp(magnitudes, magnitudesDB);
+#else
+ _fft->convToDB(magnitudes, magnitudesDB);
+#endif
+ return magnitudesDB;
+}
+
+float maxiFFT::spectralFlatness() {
+ float geometricMean=0, arithmaticMean=0;
+ for(int i=0; i < bins; i++) {
+ if (magnitudes[i] != 0)
+ geometricMean += log(magnitudes[i]);
+ arithmaticMean += magnitudes[i];
+ }
+ geometricMean = exp(geometricMean / (float)bins);
+ arithmaticMean /= (float)bins;
+ return arithmaticMean !=0 ? geometricMean / arithmaticMean : 0;
+}
+
+float maxiFFT::spectralCentroid() {
+ float x=0, y=0;
+ for(int i=0; i < bins; i++) {
+ x += fabs(magnitudes[i]) * (i+1);
+ y += fabs(magnitudes[i]);
+ }
+ return y != 0 ? x / y * ((float) maxiSettings::sampleRate / fftSize) : 0;
+}
+
+
+
maxiFFT::~maxiFFT() {
delete _fft;
- delete[] buffer,magnitudes,phases,powers, window;
- delete avgPower;
+ if (buffer)
+ delete[] buffer,magnitudes,phases,window, avgPower;
}
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.h
index 4d73441..d099e84 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.h
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiFFT.h
@@ -37,29 +37,37 @@
#include "fft.h"
+#include "stddef.h"
class maxiFFT {
public:
maxiFFT(){
- _fft = 0;
+ _fft = NULL;
+ buffer = magnitudes = phases = window = avgPower = NULL;
};
~maxiFFT();
void setup(int fftSize, int windowSize, int hopSize);
bool process(float value);
- float *magnitudes, *phases, *powers;
+ float* magsToDB();
+ float *magnitudes, *phases, *magnitudesDB;
float *avgPower;
int windowSize;
int hopSize;
+ int bins;
+
+ //features
+ float spectralFlatness();
+ float spectralCentroid();
private:
float *buffer, *window;
- int bins;
int pos;
float nextValue;
int fftSize;
fft *_fft;
bool newFFT;
+
};
class maxiIFFT {
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.cpp b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.cpp
new file mode 100644
index 0000000..951f3b5
--- /dev/null
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.cpp
@@ -0,0 +1,6 @@
+#include "maxiGrains.h"
+
+
+
+
+
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.h
new file mode 100644
index 0000000..d17ffc9
--- /dev/null
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiGrains.h
@@ -0,0 +1,443 @@
+
+
+#ifndef _MAXI_GRAINS_H
+#define _MAXI_GRAINS_H
+#include "maximilian.h"
+
+#if defined(__APPLE_CC__)
+#include "accelerate/accelerate.h";
+//Mac users can uncommment the line below to use Apple's accelerate framework for calculating grains. This gives ~300% speed improvement and better sound quality, but doesn't work well on all machines.
+//#define MAXIGRAINFAST
+#endif
+
+#define PI 3.1415926535897932384626433832795028841968
+
+#include <list>
+
+typedef unsigned long ulong;
+
+//window functions from http://en.wikipedia.org/wiki/Window_function#High-_and_moderate-resolution_windows
+
+struct hannWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return 0.5 * (1.0 - cos((2.0 * PI * windowPos) / (windowLength - 1)));
+ }
+};
+
+//this window can produce clicks
+struct hammingWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return 0.54 - (0.46 * cos((2.0 * PI * windowPos) / (windowLength - 1)));
+ }
+};
+
+
+struct cosineWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return sin((PI * windowPos) / (windowLength - 1));
+ }
+};
+
+struct rectWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return 1;
+ }
+};
+
+struct triangleWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return (2.0 / (windowLength-1.0)) * (((windowLength-1.0)/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0)));
+ }
+};
+
+struct triangleNZWinFunctor {
+ //non zero end points
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return (2.0 / windowLength) * ((windowLength/2.0) - fabs(windowPos - ((windowLength-1.0)/2.0)));
+ }
+};
+
+struct blackmanHarrisWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return 0.35875 -
+ (0.48829 * cos((2 * PI * windowPos) / (windowLength-1))) +
+ (0.14128 * cos((4 * PI * windowPos) / (windowLength-1))) +
+ (0.01168 * cos((6 * PI * windowPos) / (windowLength-1)));
+ }
+};
+
+struct blackmanNutallWinFunctor {
+ inline double operator()(ulong windowLength, ulong windowPos) {
+ return 0.3635819 -
+ (0.4891775 * cos((2 * PI * windowPos) / (windowLength-1))) +
+ (0.1365995 * cos((4 * PI * windowPos) / (windowLength-1))) +
+ (0.0106411 * cos((6 * PI * windowPos) / (windowLength-1)));
+ }
+};
+
+template<typename F>
+class maxiGrainWindowCache {
+public:
+ unsigned int cacheSize;
+
+ maxiGrainWindowCache() {
+ cacheSize = maxiSettings::sampleRate / 2.0; //allocate mem for up to 500ms grains
+ cache = (double**)malloc(cacheSize * sizeof(double*));
+ for(int i=0; i < cacheSize; i++) {
+ cache[i] = NULL;
+ }
+ }
+
+ ~maxiGrainWindowCache() {
+ for(int i=0; i < cacheSize; i++) {
+ if(NULL != cache[i]) {
+ delete[] cache[i];
+ }
+ }
+ }
+
+ double* getWindow(const unsigned int length) {
+ if (NULL == cache[length]) {
+ cache[length] = (double*)malloc(length * sizeof(double));
+ for(int i=0; i < length; i++) {
+ cache[length][i] = F()(length, i);
+ }
+ }
+ return cache[length];
+ }
+
+private:
+ double** cache;
+
+};
+
+class maxiGrainBase {
+public:
+ virtual double play() = 0;
+ bool finished;
+};
+
+template<typename F>
+class maxiGrain : public maxiGrainBase {
+public:
+ maxiSample *sample;
+ double pos;
+ double dur;
+ ulong sampleStartPos;
+ ulong sampleIdx;
+ ulong sampleDur;
+ ulong sampleEndPos;
+ double freq;
+ double speed;
+ // F winFunc;
+ double inc;
+ double frequency;
+ double* window;
+#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST)
+ double* grainSamples;
+#endif
+ /*
+ position between 0.0 and 1.0
+ duration in seconds
+ */
+ maxiGrain(maxiSample *sample, const double position, const double duration, const double speed, maxiGrainWindowCache<F> *windowCache) :sample(sample), pos(position), dur(duration), speed(speed)
+ {
+ sampleStartPos = sample->length * pos;
+ sampleDur = dur * (double)sample->mySampleRate;
+ sampleDurMinusOne = sampleDur - 1;
+ sampleIdx = 0;
+ finished = 0;
+ freq = 1.0 / dur;
+ sampleEndPos = sampleStartPos + sampleDur;
+ frequency = freq * speed;
+ if (frequency > 0) {
+ pos = sampleStartPos;
+ }else{
+ pos = sampleEndPos;
+ }
+ inc = sampleDur/(maxiSettings::sampleRate/frequency);
+ window = windowCache->getWindow(sampleDur);
+
+#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST)
+ //premake the grain using fast vector functions, and quadratic interpolation
+ double *sourceData = (double*)malloc(sampleDur * sizeof(double));
+ short* buffer = (short *)sample->myData;
+ //convert sample to double data
+ vDSP_vflt16D(buffer + sampleStartPos, 1, sourceData, 1, min(sampleDur, sample->length - sampleStartPos));
+ //todo: wraping code
+
+ grainSamples = (double*)malloc(sampleDur * sizeof(double));
+ //make list of interpolation indexes
+ double* interpIndexes = (double*)malloc(sampleDur * sizeof(double));
+ double interpPos = sampleStartPos;
+ for(int i=0; i < sampleDur; i++) {
+ interpIndexes[i] = interpPos - sampleStartPos;
+ interpPos += fabs(inc);
+ }
+ vDSP_vqintD(sourceData, interpIndexes, 1, grainSamples, 1, sampleDur, sampleDur);
+ if (frequency < 0) {
+ vDSP_vrvrsD(grainSamples,1, sampleDur);
+ }
+ static double divFactor = 32767.0;
+ vDSP_vsdivD(grainSamples, 1, &divFactor, grainSamples, 1, sampleDur);
+ vDSP_vmulD(grainSamples, 1, window, 1, grainSamples, 1, sampleDur);
+ delete sourceData, interpIndexes;
+#endif
+ }
+
+ ~maxiGrain() {
+#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST)
+ delete[] grainSamples;
+#endif
+ }
+
+ double play() {
+ double output = 0.0;
+ if (!finished) {
+#if defined(__APPLE_CC__) && defined(MAXIGRAINFAST)
+ output = grainSamples[sampleIdx];
+#else
+ envValue = window[sampleIdx];
+ double remainder;
+ long a,b;
+ short* buffer = (short *)sample->myData;
+ if (frequency >0.) {
+ pos += inc;
+ long posl = static_cast<long>(pos);
+ remainder = pos - posl;
+ a=posl++;
+ if (a>=sample->length) {
+ a=posl-1;
+ }
+ b = posl+2;
+ if (b>=sample->length) {
+ b=sample->length-1;
+ }
+ output = (double) ((1-remainder) * buffer[a] +
+ remainder * buffer[b])/32767;//linear interpolation
+ } else {
+ frequency=frequency-(frequency+frequency);
+ pos += inc;
+ long posl = static_cast<long>(pos);
+ remainder = pos - posl;
+ if (posl-1>=0) {
+ a=posl-1;
+ }
+ else {
+ a=0;
+ }
+ if (posl-2>=0) {
+ b=posl-2;
+ }
+ else {
+ b=0;
+ }
+ output = (double) ((-1-remainder) * buffer[a] +
+ remainder * buffer[b])/32767;//linear interpolation
+ }
+ output *= envValue;
+#endif
+ }
+ sampleIdx++;
+ if (sampleIdx >= sampleDur) finished = 1;
+ return output;
+ }
+
+private:
+ maxiGrain();
+ double envValue;
+ ulong sampleDurMinusOne;
+};
+
+
+typedef list<maxiGrainBase*> grainList;
+
+class maxiGrainPlayer {
+public:
+ grainList grains;
+ maxiSample *sample;
+
+ maxiGrainPlayer(maxiSample *sample) : sample(sample) {
+ }
+
+ void addGrain(maxiGrainBase *g) {
+ grains.push_back(g);
+ }
+
+ double play() {
+ double total = 0.0;
+ for(grainList::iterator it = grains.begin(); it != grains.end(); ++it) {
+ total += (*it)->play();
+ if ((*it)->finished) {
+ delete(*it);
+ grains.erase(it);
+ }
+ }
+ return total;
+ }
+};
+
+template<typename F>
+class maxiTimestretch {
+public:
+ double position;
+ long cycles;
+ maxiSample *sample;
+ maxiGrainPlayer *grainPlayer;
+ maxiGrainWindowCache<F> windowCache;
+ double randomOffset;
+
+ maxiTimestretch(maxiSample *sample) : sample(sample) {
+ position=0;
+ cycles=0;
+ grainPlayer = new maxiGrainPlayer(sample);
+ randomOffset=0;
+ }
+
+ ~maxiTimestretch() {
+ delete grainPlayer;
+ }
+
+ double play(double speed, double grainLength, int overlaps, double posMod=0.0) {
+ position = position + (1 * speed);
+ cycles++;
+ if (position > sample->length) position=0;
+ if (position < 0) position = sample->length;
+ double cycleLength = grainLength * maxiSettings::sampleRate / overlaps;
+ double cycleMod = fmod(cycles, cycleLength + randomOffset);
+ if (0 == floor(cycleMod)) {
+ // cout << cycleMod << endl;
+ speed = (speed > 0 ? 1 : -1);
+ // speed = speed - ((cycleMod / cycleLength) * 0.1);
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache);
+ grainPlayer->addGrain(g);
+ // cout << grainPlayer->grains.size() << endl;
+ // randomOffset = rand() % 10;
+ // randomOffset = rand() % 10;
+ }
+ return grainPlayer->play();
+ }
+
+ double play2(double pos, double grainLength, int overlaps) {
+ cycles++;
+ pos *= sample->length;
+ if (0 == floor(fmod(cycles, grainLength * maxiSettings::sampleRate / overlaps))) {
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache);
+ grainPlayer->addGrain(g);
+ }
+ return grainPlayer->play();
+ }
+};
+
+//in maxiTimeStretch, the speed is either 1 or -1, and the actual speed value only affects the grain position
+//in maxiPitchShift, speed is uncoupled from position and allowed to set it's value incrementally, resulting in pitchshift.
+//with both high speed values and negative speed values there are some terrific artefacts!
+
+template<typename F>
+class maxiPitchShift {
+public:
+ double position;
+ long cycles;
+ maxiSample *sample;
+ maxiGrainPlayer *grainPlayer;
+ maxiGrainWindowCache<F> windowCache;
+ double randomOffset;
+
+ maxiPitchShift(maxiSample *sample) : sample(sample) {
+ position=0;
+ cycles=0;
+ grainPlayer = new maxiGrainPlayer(sample);
+ randomOffset=0;
+ }
+
+ ~maxiPitchShift() {
+ delete grainPlayer;
+ }
+
+ double play(double speed, double grainLength, int overlaps, double posMod=0.0) {
+ position = position + 1;
+ cycles++;
+ if (position > sample->length) position=0;
+ if (position < 0) position = sample->length;
+ double cycleLength = grainLength * maxiSettings::sampleRate / overlaps;
+ double cycleMod = fmod(cycles, cycleLength + randomOffset);
+ if (0 == floor(cycleMod)) {
+ // cout << cycleMod << endl;
+ //speed = (speed > 0 ? 1 : -1);
+ speed = speed - ((cycleMod / cycleLength) * 0.1);
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache);
+ grainPlayer->addGrain(g);
+ // cout << grainPlayer->grains.size() << endl;
+ // randomOffset = rand() % 10;
+ // randomOffset = rand() % 10;
+ }
+ return grainPlayer->play();
+ }
+
+ double play2(double pos, double grainLength, int overlaps) {
+ cycles++;
+ pos *= sample->length;
+ if (0 == floor(fmod(cycles, grainLength * maxiSettings::sampleRate / overlaps))) {
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache);
+ grainPlayer->addGrain(g);
+ }
+ return grainPlayer->play();
+ }
+};
+
+//and here's maxiPitchStretch. Args to the play function are basically speed for 'pitch' and rate for playback rate.
+//the rest is the same.
+
+template<typename F>
+class maxiPitchStretch {
+public:
+ double position;
+ long cycles;
+ maxiSample *sample;
+ maxiGrainPlayer *grainPlayer;
+ maxiGrainWindowCache<F> windowCache;
+ double randomOffset;
+
+ maxiPitchStretch(maxiSample *sample) : sample(sample) {
+ position=0;
+ cycles=0;
+ grainPlayer = new maxiGrainPlayer(sample);
+ randomOffset=0;
+ }
+
+ ~maxiPitchStretch() {
+ delete grainPlayer;
+ }
+
+ double play(double speed, double rate, double grainLength, int overlaps, double posMod=0.0) {
+ position = position + (1 * rate);
+ cycles++;
+ if (position > sample->length) position=0;
+ if (position < 0) position = sample->length;
+ double cycleLength = grainLength * maxiSettings::sampleRate / overlaps;
+ double cycleMod = fmod(cycles, cycleLength + randomOffset);
+ if (0 == floor(cycleMod)) {
+ // cout << cycleMod << endl;
+ //speed = (speed > 0 ? 1 : -1);
+ speed = speed - ((cycleMod / cycleLength) * 0.1);
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(position / sample->length) + posMod),0.0), grainLength, speed, &windowCache);
+ grainPlayer->addGrain(g);
+ // cout << grainPlayer->grains.size() << endl;
+ // randomOffset = rand() % 10;
+ // randomOffset = rand() % 10;
+ }
+ return grainPlayer->play();
+ }
+
+ double play2(double pos, double grainLength, int overlaps) {
+ cycles++;
+ pos *= sample->length;
+ if (0 == floor(fmod(cycles, grainLength * maxiSettings::sampleRate / overlaps))) {
+ maxiGrain<F> *g = new maxiGrain<F>(sample, max(min(1.0,(pos / sample->length)),0.0), grainLength, 1, &windowCache);
+ grainPlayer->addGrain(g);
+ }
+ return grainPlayer->play();
+ }
+};
+
+#endif \ No newline at end of file
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.cpp b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.cpp
new file mode 100644
index 0000000..e72fd75
--- /dev/null
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.cpp
@@ -0,0 +1,78 @@
+/*
+ * maxiMFCC.cpp
+ * mfccs
+ *
+ * Created by Chris on 08/03/2011.
+ * Copyright 2011 Goldsmiths Creative Computing. All rights reserved.
+ *
+ */
+
+#include "maxiMFCC.h"
+
+
+
+template <>
+void maxiMFCCAnalyser<double>::dct(double *mfccs) {
+ vDSP_mmulD(melBands, 1, dctMatrix, 1, mfccs, 1, 1, numCoeffs, numFilters);
+ double n = (double) numCoeffs;
+ vDSP_vsdivD(mfccs, 1, &n, mfccs, 1, numCoeffs);
+}
+
+template <>
+void maxiMFCCAnalyser<float>::dct(float *mfccs) {
+ vDSP_mmul(melBands, 1, dctMatrix, 1, mfccs, 1, 1, numCoeffs, numFilters);
+ float n = (float) numCoeffs;
+ vDSP_vsdiv(mfccs, 1, &n, mfccs, 1, numCoeffs);
+}
+
+template <>
+void maxiMFCCAnalyser<double>::melFilterAndLogSquare(float* powerSpectrum) {
+#ifdef __APPLE_CC__
+ //conv to double
+ vDSP_vspdp(powerSpectrum, 1, doubleSpec, 1, numBins);
+ // vDSP_mmulD(doubleSpec, 1, melFilters, 1, melBands, 1, 1, 42, 512);
+ vDSP_mmulD(doubleSpec, 1, melFilters, 1, melBands, 1, 1, numFilters, numBins);
+#endif
+ melFilterAndLogSq_Part2();
+}
+
+
+template <>
+void maxiMFCCAnalyser<float>::melFilterAndLogSquare(float* powerSpectrum) {
+#ifdef __APPLE_CC__
+ vDSP_mmul(powerSpectrum, 1, melFilters, 1, melBands, 1, 1, numFilters, numBins);
+#endif
+ melFilterAndLogSq_Part2();
+}
+
+template <class T>
+void maxiMFCCAnalyser<T>::melFilterAndLogSq_Part2() {
+#ifdef __APPLE_CC__
+#else
+ for (int filter = 0;filter < numFilters;filter++) {
+ melBands[filter] = 0.0;
+ for (int bin=0;bin<numBins;bin++) {
+ // int idx = (numBins * filter) + bin;
+ int idx = filter + (bin * numFilters);
+ // melBands[filter] += (melFilters[filter][bin] * powerSpectrum[bin]);
+ melBands[filter] += (melFilters[idx] * powerSpectrum[bin]);
+ }
+ }
+#endif
+ for(int filter=0; filter < numFilters; filter++) {
+ // log the square
+ melBands[filter] = melBands[filter] > 0.000001 ? log(melBands[filter] * melBands[filter]) : 0.0;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.h
new file mode 100644
index 0000000..60bfe04
--- /dev/null
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maxiMFCC.h
@@ -0,0 +1,204 @@
+/*
+ * maxiMFCC.h
+ * mfccs
+ *
+ * Created by Chris on 08/03/2011.
+ * Copyright 2011 Goldsmiths Creative Computing. All rights reserved.
+ *
+
+ Based on Matthew Yee-King's MFCCMYK java class
+ */
+
+#pragma once
+#pragma pack(16)
+
+#include "maxiFFT.h"
+#include <math.h>
+#include <iostream>
+#ifdef __APPLE_CC__
+#include <Accelerate/Accelerate.h>
+#endif
+
+using namespace std;
+
+
+// implements this formula:
+// mel = 2595 log10(Hz/700 + 1)
+inline double hzToMel(double hz){
+ return 2595.0 * (log10(hz/700.0 + 1.0));
+}
+
+// implements this formula
+// Hz = 700 (10^(mel/2595) - 1)
+inline double melToHz(double mel){
+ return 700.0 * (pow(10, mel/2595.0) - 1.0);
+}
+
+template <class T>
+class maxiMFCCAnalyser {
+public:
+ T *melBands;
+ maxiMFCCAnalyser():melFilters(NULL),dctMatrix(NULL), melBands(NULL){};
+ ~maxiMFCCAnalyser() {
+ if (melFilters) {
+ delete[] melFilters;
+ delete[] melBands;
+ delete[] dctMatrix;
+#ifdef __APPLE_CC__
+ delete doubleSpec;
+#endif
+ }
+ }
+
+ void setup(unsigned int numBins, unsigned int numFilters, unsigned int numCoeffs, double minFreq, double maxFreq, unsigned int sampleRate)
+ {
+ this->numFilters = numFilters;
+ this->numCoeffs = numCoeffs;
+ this->minFreq = minFreq;
+ this->maxFreq = maxFreq;
+ this->sampleRate = sampleRate;
+ this->numBins = numBins;
+ melFilters = NULL;
+ melBands = (T*) malloc(sizeof(T) * numFilters);
+#ifdef __APPLE_CC__
+ doubleSpec = (T*)malloc(sizeof(T) * numBins);
+#endif
+ //create new matrix
+ dctMatrix = (T*)malloc(sizeof(T) * numCoeffs * numFilters);
+ calcMelFilterBank(sampleRate, numBins);
+ createDCTCoeffs();
+ }
+ void mfcc(float* powerSpectrum, T *mfccs) {
+ melFilterAndLogSquare(powerSpectrum);
+ dct(mfccs);
+ }
+
+private:
+ unsigned int numFilters, numCoeffs;
+ double minFreq, maxFreq;
+ unsigned int sampleRate;
+ T *melFilters;
+ unsigned int numBins;
+ T *dctMatrix;
+#ifdef __APPLE_CC__
+ T *doubleSpec;
+#endif
+
+#ifdef __APPLE_CC__
+ void dct(T *mfccs); //define later
+#else
+ void dct(T *mfccs) {
+ for(int i=0; i < numCoeffs; i++) {
+ mfccs[i] = 0.0;
+ }
+ for(int i=0; i < numCoeffs; i++ ) {
+ for(int j=0; j < numFilters; j++) {
+ int idx = i + (j * numCoeffs);
+ mfccs[i] += (dctMatrix[idx] * melBands[j]);
+ }
+ }
+ for(int i=0; i < numCoeffs; i++) {
+ mfccs[i] /= numCoeffs;
+ }
+ }
+#endif
+
+ void melFilterAndLogSquare(float* powerSpectrum);
+ void melFilterAndLogSq_Part2();
+
+
+ void calcMelFilterBank(double sampleRate, int numBins) {
+
+ double mel, dMel, maxMel, minMel, nyquist, binFreq, start, end, thisF, nextF, prevF;
+ int numValidBins;
+
+ // ignore bins over nyquist
+ numValidBins = numBins;
+
+ nyquist = sampleRate/2;
+ if (maxFreq > nyquist) {
+ maxFreq = nyquist;
+ }
+
+ maxMel = hzToMel(maxFreq);
+ minMel = hzToMel(minFreq);
+
+ dMel = (maxMel - minMel) / (numFilters + 2 - 1);
+
+ T *filtPos = (T*) malloc(sizeof(double) * (numFilters + 2));
+
+ // first generate an array of start and end freqs for each triangle
+ mel = minMel;
+ for (int i=0;i<numFilters + 2;i++) {
+ // start of the triangle
+ filtPos[i] = melToHz(mel);
+ // std::cout << "[" << i << "] MFCC: centre is at " <<filtPos[i]<<"hz "<<mel<<" mels" << endl;
+ mel += dMel;
+ }
+ // now generate the coefficients for the mag spectrum
+ melFilters = (T*) malloc(sizeof(T) * numFilters * numValidBins);
+
+ for (int filter = 1; filter < numFilters; filter++) {
+ for (int bin=0;bin<numValidBins;bin++) {
+ // frequency this bin represents
+ binFreq = (T) sampleRate / (T) numValidBins * (T) bin;
+ thisF = filtPos[filter];
+ nextF = filtPos[filter+1];
+ prevF = filtPos[filter-1];
+ int idx = filter + (bin * numFilters);
+ if (binFreq > nextF || binFreq < prevF) {
+ // outside this filter
+ melFilters[idx] = 0;
+ //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
+ }
+ else {
+ T height = 2.0 / (nextF - prevF);
+
+ if (binFreq < thisF) {
+ // up
+ start = prevF;
+ end = thisF;
+ melFilters[idx] = (binFreq - start) * (height / (thisF - start));
+ }
+ else {
+ // down
+ start = thisF;
+ end = nextF;
+ melFilters[idx] = height + ((binFreq - thisF) * (-height /(nextF - thisF)));
+ }
+ // cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[filter][bin] << endl;
+ //cout << "MFCCMYK: filter at " <<thisF << " bin at " <<binFreq <<" coeff " <<melFilters[idx] << endl;
+ }
+ }
+ }
+ }
+ void createDCTCoeffs() {
+ T k = 3.14159265358979323846/numFilters;
+ T w1 = 1.0/(sqrt(numFilters));
+ T w2 = sqrt(2.0/numFilters);
+
+
+ //generate dct matrix
+ for(int i = 0; i < numCoeffs; i++)
+ {
+ for(int j = 0; j < numFilters; j++)
+ {
+ int idx = i + (j * numCoeffs);
+ if(i == 0)
+ dctMatrix[idx]= w1 * cos(k * (i+1) * (j + 0.5));
+ else
+ dctMatrix[idx] = w2 * cos(k * (i+1) * (j + 0.5));
+ }
+ }
+
+
+ }
+
+
+
+};
+
+
+
+typedef maxiMFCCAnalyser<double> maxiMFCC;
+//typedef maxiMFCCAnalyser<float> maxiFloatMFCC;
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.cpp b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.cpp
index efd6d28..3741173 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.cpp
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.cpp
@@ -34,22 +34,29 @@
#include "maximilian.h"
#include "math.h"
-int channels=2;
-int samplerate=44100;
-int buffersize=1024;
+
+//int channels=2;
+//int samplerate=44100;
+//int buffersize=1024;
float chandiv= 1;
+int maxiSettings::sampleRate = 44100;
+int maxiSettings::channels = 2;
+int maxiSettings::bufferSize = 1024;
+
double sineBuffer[514]={0,0.012268,0.024536,0.036804,0.049042,0.06131,0.073547,0.085785,0.097992,0.1102,0.12241,0.13455,0.1467,0.15884,0.17093,0.18301,0.19507,0.20709,0.21909,0.23105,0.24295,0.25485,0.26669,0.2785,0.29025,0.30197,0.31366,0.32529,0.33685,0.34839,0.35986,0.37128,0.38266,0.39395,0.40521,0.41641,0.42752,0.4386,0.44958,0.46051,0.47137,0.48215,0.49286,0.50351,0.51407,0.52457,0.53497,0.54529,0.55554,0.5657,0.57578,0.58575,0.59567,0.60547,0.6152,0.62482,0.63437,0.6438,0.65314,0.66238,0.67151,0.68057,0.68951,0.69833,0.70706,0.7157,0.72421,0.7326,0.74091,0.74908,0.75717,0.76514,0.77298,0.7807,0.7883,0.79581,0.80316,0.81042,0.81754,0.82455,0.83142,0.8382,0.84482,0.85132,0.8577,0.86392,0.87006,0.87604,0.88187,0.8876,0.89319,0.89862,0.90396,0.90912,0.91415,0.91907,0.92383,0.92847,0.93295,0.93729,0.9415,0.94556,0.94949,0.95325,0.95691,0.96039,0.96375,0.96692,0.97,0.9729,0.97565,0.97827,0.98074,0.98306,0.98523,0.98724,0.98914,0.99084,0.99243,0.99387,0.99515,0.99628,0.99725,0.99808,0.99875,0.99927,0.99966,0.99988,0.99997,0.99988,0.99966,0.99927,0.99875,0.99808,0.99725,0.99628,0.99515,0.99387,0.99243,0.99084,0.98914,0.98724,0.98523,0.98306,0.98074,0.97827,0.97565,0.9729,0.97,0.96692,0.96375,0.96039,0.95691,0.95325,0.94949,0.94556,0.9415,0.93729,0.93295,0.92847,0.92383,0.91907,0.91415,0.90912,0.90396,0.89862,0.89319,0.8876,0.88187,0.87604,0.87006,0.86392,0.8577,0.85132,0.84482,0.8382,0.83142,0.82455,0.81754,0.81042,0.80316,0.79581,0.7883,0.7807,0.77298,0.76514,0.75717,0.74908,0.74091,0.7326,0.72421,0.7157,0.70706,0.69833,0.68951,0.68057,0.67151,0.66238,0.65314,0.6438,0.63437,0.62482,0.6152,0.60547,0.59567,0.58575,0.57578,0.5657,0.55554,0.54529,0.53497,0.52457,0.51407,0.50351,0.49286,0.48215,0.47137,0.46051,0.44958,0.4386,0.42752,0.41641,0.40521,0.39395,0.38266,0.37128,0.35986,0.34839,0.33685,0.32529,0.31366,0.30197,0.29025,0.2785,0.26669,0.25485,0.24295,0.23105,0.21909,0.20709,0.19507,0.18301,0.17093,0.15884,0.1467,0.13455,0.12241,0.1102,0.097992,0.085785,0.073547,0.06131,0.049042,0.036804,0.024536,0.012268,0,-0.012268,-0.024536,-0.036804,-0.049042,-0.06131,-0.073547,-0.085785,-0.097992,-0.1102,-0.12241,-0.13455,-0.1467,-0.15884,-0.17093,-0.18301,-0.19507,-0.20709,-0.21909,-0.23105,-0.24295,-0.25485,-0.26669,-0.2785,-0.29025,-0.30197,-0.31366,-0.32529,-0.33685,-0.34839,-0.35986,-0.37128,-0.38266,-0.39395,-0.40521,-0.41641,-0.42752,-0.4386,-0.44958,-0.46051,-0.47137,-0.48215,-0.49286,-0.50351,-0.51407,-0.52457,-0.53497,-0.54529,-0.55554,-0.5657,-0.57578,-0.58575,-0.59567,-0.60547,-0.6152,-0.62482,-0.63437,-0.6438,-0.65314,-0.66238,-0.67151,-0.68057,-0.68951,-0.69833,-0.70706,-0.7157,-0.72421,-0.7326,-0.74091,-0.74908,-0.75717,-0.76514,-0.77298,-0.7807,-0.7883,-0.79581,-0.80316,-0.81042,-0.81754,-0.82455,-0.83142,-0.8382,-0.84482,-0.85132,-0.8577,-0.86392,-0.87006,-0.87604,-0.88187,-0.8876,-0.89319,-0.89862,-0.90396,-0.90912,-0.91415,-0.91907,-0.92383,-0.92847,-0.93295,-0.93729,-0.9415,-0.94556,-0.94949,-0.95325,-0.95691,-0.96039,-0.96375,-0.96692,-0.97,-0.9729,-0.97565,-0.97827,-0.98074,-0.98306,-0.98523,-0.98724,-0.98914,-0.99084,-0.99243,-0.99387,-0.99515,-0.99628,-0.99725,-0.99808,-0.99875,-0.99927,-0.99966,-0.99988,-0.99997,-0.99988,-0.99966,-0.99927,-0.99875,-0.99808,-0.99725,-0.99628,-0.99515,-0.99387,-0.99243,-0.99084,-0.98914,-0.98724,-0.98523,-0.98306,-0.98074,-0.97827,-0.97565,-0.9729,-0.97,-0.96692,-0.96375,-0.96039,-0.95691,-0.95325,-0.94949,-0.94556,-0.9415,-0.93729,-0.93295,-0.92847,-0.92383,-0.91907,-0.91415,-0.90912,-0.90396,-0.89862,-0.89319,-0.8876,-0.88187,-0.87604,-0.87006,-0.86392,-0.8577,-0.85132,-0.84482,-0.8382,-0.83142,-0.82455,-0.81754,-0.81042,-0.80316,-0.79581,-0.7883,-0.7807,-0.77298,-0.76514,-0.75717,-0.74908,-0.74091,-0.7326,-0.72421,-0.7157,-0.70706,-0.69833,-0.68951,-0.68057,-0.67151,-0.66238,-0.65314,-0.6438,-0.63437,-0.62482,-0.6152,-0.60547,-0.59567,-0.58575,-0.57578,-0.5657,-0.55554,-0.54529,-0.53497,-0.52457,-0.51407,-0.50351,-0.49286,-0.48215,-0.47137,-0.46051,-0.44958,-0.4386,-0.42752,-0.41641,-0.40521,-0.39395,-0.38266,-0.37128,-0.35986,-0.34839,-0.33685,-0.32529,-0.31366,-0.30197,-0.29025,-0.2785,-0.26669,-0.25485,-0.24295,-0.23105,-0.21909,-0.20709,-0.19507,-0.18301,-0.17093,-0.15884,-0.1467,-0.13455,-0.12241,-0.1102,-0.097992,-0.085785,-0.073547,-0.06131,-0.049042,-0.036804,-0.024536,-0.012268,0,0.012268
};
+int mtofarray[129]={0, 8.661957, 9.177024, 9.722718, 10.3, 10.913383, 11.562325, 12.25, 12.978271, 13.75, 14.567617, 15.433853, 16.351599, 17.323914, 18.354048, 19.445436, 20.601723, 21.826765, 23.124651, 24.5, 25.956543, 27.5, 29.135235, 30.867706, 32.703197, 34.647827, 36.708096, 38.890873, 41.203445, 43.65353, 46.249302, 49., 51.913086, 55., 58.27047, 61.735413, 65.406395, 69.295654, 73.416191, 77.781746, 82.406891, 87.30706, 92.498604, 97.998856, 103.826172, 110., 116.540939, 123.470825, 130.81279, 138.591309, 146.832382, 155.563492, 164.813782, 174.61412, 184.997208, 195.997711, 207.652344, 220., 233.081879, 246.94165, 261.62558, 277.182617,293.664764, 311.126984, 329.627563, 349.228241, 369.994415, 391.995422, 415.304688, 440., 466.163757, 493.883301, 523.25116, 554.365234, 587.329529, 622.253967, 659.255127, 698.456482, 739.988831, 783.990845, 830.609375, 880., 932.327515, 987.766602, 1046.502319, 1108.730469, 1174.659058, 1244.507935, 1318.510254, 1396.912964, 1479.977661, 1567.981689, 1661.21875, 1760., 1864.655029, 1975.533203, 2093.004639, 2217.460938, 2349.318115, 2489.015869, 2637.020508, 2793.825928, 2959.955322, 3135.963379, 3322.4375, 3520., 3729.31, 3951.066406, 4186.009277, 4434.921875, 4698.63623, 4978.031738, 5274.041016, 5587.651855, 5919.910645, 6271.926758, 6644.875, 7040., 7458.620117, 7902.132812, 8372.018555, 8869.84375, 9397.272461, 9956.063477, 10548.082031, 11175.303711, 11839.821289, 12543.853516, 13289.75};
+
void setup();//use this to do any initialisation if you want.
void play(double *channels);//run dac!
maxiOsc::maxiOsc(){
phase = 0.0;
-// memset(phases,0,500);
-// memset(freqs,0,500);
+ // memset(phases,0,500);
+ // memset(freqs,0,500);
}
double maxiOsc::noise() {
@@ -59,10 +66,15 @@ double maxiOsc::noise() {
return(output);
}
+void maxiOsc::phaseReset(double phaseIn) {
+ phase=phaseIn;
+
+}
+
double maxiOsc::sinewave(double frequency) {
output=sin (phase*(TWOPI));
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
return(output);
}
@@ -70,7 +82,7 @@ double maxiOsc::sinewave(double frequency) {
double maxiOsc::sinebuf4(double frequency) {
double remainder;
double a,b,c,d,a1,a2,a3;
- phase += 512./(samplerate/(frequency));
+ phase += 512./(maxiSettings::sampleRate/(frequency));
if ( phase >= 511 ) phase -=512;
remainder = phase - floor(phase);
@@ -97,7 +109,7 @@ double maxiOsc::sinebuf4(double frequency) {
double maxiOsc::sinebuf(double frequency) {
double remainder;
- phase += 512./(samplerate/(frequency*chandiv));
+ phase += 512./(maxiSettings::sampleRate/(frequency*chandiv));
if ( phase >= 511 ) phase -=512;
remainder = phase - floor(phase);
output = (double) ((1-remainder) * sineBuffer[1+ (long) phase] + remainder * sineBuffer[2+(long) phase]);
@@ -107,7 +119,7 @@ double maxiOsc::sinebuf(double frequency) {
double maxiOsc::coswave(double frequency) {
output=cos (phase*(TWOPI));
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
return(output);
}
@@ -115,7 +127,7 @@ double maxiOsc::coswave(double frequency) {
double maxiOsc::phasor(double frequency) {
output=phase;
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
return(output);
}
@@ -123,7 +135,7 @@ double maxiOsc::square(double frequency) {
if (phase<0.5) output=-1;
if (phase>0.5) output=1;
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
return(output);
}
@@ -131,7 +143,7 @@ double maxiOsc::pulse(double frequency, double duty) {
if (duty<0.) duty=0;
if (duty>1.) duty=1;
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
if (phase<duty) output=-1.;
if (phase>duty) output=1.;
return(output);
@@ -143,7 +155,7 @@ double maxiOsc::phasor(double frequency, double startphase, double endphase) {
phase=startphase;
}
if ( phase >= endphase ) phase = startphase;
- phase += ((endphase-startphase)/(samplerate/(frequency)));
+ phase += ((endphase-startphase)/(maxiSettings::sampleRate/(frequency)));
return(output);
}
@@ -152,19 +164,18 @@ double maxiOsc::saw(double frequency) {
output=phase;
if ( phase >= 1.0 ) phase -= 2.0;
- phase += (1./(samplerate/(frequency)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
return(output);
}
-double maxiOsc::triangle(double frequency, double phase) {
- output=tri*2;
+double maxiOsc::triangle(double frequency) {
if ( phase >= 1.0 ) phase -= 1.0;
- phase += (1./(samplerate/(frequency*chandiv)));
+ phase += (1./(maxiSettings::sampleRate/(frequency)));
if (phase <= 0.5 ) {
- tri = phase;
- } else {
- tri =(1-phase);
+ output =((phase)*4)-1;
+ } else {
+ output =((0.5-phase)*4)-1;
}
return(output);
@@ -172,36 +183,54 @@ double maxiOsc::triangle(double frequency, double phase) {
//I like this.
double maxiEnvelope::line(int numberofsegments,double segments[1000]) {
- period=2./(segments[valindex+1]*0.004);
- nextval=segments[valindex+2];
- currentval=segments[valindex];
- if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) {
- amplitude += ((currentval-startval)/(samplerate/period));
- } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) {
- amplitude -= (((currentval-startval)*(-1))/(samplerate/period));
- } else if (valindex >numberofsegments-1) {
- valindex=numberofsegments-2;
- } else {
- valindex=valindex+2;
- startval=currentval;
+ if (isPlaying==1) {//only make a sound once you've been triggered
+
+ period=2./(segments[valindex+1]*0.004);
+ nextval=segments[valindex+2];
+ currentval=segments[valindex];
+ if (currentval-amplitude > 0.0000001 && valindex < numberofsegments) {
+ amplitude += ((currentval-startval)/(maxiSettings::sampleRate/period));
+ } else if (currentval-amplitude < -0.0000001 && valindex < numberofsegments) {
+ amplitude -= (((currentval-startval)*(-1))/(maxiSettings::sampleRate/period));
+ } else if (valindex >numberofsegments-1) {
+ valindex=numberofsegments-2;
+ } else {
+ valindex=valindex+2;
+ startval=currentval;
+ }
+ output=amplitude;
+
}
- output=amplitude;
- return(output);
+ else {
+ output=0;
+
+ }
+ return(output);
}
//and this
-void maxiEnvelope::trigger(int index,double amp) {
+void maxiEnvelope::trigger(int index, double amp) {
+ isPlaying=1;//ok the envelope is being used now.
valindex=index;
amplitude=amp;
}
//and this
+
+maxiDelayline::maxiDelayline() {
+ memory[88200]=NULL;
+
+}
+
+
double maxiDelayline::dl(double input, int size, double feedback) {
- if ( phase >=size ) phase = 0;
+ if ( phase >=size ) {
+ phase = 0;
+ }
memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5;
phase+=1;
- output=memory[phase+1];
+ output=memory[phase];
return(output);
}
@@ -231,9 +260,10 @@ double maxiFilter::hipass(double input, double cutoff) {
//awesome. cuttof is freq in hz. res is between 1 and whatever. Watch out!
double maxiFilter::lores(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
- if (cutoff>(samplerate*0.25)) cutoff=(samplerate*0.25);
+ if (cutoff<10) cutoff=10;
+ if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
- z=cos(TWOPI*cutoff/samplerate);
+ z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
@@ -243,12 +273,13 @@ double maxiFilter::lores(double input,double cutoff1, double resonance) {
return(output);
}
-//this is just stupid. Kindof works.
+//working hires filter
double maxiFilter::hires(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
- if (cutoff>(samplerate*0.25)) cutoff=(samplerate*0.25);
+ if (cutoff<10) cutoff=10;
+ if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
- z=cos(TWOPI*cutoff/samplerate);
+ z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
@@ -261,9 +292,9 @@ double maxiFilter::hires(double input,double cutoff1, double resonance) {
//This works a bit. Needs attention.
double maxiFilter::bandpass(double input,double cutoff1, double resonance) {
cutoff=cutoff1;
- if (cutoff>(samplerate*0.5)) cutoff=(samplerate*0.5);
+ if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance>=1.) resonance=0.999999;
- z=cos(TWOPI*cutoff/samplerate);
+ z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
inputs[0] = (1-resonance)*(sqrt(resonance*(resonance-4.0*pow(z,2.0)+2.0)+1));
inputs[1] = 2*z*resonance;
inputs[2] = pow((resonance*-1),2);
@@ -316,8 +347,9 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double
}
-bool maxiSample::load(string fileName) {
+bool maxiSample::load(string fileName, int channel) {
myPath = fileName;
+ readChannel=channel;
return read();
}
@@ -325,23 +357,125 @@ void maxiSample::trigger() {
position = 0;
}
+bool maxiSample::read()
+{
+ bool result;
+ ifstream inFile( myPath.c_str(), ios::in | ios::binary);
+ result = inFile;
+ if (inFile) {
+ bool datafound = false;
+ inFile.seekg(4, ios::beg);
+ inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize
+
+ inFile.seekg(16, ios::beg);
+ inFile.read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size
+
+ //inFile.seekg(20, ios::beg);
+ inFile.read( (char*) &myFormat, sizeof(short) ); // read the file format. This should be 1 for PCM
+
+ //inFile.seekg(22, ios::beg);
+ inFile.read( (char*) &myChannels, sizeof(short) ); // read the # of channels (1 or 2)
+
+ //inFile.seekg(24, ios::beg);
+ inFile.read( (char*) &mySampleRate, sizeof(int) ); // read the samplerate
+
+ //inFile.seekg(28, ios::beg);
+ inFile.read( (char*) &myByteRate, sizeof(int) ); // read the byterate
+
+ //inFile.seekg(32, ios::beg);
+ inFile.read( (char*) &myBlockAlign, sizeof(short) ); // read the blockalign
+
+ //inFile.seekg(34, ios::beg);
+ inFile.read( (char*) &myBitsPerSample, sizeof(short) ); // read the bitspersample
+
+ //ignore any extra chunks
+ char chunkID[5]="";
+ chunkID[4] = 0;
+ int filePos = 36;
+ while(!datafound && !inFile.eof()) {
+ inFile.seekg(filePos, ios::beg);
+ inFile.read((char*) &chunkID, sizeof(char) * 4);
+ inFile.seekg(filePos + 4, ios::beg);
+ inFile.read( (char*) &myDataSize, sizeof(int) ); // read the size of the data
+ filePos += 8;
+ if (strcmp(chunkID,"data") == 0) {
+ datafound = true;
+ }else{
+ filePos += myDataSize;
+ }
+ }
+
+ // read the data chunk
+ myData = (char*) malloc(myDataSize * sizeof(char));
+ inFile.seekg(filePos, ios::beg);
+ inFile.read(myData, myDataSize);
+ length=myDataSize*(0.5/myChannels);
+ inFile.close(); // close the input file
+
+ if (myChannels>1) {
+ int position=0;
+ int channel=readChannel*2;
+ for (int i=channel;i<myDataSize+6;i+=(myChannels*2)) {
+ myData[position]=myData[i];
+ myData[position+1]=myData[i+1];
+ position+=2;
+ }
+ }
+
+ }else {
+ cout << "ERROR: Could not load sample: " <<myPath << endl;
+ }
+
+
+ return result; // this should probably be something more descriptive
+}
+
+
double maxiSample::play() {
- long length=myDataSize*(1./myChannels);
+ // long length=myDataSize*(1./myChannels);
double remainder;
short* buffer = (short *)myData;
position=(position+1);
remainder = position - (long) position;
if ((long) position>length) position=0;
- output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ output =
+ (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ return(output);
+}
+
+double maxiSample::playOnce() {
+ // long length=myDataSize*(0.5/myChannels);
+ double remainder;
+ short* buffer = (short *)myData;
+ position=(position+1);
+ remainder = position - (long) position;
+ if ((long) position<length)
+ output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ else
+ output=0;
+
+ return(output);
+}
+
+double maxiSample::playOnce(double speed) {
+ double remainder;
+ //long a,b;
+ // long length=myDataSize*0.5;
+ short* buffer = (short *)myData;
+ position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate));
+ if ((long) position<length)
+ output = (double) ((1-remainder) * buffer[1+ (long) position] + remainder * buffer[2+(long) position])/32767;//linear interpolation
+ else
+ output=0;
return(output);
}
double maxiSample::play(double speed) {
double remainder;
long a,b;
-// long length=myDataSize*0.5;
+ // long length=myDataSize*0.5;
short* buffer = (short *)myData;
- position=position+((speed*chandiv*myChannels)/(samplerate/mySampleRate));
+ position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate));
if (speed >=0) {
if ((long) position>=length-1) position=1;
@@ -355,79 +489,84 @@ double maxiSample::play(double speed) {
}
if (position+2<length)
{
- b=position+2;
+ b=position+2;
}
else {
- b=length-1;
+ b=length-1;
}
output = (double) ((1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation
-} else {
+ } else {
if ((long) position<0) position=length;
remainder = position - floor(position);
if (position-1>=0) {
a=position-1;
-
- }
- else {
- a=0;
- }
- if (position-2>=0) {
- b=position-2;
- }
- else {
- b=0;
- }
+
+ }
+ else {
+ a=0;
+ }
+ if (position-2>=0) {
+ b=position-2;
+ }
+ else {
+ b=0;
+ }
output = (double) ((-1-remainder) * buffer[a] + remainder * buffer[b])/32767;//linear interpolation
}
return(output);
}
double maxiSample::play(double frequency, double start, double end) {
+ return play(frequency, start, end, position);
+}
+
+double maxiSample::play(double frequency, double start, double end, double &pos) {
double remainder;
-// long length=myDataSize;
+ // long length=myDataSize;
+
if (end>=length) end=length-1;
long a,b;
short* buffer = (short *)myData;
if (frequency >0.) {
- if (position<start) {
- position=start;
+ if (pos<start) {
+ pos=start;
}
- if ( position >= end ) position = start;
- position += ((end-start)/(samplerate/(frequency*chandiv)));
- remainder = position - floor(position);
- long pos = floor(position);
- if (pos+1<length) {
- a=pos+1;
-
+ if ( pos >= end ) pos = start;
+ pos += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
+ remainder = pos - floor(pos);
+ long posl = floor(pos);
+ if (posl+1<length) {
+ a=posl+1;
+
}
else {
- a=pos-1;
+ a=posl-1;
}
- if (pos+2<length) {
- b=pos+2;
+ if (posl+2<length) {
+ b=posl+2;
}
else {
b=length-1;
}
-
+
output = (double) ((1-remainder) * buffer[a] +
- remainder * buffer[b])/32767;//linear interpolation
+ remainder * buffer[b])/32767;//linear interpolation
} else {
frequency=frequency-(frequency+frequency);
- if ( position <= start ) position = end;
- position -= ((end-start)/(samplerate/(frequency*chandiv)));
- remainder = position - floor(position);
- long pos = floor(position);
- if (pos-1>=0) {
- a=pos-1;
- }
- else {
- a=0;
- }
- if (pos-2>=0) {
- b=pos-2;
+ if ( pos <= start ) pos = end;
+ pos -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
+ remainder = pos - floor(pos);
+ long posl = floor(pos);
+ if (posl-1>=0) {
+ a=posl-1;
+ }
+ else {
+ a=0;
+ }
+ if (posl-2>=0) {
+ b=posl-2;
}
else {
b=0;
@@ -440,6 +579,7 @@ double maxiSample::play(double frequency, double start, double end) {
return(output);
}
+
//better cubic inerpolation. Cobbled together from various (pd externals, yehar, other places).
double maxiSample::play4(double frequency, double start, double end) {
double remainder;
@@ -450,11 +590,11 @@ double maxiSample::play4(double frequency, double start, double end) {
position=start;
}
if ( position >= end ) position = start;
- position += ((end-start)/(samplerate/(frequency*chandiv)));
+ position += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>0) {
a=buffer[(int)(floor(position))-1];
-
+
} else {
a=buffer[0];
@@ -463,14 +603,14 @@ double maxiSample::play4(double frequency, double start, double end) {
b=buffer[(long) position];
if (position<end-2) {
c=buffer[(long) position+1];
-
+
} else {
c=buffer[0];
-
+
}
if (position<end-3) {
d=buffer[(long) position+2];
-
+
} else {
d=buffer[0];
}
@@ -482,7 +622,7 @@ double maxiSample::play4(double frequency, double start, double end) {
} else {
frequency=frequency-(frequency+frequency);
if ( position <= start ) position = end;
- position -= ((end-start)/(samplerate/(frequency*chandiv)));
+ position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>start && position < end-1) {
a=buffer[(long) position+1];
@@ -530,7 +670,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double speed,long length)
double remainder;
long a,b;
short* buffer = (short *)bufferin;
- position=position+((speed*chandiv*myChannels)/(samplerate/mySampleRate));
+ position=position+((speed*chandiv*myChannels)/(maxiSettings::sampleRate/mySampleRate));
if (speed >=0) {
if ((long) position>=length-1) position=1;
@@ -583,7 +723,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double frequency, double s
}
if ( position >= end ) position = start;
- position += ((end-start)/(samplerate/(frequency*chandiv)));
+ position += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
long pos = floor(position);
if (pos+1<length) {
@@ -605,7 +745,7 @@ double maxiSample::bufferPlay(unsigned char &bufferin,double frequency, double s
} else {
frequency=frequency-(frequency+frequency);
if ( position <= start ) position = end;
- position -= ((end-start)/(samplerate/(frequency*chandiv)));
+ position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
long pos = floor(position);
if (pos-1>=0) {
@@ -638,7 +778,7 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double
position=start;
}
if ( position >= end ) position = start;
- position += ((end-start)/(samplerate/(frequency*chandiv)));
+ position += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>0) {
a=buffer[(int)(floor(position))-1];
@@ -670,7 +810,7 @@ double maxiSample::bufferPlay4(unsigned char &bufferin,double frequency, double
} else {
frequency=frequency-(frequency+frequency);
if ( position <= start ) position = end;
- position -= ((end-start)/(samplerate/(frequency*chandiv)));
+ position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>start && position < end-1) {
a=buffer[(long) position+1];
@@ -710,3 +850,178 @@ void maxiSample::getLength() {
}
+/* OK this compressor and gate are now ready to use. The envelopes, like all the envelopes in this recent update, use stupid algorithms for
+ incrementing - consequently a long attack is something like 0.0001 and a long release is like 0.9999.
+ Annoyingly, a short attack is 0.1, and a short release is 0.99. I'll sort this out laters */
+
+double maxiDyn::gate(double input, double threshold, long holdtime, double attack, double release) {
+
+ if (fabs(input)>threshold && attackphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ if(amplitude==0) amplitude=0.01;
+ }
+
+ if (attackphase==1 && amplitude<1) {
+ amplitude*=(1+attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ attackphase=0;
+ holdphase=1;
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+
+double maxiDyn::compressor(double input, double ratio, double threshold, double attack, double release) {
+
+ if (fabs(input)>threshold && attackphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ if(currentRatio==0) currentRatio=ratio;
+ }
+
+ if (attackphase==1 && currentRatio<ratio-1) {
+ currentRatio*=(1+attack);
+ }
+
+ if (currentRatio>=ratio-1) {
+ attackphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && currentRatio>0.) {
+ currentRatio*=release;
+ }
+
+ if (input>0.) {
+ output = input/(1.+currentRatio);
+ } else {
+ output = input/(1.+currentRatio);
+ }
+
+ return output*(1+log(ratio));
+}
+
+
+/* Lots of people struggle with the envelope generators so here's a new easy one.
+ It takes mental numbers for attack and release tho. Basically, they're exponentials.
+ I'll map them out later so that it's a bit more intuitive */
+double maxiEnv::ar(double input, double attack, double release, long holdtime, int trigger) {
+
+ if (trigger==1 && attackphase!=1 && holdphase!=1){
+ holdcount=0;
+ releasephase=0;
+ attackphase=1;
+ }
+
+ if (attackphase==1) {
+ amplitude+=(1*attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ amplitude=1;
+ attackphase=0;
+ holdphase=1;
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime && trigger==1) {
+ output=input;
+ }
+
+ if (holdcount==holdtime && trigger!=1) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+/* and here's a new adsr. It's not bad, very simple to use*/
+
+double maxiEnv::adsr(double input, double attack, double decay, double sustain, double release, long holdtime, int trigger) {
+
+ if (trigger==1 && attackphase!=1 && holdphase!=1 && decayphase!=1){
+ holdcount=0;
+ decayphase=0;
+ sustainphase=0;
+ releasephase=0;
+ attackphase=1;
+ }
+
+ if (attackphase==1) {
+ amplitude+=(1*attack);
+ output=input*amplitude;
+ }
+
+ if (amplitude>=1) {
+ amplitude=1;
+ attackphase=0;
+ decayphase=1;
+ }
+
+ if (decayphase==1) {
+ output=input*(amplitude*=decay);
+ if (amplitude<=sustain) {
+ decayphase=0;
+ holdphase=1;
+ }
+ }
+
+ if (holdcount<holdtime && holdphase==1) {
+ output=input*amplitude;
+ holdcount++;
+ }
+
+ if (holdcount==holdtime && trigger==1) {
+ output=input*amplitude;
+ }
+
+ if (holdcount==holdtime && trigger!=1) {
+ holdphase=0;
+ releasephase=1;
+ }
+
+ if (releasephase==1 && amplitude>0.) {
+ output=input*(amplitude*=release);
+
+ }
+
+ return output;
+}
+
+double convert::mtof(int midinote) {
+
+ return mtofarray[midinote];
+} \ No newline at end of file
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.h
index 86fcef4..102d552 100755
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.h
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/libs/maximilian.h
@@ -36,17 +36,31 @@
//#define MAXIMILIAN_PORTAUDIO
#define MAXIMILIAN_RT_AUDIO
-#include "ofMain.h"
-#include "ofUtils.h"
+//#include "ofMain.h"
+//#include "ofUtils.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
+#include "math.h"
using namespace std;
-#define TWOPI 3.14159*2
+#define TWOPI (3.14159*2)
+
+class maxiSettings {
+public:
+ static int sampleRate;
+ static int channels;
+ static int bufferSize;
+ static void setup(int initSampleRate, int initChannels, int initBufferSize) {
+ maxiSettings::sampleRate = initSampleRate;
+ maxiSettings::channels = initChannels;
+ maxiSettings::bufferSize = initBufferSize;
+ }
+};
+
class maxiOsc {
@@ -56,7 +70,7 @@ class maxiOsc {
double endphase;
double output;
double tri;
-
+
public:
maxiOsc();
@@ -65,12 +79,13 @@ public:
double phasor(double frequency);
double phasor(double frequency, double startphase, double endphase);
double saw(double frequency);
- double triangle(double frequency,double phase);
+ double triangle(double frequency);
double square(double frequency);
double pulse(double frequency, double duty);
double noise();
double sinebuf(double frequency);
double sinebuf4(double frequency);
+ void phaseReset(double phaseIn);
};
@@ -82,6 +97,7 @@ class maxiEnvelope {
double startval;
double currentval;
double nextval;
+ int isPlaying;
public:
double line(int numberofsegments,double segments[100]);
@@ -101,9 +117,10 @@ class maxiDelayline {
double memory[88200];
public:
+ maxiDelayline();
double dl(double input, int size, double feedback);
double dl(double input, int size, double feedback, int position);
-
+
};
@@ -120,6 +137,7 @@ class maxiFilter {
double z;//pole
double c;//filter coefficient
public:
+ maxiFilter():x(0.0), y(0.0), z(0.0), c(0.0){};
double cutoff;
double resonance;
double lores(double input,double cutoff1, double resonance);
@@ -145,35 +163,36 @@ public:
};
-
class maxiSample {
private:
string myPath;
int myChunkSize;
int mySubChunk1Size;
+ int readChannel;
short myFormat;
int myByteRate;
short myBlockAlign;
short myBitsPerSample;
- int myDataSize;
double position;
double speed;
double output;
public:
+ int myDataSize;
short myChannels;
int mySampleRate;
long length;
void getLength();
-
+
+
char* myData;
// get/set for the Path property
-
+
~maxiSample()
{
- delete myData;
+ if (myData) delete[] myData;
myChunkSize = NULL;
mySubChunk1Size = NULL;
myFormat = NULL;
@@ -185,85 +204,27 @@ public:
myDataSize = NULL;
}
-// maxiSample();
-
- bool load(string fileName);
+ maxiSample():myData(NULL){};
+
+ bool load(string fileName, int channel=0);
void trigger();
// read a wav file into this class
- bool read()
- {
- bool result;
- ifstream inFile( myPath.c_str(), ios::in | ios::binary);
- result = inFile;
-
- if (inFile) {
- //printf("Reading wav file...\n"); // for debugging only
-
- inFile.seekg(4, ios::beg);
- inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize
-
- inFile.seekg(16, ios::beg);
- inFile.read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size
-
- //inFile.seekg(20, ios::beg);
- inFile.read( (char*) &myFormat, sizeof(short) ); // read the file format. This should be 1 for PCM
-
- //inFile.seekg(22, ios::beg);
- inFile.read( (char*) &myChannels, sizeof(short) ); // read the # of channels (1 or 2)
-
- //inFile.seekg(24, ios::beg);
- inFile.read( (char*) &mySampleRate, sizeof(int) ); // read the samplerate
-
- //inFile.seekg(28, ios::beg);
- inFile.read( (char*) &myByteRate, sizeof(int) ); // read the byterate
-
- //inFile.seekg(32, ios::beg);
- inFile.read( (char*) &myBlockAlign, sizeof(short) ); // read the blockalign
-
- //inFile.seekg(34, ios::beg);
- inFile.read( (char*) &myBitsPerSample, sizeof(short) ); // read the bitspersample
-
- //ignore any extra chunks
- char chunkID[4]="";
- int filePos = 36;
- bool found = false;
- while(!found && !inFile.eof()) {
- inFile.seekg(filePos, ios::beg);
- inFile.read((char*) &chunkID, sizeof(char) * 4);
- inFile.seekg(filePos + 4, ios::beg);
- inFile.read( (char*) &myDataSize, sizeof(int) ); // read the size of the data
- filePos += 8;
- if (strcmp(chunkID,"data") == 0) {
- found = true;
- }else{
- filePos += myDataSize;
- }
- }
-
-
-
- // read the data chunk
- myData = (char*) malloc(myDataSize * sizeof(char));
- inFile.seekg(filePos, ios::beg);
- inFile.read(myData, myDataSize);
- length=myDataSize*(0.5/myChannels);
-
- inFile.close(); // close the input file
- }
-
-
- return result; // this should probably be something more descriptive
- }
-
+ bool read();
double play();
+ double playOnce();
+
+ double playOnce(double speed);
+
double play(double speed);
+ double play(double frequency, double start, double end, double &pos);
+
double play(double frequency, double start, double end);
-
+
double play4(double frequency, double start, double end);
double bufferPlay(unsigned char &bufferin,long length);
@@ -349,7 +310,57 @@ public:
val = max(min(val, inMax), inMin);
return pow((outMax / outMin), (val - inMin) / (inMax - inMin)) * outMin;
}
+
+ static double inline explin(double val, double inMin, double inMax, double outMin, double outMax) {
+ //clipping
+ val = max(min(val, inMax), inMin);
+ return (log(val/inMin) / log(inMax/inMin) * (outMax - outMin)) + outMin;
+ }
+
};
+class maxiDyn {
+
+
+public:
+ double gate(double input, double threshold=0.9, long holdtime=1, double attack=1, double release=0.9995);
+ double compressor(double input, double ratio, double threshold=0.9, double attack=1, double release=0.9995);
+ double input;
+ double ratio;
+ double currentRatio;
+ double threshold;
+ double output;
+ double attack;
+ double release;
+ double amplitude;
+ long holdtime;
+ long holdcount;
+ int attackphase,holdphase,releasephase;
+};
+
+class maxiEnv {
+
+
+public:
+ double ar(double input, double attack=1, double release=0.9, long holdtime=1, int trigger=0);
+ double adsr(double input, double attack=1, double decay=0.99, double sustain=0.125, double release=0.9, long holdtime=1, int trigger=0);
+ double input;
+ double output;
+ double attack;
+ double decay;
+ double sustain;
+ double release;
+ double amplitude;
+ int trigger;
+ long holdtime;
+ long holdcount;
+ int attackphase,decayphase,sustainphase,holdphase,releasephase;
+};
+
+class convert {
+public:
+ double mtof(int midinote);
+};
+
#endif
diff --git a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/src/ofxMaxim.h b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/src/ofxMaxim.h
index 317ba34..ec8c539 100644
--- a/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/src/ofxMaxim.h
+++ b/ofxMaxim/ofxMaximiPhoneExample/ofxMaxim/src/ofxMaxim.h
@@ -34,7 +34,9 @@
#define _OFMAXIM_H
#include "maximilian.h"
-//#include "maxiFFT.h"
+#include "maxiFFT.h"
+#include "maxiGrains.h"
+#include "maxiMFCC.h"
typedef maxiMix ofxMaxiMix;
@@ -43,8 +45,11 @@ typedef maxiEnvelope ofxMaxiEnvelope;
typedef maxiDelayline ofxMaxiDelayline;
typedef maxiFilter ofxMaxiFilter;
typedef maxiSample ofxMaxiSample;
-//typedef maxiFFT ofxMaxiFFT;
-//typedef maxiIFFT ofxMaxiIFFT;
-//typedef maxiFFTOctaveAnalyzer ofxMaxiFFTOctaveAnalyzer;
+typedef maxiFFT ofxMaxiFFT;
+typedef maxiIFFT ofxMaxiIFFT;
+typedef maxiFFTOctaveAnalyzer ofxMaxiFFTOctaveAnalyzer;
+typedef maxiSettings ofxMaxiSettings;
+typedef maxiMFCC ofxMaxiMFCC;
+
#endif