Commit 0160af9d authored by Dr-Dan's avatar Dr-Dan

changed js to work with different numbers of channels. mixing example done;...

changed js to work with different numbers of channels. mixing example done; some cheating on c++ maxiMix stuff
parent 2090a747
......@@ -2,4 +2,38 @@
<Bucket
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Maxi_Emscripten/maxi_emscr.cpp"
timestampString = "468433055.819784"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "415"
endingLineNumber = "415"
landmarkName = "maxiMix::stereo(double input,vector&lt;double&gt;&amp; two,double x)"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Maxi_Emscripten/maxi_embind.h"
timestampString = "468536366.681087"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "97"
endingLineNumber = "97"
landmarkName = "EMSCRIPTEN_BINDINGS(my_module)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
......@@ -9,7 +9,8 @@
#ifndef Maxi_Emscripten_maxi_embind_h
#define Maxi_Emscripten_maxi_embind_h
#include <emscripten/bind.h>
#include <emscripten.h>
#include <bind.h>
class vectorTools {
public:
......@@ -37,6 +38,7 @@ EMSCRIPTEN_BINDINGS(my_module) {
;
// MAXI OSC
class_<maxiOsc>("maxiOsc")
.constructor<>()
.function("sinewave", &maxiOsc::sinewave)
......@@ -55,19 +57,24 @@ EMSCRIPTEN_BINDINGS(my_module) {
.function("phaseReset", &maxiOsc::phaseReset)
;
// MAXI ENVELOPE
class_<maxiEnvelope>("maxiEnvelope")
.constructor<>()
.function("line", &maxiEnvelope::line)
// .function("line", &maxiEnvelope::line, allow_raw_pointers()) // if using array version
.function("trigger", &maxiEnvelope::trigger)
.property("amplitude", &maxiEnvelope::GetAmplitude, &maxiEnvelope::SetAmplitude)
;
// class_<maxiDelayline>("maxiDelayline")
// .constructor<>()
// .function("dl", select_overload<double(double, int, double)>(&maxiDelayline::dl))
// .function("dl", select_overload<double(double, int, double, int)>(&maxiDelayline::dl))
// ;
//
// MAXI DELAYLINE
class_<maxiDelayline>("maxiDelayline")
.constructor<>()
.function("dl", select_overload<double(double, int, double)>(&maxiDelayline::dl))
.function("dl", select_overload<double(double, int, double, int)>(&maxiDelayline::dl))
;
// MAXI FILTER
class_<maxiFilter>("maxiFilter")
.constructor<>()
.function("lores", &maxiFilter::lores)
......@@ -77,6 +84,15 @@ EMSCRIPTEN_BINDINGS(my_module) {
.function("hipass", &maxiFilter::hipass)
;
// MAXI MIX
class_<maxiMix>("maxiMix")
.constructor<>()
.function("stereo", &maxiMix::stereo, allow_raw_pointers())
.function("quad", &maxiMix::quad, allow_raw_pointers())
.function("ambisonic", &maxiMix::ambisonic, allow_raw_pointers())
;
// MAXI SAMPLE
class_<maxiSample>("maxiSample")
.constructor<>()
.function("setSample", &maxiSample::setSample)
......@@ -96,5 +112,64 @@ EMSCRIPTEN_BINDINGS(my_module) {
// .function("load", &maxiSample::load)
// .function("read", &maxiSample::read, allow_raw_pointers())
;
}
// MAXI MAP
class_<maxiMap>("maxiMap")
.constructor<>()
.function("linlin", &maxiMap::linlin)
.function("linexp", &maxiMap::linexp)
.function("explin", &maxiMap::explin)
.function("clamp", &maxiMap::clamp)
;
// MAXI DYN
class_<maxiDyn>("maxiDyn")
.constructor<>()
.function("gate", &maxiDyn::gate)
.function("compressor", &maxiDyn::compressor)
;
// MAXI ENV
class_<maxiEnv>("maxiEnv")
.constructor<>()
.function("ar", &maxiEnv::ar)
.function("adsr", &maxiEnv::adsr)
;
// CONVERT
class_<convert>("convert")
.constructor<>()
.function("mtof", &convert::mtof)
;
// MAXI DISTORTION
class_<maxiDistortion>("maxiDistortion")
.constructor<>()
.function("fastAtan", &maxiDistortion::fastatan)
.function("atanDist", &maxiDistortion::atanDist)
.function("fastAtanDist", &maxiDistortion::fastAtanDist)
;
// MAXI FLANGER
class_<maxiFlanger>("maxiFlanger")
.constructor<>()
.function("flange", &maxiFlanger::flange)
;
// MAXI CHORUS
class_<maxiChorus>("maxiChorus")
.constructor<>()
.function("chorus", &maxiChorus::chorus)
;
// MAXI ENVELOPE FOLLOWER
class_<maxiEnvelopeFollower>("maxiEnvelopeFollower")
.constructor<>()
.function("setAttack", &maxiEnvelopeFollower::setAttack)
.function("setRelease", &maxiEnvelopeFollower::setRelease)
.function("play", &maxiEnvelopeFollower::play)
.function("reset", &maxiEnvelopeFollower::reset)
;
};
#endif
......@@ -228,7 +228,7 @@ double maxiOsc::triangle(double frequency) {
// --------------------------------------------------------------------------------
// MAXI ENVELOPE
//double maxiEnvelope::line(int numberofsegments, double segments[]) {
double maxiEnvelope::line(int numberofsegments, std::vector<double>& segments) {
//This is a basic multi-segment ramp generator that you can use for more or less anything.
//However, it's not that intuitive.
......@@ -266,7 +266,6 @@ void maxiEnvelope::trigger(int index, double amp) {
// amplitude=amp;
}
/*
// --------------------------------------------------------------------------------
// MAXI DELAY LINE
......@@ -297,7 +296,7 @@ double maxiDelayline::dl(double input, int size, double feedback, int position)
return(output);
}
*/
// --------------------------------------------------------------------------------
// MAXI FILTER
......@@ -365,11 +364,11 @@ double maxiFilter::bandpass(double input,double cutoff1, double resonance) {
/*
// --------------------------------------------------------------------------------
// MAXI MIX
/*
//stereo bus
double *maxiMix::stereo(double input,double two[2],double x) {
if (x>1) x=1;
......@@ -410,7 +409,51 @@ double *maxiMix::ambisonic(double input,double eight[8],double x,double y,double
eight[7]=input*sqrt((x*(1.0-y))*z);
return(eight);
}
*/
*/
//stereo bus
void maxiMix::stereo(double input,vector<double>& two,double x) {
if (x>1) x=1;
if (x<0) x=0;
// two.clear();
two[0]=input*sqrt(1.0-x);
two[1]=input*sqrt(x);
// return(two);
}
//quad bus
vector<double> maxiMix::quad(double input,vector<double> four, double x,double y) {
if (x>1) x=1;
if (x<0) x=0;
if (y>1) y=1;
if (y<0) y=0;
four[0]=input*sqrt((1.0-x)*y);
four[1]=input*sqrt((1.0-x)*(1.0-y));
four[2]=input*sqrt(x*y);
four[3]=input*sqrt(x*(1.0-y));
return(four);
}
//ambisonic bus
vector<double> maxiMix::ambisonic(double input,vector<double> eight,double x,double y,double z) {
if (x>1) x=1;
if (x<0) x=0;
if (y>1) y=1;
if (y<0) y=0;
if (z>1) y=1;
if (z<0) y=0;
eight[0]=input*(sqrt((1.0-x)*y)*1.0-z);
eight[1]=input*(sqrt((1.0-x)*(1.0-y))*1.0-z);
eight[2]=input*(sqrt(x*y)*1.0-z);
eight[3]=input*(sqrt(x*(1.0-y))*1.0-z);
eight[4]=input*(sqrt((1.0-x)*y)*z);
eight[5]=input*(sqrt((1.0-x)*(1.0-y))*z);
eight[6]=input*sqrt((x*y)*z);
eight[7]=input*sqrt((x*(1.0-y))*z);
return(eight);
}
// --------------------------------------------------------------------------------
// MAXI SAMPLE
......@@ -456,7 +499,7 @@ void maxiSample::trigger() {
position = 0;
}
/*
//This is the main read function.
bool maxiSample::read()
{
......@@ -538,20 +581,20 @@ bool maxiSample::read()
return result; // this should probably be something more descriptive
}
*/
// my version for easier use with js
double maxiSample::play() {
position++;
if ((int) position == length) position=0;
output = (double)(tempDC.at((int)position));
output = (double)(tempVec.at((int)position));
return output;
}
void maxiSample::setSample(vector<double>& temp){
tempDC = temp;
length = tempDC.size();
tempVec = temp;
length = tempVec.size();
}
......@@ -572,7 +615,7 @@ double maxiSample::playOnce(double speed) {
position=position+((speed*chandiv)/(maxiSettings::sampleRate/mySampleRate));
double remainder = position - (long) position;
if ((long) position<length)
output = (double) ((1-remainder) * tempDC.at(1+ (long) position) + remainder * tempDC.at(2+(long) position));//linear interpolation
output = (double) ((1-remainder) * tempVec.at(1+ (long) position) + remainder * tempVec.at(2+(long) position));//linear interpolation
else
output=0;
return(output);
......@@ -602,7 +645,7 @@ double maxiSample::play(double speed) {
b=length-1;
}
output = (double) ((1-remainder) * tempDC.at(a) + remainder * tempDC.at(b));//linear interpolation
output = (double) ((1-remainder) * tempVec.at(a) + remainder * tempVec.at(b));//linear interpolation
} else {
if ((long) position<0) position=length;
remainder = position - floor(position);
......@@ -619,7 +662,7 @@ double maxiSample::play(double speed) {
else {
b=0;
}
output = (double) ((-1-remainder) * tempDC.at(a) + remainder * tempDC.at(b));//linear interpolation
output = (double) ((-1-remainder) * tempVec.at(a) + remainder * tempVec.at(b));//linear interpolation
}
return(output);
}
......@@ -659,8 +702,8 @@ double maxiSample::play(double frequency, double start, double end, double& pos)
b=length-1;
}
output = (double) ((1-remainder) * tempDC.at(a) +
remainder * tempDC.at(b));//linear interpolation
output = (double) ((1-remainder) * tempVec.at(a) +
remainder * tempVec.at(b));//linear interpolation
} else {
frequency=frequency-(frequency+frequency);
if ( pos <= start ) pos = end;
......@@ -679,8 +722,8 @@ double maxiSample::play(double frequency, double start, double end, double& pos)
else {
b=0;
}
output = (double) ((-1-remainder) * tempDC.at(a) +
remainder * tempDC.at(b));//linear interpolation
output = (double) ((-1-remainder) * tempVec.at(a) +
remainder * tempVec.at(b));//linear interpolation
}
......@@ -703,26 +746,26 @@ double maxiSample::play4(double frequency, double start, double end) {
position += ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>0) {
a=tempDC.at((long)(floor(position))-1);
a=tempVec.at((long)(floor(position))-1);
} else {
a=tempDC.at(0);
a=tempVec.at(0);
}
b=tempDC.at((long) position);
b=tempVec.at((long) position);
if (position<end-2) {
c=tempDC.at((long) position+1);
c=tempVec.at((long) position+1);
} else {
c=tempDC.at(0);
c=tempVec.at(0);
}
if (position<end-3) {
d=tempDC.at((long) position+2);
d=tempVec.at((long) position+2);
} else {
d=tempDC.at(0);
d=tempVec.at(0);
}
a1 = 0.5f * (c - a);
......@@ -736,26 +779,26 @@ double maxiSample::play4(double frequency, double start, double end) {
position -= ((end-start)/(maxiSettings::sampleRate/(frequency*chandiv)));
remainder = position - floor(position);
if (position>start && position < end-1) {
a=tempDC.at((long) position+1);
a=tempVec.at((long) position+1);
} else {
a=tempDC.at(0);
a=tempVec.at(0);
}
b=tempDC.at((long) position);
b=tempVec.at((long) position);
if (position>start) {
c=tempDC.at((long) position-1);
c=tempVec.at((long) position-1);
} else {
c=tempDC.at(0);
c=tempVec.at(0);
}
if (position>start+1) {
d=tempDC.at((long) position-2);
d=tempVec.at((long) position-2);
} else {
d=tempDC.at(0);
d=tempVec.at(0);
}
a1 = 0.5f * (c - a);
a2 = a - 2.5 * b + 2.f * c - 0.5f * d;
......@@ -992,7 +1035,7 @@ void maxiSample::reset() {
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){
......@@ -1061,13 +1104,13 @@ double maxiDyn::compressor(double input, double ratio, double threshold, double
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){
......@@ -1175,4 +1218,3 @@ void maxiEnvelopeFollower::setAttack(double attackMS) {
void maxiEnvelopeFollower::setRelease(double releaseMS) {
release = pow( 0.01, 1.0 / ( releaseMS * maxiSettings::sampleRate * 0.001 ) );
}
*/
......@@ -126,7 +126,7 @@ public:
};
/*
class maxiDelayline {
double frequency;
int phase;
......@@ -139,10 +139,8 @@ public:
maxiDelayline();
double dl(double input, int size, double feedback);
double dl(double input, int size, double feedback, int position);
};
*/
// NEXT
class maxiFilter {
......@@ -169,22 +167,35 @@ public:
};
/*
// most variables in this class seem to have no use ??
// all recieved as args ...
class maxiMix {
double input;
double two[2];
double four[4];
double eight[8];
// double input;
// double two[2];
// double four[4];
// double eight[8];
// vector<double> two;
// vector<double> four[4];
// vector<double> eight[8];
public:
double x;
double y;
double z;
double *stereo(double input,double two[2],double x);
double *quad(double input,double four[4], double x,double y);
double *ambisonic(double input,double eight[8],double x,double y, double z);
// double x;
// double y;
// double z;
/*
currently using non-pointer version for embind, need to sort out pointer stuff though
embind has no support for pointers to primitives!
*/
// double *stereo(double input,double two[2],double x);
// double *quad(double input,double four[4], double x,double y);
// double *ambisonic(double input,double eight[8],double x,double y, double z);
void stereo(double input,vector<double>& two,double x);
vector<double> quad(double input,vector<double> four, double x,double y);
vector<double> ambisonic(double input,vector<double> eight, double x,double y, double z);
};
/*
//lagging with an exponential moving average
//a lower alpha value gives a slower lag
template <class T>
......@@ -250,8 +261,7 @@ public:
short* temp;
// different vars for use with js
vector<double> tempDC;
// get/set for the Path property
vector<double> tempVec;
~maxiSample()
{
......@@ -300,7 +310,7 @@ public:
void setSample(vector<double>& temp);
double play();
void clear(){tempDC.clear();}
void clear(){tempVec.clear();}
// double playOnce();
//
......@@ -310,9 +320,7 @@ public:
double play(double frequency, double start, double end);
// previously:
// double play(double frequency, double start, double end, double &pos);
// why this no work with bind? :
// why this no work with embind? :
// non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'
double play(double frequency, double start, double end, double& pos);
//
......@@ -372,7 +380,7 @@ public:
}
};
/*
class maxiMap {
public:
......@@ -420,6 +428,7 @@ public:
int attackphase,holdphase,releasephase;
};
class maxiEnv {
......@@ -455,11 +464,6 @@ public:
double fastatan( double x );
};
inline double maxiDistortion::fastatan(double x)
{
return (x / (1.0 + 0.28 * (x * x)));
}
inline double maxiDistortion::atanDist(const double in, const double shape) {
double out;
out = (1.0 / atan(shape)) * atan(in * shape);
......@@ -472,6 +476,11 @@ inline double maxiDistortion::fastAtanDist(const double in, const double shape)
return out;
}
inline double maxiDistortion::fastatan(double x)
{
return (x / (1.0 + 0.28 * (x * x)));
}
class maxiFlanger {
public:
......@@ -485,6 +494,7 @@ public:
};
inline double maxiFlanger::flange(const double input, const unsigned int delay, const double feedback, const double speed, const double depth)
{
//todo: needs fixing
......@@ -496,6 +506,7 @@ inline double maxiFlanger::flange(const double input, const unsigned int delay,
return (output + input) / 2.0;
}
class maxiChorus {
public:
//delay = delay time - ~800 sounds good
......@@ -522,6 +533,7 @@ inline double maxiChorus::chorus(const double input, const unsigned int delay, c
return (output1 + output2 + input) / 3.0;
}
class maxiEnvelopeFollower {
public:
maxiEnvelopeFollower() {
......@@ -544,6 +556,4 @@ private:
double attack, release, env;
};
*/
#endif
This diff is collapsed.
// Temporary patch until all browsers support unprefixed context.
AudioContext = AudioContext || webkitAudioContext;
var context;
// var context;
var context = new AudioContext();
// context = new (window.AudioContext || window.webkitAudioContext)();
var source;
var jsProcessor = 0;
var analyser;
......@@ -12,51 +16,83 @@ var bufferLoader;
var myBufferData = new Module.VectorDouble();//this data will be used to make an envelope. Value and time to value in ms.
var sampleIsLoaded = false;
// var vectorTools = new Module.vectorTools();
// init() once the page has finished loading.
window.onload = init;
// this probably isn't required if all is done correctly
// but it is making things work
// actually it is tres slow
// function roundToNPlaces(numIn, numPlaces){
// var m = Math.pow(10, numPlaces);
// return Math.round(numIn * m) / m;
// }
function setup(){
console.log("non-overrided setup happening");
console.log("non-overrided setup");
// setNumOutputChannels(3);
}
// this will be overriden in the users script
function play(){
output = 0;
// output = 0;
// console.log("non-overrided play happening");
}
function process(event) {
// Get left/right output arrays
// use to set num channels and set output as an array
// not currently working!
function setNumOutputChannels(numChannelsOut_){
var outputArrayL = event.outputBuffer.getChannelData(0);
var outputArrayR = event.outputBuffer.getChannelData(1);
var n = outputArrayL.length;
if(numChannelsOut_ > 1){
OutputIsArray(true, numChannelsOut_);
} else {
OutputIsArray(false, numChannelsOut_);
}
for (var i = 0; i < n; ++i) {
source.disconnect();
jsProcessor.disconnect();
analyser.disconnect();
play();
initAudio(numChannelsOut_);
}
outputArrayL[i] = output;
outputArrayR[i] = output;
function OutputIsArray(isArray, numChannelsOut_){
if(isArray){
output = new Array(numChannelsOut_);
for(var i = 0; i < numChannelsOut_; i++){
output[i] = 0;
}
} else {
output = 0;
}
}
var outputErrorLogged = false;
// function handling audio processing
// called byjsProcessor
function process(event) {
var numChannels = event.outputBuffer.numberOfChannels;
var outputLength = event.outputBuffer.getChannelData(0).length;
console.log(numChannels);
for (var i = 0; i < outputLength; ++i) {
play();
function initAudio() {
context = new AudioContext();
if(output instanceof Array){
for (var channel = 0; channel < numChannels; channel++) {