diff --git a/content/docs/webmodular/index.html b/content/docs/webmodular/index.html
new file mode 100644
index 0000000..36206a5
--- /dev/null
+++ b/content/docs/webmodular/index.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+WebModular
+
+
+
+
+
+
+
+
+
+
+
+1 | 2 C#3 | 3 D#3 | 4 | 5 F#3 | 6 G#3 | 7 A#3 | 8 | 9 C#4 | 0 D#4 |
+
+Q C3 | W D3 | E E3 | R F3 | T G3 | Y A3 | U B3 | I C4 | O D4 | P E4 |
+
+ | A | S C#2 | D D#2 | F | G F#2 | H G#2 | J A#2 | K | L C#3 | ; D#3 |
+
+ | Z C2 | X D2 | C E2 | V F2 | B G2 | N A2 | M B2 | , C3 | . D3 | / |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/docs/webmodular/keypress.png b/content/docs/webmodular/keypress.png
new file mode 100644
index 0000000..4d5eeb6
Binary files /dev/null and b/content/docs/webmodular/keypress.png differ
diff --git a/content/docs/webmodular/knob.png b/content/docs/webmodular/knob.png
new file mode 100644
index 0000000..f74af19
Binary files /dev/null and b/content/docs/webmodular/knob.png differ
diff --git a/content/docs/webmodular/knob2.png b/content/docs/webmodular/knob2.png
new file mode 100644
index 0000000..b36da99
Binary files /dev/null and b/content/docs/webmodular/knob2.png differ
diff --git a/content/docs/webmodular/knob3.png b/content/docs/webmodular/knob3.png
new file mode 100644
index 0000000..8eb6470
Binary files /dev/null and b/content/docs/webmodular/knob3.png differ
diff --git a/content/docs/webmodular/panel.png b/content/docs/webmodular/panel.png
new file mode 100644
index 0000000..46792fb
Binary files /dev/null and b/content/docs/webmodular/panel.png differ
diff --git a/content/docs/webmodular/play.png b/content/docs/webmodular/play.png
new file mode 100644
index 0000000..55d19c4
Binary files /dev/null and b/content/docs/webmodular/play.png differ
diff --git a/content/docs/webmodular/sliderpos.png b/content/docs/webmodular/sliderpos.png
new file mode 100644
index 0000000..30f7224
Binary files /dev/null and b/content/docs/webmodular/sliderpos.png differ
diff --git a/content/docs/webmodular/stop.png b/content/docs/webmodular/stop.png
new file mode 100644
index 0000000..270e6b5
Binary files /dev/null and b/content/docs/webmodular/stop.png differ
diff --git a/content/docs/webmodular/sw2.png b/content/docs/webmodular/sw2.png
new file mode 100644
index 0000000..7286dfa
Binary files /dev/null and b/content/docs/webmodular/sw2.png differ
diff --git a/content/docs/webmodular/sw3.png b/content/docs/webmodular/sw3.png
new file mode 100644
index 0000000..1fb9c06
Binary files /dev/null and b/content/docs/webmodular/sw3.png differ
diff --git a/content/docs/webmodular/sw5.png b/content/docs/webmodular/sw5.png
new file mode 100644
index 0000000..7c56da2
Binary files /dev/null and b/content/docs/webmodular/sw5.png differ
diff --git a/content/docs/webmodular/twitter-bird-light-bgs.png b/content/docs/webmodular/twitter-bird-light-bgs.png
new file mode 100644
index 0000000..188597e
Binary files /dev/null and b/content/docs/webmodular/twitter-bird-light-bgs.png differ
diff --git a/static/waapisim.js b/static/waapisim.js
new file mode 100644
index 0000000..acb3899
--- /dev/null
+++ b/static/waapisim.js
@@ -0,0 +1,1786 @@
+// Web Audio API Simulator
+// Copyright (c) 2013 g200kg
+// http://www.g200kg.com/
+// Released under the MIT-License
+// http://opensource.org/licenses/MIT
+//
+// Great thanks :
+// FFT algo for AnalyserNode and Convolver is based on Takuya OOURA's explanation.
+// http://www.kurims.kyoto-u.ac.jp/~ooura/fftman/index.html
+
+if(typeof(waapisimLogEnable)==="undefined")
+ var waapisimLogEnable=0;
+
+// Support Float32Array&Uint8Array if unavailable (for IE9)
+if(typeof(Float32Array)==="undefined") {
+ Float32Array=function(n) {
+ if(n instanceof Array)
+ return n;
+ var a=new Array(n);
+ a.subarray=function(x,y) {return this.slice(x,y);};
+ a.set=function(x,off) {for(var i=0;i=32768) v0=v0-65536;
+ if(v1>=32768) v1=v1-65536;
+ if(mixtomono===true)
+ v0=v1=(v0+v1)*0.5;
+ this.buf[0][i]=v0/32768;
+ this.buf[1][i]=v1/32768;
+ j+=6;
+ }
+ else {
+ v=inbuf[idx+j+9]+(inbuf[idx+j+10]<<8);
+ if(v>=32768) v=v-65536;
+ this.buf[0][i]=this.buf[1][i]=v/32768;
+ j+=3;
+ }
+ }
+ else if(wavbits==16) {
+ if(wavch==2) {
+ v0=inbuf[idx+j+8]+(inbuf[idx+j+9]<<8);
+ v1=inbuf[idx+j+10]+(inbuf[idx+j+11]<<8);
+ if(v0>=32768) v0=v0-65536;
+ if(v1>=32768) v1=v1-65536;
+ if(mixtomono===true)
+ v0=v1=(v0+v1)*0.5;
+ this.buf[0][i]=v0/32768;
+ this.buf[1][i]=v1/32768;
+ j+=4;
+ }
+ else {
+ v=inbuf[idx+j+8]+(inbuf[idx+j+9]<<8);
+ if(v>=32768) v=v-65536;
+ this.buf[0][i]=this.buf[1][i]=v/32768;
+ j+=2;
+ }
+ }
+ else {
+ if(wavch==2) {
+ v0=inbuf[idx+j+8]/128-1;
+ v1=inbuf[idx+j+9]/128-1;
+ if(mixtomono===true)
+ v0=v1=(v0+v1)*0.5;
+ this.buf[0][i]=v0;
+ this.buf[1][i]=v1;
+ j+=2;
+ }
+ else {
+ this.buf[0][i]=this.buf[1][i]=inbuf[idx+j+8]/128-1;
+ j++;
+ }
+ }
+ }
+ }
+ idx+=(chunksz+8);
+ }
+ }
+ }
+ }
+ this.getChannelData=function(i) {
+ return this.buf[i];
+ };
+ };
+ waapisimDummybuf=new waapisimAudioBuffer(2,waapisimBufSize,waapisimSampleRate);
+ waapisimSetupOutBuf=function(offset) {
+ var numctx=waapisimContexts.length;
+ var l,i,j,k,n,node;
+ for(l=(offset+waapisimBufSize)*2,i=offset*2;i0) {
+ var buf=node._nodein[0].inbuf.buf;
+ for(i=0;i0) {
+ for(var i in scr) {
+ if(scr[i].src && scr[i].src.match(/waapisim\.js$/)) {
+ var s=scr[i].src;
+ return s.substring(0,s.length-2)+"swf";
+ }
+ }
+ }
+ return "";
+ };
+ waapisimAddFlashObj=function() {
+ var div=document.createElement("DIV");
+ div.setAttribute("id","WAAPISIMFLASHOBJ");
+ div.setAttribute("style","background:#ff00ff;position:static;");
+ var body=document.getElementsByTagName("BODY");
+ body[0].appendChild(div);
+ document.getElementById("WAAPISIMFLASHOBJ").innerHTML="";
+ if(typeof(document.getElementById("waapisim_swf").SetReturnValue)==="undefined")
+ document.getElementById("waapisim_swf").SetReturnValue=function(v){document.getElementById("waapisim_swf").impl.SetReturnValue(v);};
+ };
+ waapisimFlashOffset=function(pos) {
+ waapisimUpdateCurrentTime(pos/1000);
+ };
+ waapisimFlashGetData=function() {
+ var s="";
+ var l;
+ for(l=waapisimOutBufSize/waapisimBufSize,i=0;i0)
+ successCallback(buf);
+ else
+ errorCallback();
+ };
+ this.createPeriodicWave=this.createWaveTable=function(real,imag) {
+ return new waapisimPeriodicWave(real,imag);
+ };
+ this._SortNode=function() {
+ var i,j,k,n;
+ for(i=0;i0) {
+ for(j=0;j>1;k>(i^=k);k>>=1)
+ ;
+ } while(++jmax)
+ max=v;
+ }
+ if(max==0) {
+ for(i=0;i"+next.node._nodetype+next.node._nodeId);
+ if(next===undefined)
+ return;
+ if(next.from.indexOf(this)!=-1)
+ return;
+ next.from.push(this);
+ if(this.to.indexOf(next)==-1)
+ this.to.push(next);
+ if(next.node._targettype!==0) {
+ if(this.node.context._RegisterNode(next.node)) {
+ for(var i=0;i=0) {
+ waapisimDebug(" :"+this.node._nodeId+"=>"+nodes[i]._nodeId);
+ nodes[i]._nodein[ii].from.splice(j,1);
+ }
+ }
+ }
+ for(i=0;i0)
+ this._bufferindex=off*waapisimSampleRate;
+ this._endindex=this.buffer.length;
+ if(dur>0)
+ this._endindex=Math.min(this.buffer.length,(dur+off)*waapisimSampleRate);
+ if(this.loop) {
+ if((this.loopStart||this.loopEnd)&&this.loopStart>=0&&this.loopEnd>0&&this.loopStart=this._endindex) {
+ if(this.playbackState==2)
+ --this.context.activeSourceCount;
+ this.playbackState=3;
+ }
+ if(this.playbackState==1 && this.context.currentTime>=this._whenstart) {
+ this.playbackState=2;
+ ++this.context.activeSourceCount;
+ }
+ if(this.playbackState==2 && this.context.currentTime>=this._whenstop) {
+ this.playbackState=3;
+ --this.context.activeSourceCount;
+ }
+ if(this.playbackState!=2)
+ return;
+ var b0=this.buffer.getChannelData(0);
+ var b1=this.buffer.getChannelData(1);
+ var rate=this.buffer.sampleRate/44100;
+ if(this._nodeout[0].to.length>0) {
+ for(var i=0;i=this._actualLoopEnd)
+ this._bufferindex=this._actualLoopStart;
+ }
+ }
+ this._nodeout[0].NodeEmitBuf();
+ this.playbackRate.Clear(true);
+ }
+ };
+ };
+ waapisimAudioBufferSource.UNSCHEDULED_STATE=waapisimAudioBufferSource.prototype.UNSCHEDULED_STATE=0;
+ waapisimAudioBufferSource.SCHEDULED_STATE=waapisimAudioBufferSource.prototype.SCHEDULED_STATE=1;
+ waapisimAudioBufferSource.PLAYING_STATE=waapisimAudioBufferSource.prototype.PLAYING_STATE=2;
+ waapisimAudioBufferSource.FINISHED_STATE=waapisimAudioBufferSource.prototype.FINISHED_STATE=3;
+
+ waapisimScriptProcessor=function(ctx,bufsize,inch,outch) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="ScrProc";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this._targettype=2;
+ this.context=ctx;
+ this.playbackState=0;
+ if(typeof(bufsize)!=="number")
+ throw(new TypeError("ScriptProcessor:bufferSize"));
+ if(typeof(inch)==="undefined")
+ inch=2;
+ if(typeof(outch)==="undefined")
+ outch=2;
+ this.bufferSize=bufsize;
+ this._scrinbuf=new waapisimAudioBuffer(inch,bufsize,waapisimSampleRate);
+ this._scroutbuf=new waapisimAudioBuffer(outch,bufsize,waapisimSampleRate);
+ this._index=bufsize;
+ this.onaudioprocess=null;
+ this._Process=function() {
+ var inb=this._nodein[0].inbuf;
+ if(inb===null)
+ inb=waapisimDummybuf;
+ for(var i=0;i=this.bufferSize) {
+ if(this.onaudioprocess) {
+ var ev=new waapisimAudioProcessingEvent();
+ ev.node=this;
+ ev.inputBuffer=this._scrinbuf;
+ ev.outputBuffer=this._scroutbuf;
+ this.onaudioprocess(ev);
+ }
+ this._index=0;
+ }
+ this._scrinbuf.buf[0][this._index]=inb.buf[0][i];
+ if(this._scrinbuf.numberOfChannels>=2)
+ this._scrinbuf.buf[1][this._index]=inb.buf[1][i];
+ if(this._scroutbuf.numberOfChannels>=2)
+ this._nodeout[0].NodeEmit(i,this._scroutbuf.buf[0][this._index],this._scroutbuf.buf[1][this._index]);
+ else
+ this._nodeout[0].NodeEmit(i,this._scroutbuf.buf[0][this._index],this._scroutbuf.buf[0][this._index]);
+ this._index++;
+ }
+ this._nodein[0].NodeClear();
+ };
+ ctx._RegisterNode(this);
+ };
+ waapisimBiquadFilter=webkitBiquadFilterNode=BiquadFilterNode=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="Filter";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this.context=ctx;
+ this.playbackState=0;
+ this.type=0;
+ this.frequency=new waapisimAudioParam(ctx,this,10,24000,350,0.5);
+ this.detune=new waapisimAudioParam(ctx,this,-4800,4800,0,0.5);
+ this.Q=new waapisimAudioParam(ctx,this,0.0001,1000,1,0.5);
+ this.gain=new waapisimAudioParam(ctx,this,-40,40,0,0.5);
+ this._a1=this._a2=0;
+ this._b0=this._b1=this._b2=0;
+ this._x1l=this._x1r=this._x2l=this._x2r=0;
+ this._y1l=this._y1r=this._y2l=this._y2r=0;
+ this._nodein[0].NodeClear();
+ this._Setup=function(fil) {
+ var f=fil.frequency.Get(0)*Math.pow(2,fil.detune.Get(0)/1200);
+ var q=Math.max(0.001,fil.Q.Get(0));
+ var alpha,ra0,g;
+ var w0=2*Math.PI*f/fil.context.sampleRate;
+ var cos=Math.cos(w0);
+ switch(fil.type) {
+ case "lowpass":
+ case 0:
+ q=Math.pow(10,q/20);
+ alpha=Math.sin(w0)/(2*q);
+ ra0=1/(1+alpha);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha)*ra0;
+ fil._b0=fil._b2=(1-cos)/2*ra0;
+ fil._b1=(1-cos)*ra0;
+ break;
+ case "highpass":
+ case 1:
+ q=Math.pow(10,q/20);
+ alpha=Math.sin(w0)/(2*q);
+ ra0=1/(1+alpha);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha)*ra0;
+ fil._b0=fil._b2=(1+cos)/2*ra0;
+ fil._b1=-(1+cos)*ra0;
+ break;
+ case "bandpass":
+ case 2:
+ alpha=Math.sin(w0)/(2*q);
+ ra0=1/(1+alpha);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha)*ra0;
+ fil._b0=alpha;
+ fil._b1=0;
+ fil._b2=-alpha;
+ break;
+ case "lowshelf":
+ case 3:
+ alpha=Math.sin(w0)/2*Math.sqrt(2);
+ g=Math.pow(10,fil.gain.Get(0)/40);
+ ra0=1/((g+1)+(g-1)*cos+2*Math.sqrt(g)*alpha);
+ fil._a1=-2*((g-1)+(g+1)*cos)*ra0;
+ fil._a2=((g+1)+(g-1)*cos-2*Math.sqrt(g)*alpha)*ra0;
+ fil._b0=g*((g+1)-(g-1)*cos+2*Math.sqrt(g)*alpha)*ra0;
+ fil._b1=2*g*((g-1)-(g+1)*cos)*ra0;
+ fil._b2=g*((g+1)-(g-1)*cos-2*Math.sqrt(g)*alpha)*ra0;
+ break;
+ case "highshelf":
+ case 4:
+ alpha=Math.sin(w0)/2*Math.sqrt(2);
+ g=Math.pow(10,fil.gain.Get(0)/40);
+ ra0=1/((g+1)-(g-1)*cos+2*Math.sqrt(g)*alpha);
+ fil._a1=2*((g-1)-(g+1)*cos)*ra0;
+ fil._a2=((g+1)-(g-1)*cos-2*Math.sqrt(g)*alpha)*ra0;
+ fil._b0=g*((g+1)+(g-1)*cos+2*Math.sqrt(g)*alpha)*ra0;
+ fil._b1=-2*g*((g-1)+(g+1)*cos)*ra0;
+ fil._b2=g*((g+1)+(g-1)*cos-2*Math.sqrt(g)*alpha)*ra0;
+ break;
+ case "peaking":
+ case 5:
+ alpha=Math.sin(w0)/(2*q);
+ g=Math.pow(10,fil.gain.Get(0)/40);
+ ra0=1/(1+alpha/g);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha/g)*ra0;
+ fil._b0=(1+alpha*g)*ra0;
+ fil._b1=-2*cos*ra0;
+ fil._b2=(1-alpha*g)*ra0;
+ break;
+ case "notch":
+ case 6:
+ alpha=Math.sin(w0)/(2*q);
+ ra0=1/(1+alpha);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha)*ra0;
+ fil._b0=fil._b2=ra0;
+ fil._b1=-2*cos*ra0;
+ break;
+ case "allpass":
+ case 7:
+ alpha=Math.sin(w0)/(2*q);
+ ra0=1/(1+alpha);
+ fil._a1=-2*cos*ra0;
+ fil._a2=(1-alpha)*ra0;
+ fil._b0=(1-alpha)*ra0;
+ fil._b1=-2*cos*ra0;
+ fil._b2=(1+alpha)*ra0;
+ break;
+ }
+ };
+ this._Process=function() {
+ var xl,xr,yl,yr;
+ this.frequency._Process();
+ this.detune._Process();
+ this.Q._Process();
+ this.gain._Process();
+ this._Setup(this);
+ var inbuf=this._nodein[0].inbuf.buf;
+ var outbuf=this._nodeout[0].outbuf.buf;
+ for(var i=0;i=this.context.sampleRate)
+ offs=this.context.sampleRate-1;
+ var deltaoff=(offs-this._offscur)/waapisimBufSize;
+ for(var i=0;i=waapisimSampleRate)
+ this._index=0;
+ this._offscur+=deltaoff;
+ }
+ this._nodeout[0].NodeEmitBuf();
+ this._nodein[0].NodeClear();
+ this.delayTime.Clear(false);
+ };
+ };
+ waapisimOscillator=webkitOscillatorNode=OscillatorNode=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,0,1);
+ this._nodetype="Osc";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this._targettype=3;
+ this._order=0;
+ this.context=ctx;
+ this.type=0;
+ this._wavtable=null;
+ this.frequency=new waapisimAudioParam(ctx,this,1,20000,440,0.9995);
+ this.detune=new waapisimAudioParam(ctx,this,-4800,4800,0,0.9995);
+ this.playbackState=0;
+ this._phase=0.5;
+ this._whenstart=0;
+ this._whenstop=Number.MAX_VALUE;
+ this._init=0;
+ this.start=this.noteOn=function(w) {
+ this._whenstart=w;
+ this.playbackState=1;
+ this.context._RegisterNode(this);
+ };
+ this.stop=this.noteOff=function(w) {
+ this._whenstop=w;
+ };
+ this.setPeriodicWave=this.setWaveTable=function(tab) {
+ this.type=4;
+ this._wavtable=tab;
+ };
+ this._Process=function() {
+ var i;
+ if(this._init==0) {
+ this.frequency.Init();
+ this.detune.Init();
+ this._init=1;
+ }
+ this.frequency._Process();
+ this.detune._Process();
+ if(this.playbackState==1 && this.context.currentTime>=this._whenstart)
+ this.playbackState=2;
+ if(this.playbackState==2 && this.context.currentTime>=this._whenstop)
+ this.playbackState=3;
+ if(this.playbackState!=2) {
+ for(i=0;i1) out=1;
+ if(out<-1) out=-1;
+ obuf[0][i]=obuf[1][i]=out;
+ }
+ this._phase=ph;
+ this._nodeout[0].NodeEmitBuf();
+ this.frequency.Clear(true);
+ this.detune.Clear(true);
+ };
+ };
+ waapisimOscillator.SINE=waapisimOscillator.prototype.SINE=0;
+ waapisimOscillator.SQUARE=waapisimOscillator.prototype.SQUARE=1;
+ waapisimOscillator.SAWTOOTH=waapisimOscillator.prototype.SAWTOOTH=2;
+ waapisimOscillator.TRIANGLE=waapisimOscillator.prototype.TRIANGLE=3;
+ waapisimOscillator.CUSTOM=waapisimOscillator.prototype.CUSTOM=4;
+ waapisimOscillator.UNSCHEDULED_STATE=waapisimOscillator.prototype.UNSCHEDULED_STATE=0;
+ waapisimOscillator.SCHEDULED_STATE=waapisimOscillator.prototype.SCHEDULED_STATE=1;
+ waapisimOscillator.PLAYING_STATE=waapisimOscillator.prototype.PLAYING_STATE=2;
+ waapisimOscillator.FINISHED_STATE=waapisimOscillator.prototype.FINISHED_STATE=3;
+
+ waapisimAnalyser=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="Analyser";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this.context=ctx;
+ this.playbackState=0;
+ this.fftSize=2048;
+ this.frequencyBinCount=1024;
+ this.minDecibels=-100;
+ this.maxDecibels=-30;
+ this.smoothingTimeConstant=0;
+ this._fftInData=new Array(2048);
+ this._fftOutData=new Array(2048);
+ this._timeData=new Array(2048);
+ this._fftIndex=0;
+ this._fftCurrentSize=0;
+ this._fftrev=new Array(256);
+ this._fft=function(n,data,mag) {
+ var nh=n>>1;
+ var t=-2*Math.PI;
+ var m,mh,mq,i,j,jr,ji,kr,ki,xr,xi;
+ for(mh=1;(m=mh<<1)<=n;mh=m) {
+ mq=mh>>1;
+ t*=0.5;
+ for(jr=0;jr>1;k>(i^=k);k>>=1)
+ ;
+ this._fftrev[j]=i;
+ }
+ }
+ for(i=0;i=this._fftCurrentSize) {
+ this._fftIndex=0;
+ this._fft(this._fftCurrentSize,this._fftInData,this._fftOutData);
+ }
+ }
+ this._nodein[0].NodeClear();
+ };
+ };
+ waapisimConvolver=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="Convolver";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this.context=ctx;
+ this.playbackState=0;
+ this.buffer=null;
+ this.normalize=true;
+ this._scale=1;
+ this._analyzed=null;
+ this._dlybufsize=waapisimSampleRate*5;
+ this._dlybuf=new waapisimAudioBuffer(2,this._dlybufsize,44100);
+ this._dlyidx=0;
+ this._tapsize=20;
+ this._tap=[];
+ this._kernel=null;
+ this._sum=[];
+ this._sum[0]=[];
+ this._sum[1]=[];
+ this._bitrev=[];
+ this._bitrev[0]=0;
+ this._bitrev[waapisimBufSize-1]=waapisimBufSize-1;
+ var i,j,k;
+ for(i=0,j=1;j>1;k>(i^=k);k>>=1)
+ ;
+ this._bitrev[j]=i;
+ }
+ for(i=0;i<2;++i)
+ for(j=0;j<2;++j)
+ this._sum[i][j]=new Float32Array(waapisimSampleRate);
+ this._Normalize=function(buffer) {
+ var GainCalibration=0.00125;
+ var GainCalibrationSampleRate=44100;
+ var MinPower=0.000125;
+ var numberOfChannels=2;
+ var length=buffer.length;
+ var power=0;
+ for(var i=0;i>1;k>(i^=k);k>>=1)
+ ;
+ if(j>1;
+ theta*=0.5;
+ for(jr=0;jr>1;k>(i^=k);k>>=1)
+ ;
+ if(j1e-3)
+ break;
+ if(Math.abs(this.buffer.buf[1][i])>1e-3)
+ break;
+ }
+ len=i+1;
+ for(i=0,px=0;i0) {
+ while(px=waapisimBufSize) {
+ if(p>maxp) {
+ this._kernel=kbuf[k];
+ maxp=p;
+ }
+ j=0;
+ p=0;
+ ++k;
+ }
+ }
+ if(p>maxp||this._kernel===null)
+ this._kernel=kbuf[k];
+ this._Fft(waapisimBufSize,this._kernel.buf[0]);
+ this._Fft(waapisimBufSize,this._kernel.buf[1]);
+ this._analyzed=this.buffer;
+ }
+ this._Fft(waapisimBufSize,inbuf[0]);
+ this._Fft(waapisimBufSize,inbuf[1]);
+ this._sum[0][0][0]=this._sum[1][0][0]=this._sum[0][1][0]=this._sum[1][1][0]=0;
+ for(i=1,j=waapisimBufSize-1;i=this._dlybufsize)
+ this._dlyidx=0;
+ }
+ }
+ this._nodein[0].NodeClear();
+ };
+ };
+ waapisimDynamicsCompressor=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="DynComp";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this.context=ctx;
+ this.playbackState=0;
+ this.threshold=new waapisimAudioParam(ctx,this,-100,0,-24);
+ this.knee=new waapisimAudioParam(ctx,this,0,40,30);
+ this.ratio=new waapisimAudioParam(ctx,this,1,20,12);
+ this.reduction=new waapisimAudioParam(ctx,this,-20,0,0);//ReadOnly
+ this.attack=new waapisimAudioParam(ctx,this,0,1,0.003);
+ this.release=new waapisimAudioParam(ctx,this,0,1,0.25);
+ this._maxl=0;
+ this._maxr=0;
+ this._gain=1;
+ this._Process=function() {
+ this.threshold._Process();
+ this.knee._Process();
+ this.ratio._Process();
+ this.attack._Process();
+ this.release._Process();
+ var inbuf=this._nodein[0].inbuf.buf;
+ var relratio=this.release.Get(0)*waapisimSampleRate;
+ relratio=Math.pow(1/3.16,1/relratio);
+ var atkratio=this.attack.Get(0)*waapisimSampleRate;
+ atkratio=Math.pow(1/3.16,1/atkratio);
+ var reduc=this.reduction.value;
+ var thresh=Math.pow(10,this.threshold.Get(0)/20);
+ var knee=Math.pow(10,this.knee.Get(0)/20*0.5);
+ var makeup=1/Math.sqrt(thresh)/Math.pow(10,this.knee.Get(0)/80);
+ var maxratio=0.99105;
+ var ratio=this.ratio.Get(0);
+ if(ratio<=1)
+ ratio=1;
+ for(var i=0;ithresh) {
+ var v=Math.pow(thresh*Math.min(knee,maxc/thresh)/maxc,1-1/ratio);
+ this._gain=v+(this._gain-v)*atkratio;
+ }
+ else
+ this._gain=1+(this._gain-1)*relratio;
+ var g=this._gain*makeup;
+ this._nodeout[0].NodeEmit(i,inbuf[0][i]*g,inbuf[1][i]*g);
+ }
+ this.reduction.value=this.reduction.computedValue=reduc;
+ this._nodein[0].NodeClear();
+ this.threshold.Clear(false);
+ this.knee.Clear(false);
+ this.ratio.Clear(false);
+ this.reduction.Clear(false);
+ this.attack.Clear(false);
+ this.release.Clear(false);
+ };
+ };
+ waapisimPanner=webkitAudioPannerNode=AudioPannerNode=function(ctx) {
+ waapisimAudioNode.call(this,waapisimBufSize,1,1);
+ this._nodetype="Panner";
+ waapisimDebug("create "+this._nodetype+this._nodeId);
+ this.context=ctx;
+ this.playbackState=0;
+ this.panningModel=0;
+ this.distanceModel=1;
+ this.refDistance=1;
+ this.maxDistance=10000;
+ this.rolloffFactor=1;
+ this.coneInnerAngle=360;
+ this.coneOuterAngle=360;
+ this.coneOuterGain=0;
+ this.px=0;
+ this.py=0;
+ this.pz=0;
+ this.setPosition=function(x,y,z) {this.px=x;this.py=y;this.pz=z;};
+ this.setOrientation=function(x,y,z) {};
+ this.setVelocity=function(x,y,z) {};
+ this._Process=function() {
+ var inbuf=this._nodein[0].inbuf.buf;
+ var listener=this.context.listener;
+ var dx=this.px-listener.px;
+ var dy=this.py-listener.py;
+ var dz=this.pz-listener.pz;
+ var d=Math.max(1,Math.sqrt(dx*dx+dy*dy+dz*dz));
+ var dgain;
+ switch(this.distanceModel) {
+ case "linear":
+ case 0:
+ dgain=1-this.rolloffFactor*(d-this.refDistance)/(this.maxDistance-this.refDistance);
+ break;
+ case "inverse":
+ case 1:
+ dgain=this.refDistance/(this.refDistance+this.rolloffFactor*(d-this.refDistance));
+ break;
+ case "exponential":
+ case 2:
+ dgain=Math.pow(d/this.refDistance,-this.rolloffFactor);
+ break;
+ }
+ var rgain,lgain,tr;
+ if(Math.abs(dz)<0.001) {
+ lgain=rgain=1;
+ }
+ else {
+ tr=Math.atan(dx/dz);
+ if(dz<=0) {
+ rgain=-tr+Math.PI*0.5;
+ lgain=tr+Math.PI*0.5;
+ }
+ else {
+ switch(this.panningModel) {
+ case 0:
+ case "equalpower":
+ rgain=tr+Math.PI*0.5;
+ lgain=-tr+Math.PI*0.5;
+ break;
+ default:
+ if(dx>=0) {
+ rgain=tr+Math.PI*0.5;
+ lgain=-(-tr+Math.PI*0.5);
+ }
+ else {
+ rgain=-(tr+Math.PI*0.5);
+ lgain=-tr+Math.PI*0.5;
+ }
+ }
+ }
+ }
+ var rl=Math.sqrt(rgain*rgain+lgain*lgain);
+ rgain=rgain/rl;
+ lgain=lgain/rl;
+ var a=Math.sqrt(rgain*rgain+lgain*lgain);
+ rgain=rgain/a*2*dgain; lgain=lgain/a*2*dgain;
+ for(var i=0;i=0) {
+ for(i=0;it)
+ break;
+ }
+ this.automation.splice(i,0,ev);
+ };
+ this.setValueAtTime=function(v,t) {
+ this.AddEvent([t,0,v]);
+ };
+ this.linearRampToValueAtTime=function(v,t) {
+ this.AddEvent([t,1,v]);
+ };
+ this.exponentialRampToValueAtTime=function(v,t) {
+ this.AddEvent([t,2,v]);
+ };
+ this.setTargetAtTime=this.setTargetValueAtTime=function(v,t,c) {
+ this.AddEvent([t,3,v,c]);
+ };
+ this.setValueCurveAtTime=function(values,t,d) {
+ this.AddEvent([t,4,values,d]);
+ };
+ this.cancelScheduledValues=function(t) {
+ for(var l=this.automation.length,i=0;i=t) {
+ this.automation.length=i;
+ return;
+ }
+ }
+ };
+ this._Process=function() {
+ this.value+=this.deltaAdd;
+ this.value=(this.value-this.deltaTarget)*this.deltaMul+this.deltaTarget;
+ if(this.currentEvent!==null) {
+ if(this.currentEvent[1]==4) {
+ var i=(this.currentEvent[2].length-1)*(this.context.currentTime-this.currentEvent[0])/this.currentEvent[3];
+ this.value=this.currentEvent[2][Math.min(this.currentEvent[2].length-1,i)|0];
+ }
+ }
+ if(this.automation.length>0) {
+ if(this.context.currentTime>=this.automation[0][0]) {
+ this.deltaAdd=0;
+ this.deltaMul=1;
+ this.deltaTarget=0;
+ this.currentEvent=this.automation.shift();
+ switch(this.currentEvent[1]) {
+ case 0:
+ case 1:
+ case 2:
+ this.value=this.currentEvent[2];
+ break;
+ case 3:
+ this.deltaMul=Math.pow(0.367879,1/(waapisimSampleRate/waapisimBufSize*this.currentEvent[3]));
+ this.deltaTarget=this.currentEvent[2];
+ break;
+ }
+ if(this.automation.length>0) {
+ var n=waapisimSampleRate/waapisimBufSize*(this.automation[0][0]-this.context.currentTime);
+ switch(this.automation[0][1]) {
+ case 1:
+ this.deltaAdd=(this.automation[0][2]-this.value)/n;
+ break;
+ case 2:
+ this.deltaMul=Math.pow(this.automation[0][2]/this.value,1/n);
+ break;
+ }
+ }
+ }
+ }
+ };
+ this.Init=function() {
+ this.computedValue=parseFloat(this.value);
+ }
+ this.Get=function(n) {
+ if(this.from.length>0)
+ this.computedValue=parseFloat(this.value)+(this.inbuf.buf[0][n]+this.inbuf.buf[1][n])*0.5;
+ else
+ this.computedValue=this.computedValue*this.timeconst+(1-this.timeconst)*parseFloat(this.value);
+ return this.computedValue;
+ };
+ this.Clear=function(arate) {
+ if(arate) {
+ for(var i=0;i 0)
+ app.keyboard.key.NoteOn(parseInt(msg[2], 16), velo);
+ else
+ app.keyboard.key.NoteOff(parseInt(msg[2], 16));
+ break;
+ case 0xb0:
+ if (parseInt(msg[2], 16) == 0x78) {
+ app.keyboard.key.AllOff();
+ }
+ break;
+ }
+ break;
+ }
+}
+function LinkSend(win, s) {
+ win.postMessage(s, "*");
+}
+function LinkReady() {
+ LinkSend(window.parent, "link,ready");
+}
+function GetPatchString() {
+ return CmdSave();
+}
+function SetPatchString(s) {
+ CmdLoad(s);
+}
+function getXY(e) {
+ var rc = e.target.getBoundingClientRect();
+ mouseX = Math.floor(e.clientX - rc.left);
+ mouseY = Math.floor(e.clientY - rc.top);
+ if (mouseX < 0) mouseX = 0;
+ if (mouseY < 0) mouseY = 0;
+}
+function getXYTouch(e){
+ var touch =e.changedTouches[0];
+ var rc = touch.target.getBoundingClientRect()
+ mouseX = Math.floor(touch.clientX - rc.left);
+ mouseY = Math.floor(touch.clientY - rc.top);
+ if (mouseX < 0) mouseX = 0;
+ if (mouseY < 0) mouseY = 0;
+}
+function Rect(x, y, w, h) {
+ this.ty = 10000;
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ this.Draw = function() {
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = "#000000";
+ ctx.strokeRect(x, y, w, h);
+ }
+ this.MouseDown = function(x,y) {
+ }
+ this.MouseMove = function(x,y) {
+ }
+ this.MouseUp = function(x,y) {
+ }
+}
+function Jack(x, y, ty,col) {
+ this.ty = ty;
+ this.x = x;
+ this.y = y;
+ this.w = 16;
+ this.h = 16;
+ this.connect = null;
+ this.fanout = 0;
+ if (ty == 0)
+ this.pnum = jinum++;
+ else
+ this.pnum = jonum++;
+ this.col = cablecol[colnum];
+ if (ty == 0) {
+ if (++colnum >= 18)
+ colnum = 0;
+ }
+ if (ty != 0) {
+ try {
+ this.buf = new Float32Array(128);
+ } catch (e) {
+ this.buf = new Array(128);
+ }
+ for (var i = 0; i < 128; ++i)
+ this.buf[i] = 0;
+ }
+ this.Draw = function() {
+ if (typeof (gadget) != "undefined")
+ return;
+ if (this.connect != null) {
+ this.Cable(this, this.connect.x + 8, this.connect.y + 12, this.col, 0);
+ }
+ }
+ this.FillBuf = function(v) {
+ var out = this.buf;
+ for (var i = 0; i < 128; ++i)
+ out[i] = v;
+ }
+ this.Connect = function(jck) {
+ var jIn = this;
+ var jOut = jck;
+ if (this.ty != 0) {
+ jIn = jck;
+ jOut = this;
+ }
+ if (jIn.connect != null) {
+ if (jIn.connect.fanout > 0)
+ --(jIn.connect.fanout);
+ }
+ jIn.connect = jOut;
+ if (jOut != null)
+ ++jOut.fanout;
+ }
+ this.Cable = function(j, x, y, col, f) {
+ var mx = (j.x + 8 + x) / 2;
+ var my = Math.max(j.y+12, y)+40;
+ ctx.beginPath();
+ ctx.moveTo(j.x + 8, j.y+12);
+ ctx.bezierCurveTo(mx, my, mx, my, x, y);
+
+ var r = (col >> 16) & 0xff;
+ var g = (col >> 8) & 0xff;
+ var b = col & 0xff;
+ for (var i = 3; i; --i) {
+ ctx.strokeStyle = "#" + ("000000" + ((r << 16) + (g << 8) + b).toString(16)).slice(-6);
+ if (r < 200)
+ r += Math.floor((200 - r) / 3);
+ if (g < 200)
+ g += Math.floor((200 - g) / 3);
+ if (b < 200)
+ b += Math.floor((200 - b) / 3);
+ ctx.lineWidth = i;
+ ctx.lineCap = "round";
+ ctx.stroke();
+ }
+ switch (f) {
+ case 1:
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "#00ff00";
+ ctx.beginPath();
+ ctx.arc(x, y, 8, 0, Math.PI * 2, true);
+ ctx.stroke();
+ break;
+ case 2:
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "#ff0000";
+ ctx.beginPath();
+ ctx.moveTo(x - 8, y - 8);
+ ctx.lineTo(x + 8, y + 8);
+ ctx.moveTo(x + 8, y - 8);
+ ctx.lineTo(x - 8, y + 8);
+ ctx.stroke();
+ break;
+ }
+ }
+ this.MouseDown = function(x,y) {
+ }
+ this.MouseMove = function(x,y) {
+ }
+ this.MouseUp = function(x,y) {
+ }
+}
+function Knob(x, y, w, h, img, step, def) {
+ this.ty = 100;
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ this.x0 = 0;
+ this.y0 = 0;
+ this.v0 = 0;
+ this.img = img;
+ this.step = step;
+ this.val = def;
+ this.Draw = function() {
+ if (typeof (gadget) != "undefined" || imgknobs[img] == undefined)
+ return;
+ var n = Math.floor(this.val * step);
+ if (this.val == 1)
+ --n;
+ ctx.drawImage(imgknobs[img], 0, n * h, w, h, this.x, this.y, w, h);
+ }
+ this.Set = function(v) {
+ if (v < 0)
+ v = 0;
+ if (v > 1)
+ v = 1;
+ if (this.step > 1)
+ v = Math.floor(v * (this.step - 1)) / (this.step - 1);
+ this.val = v;
+ }
+ this.MouseDown = function(x, y) {
+ this.x0 = x;
+ this.y0 = y;
+ this.v0 = this.val;
+ }
+ this.MouseMove = function(x, y) {
+ if (typeof (gadget) != "undefined")
+ return;
+ this.Set(this.v0 + (x - this.x0 - y + this.y0) * 0.01);
+ this.Draw();
+ }
+ this.MouseUp = function(x, y) {
+ }
+}
+function Switch(x, y, w, h, img, step, def) {
+ this.ty = 102;
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ this.img = img;
+ this.step = step;
+ this.val = def;
+ this.Draw = function() {
+ if (typeof (gadget) != "undefined" || imgknobs[img] == undefined)
+ return;
+ var n = Math.floor(this.val * this.step);
+ if (this.val == 1)
+ --n;
+ ctx.drawImage(imgknobs[img], 0, n * this.h, this.w, this.h, this.x, this.y, this.w, this.h);
+ }
+ this.Set = function(v) {
+ if (v < 0)
+ v = 0;
+ if (v > 1)
+ v = 1;
+ this.val = v;
+ }
+ this.MouseDown = function(x, y) {
+ this.MouseMove(x, y);
+ }
+ this.MouseMove = function(x, y) {
+ if (typeof (gadget) != "undefined")
+ return;
+ this.Set(Math.floor((1 - (y - this.y) / this.h) * this.step) / (this.step - 1));
+ this.Draw();
+ }
+ this.MouseUp = function(x, y) {
+ }
+}
+function Slider(x, y,def) {
+ this.ty = 101;
+ this.x = x;
+ this.y = y;
+ this.w = 16;
+ this.h = 65;
+ this.val = def;
+ this.vala = (Math.pow(1000, this.val) - 1) * 0.0001;
+ this.v0 = 0;
+ this.x0 = 0;
+ this.y0 = 0;
+ this.Draw = function() {
+ if (typeof (gadget) != "undefined")
+ return;
+ ctx.drawImage(imgknobs["slider"], this.x, this.y + 50 - this.val * 50);
+ }
+ this.Set=function(v) {
+ if (v < 0)
+ v = 0;
+ if (v > 1)
+ v = 1;
+ this.val = v;
+ this.vala = (Math.pow(100, this.val) - 1) * 0.04;
+ }
+ this.MouseDown = function(x, y) {
+ this.x0 = x;
+ this.y0 = y;
+ this.v0 = this.val;
+ }
+ this.MouseMove = function(x, y) {
+ if (typeof (gadget) != "undefined")
+ return;
+ this.Set(this.v0 + (this.y0 - y) * 0.01);
+ this.Draw();
+ }
+ this.MouseUp = function(x,y) {
+ }
+}
+var cnt = 0;
+function Key(x, y) {
+ this.ty = 900;
+ this.x = x;
+ this.y = y;
+ if (typeof(gadget) == "undefined")
+ this.w = 448;
+ else
+ this.w = 272;
+ this.h = 64;
+ this.gate = 0;
+ this.cv = 0;
+ this.retrig = 0;
+ this.lastn = -1;
+ this.table = [
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,-1,-1,-1,
+ 27, -1, 13, 15, -1, 18, 20, 22, -1, 25, -1, -1, -1, -1, -1, -1,
+ -1, -1, 7, 4, 3, 16, -1, 6, 8, 24, 10, -1, 13, 11, 9, 26,
+ 28, 12,17,1,19,23,5,14,2,21,0,-1,-1,-1,-1,-1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, 14, -1,
+ ];
+ this.press = new Array();
+ this.Draw = function() {
+ }
+ this.KeyPosX = function(n) {
+ return Math.floor(n / 12) * 112 + [0, 12, 16, 28, 32, 48, 60, 64, 76, 80, 92, 96][n % 12];
+ }
+ this.KeyPosY = function(n) {
+ return [40, 0, 40, 0, 40, 40, 0, 40, 0, 40, 0, 40][n % 12];
+ }
+ this.DrawKey = function(n) {
+ // if (this.lastn != n) {
+ var nmax = 48;
+ if (typeof (gadget) != "undefined")
+ nmax = 29;
+ ctx.drawImage(imgpanel, this.x, this.y, this.w, this.h, this.x, this.y, this.w, this.h);
+ if (n >= 0 && n < nmax) {
+ var y = this.KeyPosY(n);
+ var w = (y != 0) ? 16 : 8;
+ var h = (y != 0) ? 24 : 40;
+ ctx.drawImage(imgknobs["keypress"], this.KeyPosX(n), y, w, h, this.x + this.KeyPosX(n), this.y + y, w, h);
+ }
+ this.lastn = n;
+ // }
+ }
+ this.MouseDown = function(x, y) {
+ this.gate = 1;
+ this.MouseMove(x, y);
+ }
+ this.MouseMove = function(x, y) {
+ var n;
+ x = (x - this.x);
+ if (y >= this.y + 40) {
+ x = Math.floor(x / 16);
+ if (x < 0)
+ x = 0;
+ if (x >= 28)
+ x = 27;
+ n = Math.floor(x / 7) * 12 + [0, 2, 4, 5, 7, 9, 11][x % 7];
+ }
+ else {
+ var xx = x + 5;
+ if (xx % 16 < 10) {
+ var xxx = Math.floor(xx / 16) % 7;
+ if (xxx == 1 || xxx == 2 || xxx == 4 || xxx == 5 | xxx == 6) {
+ x = Math.floor(x / 16);
+ n = Math.floor(x / 7) * 12 + [0, 1, 3, 0, 6, 8, 10][xxx];
+ this.cv = n / 12 * 0.2;
+ this.DrawKey(n);
+ return;
+ }
+ }
+ x = Math.floor(x / 16);
+ if (x < 0)
+ x = 0;
+ if (x >= 28)
+ x = 27;
+ }
+ n = Math.floor(x / 7) * 12 + [0, 2, 4, 5, 7, 9, 11][x % 7];
+ this.cv = n / 12 * 0.2;
+ if (this.lastn >= 0 && n >= 0 && n != this.lastn)
+ this.retrig = 1;
+ this.DrawKey(n);
+ }
+ this.MouseUp = function(x, y) {
+ this.gate = 0;
+ this.DrawKey(-1);
+ }
+ this.AllOff = function() {
+ this.press.length = 0;
+ this.gate = 0;
+ this.DrawKey(-1);
+ }
+ this.NoteOn = function(n,v) {
+ for (var i = 0; i < this.press.length; ++i) {
+ if (this.press[i] == n)
+ break;
+ }
+ if (i == this.press.length) {
+ this.gate = 1;
+ this.retrig = 1;
+ n -= 36;
+ this.cv = n / 60;
+ this.DrawKey(n);
+ }
+ }
+ this.NoteOff = function(n) {
+ for (var i = 0; i < this.press.length; ++i) {
+ if (this.press[i] == n) {
+ this.press.splice(i, 1);
+ break;
+ }
+ }
+ if (this.press.length == 0) {
+ this.gate = 0;
+ this.DrawKey(-1);
+ }
+ else {
+ n = this.press[0] - 36;
+ this.cv = n / 60;
+ this.DrawKey(n);
+ }
+ }
+ this.KeyPress = function(c, f) {
+ if (f) {
+ if (c >= 0x20 && c <= 0xbf) {
+ var n = this.table[c - 0x20];
+ if (n >= 0) {
+ for (var i = 0; i < this.press.length; ++i) {
+ if (this.press[i] == c)
+ break;
+ }
+ if (i == this.press.length) {
+ this.press.unshift(c);
+ this.gate = 1;
+ this.retrig = 1;
+ this.cv = n / 60;
+ this.DrawKey(n);
+ }
+ }
+ }
+ }
+ else {
+ for (var i = 0; i < this.press.length; ++i) {
+ if (this.press[i] == c) {
+ this.press.splice(i, 1);
+ break;
+ }
+ }
+ if (this.press.length == 0) {
+ this.gate = 0;
+ this.DrawKey(-1);
+ }
+ else {
+ var n = this.table[this.press[0] - 0x20];
+ this.cv = n / 60;
+ this.DrawKey(n);
+ }
+ }
+ }
+}
+function Knobs() {
+ this.drag = null;
+ this.knobs = new Array();
+ this.AddRect = function(name, x, y, w, h) {
+ this.knobs[name] = new Rect(x, y, w, h);
+ return this.knobs[name];
+ }
+ this.AddJack = function(name, x, y,ty,col) {
+ this.knobs[name] = new Jack(x, y,ty,col);
+ return this.knobs[name];
+ }
+ this.AddKnob = function(name, x, y, w,h,img, step,def) {
+ this.knobs[name] = new Knob(x, y, w,h,img,step,def);
+ return this.knobs[name];
+ }
+ this.AddSwitch = function(name, x, y,w,h,img,step,def) {
+ this.knobs[name] = new Switch(x,y,w,h,img,step,def);
+ return this.knobs[name];
+ }
+ this.AddSlider = function(name, x, y, def) {
+ this.knobs[name] = new Slider(x, y, def);
+ return this.knobs[name];
+ }
+ this.AddKey = function(name, x, y) {
+ this.knobs[name] = new Key(x, y);
+ return this.knobs[name];
+ }
+ this.MouseDown = function(x, y) {
+ this.drag = this.HitTest(x, y);
+ if (this.drag != null)
+ this.drag.MouseDown(x, y);
+ }
+ this.MouseMove = function(x, y) {
+ if (this.drag != null) {
+ app.Draw();
+ this.drag.MouseMove(x, y);
+ }
+ }
+ this.MouseUp = function(x, y) {
+ var wd = this.HitTest(x, y);
+ if (this.drag != null) {
+ if (wd != null) {
+ if (wd.ty == 0 && (this.drag.ty == 1 || this.drag.ty == 2)) {
+ wd.Connect(this.drag);
+ }
+ if ((wd.ty == 1 || wd.ty == 2) && this.drag.ty == 0) {
+ this.drag.Connect(wd);
+ }
+ }
+ if (this.drag.ty == 0) {
+ if(wd==null || (wd.ty!=1 && wd.ty!=2))
+ this.drag.Connect(null);
+ }
+ this.drag.MouseUp(x, y);
+ }
+ this.drag = null;
+ app.Draw();
+ }
+ this.HitTest = function(x, y) {
+ var wd, r;
+ r = null;
+ for (var i in this.knobs) {
+ var wd = this.knobs[i];
+ if (x >= wd.x && x < wd.x + wd.w && y >= wd.y && y < wd.y + wd.h) {
+ if (wd.ty < 1000)
+ r = wd;
+ }
+ }
+ return r;
+ }
+ this.Draw = function() {
+ for (var i in this.knobs) {
+ if (this.knobs[i].ty >= 100)
+ this.knobs[i].Draw();
+ }
+ for (var i in this.knobs) {
+ if (this.knobs[i].ty < 100)
+ this.knobs[i].Draw();
+ }
+ if (this.drag != null && this.drag.ty < 100) {
+ var wd = this.HitTest(mouseX, mouseY);
+ var f = 0;
+ if (wd != null && wd.ty < 100) {
+ if ((this.drag.ty == 0 && wd.ty != 0) || (this.drag.ty != 0 && wd.ty == 0))
+ f = 1;
+ else
+ f = 2;
+ }
+ this.drag.Cable(this.drag, mouseX, mouseY, 0x808080, f);
+ }
+ }
+}
+function Keyboard(name, x, y) {
+ this.str = "";
+ this.start = 0;
+ this.tempo = 120;
+ this.deflen = 8;
+ this.oct = 3;
+ this.index = 0;
+ this.dur = 0;
+ this.gt = 0;
+ this.cvcur = 0;
+ this.cvlog = 0;
+ this.jckCv = app.knobs.AddJack(name + ".cv", x + 24, y + 8, 2,0x600000);
+ this.jckGate = app.knobs.AddJack(name + ".g", x + 60, y + 8, 2, 0x700000);
+ this.knbGlide = app.knobs.AddKnob(name + ".gl", x + 484, y + 36, 32, 32, "knob", 51, 0);
+ if (typeof (gadget) != "undefined")
+ this.key = app.knobs.AddKey(name + ".k", x, y);
+ else
+ this.key = app.knobs.AddKey(name + ".k", x + 24, y + 48);
+ this.SetStr=function(s) {
+ this.str=s;
+ }
+ this.Start = function(v) {
+ this.jckGate.buf[0] = 0;
+ this.tempo = 120;
+ this.deflen = 8;
+ this.oct = 3;
+ this.index = 0;
+ this.start = v;
+ if (v == 0)
+ this.key.DrawKey(-1);
+ }
+ this.GetNum=function() {
+ var n = 0;
+ while (this.str[this.index] >= '0' && this.str[this.index] <= '9') {
+ n = n * 10 + parseInt(this.str[this.index]);
+ ++this.index;
+ }
+ return n;
+ }
+ this.Note = function(n) {
+ ++this.index;
+ var n2 = n;
+ while (1) {
+ switch (this.str[this.index]) {
+ case '+':
+ case '#':
+ ++n2;
+ ++this.index;
+ break;
+ case '-':
+ --n2;
+ ++this.index;
+ break;
+ default:
+ var len;
+ len = this.GetNum();
+ if (len <= 0)
+ len = this.deflen;
+ var st = 240 / (this.tempo * len);
+ var st2 = st;
+ while(this.str[this.index] == '.'){
+ ++this.index;
+ st += (st2/=2);
+ }
+ if (this.str[this.index] == '&'|| this.str[this.index] == '^') {
+ ++this.index;
+ this.gt = st;
+ }
+ else
+ this.gt = st * 0.8;
+ this.dur += st;
+ if (n >= 0) {
+ var nn = (this.oct - 2) * 12 + n2;
+ var v = n / 12 * 0.2;
+ if (v < 0)
+ v = 0;
+ if (v > 2)
+ v = 2;
+ this.cvlog=(nn / 12 * 0.2);
+ this.jckGate.FillBuf(1);
+ this.key.DrawKey(nn);
+ }
+ else {
+ this.jckGate.FillBuf(0);
+ this.gt = 0;
+ this.key.DrawKey(-1);
+ }
+ return;
+ }
+ }
+ }
+ this.OutCv = function() {
+ var diff = Math.abs(this.cvlog - this.cvcur);
+ var ratio = 1;
+ if (this.knbGlide.val != 0) {
+ ratio = Math.pow(100, this.knbGlide.val) * 0.000078125 * samplerate;
+ ratio = 1 - Math.exp(Math.log(0.01) / ratio);
+ }
+ if (diff < 1e-10)
+ this.cvcur = this.cvlog;
+ else
+ this.cvcur += (this.cvlog - this.cvcur) * ratio;
+ this.jckCv.FillBuf(this.cvcur);
+ }
+ this.Process = function() {
+ if (this.start == 0) {
+ if (this.key.gate != 0) {
+ if (this.key.retrig)
+ this.jckGate.FillBuf(0);
+ else
+ this.jckGate.FillBuf(1);
+ this.cvlog = this.key.cv;
+ }
+ else
+ this.jckGate.FillBuf(0);
+ this.OutCv();
+ this.key.retrig = 0;
+ return;
+ }
+ this.key.retrig = 0;
+ if (this.dur > 0) {
+ this.dur -= 128 / samplerate;
+ }
+ if (this.gt > 0) {
+ if ((this.gt -= 128 / samplerate) <= 0) {
+ this.gt = 0;
+ this.jckGate.FillBuf(0);
+ }
+ }
+ while (this.dur <= 0) {
+ if (this.index >= this.str.length)
+ break;
+ switch (this.str[this.index]) {
+ case 'T':
+ case 't':
+ ++this.index;
+ this.tempo = this.GetNum();
+ if (this.tempo <= 0)
+ this.tempo = 120;
+ break;
+ case 'V':
+ ++this.index;
+ this.GetNum();
+ break;
+ case 'L':
+ case 'l':
+ ++this.index;
+ this.deflen = this.GetNum();
+ break;
+ case '>':
+ ++this.index;
+ ++this.oct;
+ break;
+ case '<':
+ ++this.index;
+ --this.oct;
+ break;
+ case 'O':
+ case 'o':
+ ++this.index;
+ this.oct = this.GetNum();
+ break;
+ case 'R':
+ case 'r':
+ this.Note(-1);
+ break;
+ case 'C':
+ case 'c':
+ this.Note(0);
+ break;
+ case 'D':
+ case 'd':
+ this.Note(2);
+ break;
+ case 'E':
+ case 'e':
+ this.Note(4);
+ break;
+ case 'F':
+ case 'f':
+ this.Note(5);
+ break;
+ case 'G':
+ case 'g':
+ this.Note(7);
+ break;
+ case 'A':
+ case 'a':
+ this.Note(9);
+ break;
+ case 'B':
+ case 'b':
+ this.Note(11);
+ break;
+ default:
+ ++this.index;
+ break;
+ }
+ }
+ this.OutCv();
+ if (this.index >= this.str.length) {
+ this.tempo = 120;
+ this.deflen = 8;
+ this.oct = 3;
+ this.index = 0;
+ }
+ }
+}
+function Mix(name, x, y) {
+ try {
+ this.buf = new Float32Array(128);
+ } catch(e) {
+ this.buf=new Array(128);
+ }
+ this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y+52, 0,0x005000);
+ this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y+52, 0,0x006000);
+ this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y+52, 0,0x007000);
+ this.jckIn4 = app.knobs.AddJack(name + ".i4", x + 68, y+52, 0,0x008000);
+ this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y+72, 0.8);
+ this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y+72, 0.8);
+ this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y+72, 0);
+ this.sliIn4 = app.knobs.AddSlider(name + ".i4m", x + 68, y+72, 0);
+ this.Process = function() {
+ for (var i = 0; i < 128; ++i) {
+ this.buf[i] = 1e-100;
+ }
+ if (this.jckIn1.connect) {
+ var vala = this.sliIn1.vala;
+ for (var i = 0; i < 128; ++i)
+ this.buf[i] += this.jckIn1.connect.buf[i] * vala;
+ }
+ if (this.jckIn2.connect) {
+ var vala = this.sliIn2.vala;
+ for (var i = 0; i < 128; ++i)
+ this.buf[i] += this.jckIn2.connect.buf[i] * vala;
+ }
+ if (this.jckIn3.connect) {
+ var vala = this.sliIn3.vala;
+ for (var i = 0; i < 128; ++i)
+ this.buf[i] += this.jckIn3.connect.buf[i] * vala;
+ }
+ if (this.jckIn4.connect) {
+ var vala = this.sliIn4.vala;
+ for (var i = 0; i < 128; ++i)
+ this.buf[i] += this.jckIn4.connect.buf[i] * vala;
+ }
+ }
+}
+function Ring(name, x, y) {
+ this.jckIn1 = app.knobs.AddJack(name + ".i1", x+8, y + 0, 0,0x009000);
+ this.jckIn2 = app.knobs.AddJack(name + ".i2", x+32, y + 0, 0,0x00a000);
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x800000);
+ this.Process = function() {
+ if (this.jckOut.fanout > 0) {
+ var out = this.jckOut.buf;
+ if (this.jckIn1.connect && this.jckIn2.connect) {
+ var in1 = this.jckIn1.connect.buf;
+ var in2 = this.jckIn2.connect.buf;
+ for (var i = 0; i < 128; ++i)
+ out[i] = in1[i] * in2[i];
+ }
+ else {
+ for (var i = 0; i < 128; ++i)
+ out[i] = 0;
+ }
+ }
+ }
+}
+function Noise(name, x, y) {
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x900000);
+ this.Process = function() {
+ if (this.jckOut.fanout > 0) {
+ var out = this.jckOut.buf;
+ for (var i = 0; i < 128; ++i)
+ out[i] = Math.random()*2 - 1;
+ }
+ }
+}
+function SH(name, x, y) {
+ this.hold = 0;
+ this.trlast = 0;
+ this.jckIn = app.knobs.AddJack(name + ".i", x + 8, y + 0, 0,0x009000);
+ this.jckTr = app.knobs.AddJack(name + ".tr", x + 32, y + 0, 0,0x00a000);
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 0, 1,0x990000);
+ this.Process = function() {
+ if (this.jckOut.fanout > 0) {
+ var out = this.jckOut.buf;
+ var hold = this.hold;
+ if (this.jckTr.connect != null) {
+ var tr = this.jckTr.connect.buf[0];
+ if (tr > 0 && this.trlast <= 0) {
+ if (this.jckIn.connect != null)
+ this.hold = this.jckIn.connect.buf[0];
+ else
+ this.hold = 0;
+ }
+ this.trlast = tr;
+ }
+ for (var i = 0; i < 128; ++i)
+ out[i] = hold;
+ }
+ }
+}
+function Env(name, x, y) {
+ this.jckOutP = app.knobs.AddJack(name + ".op", x + 68, y + 120, 2,0xb00000);
+ this.jckOutN = app.knobs.AddJack(name + ".on", x + 40, y + 120, 2,0xc00000);
+ this.jckTrig = app.knobs.AddJack(name + ".tr", x + 8, y + 120, 0,0);
+ this.sliA = app.knobs.AddSlider(name + ".a", x + 8, y + 28, 0);
+ this.sliD = app.knobs.AddSlider(name + ".d", x + 28, y + 28, 0);
+ this.sliS = app.knobs.AddSlider(name + ".s", x + 48, y + 28, 1);
+ this.sliR = app.knobs.AddSlider(name + ".r", x + 68, y + 28, 0);
+ this.phase = 0;
+ this.val = 0;
+ this.Process = function() {
+ if (this.jckTrig.connect == null) {
+ this.jckOutP.buf[0] = this.jckOutN.buf[0] = 0;
+ this.phase = this.val = 0;
+ return;
+ }
+ var n = 128 / samplerate;
+ var ratea = n / (Math.pow(1000, this.sliA.val) * 0.001);
+ var rated = Math.pow(10, -2 / ((Math.pow(1000, this.sliD.val) * 0.01) / n));
+ var rater = Math.pow(10, -2 / ((Math.pow(1000, this.sliR.val) * 0.01) / n));
+ switch (this.phase) {
+ case 0:
+ if (this.jckTrig.connect.buf[0] > 0)
+ this.phase = 1;
+ else {
+ if (this.val > this.sliS.val) {
+ this.val = this.sliS.val + (this.val - this.sliS.val) * rated;
+ }
+ this.val *= rater;
+ if (this.val < 0.00001)
+ this.val = 0;
+ }
+ break;
+ case 1:
+ if (this.jckTrig.connect.buf[0] > 0) {
+ if ((this.val += ratea) >= 1) {
+ this.val = 1;
+ this.phase = 2;
+ }
+ }
+ else {
+ this.phase = 0;
+ }
+ break;
+ case 2:
+ if (this.jckTrig.connect.buf[0] > 0) {
+ this.val = this.sliS.val + (this.val - this.sliS.val) * rated;
+ }
+ else
+ this.phase = 0;
+ break;
+ }
+ var xxp = this.val;
+ var xxn = -this.val;
+ for (var i = 0; i < 128; ++i) {
+ this.jckOutP.buf[i] = xxp;
+ this.jckOutN.buf[i] = xxn;
+ }
+ }
+}
+function Lfo(name, x, y) {
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 68, y + 20, 2,0x880000);
+ this.jckOut10 = app.knobs.AddJack(name + ".o10", x + 40, y + 20, 2,0x990000);
+ this.knbForm = app.knobs.AddSwitch(name + ".form", x + 8, y + 64, 16, 40, "sw3", 3, 1);
+ this.knbFreq = app.knobs.AddKnob(name + ".f", x + 48, y + 68, 32, 32, "knob", 51, 0.5);
+ this.phase = 0;
+ this.Process = function() {
+ var f = Math.pow(1000, this.knbFreq.val) * 0.1;
+ this.phase += f * 128 / samplerate;
+ if (this.phase >= 1)
+ this.phase -= 1;
+ var x, mul0, mul1, add0, add1;
+ switch (this.knbForm.val) {
+ case 1:
+ mul0 = 4;
+ mul1 = -4;
+ add0 = -1;
+ add1 = 3;
+ break;
+ case 0.5:
+ mul0 = mul1 = 2;
+ add0 = add1 = -1;
+ break;
+ case 0:
+ mul0 = mul1 = 0;
+ add0 = -1;
+ add1 = 1;
+ break;
+ }
+ if (this.phase >= 0.5)
+ x = this.phase * mul1 + add1;
+ else
+ x = this.phase * mul0 + add0;
+ var xx = x;
+ var xx10 = x * 0.1;
+ for (var i = 0; i < 128; ++i) {
+ this.jckOut.buf[i] = xx;
+ this.jckOut10.buf[0] = xx10;
+ }
+ }
+}
+function Vco(name, x, y, oct, pit) {
+ this.jckPwm = app.knobs.AddJack(name + ".ipw", x + 8, y + 52, 0, 0x007700);
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 52, 1, 0xf00000);
+ this.sliPwm = app.knobs.AddSlider(name + ".pwm", x + 8, y + 72, 0);
+ this.sliPw = app.knobs.AddSlider(name + ".pw", x + 28, y + 72, 0);
+ this.knbOct = app.knobs.AddSwitch(name + ".oct", x + 8, y + 168, 16, 40, "sw5", 5, oct);
+ this.knbForm = app.knobs.AddSwitch(name + ".form", x + 40, y + 168, 16, 40, "sw3", 3, 0.5);
+ this.knbCoarse = app.knobs.AddKnob(name + ".co", x + 8, y + 236, 40, 40, "knob2", 25, 0.5);
+ this.knbPitch = app.knobs.AddKnob(name + ".pi", x + 16, y + 244, 24, 24, "knob3", 51, pit);
+ this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
+ this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0.1);
+ this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
+ this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
+ this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
+ this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
+ this.phase = 0;
+ this.freq = 0;
+ this.delta = 0;
+ this.cpw = 0;
+ this.rcpw = 1;
+ this.Process = function() {
+ if (this.jckOut.fanout <= 0)
+ return;
+ var cv;
+ cv = (this.knbOct.val - 0.5) * (this.knbOct.step - 1) * 0.2 + (this.knbCoarse.val - 0.5) * 0.4 + (this.knbPitch.val - 0.5) * 0.4 / 12;
+ if (this.jckMod1.connect)
+ cv += this.jckMod1.connect.buf[0] * this.sliMod1.val;
+ if (this.jckMod2.connect)
+ cv += this.jckMod2.connect.buf[0] * this.sliMod2.val;
+ if (this.jckMod3.connect)
+ cv += this.jckMod3.connect.buf[0] * this.sliMod3.val;
+ this.freq = 130.8127826502993 * Math.pow(2, cv * 5);
+ this.delta = this.freq / samplerate;
+ if (this.delta > 1)
+ this.delta = 1;
+ var cpw = this.sliPw.val;
+ if (this.jckPwm.connect)
+ cpw += this.jckPwm.connect.buf[0] * this.sliPwm.val;
+ if (cpw < 0)
+ cpw = -cpw;
+ if (cpw > 0.95)
+ cpw = 0.95;
+ var rcpw = 1 / (1 - cpw);
+ var mul0, mul1, add0, add1;
+ switch (this.knbForm.val) {
+ case 1:
+ mul0 = 4;
+ add0 = -1;
+ mul1 = -4;
+ add1 = 3;
+ break;
+ case 0.5:
+ mul0 = mul1 = 2;
+ add0 = add1 = -1;
+ break;
+ case 0:
+ mul0 = mul1 = 0;
+ add0 = -1;
+ add1 = 1;
+ break;
+ }
+ var x;
+ var out = this.jckOut.buf;
+ for (var i = 0; i < 128; ++i) {
+ if (this.phase > cpw) {
+ var ph2 = (this.phase - cpw) * rcpw;
+ if (ph2 >= 0.5)
+ x = ph2 * mul1 + add1;
+ else
+ x = ph2 * mul0 + add0;
+ }
+ else
+ x = 0;
+ this.phase += this.delta;
+ if (this.phase >= 1)
+ this.phase -= 1;
+ out[i] = x;
+ }
+ }
+}
+function Vcf(name, x, y) {
+ this.y1 = this.y2 = this.y3 = this.y4 = 0;
+ this.ox = 0;
+ this.k = this.r = this.p = 0;
+ this.gain = 0;
+ this.enable = false;
+ this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y + 52, 0);
+ this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y + 52, 0);
+ this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y + 52, 0);
+ this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y + 72, 0.8);
+ this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y + 72, 0.8);
+ this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y + 72, 0);
+ this.knbFreq = app.knobs.AddKnob(name + ".f", x + 12, y + 152, 32, 32, "knob", 50, 0.8);
+ this.knbReso = app.knobs.AddKnob(name + ".r", x + 12, y + 200, 32, 32, "knob", 50, 0.5);
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 252, 1);
+ this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
+ this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0.5);
+ this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
+ this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
+ this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
+ this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
+ this.SetFreq = function(f) {
+ f = Math.min(0.45, Math.max(0.001, f));
+ this.p = f * (1.8 - 0.8 * f);
+ this.k = this.p * 2 - 1;
+ t = (1 - this.p) * 1.35;
+ t2 = 11 + t * t;
+ this.r = this.knbReso.val * (t2 + 6 * t) / (t2 - 6 * t) * 0.8;
+ }
+ this.SetFreq(1);
+ this.Process = function() {
+ if (this.jckOut.fanout <= 0)
+ return;
+ var cv;
+ cv = this.knbFreq.val;
+ if (this.jckMod1.connect)
+ cv += this.jckMod1.connect.buf[0] * this.sliMod1.val;
+ if (this.jckMod2.connect)
+ cv += this.jckMod2.connect.buf[0] * this.sliMod2.val;
+ if (this.jckMod3.connect)
+ cv += this.jckMod3.connect.buf[0] * this.sliMod3.val;
+ this.freq = 130.8127826502993 * Math.pow(2, cv * 5);
+ this.SetFreq(this.freq / samplerate);
+ var sliIn1 = this.sliIn1.val;
+ var sliIn2 = this.sliIn2.val;
+ var sliIn3 = this.sliIn3.val;
+ var enIn1 = (this.jckIn1.connect != null);
+ var enIn2 = (this.jckIn2.connect != null);
+ var enIn3 = (this.jckIn3.connect != null);
+ if (enIn1 || enIn2 || enIn3) {
+ var out = this.jckOut.buf;
+ var k = this.k;
+ var p = this.p;
+ this.enable = true;
+ for (var i = 0; i < 128; ++i) {
+ var x = 1e-100;
+ if (enIn1)
+ x += this.jckIn1.connect.buf[i] * sliIn1;
+ if (enIn2)
+ x += this.jckIn2.connect.buf[i] * sliIn2;
+ if (enIn3)
+ x += this.jckIn3.connect.buf[i] * sliIn3;
+
+ x = x * .1 - this.r * this.y4;
+ y1 = this.y1; y2 = this.y2; y3 = this.y3;
+ this.y1 = (x + this.ox) * p - y1 * k;
+ this.y2 = (this.y1 + y1) * p - y2 * k;
+ this.y3 = (this.y2 + y2) * p - y3 * k;
+ y4 = (this.y3 + y3) * p - this.y4 * k;
+ this.y4 = y4 - y4 * y4 * y4 * 0.1666666666666667;
+ this.ox = x;
+ out[i] = this.y4 * 12;
+ }
+ }
+ else {
+ if (this.enable)
+ this.jckOut.FillBuf(0);
+ this.enable = false;
+ }
+ }
+}
+function Vca(name, x, y) {
+ this.gain = 0;
+ this.enable = false;
+ this.jckIn1 = app.knobs.AddJack(name + ".i1", x + 8, y + 52, 0);
+ this.jckIn2 = app.knobs.AddJack(name + ".i2", x + 28, y + 52, 0);
+ this.jckIn3 = app.knobs.AddJack(name + ".i3", x + 48, y + 52, 0);
+ this.sliIn1 = app.knobs.AddSlider(name + ".i1m", x + 8, y + 72, 0.8);
+ this.sliIn2 = app.knobs.AddSlider(name + ".i2m", x + 28, y + 72, 0);
+ this.sliIn3 = app.knobs.AddSlider(name + ".i3m", x + 48, y + 72, 0);
+ this.knbVol = app.knobs.AddKnob(name + ".vol", x + 12, y + 164, 32, 32, "knob", 50, 0.5);
+ this.jckOut = app.knobs.AddJack(name + ".o", x + 48, y + 224, 1);
+ this.sliMod1 = app.knobs.AddSlider(name + ".m1m", x + 8, y + 280, 1);
+ this.sliMod2 = app.knobs.AddSlider(name + ".m2m", x + 28, y + 280, 0);
+ this.sliMod3 = app.knobs.AddSlider(name + ".m3m", x + 48, y + 280, 0);
+ this.jckMod1 = app.knobs.AddJack(name + ".m1", x + 8, y + 348, 0);
+ this.jckMod2 = app.knobs.AddJack(name + ".m2", x + 28, y + 348, 0);
+ this.jckMod3 = app.knobs.AddJack(name + ".m3", x + 48, y + 348, 0);
+ this.Process = function() {
+ if (this.jckOut.fanout <= 0)
+ return;
+ var v;
+ var g = this.knbVol.val;
+ if (this.jckMod1.connect != null)
+ g += this.jckMod1.connect.buf[0] * this.sliMod1.val;
+ if (this.jckMod2.connect != null)
+ g += this.jckMod2.connect.buf[0] * this.sliMod2.val;
+ if (this.jckMod3.connect != null)
+ g += this.jckMod3.connect.buf[0] * this.sliMod3.val;
+ if (g < 0)
+ g = 0;
+ if (Math.abs(this.gain - g) < 1e-10)
+ this.gain = g;
+ var sli1 = this.sliIn1.val;
+ var sli2 = this.sliIn2.val;
+ var sli3 = this.sliIn3.val;
+ var enIn1 = (this.jckIn1.connect != null);
+ var enIn2 = (this.jckIn2.connect != null);
+ var enIn3 = (this.jckIn3.connect != null);
+ if (enIn1 || enIn2 || enIn3) {
+ this.enable = true;
+ var out = this.jckOut.buf;
+ for (var i = 0; i < 128; ++i) {
+ v = 1e-100;
+ if (enIn1)
+ v += this.jckIn1.connect.buf[i] * sli1;
+ if (enIn2)
+ v += this.jckIn2.connect.buf[i] * sli2;
+ if (enIn3)
+ v += this.jckIn3.connect.buf[i] * sli3;
+ out[i] = v * this.gain;
+ this.gain += (g - this.gain) * 0.02;
+// this.gain = g;
+ }
+ }
+ else {
+ if (this.enable)
+ this.jckOut.FillBuf(0);
+ this.enable = false;
+ }
+ }
+}
+function App() {
+ this.Draw = function() {
+ if (!this.canvas || !this.canvas.getContext) {
+ return false;
+ }
+ ctx = this.canvas.getContext('2d');
+ ctx.drawImage(imgpanel, 0, 0);
+ this.knobs.Draw();
+ }
+ this.MouseDown = function(e) {
+ if(!this.ready){
+ audioif.audio.resume();
+ this.ready = true;
+ }
+ console.log("Press");
+ document.getElementById("canvas").focus();
+ getXY(e);
+ app.knobs.MouseDown(mouseX, mouseY);
+ return false;
+ }
+ this.MouseMove = function(e) {
+ getXY(e);
+ app.knobs.MouseMove(mouseX, mouseY);
+ }
+ this.MouseUp = function(e) {
+ getXY(e);
+ app.knobs.MouseUp(mouseX, mouseY);
+ }
+ this.TouchDown = function(e) {
+ if(!this.ready){
+ audioif.audio.resume();
+ this.ready = true;
+ }
+ e.preventDefault();
+ document.getElementById("canvas").focus();
+ getXYTouch(e);
+ app.knobs.MouseDown(mouseX, mouseY);
+ return false;
+ }
+ this.TouchMove = function(e) {
+ e.preventDefault();
+ getXYTouch(e);
+ app.knobs.MouseMove(mouseX, mouseY);
+ }
+ this.TouchUp = function(e) {
+ e.preventDefault();
+ getXYTouch(e);
+ app.knobs.MouseUp(mouseX, mouseY);
+ }
+ this.DblClick = function(e) {
+ }
+ this.KeyDown = function(e) {
+ if (document.activeElement == document.getElementById("canvas")) {
+ app.keyboard.key.KeyPress(e.keyCode, 1);
+ return false;
+ }
+ }
+ this.KeyUp = function(e) {
+ app.keyboard.key.KeyPress(e.keyCode, 0);
+ }
+ this.KeyPress = function(e) {
+ if (document.activeElement == document.getElementById("canvas"))
+ return false;
+ }
+ this.Init = function() {
+ samplerate = 44100;
+ this.ready = false;
+ this.canvas = document.getElementById('canvas');
+ this.canvas.onmousedown = this.MouseDown;
+ this.canvas.onmousemove = this.MouseMove;
+ this.canvas.onmouseup = this.MouseUp;
+ this.canvas.ondblclick = this.DblClick;
+ this.canvas.ontouchstart = this.TouchDown;
+ this.canvas.ontouchmove = this.TouchMove;
+ this.canvas.ontouchend = this.TouchUp;
+ document.onkeydown = this.KeyDown;
+ document.onkeyup = this.KeyUp;
+ document.onkeypress = this.KeyPress;
+ this.knobs = new Knobs();
+ this.vco1 = new Vco("vco1", 36, 78, 0.5, 0.5);
+ this.vco2 = new Vco("vco2", 108, 78, 0.25, 0.45);
+ this.vcf1 = new Vcf("vcf1", 180, 78);
+ this.vcf2 = new Vcf("vcf2", 252, 78);
+ this.vca1 = new Vca("vca1", 324, 78);
+ this.vca2 = new Vca("vca2", 396, 78);
+ this.env1 = new Env("env1", 468, 78);
+ this.env2 = new Env("env2", 468, 226);
+ this.lfo1 = new Lfo("lfo1", 468, 374);
+ this.lfo2 = new Lfo("lfo2", 564, 374);
+ this.mix = new Mix("mix", 564, 78);
+ this.ring = new Ring("ring", 564, 250);
+ this.noise = new Noise("noise", 564, 286);
+ this.sh = new SH("sh", 564, 346);
+ if (typeof(gadget) != "undefined")
+ this.keyboard = new Keyboard("kb", 24, 154);
+ else
+ this.keyboard = new Keyboard("kb", 48, 502);
+ try {
+ this.dummybuf = new Float32Array(128);
+ } catch (e) {
+ this.dummybuf = new Array(128);
+ }
+ for (var i = 0; i < 128; ++i)
+ this.dummybuf[i] = 0;
+ audioif = new AudioIf();
+ audiomix = new AudioMix();
+ imgpanel = document.getElementById("panel");
+ imgknobs["knob"] = document.getElementById("knob");
+ imgknobs["knob2"] = document.getElementById("knob2");
+ imgknobs["knob3"] = document.getElementById("knob3");
+ imgknobs["sw2"] = document.getElementById("sw2");
+ imgknobs["sw3"] = document.getElementById("sw3");
+ imgknobs["sw5"] = document.getElementById("sw5");
+ imgknobs["slider"] = document.getElementById("slider");
+ imgknobs["keypress"] = document.getElementById("keypress");
+ Setup();
+ this.Draw();
+ var param = location.search;
+ if (param.length > 1)
+ CmdLoad(location.search.substring(1));
+ }
+}
+function Interval() {
+// if (typeof (document.hasFocus) != "undefined" && document.hasFocus() == false)
+// return;
+ audiomix.Play();
+ audioif.Write();
+}
+function Init() {
+ app = new App();
+ app.Init();
+ if (audioif.enable == 0) {
+ return;
+ }
+ if (audioif.start == 0) {
+ audioif.Start();
+ audiomix.Reset();
+ playint = setInterval(Interval, 20);
+ }
+ LinkReady();
+}
+function CmdPlay(v) {
+ if (v) {
+ if(!app.ready)
+ audioif.audio.resume();
+ app.keyboard.SetStr(document.getElementById("mml").value);
+ app.keyboard.Start(1);
+ }
+ else {
+ app.keyboard.Start(0);
+ }
+}
+function CmdSave() {
+ var jstr = "";
+ var kstr = "";
+ var vals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ for (var i in app.knobs.knobs) {
+ var w = app.knobs.knobs[i];
+ switch(w.ty) {
+ case 0:
+ if (w.connect != null) {
+ jstr += vals[w.pnum];
+ jstr += vals[w.connect.pnum];
+ }
+ break;
+ case 100:
+ case 102:
+ kstr += vals[(w.val * (w.step-1)) | 0];
+ break;
+ case 101:
+ kstr += vals[(w.val * 50) | 0];
+ break;
+ }
+ }
+ var mstr = encodeURIComponent(document.getElementById("mml").value);
+ var url = document.URL.split("?")[0] + "?p=" + jstr + "_" + kstr+"&m="+mstr;
+ document.getElementById("url").value = url;
+ return url;
+}
+function GetJack(n, t) {
+ for (var i in app.knobs.knobs) {
+ var w = app.knobs.knobs[i];
+ if (t == 0) {
+ if (w.ty == 0) {
+ if (w.pnum == n)
+ return w;
+ }
+ }
+ else {
+ if (w.ty != 0 && w.ty < 100) {
+ if (w.pnum == n)
+ return w;
+ }
+ }
+ }
+}
+function CmdLoad(str) {
+ if (str == null) {
+ str = document.getElementById("url").value;
+ }
+ n = str.indexOf("?");
+ if (n >= 0)
+ str = str.substring(n + 1);
+ var param = str.split("&");
+ var vals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ for (var i = 0; i < param.length; ++i) {
+ if (param[i].search("p=") == 0) {
+ var s = param[i].substring(2);
+ for (var ii in app.knobs.knobs) {
+ var w = app.knobs.knobs[ii];
+ if (w.ty == 0)
+ w.connect = null;
+ else if (w.ty < 100)
+ w.fanout = 0;
+ }
+ for (var j = 0; j < s.length; j += 2) {
+ if (s.charAt(j) == "_")
+ break;
+ var n = vals.indexOf(s.charAt(j));
+ var v = vals.indexOf(s.charAt(j + 1));
+ GetJack(n, 0).Connect(GetJack(v, 1));
+ }
+ ++j;
+ for (var ii in app.knobs.knobs) {
+ var w = app.knobs.knobs[ii];
+ switch (w.ty) {
+ case 100:
+ case 102:
+ w.Set(vals.indexOf(s.charAt(j)) / (w.step-1));
+ ++j;
+ break;
+ case 101:
+ w.Set(vals.indexOf(s.charAt(j)) / 50);
+ ++j;
+ break;
+ }
+ }
+ }
+ else if (param[i].search("m=") == 0) {
+ var s;
+ try {
+ s=decodeURIComponent(param[i].substring(2));
+ } catch (e) {
+ s = param[i].substring(2);
+ }
+ document.getElementById("mml").value = s;
+ }
+ }
+ app.Draw();
+}
+function CmdTweet() {
+ CmdSave();
+ var url = "https://twitter.com/intent/tweet?hashtags=WebModular&url=" + encodeURIComponent(document.getElementById("url").value);
+ var win = window.open(url, "", "toolbar=0, status=0, width=650, height=360");
+
+}
+function Message(s) {
+}
+var datbuf = new Array(4096);
+for (var ii = 0; ii < 4096; ++ii) {
+ datbuf[ii] = 0;
+}
+function FlashGetEnable() {
+ if (audioif.enable == 3)
+ return 1;
+ else
+ return 0;
+}
+function FlashGetData() {
+ var b = audiomix.GetOutBuf();
+ if (b < 0) {
+ return datbuf;
+ }
+ else {
+ audiomix.NextBuf();
+ return audiomix.queout[b];
+ }
+}
+function AudioIf() {
+ this.start = 0;
+ this.written = 0;
+ this.size = Math.floor(samplerate * 15 / 120) * 16;
+ this.buf = 0;
+ samplerate = 44100;
+ this.enable = 0;
+ this.totalwritten = 0;
+ this.count = 0;
+ if (typeof (webkitAudioContext) != "undefined") {
+ this.audio = new webkitAudioContext();
+ samplerate = this.audio.sampleRate;
+ this.enable = 2;
+ outbufsize = 1024;
+ }
+ else if(typeof (AudioContext) != "undefined") {
+ this.audio = new AudioContext();
+ samplerate = this.audio.sampleRate;
+ this.enable = 2;
+ outbufsize = 1024;
+ }
+ else if (typeof (Audio) != "function") {
+ this.audio = new Audio();
+ if (typeof (this.audio.mozSetup) == "function") {
+ this.enable = 1;
+ outbufsize = 1024;
+ }
+ }
+ if (this.enable == 0) {
+ this.enable = 3;
+ outbufsize = 4096;
+ }
+ switch (this.enable) {
+ case 0:
+ Message("Audio Disabled: 'AudioDataAPI' or 'WebAudioAPI' is not supported in this browser.");
+ break;
+ case 1:
+ Message("Using Audio Data API");
+ break;
+ case 2:
+ Message("Using Web Audio API");
+ break;
+ case 3:
+ break;
+ }
+ if (this.enable > 0) {
+ try {
+ this.dummysample = new Float32Array(outbufsize);
+ } catch (e) {
+ this.dummysample = new Array(outbufsize);
+ }
+ for (var i = 0; i < outbufsize; ++i)
+ this.dummysample[i] = 0;
+ }
+ if (this.enable == 1) {
+ this.audio.mozSetup(stereo+1, samplerate);
+ }
+ if (this.enable == 2) {
+ this.dummyosc = this.audio.createOscillator();
+ this.jsnode = this.audio.createScriptProcessor(outbufsize,2,2);
+// this.jsnode = this.audio.createJavaScriptNode(outbufsize, 2, 2);
+ this.jsnode.onaudioprocess = function(e) {
+ var outl = e.outputBuffer.getChannelData(0);
+ var outr = e.outputBuffer.getChannelData(1);
+ var b = audiomix.GetOutBuf();
+ if (b < 0) {
+ outl.set(audioif.dummysample);
+ outr.set(audioif.dummysample);
+ }
+ else {
+ outl.set(audiomix.queout[b]);
+ outr.set(audiomix.queout[b]);
+ audiomix.NextBuf();
+ }
+ }
+ }
+ this.SetSamplerate = function(s) {
+ if (s != samplerate) {
+ samplerate = s;
+ audiomix.SetSamplerate();
+ }
+ }
+ this.Write = function() {
+ if (this.enable == 1) {
+ if (audioif.start == 0)
+ return;
+ if (this.written >= outbufsize2) {
+ if (audiomix.NextBuf() < 0)
+ return;
+ this.written = 0;
+ }
+ if (this.totalwritten > this.audio.mozCurrentSampleOffset() + 16384)
+ return;
+ var b = audiomix.GetOutBuf();
+ if (b >= 0) {
+ w = this.audio.mozWriteAudio(audiomix.queout[b].subarray(this.written));
+ this.totalwritten += w;
+ this.written += w;
+ }
+ }
+ }
+ this.Start = function() {
+ this.start = 1;
+ switch (this.enable) {
+ case 1:
+ break;
+ case 2:
+ this.audio.resume();
+ this.dummyosc.connect(this.audio.destination);
+ this.jsnode.connect(this.audio.destination);
+ break;
+ }
+ }
+ this.Stop = function() {
+ this.start = 0;
+ switch (this.enable) {
+ case 1:
+ break;
+ case 2:
+ this.jsnode.disconnect(0);
+ break;
+ }
+ }
+ this.SetSize = function(s) {
+ this.size = s;
+ }
+}
+function AudioMix() {
+ this.queout = new Array(outquenum);
+ this.queout2 = new Array(outquenum);
+ this.windex = 0;
+ this.rindex = 0;
+ this.pat = 0;
+ this.step = 0;
+ this.steplen = samplerate / 8;
+ this.tick = 0;
+ this.count = 0;
+ for (var i = 0; i < outquenum; ++i) {
+ if (audioif.enable == 1) {
+ this.queout[i] = new Float32Array(outbufsize2);
+ for (var ii = 0; ii < outbufsize2; ++ii)
+ this.queout[i][ii] = 0;
+ }
+ else if (audioif.enable == 2) {
+ this.queout[i] = new Float32Array(outbufsize);
+ this.queout2[i] = new Float32Array(outbufsize);
+ for (var ii = 0; ii < outbufsize; ++ii) {
+ this.queout[i][ii] = this.queout2[i][ii] = 0;
+ }
+ }
+ else {
+ this.queout[i] = new Array(outbufsize);
+ for (var ii = 0; ii < outbufsize2; ++ii)
+ this.queout[i][ii] = 0;
+ }
+ }
+ this.SetSamplerate = function() {
+ this.steplen = samplerate * 15 / tempo;
+ }
+ this.SetTempo = function(x) {
+ this.steplen = samplerate * 15 / x;
+ }
+ this.GetQueNum = function() {
+ if ((n = this.windex - this.rindex) < 0)
+ n += outquenum;
+ return n;
+ }
+ this.GetOutBuf = function() {
+ if (audiomix.rindex == audiomix.windex)
+ return -1;
+ return audiomix.rindex;
+ }
+ this.NextBuf = function() {
+ if (audiomix.rindex == audiomix.windex)
+ return -1;
+ if (++audiomix.rindex >= outquenum)
+ audiomix.rindex = 0;
+ return 1;
+ }
+ this.Reset = function() {
+ audiomix.tick = audiomix.steplen;
+ audiomix.rindex = audiomix.windex = 0;
+ audioif.written = 0;
+ }
+ this.Render = function(buf) {
+ }
+ this.DrawVu = function() {
+ }
+ this.Play = function() {
+ if (((audiomix.windex + 1) % outquenum) == audiomix.rindex)
+ return;
+ for (var ilp = 0; ilp < outbufsize; ilp += 128) {
+ app.keyboard.Process();
+ app.noise.Process();
+ app.vco1.Process();
+ app.vco2.Process();
+ app.vcf1.Process();
+ app.vcf2.Process();
+ app.vca1.Process();
+ app.vca2.Process();
+ app.lfo1.Process();
+ app.lfo2.Process();
+ app.env1.Process();
+ app.env2.Process();
+ app.ring.Process();
+ app.sh.Process();
+ app.mix.Process();
+ switch (audioif.enable) {
+ case 1:
+ for (var j = 0; j < 128; ++j) {
+ audiomix.queout[audiomix.windex][(ilp + j) << 1] = app.mix.buf[j];
+ audiomix.queout[audiomix.windex][((ilp + j) << 1) + 1] = app.mix.buf[j];
+ }
+ break;
+ case 2:
+ for (var j = 0; j < 128; ++j) {
+ audiomix.queout[audiomix.windex][ilp + j] = app.mix.buf[j];
+ audiomix.queout2[audiomix.windex][ilp + j] = app.mix.buf[j];
+ }
+ break;
+ case 3:
+ for (var j = 0; j < 128; ++j) {
+ audiomix.queout[audiomix.windex][ilp + j] = app.mix.buf[j];
+ }
+ break;
+ }
+ }
+ audiomix.windex = (audiomix.windex + 1) % outquenum;
+ }
+}
+function Setup() {
+ for (var i in app.knobs.knobs) {
+ var widget = app.knobs.knobs[i];
+ if (widget.ty == 0) {
+ widget.Connect(null);
+ }
+ else if (widget.ty < 100) {
+ widget.fanout = 0;
+ }
+ if (widget.ty >= 100 && widget.ty < 200)
+ widget.Set(0);
+ }
+ app.knobs.knobs["vco1.oct"].Set(0.5);
+ app.knobs.knobs["vco1.form"].Set(0.5);
+ app.knobs.knobs["vco1.co"].Set(0.5);
+ app.knobs.knobs["vco1.pi"].Set(0.5);
+ app.knobs.knobs["vco1.m1m"].Set(1);
+ app.knobs.knobs["vco2.oct"].Set(0.5);
+ app.knobs.knobs["vco2.form"].Set(0.5);
+ app.knobs.knobs["vco2.co"].Set(0.5);
+ app.knobs.knobs["vco2.pi"].Set(0.48);
+ app.knobs.knobs["vco2.m1m"].Set(1);
+ app.knobs.knobs["vcf1.i1m"].Set(0.7);
+ app.knobs.knobs["vcf1.f"].Set(1);
+ app.knobs.knobs["vcf1.r"].Set(0.5);
+ app.knobs.knobs["vcf1.m1m"].Set(1);
+ app.knobs.knobs["vcf2.i1m"].Set(0.7);
+ app.knobs.knobs["vcf2.f"].Set(0.8);
+ app.knobs.knobs["vcf2.r"].Set(0.5);
+ app.knobs.knobs["vcf2.m1m"].Set(1);
+ app.knobs.knobs["vca1.i1m"].Set(0.7);
+ app.knobs.knobs["vca1.m1m"].Set(1);
+ app.knobs.knobs["vca2.i1m"].Set(0.7);
+ app.knobs.knobs["vca2.m1m"].Set(1);
+ app.knobs.knobs["env1.s"].Set(1);
+ app.knobs.knobs["env2.s"].Set(1);
+ app.knobs.knobs["lfo1.f"].Set(0.5);
+ app.knobs.knobs["lfo1.form"].Set(0.5);
+ app.knobs.knobs["lfo2.f"].Set(0.5);
+ app.knobs.knobs["lfo2.form"].Set(0.5);
+ app.knobs.knobs["mix.i1m"].Set(0.5);
+ app.knobs.knobs["mix.i2m"].Set(0.5);
+ var n = document.getElementById("patch").selectedIndex;
+ switch (n) {
+ case 0:
+ break;
+ case 1:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["kb.g"]);
+ break;
+ case 2:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
+ app.knobs.knobs["vco2.oct"].Set(0);
+ app.knobs.knobs["vcf1.i2m"].Set(0.7);
+ break;
+ case 3:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["env2.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["vcf2.i1"].Connect(app.knobs.knobs["vco2.o"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
+ app.knobs.knobs["vca2.i1"].Connect(app.knobs.knobs["vcf2.o"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["mix.i2"].Connect(app.knobs.knobs["vca2.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
+ app.knobs.knobs["vca2.m1"].Connect(app.knobs.knobs["env2.op"]);
+ app.knobs.knobs["vcf1.f"].Set(0.6);
+ app.knobs.knobs["vcf1.r"].Set(0.6);
+ app.knobs.knobs["vcf2.f"].Set(0.7);
+ app.knobs.knobs["vcf2.r"].Set(1);
+ app.knobs.knobs["vco2.oct"].Set(0);
+ app.knobs.knobs["env1.d"].Set(0.8);
+ app.knobs.knobs["env1.s"].Set(0.1);
+ break;
+ case 4:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
+ app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["lfo1.o10"]);
+ app.knobs.knobs["vcf1.m2"].Connect(app.knobs.knobs["lfo1.o"]);
+ app.knobs.knobs["vcf1.i2m"].Set(0.8);
+ app.knobs.knobs["vco1.m2m"].Set(0.1);
+ app.knobs.knobs["vcf1.m2m"].Set(0.5);
+ app.knobs.knobs["lfo1.f"].Set(0.4);
+ app.knobs.knobs["lfo1.form"].Set(1);
+ break;
+ case 5:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vco2.o"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
+ app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["lfo1.o10"]);
+ app.knobs.knobs["vcf1.m2"].Connect(app.knobs.knobs["lfo1.o"]);
+ app.knobs.knobs["vcf1.i3"].Connect(app.knobs.knobs["noise.o"]);
+ app.knobs.knobs["sh.i"].Connect(app.knobs.knobs["noise.o"]);
+ app.knobs.knobs["sh.tr"].Connect(app.knobs.knobs["lfo2.o"]);
+ app.knobs.knobs["vco1.m2"].Connect(app.knobs.knobs["sh.o"]);
+ app.knobs.knobs["vcf1.i2m"].Set(0.5);
+ app.knobs.knobs["vcf1.i3m"].Set(0.4);
+ app.knobs.knobs["vcf1.r"].Set(0.8);
+ app.knobs.knobs["vco1.m2m"].Set(0.2);
+ app.knobs.knobs["vcf1.m2m"].Set(0.5);
+ app.knobs.knobs["lfo1.f"].Set(0.4);
+ app.knobs.knobs["lfo1.form"].Set(1);
+ app.knobs.knobs["lfo2.f"].Set(0.7);
+ break;
+ case 6:
+ app.knobs.knobs["vco1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vco2.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vcf1.i1"].Connect(app.knobs.knobs["ring.o"]);
+ app.knobs.knobs["vcf1.i2"].Connect(app.knobs.knobs["vca2.o"]);
+ app.knobs.knobs["vcf1.m1"].Connect(app.knobs.knobs["kb.cv"]);
+ app.knobs.knobs["vca1.i1"].Connect(app.knobs.knobs["vcf1.o"]);
+ app.knobs.knobs["vca1.m1"].Connect(app.knobs.knobs["env1.op"]);
+ app.knobs.knobs["vca2.i1"].Connect(app.knobs.knobs["noise.o"]);
+ app.knobs.knobs["vca2.m1"].Connect(app.knobs.knobs["env2.op"]);
+ app.knobs.knobs["env1.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["env2.tr"].Connect(app.knobs.knobs["kb.g"]);
+ app.knobs.knobs["mix.i1"].Connect(app.knobs.knobs["vca1.o"]);
+ app.knobs.knobs["ring.i1"].Connect(app.knobs.knobs["vco1.o"]);
+ app.knobs.knobs["ring.i2"].Connect(app.knobs.knobs["vco2.o"]);
+ app.knobs.knobs["vco1.form"].Set(1);
+ app.knobs.knobs["vco2.form"].Set(1);
+ app.knobs.knobs["vco2.pi"].Set(0);
+ app.knobs.knobs["vco2.m1m"].Set(0.5);
+ app.knobs.knobs["vcf1.i2m"].Set(0.5);
+ app.knobs.knobs["vcf1.r"].Set(0.8);
+ app.knobs.knobs["vcf1.f"].Set(0.5);
+ app.knobs.knobs["env1.d"].Set(0.75);
+ app.knobs.knobs["env1.s"].Set(0);
+ app.knobs.knobs["env1.r"].Set(0.75);
+ app.knobs.knobs["env2.s"].Set(0);
+ app.knobs.knobs["env2.d"].Set(0.8);
+ app.knobs.knobs["env2.r"].Set(0.8);
+ app.knobs.knobs["mix.i1m"].Set(0.75);
+ break;
+ }
+ app.Draw();
+}