From 7fd849d255d08511f3d133234fd6e61c68f85211 Mon Sep 17 00:00:00 2001 From: yining1023 Date: Sun, 4 Feb 2024 14:35:03 -0500 Subject: [PATCH] Fix some examples --- README.md | 2 +- rnn/CharRNN_Interactive/index.html | 3 +- rnn/CharRNN_Text/index.html | 65 +- rnn/CharRNN_Text_Stateful/index.html | 98 +- rnn/SketchRNN_basic/index.html | 9 +- rnn/SketchRNN_interactive/index.html | 9 +- text/CharRNN_Interactive/index.html | 58 +- text/CharRNN_Text/index.html | 65 +- text/CharRNN_Text_Stateful/index.html | 98 +- text/Sentiment/index.html | 14 +- text/Word2Vec/index.html | 107 +- text/gpt-2/p5.sound.min.js | 7101 ++++- .../ImageClassification/index.html | 30 +- .../ImageClassification_Video/index.html | 26 +- .../index.html | 44 +- .../ImageClassification_VideoSound/index.html | 47 +- .../index.html | 77 +- .../ImageClassification_Video_js/index.html | 40 +- .../p5+arduino+mobileNet/p5_code/index.html | 22 +- .../p5+arduino+mobileNet/p5_code/ml5.min.js | 90 - .../p5_code/p5.sound.min.js | 7101 ++++- .../StyleGAN_Generate/p5.sound.min.js | 7101 ++++- .../StyleGAN_Interpolate/p5.sound.min.js | 7101 ++++- .../StyleGAN_Wander/p5.sound.min.js | 7101 ++++- .../cupcakes_transition/p5.sound.min.js | 7101 ++++- .../index.html | 79 +- .../KNNClassification_VideoSound/index.html | 73 +- .../KNNClassification_VideoSquare/index.html | 80 +- week3-pose/PoseNet/index.html | 30 +- .../PoseNet_KNNClassification/index.html | 2 +- week3-pose/PoseNet_VideoMusic/index.html | 34 +- .../PoseNet_VideoMusic_multiple/index.html | 39 +- week3-pose/PoseNet_Zoom/p5.sound.min.js | 7711 ++++- week3-pose/PoseNet_dance_vis/index.html | 2 +- week3-pose/Posenet_mutil_noses/index.html | 30 +- week3-pose/UNET_webcam/index.html | 9 +- .../StyleTransfer_Image/index.html | 88 +- .../StyleTransfer_Video/index.html | 56 +- .../pix2pix-ml5/Pix2Pix_callback/index.html | 94 +- week7-runway/CycleGAN/libraries/p5.sound.js | 25649 ++++++++-------- week7-runway/GPT2/libraries/p5.sound.js | 25649 ++++++++-------- .../p5.sound.min.js | 7711 ++++- .../p5.sound.min.js | 7711 ++++- .../runway_u2net_hosted_model/p5.sound.min.js | 7711 ++++- 44 files changed, 100643 insertions(+), 25625 deletions(-) delete mode 100644 week1-intro/p5+arduino+mobileNet/p5_code/ml5.min.js diff --git a/README.md b/README.md index 2fdf8e6..49fc189 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ To run each examples, open your terminal, type in the following commands: ``` $ git clone https://github.com/yining1023/machine-learning-for-the-web.git $ cd machine-learning-for-the-web -$ python -m SimpleHTTPServer # $ python -m http.server (if you are using python 3) +$ python3 -m http.server ``` Go to `localhost:8000` in your browser, you will see a directory list like this: diff --git a/rnn/CharRNN_Interactive/index.html b/rnn/CharRNN_Interactive/index.html index 3f534dd..2bbb45d 100644 --- a/rnn/CharRNN_Interactive/index.html +++ b/rnn/CharRNN_Interactive/index.html @@ -6,8 +6,7 @@ - - + diff --git a/rnn/CharRNN_Text/index.html b/rnn/CharRNN_Text/index.html index c21b60c..5123820 100644 --- a/rnn/CharRNN_Text/index.html +++ b/rnn/CharRNN_Text/index.html @@ -1,31 +1,42 @@ + + + LSTM Text Generation Example - - - LSTM Text Generation Example + + + + - - - - - + +

LSTM Text Generation Example

+

+ This example uses a pre-trained model on a corpus of + Virginia Woolf +

+

+ seed text: + +

+

+ length: + + 100 +

+

+ temperature: + 0.5 +

+

Loading Model

+ +

- -

LSTM Text Generation Example

-

This example uses a pre-trained model on a corpus of Virginia Woolf

-

seed text: - -

-

length: - 100

-

temperature: - 0.5

-

Loading Model

- -

- - - - - - \ No newline at end of file + + + diff --git a/rnn/CharRNN_Text_Stateful/index.html b/rnn/CharRNN_Text_Stateful/index.html index 9f84adf..c052dca 100644 --- a/rnn/CharRNN_Text_Stateful/index.html +++ b/rnn/CharRNN_Text_Stateful/index.html @@ -1,41 +1,59 @@ - - - - Stateful CharRNN Text Generation Example using p5.js - - - - - - - - - - - -

Stateful CharRNN Text Generation Example using p5.js

-

Instead of feeding every single character every frame to predict the next character, we feed only the last character, and instruct the CharRNN to remember its internal state.

-

This example uses a pre-trained model on a corpus of Virginia Woolf

-

seed text: - -

-

temperature: - 0.5 -

-

-

Loading Model

-
- -

- -
-

Acknowledgements

-

- This work was supported through a residency at the Frank-Ratchye STUDIO for Creative Inquiry at Carnegie Mellon University, Pittsburgh, October 2018, with additional support from the Sylvia and David Steiner Speaker Series. -

- - - - - \ No newline at end of file + + + Stateful CharRNN Text Generation Example using p5.js + + + + + + + + + +

Stateful CharRNN Text Generation Example using p5.js

+

+ Instead of feeding every single character every frame to predict the next + character, we feed only the last character, and instruct the CharRNN to + remember its internal state. +

+

+ This example uses a pre-trained model on a corpus of + Virginia Woolf +

+

+ seed text: + +

+

+ temperature: + 0.5 +

+

+ +

+

Loading Model

+
+ +

+ +
+

Acknowledgements

+

+ This work was supported through a residency at the + Frank-Ratchye STUDIO for Creative Inquiry + at Carnegie Mellon University, Pittsburgh, October 2018, with additional + support from the Sylvia and David Steiner Speaker Series. +

+ + + diff --git a/rnn/SketchRNN_basic/index.html b/rnn/SketchRNN_basic/index.html index 6beb8fc..3e426e0 100644 --- a/rnn/SketchRNN_basic/index.html +++ b/rnn/SketchRNN_basic/index.html @@ -1,15 +1,18 @@ - + SketchRNN - +

SketchRNN

- \ No newline at end of file + diff --git a/rnn/SketchRNN_interactive/index.html b/rnn/SketchRNN_interactive/index.html index 55789c9..2cac02b 100644 --- a/rnn/SketchRNN_interactive/index.html +++ b/rnn/SketchRNN_interactive/index.html @@ -1,11 +1,14 @@ - + SketchRNN - + @@ -14,4 +17,4 @@

SketchRNN

- \ No newline at end of file + diff --git a/text/CharRNN_Interactive/index.html b/text/CharRNN_Interactive/index.html index 3f534dd..1a5e7a7 100644 --- a/text/CharRNN_Interactive/index.html +++ b/text/CharRNN_Interactive/index.html @@ -1,30 +1,40 @@ + + + Interactive CharRNN Text Generation Example using p5.js - - - Interactive CharRNN Text Generation Example using p5.js + + + - - - + + - - + - - - +

Interactive CharRNN Text Generation Example using p5.js

-

This example uses a pre-trained model on a corpus of Virginia Woolf

- -
length: - 20 -
temperature: - 0.5 -

Loading Model

-

- -

- - - \ No newline at end of file +

+ This example uses a pre-trained model on a corpus of + Virginia Woolf +

+ +
+ length: + 20
+ temperature: + 0.5 +

Loading Model

+

+ + diff --git a/text/CharRNN_Text/index.html b/text/CharRNN_Text/index.html index c21b60c..5123820 100644 --- a/text/CharRNN_Text/index.html +++ b/text/CharRNN_Text/index.html @@ -1,31 +1,42 @@ + + + LSTM Text Generation Example - - - LSTM Text Generation Example + + + + - - - - - + +

LSTM Text Generation Example

+

+ This example uses a pre-trained model on a corpus of + Virginia Woolf +

+

+ seed text: + +

+

+ length: + + 100 +

+

+ temperature: + 0.5 +

+

Loading Model

+ +

- -

LSTM Text Generation Example

-

This example uses a pre-trained model on a corpus of Virginia Woolf

-

seed text: - -

-

length: - 100

-

temperature: - 0.5

-

Loading Model

- -

- - - - - - \ No newline at end of file + + + diff --git a/text/CharRNN_Text_Stateful/index.html b/text/CharRNN_Text_Stateful/index.html index 9f84adf..c052dca 100644 --- a/text/CharRNN_Text_Stateful/index.html +++ b/text/CharRNN_Text_Stateful/index.html @@ -1,41 +1,59 @@ - - - - Stateful CharRNN Text Generation Example using p5.js - - - - - - - - - - - -

Stateful CharRNN Text Generation Example using p5.js

-

Instead of feeding every single character every frame to predict the next character, we feed only the last character, and instruct the CharRNN to remember its internal state.

-

This example uses a pre-trained model on a corpus of Virginia Woolf

-

seed text: - -

-

temperature: - 0.5 -

-

-

Loading Model

-
- -

- -
-

Acknowledgements

-

- This work was supported through a residency at the Frank-Ratchye STUDIO for Creative Inquiry at Carnegie Mellon University, Pittsburgh, October 2018, with additional support from the Sylvia and David Steiner Speaker Series. -

- - - - - \ No newline at end of file + + + Stateful CharRNN Text Generation Example using p5.js + + + + + + + + + +

Stateful CharRNN Text Generation Example using p5.js

+

+ Instead of feeding every single character every frame to predict the next + character, we feed only the last character, and instruct the CharRNN to + remember its internal state. +

+

+ This example uses a pre-trained model on a corpus of + Virginia Woolf +

+

+ seed text: + +

+

+ temperature: + 0.5 +

+

+ +

+

Loading Model

+
+ +

+ +
+

Acknowledgements

+

+ This work was supported through a residency at the + Frank-Ratchye STUDIO for Creative Inquiry + at Carnegie Mellon University, Pittsburgh, October 2018, with additional + support from the Sylvia and David Steiner Speaker Series. +

+ + + diff --git a/text/Sentiment/index.html b/text/Sentiment/index.html index 4792d43..d39604f 100644 --- a/text/Sentiment/index.html +++ b/text/Sentiment/index.html @@ -3,17 +3,21 @@ ml5 - Sentiment - +

Sentiment Analysis Demo

- This example uses model trained on movie reviews. This model scores the sentiment of text with - a value between 0 ("negative") and 1 ("positive"). The movie reviews were truncated to a - maximum of 200 words and only the 20,000 most common words in the reviews are used. + This example uses model trained on movie reviews. This model scores the + sentiment of text with a value between 0 ("negative") and 1 ("positive"). + The movie reviews were truncated to a maximum of 200 words and only the + 20,000 most common words in the reviews are used.

- \ No newline at end of file + diff --git a/text/Word2Vec/index.html b/text/Word2Vec/index.html index 6048402..0176e7f 100755 --- a/text/Word2Vec/index.html +++ b/text/Word2Vec/index.html @@ -1,54 +1,59 @@ - - - - - - Word2Vec example with p5.js. Using a pre-trained model on common English words. - - - - - - - - - - -

Word2Vec example with p5.js. Using a pre-trained model on common English words.

-

Loading Model...

-
-
-

- - -

-

-
- -
-

- Between - and - - -

-

-
- -
-

- is to - as - - -

-

+ + + + + + Word2Vec example with p5.js. Using a pre-trained model on common English + words. + + + + + + + + + + +

+ Word2Vec example with p5.js. Using a pre-trained model on common English + words. +

+

Loading Model...

+
+
+

+ + +

+

+
+ +
+

+ Between + and + + +

+

+
+ +
+

+ is to + as + + +

+

+
-
- - - - - \ No newline at end of file + + + diff --git a/text/gpt-2/p5.sound.min.js b/text/gpt-2/p5.sound.min.js index 899f447..f53f0c8 100644 --- a/text/gpt-2/p5.sound.min.js +++ b/text/gpt-2/p5.sound.min.js @@ -1,7 +1,7 @@ -/*! p5.sound.min.js v0.3.11 2019-03-14 */ +/*! p5.sound.min.js vlatest1 2019-03-14 */ /** - * p5.sound + * p5.sound * https://p5js.org/reference/#/libraries/p5.sound * * From the Processing Foundation and contributors @@ -21,8 +21,7095 @@ * Web Audio API: http://w3.org/TR/webaudio/ */ -!function(t,e){"function"==typeof define&&define.amd?define("p5.sound",["p5"],function(t){e(t)}):e("object"==typeof exports?require("../p5"):t.p5)}(this,function(t){var e;e=function(){!function(){function t(t){t&&(t.setTargetAtTime||(t.setTargetAtTime=t.setTargetValueAtTime))}window.hasOwnProperty("webkitAudioContext")&&!window.hasOwnProperty("AudioContext")&&(window.AudioContext=window.webkitAudioContext,"function"!=typeof AudioContext.prototype.createGain&&(AudioContext.prototype.createGain=AudioContext.prototype.createGainNode),"function"!=typeof AudioContext.prototype.createDelay&&(AudioContext.prototype.createDelay=AudioContext.prototype.createDelayNode),"function"!=typeof AudioContext.prototype.createScriptProcessor&&(AudioContext.prototype.createScriptProcessor=AudioContext.prototype.createJavaScriptNode),"function"!=typeof AudioContext.prototype.createPeriodicWave&&(AudioContext.prototype.createPeriodicWave=AudioContext.prototype.createWaveTable),AudioContext.prototype.internal_createGain=AudioContext.prototype.createGain,AudioContext.prototype.createGain=function(){var e=this.internal_createGain();return t(e.gain),e},AudioContext.prototype.internal_createDelay=AudioContext.prototype.createDelay,AudioContext.prototype.createDelay=function(e){var i=e?this.internal_createDelay(e):this.internal_createDelay();return t(i.delayTime),i},AudioContext.prototype.internal_createBufferSource=AudioContext.prototype.createBufferSource,AudioContext.prototype.createBufferSource=function(){var e=this.internal_createBufferSource();return e.start?(e.internal_start=e.start,e.start=function(t,i,n){"undefined"!=typeof n?e.internal_start(t||0,i,n):e.internal_start(t||0,i||0)}):e.start=function(t,e,i){e||i?this.noteGrainOn(t||0,e,i):this.noteOn(t||0)},e.stop?(e.internal_stop=e.stop,e.stop=function(t){e.internal_stop(t||0)}):e.stop=function(t){this.noteOff(t||0)},t(e.playbackRate),e},AudioContext.prototype.internal_createDynamicsCompressor=AudioContext.prototype.createDynamicsCompressor,AudioContext.prototype.createDynamicsCompressor=function(){var e=this.internal_createDynamicsCompressor();return t(e.threshold),t(e.knee),t(e.ratio),t(e.reduction),t(e.attack),t(e.release),e},AudioContext.prototype.internal_createBiquadFilter=AudioContext.prototype.createBiquadFilter,AudioContext.prototype.createBiquadFilter=function(){var e=this.internal_createBiquadFilter();return t(e.frequency),t(e.detune),t(e.Q),t(e.gain),e},"function"!=typeof AudioContext.prototype.createOscillator&&(AudioContext.prototype.internal_createOscillator=AudioContext.prototype.createOscillator,AudioContext.prototype.createOscillator=function(){var e=this.internal_createOscillator();return e.start?(e.internal_start=e.start,e.start=function(t){e.internal_start(t||0)}):e.start=function(t){this.noteOn(t||0)},e.stop?(e.internal_stop=e.stop,e.stop=function(t){e.internal_stop(t||0)}):e.stop=function(t){this.noteOff(t||0)},e.setPeriodicWave||(e.setPeriodicWave=e.setWaveTable),t(e.frequency),t(e.detune),e})),window.hasOwnProperty("webkitOfflineAudioContext")&&!window.hasOwnProperty("OfflineAudioContext")&&(window.OfflineAudioContext=window.webkitOfflineAudioContext)}(window),navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;var e=document.createElement("audio");t.prototype.isSupported=function(){return!!e.canPlayType};var i=function(){return!!e.canPlayType&&e.canPlayType('audio/ogg; codecs="vorbis"')},n=function(){return!!e.canPlayType&&e.canPlayType("audio/mpeg;")},o=function(){return!!e.canPlayType&&e.canPlayType('audio/wav; codecs="1"')},r=function(){return!!e.canPlayType&&(e.canPlayType("audio/x-m4a;")||e.canPlayType("audio/aac;"))},s=function(){return!!e.canPlayType&&e.canPlayType("audio/x-aiff;")};t.prototype.isFileSupported=function(t){switch(t.toLowerCase()){case"mp3":return n();case"wav":return o();case"ogg":return i();case"aac":case"m4a":case"mp4":return r();case"aif":case"aiff":return s();default:return!1}}}();var i;!function(t,e){i=function(){return e()}()}(this,function(){function t(t){var e=t.createBuffer(1,1,t.sampleRate),i=t.createBufferSource();i.buffer=e,i.connect(t.destination),i.start(0),t.resume&&t.resume()}function e(t){return"running"===t.state}function i(t,i){function n(){e(t)?i():(requestAnimationFrame(n),t.resume&&t.resume())}e(t)?i():n()}function n(t,e,i){if(Array.isArray(t)||NodeList&&t instanceof NodeList)for(var o=0;o1&&(this.input=new Array(t)),this.isUndef(e)||1===e?this.output=this.context.createGain():e>1&&(this.output=new Array(t))};t.prototype.set=function(e,i,n){if(this.isObject(e))n=i;else if(this.isString(e)){var o={};o[e]=i,e=o}t:for(var r in e){i=e[r];var s=this;if(-1!==r.indexOf(".")){for(var a=r.split("."),u=0;u1)for(var t=arguments[0],e=1;e0)for(var t=this,e=0;e0)for(var t=0;tn;n++)i[n].apply(this,e)}return this},t.Emitter.mixin=function(e){var i=["on","off","emit"];e._events={};for(var n=0;n1?t.getChannelData(1):e;var s=i(e,r),a=new window.ArrayBuffer(44+2*s.length),u=new window.DataView(a);n(u,0,"RIFF"),u.setUint32(4,36+2*s.length,!0),n(u,8,"WAVE"),n(u,12,"fmt "),u.setUint32(16,16,!0),u.setUint16(20,1,!0),u.setUint16(22,2,!0),u.setUint32(24,o.audiocontext.sampleRate,!0),u.setUint32(28,4*o.audiocontext.sampleRate,!0),u.setUint16(32,4,!0),u.setUint16(34,16,!0),n(u,36,"data"),u.setUint32(40,2*s.length,!0);for(var c=s.length,p=44,h=1,l=0;c>l;l++)u.setInt16(p,s[l]*(32767*h),!0),p+=2;return u}function i(t,e){for(var i=t.length+e.length,n=new Float32Array(i),o=0,r=0;i>r;)n[r++]=t[o],n[r++]=e[o],o++;return n}function n(t,e,i){for(var n=i.length,o=0;n>o;o++)t.setUint8(e+o,i.charCodeAt(o))}var o=a;t.prototype.sampleRate=function(){return o.audiocontext.sampleRate},t.prototype.freqToMidi=function(t){var e=Math.log(t/440)/Math.log(2),i=Math.round(12*e)+69;return i};var r=t.prototype.midiToFreq=function(t){return 440*Math.pow(2,(t-69)/12)},s=function(t){if("string"!=typeof t)return t;var e={A:21,B:23,C:24,D:26,E:28,F:29,G:31},i=e[t[0].toUpperCase()],n=~~t.slice(-1);switch(i+=12*(n-1),t[1]){case"#":i+=1;break;case"b":i-=1}return r(i)};return t.prototype.soundFormats=function(){o.extensions=[];for(var t=0;t-1))throw arguments[t]+" is not a valid sound format!";o.extensions.push(arguments[t])}},t.prototype.disposeSound=function(){for(var t=0;t-1)if(t.prototype.isFileSupported(n))i=i;else for(var r=i.split("."),s=r[r.length-1],a=0;a1?(this.splitter=i.createChannelSplitter(2),this.input.connect(this.splitter),this.splitter.connect(this.left,1),this.splitter.connect(this.right,0)):(this.input.connect(this.left),this.input.connect(this.right)),this.output=i.createChannelMerger(2),this.left.connect(this.output,0,1),this.right.connect(this.output,0,0),this.output.connect(e)},t.Panner.prototype.pan=function(t,e){var n=e||0,o=i.currentTime+n,r=(t+1)/2,s=Math.cos(r*Math.PI/2),a=Math.sin(r*Math.PI/2);this.left.gain.linearRampToValueAtTime(a,o),this.right.gain.linearRampToValueAtTime(s,o)},t.Panner.prototype.inputChannels=function(t){1===t?(this.input.disconnect(),this.input.connect(this.left),this.input.connect(this.right)):2===t&&(this.splitter=i.createChannelSplitter(2),this.input.disconnect(),this.input.connect(this.splitter),this.splitter.connect(this.left,1),this.splitter.connect(this.right,0))},t.Panner.prototype.connect=function(t){this.output.connect(t)},t.Panner.prototype.disconnect=function(){this.output&&this.output.disconnect()})}(a);var h;h=function(){function e(t,e){for(var i={},n=t.length,o=0;n>o;o++){if(t[o]>e){var r=t[o],s=new v(r,o);i[o]=s,o+=6e3}o++}return i}function i(t){for(var e=[],i=Object.keys(t).sort(),n=0;no;o++){var r=t[i[n]],s=t[i[n+o]];if(r&&s){var a=r.sampleIndex,u=s.sampleIndex,c=u-a;c>0&&r.intervals.push(c);var p=e.some(function(t){return t.interval===c?(t.count++,t):void 0});p||e.push({interval:c,count:1})}}return e}function n(t,e){var i=[];return t.forEach(function(t){try{var n=Math.abs(60/(t.interval/e));n=r(n);var o=i.some(function(e){return e.tempo===n?e.count+=t.count:void 0});if(!o){if(isNaN(n))return;i.push({tempo:Math.round(n),count:t.count})}}catch(s){throw s}}),i}function o(t,e,i,n){for(var o=[],s=Object.keys(t).sort(),a=0;a.01?!0:void 0})}function r(t){if(isFinite(t)&&0!==t){for(;90>t;)t*=2;for(;t>180&&t>90;)t/=2;return t}}function s(t){var e=t.inputBuffer.getChannelData(0);this._lastPos=e[e.length-1]||0,this._onTimeUpdate(self._lastPos)}function p(t){const e=t.target,i=this;e._playing=!1,e.removeEventListener("ended",i._clearOnEnd),i._onended(i),i.bufferSourceNodes.forEach(function(t,e){t._playing===!1&&i.bufferSourceNodes.splice(e)}),0===i.bufferSourceNodes.length&&(i._playing=!1)}var h=c,l=a,f=l.audiocontext,d=u.midiToFreq,m=u.convertToWav;t.SoundFile=function(e,i,n,o){if("undefined"!=typeof e){if("string"==typeof e||"string"==typeof e[0]){var r=t.prototype._checkFileFormats(e);this.url=r}else if("object"==typeof e&&!(window.File&&window.FileReader&&window.FileList&&window.Blob))throw"Unable to load file because the File API is not supported";e.file&&(e=e.file),this.file=e}this._onended=function(){},this._looping=!1,this._playing=!1,this._paused=!1,this._pauseTime=0,this._cues=[],this._cueIDCounter=0,this._lastPos=0,this._counterNode=null,this._scopeNode=null,this.bufferSourceNodes=[],this.bufferSourceNode=null,this.buffer=null,this.playbackRate=1,this.input=l.audiocontext.createGain(),this.output=l.audiocontext.createGain(),this.reversed=!1,this.startTime=0,this.endTime=null,this.pauseTime=0,this.mode="sustain",this.startMillis=null,this.panPosition=0,this.panner=new t.Panner(this.output,l.input,2),(this.url||this.file)&&this.load(i,n),l.soundArray.push(this),"function"==typeof o?this._whileLoading=o:this._whileLoading=function(){},this._onAudioProcess=s.bind(this),this._clearOnEnd=p.bind(this)},t.prototype.registerPreloadMethod("loadSound",t.prototype),t.prototype.loadSound=function(e,i,n,o){window.location.origin.indexOf("file://")>-1&&"undefined"===window.cordova&&window.alert("This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS");var r=this,s=new t.SoundFile(e,function(){"function"==typeof i&&i.apply(r,arguments),"function"==typeof r._decrementPreload&&r._decrementPreload()},n,o);return s},t.SoundFile.prototype.load=function(t,e){var i=this,n=(new Error).stack;if(void 0!==this.url&&""!==this.url){var o=new XMLHttpRequest;o.addEventListener("progress",function(t){i._updateProgress(t)},!1),o.open("GET",this.url,!0),o.responseType="arraybuffer",o.onload=function(){if(200===o.status){if(!i.panner)return;f.decodeAudioData(o.response,function(e){i.panner&&(i.buffer=e,i.panner.inputChannels(e.numberOfChannels),t&&t(i))},function(){if(i.panner){var t=new h("decodeAudioData",n,i.url),o="AudioContext error at decodeAudioData for "+i.url;e?(t.msg=o,e(t)):console.error(o+"\n The error stack trace includes: \n"+t.stack)}})}else{if(!i.panner)return;var r=new h("loadSound",n,i.url),s="Unable to load "+i.url+". The request status was: "+o.status+" ("+o.statusText+")";e?(r.message=s,e(r)):console.error(s+"\n The error stack trace includes: \n"+r.stack)}},o.onerror=function(){var t=new h("loadSound",n,i.url),o="There was no response from the server at "+i.url+". Check the url and internet connectivity.";e?(t.message=o,e(t)):console.error(o+"\n The error stack trace includes: \n"+t.stack)},o.send()}else if(void 0!==this.file){var r=new FileReader;r.onload=function(){i.panner&&f.decodeAudioData(r.result,function(e){i.panner&&(i.buffer=e,i.panner.inputChannels(e.numberOfChannels),t&&t(i))})},r.onerror=function(t){i.panner&&onerror&&onerror(t)},r.readAsArrayBuffer(this.file)}},t.SoundFile.prototype._updateProgress=function(t){if(t.lengthComputable){var e=t.loaded/t.total*.99;this._whileLoading(e,t)}else this._whileLoading("size unknown")},t.SoundFile.prototype.isLoaded=function(){return this.buffer?!0:!1},t.SoundFile.prototype.play=function(t,e,i,n,o){if(!this.output)return void console.warn("SoundFile.play() called after dispose");var r,s,a=l.audiocontext.currentTime,u=t||0;if(0>u&&(u=0),u+=a,"undefined"!=typeof e&&this.rate(e),"undefined"!=typeof i&&this.setVolume(i),!this.buffer)throw"not ready to play file, buffer has yet to load. Try preload()";if(this._pauseTime=0,"restart"===this.mode&&this.buffer&&this.bufferSourceNode&&(this.bufferSourceNode.stop(u),this._counterNode.stop(u)),"untildone"!==this.mode||!this.isPlaying()){if(this.bufferSourceNode=this._initSourceNode(),delete this._counterNode,this._counterNode=this._initCounterNode(),n){if(!(n>=0&&nt&&!this.reversed?(t=Math.abs(t),e=!0):t>0&&this.reversed&&(e=!0),this.bufferSourceNode){var i=l.audiocontext.currentTime;this.bufferSourceNode.playbackRate.cancelScheduledValues(i),this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(t),i),this._counterNode.playbackRate.cancelScheduledValues(i),this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(t),i)}return e&&this.reverseBuffer(),this.playbackRate},t.SoundFile.prototype.setPitch=function(t){var e=d(t)/d(60);this.rate(e)},t.SoundFile.prototype.getPlaybackRate=function(){return this.playbackRate},t.SoundFile.prototype.duration=function(){return this.buffer?this.buffer.duration:0},t.SoundFile.prototype.currentTime=function(){return this.reversed?Math.abs(this._lastPos-this.buffer.length)/f.sampleRate:this._lastPos/f.sampleRate},t.SoundFile.prototype.jump=function(t,e){if(0>t||t>this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var i=t||0,n=e||void 0;this.isPlaying()&&this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,i,n); -},t.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},t.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},t.SoundFile.prototype.frames=function(){return this.buffer.length},t.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t||(t=5*window.width),this.buffer){for(var e=this.buffer,i=e.length/t,n=~~(i/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;o>s;s++)for(var a=e.getChannelData(s),u=0;t>u;u++){for(var c=~~(u*i),p=~~(c+i),h=0,l=c;p>l;l+=n){var f=a[l];f>h?h=f:-f>h&&(h=f)}(0===s||Math.abs(h)>r[u])&&(r[u]=h)}return r}},t.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/f.sampleRate,e=this.getVolume();this.setVolume(0,.001);const i=this.buffer.numberOfChannels;for(var n=0;i>n;n++)this.buffer.getChannelData(n).reverse();this.reversed=!this.reversed,t&&this.jump(this.duration()-t),this.setVolume(e,.001)},t.SoundFile.prototype.onended=function(t){return this._onended=t,this},t.SoundFile.prototype.add=function(){},t.SoundFile.prototype.dispose=function(){var t=l.audiocontext.currentTime,e=l.soundArray.indexOf(this);if(l.soundArray.splice(e,1),this.stop(t),this.buffer&&this.bufferSourceNode){for(var i=0;io;o++){var r=n.getChannelData(o);r.set(t[o])}this.buffer=n,this.panner.inputChannels(e)};var y=function(t){const e=t.length,i=f.createBuffer(1,t.length,f.sampleRate),n=i.getChannelData(0);for(var o=0;e>o;o++)n[o]=o;return i};t.SoundFile.prototype._initCounterNode=function(){var e=this,i=f.currentTime,n=f.createBufferSource();return e._scopeNode&&(e._scopeNode.disconnect(),e._scopeNode.removeEventListener("audioprocess",e._onAudioProcess),delete e._scopeNode),e._scopeNode=f.createScriptProcessor(256,1,1),n.buffer=y(e.buffer),n.playbackRate.setValueAtTime(e.playbackRate,i),n.connect(e._scopeNode),e._scopeNode.connect(t.soundOut._silentNode),e._scopeNode.addEventListener("audioprocess",e._onAudioProcess),n},t.SoundFile.prototype._initSourceNode=function(){var t=f.createBufferSource();return t.buffer=this.buffer,t.playbackRate.value=this.playbackRate,t.connect(this.output),t},t.SoundFile.prototype.processPeaks=function(t,r,s,a){var u=this.buffer.length,c=this.buffer.sampleRate,p=this.buffer,h=[],l=r||.9,f=l,d=s||.22,m=a||200,y=new window.OfflineAudioContext(1,u,c),v=y.createBufferSource();v.buffer=p;var g=y.createBiquadFilter();g.type="lowpass",v.connect(g),g.connect(y.destination),v.start(0),y.startRendering(),y.oncomplete=function(r){if(self.panner){var s=r.renderedBuffer,a=s.getChannelData(0);do h=e(a,f),f-=.005;while(Object.keys(h).length=d);var u=i(h),c=n(u,s.sampleRate),p=c.sort(function(t,e){return e.count-t.count}).splice(0,5);this.tempo=p[0].tempo;var l=5,y=o(h,p[0].tempo,s.sampleRate,l);t(y)}}};var v=function(t,e){this.sampleIndex=e,this.amplitude=t,this.tempos=[],this.intervals=[]},g=function(t,e,i,n){this.callback=t,this.time=e,this.id=i,this.val=n};t.SoundFile.prototype.addCue=function(t,e,i){var n=this._cueIDCounter++,o=new g(e,t,n,i);return this._cues.push(o),n},t.SoundFile.prototype.removeCue=function(t){for(var e=this._cues.length,i=0;e>i;i++){var n=this._cues[i];if(n.id===t){this._cues.splice(i,1);break}}0===this._cues.length},t.SoundFile.prototype.clearCues=function(){this._cues=[]},t.SoundFile.prototype._onTimeUpdate=function(t){for(var e=t/this.buffer.sampleRate,i=this._cues.length,n=0;i>n;n++){var o=this._cues[n],r=o.time,s=o.val;this._prevTime=r&&o.callback(s)}this._prevTime=e},t.SoundFile.prototype.save=function(e){const i=m(this.buffer);t.prototype.saveSound([i],e,"wav")},t.SoundFile.prototype.getBlob=function(){const t=m(this.buffer);return new Blob([t],{type:"audio/wav"})}}(c,a,u,u);var l;l=function(){var e=a;t.Amplitude=function(t){this.bufferSize=2048,this.audiocontext=e.audiocontext,this.processor=this.audiocontext.createScriptProcessor(this.bufferSize,2,1),this.input=this.processor,this.output=this.audiocontext.createGain(),this.smoothing=t||0,this.volume=0,this.average=0,this.stereoVol=[0,0],this.stereoAvg=[0,0],this.stereoVolNorm=[0,0],this.volMax=.001,this.normalize=!1,this.processor.onaudioprocess=this._audioProcess.bind(this),this.processor.connect(this.output),this.output.gain.value=0,this.output.connect(this.audiocontext.destination),e.meter.connect(this.processor),e.soundArray.push(this)},t.Amplitude.prototype.setInput=function(i,n){e.meter.disconnect(),n&&(this.smoothing=n),null==i?(console.log("Amplitude input source is not ready! Connecting to master output instead"),e.meter.connect(this.processor)):i instanceof t.Signal?i.output.connect(this.processor):i?(i.connect(this.processor),this.processor.disconnect(),this.processor.connect(this.output)):e.meter.connect(this.processor)},t.Amplitude.prototype.connect=function(t){t?t.hasOwnProperty("input")?this.output.connect(t.input):this.output.connect(t):this.output.connect(this.panner.connect(e.input))},t.Amplitude.prototype.disconnect=function(){this.output&&this.output.disconnect()},t.Amplitude.prototype._audioProcess=function(t){for(var e=0;ea;a++)i=n[a],this.normalize?(r+=Math.max(Math.min(i/this.volMax,1),-1),s+=Math.max(Math.min(i/this.volMax,1),-1)*Math.max(Math.min(i/this.volMax,1),-1)):(r+=i,s+=i*i);var u=r/o,c=Math.sqrt(s/o);this.stereoVol[e]=Math.max(c,this.stereoVol[e]*this.smoothing),this.stereoAvg[e]=Math.max(u,this.stereoVol[e]*this.smoothing),this.volMax=Math.max(this.stereoVol[e],this.volMax)}var p=this,h=this.stereoVol.reduce(function(t,e,i){return p.stereoVolNorm[i-1]=Math.max(Math.min(p.stereoVol[i-1]/p.volMax,1),0),p.stereoVolNorm[i]=Math.max(Math.min(p.stereoVol[i]/p.volMax,1),0),t+e});this.volume=h/this.stereoVol.length,this.volNorm=Math.max(Math.min(this.volume/this.volMax,1),0)},t.Amplitude.prototype.getLevel=function(t){return"undefined"!=typeof t?this.normalize?this.stereoVolNorm[t]:this.stereoVol[t]:this.normalize?this.volNorm:this.volume},t.Amplitude.prototype.toggleNormalize=function(t){"boolean"==typeof t?this.normalize=t:this.normalize=!this.normalize},t.Amplitude.prototype.smooth=function(t){t>=0&&1>t?this.smoothing=t:console.log("Error: smoothing must be between 0 and 1")},t.Amplitude.prototype.dispose=function(){var t=e.soundArray.indexOf(this);e.soundArray.splice(t,1),this.input&&(this.input.disconnect(),delete this.input),this.output&&(this.output.disconnect(),delete this.output),delete this.processor}}(a);var f;f=function(){var e=a;t.FFT=function(t,i){this.input=this.analyser=e.audiocontext.createAnalyser(),Object.defineProperties(this,{bins:{get:function(){return this.analyser.fftSize/2},set:function(t){this.analyser.fftSize=2*t},configurable:!0,enumerable:!0},smoothing:{get:function(){return this.analyser.smoothingTimeConstant},set:function(t){this.analyser.smoothingTimeConstant=t},configurable:!0,enumerable:!0}}),this.smooth(t),this.bins=i||1024,e.fftMeter.connect(this.analyser),this.freqDomain=new Uint8Array(this.analyser.frequencyBinCount),this.timeDomain=new Uint8Array(this.analyser.frequencyBinCount),this.bass=[20,140],this.lowMid=[140,400],this.mid=[400,2600],this.highMid=[2600,5200],this.treble=[5200,14e3],e.soundArray.push(this)},t.FFT.prototype.setInput=function(t){t?(t.output?t.output.connect(this.analyser):t.connect&&t.connect(this.analyser),e.fftMeter.disconnect()):e.fftMeter.connect(this.analyser)},t.FFT.prototype.waveform=function(){for(var e,i,n,s=0;si){var o=i;i=t,t=o}for(var r=Math.round(t/n*this.freqDomain.length),s=Math.round(i/n*this.freqDomain.length),a=0,u=0,c=r;s>=c;c++)a+=this.freqDomain[c],u+=1;var p=a/u;return p}throw"invalid input for getEnergy()"}var h=Math.round(t/n*this.freqDomain.length);return this.freqDomain[h]},t.FFT.prototype.getFreq=function(t,e){console.log("getFreq() is deprecated. Please use getEnergy() instead.");var i=this.getEnergy(t,e);return i},t.FFT.prototype.getCentroid=function(){for(var t=e.audiocontext.sampleRate/2,i=0,n=0,o=0;os;s++)o[r]=void 0!==o[r]?(o[r]+e[s])/2:e[s],s%n===n-1&&r++;return o},t.FFT.prototype.logAverages=function(t){for(var i=e.audiocontext.sampleRate/2,n=this.freqDomain,o=n.length,r=new Array(t.length),s=0,a=0;o>a;a++){var u=Math.round(a*i/this.freqDomain.length);u>t[s].hi&&s++,r[s]=void 0!==r[s]?(r[s]+n[a])/2:n[a]}return r},t.FFT.prototype.getOctaveBands=function(t,i){var t=t||3,i=i||15.625,n=[],o={lo:i/Math.pow(2,1/(2*t)),ctr:i,hi:i*Math.pow(2,1/(2*t))};n.push(o);for(var r=e.audiocontext.sampleRate/2;o.hie;e++){var n=e/(i-1)*2-1;this._curve[e]=t(n,e)}return this._shaper.curve=this._curve,this},Object.defineProperty(t.WaveShaper.prototype,"curve",{get:function(){return this._shaper.curve},set:function(t){this._curve=new Float32Array(t),this._shaper.curve=this._curve}}),Object.defineProperty(t.WaveShaper.prototype,"oversample",{get:function(){return this._shaper.oversample},set:function(t){if(-1===["none","2x","4x"].indexOf(t))throw new RangeError("Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'");this._shaper.oversample=t}}),t.WaveShaper.prototype.dispose=function(){return t.prototype.dispose.call(this),this._shaper.disconnect(),this._shaper=null,this._curve=null,this},t.WaveShaper}(n);var y;y=function(t){return t.TimeBase=function(e,i){if(!(this instanceof t.TimeBase))return new t.TimeBase(e,i);if(this._expr=this._noOp,e instanceof t.TimeBase)this.copy(e);else if(!this.isUndef(i)||this.isNumber(e)){i=this.defaultArg(i,this._defaultUnits);var n=this._primaryExpressions[i].method;this._expr=n.bind(this,e)}else this.isString(e)?this.set(e):this.isUndef(e)&&(this._expr=this._defaultExpr())},t.extend(t.TimeBase),t.TimeBase.prototype.set=function(t){return this._expr=this._parseExprString(t),this},t.TimeBase.prototype.clone=function(){var t=new this.constructor;return t.copy(this),t},t.TimeBase.prototype.copy=function(t){var e=t._expr();return this.set(e)},t.TimeBase.prototype._primaryExpressions={n:{regexp:/^(\d+)n/i,method:function(t){return t=parseInt(t),1===t?this._beatsToUnits(this._timeSignature()):this._beatsToUnits(4/t)}},t:{regexp:/^(\d+)t/i,method:function(t){return t=parseInt(t),this._beatsToUnits(8/(3*parseInt(t)))}},m:{regexp:/^(\d+)m/i,method:function(t){return this._beatsToUnits(parseInt(t)*this._timeSignature())}},i:{regexp:/^(\d+)i/i,method:function(t){return this._ticksToUnits(parseInt(t))}},hz:{regexp:/^(\d+(?:\.\d+)?)hz/i,method:function(t){return this._frequencyToUnits(parseFloat(t))}},tr:{regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(t,e,i){var n=0;return t&&"0"!==t&&(n+=this._beatsToUnits(this._timeSignature()*parseFloat(t))),e&&"0"!==e&&(n+=this._beatsToUnits(parseFloat(e))),i&&"0"!==i&&(n+=this._beatsToUnits(parseFloat(i)/4)),n}},s:{regexp:/^(\d+(?:\.\d+)?s)/,method:function(t){return this._secondsToUnits(parseFloat(t))}},samples:{regexp:/^(\d+)samples/,method:function(t){return parseInt(t)/this.context.sampleRate}},"default":{regexp:/^(\d+(?:\.\d+)?)/,method:function(t){return this._primaryExpressions[this._defaultUnits].method.call(this,t)}}},t.TimeBase.prototype._binaryExpressions={"+":{regexp:/^\+/,precedence:2,method:function(t,e){return t()+e()}},"-":{regexp:/^\-/,precedence:2,method:function(t,e){return t()-e()}},"*":{regexp:/^\*/,precedence:1,method:function(t,e){return t()*e()}},"/":{regexp:/^\//,precedence:1,method:function(t,e){return t()/e()}}},t.TimeBase.prototype._unaryExpressions={neg:{regexp:/^\-/,method:function(t){return-t()}}},t.TimeBase.prototype._syntaxGlue={"(":{regexp:/^\(/},")":{regexp:/^\)/}},t.TimeBase.prototype._tokenize=function(t){function e(t,e){for(var i=["_binaryExpressions","_unaryExpressions","_primaryExpressions","_syntaxGlue"],n=0;n0;){t=t.trim();var o=e(t,this);n.push(o),t=t.substr(o.value.length)}return{next:function(){return n[++i]},peek:function(){return n[i+1]}}},t.TimeBase.prototype._matchGroup=function(t,e,i){var n=!1;if(!this.isUndef(t))for(var o in e){var r=e[o];if(r.regexp.test(t.value)){if(this.isUndef(i))return r;if(r.precedence===i)return r}}return n},t.TimeBase.prototype._parseBinary=function(t,e){this.isUndef(e)&&(e=2);var i;i=0>e?this._parseUnary(t):this._parseBinary(t,e-1);for(var n=t.peek();n&&this._matchGroup(n,this._binaryExpressions,e);)n=t.next(),i=n.method.bind(this,i,this._parseBinary(t,e-1)),n=t.peek();return i},t.TimeBase.prototype._parseUnary=function(t){var e,i;e=t.peek();var n=this._matchGroup(e,this._unaryExpressions);return n?(e=t.next(),i=this._parseUnary(t),n.method.bind(this,i)):this._parsePrimary(t)},t.TimeBase.prototype._parsePrimary=function(t){var e,i;if(e=t.peek(),this.isUndef(e))throw new SyntaxError("Tone.TimeBase: Unexpected end of expression");if(this._matchGroup(e,this._primaryExpressions)){e=t.next();var n=e.value.match(e.regexp);return e.method.bind(this,n[1],n[2],n[3])}if(e&&"("===e.value){if(t.next(),i=this._parseBinary(t),e=t.next(),!e||")"!==e.value)throw new SyntaxError("Expected )");return i}throw new SyntaxError("Tone.TimeBase: Cannot process token "+e.value)},t.TimeBase.prototype._parseExprString=function(t){this.isString(t)||(t=t.toString());var e=this._tokenize(t),i=this._parseBinary(e);return i},t.TimeBase.prototype._noOp=function(){return 0},t.TimeBase.prototype._defaultExpr=function(){return this._noOp},t.TimeBase.prototype._defaultUnits="s",t.TimeBase.prototype._frequencyToUnits=function(t){return 1/t},t.TimeBase.prototype._beatsToUnits=function(e){return 60/t.Transport.bpm.value*e},t.TimeBase.prototype._secondsToUnits=function(t){return t},t.TimeBase.prototype._ticksToUnits=function(e){return e*(this._beatsToUnits(1)/t.Transport.PPQ)},t.TimeBase.prototype._timeSignature=function(){return t.Transport.timeSignature},t.TimeBase.prototype._pushExpr=function(e,i,n){return e instanceof t.TimeBase||(e=new this.constructor(e,n)),this._expr=this._binaryExpressions[i].method.bind(this,this._expr,e._expr),this},t.TimeBase.prototype.add=function(t,e){return this._pushExpr(t,"+",e)},t.TimeBase.prototype.sub=function(t,e){return this._pushExpr(t,"-",e)},t.TimeBase.prototype.mult=function(t,e){return this._pushExpr(t,"*",e)},t.TimeBase.prototype.div=function(t,e){return this._pushExpr(t,"/",e)},t.TimeBase.prototype.valueOf=function(){return this._expr()},t.TimeBase.prototype.dispose=function(){this._expr=null},t.TimeBase}(n);var v;v=function(t){return t.Time=function(e,i){return this instanceof t.Time?(this._plusNow=!1,void t.TimeBase.call(this,e,i)):new t.Time(e,i)},t.extend(t.Time,t.TimeBase),t.Time.prototype._unaryExpressions=Object.create(t.TimeBase.prototype._unaryExpressions),t.Time.prototype._unaryExpressions.quantize={regexp:/^@/,method:function(e){return t.Transport.nextSubdivision(e())}},t.Time.prototype._unaryExpressions.now={regexp:/^\+/,method:function(t){return this._plusNow=!0,t()}},t.Time.prototype.quantize=function(t,e){return e=this.defaultArg(e,1),this._expr=function(t,e,i){t=t(),e=e.toSeconds();var n=Math.round(t/e),o=n*e,r=o-t;return t+r*i}.bind(this,this._expr,new this.constructor(t),e),this},t.Time.prototype.addNow=function(){return this._plusNow=!0,this},t.Time.prototype._defaultExpr=function(){return this._plusNow=!0,this._noOp},t.Time.prototype.copy=function(e){return t.TimeBase.prototype.copy.call(this,e),this._plusNow=e._plusNow,this},t.Time.prototype.toNotation=function(){var t=this.toSeconds(),e=["1m","2n","4n","8n","16n","32n","64n","128n"],i=this._toNotationHelper(t,e),n=["1m","2n","2t","4n","4t","8n","8t","16n","16t","32n","32t","64n","64t","128n"],o=this._toNotationHelper(t,n);return o.split("+").length1-s%1&&(s+=a),s=Math.floor(s),s>0){if(n+=1===s?e[o]:s.toString()+"*"+e[o],t-=s*r,i>t)break;n+=" + "}}return""===n&&(n="0"),n},t.Time.prototype._notationToUnits=function(t){for(var e=this._primaryExpressions,i=[e.n,e.t,e.m],n=0;n3&&(n=parseFloat(n).toFixed(3));var o=[i,e,n];return o.join(":")},t.Time.prototype.toTicks=function(){var e=this._beatsToUnits(1),i=this.valueOf()/e;return Math.floor(i*t.Transport.PPQ)},t.Time.prototype.toSamples=function(){return this.toSeconds()*this.context.sampleRate},t.Time.prototype.toFrequency=function(){return 1/this.toSeconds()},t.Time.prototype.toSeconds=function(){return this.valueOf()},t.Time.prototype.toMilliseconds=function(){return 1e3*this.toSeconds()},t.Time.prototype.valueOf=function(){var t=this._expr();return t+(this._plusNow?this.now():0)},t.Time}(n);var g;g=function(t){t.Frequency=function(e,i){return this instanceof t.Frequency?void t.TimeBase.call(this,e,i):new t.Frequency(e,i)},t.extend(t.Frequency,t.TimeBase),t.Frequency.prototype._primaryExpressions=Object.create(t.TimeBase.prototype._primaryExpressions),t.Frequency.prototype._primaryExpressions.midi={regexp:/^(\d+(?:\.\d+)?midi)/,method:function(t){return this.midiToFrequency(t)}},t.Frequency.prototype._primaryExpressions.note={regexp:/^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i,method:function(t,i){var n=e[t.toLowerCase()],o=n+12*(parseInt(i)+1);return this.midiToFrequency(o)}},t.Frequency.prototype._primaryExpressions.tr={regexp:/^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/,method:function(t,e,i){var n=1;return t&&"0"!==t&&(n*=this._beatsToUnits(this._timeSignature()*parseFloat(t))),e&&"0"!==e&&(n*=this._beatsToUnits(parseFloat(e))),i&&"0"!==i&&(n*=this._beatsToUnits(parseFloat(i)/4)),n}},t.Frequency.prototype.transpose=function(t){return this._expr=function(t,e){var i=t();return i*this.intervalToFrequencyRatio(e)}.bind(this,this._expr,t),this},t.Frequency.prototype.harmonize=function(t){return this._expr=function(t,e){for(var i=t(),n=[],o=0;or&&(o+=-12*r);var s=i[o%12];return s+r.toString()},t.Frequency.prototype.toSeconds=function(){return 1/this.valueOf()},t.Frequency.prototype.toFrequency=function(){return this.valueOf()},t.Frequency.prototype.toTicks=function(){var e=this._beatsToUnits(1),i=this.valueOf()/e;return Math.floor(i*t.Transport.PPQ)},t.Frequency.prototype._frequencyToUnits=function(t){return t},t.Frequency.prototype._ticksToUnits=function(e){return 1/(60*e/(t.Transport.bpm.value*t.Transport.PPQ))},t.Frequency.prototype._beatsToUnits=function(e){return 1/t.TimeBase.prototype._beatsToUnits.call(this,e)},t.Frequency.prototype._secondsToUnits=function(t){return 1/t},t.Frequency.prototype._defaultUnits="hz";var e={cbb:-2,cb:-1,c:0,"c#":1,cx:2,dbb:0,db:1,d:2,"d#":3,dx:4,ebb:2,eb:3,e:4,"e#":5,ex:6,fbb:3,fb:4,f:5,"f#":6,fx:7,gbb:5,gb:6,g:7,"g#":8,gx:9,abb:7,ab:8,a:9,"a#":10,ax:11,bbb:9,bb:10,b:11,"b#":12,bx:13},i=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];return t.Frequency.A4=440,t.Frequency.prototype.midiToFrequency=function(e){return t.Frequency.A4*Math.pow(2,(e-69)/12)},t.Frequency.prototype.frequencyToMidi=function(e){return 69+12*Math.log(e/t.Frequency.A4)/Math.LN2},t.Frequency}(n);var _;_=function(t){return t.TransportTime=function(e,i){return this instanceof t.TransportTime?void t.Time.call(this,e,i):new t.TransportTime(e,i)},t.extend(t.TransportTime,t.Time),t.TransportTime.prototype._unaryExpressions=Object.create(t.Time.prototype._unaryExpressions),t.TransportTime.prototype._unaryExpressions.quantize={regexp:/^@/,method:function(e){var i=this._secondsToTicks(e()),n=Math.ceil(t.Transport.ticks/i);return this._ticksToUnits(n*i)}},t.TransportTime.prototype._secondsToTicks=function(e){var i=this._beatsToUnits(1),n=e/i;return Math.round(n*t.Transport.PPQ)},t.TransportTime.prototype.valueOf=function(){var e=this._secondsToTicks(this._expr());return e+(this._plusNow?t.Transport.ticks:0)},t.TransportTime.prototype.toTicks=function(){return this.valueOf()},t.TransportTime.prototype.toSeconds=function(){var e=this._expr();return e+(this._plusNow?t.Transport.seconds:0)},t.TransportTime.prototype.toFrequency=function(){return 1/this.toSeconds()},t.TransportTime}(n);var T;T=function(t){return t.Type={Default:"number",Time:"time",Frequency:"frequency",TransportTime:"transportTime",Ticks:"ticks",NormalRange:"normalRange",AudioRange:"audioRange",Decibels:"db",Interval:"interval",BPM:"bpm",Positive:"positive",Cents:"cents",Degrees:"degrees",MIDI:"midi",BarsBeatsSixteenths:"barsBeatsSixteenths",Samples:"samples",Hertz:"hertz",Note:"note",Milliseconds:"milliseconds",Seconds:"seconds",Notation:"notation"},t.prototype.toSeconds=function(e){return this.isNumber(e)?e:this.isUndef(e)?this.now():this.isString(e)?new t.Time(e).toSeconds():e instanceof t.TimeBase?e.toSeconds():void 0},t.prototype.toFrequency=function(e){return this.isNumber(e)?e:this.isString(e)||this.isUndef(e)?new t.Frequency(e).valueOf():e instanceof t.TimeBase?e.toFrequency():void 0},t.prototype.toTicks=function(e){return this.isNumber(e)||this.isString(e)?new t.TransportTime(e).toTicks():this.isUndef(e)?t.Transport.ticks:e instanceof t.TimeBase?e.toTicks():void 0},t}(n,v,g,_);var b;b=function(t){"use strict";return t.Param=function(){var e=this.optionsObject(arguments,["param","units","convert"],t.Param.defaults);this._param=this.input=e.param,this.units=e.units,this.convert=e.convert,this.overridden=!1,this._lfo=null,this.isObject(e.lfo)?this.value=e.lfo:this.isUndef(e.value)||(this.value=e.value)},t.extend(t.Param),t.Param.defaults={units:t.Type.Default,convert:!0,param:void 0},Object.defineProperty(t.Param.prototype,"value",{get:function(){return this._toUnits(this._param.value)},set:function(e){if(this.isObject(e)){if(this.isUndef(t.LFO))throw new Error("Include 'Tone.LFO' to use an LFO as a Param value.");this._lfo&&this._lfo.dispose(),this._lfo=new t.LFO(e).start(),this._lfo.connect(this.input)}else{var i=this._fromUnits(e);this._param.cancelScheduledValues(0),this._param.value=i}}}),t.Param.prototype._fromUnits=function(e){if(!this.convert&&!this.isUndef(this.convert))return e;switch(this.units){case t.Type.Time:return this.toSeconds(e);case t.Type.Frequency:return this.toFrequency(e);case t.Type.Decibels:return this.dbToGain(e);case t.Type.NormalRange:return Math.min(Math.max(e,0),1);case t.Type.AudioRange:return Math.min(Math.max(e,-1),1);case t.Type.Positive:return Math.max(e,0);default:return e}},t.Param.prototype._toUnits=function(e){if(!this.convert&&!this.isUndef(this.convert))return e;switch(this.units){case t.Type.Decibels:return this.gainToDb(e);default:return e}},t.Param.prototype._minOutput=1e-5,t.Param.prototype.setValueAtTime=function(t,e){return t=this._fromUnits(t),e=this.toSeconds(e),e<=this.now()+this.blockTime?this._param.value=t:this._param.setValueAtTime(t,e),this},t.Param.prototype.setRampPoint=function(t){t=this.defaultArg(t,this.now());var e=this._param.value;return 0===e&&(e=this._minOutput),this._param.setValueAtTime(e,t),this},t.Param.prototype.linearRampToValueAtTime=function(t,e){return t=this._fromUnits(t),this._param.linearRampToValueAtTime(t,this.toSeconds(e)),this},t.Param.prototype.exponentialRampToValueAtTime=function(t,e){return t=this._fromUnits(t),t=Math.max(this._minOutput,t),this._param.exponentialRampToValueAtTime(t,this.toSeconds(e)),this},t.Param.prototype.exponentialRampToValue=function(t,e,i){return i=this.toSeconds(i),this.setRampPoint(i),this.exponentialRampToValueAtTime(t,i+this.toSeconds(e)),this},t.Param.prototype.linearRampToValue=function(t,e,i){return i=this.toSeconds(i),this.setRampPoint(i),this.linearRampToValueAtTime(t,i+this.toSeconds(e)),this},t.Param.prototype.setTargetAtTime=function(t,e,i){return t=this._fromUnits(t),t=Math.max(this._minOutput,t),i=Math.max(this._minOutput,i),this._param.setTargetAtTime(t,this.toSeconds(e),i),this},t.Param.prototype.setValueCurveAtTime=function(t,e,i){for(var n=0;n1&&(this.input=new Array(e)),1===i?this.output=new t.Gain:i>1&&(this.output=new Array(e))},t.Gain}(n,b);var S;S=function(t){"use strict";return t.Signal=function(){var e=this.optionsObject(arguments,["value","units"],t.Signal.defaults);this.output=this._gain=this.context.createGain(),e.param=this._gain.gain,t.Param.call(this,e),this.input=this._param=this._gain.gain,this.context.getConstant(1).chain(this._gain)},t.extend(t.Signal,t.Param),t.Signal.defaults={value:0,units:t.Type.Default,convert:!0},t.Signal.prototype.connect=t.SignalBase.prototype.connect,t.Signal.prototype.dispose=function(){return t.Param.prototype.dispose.call(this),this._param=null,this._gain.disconnect(),this._gain=null,this},t.Signal}(n,m,T,b);var w;w=function(t){"use strict";return t.Add=function(e){this.createInsOuts(2,0),this._sum=this.input[0]=this.input[1]=this.output=new t.Gain,this._param=this.input[1]=new t.Signal(e),this._param.connect(this._sum)},t.extend(t.Add,t.Signal),t.Add.prototype.dispose=function(){return t.prototype.dispose.call(this),this._sum.dispose(),this._sum=null,this._param.dispose(),this._param=null,this},t.Add}(n,S);var A;A=function(t){"use strict";return t.Multiply=function(e){this.createInsOuts(2,0),this._mult=this.input[0]=this.output=new t.Gain,this._param=this.input[1]=this.output.gain,this._param.value=this.defaultArg(e,0)},t.extend(t.Multiply,t.Signal),t.Multiply.prototype.dispose=function(){return t.prototype.dispose.call(this),this._mult.dispose(),this._mult=null, -this._param=null,this},t.Multiply}(n,S);var P;P=function(t){"use strict";return t.Scale=function(e,i){this._outputMin=this.defaultArg(e,0),this._outputMax=this.defaultArg(i,1),this._scale=this.input=new t.Multiply(1),this._add=this.output=new t.Add(0),this._scale.connect(this._add),this._setRange()},t.extend(t.Scale,t.SignalBase),Object.defineProperty(t.Scale.prototype,"min",{get:function(){return this._outputMin},set:function(t){this._outputMin=t,this._setRange()}}),Object.defineProperty(t.Scale.prototype,"max",{get:function(){return this._outputMax},set:function(t){this._outputMax=t,this._setRange()}}),t.Scale.prototype._setRange=function(){this._add.value=this._outputMin,this._scale.value=this._outputMax-this._outputMin},t.Scale.prototype.dispose=function(){return t.prototype.dispose.call(this),this._add.dispose(),this._add=null,this._scale.dispose(),this._scale=null,this},t.Scale}(n,w,A);var k;k=function(){var e=S,i=w,n=A,o=P;t.Signal=function(t){var i=new e(t);return i},e.prototype.fade=e.prototype.linearRampToValueAtTime,n.prototype.fade=e.prototype.fade,i.prototype.fade=e.prototype.fade,o.prototype.fade=e.prototype.fade,e.prototype.setInput=function(t){t.connect(this)},n.prototype.setInput=e.prototype.setInput,i.prototype.setInput=e.prototype.setInput,o.prototype.setInput=e.prototype.setInput,e.prototype.add=function(t){var e=new i(t);return this.connect(e),e},n.prototype.add=e.prototype.add,i.prototype.add=e.prototype.add,o.prototype.add=e.prototype.add,e.prototype.mult=function(t){var e=new n(t);return this.connect(e),e},n.prototype.mult=e.prototype.mult,i.prototype.mult=e.prototype.mult,o.prototype.mult=e.prototype.mult,e.prototype.scale=function(e,i,n,r){var s,a;4===arguments.length?(s=t.prototype.map(n,e,i,0,1)-.5,a=t.prototype.map(r,e,i,0,1)-.5):(s=arguments[0],a=arguments[1]);var u=new o(s,a);return this.connect(u),u},n.prototype.scale=e.prototype.scale,i.prototype.scale=e.prototype.scale,o.prototype.scale=e.prototype.scale}(S,w,A,P);var O;O=function(){var e=a,i=w,n=A,o=P;t.Oscillator=function(i,n){if("string"==typeof i){var o=n;n=i,i=o}if("number"==typeof n){var o=n;n=i,i=o}this.started=!1,this.phaseAmount=void 0,this.oscillator=e.audiocontext.createOscillator(),this.f=i||440,this.oscillator.type=n||"sine",this.oscillator.frequency.setValueAtTime(this.f,e.audiocontext.currentTime),this.output=e.audiocontext.createGain(),this._freqMods=[],this.output.gain.value=.5,this.output.gain.setValueAtTime(.5,e.audiocontext.currentTime),this.oscillator.connect(this.output),this.panPosition=0,this.connection=e.input,this.panner=new t.Panner(this.output,this.connection,1),this.mathOps=[this.output],e.soundArray.push(this)},t.Oscillator.prototype.start=function(t,i){if(this.started){var n=e.audiocontext.currentTime;this.stop(n)}if(!this.started){var o=i||this.f,r=this.oscillator.type;this.oscillator&&(this.oscillator.disconnect(),delete this.oscillator),this.oscillator=e.audiocontext.createOscillator(),this.oscillator.frequency.value=Math.abs(o),this.oscillator.type=r,this.oscillator.connect(this.output),t=t||0,this.oscillator.start(t+e.audiocontext.currentTime),this.freqNode=this.oscillator.frequency;for(var s in this._freqMods)"undefined"!=typeof this._freqMods[s].connect&&this._freqMods[s].connect(this.oscillator.frequency);this.started=!0}},t.Oscillator.prototype.stop=function(t){if(this.started){var i=t||0,n=e.audiocontext.currentTime;this.oscillator.stop(i+n),this.started=!1}},t.Oscillator.prototype.amp=function(t,i,n){var o=this;if("number"==typeof t){var i=i||0,n=n||0,r=e.audiocontext.currentTime;this.output.gain.linearRampToValueAtTime(t,r+n+i)}else{if(!t)return this.output.gain;t.connect(o.output.gain)}},t.Oscillator.prototype.fade=t.Oscillator.prototype.amp,t.Oscillator.prototype.getAmp=function(){return this.output.gain.value},t.Oscillator.prototype.freq=function(t,i,n){if("number"!=typeof t||isNaN(t)){if(!t)return this.oscillator.frequency;t.output&&(t=t.output),t.connect(this.oscillator.frequency),this._freqMods.push(t)}else{this.f=t;var o=e.audiocontext.currentTime,i=i||0,n=n||0;0===i?this.oscillator.frequency.setValueAtTime(t,n+o):t>0?this.oscillator.frequency.exponentialRampToValueAtTime(t,n+i+o):this.oscillator.frequency.linearRampToValueAtTime(t,n+i+o),this.phaseAmount&&this.phase(this.phaseAmount)}},t.Oscillator.prototype.getFreq=function(){return this.oscillator.frequency.value},t.Oscillator.prototype.setType=function(t){this.oscillator.type=t},t.Oscillator.prototype.getType=function(){return this.oscillator.type},t.Oscillator.prototype.connect=function(t){t?t.hasOwnProperty("input")?(this.panner.connect(t.input),this.connection=t.input):(this.panner.connect(t),this.connection=t):this.panner.connect(e.input)},t.Oscillator.prototype.disconnect=function(){this.output&&this.output.disconnect(),this.panner&&(this.panner.disconnect(),this.output&&this.output.connect(this.panner)),this.oscMods=[]},t.Oscillator.prototype.pan=function(t,e){this.panPosition=t,this.panner.pan(t,e)},t.Oscillator.prototype.getPan=function(){return this.panPosition},t.Oscillator.prototype.dispose=function(){var t=e.soundArray.indexOf(this);if(e.soundArray.splice(t,1),this.oscillator){var i=e.audiocontext.currentTime;this.stop(i),this.disconnect(),this.panner=null,this.oscillator=null}this.osc2&&this.osc2.dispose()},t.Oscillator.prototype.phase=function(i){var n=t.prototype.map(i,0,1,0,1/this.f),o=e.audiocontext.currentTime;this.phaseAmount=i,this.dNode||(this.dNode=e.audiocontext.createDelay(),this.oscillator.disconnect(),this.oscillator.connect(this.dNode),this.dNode.connect(this.output)),this.dNode.delayTime.setValueAtTime(n,o)};var r=function(t,e,i,n,o){var r=t.oscillator;for(var s in t.mathOps)t.mathOps[s]instanceof o&&(r.disconnect(),t.mathOps[s].dispose(),i=s,i0&&(r=t.mathOps[s-1]),r.disconnect(),r.connect(e),e.connect(n),t.mathOps[i]=e,t};t.Oscillator.prototype.add=function(t){var e=new i(t),n=this.mathOps.length-1,o=this.output;return r(this,e,n,o,i)},t.Oscillator.prototype.mult=function(t){var e=new n(t),i=this.mathOps.length-1,o=this.output;return r(this,e,i,o,n)},t.Oscillator.prototype.scale=function(e,i,n,s){var a,u;4===arguments.length?(a=t.prototype.map(n,e,i,0,1)-.5,u=t.prototype.map(s,e,i,0,1)-.5):(a=arguments[0],u=arguments[1]);var c=new o(a,u),p=this.mathOps.length-1,h=this.output;return r(this,c,p,h,o)},t.SinOsc=function(e){t.Oscillator.call(this,e,"sine")},t.SinOsc.prototype=Object.create(t.Oscillator.prototype),t.TriOsc=function(e){t.Oscillator.call(this,e,"triangle")},t.TriOsc.prototype=Object.create(t.Oscillator.prototype),t.SawOsc=function(e){t.Oscillator.call(this,e,"sawtooth")},t.SawOsc.prototype=Object.create(t.Oscillator.prototype),t.SqrOsc=function(e){t.Oscillator.call(this,e,"square")},t.SqrOsc.prototype=Object.create(t.Oscillator.prototype)}(a,w,A,P);var F;F=function(t){"use strict";return t.Timeline=function(){var e=this.optionsObject(arguments,["memory"],t.Timeline.defaults);this._timeline=[],this._toRemove=[],this._iterating=!1,this.memory=e.memory},t.extend(t.Timeline),t.Timeline.defaults={memory:1/0},Object.defineProperty(t.Timeline.prototype,"length",{get:function(){return this._timeline.length}}),t.Timeline.prototype.add=function(t){if(this.isUndef(t.time))throw new Error("Tone.Timeline: events must have a time attribute");if(this._timeline.length){var e=this._search(t.time);this._timeline.splice(e+1,0,t)}else this._timeline.push(t);if(this.length>this.memory){var i=this.length-this.memory;this._timeline.splice(0,i)}return this},t.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},t.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},t.Timeline.prototype.peek=function(){return this._timeline[0]},t.Timeline.prototype.shift=function(){return this._timeline.shift()},t.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+10&&this._timeline[e-1].time=0?this._timeline[i-1]:null},t.Timeline.prototype.cancel=function(t){if(this._timeline.length>1){var e=this._search(t);if(e>=0)if(this._timeline[e].time===t){for(var i=e;i>=0&&this._timeline[i].time===t;i--)e=i;this._timeline=this._timeline.slice(0,e)}else this._timeline=this._timeline.slice(0,e+1);else this._timeline=[]}else 1===this._timeline.length&&this._timeline[0].time>=t&&(this._timeline=[]);return this},t.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);e>=0&&(this._timeline=this._timeline.slice(e+1))}return this},t.Timeline.prototype._search=function(t){var e=0,i=this._timeline.length,n=i;if(i>0&&this._timeline[i-1].time<=t)return i-1;for(;n>e;){var o=Math.floor(e+(n-e)/2),r=this._timeline[o],s=this._timeline[o+1];if(r.time===t){for(var a=o;at)return o;r.time>t?n=o:r.time=n;n++)t(this._timeline[n]);if(this._iterating=!1,this._toRemove.length>0){for(var o=0;o=0&&this._timeline[i].time>=t;)i--;return this._iterate(e,i+1),this},t.Timeline.prototype.forEachAtTime=function(t,e){var i=this._search(t);return-1!==i&&this._iterate(function(i){i.time===t&&e(i)},0,i),this},t.Timeline.prototype.dispose=function(){t.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},t.Timeline}(n);var q;q=function(t){"use strict";return t.TimelineSignal=function(){var e=this.optionsObject(arguments,["value","units"],t.Signal.defaults);this._events=new t.Timeline(10),t.Signal.apply(this,e),e.param=this._param,t.Param.call(this,e),this._initial=this._fromUnits(this._param.value)},t.extend(t.TimelineSignal,t.Param),t.TimelineSignal.Type={Linear:"linear",Exponential:"exponential",Target:"target",Curve:"curve",Set:"set"},Object.defineProperty(t.TimelineSignal.prototype,"value",{get:function(){var t=this.now(),e=this.getValueAtTime(t);return this._toUnits(e)},set:function(t){var e=this._fromUnits(t);this._initial=e,this.cancelScheduledValues(),this._param.value=e}}),t.TimelineSignal.prototype.setValueAtTime=function(e,i){return e=this._fromUnits(e),i=this.toSeconds(i),this._events.add({type:t.TimelineSignal.Type.Set,value:e,time:i}),this._param.setValueAtTime(e,i),this},t.TimelineSignal.prototype.linearRampToValueAtTime=function(e,i){return e=this._fromUnits(e),i=this.toSeconds(i),this._events.add({type:t.TimelineSignal.Type.Linear,value:e,time:i}),this._param.linearRampToValueAtTime(e,i),this},t.TimelineSignal.prototype.exponentialRampToValueAtTime=function(e,i){i=this.toSeconds(i);var n=this._searchBefore(i);n&&0===n.value&&this.setValueAtTime(this._minOutput,n.time),e=this._fromUnits(e);var o=Math.max(e,this._minOutput);return this._events.add({type:t.TimelineSignal.Type.Exponential,value:o,time:i}),ee)this.cancelScheduledValues(e),this.linearRampToValueAtTime(i,e);else{var o=this._searchAfter(e);o&&(this.cancelScheduledValues(e),o.type===t.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(i,e):o.type===t.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(i,e)),this.setValueAtTime(i,e)}return this},t.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.linearRampToValueAtTime(t,i),this},t.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,i){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,i),this},t.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},t.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},t.TimelineSignal.prototype.getValueAtTime=function(e){e=this.toSeconds(e);var i=this._searchAfter(e),n=this._searchBefore(e),o=this._initial;if(null===n)o=this._initial;else if(n.type===t.TimelineSignal.Type.Target){var r,s=this._events.getBefore(n.time);r=null===s?this._initial:s.value,o=this._exponentialApproach(n.time,r,n.value,n.constant,e)}else o=n.type===t.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,e):null===i?n.value:i.type===t.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,i.time,i.value,e):i.type===t.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,i.time,i.value,e):n.value;return o},t.TimelineSignal.prototype.connect=t.SignalBase.prototype.connect,t.TimelineSignal.prototype._exponentialApproach=function(t,e,i,n,o){return i+(e-i)*Math.exp(-(o-t)/n)},t.TimelineSignal.prototype._linearInterpolate=function(t,e,i,n,o){return e+(n-e)*((o-t)/(i-t))},t.TimelineSignal.prototype._exponentialInterpolate=function(t,e,i,n,o){return e=Math.max(this._minOutput,e),e*Math.pow(n/e,(o-t)/(i-t))},t.TimelineSignal.prototype._curveInterpolate=function(t,e,i,n){var o=e.length;if(n>=t+i)return e[o-1];if(t>=n)return e[0];var r=(n-t)/i,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),u=e[s],c=e[a];return a===s?u:this._linearInterpolate(s,u,a,c,r*(o-1))},t.TimelineSignal.prototype.dispose=function(){t.Signal.prototype.dispose.call(this),t.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},t.TimelineSignal}(n,S);var M;M=function(){var e=a,i=w,n=A,o=P,r=q;t.Envelope=function(t,i,n,o,s,a){this.aTime=t||.1,this.aLevel=i||1,this.dTime=n||.5,this.dLevel=o||0,this.rTime=s||0,this.rLevel=a||0,this._rampHighPercentage=.98,this._rampLowPercentage=.02,this.output=e.audiocontext.createGain(),this.control=new r,this._init(),this.control.connect(this.output),this.connection=null,this.mathOps=[this.control],this.isExponential=!1,this.sourceToClear=null,this.wasTriggered=!1,e.soundArray.push(this)},t.Envelope.prototype._init=function(){var t=e.audiocontext.currentTime,i=t;this.control.setTargetAtTime(1e-5,i,.001),this._setRampAD(this.aTime,this.dTime)},t.Envelope.prototype.set=function(t,e,i,n,o,r){this.aTime=t,this.aLevel=e,this.dTime=i||0,this.dLevel=n||0,this.rTime=o||0,this.rLevel=r||0,this._setRampAD(t,i)},t.Envelope.prototype.setADSR=function(t,e,i,n){this.aTime=t,this.dTime=e||0,this.sPercent=i||0,this.dLevel="undefined"!=typeof i?i*(this.aLevel-this.rLevel)+this.rLevel:0,this.rTime=n||0,this._setRampAD(t,e)},t.Envelope.prototype.setRange=function(t,e){this.aLevel=t||1,this.rLevel=e||0},t.Envelope.prototype._setRampAD=function(t,e){this._rampAttackTime=this.checkExpInput(t),this._rampDecayTime=this.checkExpInput(e);var i=1;i=Math.log(1/this.checkExpInput(1-this._rampHighPercentage)),this._rampAttackTC=t/this.checkExpInput(i),i=Math.log(1/this._rampLowPercentage),this._rampDecayTC=e/this.checkExpInput(i)},t.Envelope.prototype.setRampPercentages=function(t,e){this._rampHighPercentage=this.checkExpInput(t),this._rampLowPercentage=this.checkExpInput(e);var i=1;i=Math.log(1/this.checkExpInput(1-this._rampHighPercentage)),this._rampAttackTC=this._rampAttackTime/this.checkExpInput(i),i=Math.log(1/this._rampLowPercentage),this._rampDecayTC=this._rampDecayTime/this.checkExpInput(i)},t.Envelope.prototype.setInput=function(){for(var t=0;t=t&&(t=1e-8),t},t.Envelope.prototype.play=function(t,e,i){var n=e||0,i=i||0;t&&this.connection!==t&&this.connect(t),this.triggerAttack(t,n),this.triggerRelease(t,n+this.aTime+this.dTime+i)},t.Envelope.prototype.triggerAttack=function(t,i){var n=e.audiocontext.currentTime,o=i||0,r=n+o;this.lastAttack=r,this.wasTriggered=!0,t&&this.connection!==t&&this.connect(t);var s=this.control.getValueAtTime(r);this.isExponential===!0?this.control.exponentialRampToValueAtTime(this.checkExpInput(s),r):this.control.linearRampToValueAtTime(s,r),r+=this.aTime,this.isExponential===!0?(this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel),r),s=this.checkExpInput(this.control.getValueAtTime(r)),this.control.cancelScheduledValues(r),this.control.exponentialRampToValueAtTime(s,r)):(this.control.linearRampToValueAtTime(this.aLevel,r),s=this.control.getValueAtTime(r),this.control.cancelScheduledValues(r),this.control.linearRampToValueAtTime(s,r)),r+=this.dTime,this.isExponential===!0?(this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel),r),s=this.checkExpInput(this.control.getValueAtTime(r)),this.control.cancelScheduledValues(r),this.control.exponentialRampToValueAtTime(s,r)):(this.control.linearRampToValueAtTime(this.dLevel,r),s=this.control.getValueAtTime(r),this.control.cancelScheduledValues(r),this.control.linearRampToValueAtTime(s,r))},t.Envelope.prototype.triggerRelease=function(t,i){if(this.wasTriggered){var n=e.audiocontext.currentTime,o=i||0,r=n+o;t&&this.connection!==t&&this.connect(t);var s=this.control.getValueAtTime(r);this.isExponential===!0?this.control.exponentialRampToValueAtTime(this.checkExpInput(s),r):this.control.linearRampToValueAtTime(s,r),r+=this.rTime,this.isExponential===!0?(this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel),r),s=this.checkExpInput(this.control.getValueAtTime(r)),this.control.cancelScheduledValues(r),this.control.exponentialRampToValueAtTime(s,r)):(this.control.linearRampToValueAtTime(this.rLevel,r),s=this.control.getValueAtTime(r),this.control.cancelScheduledValues(r),this.control.linearRampToValueAtTime(s,r)),this.wasTriggered=!1}},t.Envelope.prototype.ramp=function(t,i,n,o){var r=e.audiocontext.currentTime,s=i||0,a=r+s,u=this.checkExpInput(n),c="undefined"!=typeof o?this.checkExpInput(o):void 0;t&&this.connection!==t&&this.connect(t);var p=this.checkExpInput(this.control.getValueAtTime(a));u>p?(this.control.setTargetAtTime(u,a,this._rampAttackTC),a+=this._rampAttackTime):p>u&&(this.control.setTargetAtTime(u,a,this._rampDecayTC),a+=this._rampDecayTime),void 0!==c&&(c>u?this.control.setTargetAtTime(c,a,this._rampAttackTC):u>c&&this.control.setTargetAtTime(c,a,this._rampDecayTC))},t.Envelope.prototype.connect=function(i){this.connection=i,(i instanceof t.Oscillator||i instanceof t.SoundFile||i instanceof t.AudioIn||i instanceof t.Reverb||i instanceof t.Noise||i instanceof t.Filter||i instanceof t.Delay)&&(i=i.output.gain),i instanceof AudioParam&&i.setValueAtTime(0,e.audiocontext.currentTime),i instanceof t.Signal&&i.setValue(0),this.output.connect(i)},t.Envelope.prototype.disconnect=function(){this.output&&this.output.disconnect()},t.Envelope.prototype.add=function(e){var n=new i(e),o=this.mathOps.length,r=this.output;return t.prototype._mathChain(this,n,o,r,i)},t.Envelope.prototype.mult=function(e){var i=new n(e),o=this.mathOps.length,r=this.output;return t.prototype._mathChain(this,i,o,r,n)},t.Envelope.prototype.scale=function(e,i,n,r){var s=new o(e,i,n,r),a=this.mathOps.length,u=this.output;return t.prototype._mathChain(this,s,a,u,o)},t.Envelope.prototype.dispose=function(){var t=e.soundArray.indexOf(this);e.soundArray.splice(t,1),this.disconnect(),this.control&&(this.control.dispose(),this.control=null);for(var i=1;io;o++)n[o]=1;var r=t.createBufferSource();return r.buffer=e,r.loop=!0,r}var i=a;t.Pulse=function(n,o){t.Oscillator.call(this,n,"sawtooth"),this.w=o||0,this.osc2=new t.SawOsc(n),this.dNode=i.audiocontext.createDelay(),this.dcOffset=e(),this.dcGain=i.audiocontext.createGain(),this.dcOffset.connect(this.dcGain),this.dcGain.connect(this.output),this.f=n||440;var r=this.w/this.oscillator.frequency.value;this.dNode.delayTime.value=r,this.dcGain.gain.value=1.7*(.5-this.w),this.osc2.disconnect(),this.osc2.panner.disconnect(),this.osc2.amp(-1),this.osc2.output.connect(this.dNode),this.dNode.connect(this.output),this.output.gain.value=1,this.output.connect(this.panner)},t.Pulse.prototype=Object.create(t.Oscillator.prototype),t.Pulse.prototype.width=function(e){if("number"==typeof e){if(1>=e&&e>=0){this.w=e;var i=this.w/this.oscillator.frequency.value;this.dNode.delayTime.value=i}this.dcGain.gain.value=1.7*(.5-this.w)}else{e.connect(this.dNode.delayTime);var n=new t.SignalAdd(-.5);n.setInput(e),n=n.mult(-1),n=n.mult(1.7),n.connect(this.dcGain.gain)}},t.Pulse.prototype.start=function(t,n){var o=i.audiocontext.currentTime,r=n||0;if(!this.started){var s=t||this.f,a=this.oscillator.type;this.oscillator=i.audiocontext.createOscillator(),this.oscillator.frequency.setValueAtTime(s,o),this.oscillator.type=a,this.oscillator.connect(this.output),this.oscillator.start(r+o),this.osc2.oscillator=i.audiocontext.createOscillator(),this.osc2.oscillator.frequency.setValueAtTime(s,r+o),this.osc2.oscillator.type=a,this.osc2.oscillator.connect(this.osc2.output),this.osc2.start(r+o),this.freqNode=[this.oscillator.frequency,this.osc2.oscillator.frequency],this.dcOffset=e(),this.dcOffset.connect(this.dcGain),this.dcOffset.start(r+o),void 0!==this.mods&&void 0!==this.mods.frequency&&(this.mods.frequency.connect(this.freqNode[0]),this.mods.frequency.connect(this.freqNode[1])),this.started=!0,this.osc2.started=!0}},t.Pulse.prototype.stop=function(t){if(this.started){var e=t||0,n=i.audiocontext.currentTime;this.oscillator.stop(e+n),this.osc2.oscillator&&this.osc2.oscillator.stop(e+n),this.dcOffset.stop(e+n),this.started=!1,this.osc2.started=!1}},t.Pulse.prototype.freq=function(t,e,n){if("number"==typeof t){this.f=t;var o=i.audiocontext.currentTime,e=e||0,n=n||0,r=this.oscillator.frequency.value;this.oscillator.frequency.cancelScheduledValues(o),this.oscillator.frequency.setValueAtTime(r,o+n),this.oscillator.frequency.exponentialRampToValueAtTime(t,n+e+o),this.osc2.oscillator.frequency.cancelScheduledValues(o),this.osc2.oscillator.frequency.setValueAtTime(r,o+n),this.osc2.oscillator.frequency.exponentialRampToValueAtTime(t,n+e+o),this.freqMod&&(this.freqMod.output.disconnect(),this.freqMod=null)}else t.output&&(t.output.disconnect(),t.output.connect(this.oscillator.frequency),t.output.connect(this.osc2.oscillator.frequency),this.freqMod=t)}}(a,O);var V;V=function(){var e=a;t.Noise=function(e){var r;t.Oscillator.call(this),delete this.f,delete this.freq,delete this.oscillator,r="brown"===e?o:"pink"===e?n:i,this.buffer=r},t.Noise.prototype=Object.create(t.Oscillator.prototype);var i=function(){for(var t=2*e.audiocontext.sampleRate,i=e.audiocontext.createBuffer(1,t,e.audiocontext.sampleRate),n=i.getChannelData(0),o=0;t>o;o++)n[o]=2*Math.random()-1;return i.type="white",i}(),n=function(){var t,i,n,o,r,s,a,u=2*e.audiocontext.sampleRate,c=e.audiocontext.createBuffer(1,u,e.audiocontext.sampleRate),p=c.getChannelData(0);t=i=n=o=r=s=a=0;for(var h=0;u>h;h++){var l=2*Math.random()-1;t=.99886*t+.0555179*l,i=.99332*i+.0750759*l,n=.969*n+.153852*l,o=.8665*o+.3104856*l,r=.55*r+.5329522*l,s=-.7616*s-.016898*l,p[h]=t+i+n+o+r+s+a+.5362*l,p[h]*=.11,a=.115926*l}return c.type="pink",c}(),o=function(){for(var t=2*e.audiocontext.sampleRate,i=e.audiocontext.createBuffer(1,t,e.audiocontext.sampleRate),n=i.getChannelData(0),o=0,r=0;t>r;r++){var s=2*Math.random()-1;n[r]=(o+.02*s)/1.02,o=n[r],n[r]*=3.5}return i.type="brown",i}();t.Noise.prototype.setType=function(t){switch(t){case"white":this.buffer=i;break;case"pink":this.buffer=n;break;case"brown":this.buffer=o;break;default:this.buffer=i}if(this.started){var r=e.audiocontext.currentTime;this.stop(r),this.start(r+.01)}},t.Noise.prototype.getType=function(){return this.buffer.type},t.Noise.prototype.start=function(){this.started&&this.stop(),this.noise=e.audiocontext.createBufferSource(),this.noise.buffer=this.buffer,this.noise.loop=!0,this.noise.connect(this.output);var t=e.audiocontext.currentTime;this.noise.start(t),this.started=!0},t.Noise.prototype.stop=function(){var t=e.audiocontext.currentTime;this.noise&&(this.noise.stop(t),this.started=!1)},t.Noise.prototype.dispose=function(){var t=e.audiocontext.currentTime,i=e.soundArray.indexOf(this);e.soundArray.splice(i,1),this.noise&&(this.noise.disconnect(),this.stop(t)),this.output&&this.output.disconnect(),this.panner&&this.panner.disconnect(),this.output=null,this.panner=null,this.buffer=null,this.noise=null}}(a);var R;R=function(){var e=a;e.inputSources=[],t.AudioIn=function(i){this.input=e.audiocontext.createGain(),this.output=e.audiocontext.createGain(),this.stream=null,this.mediaStream=null,this.currentSource=null,this.enabled=!1,this.amplitude=new t.Amplitude,this.output.connect(this.amplitude.input),window.MediaStreamTrack&&window.navigator.mediaDevices&&window.navigator.mediaDevices.getUserMedia||(i?i():window.alert("This browser does not support MediaStreamTrack and mediaDevices")),e.soundArray.push(this)},t.AudioIn.prototype.start=function(t,i){var n=this;this.stream&&this.stop();var o=e.inputSources[n.currentSource],r={audio:{sampleRate:e.audiocontext.sampleRate,echoCancellation:!1}};e.inputSources[this.currentSource]&&(r.audio.deviceId=o.deviceId),window.navigator.mediaDevices.getUserMedia(r).then(function(i){n.stream=i,n.enabled=!0,n.mediaStream=e.audiocontext.createMediaStreamSource(i),n.mediaStream.connect(n.output),n.amplitude.setInput(n.output),t&&t()})["catch"](function(t){i?i(t):console.error(t)})},t.AudioIn.prototype.stop=function(){this.stream&&(this.stream.getTracks().forEach(function(t){t.stop()}),this.mediaStream.disconnect(),delete this.mediaStream,delete this.stream)},t.AudioIn.prototype.connect=function(t){t?t.hasOwnProperty("input")?this.output.connect(t.input):t.hasOwnProperty("analyser")?this.output.connect(t.analyser):this.output.connect(t):this.output.connect(e.input)},t.AudioIn.prototype.disconnect=function(){this.output&&(this.output.disconnect(),this.output.connect(this.amplitude.input))},t.AudioIn.prototype.getLevel=function(t){return t&&(this.amplitude.smoothing=t),this.amplitude.getLevel()},t.AudioIn.prototype.amp=function(t,i){if(i){var n=i||0,o=this.output.gain.value;this.output.gain.cancelScheduledValues(e.audiocontext.currentTime),this.output.gain.setValueAtTime(o,e.audiocontext.currentTime),this.output.gain.linearRampToValueAtTime(t,n+e.audiocontext.currentTime)}else this.output.gain.cancelScheduledValues(e.audiocontext.currentTime),this.output.gain.setValueAtTime(t,e.audiocontext.currentTime)},t.AudioIn.prototype.getSources=function(t,i){return new Promise(function(n,o){window.navigator.mediaDevices.enumerateDevices().then(function(i){e.inputSources=i.filter(function(t){return"audioinput"===t.kind}),n(e.inputSources),t&&t(e.inputSources)})["catch"](function(t){o(t),i?i(t):console.error("This browser does not support MediaStreamTrack.getSources()")})})},t.AudioIn.prototype.setSource=function(t){e.inputSources.length>0&&t=t?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}(n,S,A);var B;B=function(t){"use strict";return t.GreaterThan=function(e){this.createInsOuts(2,0),this._param=this.input[0]=new t.Subtract(e),this.input[1]=this._param.input[1],this._gtz=this.output=new t.GreaterThanZero,this._param.connect(this._gtz)},t.extend(t.GreaterThan,t.Signal),t.GreaterThan.prototype.dispose=function(){return t.prototype.dispose.call(this),this._param.dispose(),this._param=null,this._gtz.dispose(),this._gtz=null,this},t.GreaterThan}(n,N,D);var U;U=function(t){"use strict";return t.Abs=function(){this._abs=this.input=this.output=new t.WaveShaper(function(t){return 0===t?0:Math.abs(t)},127)},t.extend(t.Abs,t.SignalBase),t.Abs.prototype.dispose=function(){return t.prototype.dispose.call(this),this._abs.dispose(),this._abs=null,this},t.Abs}(n,m);var I;I=function(t){"use strict";return t.Modulo=function(e){this.createInsOuts(1,0),this._shaper=new t.WaveShaper(Math.pow(2,16)),this._multiply=new t.Multiply,this._subtract=this.output=new t.Subtract,this._modSignal=new t.Signal(e),this.input.fan(this._shaper,this._subtract),this._modSignal.connect(this._multiply,0,0),this._shaper.connect(this._multiply,0,1),this._multiply.connect(this._subtract,0,1),this._setWaveShaper(e)},t.extend(t.Modulo,t.SignalBase),t.Modulo.prototype._setWaveShaper=function(t){this._shaper.setMap(function(e){var i=Math.floor((e+1e-4)/t);return i; -})},Object.defineProperty(t.Modulo.prototype,"value",{get:function(){return this._modSignal.value},set:function(t){this._modSignal.value=t,this._setWaveShaper(t)}}),t.Modulo.prototype.dispose=function(){return t.prototype.dispose.call(this),this._shaper.dispose(),this._shaper=null,this._multiply.dispose(),this._multiply=null,this._subtract.dispose(),this._subtract=null,this._modSignal.dispose(),this._modSignal=null,this},t.Modulo}(n,m,A);var G;G=function(t){"use strict";return t.Pow=function(e){this._exp=this.defaultArg(e,1),this._expScaler=this.input=this.output=new t.WaveShaper(this._expFunc(this._exp),8192)},t.extend(t.Pow,t.SignalBase),Object.defineProperty(t.Pow.prototype,"value",{get:function(){return this._exp},set:function(t){this._exp=t,this._expScaler.setMap(this._expFunc(this._exp))}}),t.Pow.prototype._expFunc=function(t){return function(e){return Math.pow(Math.abs(e),t)}},t.Pow.prototype.dispose=function(){return t.prototype.dispose.call(this),this._expScaler.dispose(),this._expScaler=null,this},t.Pow}(n);var L;L=function(t){"use strict";return t.AudioToGain=function(){this._norm=this.input=this.output=new t.WaveShaper(function(t){return(t+1)/2})},t.extend(t.AudioToGain,t.SignalBase),t.AudioToGain.prototype.dispose=function(){return t.prototype.dispose.call(this),this._norm.dispose(),this._norm=null,this},t.AudioToGain}(n,m);var j;j=function(t){"use strict";function e(t,e,i){var n=new t;return i._eval(e[0]).connect(n,0,0),i._eval(e[1]).connect(n,0,1),n}function i(t,e,i){var n=new t;return i._eval(e[0]).connect(n,0,0),n}function n(t){return t?parseFloat(t):void 0}function o(t){return t&&t.args?parseFloat(t.args):void 0}return t.Expr=function(){var t=this._replacements(Array.prototype.slice.call(arguments)),e=this._parseInputs(t);this._nodes=[],this.input=new Array(e);for(var i=0;e>i;i++)this.input[i]=this.context.createGain();var n,o=this._parseTree(t);try{n=this._eval(o)}catch(r){throw this._disposeNodes(),new Error("Tone.Expr: Could evaluate expression: "+t)}this.output=n},t.extend(t.Expr,t.SignalBase),t.Expr._Expressions={value:{signal:{regexp:/^\d+\.\d+|^\d+/,method:function(e){var i=new t.Signal(n(e));return i}},input:{regexp:/^\$\d/,method:function(t,e){return e.input[n(t.substr(1))]}}},glue:{"(":{regexp:/^\(/},")":{regexp:/^\)/},",":{regexp:/^,/}},func:{abs:{regexp:/^abs/,method:i.bind(this,t.Abs)},mod:{regexp:/^mod/,method:function(e,i){var n=o(e[1]),r=new t.Modulo(n);return i._eval(e[0]).connect(r),r}},pow:{regexp:/^pow/,method:function(e,i){var n=o(e[1]),r=new t.Pow(n);return i._eval(e[0]).connect(r),r}},a2g:{regexp:/^a2g/,method:function(e,i){var n=new t.AudioToGain;return i._eval(e[0]).connect(n),n}}},binary:{"+":{regexp:/^\+/,precedence:1,method:e.bind(this,t.Add)},"-":{regexp:/^\-/,precedence:1,method:function(n,o){return 1===n.length?i(t.Negate,n,o):e(t.Subtract,n,o)}},"*":{regexp:/^\*/,precedence:0,method:e.bind(this,t.Multiply)}},unary:{"-":{regexp:/^\-/,method:i.bind(this,t.Negate)},"!":{regexp:/^\!/,method:i.bind(this,t.NOT)}}},t.Expr.prototype._parseInputs=function(t){var e=t.match(/\$\d/g),i=0;if(null!==e)for(var n=0;n0;){e=e.trim();var r=i(e);o.push(r),e=e.substr(r.value.length)}return{next:function(){return o[++n]},peek:function(){return o[n+1]}}},t.Expr.prototype._parseTree=function(e){function i(t,e){return!p(t)&&"glue"===t.type&&t.value===e}function n(e,i,n){var o=!1,r=t.Expr._Expressions[i];if(!p(e))for(var s in r){var a=r[s];if(a.regexp.test(e.value)){if(p(n))return!0;if(a.precedence===n)return!0}}return o}function o(t){p(t)&&(t=5);var e;e=0>t?r():o(t-1);for(var i=c.peek();n(i,"binary",t);)i=c.next(),e={operator:i.value,method:i.method,args:[e,o(t-1)]},i=c.peek();return e}function r(){var t,e;return t=c.peek(),n(t,"unary")?(t=c.next(),e=r(),{operator:t.value,method:t.method,args:[e]}):s()}function s(){var t,e;if(t=c.peek(),p(t))throw new SyntaxError("Tone.Expr: Unexpected termination of expression");if("func"===t.type)return t=c.next(),a(t);if("value"===t.type)return t=c.next(),{method:t.method,args:t.value};if(i(t,"(")){if(c.next(),e=o(),t=c.next(),!i(t,")"))throw new SyntaxError("Expected )");return e}throw new SyntaxError("Tone.Expr: Parse error, cannot process token "+t.value)}function a(t){var e,n=[];if(e=c.next(),!i(e,"("))throw new SyntaxError('Tone.Expr: Expected ( in a function call "'+t.value+'"');if(e=c.peek(),i(e,")")||(n=u()),e=c.next(),!i(e,")"))throw new SyntaxError('Tone.Expr: Expected ) in a function call "'+t.value+'"');return{method:t.method,args:n,name:name}}function u(){for(var t,e,n=[];;){if(e=o(),p(e))break;if(n.push(e),t=c.peek(),!i(t,","))break;c.next()}return n}var c=this._tokenize(e),p=this.isUndef.bind(this);return o()},t.Expr.prototype._eval=function(t){if(!this.isUndef(t)){var e=t.method(t.args,this);return this._nodes.push(e),e}},t.Expr.prototype._disposeNodes=function(){for(var t=0;t0){this.connect(arguments[0]);for(var t=1;t=t&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},t.Filter.prototype.res=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},t.Filter.prototype.gain=function(t,e){var i=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+i),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},t.Filter.prototype.toggle=function(){return this._on=!this._on,this._on===!0?this.biquad.type=this._untoggledType:this._on===!1&&(this.biquad.type="allpass"),this._on},t.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},t.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},t.LowPass=function(){t.Filter.call(this,"lowpass")},t.LowPass.prototype=Object.create(t.Filter.prototype),t.HighPass=function(){t.Filter.call(this,"highpass")},t.HighPass.prototype=Object.create(t.Filter.prototype),t.BandPass=function(){t.Filter.call(this,"bandpass")},t.BandPass.prototype=Object.create(t.Filter.prototype),t.Filter}(a,Y);var W;W=function(){var e=z,i=a,n=function(t,i){e.call(this,"peaking"),this.disconnect(),this.set(t,i),this.biquad.gain.value=0,delete this.input,delete this.output,delete this._drywet,delete this.wet};return n.prototype=Object.create(e.prototype),n.prototype.amp=function(){console.warn("`amp()` is not available for p5.EQ bands. Use `.gain()`")},n.prototype.drywet=function(){console.warn("`drywet()` is not available for p5.EQ bands.")},n.prototype.connect=function(e){var i=e||t.soundOut.input;this.biquad?this.biquad.connect(i.input?i.input:i):this.output.connect(i.input?i.input:i)},n.prototype.disconnect=function(){this.biquad&&this.biquad.disconnect()},n.prototype.dispose=function(){var t=i.soundArray.indexOf(this);i.soundArray.splice(t,1),this.disconnect(),delete this.biquad},n}(z,a);var Q;Q=function(){var e=Y,i=W;return t.EQ=function(t){e.call(this),t=3===t||8===t?t:3;var i;i=3===t?Math.pow(2,3):2,this.bands=[];for(var n,o,r=0;t>r;r++)r===t-1?(n=21e3,o=.01):0===r?(n=100,o=.1):1===r?(n=3===t?360*i:360,o=1):(n=this.bands[r-1].freq()*i,o=1),this.bands[r]=this._newBand(n,o),r>0?this.bands[r-1].connect(this.bands[r].biquad):this.input.connect(this.bands[r].biquad);this.bands[t-1].connect(this.output)},t.EQ.prototype=Object.create(e.prototype),t.EQ.prototype.process=function(t){t.connect(this.input)},t.EQ.prototype.set=function(){if(arguments.length===2*this.bands.length)for(var t=0;t0;)delete this.bands.pop().dispose();delete this.bands}},t.EQ}(Y,W);var H;H=function(){var e=Y;return t.Panner3D=function(){e.call(this),this.panner=this.ac.createPanner(),this.panner.panningModel="HRTF",this.panner.distanceModel="linear",this.panner.connect(this.output),this.input.connect(this.panner)},t.Panner3D.prototype=Object.create(e.prototype),t.Panner3D.prototype.process=function(t){t.connect(this.input)},t.Panner3D.prototype.set=function(t,e,i,n){return this.positionX(t,n),this.positionY(e,n),this.positionZ(i,n),[this.panner.positionX.value,this.panner.positionY.value,this.panner.positionZ.value]},t.Panner3D.prototype.positionX=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.positionX.value=t,this.panner.positionX.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.positionX.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.positionX),this.panner.positionX.value},t.Panner3D.prototype.positionY=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.positionY.value=t,this.panner.positionY.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.positionY.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.positionY),this.panner.positionY.value},t.Panner3D.prototype.positionZ=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.positionZ.value=t,this.panner.positionZ.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.positionZ.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.positionZ),this.panner.positionZ.value},t.Panner3D.prototype.orient=function(t,e,i,n){return this.orientX(t,n),this.orientY(e,n),this.orientZ(i,n),[this.panner.orientationX.value,this.panner.orientationY.value,this.panner.orientationZ.value]},t.Panner3D.prototype.orientX=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.orientationX.value=t,this.panner.orientationX.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.orientationX.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.orientationX),this.panner.orientationX.value},t.Panner3D.prototype.orientY=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.orientationY.value=t,this.panner.orientationY.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.orientationY.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.orientationY),this.panner.orientationY.value},t.Panner3D.prototype.orientZ=function(t,e){var i=e||0;return"number"==typeof t?(this.panner.orientationZ.value=t,this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime+.01+i),this.panner.orientationZ.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.panner.orientationZ),this.panner.orientationZ.value},t.Panner3D.prototype.setFalloff=function(t,e){this.maxDist(t),this.rolloff(e)},t.Panner3D.prototype.maxDist=function(t){return"number"==typeof t&&(this.panner.maxDistance=t),this.panner.maxDistance},t.Panner3D.prototype.rolloff=function(t){return"number"==typeof t&&(this.panner.rolloffFactor=t),this.panner.rolloffFactor},t.Panner3D.dispose=function(){e.prototype.dispose.apply(this),this.panner&&(this.panner.disconnect(),delete this.panner)},t.Panner3D}(a,Y);var $;$=function(){var e=a;return t.Listener3D=function(t){this.ac=e.audiocontext,this.listener=this.ac.listener},t.Listener3D.prototype.process=function(t){t.connect(this.input)},t.Listener3D.prototype.position=function(t,e,i,n){return this.positionX(t,n),this.positionY(e,n),this.positionZ(i,n),[this.listener.positionX.value,this.listener.positionY.value,this.listener.positionZ.value]},t.Listener3D.prototype.positionX=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.positionX.value=t,this.listener.positionX.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.positionX.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.positionX),this.listener.positionX.value},t.Listener3D.prototype.positionY=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.positionY.value=t,this.listener.positionY.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.positionY.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.positionY),this.listener.positionY.value},t.Listener3D.prototype.positionZ=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.positionZ.value=t,this.listener.positionZ.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.positionZ.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.positionZ),this.listener.positionZ.value},t.Listener3D.prototype.orient=function(t,e,i,n,o,r,s){return 3===arguments.length||4===arguments.length?(s=arguments[3],this.orientForward(t,e,i,s)):(6===arguments.length||7===arguments)&&(this.orientForward(t,e,i),this.orientUp(n,o,r,s)),[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value,this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]},t.Listener3D.prototype.orientForward=function(t,e,i,n){return this.forwardX(t,n),this.forwardY(e,n),this.forwardZ(i,n),[this.listener.forwardX,this.listener.forwardY,this.listener.forwardZ]},t.Listener3D.prototype.orientUp=function(t,e,i,n){return this.upX(t,n),this.upY(e,n),this.upZ(i,n),[this.listener.upX,this.listener.upY,this.listener.upZ]},t.Listener3D.prototype.forwardX=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.forwardX.value=t,this.listener.forwardX.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.forwardX.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.forwardX),this.listener.forwardX.value},t.Listener3D.prototype.forwardY=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.forwardY.value=t,this.listener.forwardY.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.forwardY.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.forwardY),this.listener.forwardY.value},t.Listener3D.prototype.forwardZ=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.forwardZ.value=t,this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.forwardZ.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.forwardZ),this.listener.forwardZ.value},t.Listener3D.prototype.upX=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.upX.value=t,this.listener.upX.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.upX.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.upX),this.listener.upX.value},t.Listener3D.prototype.upY=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.upY.value=t,this.listener.upY.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.upY.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.upY),this.listener.upY.value},t.Listener3D.prototype.upZ=function(t,e){var i=e||0;return"number"==typeof t?(this.listener.upZ.value=t,this.listener.upZ.cancelScheduledValues(this.ac.currentTime+.01+i),this.listener.upZ.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):t&&t.connect(this.listener.upZ),this.listener.upZ.value},t.Listener3D}(a,Y);var J;J=function(){var e=z,i=Y;t.Delay=function(){i.call(this),this._split=this.ac.createChannelSplitter(2),this._merge=this.ac.createChannelMerger(2),this._leftGain=this.ac.createGain(),this._rightGain=this.ac.createGain(),this.leftDelay=this.ac.createDelay(),this.rightDelay=this.ac.createDelay(),this._leftFilter=new e,this._rightFilter=new e,this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._leftFilter.biquad.frequency.setValueAtTime(1200,this.ac.currentTime),this._rightFilter.biquad.frequency.setValueAtTime(1200,this.ac.currentTime),this._leftFilter.biquad.Q.setValueAtTime(.3,this.ac.currentTime),this._rightFilter.biquad.Q.setValueAtTime(.3,this.ac.currentTime),this.input.connect(this._split),this.leftDelay.connect(this._leftGain),this.rightDelay.connect(this._rightGain),this._leftGain.connect(this._leftFilter.input),this._rightGain.connect(this._rightFilter.input),this._merge.connect(this.wet),this._leftFilter.biquad.gain.setValueAtTime(1,this.ac.currentTime),this._rightFilter.biquad.gain.setValueAtTime(1,this.ac.currentTime),this.setType(0),this._maxDelay=this.leftDelay.delayTime.maxValue,this.feedback(.5)},t.Delay.prototype=Object.create(i.prototype),t.Delay.prototype.process=function(t,e,i,n){var o=i||0,r=e||0;if(o>=1)throw new Error("Feedback value will force a positive feedback loop.");if(r>=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,n&&(this._leftFilter.freq(n),this._rightFilter.freq(n))},t.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},t.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(t>=1)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},t.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},t.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},t.Delay.prototype.dispose=function(){i.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}(z,Y);var K;K=function(){var e=c,i=Y;t.Reverb=function(){i.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},t.Reverb.prototype=Object.create(i.prototype),t.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},t.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},t.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},t.Reverb.prototype.process=function(t,e,i,n){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),i&&(this._decay=i),n&&(this._reverse=n),o&&this._buildImpulse()},t.Reverb.prototype.set=function(t,e,i){var n=!1;t&&(this._seconds=t,n=!0),e&&(this._decay=e),i&&(this._reverse=i),n&&this._buildImpulse()},t.Reverb.prototype._buildImpulse=function(){var t,e,i=this.ac.sampleRate,n=i*this._seconds,o=this._decay,r=this.ac.createBuffer(2,n,i),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;n>e;e++)t=this._reverse?n-e:e,s[e]=(2*Math.random()-1)*Math.pow(1-t/n,o),a[e]=(2*Math.random()-1)*Math.pow(1-t/n,o);this._setBuffer(r)},t.Reverb.prototype.dispose=function(){i.prototype.dispose.apply(this),this._teardownConvolverNode()},t.Convolver=function(e,i,n){t.Reverb.call(this),this._initConvolverNode(),this.input.gain.value=.5,e?(this.impulses=[],this._loadBuffer(e,i,n)):(this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse())},t.Convolver.prototype=Object.create(t.Reverb.prototype),t.prototype.registerPreloadMethod("createConvolver",t.prototype),t.prototype.createConvolver=function(e,i,n){window.location.origin.indexOf("file://")>-1&&"undefined"===window.cordova&&alert("This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS");var o=this,r=new t.Convolver(e,function(t){"function"==typeof i&&i(t),"function"==typeof o._decrementPreload&&o._decrementPreload()},n);return r.impulses=[],r},t.Convolver.prototype._loadBuffer=function(i,n,o){var i=t.prototype._checkFileFormats(i),r=this,s=(new Error).stack,a=t.prototype.getAudioContext(),u=new XMLHttpRequest;u.open("GET",i,!0),u.responseType="arraybuffer",u.onload=function(){if(200===u.status)a.decodeAudioData(u.response,function(t){var e={},o=i.split("/");e.name=o[o.length-1],e.audioBuffer=t,r.impulses.push(e),r._setBuffer(e.audioBuffer),n&&n(e)},function(){var t=new e("decodeAudioData",s,r.url),i="AudioContext error at decodeAudioData for "+r.url;o?(t.msg=i,o(t)):console.error(i+"\n The error stack trace includes: \n"+t.stack)});else{var t=new e("loadConvolver",s,r.url),c="Unable to load "+r.url+". The request status was: "+u.status+" ("+u.statusText+")";o?(t.message=c,o(t)):console.error(c+"\n The error stack trace includes: \n"+t.stack)}},u.onerror=function(){var t=new e("loadConvolver",s,r.url),i="There was no response from the server at "+r.url+". Check the url and internet connectivity.";o?(t.message=i,o(t)):console.error(i+"\n The error stack trace includes: \n"+t.stack)},u.send()},t.Convolver.prototype.set=null,t.Convolver.prototype.process=function(t){t.connect(this.input)},t.Convolver.prototype.impulses=[],t.Convolver.prototype.addImpulse=function(t,e,i){window.location.origin.indexOf("file://")>-1&&"undefined"===window.cordova&&alert("This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS"),this._loadBuffer(t,e,i)},t.Convolver.prototype.resetImpulse=function(t,e,i){window.location.origin.indexOf("file://")>-1&&"undefined"===window.cordova&&alert("This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS"),this.impulses=[],this._loadBuffer(t,e,i)},t.Convolver.prototype.toggleImpulse=function(t){if("number"==typeof t&&tthis._nextTick&&this._state;){var s=this._state.getValueAtTime(this._nextTick);if(s!==this._lastState){this._lastState=s;var a=this._state.get(this._nextTick);s===t.State.Started?(this._nextTick=a.time,this.isUndef(a.offset)||(this.ticks=a.offset),this.emit("start",a.time,this.ticks)):s===t.State.Stopped?(this.ticks=0,this.emit("stop",a.time)):s===t.State.Paused&&this.emit("pause",a.time)}var u=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),s===t.State.Started&&(this.callback(u),this.ticks++))}},t.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},t.Clock.prototype.dispose=function(){t.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},t.Clock}(n,q,tt,o);var it;it=function(){var e=a,i=et;t.Metro=function(){this.clock=new i({callback:this.ontick.bind(this)}),this.syncedParts=[],this.bpm=120,this._init(),this.prevTick=0,this.tatumTime=0,this.tickCallback=function(){}},t.Metro.prototype.ontick=function(t){var i=t-this.prevTick,n=t-e.audiocontext.currentTime;if(!(i-this.tatumTime<=-.02)){this.prevTick=t;var o=this;this.syncedParts.forEach(function(t){t.isPlaying&&(t.incrementStep(n),t.phrases.forEach(function(t){var e=t.sequence,i=o.metroTicks%e.length;0!==e[i]&&(o.metroTicks=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}var i=a,n=120;t.prototype.setBPM=function(t,e){n=t;for(var o in i.parts)i.parts[o]&&i.parts[o].setBPM(t,e)},t.Phrase=function(t,e,i){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=i},t.Part=function(e,o){this.length=e||0,this.partStep=0, -this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=o||.0625,this.metro=new t.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(n),i.parts.push(this),this.callback=function(){}},t.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},t.Part.prototype.getBPM=function(){return this.metro.getBPM()},t.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},t.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},t.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},t.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},t.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},t.Part.prototype.addPhrase=function(e,i,n){var o;if(3===arguments.length)o=new t.Phrase(e,i,n);else{if(!(arguments[0]instanceof t.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";o=arguments[0]}this.phrases.push(o),o.sequence.length>this.length&&(this.length=o.sequence.length)},t.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},t.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},t.Part.prototype.replaceSequence=function(t,e){for(var i in this.phrases)this.phrases[i].name===t&&(this.phrases[i].sequence=e)},t.Part.prototype.incrementStep=function(t){this.partStep0&&o.iterations<=o.maxIterations&&o.callback(i)},frequency:this._calcFreq()})},t.SoundLoop.prototype.start=function(t){var i=t||0,n=e.audiocontext.currentTime;this.isPlaying||(this.clock.start(n+i),this.isPlaying=!0)},t.SoundLoop.prototype.stop=function(t){var i=t||0,n=e.audiocontext.currentTime;this.isPlaying&&(this.clock.stop(n+i),this.isPlaying=!1)},t.SoundLoop.prototype.pause=function(t){var i=t||0,n=e.audiocontext.currentTime;this.isPlaying&&(this.clock.pause(n+i),this.isPlaying=!1)},t.SoundLoop.prototype.syncedStart=function(t,i){var n=i||0,o=e.audiocontext.currentTime;if(t.isPlaying){if(t.isPlaying){var r=t.clock._nextTick-e.audiocontext.currentTime;this.clock.start(o+r),this.isPlaying=!0}}else t.clock.start(o+n),t.isPlaying=!0,this.clock.start(o+n),this.isPlaying=!0},t.SoundLoop.prototype._update=function(){this.clock.frequency.value=this._calcFreq()},t.SoundLoop.prototype._calcFreq=function(){return"number"==typeof this._interval?(this.musicalTimeMode=!1,1/this._interval):"string"==typeof this._interval?(this.musicalTimeMode=!0,this._bpm/60/this._convertNotation(this._interval)*(this._timeSignature/4)):void 0},t.SoundLoop.prototype._convertNotation=function(t){var e=t.slice(-1);switch(t=Number(t.slice(0,-1)),e){case"m":return this._measure(t);case"n":return this._note(t);default:console.warn("Specified interval is not formatted correctly. See Tone.js timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time")}},t.SoundLoop.prototype._measure=function(t){return t*this._timeSignature},t.SoundLoop.prototype._note=function(t){return this._timeSignature/t},Object.defineProperty(t.SoundLoop.prototype,"bpm",{get:function(){return this._bpm},set:function(t){this.musicalTimeMode||console.warn('Changing the BPM in "seconds" mode has no effect. BPM is only relevant in musicalTimeMode when the interval is specified as a string ("2n", "4n", "1m"...etc)'),this._bpm=t,this._update()}}),Object.defineProperty(t.SoundLoop.prototype,"timeSignature",{get:function(){return this._timeSignature},set:function(t){this.musicalTimeMode||console.warn('Changing the timeSignature in "seconds" mode has no effect. BPM is only relevant in musicalTimeMode when the interval is specified as a string ("2n", "4n", "1m"...etc)'),this._timeSignature=t,this._update()}}),Object.defineProperty(t.SoundLoop.prototype,"interval",{get:function(){return this._interval},set:function(t){this.musicalTimeMode="Number"==typeof t?!1:!0,this._interval=t,this._update()}}),Object.defineProperty(t.SoundLoop.prototype,"iterations",{get:function(){return this.clock.ticks}}),t.SoundLoop}(a,et);var rt;rt=function(){"use strict";var e=Y;return t.Compressor=function(){e.call(this),this.compressor=this.ac.createDynamicsCompressor(),this.input.connect(this.compressor),this.compressor.connect(this.wet)},t.Compressor.prototype=Object.create(e.prototype),t.Compressor.prototype.process=function(t,e,i,n,o,r){t.connect(this.input),this.set(e,i,n,o,r)},t.Compressor.prototype.set=function(t,e,i,n,o){"undefined"!=typeof t&&this.attack(t),"undefined"!=typeof e&&this.knee(e),"undefined"!=typeof i&&this.ratio(i),"undefined"!=typeof n&&this.threshold(n),"undefined"!=typeof o&&this.release(o)},t.Compressor.prototype.attack=function(t,e){var i=e||0;return"number"==typeof t?(this.compressor.attack.value=t,this.compressor.attack.cancelScheduledValues(this.ac.currentTime+.01+i),this.compressor.attack.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):"undefined"!=typeof t&&t.connect(this.compressor.attack),this.compressor.attack.value},t.Compressor.prototype.knee=function(t,e){var i=e||0;return"number"==typeof t?(this.compressor.knee.value=t,this.compressor.knee.cancelScheduledValues(this.ac.currentTime+.01+i),this.compressor.knee.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):"undefined"!=typeof t&&t.connect(this.compressor.knee),this.compressor.knee.value},t.Compressor.prototype.ratio=function(t,e){var i=e||0;return"number"==typeof t?(this.compressor.ratio.value=t,this.compressor.ratio.cancelScheduledValues(this.ac.currentTime+.01+i),this.compressor.ratio.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):"undefined"!=typeof t&&t.connect(this.compressor.ratio),this.compressor.ratio.value},t.Compressor.prototype.threshold=function(t,e){var i=e||0;return"number"==typeof t?(this.compressor.threshold.value=t,this.compressor.threshold.cancelScheduledValues(this.ac.currentTime+.01+i),this.compressor.threshold.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):"undefined"!=typeof t&&t.connect(this.compressor.threshold),this.compressor.threshold.value},t.Compressor.prototype.release=function(t,e){var i=e||0;return"number"==typeof t?(this.compressor.release.value=t,this.compressor.release.cancelScheduledValues(this.ac.currentTime+.01+i),this.compressor.release.linearRampToValueAtTime(t,this.ac.currentTime+.02+i)):"undefined"!=typeof number&&t.connect(this.compressor.release),this.compressor.release.value},t.Compressor.prototype.reduction=function(){return this.compressor.reduction.value},t.Compressor.prototype.dispose=function(){e.prototype.dispose.apply(this),this.compressor&&(this.compressor.disconnect(),delete this.compressor)},t.Compressor}(a,Y,c);var st;st=function(){var e=a,i=u.convertToWav,n=e.audiocontext;t.SoundRecorder=function(){this.input=n.createGain(),this.output=n.createGain(),this.recording=!1,this.bufferSize=1024,this._channels=2,this._clear(),this._jsNode=n.createScriptProcessor(this.bufferSize,this._channels,2),this._jsNode.onaudioprocess=this._audioprocess.bind(this),this._callback=function(){},this._jsNode.connect(t.soundOut._silentNode),this.setInput(),e.soundArray.push(this)},t.SoundRecorder.prototype.setInput=function(e){this.input.disconnect(),this.input=null,this.input=n.createGain(),this.input.connect(this._jsNode),this.input.connect(this.output),e?e.connect(this.input):t.soundOut.output.connect(this.input)},t.SoundRecorder.prototype.record=function(t,e,i){this.recording=!0,e&&(this.sampleLimit=Math.round(e*n.sampleRate)),t&&i?this._callback=function(){this.buffer=this._getBuffer(),t.setBuffer(this.buffer),i()}:t&&(this._callback=function(){this.buffer=this._getBuffer(),t.setBuffer(this.buffer)})},t.SoundRecorder.prototype.stop=function(){this.recording=!1,this._callback(),this._clear()},t.SoundRecorder.prototype._clear=function(){this._leftBuffers=[],this._rightBuffers=[],this.recordedSamples=0,this.sampleLimit=null},t.SoundRecorder.prototype._audioprocess=function(t){if(this.recording!==!1&&this.recording===!0)if(this.sampleLimit&&this.recordedSamples>=this.sampleLimit)this.stop();else{var e=t.inputBuffer.getChannelData(0),i=t.inputBuffer.getChannelData(1);this._leftBuffers.push(new Float32Array(e)),this._rightBuffers.push(new Float32Array(i)),this.recordedSamples+=this.bufferSize}},t.SoundRecorder.prototype._getBuffer=function(){var t=[];return t.push(this._mergeBuffers(this._leftBuffers)),t.push(this._mergeBuffers(this._rightBuffers)),t},t.SoundRecorder.prototype._mergeBuffers=function(t){for(var e=new Float32Array(this.recordedSamples),i=0,n=t.length,o=0;n>o;o++){var r=t[o];e.set(r,i),i+=r.length}return e},t.SoundRecorder.prototype.dispose=function(){this._clear();var t=e.soundArray.indexOf(this);e.soundArray.splice(t,1),this._callback=function(){},this.input&&this.input.disconnect(),this.input=null,this._jsNode=null},t.prototype.saveSound=function(e,n){const o=i(e.buffer);t.prototype.writeFile([o],n,"wav")}}(a,u);var at;at=function(){t.PeakDetect=function(t,e,i,n){this.framesPerPeak=n||20,this.framesSinceLastPeak=0,this.decayRate=.95,this.threshold=i||.35,this.cutoff=0,this.cutoffMult=1.5,this.energy=0,this.penergy=0,this.currentValue=0,this.isDetected=!1,this.f1=t||40,this.f2=e||2e4,this._onPeak=function(){}},t.PeakDetect.prototype.update=function(t){var e=this.energy=t.getEnergy(this.f1,this.f2)/255;e>this.cutoff&&e>this.threshold&&e-this.penergy>0?(this._onPeak(),this.isDetected=!0,this.cutoff=e*this.cutoffMult,this.framesSinceLastPeak=0):(this.isDetected=!1,this.framesSinceLastPeak<=this.framesPerPeak?this.framesSinceLastPeak++:(this.cutoff*=this.decayRate,this.cutoff=Math.max(this.cutoff,this.threshold))),this.currentValue=e,this.penergy=e},t.PeakDetect.prototype.onPeak=function(t,e){var i=this;i._onPeak=function(){t(i.energy,e)}}}();var ut;ut=function(){var e=a;t.Gain=function(){this.ac=e.audiocontext,this.input=this.ac.createGain(),this.output=this.ac.createGain(),this.input.gain.value=.5,this.input.connect(this.output),e.soundArray.push(this)},t.Gain.prototype.setInput=function(t){t.connect(this.input)},t.Gain.prototype.connect=function(e){var i=e||t.soundOut.input;this.output.connect(i.input?i.input:i)},t.Gain.prototype.disconnect=function(){this.output&&this.output.disconnect()},t.Gain.prototype.amp=function(t,i,n){var i=i||0,n=n||0,o=e.audiocontext.currentTime,r=this.output.gain.value;this.output.gain.cancelScheduledValues(o),this.output.gain.linearRampToValueAtTime(r,o+n),this.output.gain.linearRampToValueAtTime(t,o+n+i)},t.Gain.prototype.dispose=function(){var t=e.soundArray.indexOf(this);e.soundArray.splice(t,1),this.output&&(this.output.disconnect(),delete this.output),this.input&&(this.input.disconnect(),delete this.input)}}(a);var ct;ct=function(){var e=a;return t.AudioVoice=function(){this.ac=e.audiocontext,this.output=this.ac.createGain(),this.connect(),e.soundArray.push(this)},t.AudioVoice.prototype.play=function(t,e,i,n){},t.AudioVoice.prototype.triggerAttack=function(t,e,i){},t.AudioVoice.prototype.triggerRelease=function(t){},t.AudioVoice.prototype.amp=function(t,e){},t.AudioVoice.prototype.connect=function(t){var i=t||e.input;this.output.connect(i.input?i.input:i)},t.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},t.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},t.AudioVoice}(a);var pt;pt=function(){var e=a,i=ct,n=u.noteToFreq,o=.15;t.MonoSynth=function(){i.call(this),this.oscillator=new t.Oscillator,this.env=new t.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),e.soundArray.push(this)},t.MonoSynth.prototype=Object.create(t.AudioVoice.prototype),t.MonoSynth.prototype.play=function(t,e,i,n){this.triggerAttack(t,e,~~i),this.triggerRelease(~~i+(n||o))},t.MonoSynth.prototype.triggerAttack=function(t,e,i){var i=~~i,o=n(t),r=e||.1;this.oscillator.freq(o,0,i),this.env.ramp(this.output.gain,i,r)},t.MonoSynth.prototype.triggerRelease=function(t){var t=t||0;this.env.ramp(this.output.gain,t,0)},t.MonoSynth.prototype.setADSR=function(t,e,i,n){this.env.setADSR(t,e,i,n)},Object.defineProperties(t.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),t.MonoSynth.prototype.amp=function(t,e){var i=e||0;return"undefined"!=typeof t&&this.oscillator.amp(t,i),this.oscillator.amp().value},t.MonoSynth.prototype.connect=function(t){var i=t||e.input;this.output.connect(i.input?i.input:i)},t.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},t.MonoSynth.prototype.dispose=function(){i.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}(a,ct,u);var ht;ht=function(){var e=a,i=q,n=u.noteToFreq;t.PolySynth=function(n,o){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=o||8,this.AudioVoice=void 0===n?t.MonoSynth:n,this._voicesInUse=new i(0),this.output=e.audiocontext.createGain(),this.connect(),this._allocateVoices(),e.soundArray.push(this)},t.PolySynth.prototype._allocateVoices=function(){for(var t=0;tf?f:p}this.audiovoices[a].triggerAttack(c,p,s)},t.PolySynth.prototype._updateAfter=function(t,e){if(null!==this._voicesInUse._searchAfter(t)){this._voicesInUse._searchAfter(t).value+=e;var i=this._voicesInUse._searchAfter(t).time;this._updateAfter(i,e)}},t.PolySynth.prototype.noteRelease=function(t,i){var o=e.audiocontext.currentTime,r=i||0,s=o+r;if(t){var a=n(t);if(this.notes[a]&&null!==this.notes[a].getValueAtTime(s)){var u=Math.max(~~this._voicesInUse.getValueAtTime(s).value,1);this._voicesInUse.setValueAtTime(u-1,s),u>0&&this._updateAfter(s,-1),this.audiovoices[this.notes[a].getValueAtTime(s)].triggerRelease(r),this.notes[a].dispose(),delete this.notes[a],this._newest=0===this._newest?0:(this._newest-1)%(this.maxVoices-1)}else console.warn("Cannot release a note that is not already playing")}else{this.audiovoices.forEach(function(t){t.triggerRelease(r)}),this._voicesInUse.setValueAtTime(0,s);for(var c in this.notes)this.notes[c].dispose(),delete this.notes[c]}},t.PolySynth.prototype.connect=function(t){var i=t||e.input;this.output.connect(i.input?i.input:i)},t.PolySynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},t.PolySynth.prototype.dispose=function(){this.audiovoices.forEach(function(t){t.dispose()}),this.output&&(this.output.disconnect(),delete this.output)}}(a,q,u);var lt;lt=function(){function e(t){for(var e,i="number"==typeof t?t:50,n=44100,o=new Float32Array(n),r=Math.PI/180,s=0;n>s;++s)e=2*s/n-1,o[s]=(3+i)*e*20*r/(Math.PI+i*Math.abs(e));return o}var i=Y;t.Distortion=function(n,o){if(i.call(this),"undefined"==typeof n&&(n=.25),"number"!=typeof n)throw new Error("amount must be a number");if("undefined"==typeof o&&(o="2x"),"string"!=typeof o)throw new Error("oversample must be a String");var r=t.prototype.map(n,0,1,0,2e3);this.waveShaperNode=this.ac.createWaveShaper(),this.amount=r,this.waveShaperNode.curve=e(r),this.waveShaperNode.oversample=o,this.input.connect(this.waveShaperNode),this.waveShaperNode.connect(this.wet)},t.Distortion.prototype=Object.create(i.prototype),t.Distortion.prototype.process=function(t,e,i){t.connect(this.input),this.set(e,i)},t.Distortion.prototype.set=function(i,n){if(i){var o=t.prototype.map(i,0,1,0,2e3);this.amount=o,this.waveShaperNode.curve=e(o)}n&&(this.waveShaperNode.oversample=n)},t.Distortion.prototype.getAmount=function(){return this.amount},t.Distortion.prototype.getOversample=function(){return this.waveShaperNode.oversample},t.Distortion.prototype.dispose=function(){i.prototype.dispose.apply(this),this.waveShaperNode&&(this.waveShaperNode.disconnect(),this.waveShaperNode=null)}}(Y);var ft;ft=function(){var t=a;return t}(e,s,a,u,c,p,h,l,f,k,O,M,E,V,R,z,Q,H,$,J,K,it,nt,ot,rt,st,at,ut,pt,ht,lt,ct,pt,ht)}); \ No newline at end of file +!(function (t, e) { + "function" == typeof define && define.amd + ? define("p5.sound", ["p5"], function (t) { + e(t); + }) + : e("object" == typeof exports ? require("../p5") : t.p5); +})(this, function (t) { + var e; + e = (function () { + !(function () { + function t(t) { + t && + (t.setTargetAtTime || (t.setTargetAtTime = t.setTargetValueAtTime)); + } + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") && + ((window.AudioContext = window.webkitAudioContext), + "function" != typeof AudioContext.prototype.createGain && + (AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode), + "function" != typeof AudioContext.prototype.createDelay && + (AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode), + "function" != typeof AudioContext.prototype.createScriptProcessor && + (AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode), + "function" != typeof AudioContext.prototype.createPeriodicWave && + (AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable), + (AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain), + (AudioContext.prototype.createGain = function () { + var e = this.internal_createGain(); + return t(e.gain), e; + }), + (AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay), + (AudioContext.prototype.createDelay = function (e) { + var i = e + ? this.internal_createDelay(e) + : this.internal_createDelay(); + return t(i.delayTime), i; + }), + (AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource), + (AudioContext.prototype.createBufferSource = function () { + var e = this.internal_createBufferSource(); + return ( + e.start + ? ((e.internal_start = e.start), + (e.start = function (t, i, n) { + "undefined" != typeof n + ? e.internal_start(t || 0, i, n) + : e.internal_start(t || 0, i || 0); + })) + : (e.start = function (t, e, i) { + e || i ? this.noteGrainOn(t || 0, e, i) : this.noteOn(t || 0); + }), + e.stop + ? ((e.internal_stop = e.stop), + (e.stop = function (t) { + e.internal_stop(t || 0); + })) + : (e.stop = function (t) { + this.noteOff(t || 0); + }), + t(e.playbackRate), + e + ); + }), + (AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor), + (AudioContext.prototype.createDynamicsCompressor = function () { + var e = this.internal_createDynamicsCompressor(); + return ( + t(e.threshold), + t(e.knee), + t(e.ratio), + t(e.reduction), + t(e.attack), + t(e.release), + e + ); + }), + (AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter), + (AudioContext.prototype.createBiquadFilter = function () { + var e = this.internal_createBiquadFilter(); + return t(e.frequency), t(e.detune), t(e.Q), t(e.gain), e; + }), + "function" != typeof AudioContext.prototype.createOscillator && + ((AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator), + (AudioContext.prototype.createOscillator = function () { + var e = this.internal_createOscillator(); + return ( + e.start + ? ((e.internal_start = e.start), + (e.start = function (t) { + e.internal_start(t || 0); + })) + : (e.start = function (t) { + this.noteOn(t || 0); + }), + e.stop + ? ((e.internal_stop = e.stop), + (e.stop = function (t) { + e.internal_stop(t || 0); + })) + : (e.stop = function (t) { + this.noteOff(t || 0); + }), + e.setPeriodicWave || (e.setPeriodicWave = e.setWaveTable), + t(e.frequency), + t(e.detune), + e + ); + }))), + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") && + (window.OfflineAudioContext = window.webkitOfflineAudioContext); + })(window), + (navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia); + var e = document.createElement("audio"); + t.prototype.isSupported = function () { + return !!e.canPlayType; + }; + var i = function () { + return !!e.canPlayType && e.canPlayType('audio/ogg; codecs="vorbis"'); + }, + n = function () { + return !!e.canPlayType && e.canPlayType("audio/mpeg;"); + }, + o = function () { + return !!e.canPlayType && e.canPlayType('audio/wav; codecs="1"'); + }, + r = function () { + return ( + !!e.canPlayType && + (e.canPlayType("audio/x-m4a;") || e.canPlayType("audio/aac;")) + ); + }, + s = function () { + return !!e.canPlayType && e.canPlayType("audio/x-aiff;"); + }; + t.prototype.isFileSupported = function (t) { + switch (t.toLowerCase()) { + case "mp3": + return n(); + case "wav": + return o(); + case "ogg": + return i(); + case "aac": + case "m4a": + case "mp4": + return r(); + case "aif": + case "aiff": + return s(); + default: + return !1; + } + }; + })(); + var i; + !(function (t, e) { + i = (function () { + return e(); + })(); + })(this, function () { + function t(t) { + var e = t.createBuffer(1, 1, t.sampleRate), + i = t.createBufferSource(); + (i.buffer = e), + i.connect(t.destination), + i.start(0), + t.resume && t.resume(); + } + function e(t) { + return "running" === t.state; + } + function i(t, i) { + function n() { + e(t) ? i() : (requestAnimationFrame(n), t.resume && t.resume()); + } + e(t) ? i() : n(); + } + function n(t, e, i) { + if (Array.isArray(t) || (NodeList && t instanceof NodeList)) + for (var o = 0; o < t.length; o++) n(t[o], e, i); + else if ("string" == typeof t) n(document.querySelectorAll(t), e, i); + else if (t.jquery && "function" == typeof t.toArray) n(t.toArray(), e, i); + else if (Element && t instanceof Element) { + var s = new r(t, i); + e.push(s); + } + } + function o(t, e, o) { + var r = new Promise(function (e) { + i(t, e); + }), + s = []; + return ( + e || (e = document.body), + n(e, s, t), + r.then(function () { + for (var t = 0; t < s.length; t++) s[t].dispose(); + (s = null), o && o(); + }), + r + ); + } + var r = function (t, e) { + (this._dragged = !1), + (this._element = t), + (this._bindedMove = this._moved.bind(this)), + (this._bindedEnd = this._ended.bind(this, e)), + t.addEventListener("touchstart", this._bindedEnd), + t.addEventListener("touchmove", this._bindedMove), + t.addEventListener("touchend", this._bindedEnd), + t.addEventListener("mouseup", this._bindedEnd); + }; + return ( + (r.prototype._moved = function (t) { + this._dragged = !0; + }), + (r.prototype._ended = function (e) { + this._dragged || t(e), (this._dragged = !1); + }), + (r.prototype.dispose = function () { + this._element.removeEventListener("touchstart", this._bindedEnd), + this._element.removeEventListener("touchmove", this._bindedMove), + this._element.removeEventListener("touchend", this._bindedEnd), + this._element.removeEventListener("mouseup", this._bindedEnd), + (this._bindedMove = null), + (this._bindedEnd = null), + (this._element = null); + }), + o + ); + }); + var n; + n = (function () { + "use strict"; + var t = function (t, e) { + this.isUndef(t) || 1 === t + ? (this.input = this.context.createGain()) + : t > 1 && (this.input = new Array(t)), + this.isUndef(e) || 1 === e + ? (this.output = this.context.createGain()) + : e > 1 && (this.output = new Array(t)); + }; + (t.prototype.set = function (e, i, n) { + if (this.isObject(e)) n = i; + else if (this.isString(e)) { + var o = {}; + (o[e] = i), (e = o); + } + t: for (var r in e) { + i = e[r]; + var s = this; + if (-1 !== r.indexOf(".")) { + for (var a = r.split("."), u = 0; u < a.length - 1; u++) + if (((s = s[a[u]]), s instanceof t)) { + a.splice(0, u + 1); + var c = a.join("."); + s.set(c, i); + continue t; + } + r = a[a.length - 1]; + } + var p = s[r]; + this.isUndef(p) || + ((t.Signal && p instanceof t.Signal) || + (t.Param && p instanceof t.Param) + ? p.value !== i && + (this.isUndef(n) ? (p.value = i) : p.rampTo(i, n)) + : p instanceof AudioParam + ? p.value !== i && (p.value = i) + : p instanceof t + ? p.set(i) + : p !== i && (s[r] = i)); + } + return this; + }), + (t.prototype.get = function (e) { + this.isUndef(e) + ? (e = this._collectDefaults(this.constructor)) + : this.isString(e) && (e = [e]); + for (var i = {}, n = 0; n < e.length; n++) { + var o = e[n], + r = this, + s = i; + if (-1 !== o.indexOf(".")) { + for (var a = o.split("."), u = 0; u < a.length - 1; u++) { + var c = a[u]; + (s[c] = s[c] || {}), (s = s[c]), (r = r[c]); + } + o = a[a.length - 1]; + } + var p = r[o]; + this.isObject(e[o]) + ? (s[o] = p.get()) + : t.Signal && p instanceof t.Signal + ? (s[o] = p.value) + : t.Param && p instanceof t.Param + ? (s[o] = p.value) + : p instanceof AudioParam + ? (s[o] = p.value) + : p instanceof t + ? (s[o] = p.get()) + : this.isFunction(p) || this.isUndef(p) || (s[o] = p); + } + return i; + }), + (t.prototype._collectDefaults = function (t) { + var e = []; + if ( + (this.isUndef(t.defaults) || (e = Object.keys(t.defaults)), + !this.isUndef(t._super)) + ) + for ( + var i = this._collectDefaults(t._super), n = 0; + n < i.length; + n++ + ) + -1 === e.indexOf(i[n]) && e.push(i[n]); + return e; + }), + (t.prototype.toString = function () { + for (var e in t) { + var i = e[0].match(/^[A-Z]$/), + n = t[e] === this.constructor; + if (this.isFunction(t[e]) && i && n) return e; + } + return "Tone"; + }), + Object.defineProperty(t.prototype, "numberOfInputs", { + get: function () { + return this.input + ? this.isArray(this.input) + ? this.input.length + : 1 + : 0; + }, + }), + Object.defineProperty(t.prototype, "numberOfOutputs", { + get: function () { + return this.output + ? this.isArray(this.output) + ? this.output.length + : 1 + : 0; + }, + }), + (t.prototype.dispose = function () { + return ( + this.isUndef(this.input) || + (this.input instanceof AudioNode && this.input.disconnect(), + (this.input = null)), + this.isUndef(this.output) || + (this.output instanceof AudioNode && this.output.disconnect(), + (this.output = null)), + this + ); + }), + (t.prototype.connect = function (t, e, i) { + return ( + Array.isArray(this.output) + ? ((e = this.defaultArg(e, 0)), this.output[e].connect(t, 0, i)) + : this.output.connect(t, e, i), + this + ); + }), + (t.prototype.disconnect = function (t, e, i) { + this.isArray(this.output) + ? this.isNumber(t) + ? this.output[t].disconnect() + : ((e = this.defaultArg(e, 0)), this.output[e].disconnect(t, 0, i)) + : this.output.disconnect.apply(this.output, arguments); + }), + (t.prototype.connectSeries = function () { + if (arguments.length > 1) + for (var t = arguments[0], e = 1; e < arguments.length; e++) { + var i = arguments[e]; + t.connect(i), (t = i); + } + return this; + }), + (t.prototype.chain = function () { + if (arguments.length > 0) + for (var t = this, e = 0; e < arguments.length; e++) { + var i = arguments[e]; + t.connect(i), (t = i); + } + return this; + }), + (t.prototype.fan = function () { + if (arguments.length > 0) + for (var t = 0; t < arguments.length; t++) this.connect(arguments[t]); + return this; + }), + (AudioNode.prototype.chain = t.prototype.chain), + (AudioNode.prototype.fan = t.prototype.fan), + (t.prototype.defaultArg = function (t, e) { + if (this.isObject(t) && this.isObject(e)) { + var i = {}; + for (var n in t) i[n] = this.defaultArg(e[n], t[n]); + for (var o in e) i[o] = this.defaultArg(t[o], e[o]); + return i; + } + return this.isUndef(t) ? e : t; + }), + (t.prototype.optionsObject = function (t, e, i) { + var n = {}; + if (1 === t.length && this.isObject(t[0])) n = t[0]; + else for (var o = 0; o < e.length; o++) n[e[o]] = t[o]; + return this.isUndef(i) ? n : this.defaultArg(n, i); + }), + (t.prototype.isUndef = function (t) { + return "undefined" == typeof t; + }), + (t.prototype.isFunction = function (t) { + return "function" == typeof t; + }), + (t.prototype.isNumber = function (t) { + return "number" == typeof t; + }), + (t.prototype.isObject = function (t) { + return ( + "[object Object]" === Object.prototype.toString.call(t) && + t.constructor === Object + ); + }), + (t.prototype.isBoolean = function (t) { + return "boolean" == typeof t; + }), + (t.prototype.isArray = function (t) { + return Array.isArray(t); + }), + (t.prototype.isString = function (t) { + return "string" == typeof t; + }), + (t.noOp = function () {}), + (t.prototype._readOnly = function (t) { + if (Array.isArray(t)) + for (var e = 0; e < t.length; e++) this._readOnly(t[e]); + else Object.defineProperty(this, t, { writable: !1, enumerable: !0 }); + }), + (t.prototype._writable = function (t) { + if (Array.isArray(t)) + for (var e = 0; e < t.length; e++) this._writable(t[e]); + else Object.defineProperty(this, t, { writable: !0 }); + }), + (t.State = { Started: "started", Stopped: "stopped", Paused: "paused" }), + (t.prototype.equalPowerScale = function (t) { + var e = 0.5 * Math.PI; + return Math.sin(t * e); + }), + (t.prototype.dbToGain = function (t) { + return Math.pow(2, t / 6); + }), + (t.prototype.gainToDb = function (t) { + return 20 * (Math.log(t) / Math.LN10); + }), + (t.prototype.intervalToFrequencyRatio = function (t) { + return Math.pow(2, t / 12); + }), + (t.prototype.now = function () { + return t.context.now(); + }), + (t.now = function () { + return t.context.now(); + }), + (t.extend = function (e, i) { + function n() {} + t.prototype.isUndef(i) && (i = t), + (n.prototype = i.prototype), + (e.prototype = new n()), + (e.prototype.constructor = e), + (e._super = i); + }); + var e; + return ( + Object.defineProperty(t, "context", { + get: function () { + return e; + }, + set: function (i) { + (e = t.Context && i instanceof t.Context ? i : new t.Context(i)), + t.Context && t.Context.emit("init", e); + }, + }), + Object.defineProperty(t.prototype, "context", { + get: function () { + return t.context; + }, + }), + (t.setContext = function (e) { + t.context = e; + }), + Object.defineProperty(t.prototype, "blockTime", { + get: function () { + return 128 / this.context.sampleRate; + }, + }), + Object.defineProperty(t.prototype, "sampleTime", { + get: function () { + return 1 / this.context.sampleRate; + }, + }), + Object.defineProperty(t, "supported", { + get: function () { + var t = + window.hasOwnProperty("AudioContext") || + window.hasOwnProperty("webkitAudioContext"), + e = window.hasOwnProperty("Promise"), + i = window.hasOwnProperty("Worker"); + return t && e && i; + }, + }), + (t.version = "r10"), + !window.TONE_SILENCE_VERSION_LOGGING, + t + ); + })(); + var o; + o = (function (t) { + "use strict"; + return ( + (t.Emitter = function () { + this._events = {}; + }), + t.extend(t.Emitter), + (t.Emitter.prototype.on = function (t, e) { + for (var i = t.split(/\W+/), n = 0; n < i.length; n++) { + var o = i[n]; + this._events.hasOwnProperty(o) || (this._events[o] = []), + this._events[o].push(e); + } + return this; + }), + (t.Emitter.prototype.off = function (e, i) { + for (var n = e.split(/\W+/), o = 0; o < n.length; o++) + if (((e = n[o]), this._events.hasOwnProperty(e))) + if (t.prototype.isUndef(i)) this._events[e] = []; + else + for (var r = this._events[e], s = 0; s < r.length; s++) + r[s] === i && r.splice(s, 1); + return this; + }), + (t.Emitter.prototype.emit = function (t) { + if (this._events) { + var e = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(t)) + for (var i = this._events[t], n = 0, o = i.length; o > n; n++) + i[n].apply(this, e); + } + return this; + }), + (t.Emitter.mixin = function (e) { + var i = ["on", "off", "emit"]; + e._events = {}; + for (var n = 0; n < i.length; n++) { + var o = i[n], + r = t.Emitter.prototype[o]; + e[o] = r; + } + }), + (t.Emitter.prototype.dispose = function () { + return t.prototype.dispose.call(this), (this._events = null), this; + }), + t.Emitter + ); + })(n); + var r; + r = (function (t) { + function e() { + function e(e, i, o) { + if (e.input) + Array.isArray(e.input) + ? (t.prototype.isUndef(o) && (o = 0), this.connect(e.input[o])) + : this.connect(e.input, i, o); + else + try { + e instanceof AudioNode ? n.call(this, e, i, o) : n.call(this, e, i); + } catch (r) { + throw new Error("error connecting to node: " + e + "\n" + r); + } + } + function i(e, i, n) { + if (e && e.input && Array.isArray(e.input)) + t.prototype.isUndef(n) && (n = 0), this.disconnect(e.input[n], i, n); + else if (e && e.input) this.disconnect(e.input, i, n); + else + try { + o.apply(this, arguments); + } catch (r) { + throw new Error("error disconnecting node: " + e + "\n" + r); + } + } + var n = AudioNode.prototype.connect, + o = AudioNode.prototype.disconnect; + AudioNode.prototype.connect !== e && + ((AudioNode.prototype.connect = e), + (AudioNode.prototype.disconnect = i)); + } + return ( + !window.hasOwnProperty("AudioContext") && + window.hasOwnProperty("webkitAudioContext") && + (window.AudioContext = window.webkitAudioContext), + (t.Context = function (e) { + t.Emitter.call(this), + e || (e = new window.AudioContext()), + (this._context = e); + for (var i in this._context) this._defineProperty(this._context, i); + (this._latencyHint = "interactive"), + (this._lookAhead = 0.1), + (this._updateInterval = this._lookAhead / 3), + (this._computedUpdateInterval = 0), + (this._worker = this._createWorker()), + (this._constants = {}); + }), + t.extend(t.Context, t.Emitter), + t.Emitter.mixin(t.Context), + (t.Context.prototype._defineProperty = function (t, e) { + this.isUndef(this[e]) && + Object.defineProperty(this, e, { + get: function () { + return "function" == typeof t[e] ? t[e].bind(t) : t[e]; + }, + set: function (i) { + t[e] = i; + }, + }); + }), + (t.Context.prototype.now = function () { + return this._context.currentTime; + }), + (t.Context.prototype._createWorker = function () { + window.URL = window.URL || window.webkitURL; + var t = new Blob([ + "var timeoutTime = " + + (1e3 * this._updateInterval).toFixed(1) + + ";self.onmessage = function(msg){ timeoutTime = parseInt(msg.data);};function tick(){ setTimeout(tick, timeoutTime); self.postMessage('tick');}tick();", + ]), + e = URL.createObjectURL(t), + i = new Worker(e); + return ( + i.addEventListener( + "message", + function () { + this.emit("tick"); + }.bind(this) + ), + i.addEventListener( + "message", + function () { + var t = this.now(); + if (this.isNumber(this._lastUpdate)) { + var e = t - this._lastUpdate; + this._computedUpdateInterval = Math.max( + e, + 0.97 * this._computedUpdateInterval + ); + } + this._lastUpdate = t; + }.bind(this) + ), + i + ); + }), + (t.Context.prototype.getConstant = function (t) { + if (this._constants[t]) return this._constants[t]; + for ( + var e = this._context.createBuffer(1, 128, this._context.sampleRate), + i = e.getChannelData(0), + n = 0; + n < i.length; + n++ + ) + i[n] = t; + var o = this._context.createBufferSource(); + return ( + (o.channelCount = 1), + (o.channelCountMode = "explicit"), + (o.buffer = e), + (o.loop = !0), + o.start(0), + (this._constants[t] = o), + o + ); + }), + Object.defineProperty(t.Context.prototype, "lag", { + get: function () { + var t = this._computedUpdateInterval - this._updateInterval; + return (t = Math.max(t, 0)); + }, + }), + Object.defineProperty(t.Context.prototype, "lookAhead", { + get: function () { + return this._lookAhead; + }, + set: function (t) { + this._lookAhead = t; + }, + }), + Object.defineProperty(t.Context.prototype, "updateInterval", { + get: function () { + return this._updateInterval; + }, + set: function (e) { + (this._updateInterval = Math.max(e, t.prototype.blockTime)), + this._worker.postMessage(Math.max(1e3 * e, 1)); + }, + }), + Object.defineProperty(t.Context.prototype, "latencyHint", { + get: function () { + return this._latencyHint; + }, + set: function (t) { + var e = t; + if (((this._latencyHint = t), this.isString(t))) + switch (t) { + case "interactive": + (e = 0.1), (this._context.latencyHint = t); + break; + case "playback": + (e = 0.8), (this._context.latencyHint = t); + break; + case "balanced": + (e = 0.25), (this._context.latencyHint = t); + break; + case "fastest": + e = 0.01; + } + (this.lookAhead = e), (this.updateInterval = e / 3); + }, + }), + t.supported + ? (e(), (t.context = new t.Context())) + : console.warn("This browser does not support Tone.js"), + t.Context + ); + })(n); + var s; + s = (function (e, i, n) { + const o = new window.AudioContext(); + return ( + n.context.dispose(), + n.setContext(o), + (t.prototype.getAudioContext = function () { + return o; + }), + (t.prototype.userStartAudio = function (i, n) { + var r = i; + return ( + i instanceof t.Element + ? (r = i.elt) + : i instanceof Array && + i[0] instanceof t.Element && + (r = i.map(function (t) { + return t.elt; + })), + e(o, r, n) + ); + }), + o + ); + })(i, r, n); + var a; + a = (function (e) { + var i = function () { + (this.input = e.createGain()), + (this.output = e.createGain()), + (this.limiter = e.createDynamicsCompressor()), + (this.limiter.threshold.value = -3), + (this.limiter.ratio.value = 20), + (this.limiter.knee.value = 1), + (this.audiocontext = e), + this.output.disconnect(), + this.input.connect(this.limiter), + this.limiter.connect(this.output), + (this.meter = e.createGain()), + (this.fftMeter = e.createGain()), + this.output.connect(this.meter), + this.output.connect(this.fftMeter), + this.output.connect(this.audiocontext.destination), + (this.soundArray = []), + (this.parts = []), + (this.extensions = []); + }, + n = new i(); + return ( + (t.prototype.getMasterVolume = function () { + return n.output.gain.value; + }), + (t.prototype.masterVolume = function (t, e, i) { + if ("number" == typeof t) { + var e = e || 0, + i = i || 0, + o = n.audiocontext.currentTime, + r = n.output.gain.value; + n.output.gain.cancelScheduledValues(o + i), + n.output.gain.linearRampToValueAtTime(r, o + i), + n.output.gain.linearRampToValueAtTime(t, o + i + e); + } else { + if (!t) return n.output.gain; + t.connect(n.output.gain); + } + }), + (t.prototype.soundOut = t.soundOut = n), + (t.soundOut._silentNode = n.audiocontext.createGain()), + (t.soundOut._silentNode.gain.value = 0), + t.soundOut._silentNode.connect(n.audiocontext.destination), + n + ); + })(s); + var u; + u = (function () { + function e(t) { + var e, r; + (e = t.getChannelData(0)), + (r = t.numberOfChannels > 1 ? t.getChannelData(1) : e); + var s = i(e, r), + a = new window.ArrayBuffer(44 + 2 * s.length), + u = new window.DataView(a); + n(u, 0, "RIFF"), + u.setUint32(4, 36 + 2 * s.length, !0), + n(u, 8, "WAVE"), + n(u, 12, "fmt "), + u.setUint32(16, 16, !0), + u.setUint16(20, 1, !0), + u.setUint16(22, 2, !0), + u.setUint32(24, o.audiocontext.sampleRate, !0), + u.setUint32(28, 4 * o.audiocontext.sampleRate, !0), + u.setUint16(32, 4, !0), + u.setUint16(34, 16, !0), + n(u, 36, "data"), + u.setUint32(40, 2 * s.length, !0); + for (var c = s.length, p = 44, h = 1, l = 0; c > l; l++) + u.setInt16(p, s[l] * (32767 * h), !0), (p += 2); + return u; + } + function i(t, e) { + for ( + var i = t.length + e.length, n = new Float32Array(i), o = 0, r = 0; + i > r; + + ) + (n[r++] = t[o]), (n[r++] = e[o]), o++; + return n; + } + function n(t, e, i) { + for (var n = i.length, o = 0; n > o; o++) + t.setUint8(e + o, i.charCodeAt(o)); + } + var o = a; + (t.prototype.sampleRate = function () { + return o.audiocontext.sampleRate; + }), + (t.prototype.freqToMidi = function (t) { + var e = Math.log(t / 440) / Math.log(2), + i = Math.round(12 * e) + 69; + return i; + }); + var r = (t.prototype.midiToFreq = function (t) { + return 440 * Math.pow(2, (t - 69) / 12); + }), + s = function (t) { + if ("string" != typeof t) return t; + var e = { A: 21, B: 23, C: 24, D: 26, E: 28, F: 29, G: 31 }, + i = e[t[0].toUpperCase()], + n = ~~t.slice(-1); + switch (((i += 12 * (n - 1)), t[1])) { + case "#": + i += 1; + break; + case "b": + i -= 1; + } + return r(i); + }; + return ( + (t.prototype.soundFormats = function () { + o.extensions = []; + for (var t = 0; t < arguments.length; t++) { + if ( + ((arguments[t] = arguments[t].toLowerCase()), + !(["mp3", "wav", "ogg", "m4a", "aac"].indexOf(arguments[t]) > -1)) + ) + throw arguments[t] + " is not a valid sound format!"; + o.extensions.push(arguments[t]); + } + }), + (t.prototype.disposeSound = function () { + for (var t = 0; t < o.soundArray.length; t++) o.soundArray[t].dispose(); + }), + t.prototype.registerMethod("remove", t.prototype.disposeSound), + (t.prototype._checkFileFormats = function (e) { + var i; + if ("string" == typeof e) { + i = e; + var n = i.split(".").pop(); + if (["mp3", "wav", "ogg", "m4a", "aac"].indexOf(n) > -1) + if (t.prototype.isFileSupported(n)) i = i; + else + for ( + var r = i.split("."), s = r[r.length - 1], a = 0; + a < o.extensions.length; + a++ + ) { + var u = o.extensions[a], + c = t.prototype.isFileSupported(u); + if (c) { + (s = ""), 2 === r.length && (s += r[0]); + for (var a = 1; a <= r.length - 2; a++) { + var p = r[a]; + s += "." + p; + } + (i = s += "."), (i = i += u); + break; + } + } + else + for (var a = 0; a < o.extensions.length; a++) { + var u = o.extensions[a], + c = t.prototype.isFileSupported(u); + if (c) { + i = i + "." + u; + break; + } + } + } else if ("object" == typeof e) + for (var a = 0; a < e.length; a++) { + var u = e[a].split(".").pop(), + c = t.prototype.isFileSupported(u); + if (c) { + i = e[a]; + break; + } + } + return i; + }), + (t.prototype._mathChain = function (t, e, i, n, o) { + for (var r in t.mathOps) + t.mathOps[r] instanceof o && + (t.mathOps[r].dispose(), + (i = r), + i < t.mathOps.length - 1 && (n = t.mathOps[r + 1])); + return ( + t.mathOps[i - 1].disconnect(), + t.mathOps[i - 1].connect(e), + e.connect(n), + (t.mathOps[i] = e), + t + ); + }), + { convertToWav: e, midiToFreq: r, noteToFreq: s } + ); + })(a); + var c; + c = (function () { + var t = function (t, e, i) { + var n, + o, + r = new Error(); + (r.name = t), + (r.originalStack = r.stack + e), + (n = r.stack + e), + (r.failedPath = i); + var o = n.split("\n"); + return ( + (o = o.filter(function (t) { + return !t.match(/(p5.|native code|globalInit)/g); + })), + (r.stack = o.join("\n")), + r + ); + }; + return t; + })(); + var p; + p = (function () { + var e = a, + i = e.audiocontext; + "undefined" != typeof i.createStereoPanner + ? ((t.Panner = function (t, e) { + (this.stereoPanner = this.input = i.createStereoPanner()), + t.connect(this.stereoPanner), + this.stereoPanner.connect(e); + }), + (t.Panner.prototype.pan = function (t, e) { + var n = e || 0, + o = i.currentTime + n; + this.stereoPanner.pan.linearRampToValueAtTime(t, o); + }), + (t.Panner.prototype.inputChannels = function () {}), + (t.Panner.prototype.connect = function (t) { + this.stereoPanner.connect(t); + }), + (t.Panner.prototype.disconnect = function () { + this.stereoPanner && this.stereoPanner.disconnect(); + })) + : ((t.Panner = function (t, e, n) { + (this.input = i.createGain()), + t.connect(this.input), + (this.left = i.createGain()), + (this.right = i.createGain()), + (this.left.channelInterpretation = "discrete"), + (this.right.channelInterpretation = "discrete"), + n > 1 + ? ((this.splitter = i.createChannelSplitter(2)), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)) + : (this.input.connect(this.left), this.input.connect(this.right)), + (this.output = i.createChannelMerger(2)), + this.left.connect(this.output, 0, 1), + this.right.connect(this.output, 0, 0), + this.output.connect(e); + }), + (t.Panner.prototype.pan = function (t, e) { + var n = e || 0, + o = i.currentTime + n, + r = (t + 1) / 2, + s = Math.cos((r * Math.PI) / 2), + a = Math.sin((r * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(a, o), + this.right.gain.linearRampToValueAtTime(s, o); + }), + (t.Panner.prototype.inputChannels = function (t) { + 1 === t + ? (this.input.disconnect(), + this.input.connect(this.left), + this.input.connect(this.right)) + : 2 === t && + ((this.splitter = i.createChannelSplitter(2)), + this.input.disconnect(), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)); + }), + (t.Panner.prototype.connect = function (t) { + this.output.connect(t); + }), + (t.Panner.prototype.disconnect = function () { + this.output && this.output.disconnect(); + })); + })(a); + var h; + h = (function () { + function e(t, e) { + for (var i = {}, n = t.length, o = 0; n > o; o++) { + if (t[o] > e) { + var r = t[o], + s = new v(r, o); + (i[o] = s), (o += 6e3); + } + o++; + } + return i; + } + function i(t) { + for (var e = [], i = Object.keys(t).sort(), n = 0; n < i.length; n++) + for (var o = 0; 10 > o; o++) { + var r = t[i[n]], + s = t[i[n + o]]; + if (r && s) { + var a = r.sampleIndex, + u = s.sampleIndex, + c = u - a; + c > 0 && r.intervals.push(c); + var p = e.some(function (t) { + return t.interval === c ? (t.count++, t) : void 0; + }); + p || e.push({ interval: c, count: 1 }); + } + } + return e; + } + function n(t, e) { + var i = []; + return ( + t.forEach(function (t) { + try { + var n = Math.abs(60 / (t.interval / e)); + n = r(n); + var o = i.some(function (e) { + return e.tempo === n ? (e.count += t.count) : void 0; + }); + if (!o) { + if (isNaN(n)) return; + i.push({ tempo: Math.round(n), count: t.count }); + } + } catch (s) { + throw s; + } + }), + i + ); + } + function o(t, e, i, n) { + for (var o = [], s = Object.keys(t).sort(), a = 0; a < s.length; a++) + for (var u = s[a], c = t[u], p = 0; p < c.intervals.length; p++) { + var h = Math.round(Math.abs(60 / (c.intervals[p] / i))); + (h = r(h)), Math.abs(h - e) < n && o.push(c.sampleIndex / i); + } + return (o = o.filter(function (t, e, i) { + var n = i[e + 1] - t; + return n > 0.01 ? !0 : void 0; + })); + } + function r(t) { + if (isFinite(t) && 0 !== t) { + for (; 90 > t; ) t *= 2; + for (; t > 180 && t > 90; ) t /= 2; + return t; + } + } + function s(t) { + var e = t.inputBuffer.getChannelData(0); + (this._lastPos = e[e.length - 1] || 0), this._onTimeUpdate(self._lastPos); + } + function p(t) { + const e = t.target, + i = this; + (e._playing = !1), + e.removeEventListener("ended", i._clearOnEnd), + i._onended(i), + i.bufferSourceNodes.forEach(function (t, e) { + t._playing === !1 && i.bufferSourceNodes.splice(e); + }), + 0 === i.bufferSourceNodes.length && (i._playing = !1); + } + var h = c, + l = a, + f = l.audiocontext, + d = u.midiToFreq, + m = u.convertToWav; + (t.SoundFile = function (e, i, n, o) { + if ("undefined" != typeof e) { + if ("string" == typeof e || "string" == typeof e[0]) { + var r = t.prototype._checkFileFormats(e); + this.url = r; + } else if ( + "object" == typeof e && + !(window.File && window.FileReader && window.FileList && window.Blob) + ) + throw "Unable to load file because the File API is not supported"; + e.file && (e = e.file), (this.file = e); + } + (this._onended = function () {}), + (this._looping = !1), + (this._playing = !1), + (this._paused = !1), + (this._pauseTime = 0), + (this._cues = []), + (this._cueIDCounter = 0), + (this._lastPos = 0), + (this._counterNode = null), + (this._scopeNode = null), + (this.bufferSourceNodes = []), + (this.bufferSourceNode = null), + (this.buffer = null), + (this.playbackRate = 1), + (this.input = l.audiocontext.createGain()), + (this.output = l.audiocontext.createGain()), + (this.reversed = !1), + (this.startTime = 0), + (this.endTime = null), + (this.pauseTime = 0), + (this.mode = "sustain"), + (this.startMillis = null), + (this.panPosition = 0), + (this.panner = new t.Panner(this.output, l.input, 2)), + (this.url || this.file) && this.load(i, n), + l.soundArray.push(this), + "function" == typeof o + ? (this._whileLoading = o) + : (this._whileLoading = function () {}), + (this._onAudioProcess = s.bind(this)), + (this._clearOnEnd = p.bind(this)); + }), + t.prototype.registerPreloadMethod("loadSound", t.prototype), + (t.prototype.loadSound = function (e, i, n, o) { + window.location.origin.indexOf("file://") > -1 && + "undefined" === window.cordova && + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var r = this, + s = new t.SoundFile( + e, + function () { + "function" == typeof i && i.apply(r, arguments), + "function" == typeof r._decrementPreload && + r._decrementPreload(); + }, + n, + o + ); + return s; + }), + (t.SoundFile.prototype.load = function (t, e) { + var i = this, + n = new Error().stack; + if (void 0 !== this.url && "" !== this.url) { + var o = new XMLHttpRequest(); + o.addEventListener( + "progress", + function (t) { + i._updateProgress(t); + }, + !1 + ), + o.open("GET", this.url, !0), + (o.responseType = "arraybuffer"), + (o.onload = function () { + if (200 === o.status) { + if (!i.panner) return; + f.decodeAudioData( + o.response, + function (e) { + i.panner && + ((i.buffer = e), + i.panner.inputChannels(e.numberOfChannels), + t && t(i)); + }, + function () { + if (i.panner) { + var t = new h("decodeAudioData", n, i.url), + o = + "AudioContext error at decodeAudioData for " + i.url; + e + ? ((t.msg = o), e(t)) + : console.error( + o + + "\n The error stack trace includes: \n" + + t.stack + ); + } + } + ); + } else { + if (!i.panner) return; + var r = new h("loadSound", n, i.url), + s = + "Unable to load " + + i.url + + ". The request status was: " + + o.status + + " (" + + o.statusText + + ")"; + e + ? ((r.message = s), e(r)) + : console.error( + s + "\n The error stack trace includes: \n" + r.stack + ); + } + }), + (o.onerror = function () { + var t = new h("loadSound", n, i.url), + o = + "There was no response from the server at " + + i.url + + ". Check the url and internet connectivity."; + e + ? ((t.message = o), e(t)) + : console.error( + o + "\n The error stack trace includes: \n" + t.stack + ); + }), + o.send(); + } else if (void 0 !== this.file) { + var r = new FileReader(); + (r.onload = function () { + i.panner && + f.decodeAudioData(r.result, function (e) { + i.panner && + ((i.buffer = e), + i.panner.inputChannels(e.numberOfChannels), + t && t(i)); + }); + }), + (r.onerror = function (t) { + i.panner && onerror && onerror(t); + }), + r.readAsArrayBuffer(this.file); + } + }), + (t.SoundFile.prototype._updateProgress = function (t) { + if (t.lengthComputable) { + var e = (t.loaded / t.total) * 0.99; + this._whileLoading(e, t); + } else this._whileLoading("size unknown"); + }), + (t.SoundFile.prototype.isLoaded = function () { + return this.buffer ? !0 : !1; + }), + (t.SoundFile.prototype.play = function (t, e, i, n, o) { + if (!this.output) + return void console.warn("SoundFile.play() called after dispose"); + var r, + s, + a = l.audiocontext.currentTime, + u = t || 0; + if ( + (0 > u && (u = 0), + (u += a), + "undefined" != typeof e && this.rate(e), + "undefined" != typeof i && this.setVolume(i), + !this.buffer) + ) + throw "not ready to play file, buffer has yet to load. Try preload()"; + if ( + ((this._pauseTime = 0), + "restart" === this.mode && + this.buffer && + this.bufferSourceNode && + (this.bufferSourceNode.stop(u), this._counterNode.stop(u)), + "untildone" !== this.mode || !this.isPlaying()) + ) { + if ( + ((this.bufferSourceNode = this._initSourceNode()), + delete this._counterNode, + (this._counterNode = this._initCounterNode()), + n) + ) { + if (!(n >= 0 && n < this.buffer.duration)) + throw "start time out of range"; + r = n; + } else r = 0; + o && (o = o <= this.buffer.duration - r ? o : this.buffer.duration), + this._paused + ? (this.bufferSourceNode.start(u, this.pauseTime, o), + this._counterNode.start(u, this.pauseTime, o)) + : (this.bufferSourceNode.start(u, r, o), + this._counterNode.start(u, r, o)), + (this._playing = !0), + (this._paused = !1), + this.bufferSourceNodes.push(this.bufferSourceNode), + (this.bufferSourceNode._arrayIndex = + this.bufferSourceNodes.length - 1), + this.bufferSourceNode.addEventListener("ended", this._clearOnEnd), + (this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping), + this._looping === !0 && + ((s = o ? o : r - 1e-15), + (this.bufferSourceNode.loopStart = r), + (this.bufferSourceNode.loopEnd = s), + (this._counterNode.loopStart = r), + (this._counterNode.loopEnd = s)); + } + }), + (t.SoundFile.prototype.playMode = function (t) { + var e = t.toLowerCase(); + if ("restart" === e && this.buffer && this.bufferSourceNode) + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + var n = l.audiocontext.currentTime; + this.bufferSourceNodes[i].stop(n); + } + if ("restart" !== e && "sustain" !== e && "untildone" !== e) + throw 'Invalid play mode. Must be either "restart" or "sustain"'; + this.mode = e; + }), + (t.SoundFile.prototype.pause = function (t) { + var e = l.audiocontext.currentTime, + i = t || 0, + n = i + e; + this.isPlaying() && this.buffer && this.bufferSourceNode + ? ((this.pauseTime = this.currentTime()), + this.bufferSourceNode.stop(n), + this._counterNode.stop(n), + (this._paused = !0), + (this._playing = !1), + (this._pauseTime = this.currentTime())) + : (this._pauseTime = 0); + }), + (t.SoundFile.prototype.loop = function (t, e, i, n, o) { + (this._looping = !0), this.play(t, e, i, n, o); + }), + (t.SoundFile.prototype.setLoop = function (t) { + if (t === !0) this._looping = !0; + else { + if (t !== !1) throw "Error: setLoop accepts either true or false"; + this._looping = !1; + } + this.bufferSourceNode && + ((this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping)); + }), + (t.SoundFile.prototype.isLooping = function () { + return this.bufferSourceNode && + this._looping === !0 && + this.isPlaying() === !0 + ? !0 + : !1; + }), + (t.SoundFile.prototype.isPlaying = function () { + return this._playing; + }), + (t.SoundFile.prototype.isPaused = function () { + return this._paused; + }), + (t.SoundFile.prototype.stop = function (t) { + var e = t || 0; + if ("sustain" === this.mode || "untildone" === this.mode) + this.stopAll(e), + (this._playing = !1), + (this.pauseTime = 0), + (this._paused = !1); + else if (this.buffer && this.bufferSourceNode) { + var i = l.audiocontext.currentTime, + n = e || 0; + (this.pauseTime = 0), + this.bufferSourceNode.stop(i + n), + this._counterNode.stop(i + n), + (this._playing = !1), + (this._paused = !1); + } + }), + (t.SoundFile.prototype.stopAll = function (t) { + var e = l.audiocontext.currentTime, + i = t || 0; + if (this.buffer && this.bufferSourceNode) { + for (var n in this.bufferSourceNodes) { + const o = this.bufferSourceNodes[n]; + if (o) + try { + o.stop(e + i); + } catch (r) {} + } + this._counterNode.stop(e + i), this._onended(this); + } + }), + (t.SoundFile.prototype.setVolume = function (t, e, i) { + if ("number" == typeof t) { + var n = e || 0, + o = i || 0, + r = l.audiocontext.currentTime, + s = this.output.gain.value; + this.output.gain.cancelScheduledValues(r + o), + this.output.gain.linearRampToValueAtTime(s, r + o), + this.output.gain.linearRampToValueAtTime(t, r + o + n); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (t.SoundFile.prototype.amp = t.SoundFile.prototype.setVolume), + (t.SoundFile.prototype.fade = t.SoundFile.prototype.setVolume), + (t.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }), + (t.SoundFile.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (t.SoundFile.prototype.getPan = function () { + return this.panPosition; + }), + (t.SoundFile.prototype.rate = function (t) { + var e = !1; + if ("undefined" == typeof t) return this.playbackRate; + if ( + ((this.playbackRate = t), + 0 === t + ? (t = 1e-13) + : 0 > t && !this.reversed + ? ((t = Math.abs(t)), (e = !0)) + : t > 0 && this.reversed && (e = !0), + this.bufferSourceNode) + ) { + var i = l.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(i), + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + i + ), + this._counterNode.playbackRate.cancelScheduledValues(i), + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + i + ); + } + return e && this.reverseBuffer(), this.playbackRate; + }), + (t.SoundFile.prototype.setPitch = function (t) { + var e = d(t) / d(60); + this.rate(e); + }), + (t.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }), + (t.SoundFile.prototype.duration = function () { + return this.buffer ? this.buffer.duration : 0; + }), + (t.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / f.sampleRate + : this._lastPos / f.sampleRate; + }), + (t.SoundFile.prototype.jump = function (t, e) { + if (0 > t || t > this.buffer.duration) throw "jump time out of range"; + if (e > this.buffer.duration - t) throw "end time out of range"; + var i = t || 0, + n = e || void 0; + this.isPlaying() && this.stop(0), + this.play(0, this.playbackRate, this.output.gain.value, i, n); + }), + (t.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }), + (t.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }), + (t.SoundFile.prototype.frames = function () { + return this.buffer.length; + }), + (t.SoundFile.prototype.getPeaks = function (t) { + if (!this.buffer) throw "Cannot load peaks yet, buffer is not loaded"; + if ((t || (t = 5 * window.width), this.buffer)) { + for ( + var e = this.buffer, + i = e.length / t, + n = ~~(i / 10) || 1, + o = e.numberOfChannels, + r = new Float32Array(Math.round(t)), + s = 0; + o > s; + s++ + ) + for (var a = e.getChannelData(s), u = 0; t > u; u++) { + for ( + var c = ~~(u * i), p = ~~(c + i), h = 0, l = c; + p > l; + l += n + ) { + var f = a[l]; + f > h ? (h = f) : -f > h && (h = f); + } + (0 === s || Math.abs(h) > r[u]) && (r[u] = h); + } + return r; + } + }), + (t.SoundFile.prototype.reverseBuffer = function () { + if (!this.buffer) throw "SoundFile is not done loading"; + var t = this._lastPos / f.sampleRate, + e = this.getVolume(); + this.setVolume(0, 0.001); + const i = this.buffer.numberOfChannels; + for (var n = 0; i > n; n++) this.buffer.getChannelData(n).reverse(); + (this.reversed = !this.reversed), + t && this.jump(this.duration() - t), + this.setVolume(e, 0.001); + }), + (t.SoundFile.prototype.onended = function (t) { + return (this._onended = t), this; + }), + (t.SoundFile.prototype.add = function () {}), + (t.SoundFile.prototype.dispose = function () { + var t = l.audiocontext.currentTime, + e = l.soundArray.indexOf(this); + if ( + (l.soundArray.splice(e, 1), + this.stop(t), + this.buffer && this.bufferSourceNode) + ) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) + if (null !== this.bufferSourceNodes[i]) { + this.bufferSourceNodes[i].disconnect(); + try { + this.bufferSourceNodes[i].stop(t); + } catch (n) { + console.warning("no buffer source node to dispose"); + } + this.bufferSourceNodes[i] = null; + } + if (this.isPlaying()) { + try { + this._counterNode.stop(t); + } catch (n) { + console.log(n); + } + this._counterNode = null; + } + } + this.output && (this.output.disconnect(), (this.output = null)), + this.panner && (this.panner.disconnect(), (this.panner = null)); + }), + (t.SoundFile.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.panner.connect(t.input) + : this.panner.connect(t) + : this.panner.connect(l.input); + }), + (t.SoundFile.prototype.disconnect = function () { + this.panner && this.panner.disconnect(); + }), + (t.SoundFile.prototype.getLevel = function () { + console.warn( + "p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead" + ); + }), + (t.SoundFile.prototype.setPath = function (e, i) { + var n = t.prototype._checkFileFormats(e); + (this.url = n), this.load(i); + }), + (t.SoundFile.prototype.setBuffer = function (t) { + var e = t.length, + i = t[0].length, + n = f.createBuffer(e, i, f.sampleRate); + t[0] instanceof Float32Array || (t[0] = new Float32Array(t[0])); + for (var o = 0; e > o; o++) { + var r = n.getChannelData(o); + r.set(t[o]); + } + (this.buffer = n), this.panner.inputChannels(e); + }); + var y = function (t) { + const e = t.length, + i = f.createBuffer(1, t.length, f.sampleRate), + n = i.getChannelData(0); + for (var o = 0; e > o; o++) n[o] = o; + return i; + }; + (t.SoundFile.prototype._initCounterNode = function () { + var e = this, + i = f.currentTime, + n = f.createBufferSource(); + return ( + e._scopeNode && + (e._scopeNode.disconnect(), + e._scopeNode.removeEventListener("audioprocess", e._onAudioProcess), + delete e._scopeNode), + (e._scopeNode = f.createScriptProcessor(256, 1, 1)), + (n.buffer = y(e.buffer)), + n.playbackRate.setValueAtTime(e.playbackRate, i), + n.connect(e._scopeNode), + e._scopeNode.connect(t.soundOut._silentNode), + e._scopeNode.addEventListener("audioprocess", e._onAudioProcess), + n + ); + }), + (t.SoundFile.prototype._initSourceNode = function () { + var t = f.createBufferSource(); + return ( + (t.buffer = this.buffer), + (t.playbackRate.value = this.playbackRate), + t.connect(this.output), + t + ); + }), + (t.SoundFile.prototype.processPeaks = function (t, r, s, a) { + var u = this.buffer.length, + c = this.buffer.sampleRate, + p = this.buffer, + h = [], + l = r || 0.9, + f = l, + d = s || 0.22, + m = a || 200, + y = new window.OfflineAudioContext(1, u, c), + v = y.createBufferSource(); + v.buffer = p; + var g = y.createBiquadFilter(); + (g.type = "lowpass"), + v.connect(g), + g.connect(y.destination), + v.start(0), + y.startRendering(), + (y.oncomplete = function (r) { + if (self.panner) { + var s = r.renderedBuffer, + a = s.getChannelData(0); + do (h = e(a, f)), (f -= 0.005); + while (Object.keys(h).length < m && f >= d); + var u = i(h), + c = n(u, s.sampleRate), + p = c + .sort(function (t, e) { + return e.count - t.count; + }) + .splice(0, 5); + this.tempo = p[0].tempo; + var l = 5, + y = o(h, p[0].tempo, s.sampleRate, l); + t(y); + } + }); + }); + var v = function (t, e) { + (this.sampleIndex = e), + (this.amplitude = t), + (this.tempos = []), + (this.intervals = []); + }, + g = function (t, e, i, n) { + (this.callback = t), (this.time = e), (this.id = i), (this.val = n); + }; + (t.SoundFile.prototype.addCue = function (t, e, i) { + var n = this._cueIDCounter++, + o = new g(e, t, n, i); + return this._cues.push(o), n; + }), + (t.SoundFile.prototype.removeCue = function (t) { + for (var e = this._cues.length, i = 0; e > i; i++) { + var n = this._cues[i]; + if (n.id === t) { + this._cues.splice(i, 1); + break; + } + } + 0 === this._cues.length; + }), + (t.SoundFile.prototype.clearCues = function () { + this._cues = []; + }), + (t.SoundFile.prototype._onTimeUpdate = function (t) { + for ( + var e = t / this.buffer.sampleRate, i = this._cues.length, n = 0; + i > n; + n++ + ) { + var o = this._cues[n], + r = o.time, + s = o.val; + this._prevTime < r && e >= r && o.callback(s); + } + this._prevTime = e; + }), + (t.SoundFile.prototype.save = function (e) { + const i = m(this.buffer); + t.prototype.saveSound([i], e, "wav"); + }), + (t.SoundFile.prototype.getBlob = function () { + const t = m(this.buffer); + return new Blob([t], { type: "audio/wav" }); + }); + })(c, a, u, u); + var l; + l = (function () { + var e = a; + (t.Amplitude = function (t) { + (this.bufferSize = 2048), + (this.audiocontext = e.audiocontext), + (this.processor = this.audiocontext.createScriptProcessor( + this.bufferSize, + 2, + 1 + )), + (this.input = this.processor), + (this.output = this.audiocontext.createGain()), + (this.smoothing = t || 0), + (this.volume = 0), + (this.average = 0), + (this.stereoVol = [0, 0]), + (this.stereoAvg = [0, 0]), + (this.stereoVolNorm = [0, 0]), + (this.volMax = 0.001), + (this.normalize = !1), + (this.processor.onaudioprocess = this._audioProcess.bind(this)), + this.processor.connect(this.output), + (this.output.gain.value = 0), + this.output.connect(this.audiocontext.destination), + e.meter.connect(this.processor), + e.soundArray.push(this); + }), + (t.Amplitude.prototype.setInput = function (i, n) { + e.meter.disconnect(), + n && (this.smoothing = n), + null == i + ? (console.log( + "Amplitude input source is not ready! Connecting to master output instead" + ), + e.meter.connect(this.processor)) + : i instanceof t.Signal + ? i.output.connect(this.processor) + : i + ? (i.connect(this.processor), + this.processor.disconnect(), + this.processor.connect(this.output)) + : e.meter.connect(this.processor); + }), + (t.Amplitude.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : this.output.connect(t) + : this.output.connect(this.panner.connect(e.input)); + }), + (t.Amplitude.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.Amplitude.prototype._audioProcess = function (t) { + for (var e = 0; e < t.inputBuffer.numberOfChannels; e++) { + for ( + var i, + n = t.inputBuffer.getChannelData(e), + o = n.length, + r = 0, + s = 0, + a = 0; + o > a; + a++ + ) + (i = n[a]), + this.normalize + ? ((r += Math.max(Math.min(i / this.volMax, 1), -1)), + (s += + Math.max(Math.min(i / this.volMax, 1), -1) * + Math.max(Math.min(i / this.volMax, 1), -1))) + : ((r += i), (s += i * i)); + var u = r / o, + c = Math.sqrt(s / o); + (this.stereoVol[e] = Math.max(c, this.stereoVol[e] * this.smoothing)), + (this.stereoAvg[e] = Math.max( + u, + this.stereoVol[e] * this.smoothing + )), + (this.volMax = Math.max(this.stereoVol[e], this.volMax)); + } + var p = this, + h = this.stereoVol.reduce(function (t, e, i) { + return ( + (p.stereoVolNorm[i - 1] = Math.max( + Math.min(p.stereoVol[i - 1] / p.volMax, 1), + 0 + )), + (p.stereoVolNorm[i] = Math.max( + Math.min(p.stereoVol[i] / p.volMax, 1), + 0 + )), + t + e + ); + }); + (this.volume = h / this.stereoVol.length), + (this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0)); + }), + (t.Amplitude.prototype.getLevel = function (t) { + return "undefined" != typeof t + ? this.normalize + ? this.stereoVolNorm[t] + : this.stereoVol[t] + : this.normalize + ? this.volNorm + : this.volume; + }), + (t.Amplitude.prototype.toggleNormalize = function (t) { + "boolean" == typeof t + ? (this.normalize = t) + : (this.normalize = !this.normalize); + }), + (t.Amplitude.prototype.smooth = function (t) { + t >= 0 && 1 > t + ? (this.smoothing = t) + : console.log("Error: smoothing must be between 0 and 1"); + }), + (t.Amplitude.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.input && (this.input.disconnect(), delete this.input), + this.output && (this.output.disconnect(), delete this.output), + delete this.processor; + }); + })(a); + var f; + f = (function () { + var e = a; + (t.FFT = function (t, i) { + (this.input = this.analyser = e.audiocontext.createAnalyser()), + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (t) { + this.analyser.fftSize = 2 * t; + }, + configurable: !0, + enumerable: !0, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (t) { + this.analyser.smoothingTimeConstant = t; + }, + configurable: !0, + enumerable: !0, + }, + }), + this.smooth(t), + (this.bins = i || 1024), + e.fftMeter.connect(this.analyser), + (this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.bass = [20, 140]), + (this.lowMid = [140, 400]), + (this.mid = [400, 2600]), + (this.highMid = [2600, 5200]), + (this.treble = [5200, 14e3]), + e.soundArray.push(this); + }), + (t.FFT.prototype.setInput = function (t) { + t + ? (t.output + ? t.output.connect(this.analyser) + : t.connect && t.connect(this.analyser), + e.fftMeter.disconnect()) + : e.fftMeter.connect(this.analyser); + }), + (t.FFT.prototype.waveform = function () { + for (var e, i, n, s = 0; s < arguments.length; s++) + "number" == typeof arguments[s] && + ((e = arguments[s]), (this.analyser.fftSize = 2 * e)), + "string" == typeof arguments[s] && (i = arguments[s]); + if (i && !t.prototype._isSafari()) + return ( + o(this, this.timeDomain), + this.analyser.getFloatTimeDomainData(this.timeDomain), + this.timeDomain + ); + r(this, this.timeDomain), + this.analyser.getByteTimeDomainData(this.timeDomain); + for (var n = new Array(), a = 0; a < this.timeDomain.length; a++) { + var u = t.prototype.map(this.timeDomain[a], 0, 255, -1, 1); + n.push(u); + } + return n; + }), + (t.FFT.prototype.analyze = function () { + for (var t, e = 0; e < arguments.length; e++) + "number" == typeof arguments[e] && + ((this.bins = arguments[e]), + (this.analyser.fftSize = 2 * this.bins)), + "string" == typeof arguments[e] && (t = arguments[e]); + if (t && "db" === t.toLowerCase()) + return ( + i(this), + this.analyser.getFloatFrequencyData(this.freqDomain), + this.freqDomain + ); + n(this, this.freqDomain), + this.analyser.getByteFrequencyData(this.freqDomain); + var o = Array.apply([], this.freqDomain); + return o.length === this.analyser.fftSize, o.constructor === Array, o; + }), + (t.FFT.prototype.getEnergy = function (t, i) { + var n = e.audiocontext.sampleRate / 2; + if ( + ("bass" === t + ? ((t = this.bass[0]), (i = this.bass[1])) + : "lowMid" === t + ? ((t = this.lowMid[0]), (i = this.lowMid[1])) + : "mid" === t + ? ((t = this.mid[0]), (i = this.mid[1])) + : "highMid" === t + ? ((t = this.highMid[0]), (i = this.highMid[1])) + : "treble" === t && ((t = this.treble[0]), (i = this.treble[1])), + "number" != typeof t) + ) + throw "invalid input for getEnergy()"; + if (i) { + if (t && i) { + if (t > i) { + var o = i; + (i = t), (t = o); + } + for ( + var r = Math.round((t / n) * this.freqDomain.length), + s = Math.round((i / n) * this.freqDomain.length), + a = 0, + u = 0, + c = r; + s >= c; + c++ + ) + (a += this.freqDomain[c]), (u += 1); + var p = a / u; + return p; + } + throw "invalid input for getEnergy()"; + } + var h = Math.round((t / n) * this.freqDomain.length); + return this.freqDomain[h]; + }), + (t.FFT.prototype.getFreq = function (t, e) { + console.log("getFreq() is deprecated. Please use getEnergy() instead."); + var i = this.getEnergy(t, e); + return i; + }), + (t.FFT.prototype.getCentroid = function () { + for ( + var t = e.audiocontext.sampleRate / 2, i = 0, n = 0, o = 0; + o < this.freqDomain.length; + o++ + ) + (i += o * this.freqDomain[o]), (n += this.freqDomain[o]); + var r = 0; + 0 !== n && (r = i / n); + var s = r * (t / this.freqDomain.length); + return s; + }), + (t.FFT.prototype.smooth = function (t) { + return "undefined" != typeof t && (this.smoothing = t), this.smoothing; + }), + (t.FFT.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.analyser && (this.analyser.disconnect(), delete this.analyser); + }), + (t.FFT.prototype.linAverages = function (t) { + for ( + var t = t || 16, + e = this.freqDomain, + i = e.length, + n = Math.floor(i / t), + o = new Array(t), + r = 0, + s = 0; + i > s; + s++ + ) + (o[r] = void 0 !== o[r] ? (o[r] + e[s]) / 2 : e[s]), + s % n === n - 1 && r++; + return o; + }), + (t.FFT.prototype.logAverages = function (t) { + for ( + var i = e.audiocontext.sampleRate / 2, + n = this.freqDomain, + o = n.length, + r = new Array(t.length), + s = 0, + a = 0; + o > a; + a++ + ) { + var u = Math.round((a * i) / this.freqDomain.length); + u > t[s].hi && s++, + (r[s] = void 0 !== r[s] ? (r[s] + n[a]) / 2 : n[a]); + } + return r; + }), + (t.FFT.prototype.getOctaveBands = function (t, i) { + var t = t || 3, + i = i || 15.625, + n = [], + o = { + lo: i / Math.pow(2, 1 / (2 * t)), + ctr: i, + hi: i * Math.pow(2, 1 / (2 * t)), + }; + n.push(o); + for (var r = e.audiocontext.sampleRate / 2; o.hi < r; ) { + var s = {}; + (s.lo = o.hi), + (s.ctr = o.ctr * Math.pow(2, 1 / t)), + (s.hi = s.ctr * Math.pow(2, 1 / (2 * t))), + n.push(s), + (o = s); + } + return n; + }); + var i = function (t) { + t.freqDomain instanceof Float32Array == !1 && + (t.freqDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + n = function (t) { + t.freqDomain instanceof Uint8Array == !1 && + (t.freqDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }, + o = function (t) { + t.timeDomain instanceof Float32Array == !1 && + (t.timeDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + r = function (t) { + t.timeDomain instanceof Uint8Array == !1 && + (t.timeDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }; + })(a); + var d; + d = (function (t) { + "use strict"; + return ( + (t.SignalBase = function () {}), + t.extend(t.SignalBase), + (t.SignalBase.prototype.connect = function (e, i, n) { + return ( + (t.Signal && t.Signal === e.constructor) || + (t.Param && t.Param === e.constructor) || + (t.TimelineSignal && t.TimelineSignal === e.constructor) + ? (e._param.cancelScheduledValues(0), + (e._param.value = 0), + (e.overridden = !0)) + : e instanceof AudioParam && + (e.cancelScheduledValues(0), (e.value = 0)), + t.prototype.connect.call(this, e, i, n), + this + ); + }), + t.SignalBase + ); + })(n); + var m; + m = (function (t) { + "use strict"; + return ( + (t.WaveShaper = function (t, e) { + (this._shaper = + this.input = + this.output = + this.context.createWaveShaper()), + (this._curve = null), + Array.isArray(t) + ? (this.curve = t) + : isFinite(t) || this.isUndef(t) + ? (this._curve = new Float32Array(this.defaultArg(t, 1024))) + : this.isFunction(t) && + ((this._curve = new Float32Array(this.defaultArg(e, 1024))), + this.setMap(t)); + }), + t.extend(t.WaveShaper, t.SignalBase), + (t.WaveShaper.prototype.setMap = function (t) { + for (var e = 0, i = this._curve.length; i > e; e++) { + var n = (e / (i - 1)) * 2 - 1; + this._curve[e] = t(n, e); + } + return (this._shaper.curve = this._curve), this; + }), + Object.defineProperty(t.WaveShaper.prototype, "curve", { + get: function () { + return this._shaper.curve; + }, + set: function (t) { + (this._curve = new Float32Array(t)), + (this._shaper.curve = this._curve); + }, + }), + Object.defineProperty(t.WaveShaper.prototype, "oversample", { + get: function () { + return this._shaper.oversample; + }, + set: function (t) { + if (-1 === ["none", "2x", "4x"].indexOf(t)) + throw new RangeError( + "Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'" + ); + this._shaper.oversample = t; + }, + }), + (t.WaveShaper.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._shaper.disconnect(), + (this._shaper = null), + (this._curve = null), + this + ); + }), + t.WaveShaper + ); + })(n); + var y; + y = (function (t) { + return ( + (t.TimeBase = function (e, i) { + if (!(this instanceof t.TimeBase)) return new t.TimeBase(e, i); + if (((this._expr = this._noOp), e instanceof t.TimeBase)) this.copy(e); + else if (!this.isUndef(i) || this.isNumber(e)) { + i = this.defaultArg(i, this._defaultUnits); + var n = this._primaryExpressions[i].method; + this._expr = n.bind(this, e); + } else + this.isString(e) + ? this.set(e) + : this.isUndef(e) && (this._expr = this._defaultExpr()); + }), + t.extend(t.TimeBase), + (t.TimeBase.prototype.set = function (t) { + return (this._expr = this._parseExprString(t)), this; + }), + (t.TimeBase.prototype.clone = function () { + var t = new this.constructor(); + return t.copy(this), t; + }), + (t.TimeBase.prototype.copy = function (t) { + var e = t._expr(); + return this.set(e); + }), + (t.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (t) { + return ( + (t = parseInt(t)), + 1 === t + ? this._beatsToUnits(this._timeSignature()) + : this._beatsToUnits(4 / t) + ); + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (t) { + return (t = parseInt(t)), this._beatsToUnits(8 / (3 * parseInt(t))); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (t) { + return this._beatsToUnits(parseInt(t) * this._timeSignature()); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (t) { + return this._ticksToUnits(parseInt(t)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (t) { + return this._frequencyToUnits(parseFloat(t)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, i) { + var n = 0; + return ( + t && + "0" !== t && + (n += this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (n += this._beatsToUnits(parseFloat(e))), + i && "0" !== i && (n += this._beatsToUnits(parseFloat(i) / 4)), + n + ); + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (t) { + return this._secondsToUnits(parseFloat(t)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (t) { + return parseInt(t) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (t) { + return this._primaryExpressions[this._defaultUnits].method.call( + this, + t + ); + }, + }, + }), + (t.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (t, e) { + return t() + e(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (t, e) { + return t() - e(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (t, e) { + return t() * e(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (t, e) { + return t() / e(); + }, + }, + }), + (t.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (t) { + return -t(); + }, + }, + }), + (t.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }), + (t.TimeBase.prototype._tokenize = function (t) { + function e(t, e) { + for ( + var i = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ], + n = 0; + n < i.length; + n++ + ) { + var o = e[i[n]]; + for (var r in o) { + var s = o[r], + a = s.regexp, + u = t.match(a); + if (null !== u) + return { + method: s.method, + precedence: s.precedence, + regexp: s.regexp, + value: u[0], + }; + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + t); + } + for (var i = -1, n = []; t.length > 0; ) { + t = t.trim(); + var o = e(t, this); + n.push(o), (t = t.substr(o.value.length)); + } + return { + next: function () { + return n[++i]; + }, + peek: function () { + return n[i + 1]; + }, + }; + }), + (t.TimeBase.prototype._matchGroup = function (t, e, i) { + var n = !1; + if (!this.isUndef(t)) + for (var o in e) { + var r = e[o]; + if (r.regexp.test(t.value)) { + if (this.isUndef(i)) return r; + if (r.precedence === i) return r; + } + } + return n; + }), + (t.TimeBase.prototype._parseBinary = function (t, e) { + this.isUndef(e) && (e = 2); + var i; + i = 0 > e ? this._parseUnary(t) : this._parseBinary(t, e - 1); + for ( + var n = t.peek(); + n && this._matchGroup(n, this._binaryExpressions, e); + + ) + (n = t.next()), + (i = n.method.bind(this, i, this._parseBinary(t, e - 1))), + (n = t.peek()); + return i; + }), + (t.TimeBase.prototype._parseUnary = function (t) { + var e, i; + e = t.peek(); + var n = this._matchGroup(e, this._unaryExpressions); + return n + ? ((e = t.next()), (i = this._parseUnary(t)), n.method.bind(this, i)) + : this._parsePrimary(t); + }), + (t.TimeBase.prototype._parsePrimary = function (t) { + var e, i; + if (((e = t.peek()), this.isUndef(e))) + throw new SyntaxError("Tone.TimeBase: Unexpected end of expression"); + if (this._matchGroup(e, this._primaryExpressions)) { + e = t.next(); + var n = e.value.match(e.regexp); + return e.method.bind(this, n[1], n[2], n[3]); + } + if (e && "(" === e.value) { + if ( + (t.next(), + (i = this._parseBinary(t)), + (e = t.next()), + !e || ")" !== e.value) + ) + throw new SyntaxError("Expected )"); + return i; + } + throw new SyntaxError("Tone.TimeBase: Cannot process token " + e.value); + }), + (t.TimeBase.prototype._parseExprString = function (t) { + this.isString(t) || (t = t.toString()); + var e = this._tokenize(t), + i = this._parseBinary(e); + return i; + }), + (t.TimeBase.prototype._noOp = function () { + return 0; + }), + (t.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }), + (t.TimeBase.prototype._defaultUnits = "s"), + (t.TimeBase.prototype._frequencyToUnits = function (t) { + return 1 / t; + }), + (t.TimeBase.prototype._beatsToUnits = function (e) { + return (60 / t.Transport.bpm.value) * e; + }), + (t.TimeBase.prototype._secondsToUnits = function (t) { + return t; + }), + (t.TimeBase.prototype._ticksToUnits = function (e) { + return e * (this._beatsToUnits(1) / t.Transport.PPQ); + }), + (t.TimeBase.prototype._timeSignature = function () { + return t.Transport.timeSignature; + }), + (t.TimeBase.prototype._pushExpr = function (e, i, n) { + return ( + e instanceof t.TimeBase || (e = new this.constructor(e, n)), + (this._expr = this._binaryExpressions[i].method.bind( + this, + this._expr, + e._expr + )), + this + ); + }), + (t.TimeBase.prototype.add = function (t, e) { + return this._pushExpr(t, "+", e); + }), + (t.TimeBase.prototype.sub = function (t, e) { + return this._pushExpr(t, "-", e); + }), + (t.TimeBase.prototype.mult = function (t, e) { + return this._pushExpr(t, "*", e); + }), + (t.TimeBase.prototype.div = function (t, e) { + return this._pushExpr(t, "/", e); + }), + (t.TimeBase.prototype.valueOf = function () { + return this._expr(); + }), + (t.TimeBase.prototype.dispose = function () { + this._expr = null; + }), + t.TimeBase + ); + })(n); + var v; + v = (function (t) { + return ( + (t.Time = function (e, i) { + return this instanceof t.Time + ? ((this._plusNow = !1), void t.TimeBase.call(this, e, i)) + : new t.Time(e, i); + }), + t.extend(t.Time, t.TimeBase), + (t.Time.prototype._unaryExpressions = Object.create( + t.TimeBase.prototype._unaryExpressions + )), + (t.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (e) { + return t.Transport.nextSubdivision(e()); + }, + }), + (t.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (t) { + return (this._plusNow = !0), t(); + }, + }), + (t.Time.prototype.quantize = function (t, e) { + return ( + (e = this.defaultArg(e, 1)), + (this._expr = function (t, e, i) { + (t = t()), (e = e.toSeconds()); + var n = Math.round(t / e), + o = n * e, + r = o - t; + return t + r * i; + }.bind(this, this._expr, new this.constructor(t), e)), + this + ); + }), + (t.Time.prototype.addNow = function () { + return (this._plusNow = !0), this; + }), + (t.Time.prototype._defaultExpr = function () { + return (this._plusNow = !0), this._noOp; + }), + (t.Time.prototype.copy = function (e) { + return ( + t.TimeBase.prototype.copy.call(this, e), + (this._plusNow = e._plusNow), + this + ); + }), + (t.Time.prototype.toNotation = function () { + var t = this.toSeconds(), + e = ["1m", "2n", "4n", "8n", "16n", "32n", "64n", "128n"], + i = this._toNotationHelper(t, e), + n = [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ], + o = this._toNotationHelper(t, n); + return o.split("+").length < i.split("+").length ? o : i; + }), + (t.Time.prototype._toNotationHelper = function (t, e) { + for ( + var i = this._notationToUnits(e[e.length - 1]), n = "", o = 0; + o < e.length; + o++ + ) { + var r = this._notationToUnits(e[o]), + s = t / r, + a = 1e-6; + if ((a > 1 - (s % 1) && (s += a), (s = Math.floor(s)), s > 0)) { + if ( + ((n += 1 === s ? e[o] : s.toString() + "*" + e[o]), + (t -= s * r), + i > t) + ) + break; + n += " + "; + } + } + return "" === n && (n = "0"), n; + }), + (t.Time.prototype._notationToUnits = function (t) { + for ( + var e = this._primaryExpressions, i = [e.n, e.t, e.m], n = 0; + n < i.length; + n++ + ) { + var o = i[n], + r = t.match(o.regexp); + if (r) return o.method.call(this, r[1]); + } + }), + (t.Time.prototype.toBarsBeatsSixteenths = function () { + var t = this._beatsToUnits(1), + e = this.toSeconds() / t, + i = Math.floor(e / this._timeSignature()), + n = (e % 1) * 4; + (e = Math.floor(e) % this._timeSignature()), + (n = n.toString()), + n.length > 3 && (n = parseFloat(n).toFixed(3)); + var o = [i, e, n]; + return o.join(":"); + }), + (t.Time.prototype.toTicks = function () { + var e = this._beatsToUnits(1), + i = this.valueOf() / e; + return Math.floor(i * t.Transport.PPQ); + }), + (t.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }), + (t.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + (t.Time.prototype.toSeconds = function () { + return this.valueOf(); + }), + (t.Time.prototype.toMilliseconds = function () { + return 1e3 * this.toSeconds(); + }), + (t.Time.prototype.valueOf = function () { + var t = this._expr(); + return t + (this._plusNow ? this.now() : 0); + }), + t.Time + ); + })(n); + var g; + g = (function (t) { + (t.Frequency = function (e, i) { + return this instanceof t.Frequency + ? void t.TimeBase.call(this, e, i) + : new t.Frequency(e, i); + }), + t.extend(t.Frequency, t.TimeBase), + (t.Frequency.prototype._primaryExpressions = Object.create( + t.TimeBase.prototype._primaryExpressions + )), + (t.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (t) { + return this.midiToFrequency(t); + }, + }), + (t.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (t, i) { + var n = e[t.toLowerCase()], + o = n + 12 * (parseInt(i) + 1); + return this.midiToFrequency(o); + }, + }), + (t.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, i) { + var n = 1; + return ( + t && + "0" !== t && + (n *= this._beatsToUnits(this._timeSignature() * parseFloat(t))), + e && "0" !== e && (n *= this._beatsToUnits(parseFloat(e))), + i && "0" !== i && (n *= this._beatsToUnits(parseFloat(i) / 4)), + n + ); + }, + }), + (t.Frequency.prototype.transpose = function (t) { + return ( + (this._expr = function (t, e) { + var i = t(); + return i * this.intervalToFrequencyRatio(e); + }.bind(this, this._expr, t)), + this + ); + }), + (t.Frequency.prototype.harmonize = function (t) { + return ( + (this._expr = function (t, e) { + for (var i = t(), n = [], o = 0; o < e.length; o++) + n[o] = i * this.intervalToFrequencyRatio(e[o]); + return n; + }.bind(this, this._expr, t)), + this + ); + }), + (t.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }), + (t.Frequency.prototype.toNote = function () { + var e = this.valueOf(), + n = Math.log(e / t.Frequency.A4) / Math.LN2, + o = Math.round(12 * n) + 57, + r = Math.floor(o / 12); + 0 > r && (o += -12 * r); + var s = i[o % 12]; + return s + r.toString(); + }), + (t.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }), + (t.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }), + (t.Frequency.prototype.toTicks = function () { + var e = this._beatsToUnits(1), + i = this.valueOf() / e; + return Math.floor(i * t.Transport.PPQ); + }), + (t.Frequency.prototype._frequencyToUnits = function (t) { + return t; + }), + (t.Frequency.prototype._ticksToUnits = function (e) { + return 1 / ((60 * e) / (t.Transport.bpm.value * t.Transport.PPQ)); + }), + (t.Frequency.prototype._beatsToUnits = function (e) { + return 1 / t.TimeBase.prototype._beatsToUnits.call(this, e); + }), + (t.Frequency.prototype._secondsToUnits = function (t) { + return 1 / t; + }), + (t.Frequency.prototype._defaultUnits = "hz"); + var e = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }, + i = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + return ( + (t.Frequency.A4 = 440), + (t.Frequency.prototype.midiToFrequency = function (e) { + return t.Frequency.A4 * Math.pow(2, (e - 69) / 12); + }), + (t.Frequency.prototype.frequencyToMidi = function (e) { + return 69 + (12 * Math.log(e / t.Frequency.A4)) / Math.LN2; + }), + t.Frequency + ); + })(n); + var _; + _ = (function (t) { + return ( + (t.TransportTime = function (e, i) { + return this instanceof t.TransportTime + ? void t.Time.call(this, e, i) + : new t.TransportTime(e, i); + }), + t.extend(t.TransportTime, t.Time), + (t.TransportTime.prototype._unaryExpressions = Object.create( + t.Time.prototype._unaryExpressions + )), + (t.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (e) { + var i = this._secondsToTicks(e()), + n = Math.ceil(t.Transport.ticks / i); + return this._ticksToUnits(n * i); + }, + }), + (t.TransportTime.prototype._secondsToTicks = function (e) { + var i = this._beatsToUnits(1), + n = e / i; + return Math.round(n * t.Transport.PPQ); + }), + (t.TransportTime.prototype.valueOf = function () { + var e = this._secondsToTicks(this._expr()); + return e + (this._plusNow ? t.Transport.ticks : 0); + }), + (t.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }), + (t.TransportTime.prototype.toSeconds = function () { + var e = this._expr(); + return e + (this._plusNow ? t.Transport.seconds : 0); + }), + (t.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + t.TransportTime + ); + })(n); + var T; + T = (function (t) { + return ( + (t.Type = { + Default: "number", + Time: "time", + Frequency: "frequency", + TransportTime: "transportTime", + Ticks: "ticks", + NormalRange: "normalRange", + AudioRange: "audioRange", + Decibels: "db", + Interval: "interval", + BPM: "bpm", + Positive: "positive", + Cents: "cents", + Degrees: "degrees", + MIDI: "midi", + BarsBeatsSixteenths: "barsBeatsSixteenths", + Samples: "samples", + Hertz: "hertz", + Note: "note", + Milliseconds: "milliseconds", + Seconds: "seconds", + Notation: "notation", + }), + (t.prototype.toSeconds = function (e) { + return this.isNumber(e) + ? e + : this.isUndef(e) + ? this.now() + : this.isString(e) + ? new t.Time(e).toSeconds() + : e instanceof t.TimeBase + ? e.toSeconds() + : void 0; + }), + (t.prototype.toFrequency = function (e) { + return this.isNumber(e) + ? e + : this.isString(e) || this.isUndef(e) + ? new t.Frequency(e).valueOf() + : e instanceof t.TimeBase + ? e.toFrequency() + : void 0; + }), + (t.prototype.toTicks = function (e) { + return this.isNumber(e) || this.isString(e) + ? new t.TransportTime(e).toTicks() + : this.isUndef(e) + ? t.Transport.ticks + : e instanceof t.TimeBase + ? e.toTicks() + : void 0; + }), + t + ); + })(n, v, g, _); + var b; + b = (function (t) { + "use strict"; + return ( + (t.Param = function () { + var e = this.optionsObject( + arguments, + ["param", "units", "convert"], + t.Param.defaults + ); + (this._param = this.input = e.param), + (this.units = e.units), + (this.convert = e.convert), + (this.overridden = !1), + (this._lfo = null), + this.isObject(e.lfo) + ? (this.value = e.lfo) + : this.isUndef(e.value) || (this.value = e.value); + }), + t.extend(t.Param), + (t.Param.defaults = { + units: t.Type.Default, + convert: !0, + param: void 0, + }), + Object.defineProperty(t.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (e) { + if (this.isObject(e)) { + if (this.isUndef(t.LFO)) + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + this._lfo && this._lfo.dispose(), + (this._lfo = new t.LFO(e).start()), + this._lfo.connect(this.input); + } else { + var i = this._fromUnits(e); + this._param.cancelScheduledValues(0), (this._param.value = i); + } + }, + }), + (t.Param.prototype._fromUnits = function (e) { + if (!this.convert && !this.isUndef(this.convert)) return e; + switch (this.units) { + case t.Type.Time: + return this.toSeconds(e); + case t.Type.Frequency: + return this.toFrequency(e); + case t.Type.Decibels: + return this.dbToGain(e); + case t.Type.NormalRange: + return Math.min(Math.max(e, 0), 1); + case t.Type.AudioRange: + return Math.min(Math.max(e, -1), 1); + case t.Type.Positive: + return Math.max(e, 0); + default: + return e; + } + }), + (t.Param.prototype._toUnits = function (e) { + if (!this.convert && !this.isUndef(this.convert)) return e; + switch (this.units) { + case t.Type.Decibels: + return this.gainToDb(e); + default: + return e; + } + }), + (t.Param.prototype._minOutput = 1e-5), + (t.Param.prototype.setValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (e = this.toSeconds(e)), + e <= this.now() + this.blockTime + ? (this._param.value = t) + : this._param.setValueAtTime(t, e), + this + ); + }), + (t.Param.prototype.setRampPoint = function (t) { + t = this.defaultArg(t, this.now()); + var e = this._param.value; + return ( + 0 === e && (e = this._minOutput), + this._param.setValueAtTime(e, t), + this + ); + }), + (t.Param.prototype.linearRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + this._param.linearRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (t.Param.prototype.exponentialRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + this._param.exponentialRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (t.Param.prototype.exponentialRampToValue = function (t, e, i) { + return ( + (i = this.toSeconds(i)), + this.setRampPoint(i), + this.exponentialRampToValueAtTime(t, i + this.toSeconds(e)), + this + ); + }), + (t.Param.prototype.linearRampToValue = function (t, e, i) { + return ( + (i = this.toSeconds(i)), + this.setRampPoint(i), + this.linearRampToValueAtTime(t, i + this.toSeconds(e)), + this + ); + }), + (t.Param.prototype.setTargetAtTime = function (t, e, i) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + (i = Math.max(this._minOutput, i)), + this._param.setTargetAtTime(t, this.toSeconds(e), i), + this + ); + }), + (t.Param.prototype.setValueCurveAtTime = function (t, e, i) { + for (var n = 0; n < t.length; n++) t[n] = this._fromUnits(t[n]); + return ( + this._param.setValueCurveAtTime( + t, + this.toSeconds(e), + this.toSeconds(i) + ), + this + ); + }), + (t.Param.prototype.cancelScheduledValues = function (t) { + return this._param.cancelScheduledValues(this.toSeconds(t)), this; + }), + (t.Param.prototype.rampTo = function (e, i, n) { + return ( + (i = this.defaultArg(i, 0)), + this.units === t.Type.Frequency || + this.units === t.Type.BPM || + this.units === t.Type.Decibels + ? this.exponentialRampToValue(e, i, n) + : this.linearRampToValue(e, i, n), + this + ); + }), + Object.defineProperty(t.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, + }), + (t.Param.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + (this._param = null), + this._lfo && (this._lfo.dispose(), (this._lfo = null)), + this + ); + }), + t.Param + ); + })(n); + var x; + x = (function (t) { + "use strict"; + return ( + window.GainNode && + !AudioContext.prototype.createGain && + (AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode), + (t.Gain = function () { + var e = this.optionsObject( + arguments, + ["gain", "units"], + t.Gain.defaults + ); + (this.input = this.output = this._gainNode = this.context.createGain()), + (this.gain = new t.Param({ + param: this._gainNode.gain, + units: e.units, + value: e.gain, + convert: e.convert, + })), + this._readOnly("gain"); + }), + t.extend(t.Gain), + (t.Gain.defaults = { gain: 1, convert: !0 }), + (t.Gain.prototype.dispose = function () { + t.Param.prototype.dispose.call(this), + this._gainNode.disconnect(), + (this._gainNode = null), + this._writable("gain"), + this.gain.dispose(), + (this.gain = null); + }), + (t.prototype.createInsOuts = function (e, i) { + 1 === e + ? (this.input = new t.Gain()) + : e > 1 && (this.input = new Array(e)), + 1 === i + ? (this.output = new t.Gain()) + : i > 1 && (this.output = new Array(e)); + }), + t.Gain + ); + })(n, b); + var S; + S = (function (t) { + "use strict"; + return ( + (t.Signal = function () { + var e = this.optionsObject( + arguments, + ["value", "units"], + t.Signal.defaults + ); + (this.output = this._gain = this.context.createGain()), + (e.param = this._gain.gain), + t.Param.call(this, e), + (this.input = this._param = this._gain.gain), + this.context.getConstant(1).chain(this._gain); + }), + t.extend(t.Signal, t.Param), + (t.Signal.defaults = { value: 0, units: t.Type.Default, convert: !0 }), + (t.Signal.prototype.connect = t.SignalBase.prototype.connect), + (t.Signal.prototype.dispose = function () { + return ( + t.Param.prototype.dispose.call(this), + (this._param = null), + this._gain.disconnect(), + (this._gain = null), + this + ); + }), + t.Signal + ); + })(n, m, T, b); + var w; + w = (function (t) { + "use strict"; + return ( + (t.Add = function (e) { + this.createInsOuts(2, 0), + (this._sum = + this.input[0] = + this.input[1] = + this.output = + new t.Gain()), + (this._param = this.input[1] = new t.Signal(e)), + this._param.connect(this._sum); + }), + t.extend(t.Add, t.Signal), + (t.Add.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._sum.dispose(), + (this._sum = null), + this._param.dispose(), + (this._param = null), + this + ); + }), + t.Add + ); + })(n, S); + var A; + A = (function (t) { + "use strict"; + return ( + (t.Multiply = function (e) { + this.createInsOuts(2, 0), + (this._mult = this.input[0] = this.output = new t.Gain()), + (this._param = this.input[1] = this.output.gain), + (this._param.value = this.defaultArg(e, 0)); + }), + t.extend(t.Multiply, t.Signal), + (t.Multiply.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._mult.dispose(), + (this._mult = null), + (this._param = null), + this + ); + }), + t.Multiply + ); + })(n, S); + var P; + P = (function (t) { + "use strict"; + return ( + (t.Scale = function (e, i) { + (this._outputMin = this.defaultArg(e, 0)), + (this._outputMax = this.defaultArg(i, 1)), + (this._scale = this.input = new t.Multiply(1)), + (this._add = this.output = new t.Add(0)), + this._scale.connect(this._add), + this._setRange(); + }), + t.extend(t.Scale, t.SignalBase), + Object.defineProperty(t.Scale.prototype, "min", { + get: function () { + return this._outputMin; + }, + set: function (t) { + (this._outputMin = t), this._setRange(); + }, + }), + Object.defineProperty(t.Scale.prototype, "max", { + get: function () { + return this._outputMax; + }, + set: function (t) { + (this._outputMax = t), this._setRange(); + }, + }), + (t.Scale.prototype._setRange = function () { + (this._add.value = this._outputMin), + (this._scale.value = this._outputMax - this._outputMin); + }), + (t.Scale.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._add.dispose(), + (this._add = null), + this._scale.dispose(), + (this._scale = null), + this + ); + }), + t.Scale + ); + })(n, w, A); + var k; + k = (function () { + var e = S, + i = w, + n = A, + o = P; + (t.Signal = function (t) { + var i = new e(t); + return i; + }), + (e.prototype.fade = e.prototype.linearRampToValueAtTime), + (n.prototype.fade = e.prototype.fade), + (i.prototype.fade = e.prototype.fade), + (o.prototype.fade = e.prototype.fade), + (e.prototype.setInput = function (t) { + t.connect(this); + }), + (n.prototype.setInput = e.prototype.setInput), + (i.prototype.setInput = e.prototype.setInput), + (o.prototype.setInput = e.prototype.setInput), + (e.prototype.add = function (t) { + var e = new i(t); + return this.connect(e), e; + }), + (n.prototype.add = e.prototype.add), + (i.prototype.add = e.prototype.add), + (o.prototype.add = e.prototype.add), + (e.prototype.mult = function (t) { + var e = new n(t); + return this.connect(e), e; + }), + (n.prototype.mult = e.prototype.mult), + (i.prototype.mult = e.prototype.mult), + (o.prototype.mult = e.prototype.mult), + (e.prototype.scale = function (e, i, n, r) { + var s, a; + 4 === arguments.length + ? ((s = t.prototype.map(n, e, i, 0, 1) - 0.5), + (a = t.prototype.map(r, e, i, 0, 1) - 0.5)) + : ((s = arguments[0]), (a = arguments[1])); + var u = new o(s, a); + return this.connect(u), u; + }), + (n.prototype.scale = e.prototype.scale), + (i.prototype.scale = e.prototype.scale), + (o.prototype.scale = e.prototype.scale); + })(S, w, A, P); + var O; + O = (function () { + var e = a, + i = w, + n = A, + o = P; + (t.Oscillator = function (i, n) { + if ("string" == typeof i) { + var o = n; + (n = i), (i = o); + } + if ("number" == typeof n) { + var o = n; + (n = i), (i = o); + } + (this.started = !1), + (this.phaseAmount = void 0), + (this.oscillator = e.audiocontext.createOscillator()), + (this.f = i || 440), + (this.oscillator.type = n || "sine"), + this.oscillator.frequency.setValueAtTime( + this.f, + e.audiocontext.currentTime + ), + (this.output = e.audiocontext.createGain()), + (this._freqMods = []), + (this.output.gain.value = 0.5), + this.output.gain.setValueAtTime(0.5, e.audiocontext.currentTime), + this.oscillator.connect(this.output), + (this.panPosition = 0), + (this.connection = e.input), + (this.panner = new t.Panner(this.output, this.connection, 1)), + (this.mathOps = [this.output]), + e.soundArray.push(this); + }), + (t.Oscillator.prototype.start = function (t, i) { + if (this.started) { + var n = e.audiocontext.currentTime; + this.stop(n); + } + if (!this.started) { + var o = i || this.f, + r = this.oscillator.type; + this.oscillator && + (this.oscillator.disconnect(), delete this.oscillator), + (this.oscillator = e.audiocontext.createOscillator()), + (this.oscillator.frequency.value = Math.abs(o)), + (this.oscillator.type = r), + this.oscillator.connect(this.output), + (t = t || 0), + this.oscillator.start(t + e.audiocontext.currentTime), + (this.freqNode = this.oscillator.frequency); + for (var s in this._freqMods) + "undefined" != typeof this._freqMods[s].connect && + this._freqMods[s].connect(this.oscillator.frequency); + this.started = !0; + } + }), + (t.Oscillator.prototype.stop = function (t) { + if (this.started) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.oscillator.stop(i + n), (this.started = !1); + } + }), + (t.Oscillator.prototype.amp = function (t, i, n) { + var o = this; + if ("number" == typeof t) { + var i = i || 0, + n = n || 0, + r = e.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime(t, r + n + i); + } else { + if (!t) return this.output.gain; + t.connect(o.output.gain); + } + }), + (t.Oscillator.prototype.fade = t.Oscillator.prototype.amp), + (t.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }), + (t.Oscillator.prototype.freq = function (t, i, n) { + if ("number" != typeof t || isNaN(t)) { + if (!t) return this.oscillator.frequency; + t.output && (t = t.output), + t.connect(this.oscillator.frequency), + this._freqMods.push(t); + } else { + this.f = t; + var o = e.audiocontext.currentTime, + i = i || 0, + n = n || 0; + 0 === i + ? this.oscillator.frequency.setValueAtTime(t, n + o) + : t > 0 + ? this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + i + o + ) + : this.oscillator.frequency.linearRampToValueAtTime(t, n + i + o), + this.phaseAmount && this.phase(this.phaseAmount); + } + }), + (t.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }), + (t.Oscillator.prototype.setType = function (t) { + this.oscillator.type = t; + }), + (t.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }), + (t.Oscillator.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? (this.panner.connect(t.input), (this.connection = t.input)) + : (this.panner.connect(t), (this.connection = t)) + : this.panner.connect(e.input); + }), + (t.Oscillator.prototype.disconnect = function () { + this.output && this.output.disconnect(), + this.panner && + (this.panner.disconnect(), + this.output && this.output.connect(this.panner)), + (this.oscMods = []); + }), + (t.Oscillator.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (t.Oscillator.prototype.getPan = function () { + return this.panPosition; + }), + (t.Oscillator.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + if ((e.soundArray.splice(t, 1), this.oscillator)) { + var i = e.audiocontext.currentTime; + this.stop(i), + this.disconnect(), + (this.panner = null), + (this.oscillator = null); + } + this.osc2 && this.osc2.dispose(); + }), + (t.Oscillator.prototype.phase = function (i) { + var n = t.prototype.map(i, 0, 1, 0, 1 / this.f), + o = e.audiocontext.currentTime; + (this.phaseAmount = i), + this.dNode || + ((this.dNode = e.audiocontext.createDelay()), + this.oscillator.disconnect(), + this.oscillator.connect(this.dNode), + this.dNode.connect(this.output)), + this.dNode.delayTime.setValueAtTime(n, o); + }); + var r = function (t, e, i, n, o) { + var r = t.oscillator; + for (var s in t.mathOps) + t.mathOps[s] instanceof o && + (r.disconnect(), + t.mathOps[s].dispose(), + (i = s), + i < t.mathOps.length - 2 && (n = t.mathOps[s + 1])); + return ( + i === t.mathOps.length - 1 && t.mathOps.push(n), + s > 0 && (r = t.mathOps[s - 1]), + r.disconnect(), + r.connect(e), + e.connect(n), + (t.mathOps[i] = e), + t + ); + }; + (t.Oscillator.prototype.add = function (t) { + var e = new i(t), + n = this.mathOps.length - 1, + o = this.output; + return r(this, e, n, o, i); + }), + (t.Oscillator.prototype.mult = function (t) { + var e = new n(t), + i = this.mathOps.length - 1, + o = this.output; + return r(this, e, i, o, n); + }), + (t.Oscillator.prototype.scale = function (e, i, n, s) { + var a, u; + 4 === arguments.length + ? ((a = t.prototype.map(n, e, i, 0, 1) - 0.5), + (u = t.prototype.map(s, e, i, 0, 1) - 0.5)) + : ((a = arguments[0]), (u = arguments[1])); + var c = new o(a, u), + p = this.mathOps.length - 1, + h = this.output; + return r(this, c, p, h, o); + }), + (t.SinOsc = function (e) { + t.Oscillator.call(this, e, "sine"); + }), + (t.SinOsc.prototype = Object.create(t.Oscillator.prototype)), + (t.TriOsc = function (e) { + t.Oscillator.call(this, e, "triangle"); + }), + (t.TriOsc.prototype = Object.create(t.Oscillator.prototype)), + (t.SawOsc = function (e) { + t.Oscillator.call(this, e, "sawtooth"); + }), + (t.SawOsc.prototype = Object.create(t.Oscillator.prototype)), + (t.SqrOsc = function (e) { + t.Oscillator.call(this, e, "square"); + }), + (t.SqrOsc.prototype = Object.create(t.Oscillator.prototype)); + })(a, w, A, P); + var F; + F = (function (t) { + "use strict"; + return ( + (t.Timeline = function () { + var e = this.optionsObject(arguments, ["memory"], t.Timeline.defaults); + (this._timeline = []), + (this._toRemove = []), + (this._iterating = !1), + (this.memory = e.memory); + }), + t.extend(t.Timeline), + (t.Timeline.defaults = { memory: 1 / 0 }), + Object.defineProperty(t.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }), + (t.Timeline.prototype.add = function (t) { + if (this.isUndef(t.time)) + throw new Error("Tone.Timeline: events must have a time attribute"); + if (this._timeline.length) { + var e = this._search(t.time); + this._timeline.splice(e + 1, 0, t); + } else this._timeline.push(t); + if (this.length > this.memory) { + var i = this.length - this.memory; + this._timeline.splice(0, i); + } + return this; + }), + (t.Timeline.prototype.remove = function (t) { + if (this._iterating) this._toRemove.push(t); + else { + var e = this._timeline.indexOf(t); + -1 !== e && this._timeline.splice(e, 1); + } + return this; + }), + (t.Timeline.prototype.get = function (t) { + var e = this._search(t); + return -1 !== e ? this._timeline[e] : null; + }), + (t.Timeline.prototype.peek = function () { + return this._timeline[0]; + }), + (t.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }), + (t.Timeline.prototype.getAfter = function (t) { + var e = this._search(t); + return e + 1 < this._timeline.length ? this._timeline[e + 1] : null; + }), + (t.Timeline.prototype.getBefore = function (t) { + var e = this._timeline.length; + if (e > 0 && this._timeline[e - 1].time < t) + return this._timeline[e - 1]; + var i = this._search(t); + return i - 1 >= 0 ? this._timeline[i - 1] : null; + }), + (t.Timeline.prototype.cancel = function (t) { + if (this._timeline.length > 1) { + var e = this._search(t); + if (e >= 0) + if (this._timeline[e].time === t) { + for (var i = e; i >= 0 && this._timeline[i].time === t; i--) + e = i; + this._timeline = this._timeline.slice(0, e); + } else this._timeline = this._timeline.slice(0, e + 1); + else this._timeline = []; + } else + 1 === this._timeline.length && + this._timeline[0].time >= t && + (this._timeline = []); + return this; + }), + (t.Timeline.prototype.cancelBefore = function (t) { + if (this._timeline.length) { + var e = this._search(t); + e >= 0 && (this._timeline = this._timeline.slice(e + 1)); + } + return this; + }), + (t.Timeline.prototype._search = function (t) { + var e = 0, + i = this._timeline.length, + n = i; + if (i > 0 && this._timeline[i - 1].time <= t) return i - 1; + for (; n > e; ) { + var o = Math.floor(e + (n - e) / 2), + r = this._timeline[o], + s = this._timeline[o + 1]; + if (r.time === t) { + for (var a = o; a < this._timeline.length; a++) { + var u = this._timeline[a]; + u.time === t && (o = a); + } + return o; + } + if (r.time < t && s.time > t) return o; + r.time > t ? (n = o) : r.time < t && (e = o + 1); + } + return -1; + }), + (t.Timeline.prototype._iterate = function (t, e, i) { + (this._iterating = !0), + (e = this.defaultArg(e, 0)), + (i = this.defaultArg(i, this._timeline.length - 1)); + for (var n = e; i >= n; n++) t(this._timeline[n]); + if (((this._iterating = !1), this._toRemove.length > 0)) { + for (var o = 0; o < this._toRemove.length; o++) { + var r = this._timeline.indexOf(this._toRemove[o]); + -1 !== r && this._timeline.splice(r, 1); + } + this._toRemove = []; + } + }), + (t.Timeline.prototype.forEach = function (t) { + return this._iterate(t), this; + }), + (t.Timeline.prototype.forEachBefore = function (t, e) { + var i = this._search(t); + return -1 !== i && this._iterate(e, 0, i), this; + }), + (t.Timeline.prototype.forEachAfter = function (t, e) { + var i = this._search(t); + return this._iterate(e, i + 1), this; + }), + (t.Timeline.prototype.forEachFrom = function (t, e) { + for (var i = this._search(t); i >= 0 && this._timeline[i].time >= t; ) + i--; + return this._iterate(e, i + 1), this; + }), + (t.Timeline.prototype.forEachAtTime = function (t, e) { + var i = this._search(t); + return ( + -1 !== i && + this._iterate( + function (i) { + i.time === t && e(i); + }, + 0, + i + ), + this + ); + }), + (t.Timeline.prototype.dispose = function () { + t.prototype.dispose.call(this), + (this._timeline = null), + (this._toRemove = null); + }), + t.Timeline + ); + })(n); + var q; + q = (function (t) { + "use strict"; + return ( + (t.TimelineSignal = function () { + var e = this.optionsObject( + arguments, + ["value", "units"], + t.Signal.defaults + ); + (this._events = new t.Timeline(10)), + t.Signal.apply(this, e), + (e.param = this._param), + t.Param.call(this, e), + (this._initial = this._fromUnits(this._param.value)); + }), + t.extend(t.TimelineSignal, t.Param), + (t.TimelineSignal.Type = { + Linear: "linear", + Exponential: "exponential", + Target: "target", + Curve: "curve", + Set: "set", + }), + Object.defineProperty(t.TimelineSignal.prototype, "value", { + get: function () { + var t = this.now(), + e = this.getValueAtTime(t); + return this._toUnits(e); + }, + set: function (t) { + var e = this._fromUnits(t); + (this._initial = e), + this.cancelScheduledValues(), + (this._param.value = e); + }, + }), + (t.TimelineSignal.prototype.setValueAtTime = function (e, i) { + return ( + (e = this._fromUnits(e)), + (i = this.toSeconds(i)), + this._events.add({ + type: t.TimelineSignal.Type.Set, + value: e, + time: i, + }), + this._param.setValueAtTime(e, i), + this + ); + }), + (t.TimelineSignal.prototype.linearRampToValueAtTime = function (e, i) { + return ( + (e = this._fromUnits(e)), + (i = this.toSeconds(i)), + this._events.add({ + type: t.TimelineSignal.Type.Linear, + value: e, + time: i, + }), + this._param.linearRampToValueAtTime(e, i), + this + ); + }), + (t.TimelineSignal.prototype.exponentialRampToValueAtTime = function ( + e, + i + ) { + i = this.toSeconds(i); + var n = this._searchBefore(i); + n && 0 === n.value && this.setValueAtTime(this._minOutput, n.time), + (e = this._fromUnits(e)); + var o = Math.max(e, this._minOutput); + return ( + this._events.add({ + type: t.TimelineSignal.Type.Exponential, + value: o, + time: i, + }), + e < this._minOutput + ? (this._param.exponentialRampToValueAtTime( + this._minOutput, + i - this.sampleTime + ), + this.setValueAtTime(0, i)) + : this._param.exponentialRampToValueAtTime(e, i), + this + ); + }), + (t.TimelineSignal.prototype.setTargetAtTime = function (e, i, n) { + return ( + (e = this._fromUnits(e)), + (e = Math.max(this._minOutput, e)), + (n = Math.max(this._minOutput, n)), + (i = this.toSeconds(i)), + this._events.add({ + type: t.TimelineSignal.Type.Target, + value: e, + time: i, + constant: n, + }), + this._param.setTargetAtTime(e, i, n), + this + ); + }), + (t.TimelineSignal.prototype.setValueCurveAtTime = function (e, i, n, o) { + o = this.defaultArg(o, 1); + for (var r = new Array(e.length), s = 0; s < r.length; s++) + r[s] = this._fromUnits(e[s]) * o; + (i = this.toSeconds(i)), + (n = this.toSeconds(n)), + this._events.add({ + type: t.TimelineSignal.Type.Curve, + value: r, + time: i, + duration: n, + }), + this._param.setValueAtTime(r[0], i); + for (var a = 1; a < r.length; a++) { + var u = i + (a / (r.length - 1)) * n; + this._param.linearRampToValueAtTime(r[a], u); + } + return this; + }), + (t.TimelineSignal.prototype.cancelScheduledValues = function (t) { + return ( + (t = this.toSeconds(t)), + this._events.cancel(t), + this._param.cancelScheduledValues(t), + this + ); + }), + (t.TimelineSignal.prototype.setRampPoint = function (e) { + e = this.toSeconds(e); + var i = this._toUnits(this.getValueAtTime(e)), + n = this._searchBefore(e); + if (n && n.time === e) this.cancelScheduledValues(e + this.sampleTime); + else if ( + n && + n.type === t.TimelineSignal.Type.Curve && + n.time + n.duration > e + ) + this.cancelScheduledValues(e), this.linearRampToValueAtTime(i, e); + else { + var o = this._searchAfter(e); + o && + (this.cancelScheduledValues(e), + o.type === t.TimelineSignal.Type.Linear + ? this.linearRampToValueAtTime(i, e) + : o.type === t.TimelineSignal.Type.Exponential && + this.exponentialRampToValueAtTime(i, e)), + this.setValueAtTime(i, e); + } + return this; + }), + (t.TimelineSignal.prototype.linearRampToValueBetween = function ( + t, + e, + i + ) { + return this.setRampPoint(e), this.linearRampToValueAtTime(t, i), this; + }), + (t.TimelineSignal.prototype.exponentialRampToValueBetween = function ( + t, + e, + i + ) { + return ( + this.setRampPoint(e), this.exponentialRampToValueAtTime(t, i), this + ); + }), + (t.TimelineSignal.prototype._searchBefore = function (t) { + return this._events.get(t); + }), + (t.TimelineSignal.prototype._searchAfter = function (t) { + return this._events.getAfter(t); + }), + (t.TimelineSignal.prototype.getValueAtTime = function (e) { + e = this.toSeconds(e); + var i = this._searchAfter(e), + n = this._searchBefore(e), + o = this._initial; + if (null === n) o = this._initial; + else if (n.type === t.TimelineSignal.Type.Target) { + var r, + s = this._events.getBefore(n.time); + (r = null === s ? this._initial : s.value), + (o = this._exponentialApproach(n.time, r, n.value, n.constant, e)); + } else + o = + n.type === t.TimelineSignal.Type.Curve + ? this._curveInterpolate(n.time, n.value, n.duration, e) + : null === i + ? n.value + : i.type === t.TimelineSignal.Type.Linear + ? this._linearInterpolate(n.time, n.value, i.time, i.value, e) + : i.type === t.TimelineSignal.Type.Exponential + ? this._exponentialInterpolate( + n.time, + n.value, + i.time, + i.value, + e + ) + : n.value; + return o; + }), + (t.TimelineSignal.prototype.connect = t.SignalBase.prototype.connect), + (t.TimelineSignal.prototype._exponentialApproach = function ( + t, + e, + i, + n, + o + ) { + return i + (e - i) * Math.exp(-(o - t) / n); + }), + (t.TimelineSignal.prototype._linearInterpolate = function ( + t, + e, + i, + n, + o + ) { + return e + (n - e) * ((o - t) / (i - t)); + }), + (t.TimelineSignal.prototype._exponentialInterpolate = function ( + t, + e, + i, + n, + o + ) { + return ( + (e = Math.max(this._minOutput, e)), + e * Math.pow(n / e, (o - t) / (i - t)) + ); + }), + (t.TimelineSignal.prototype._curveInterpolate = function (t, e, i, n) { + var o = e.length; + if (n >= t + i) return e[o - 1]; + if (t >= n) return e[0]; + var r = (n - t) / i, + s = Math.floor((o - 1) * r), + a = Math.ceil((o - 1) * r), + u = e[s], + c = e[a]; + return a === s ? u : this._linearInterpolate(s, u, a, c, r * (o - 1)); + }), + (t.TimelineSignal.prototype.dispose = function () { + t.Signal.prototype.dispose.call(this), + t.Param.prototype.dispose.call(this), + this._events.dispose(), + (this._events = null); + }), + t.TimelineSignal + ); + })(n, S); + var M; + M = (function () { + var e = a, + i = w, + n = A, + o = P, + r = q; + (t.Envelope = function (t, i, n, o, s, a) { + (this.aTime = t || 0.1), + (this.aLevel = i || 1), + (this.dTime = n || 0.5), + (this.dLevel = o || 0), + (this.rTime = s || 0), + (this.rLevel = a || 0), + (this._rampHighPercentage = 0.98), + (this._rampLowPercentage = 0.02), + (this.output = e.audiocontext.createGain()), + (this.control = new r()), + this._init(), + this.control.connect(this.output), + (this.connection = null), + (this.mathOps = [this.control]), + (this.isExponential = !1), + (this.sourceToClear = null), + (this.wasTriggered = !1), + e.soundArray.push(this); + }), + (t.Envelope.prototype._init = function () { + var t = e.audiocontext.currentTime, + i = t; + this.control.setTargetAtTime(1e-5, i, 0.001), + this._setRampAD(this.aTime, this.dTime); + }), + (t.Envelope.prototype.set = function (t, e, i, n, o, r) { + (this.aTime = t), + (this.aLevel = e), + (this.dTime = i || 0), + (this.dLevel = n || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + this._setRampAD(t, i); + }), + (t.Envelope.prototype.setADSR = function (t, e, i, n) { + (this.aTime = t), + (this.dTime = e || 0), + (this.sPercent = i || 0), + (this.dLevel = + "undefined" != typeof i + ? i * (this.aLevel - this.rLevel) + this.rLevel + : 0), + (this.rTime = n || 0), + this._setRampAD(t, e); + }), + (t.Envelope.prototype.setRange = function (t, e) { + (this.aLevel = t || 1), (this.rLevel = e || 0); + }), + (t.Envelope.prototype._setRampAD = function (t, e) { + (this._rampAttackTime = this.checkExpInput(t)), + (this._rampDecayTime = this.checkExpInput(e)); + var i = 1; + (i = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage))), + (this._rampAttackTC = t / this.checkExpInput(i)), + (i = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = e / this.checkExpInput(i)); + }), + (t.Envelope.prototype.setRampPercentages = function (t, e) { + (this._rampHighPercentage = this.checkExpInput(t)), + (this._rampLowPercentage = this.checkExpInput(e)); + var i = 1; + (i = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage))), + (this._rampAttackTC = this._rampAttackTime / this.checkExpInput(i)), + (i = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = this._rampDecayTime / this.checkExpInput(i)); + }), + (t.Envelope.prototype.setInput = function () { + for (var t = 0; t < arguments.length; t++) this.connect(arguments[t]); + }), + (t.Envelope.prototype.setExp = function (t) { + this.isExponential = t; + }), + (t.Envelope.prototype.checkExpInput = function (t) { + return 0 >= t && (t = 1e-8), t; + }), + (t.Envelope.prototype.play = function (t, e, i) { + var n = e || 0, + i = i || 0; + t && this.connection !== t && this.connect(t), + this.triggerAttack(t, n), + this.triggerRelease(t, n + this.aTime + this.dTime + i); + }), + (t.Envelope.prototype.triggerAttack = function (t, i) { + var n = e.audiocontext.currentTime, + o = i || 0, + r = n + o; + (this.lastAttack = r), + (this.wasTriggered = !0), + t && this.connection !== t && this.connect(t); + var s = this.control.getValueAtTime(r); + this.isExponential === !0 + ? this.control.exponentialRampToValueAtTime(this.checkExpInput(s), r) + : this.control.linearRampToValueAtTime(s, r), + (r += this.aTime), + this.isExponential === !0 + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + r + ), + (s = this.checkExpInput(this.control.getValueAtTime(r))), + this.control.cancelScheduledValues(r), + this.control.exponentialRampToValueAtTime(s, r)) + : (this.control.linearRampToValueAtTime(this.aLevel, r), + (s = this.control.getValueAtTime(r)), + this.control.cancelScheduledValues(r), + this.control.linearRampToValueAtTime(s, r)), + (r += this.dTime), + this.isExponential === !0 + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + r + ), + (s = this.checkExpInput(this.control.getValueAtTime(r))), + this.control.cancelScheduledValues(r), + this.control.exponentialRampToValueAtTime(s, r)) + : (this.control.linearRampToValueAtTime(this.dLevel, r), + (s = this.control.getValueAtTime(r)), + this.control.cancelScheduledValues(r), + this.control.linearRampToValueAtTime(s, r)); + }), + (t.Envelope.prototype.triggerRelease = function (t, i) { + if (this.wasTriggered) { + var n = e.audiocontext.currentTime, + o = i || 0, + r = n + o; + t && this.connection !== t && this.connect(t); + var s = this.control.getValueAtTime(r); + this.isExponential === !0 + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(s), + r + ) + : this.control.linearRampToValueAtTime(s, r), + (r += this.rTime), + this.isExponential === !0 + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + r + ), + (s = this.checkExpInput(this.control.getValueAtTime(r))), + this.control.cancelScheduledValues(r), + this.control.exponentialRampToValueAtTime(s, r)) + : (this.control.linearRampToValueAtTime(this.rLevel, r), + (s = this.control.getValueAtTime(r)), + this.control.cancelScheduledValues(r), + this.control.linearRampToValueAtTime(s, r)), + (this.wasTriggered = !1); + } + }), + (t.Envelope.prototype.ramp = function (t, i, n, o) { + var r = e.audiocontext.currentTime, + s = i || 0, + a = r + s, + u = this.checkExpInput(n), + c = "undefined" != typeof o ? this.checkExpInput(o) : void 0; + t && this.connection !== t && this.connect(t); + var p = this.checkExpInput(this.control.getValueAtTime(a)); + u > p + ? (this.control.setTargetAtTime(u, a, this._rampAttackTC), + (a += this._rampAttackTime)) + : p > u && + (this.control.setTargetAtTime(u, a, this._rampDecayTC), + (a += this._rampDecayTime)), + void 0 !== c && + (c > u + ? this.control.setTargetAtTime(c, a, this._rampAttackTC) + : u > c && this.control.setTargetAtTime(c, a, this._rampDecayTC)); + }), + (t.Envelope.prototype.connect = function (i) { + (this.connection = i), + (i instanceof t.Oscillator || + i instanceof t.SoundFile || + i instanceof t.AudioIn || + i instanceof t.Reverb || + i instanceof t.Noise || + i instanceof t.Filter || + i instanceof t.Delay) && + (i = i.output.gain), + i instanceof AudioParam && + i.setValueAtTime(0, e.audiocontext.currentTime), + i instanceof t.Signal && i.setValue(0), + this.output.connect(i); + }), + (t.Envelope.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.Envelope.prototype.add = function (e) { + var n = new i(e), + o = this.mathOps.length, + r = this.output; + return t.prototype._mathChain(this, n, o, r, i); + }), + (t.Envelope.prototype.mult = function (e) { + var i = new n(e), + o = this.mathOps.length, + r = this.output; + return t.prototype._mathChain(this, i, o, r, n); + }), + (t.Envelope.prototype.scale = function (e, i, n, r) { + var s = new o(e, i, n, r), + a = this.mathOps.length, + u = this.output; + return t.prototype._mathChain(this, s, a, u, o); + }), + (t.Envelope.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.disconnect(), + this.control && (this.control.dispose(), (this.control = null)); + for (var i = 1; i < this.mathOps.length; i++) this.mathOps[i].dispose(); + }), + (t.Env = function (e, i, n, o, r, s) { + console.warn( + "WARNING: p5.Env is now deprecated and may be removed in future versions. Please use the new p5.Envelope instead." + ), + t.Envelope.call(this, e, i, n, o, r, s); + }), + (t.Env.prototype = Object.create(t.Envelope.prototype)); + })(a, w, A, P, q); + var E; + E = (function () { + function e() { + for ( + var t = i.audiocontext, + e = t.createBuffer(1, 2048, t.sampleRate), + n = e.getChannelData(0), + o = 0; + 2048 > o; + o++ + ) + n[o] = 1; + var r = t.createBufferSource(); + return (r.buffer = e), (r.loop = !0), r; + } + var i = a; + (t.Pulse = function (n, o) { + t.Oscillator.call(this, n, "sawtooth"), + (this.w = o || 0), + (this.osc2 = new t.SawOsc(n)), + (this.dNode = i.audiocontext.createDelay()), + (this.dcOffset = e()), + (this.dcGain = i.audiocontext.createGain()), + this.dcOffset.connect(this.dcGain), + this.dcGain.connect(this.output), + (this.f = n || 440); + var r = this.w / this.oscillator.frequency.value; + (this.dNode.delayTime.value = r), + (this.dcGain.gain.value = 1.7 * (0.5 - this.w)), + this.osc2.disconnect(), + this.osc2.panner.disconnect(), + this.osc2.amp(-1), + this.osc2.output.connect(this.dNode), + this.dNode.connect(this.output), + (this.output.gain.value = 1), + this.output.connect(this.panner); + }), + (t.Pulse.prototype = Object.create(t.Oscillator.prototype)), + (t.Pulse.prototype.width = function (e) { + if ("number" == typeof e) { + if (1 >= e && e >= 0) { + this.w = e; + var i = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = i; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + e.connect(this.dNode.delayTime); + var n = new t.SignalAdd(-0.5); + n.setInput(e), + (n = n.mult(-1)), + (n = n.mult(1.7)), + n.connect(this.dcGain.gain); + } + }), + (t.Pulse.prototype.start = function (t, n) { + var o = i.audiocontext.currentTime, + r = n || 0; + if (!this.started) { + var s = t || this.f, + a = this.oscillator.type; + (this.oscillator = i.audiocontext.createOscillator()), + this.oscillator.frequency.setValueAtTime(s, o), + (this.oscillator.type = a), + this.oscillator.connect(this.output), + this.oscillator.start(r + o), + (this.osc2.oscillator = i.audiocontext.createOscillator()), + this.osc2.oscillator.frequency.setValueAtTime(s, r + o), + (this.osc2.oscillator.type = a), + this.osc2.oscillator.connect(this.osc2.output), + this.osc2.start(r + o), + (this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]), + (this.dcOffset = e()), + this.dcOffset.connect(this.dcGain), + this.dcOffset.start(r + o), + void 0 !== this.mods && + void 0 !== this.mods.frequency && + (this.mods.frequency.connect(this.freqNode[0]), + this.mods.frequency.connect(this.freqNode[1])), + (this.started = !0), + (this.osc2.started = !0); + } + }), + (t.Pulse.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = i.audiocontext.currentTime; + this.oscillator.stop(e + n), + this.osc2.oscillator && this.osc2.oscillator.stop(e + n), + this.dcOffset.stop(e + n), + (this.started = !1), + (this.osc2.started = !1); + } + }), + (t.Pulse.prototype.freq = function (t, e, n) { + if ("number" == typeof t) { + this.f = t; + var o = i.audiocontext.currentTime, + e = e || 0, + n = n || 0, + r = this.oscillator.frequency.value; + this.oscillator.frequency.cancelScheduledValues(o), + this.oscillator.frequency.setValueAtTime(r, o + n), + this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + o + ), + this.osc2.oscillator.frequency.cancelScheduledValues(o), + this.osc2.oscillator.frequency.setValueAtTime(r, o + n), + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + o + ), + this.freqMod && + (this.freqMod.output.disconnect(), (this.freqMod = null)); + } else + t.output && + (t.output.disconnect(), + t.output.connect(this.oscillator.frequency), + t.output.connect(this.osc2.oscillator.frequency), + (this.freqMod = t)); + }); + })(a, O); + var V; + V = (function () { + var e = a; + (t.Noise = function (e) { + var r; + t.Oscillator.call(this), + delete this.f, + delete this.freq, + delete this.oscillator, + (r = "brown" === e ? o : "pink" === e ? n : i), + (this.buffer = r); + }), + (t.Noise.prototype = Object.create(t.Oscillator.prototype)); + var i = (function () { + for ( + var t = 2 * e.audiocontext.sampleRate, + i = e.audiocontext.createBuffer(1, t, e.audiocontext.sampleRate), + n = i.getChannelData(0), + o = 0; + t > o; + o++ + ) + n[o] = 2 * Math.random() - 1; + return (i.type = "white"), i; + })(), + n = (function () { + var t, + i, + n, + o, + r, + s, + a, + u = 2 * e.audiocontext.sampleRate, + c = e.audiocontext.createBuffer(1, u, e.audiocontext.sampleRate), + p = c.getChannelData(0); + t = i = n = o = r = s = a = 0; + for (var h = 0; u > h; h++) { + var l = 2 * Math.random() - 1; + (t = 0.99886 * t + 0.0555179 * l), + (i = 0.99332 * i + 0.0750759 * l), + (n = 0.969 * n + 0.153852 * l), + (o = 0.8665 * o + 0.3104856 * l), + (r = 0.55 * r + 0.5329522 * l), + (s = -0.7616 * s - 0.016898 * l), + (p[h] = t + i + n + o + r + s + a + 0.5362 * l), + (p[h] *= 0.11), + (a = 0.115926 * l); + } + return (c.type = "pink"), c; + })(), + o = (function () { + for ( + var t = 2 * e.audiocontext.sampleRate, + i = e.audiocontext.createBuffer(1, t, e.audiocontext.sampleRate), + n = i.getChannelData(0), + o = 0, + r = 0; + t > r; + r++ + ) { + var s = 2 * Math.random() - 1; + (n[r] = (o + 0.02 * s) / 1.02), (o = n[r]), (n[r] *= 3.5); + } + return (i.type = "brown"), i; + })(); + (t.Noise.prototype.setType = function (t) { + switch (t) { + case "white": + this.buffer = i; + break; + case "pink": + this.buffer = n; + break; + case "brown": + this.buffer = o; + break; + default: + this.buffer = i; + } + if (this.started) { + var r = e.audiocontext.currentTime; + this.stop(r), this.start(r + 0.01); + } + }), + (t.Noise.prototype.getType = function () { + return this.buffer.type; + }), + (t.Noise.prototype.start = function () { + this.started && this.stop(), + (this.noise = e.audiocontext.createBufferSource()), + (this.noise.buffer = this.buffer), + (this.noise.loop = !0), + this.noise.connect(this.output); + var t = e.audiocontext.currentTime; + this.noise.start(t), (this.started = !0); + }), + (t.Noise.prototype.stop = function () { + var t = e.audiocontext.currentTime; + this.noise && (this.noise.stop(t), (this.started = !1)); + }), + (t.Noise.prototype.dispose = function () { + var t = e.audiocontext.currentTime, + i = e.soundArray.indexOf(this); + e.soundArray.splice(i, 1), + this.noise && (this.noise.disconnect(), this.stop(t)), + this.output && this.output.disconnect(), + this.panner && this.panner.disconnect(), + (this.output = null), + (this.panner = null), + (this.buffer = null), + (this.noise = null); + }); + })(a); + var R; + R = (function () { + var e = a; + (e.inputSources = []), + (t.AudioIn = function (i) { + (this.input = e.audiocontext.createGain()), + (this.output = e.audiocontext.createGain()), + (this.stream = null), + (this.mediaStream = null), + (this.currentSource = null), + (this.enabled = !1), + (this.amplitude = new t.Amplitude()), + this.output.connect(this.amplitude.input), + (window.MediaStreamTrack && + window.navigator.mediaDevices && + window.navigator.mediaDevices.getUserMedia) || + (i + ? i() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + )), + e.soundArray.push(this); + }), + (t.AudioIn.prototype.start = function (t, i) { + var n = this; + this.stream && this.stop(); + var o = e.inputSources[n.currentSource], + r = { + audio: { + sampleRate: e.audiocontext.sampleRate, + echoCancellation: !1, + }, + }; + e.inputSources[this.currentSource] && (r.audio.deviceId = o.deviceId), + window.navigator.mediaDevices + .getUserMedia(r) + .then(function (i) { + (n.stream = i), + (n.enabled = !0), + (n.mediaStream = e.audiocontext.createMediaStreamSource(i)), + n.mediaStream.connect(n.output), + n.amplitude.setInput(n.output), + t && t(); + }) + ["catch"](function (t) { + i ? i(t) : console.error(t); + }); + }), + (t.AudioIn.prototype.stop = function () { + this.stream && + (this.stream.getTracks().forEach(function (t) { + t.stop(); + }), + this.mediaStream.disconnect(), + delete this.mediaStream, + delete this.stream); + }), + (t.AudioIn.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : t.hasOwnProperty("analyser") + ? this.output.connect(t.analyser) + : this.output.connect(t) + : this.output.connect(e.input); + }), + (t.AudioIn.prototype.disconnect = function () { + this.output && + (this.output.disconnect(), this.output.connect(this.amplitude.input)); + }), + (t.AudioIn.prototype.getLevel = function (t) { + return t && (this.amplitude.smoothing = t), this.amplitude.getLevel(); + }), + (t.AudioIn.prototype.amp = function (t, i) { + if (i) { + var n = i || 0, + o = this.output.gain.value; + this.output.gain.cancelScheduledValues(e.audiocontext.currentTime), + this.output.gain.setValueAtTime(o, e.audiocontext.currentTime), + this.output.gain.linearRampToValueAtTime( + t, + n + e.audiocontext.currentTime + ); + } else + this.output.gain.cancelScheduledValues(e.audiocontext.currentTime), + this.output.gain.setValueAtTime(t, e.audiocontext.currentTime); + }), + (t.AudioIn.prototype.getSources = function (t, i) { + return new Promise(function (n, o) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (i) { + (e.inputSources = i.filter(function (t) { + return "audioinput" === t.kind; + })), + n(e.inputSources), + t && t(e.inputSources); + }) + ["catch"](function (t) { + o(t), + i + ? i(t) + : console.error( + "This browser does not support MediaStreamTrack.getSources()" + ); + }); + }); + }), + (t.AudioIn.prototype.setSource = function (t) { + e.inputSources.length > 0 && t < e.inputSources.length + ? ((this.currentSource = t), + console.log("set source to ", e.inputSources[this.currentSource])) + : console.log("unable to set input source"), + this.stream && this.stream.active && this.start(); + }), + (t.AudioIn.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.stop(), + this.output && this.output.disconnect(), + this.amplitude && this.amplitude.disconnect(), + delete this.amplitude, + delete this.output; + }); + })(a); + var C; + C = (function (t) { + "use strict"; + return ( + (t.Negate = function () { + this._multiply = this.input = this.output = new t.Multiply(-1); + }), + t.extend(t.Negate, t.SignalBase), + (t.Negate.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._multiply.dispose(), + (this._multiply = null), + this + ); + }), + t.Negate + ); + })(n, A); + var D; + D = (function (t) { + "use strict"; + return ( + (t.Subtract = function (e) { + this.createInsOuts(2, 0), + (this._sum = this.input[0] = this.output = new t.Gain()), + (this._neg = new t.Negate()), + (this._param = this.input[1] = new t.Signal(e)), + this._param.chain(this._neg, this._sum); + }), + t.extend(t.Subtract, t.Signal), + (t.Subtract.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._neg.dispose(), + (this._neg = null), + this._sum.disconnect(), + (this._sum = null), + this._param.dispose(), + (this._param = null), + this + ); + }), + t.Subtract + ); + })(n, w, C, S); + var N; + N = (function (t) { + "use strict"; + return ( + (t.GreaterThanZero = function () { + (this._thresh = this.output = + new t.WaveShaper(function (t) { + return 0 >= t ? 0 : 1; + }, 127)), + (this._scale = this.input = new t.Multiply(1e4)), + this._scale.connect(this._thresh); + }), + t.extend(t.GreaterThanZero, t.SignalBase), + (t.GreaterThanZero.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._scale.dispose(), + (this._scale = null), + this._thresh.dispose(), + (this._thresh = null), + this + ); + }), + t.GreaterThanZero + ); + })(n, S, A); + var B; + B = (function (t) { + "use strict"; + return ( + (t.GreaterThan = function (e) { + this.createInsOuts(2, 0), + (this._param = this.input[0] = new t.Subtract(e)), + (this.input[1] = this._param.input[1]), + (this._gtz = this.output = new t.GreaterThanZero()), + this._param.connect(this._gtz); + }), + t.extend(t.GreaterThan, t.Signal), + (t.GreaterThan.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._param.dispose(), + (this._param = null), + this._gtz.dispose(), + (this._gtz = null), + this + ); + }), + t.GreaterThan + ); + })(n, N, D); + var U; + U = (function (t) { + "use strict"; + return ( + (t.Abs = function () { + this._abs = + this.input = + this.output = + new t.WaveShaper(function (t) { + return 0 === t ? 0 : Math.abs(t); + }, 127); + }), + t.extend(t.Abs, t.SignalBase), + (t.Abs.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._abs.dispose(), + (this._abs = null), + this + ); + }), + t.Abs + ); + })(n, m); + var I; + I = (function (t) { + "use strict"; + return ( + (t.Modulo = function (e) { + this.createInsOuts(1, 0), + (this._shaper = new t.WaveShaper(Math.pow(2, 16))), + (this._multiply = new t.Multiply()), + (this._subtract = this.output = new t.Subtract()), + (this._modSignal = new t.Signal(e)), + this.input.fan(this._shaper, this._subtract), + this._modSignal.connect(this._multiply, 0, 0), + this._shaper.connect(this._multiply, 0, 1), + this._multiply.connect(this._subtract, 0, 1), + this._setWaveShaper(e); + }), + t.extend(t.Modulo, t.SignalBase), + (t.Modulo.prototype._setWaveShaper = function (t) { + this._shaper.setMap(function (e) { + var i = Math.floor((e + 1e-4) / t); + return i; + }); + }), + Object.defineProperty(t.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (t) { + (this._modSignal.value = t), this._setWaveShaper(t); + }, + }), + (t.Modulo.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._shaper.dispose(), + (this._shaper = null), + this._multiply.dispose(), + (this._multiply = null), + this._subtract.dispose(), + (this._subtract = null), + this._modSignal.dispose(), + (this._modSignal = null), + this + ); + }), + t.Modulo + ); + })(n, m, A); + var G; + G = (function (t) { + "use strict"; + return ( + (t.Pow = function (e) { + (this._exp = this.defaultArg(e, 1)), + (this._expScaler = + this.input = + this.output = + new t.WaveShaper(this._expFunc(this._exp), 8192)); + }), + t.extend(t.Pow, t.SignalBase), + Object.defineProperty(t.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (t) { + (this._exp = t), this._expScaler.setMap(this._expFunc(this._exp)); + }, + }), + (t.Pow.prototype._expFunc = function (t) { + return function (e) { + return Math.pow(Math.abs(e), t); + }; + }), + (t.Pow.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._expScaler.dispose(), + (this._expScaler = null), + this + ); + }), + t.Pow + ); + })(n); + var L; + L = (function (t) { + "use strict"; + return ( + (t.AudioToGain = function () { + this._norm = + this.input = + this.output = + new t.WaveShaper(function (t) { + return (t + 1) / 2; + }); + }), + t.extend(t.AudioToGain, t.SignalBase), + (t.AudioToGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._norm.dispose(), + (this._norm = null), + this + ); + }), + t.AudioToGain + ); + })(n, m); + var j; + j = (function (t) { + "use strict"; + function e(t, e, i) { + var n = new t(); + return i._eval(e[0]).connect(n, 0, 0), i._eval(e[1]).connect(n, 0, 1), n; + } + function i(t, e, i) { + var n = new t(); + return i._eval(e[0]).connect(n, 0, 0), n; + } + function n(t) { + return t ? parseFloat(t) : void 0; + } + function o(t) { + return t && t.args ? parseFloat(t.args) : void 0; + } + return ( + (t.Expr = function () { + var t = this._replacements(Array.prototype.slice.call(arguments)), + e = this._parseInputs(t); + (this._nodes = []), (this.input = new Array(e)); + for (var i = 0; e > i; i++) this.input[i] = this.context.createGain(); + var n, + o = this._parseTree(t); + try { + n = this._eval(o); + } catch (r) { + throw ( + (this._disposeNodes(), + new Error("Tone.Expr: Could evaluate expression: " + t)) + ); + } + this.output = n; + }), + t.extend(t.Expr, t.SignalBase), + (t.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (e) { + var i = new t.Signal(n(e)); + return i; + }, + }, + input: { + regexp: /^\$\d/, + method: function (t, e) { + return e.input[n(t.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { regexp: /^abs/, method: i.bind(this, t.Abs) }, + mod: { + regexp: /^mod/, + method: function (e, i) { + var n = o(e[1]), + r = new t.Modulo(n); + return i._eval(e[0]).connect(r), r; + }, + }, + pow: { + regexp: /^pow/, + method: function (e, i) { + var n = o(e[1]), + r = new t.Pow(n); + return i._eval(e[0]).connect(r), r; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (e, i) { + var n = new t.AudioToGain(); + return i._eval(e[0]).connect(n), n; + }, + }, + }, + binary: { + "+": { regexp: /^\+/, precedence: 1, method: e.bind(this, t.Add) }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (n, o) { + return 1 === n.length ? i(t.Negate, n, o) : e(t.Subtract, n, o); + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: e.bind(this, t.Multiply), + }, + }, + unary: { + "-": { regexp: /^\-/, method: i.bind(this, t.Negate) }, + "!": { regexp: /^\!/, method: i.bind(this, t.NOT) }, + }, + }), + (t.Expr.prototype._parseInputs = function (t) { + var e = t.match(/\$\d/g), + i = 0; + if (null !== e) + for (var n = 0; n < e.length; n++) { + var o = parseInt(e[n].substr(1)) + 1; + i = Math.max(i, o); + } + return i; + }), + (t.Expr.prototype._replacements = function (t) { + for (var e = t.shift(), i = 0; i < t.length; i++) + e = e.replace(/\%/i, t[i]); + return e; + }), + (t.Expr.prototype._tokenize = function (e) { + function i(e) { + for (var i in t.Expr._Expressions) { + var n = t.Expr._Expressions[i]; + for (var o in n) { + var r = n[o], + s = r.regexp, + a = e.match(s); + if (null !== a) return { type: i, value: a[0], method: r.method }; + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + e); + } + for (var n = -1, o = []; e.length > 0; ) { + e = e.trim(); + var r = i(e); + o.push(r), (e = e.substr(r.value.length)); + } + return { + next: function () { + return o[++n]; + }, + peek: function () { + return o[n + 1]; + }, + }; + }), + (t.Expr.prototype._parseTree = function (e) { + function i(t, e) { + return !p(t) && "glue" === t.type && t.value === e; + } + function n(e, i, n) { + var o = !1, + r = t.Expr._Expressions[i]; + if (!p(e)) + for (var s in r) { + var a = r[s]; + if (a.regexp.test(e.value)) { + if (p(n)) return !0; + if (a.precedence === n) return !0; + } + } + return o; + } + function o(t) { + p(t) && (t = 5); + var e; + e = 0 > t ? r() : o(t - 1); + for (var i = c.peek(); n(i, "binary", t); ) + (i = c.next()), + (e = { + operator: i.value, + method: i.method, + args: [e, o(t - 1)], + }), + (i = c.peek()); + return e; + } + function r() { + var t, e; + return ( + (t = c.peek()), + n(t, "unary") + ? ((t = c.next()), + (e = r()), + { operator: t.value, method: t.method, args: [e] }) + : s() + ); + } + function s() { + var t, e; + if (((t = c.peek()), p(t))) + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + if ("func" === t.type) return (t = c.next()), a(t); + if ("value" === t.type) + return (t = c.next()), { method: t.method, args: t.value }; + if (i(t, "(")) { + if ((c.next(), (e = o()), (t = c.next()), !i(t, ")"))) + throw new SyntaxError("Expected )"); + return e; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + t.value + ); + } + function a(t) { + var e, + n = []; + if (((e = c.next()), !i(e, "("))) + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + t.value + '"' + ); + if ( + ((e = c.peek()), i(e, ")") || (n = u()), (e = c.next()), !i(e, ")")) + ) + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + t.value + '"' + ); + return { method: t.method, args: n, name: name }; + } + function u() { + for (var t, e, n = []; ; ) { + if (((e = o()), p(e))) break; + if ((n.push(e), (t = c.peek()), !i(t, ","))) break; + c.next(); + } + return n; + } + var c = this._tokenize(e), + p = this.isUndef.bind(this); + return o(); + }), + (t.Expr.prototype._eval = function (t) { + if (!this.isUndef(t)) { + var e = t.method(t.args, this); + return this._nodes.push(e), e; + } + }), + (t.Expr.prototype._disposeNodes = function () { + for (var t = 0; t < this._nodes.length; t++) { + var e = this._nodes[t]; + this.isFunction(e.dispose) + ? e.dispose() + : this.isFunction(e.disconnect) && e.disconnect(), + (e = null), + (this._nodes[t] = null); + } + this._nodes = null; + }), + (t.Expr.prototype.dispose = function () { + t.prototype.dispose.call(this), this._disposeNodes(); + }), + t.Expr + ); + })(n, w, D, A, B, N, U, C, I, G); + var Z; + Z = (function (t) { + "use strict"; + return ( + (t.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new t.WaveShaper( + function (t) { + return Math.abs(t) < 0.001 ? 0 : this.equalPowerScale(t); + }.bind(this), + 4096 + ); + }), + t.extend(t.EqualPowerGain, t.SignalBase), + (t.EqualPowerGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._eqPower.dispose(), + (this._eqPower = null), + this + ); + }), + t.EqualPowerGain + ); + })(n); + var X; + X = (function (t) { + "use strict"; + return ( + (t.CrossFade = function (e) { + this.createInsOuts(2, 1), + (this.a = this.input[0] = new t.Gain()), + (this.b = this.input[1] = new t.Gain()), + (this.fade = new t.Signal( + this.defaultArg(e, 0.5), + t.Type.NormalRange + )), + (this._equalPowerA = new t.EqualPowerGain()), + (this._equalPowerB = new t.EqualPowerGain()), + (this._invert = new t.Expr("1 - $0")), + this.a.connect(this.output), + this.b.connect(this.output), + this.fade.chain(this._equalPowerB, this.b.gain), + this.fade.chain(this._invert, this._equalPowerA, this.a.gain), + this._readOnly("fade"); + }), + t.extend(t.CrossFade), + (t.CrossFade.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._writable("fade"), + this._equalPowerA.dispose(), + (this._equalPowerA = null), + this._equalPowerB.dispose(), + (this._equalPowerB = null), + this.fade.dispose(), + (this.fade = null), + this._invert.dispose(), + (this._invert = null), + this.a.dispose(), + (this.a = null), + this.b.dispose(), + (this.b = null), + this + ); + }), + t.CrossFade + ); + })(n, S, j, Z); + var Y; + Y = (function () { + var e = a, + i = X; + return ( + (t.Effect = function () { + (this.ac = e.audiocontext), + (this.input = this.ac.createGain()), + (this.output = this.ac.createGain()), + (this._drywet = new i(1)), + (this.wet = this.ac.createGain()), + this.input.connect(this._drywet.a), + this.wet.connect(this._drywet.b), + this._drywet.connect(this.output), + this.connect(), + e.soundArray.push(this); + }), + (t.Effect.prototype.amp = function (t, i, n) { + var i = i || 0, + n = n || 0, + o = e.audiocontext.currentTime, + r = this.output.gain.value; + this.output.gain.cancelScheduledValues(o), + this.output.gain.linearRampToValueAtTime(r, o + n + 0.001), + this.output.gain.linearRampToValueAtTime(t, o + n + i + 0.001); + }), + (t.Effect.prototype.chain = function () { + if (arguments.length > 0) { + this.connect(arguments[0]); + for (var t = 1; t < arguments.length; t += 1) + arguments[t - 1].connect(arguments[t]); + } + return this; + }), + (t.Effect.prototype.drywet = function (t) { + return ( + "undefined" != typeof t && (this._drywet.fade.value = t), + this._drywet.fade.value + ); + }), + (t.Effect.prototype.connect = function (e) { + var i = e || t.soundOut.input; + this.output.connect(i.input ? i.input : i); + }), + (t.Effect.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.Effect.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.input && (this.input.disconnect(), delete this.input), + this.output && (this.output.disconnect(), delete this.output), + this._drywet && (this._drywet.disconnect(), delete this._drywet), + this.wet && (this.wet.disconnect(), delete this.wet), + (this.ac = void 0); + }), + t.Effect + ); + })(a, X); + var z; + z = (function () { + var e = Y; + return ( + (t.Filter = function (t) { + e.call(this), + (this.biquad = this.ac.createBiquadFilter()), + this.input.connect(this.biquad), + this.biquad.connect(this.wet), + t && this.setType(t), + (this._on = !0), + (this._untoggledType = this.biquad.type); + }), + (t.Filter.prototype = Object.create(e.prototype)), + (t.Filter.prototype.process = function (t, e, i, n) { + t.connect(this.input), this.set(e, i, n); + }), + (t.Filter.prototype.set = function (t, e, i) { + t && this.freq(t, i), e && this.res(e, i); + }), + (t.Filter.prototype.freq = function (t, e) { + var i = e || 0; + return ( + 0 >= t && (t = 1), + "number" == typeof t + ? (this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.biquad.frequency.exponentialRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.biquad.frequency), + this.biquad.frequency.value + ); + }), + (t.Filter.prototype.res = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.Q.value = t), + this.biquad.Q.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.biquad.Q.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.biquad.Q), + this.biquad.Q.value + ); + }), + (t.Filter.prototype.gain = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.gain.value = t), + this.biquad.gain.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.biquad.gain.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.biquad.gain), + this.biquad.gain.value + ); + }), + (t.Filter.prototype.toggle = function () { + return ( + (this._on = !this._on), + this._on === !0 + ? (this.biquad.type = this._untoggledType) + : this._on === !1 && (this.biquad.type = "allpass"), + this._on + ); + }), + (t.Filter.prototype.setType = function (t) { + (this.biquad.type = t), (this._untoggledType = this.biquad.type); + }), + (t.Filter.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.biquad && (this.biquad.disconnect(), delete this.biquad); + }), + (t.LowPass = function () { + t.Filter.call(this, "lowpass"); + }), + (t.LowPass.prototype = Object.create(t.Filter.prototype)), + (t.HighPass = function () { + t.Filter.call(this, "highpass"); + }), + (t.HighPass.prototype = Object.create(t.Filter.prototype)), + (t.BandPass = function () { + t.Filter.call(this, "bandpass"); + }), + (t.BandPass.prototype = Object.create(t.Filter.prototype)), + t.Filter + ); + })(a, Y); + var W; + W = (function () { + var e = z, + i = a, + n = function (t, i) { + e.call(this, "peaking"), + this.disconnect(), + this.set(t, i), + (this.biquad.gain.value = 0), + delete this.input, + delete this.output, + delete this._drywet, + delete this.wet; + }; + return ( + (n.prototype = Object.create(e.prototype)), + (n.prototype.amp = function () { + console.warn("`amp()` is not available for p5.EQ bands. Use `.gain()`"); + }), + (n.prototype.drywet = function () { + console.warn("`drywet()` is not available for p5.EQ bands."); + }), + (n.prototype.connect = function (e) { + var i = e || t.soundOut.input; + this.biquad + ? this.biquad.connect(i.input ? i.input : i) + : this.output.connect(i.input ? i.input : i); + }), + (n.prototype.disconnect = function () { + this.biquad && this.biquad.disconnect(); + }), + (n.prototype.dispose = function () { + var t = i.soundArray.indexOf(this); + i.soundArray.splice(t, 1), this.disconnect(), delete this.biquad; + }), + n + ); + })(z, a); + var Q; + Q = (function () { + var e = Y, + i = W; + return ( + (t.EQ = function (t) { + e.call(this), (t = 3 === t || 8 === t ? t : 3); + var i; + (i = 3 === t ? Math.pow(2, 3) : 2), (this.bands = []); + for (var n, o, r = 0; t > r; r++) + r === t - 1 + ? ((n = 21e3), (o = 0.01)) + : 0 === r + ? ((n = 100), (o = 0.1)) + : 1 === r + ? ((n = 3 === t ? 360 * i : 360), (o = 1)) + : ((n = this.bands[r - 1].freq() * i), (o = 1)), + (this.bands[r] = this._newBand(n, o)), + r > 0 + ? this.bands[r - 1].connect(this.bands[r].biquad) + : this.input.connect(this.bands[r].biquad); + this.bands[t - 1].connect(this.output); + }), + (t.EQ.prototype = Object.create(e.prototype)), + (t.EQ.prototype.process = function (t) { + t.connect(this.input); + }), + (t.EQ.prototype.set = function () { + if (arguments.length === 2 * this.bands.length) + for (var t = 0; t < arguments.length; t += 2) + this.bands[t / 2].freq(arguments[t]), + this.bands[t / 2].gain(arguments[t + 1]); + else + console.error( + "Argument mismatch. .set() should be called with " + + 2 * this.bands.length + + " arguments. (one frequency and gain value pair for each band of the eq)" + ); + }), + (t.EQ.prototype._newBand = function (t, e) { + return new i(t, e); + }), + (t.EQ.prototype.dispose = function () { + if ((e.prototype.dispose.apply(this), this.bands)) { + for (; this.bands.length > 0; ) delete this.bands.pop().dispose(); + delete this.bands; + } + }), + t.EQ + ); + })(Y, W); + var H; + H = (function () { + var e = Y; + return ( + (t.Panner3D = function () { + e.call(this), + (this.panner = this.ac.createPanner()), + (this.panner.panningModel = "HRTF"), + (this.panner.distanceModel = "linear"), + this.panner.connect(this.output), + this.input.connect(this.panner); + }), + (t.Panner3D.prototype = Object.create(e.prototype)), + (t.Panner3D.prototype.process = function (t) { + t.connect(this.input); + }), + (t.Panner3D.prototype.set = function (t, e, i, n) { + return ( + this.positionX(t, n), + this.positionY(e, n), + this.positionZ(i, n), + [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ] + ); + }), + (t.Panner3D.prototype.positionX = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionX.value = t), + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.positionX), + this.panner.positionX.value + ); + }), + (t.Panner3D.prototype.positionY = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionY.value = t), + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.positionY), + this.panner.positionY.value + ); + }), + (t.Panner3D.prototype.positionZ = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionZ.value = t), + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.positionZ), + this.panner.positionZ.value + ); + }), + (t.Panner3D.prototype.orient = function (t, e, i, n) { + return ( + this.orientX(t, n), + this.orientY(e, n), + this.orientZ(i, n), + [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ] + ); + }), + (t.Panner3D.prototype.orientX = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationX.value = t), + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.orientationX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.orientationX), + this.panner.orientationX.value + ); + }), + (t.Panner3D.prototype.orientY = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationY.value = t), + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.orientationY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.orientationY), + this.panner.orientationY.value + ); + }), + (t.Panner3D.prototype.orientZ = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationZ.value = t), + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.panner.orientationZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.panner.orientationZ), + this.panner.orientationZ.value + ); + }), + (t.Panner3D.prototype.setFalloff = function (t, e) { + this.maxDist(t), this.rolloff(e); + }), + (t.Panner3D.prototype.maxDist = function (t) { + return ( + "number" == typeof t && (this.panner.maxDistance = t), + this.panner.maxDistance + ); + }), + (t.Panner3D.prototype.rolloff = function (t) { + return ( + "number" == typeof t && (this.panner.rolloffFactor = t), + this.panner.rolloffFactor + ); + }), + (t.Panner3D.dispose = function () { + e.prototype.dispose.apply(this), + this.panner && (this.panner.disconnect(), delete this.panner); + }), + t.Panner3D + ); + })(a, Y); + var $; + $ = (function () { + var e = a; + return ( + (t.Listener3D = function (t) { + (this.ac = e.audiocontext), (this.listener = this.ac.listener); + }), + (t.Listener3D.prototype.process = function (t) { + t.connect(this.input); + }), + (t.Listener3D.prototype.position = function (t, e, i, n) { + return ( + this.positionX(t, n), + this.positionY(e, n), + this.positionZ(i, n), + [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ] + ); + }), + (t.Listener3D.prototype.positionX = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionX.value = t), + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.positionX), + this.listener.positionX.value + ); + }), + (t.Listener3D.prototype.positionY = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionY.value = t), + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.positionY), + this.listener.positionY.value + ); + }), + (t.Listener3D.prototype.positionZ = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionZ.value = t), + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.positionZ), + this.listener.positionZ.value + ); + }), + (t.Listener3D.prototype.orient = function (t, e, i, n, o, r, s) { + return ( + 3 === arguments.length || 4 === arguments.length + ? ((s = arguments[3]), this.orientForward(t, e, i, s)) + : (6 === arguments.length || 7 === arguments) && + (this.orientForward(t, e, i), this.orientUp(n, o, r, s)), + [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ] + ); + }), + (t.Listener3D.prototype.orientForward = function (t, e, i, n) { + return ( + this.forwardX(t, n), + this.forwardY(e, n), + this.forwardZ(i, n), + [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ] + ); + }), + (t.Listener3D.prototype.orientUp = function (t, e, i, n) { + return ( + this.upX(t, n), + this.upY(e, n), + this.upZ(i, n), + [this.listener.upX, this.listener.upY, this.listener.upZ] + ); + }), + (t.Listener3D.prototype.forwardX = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardX.value = t), + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.forwardX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.forwardX), + this.listener.forwardX.value + ); + }), + (t.Listener3D.prototype.forwardY = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardY.value = t), + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.forwardY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.forwardY), + this.listener.forwardY.value + ); + }), + (t.Listener3D.prototype.forwardZ = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardZ.value = t), + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.forwardZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.forwardZ), + this.listener.forwardZ.value + ); + }), + (t.Listener3D.prototype.upX = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upX.value = t), + this.listener.upX.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.upX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.upX), + this.listener.upX.value + ); + }), + (t.Listener3D.prototype.upY = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upY.value = t), + this.listener.upY.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.upY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.upY), + this.listener.upY.value + ); + }), + (t.Listener3D.prototype.upZ = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upZ.value = t), + this.listener.upZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.listener.upZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : t && t.connect(this.listener.upZ), + this.listener.upZ.value + ); + }), + t.Listener3D + ); + })(a, Y); + var J; + J = (function () { + var e = z, + i = Y; + (t.Delay = function () { + i.call(this), + (this._split = this.ac.createChannelSplitter(2)), + (this._merge = this.ac.createChannelMerger(2)), + (this._leftGain = this.ac.createGain()), + (this._rightGain = this.ac.createGain()), + (this.leftDelay = this.ac.createDelay()), + (this.rightDelay = this.ac.createDelay()), + (this._leftFilter = new e()), + (this._rightFilter = new e()), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this.input.connect(this._split), + this.leftDelay.connect(this._leftGain), + this.rightDelay.connect(this._rightGain), + this._leftGain.connect(this._leftFilter.input), + this._rightGain.connect(this._rightFilter.input), + this._merge.connect(this.wet), + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime), + this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime), + this.setType(0), + (this._maxDelay = this.leftDelay.delayTime.maxValue), + this.feedback(0.5); + }), + (t.Delay.prototype = Object.create(i.prototype)), + (t.Delay.prototype.process = function (t, e, i, n) { + var o = i || 0, + r = e || 0; + if (o >= 1) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + if (r >= this._maxDelay) + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + t.connect(this.input), + this.leftDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + this.rightDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + (this._leftGain.gain.value = o), + (this._rightGain.gain.value = o), + n && (this._leftFilter.freq(n), this._rightFilter.freq(n)); + }), + (t.Delay.prototype.delayTime = function (t) { + "number" != typeof t + ? (t.connect(this.leftDelay.delayTime), + t.connect(this.rightDelay.delayTime)) + : (this.leftDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.rightDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ), + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + )); + }), + (t.Delay.prototype.feedback = function (t) { + if (t && "number" != typeof t) + t.connect(this._leftGain.gain), t.connect(this._rightGain.gain); + else { + if (t >= 1) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + "number" == typeof t && + ((this._leftGain.gain.value = t), (this._rightGain.gain.value = t)); + } + return this._leftGain.gain.value; + }), + (t.Delay.prototype.filter = function (t, e) { + this._leftFilter.set(t, e), this._rightFilter.set(t, e); + }), + (t.Delay.prototype.setType = function (t) { + switch ( + (1 === t && (t = "pingPong"), + this._split.disconnect(), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._split.connect(this.leftDelay, 0), + this._split.connect(this.rightDelay, 1), + t) + ) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type), + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.rightDelay), + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.leftDelay), + this._rightFilter.output.connect(this.rightDelay); + } + }), + (t.Delay.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this._split.disconnect(), + this._leftFilter.dispose(), + this._rightFilter.dispose(), + this._merge.disconnect(), + this._leftGain.disconnect(), + this._rightGain.disconnect(), + this.leftDelay.disconnect(), + this.rightDelay.disconnect(), + (this._split = void 0), + (this._leftFilter = void 0), + (this._rightFilter = void 0), + (this._merge = void 0), + (this._leftGain = void 0), + (this._rightGain = void 0), + (this.leftDelay = void 0), + (this.rightDelay = void 0); + }); + })(z, Y); + var K; + K = (function () { + var e = c, + i = Y; + (t.Reverb = function () { + i.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + (this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse(); + }), + (t.Reverb.prototype = Object.create(i.prototype)), + (t.Reverb.prototype._initConvolverNode = function () { + (this.convolverNode = this.ac.createConvolver()), + this.input.connect(this.convolverNode), + this.convolverNode.connect(this.wet); + }), + (t.Reverb.prototype._teardownConvolverNode = function () { + this.convolverNode && + (this.convolverNode.disconnect(), delete this.convolverNode); + }), + (t.Reverb.prototype._setBuffer = function (t) { + this._teardownConvolverNode(), + this._initConvolverNode(), + (this.convolverNode.buffer = t); + }), + (t.Reverb.prototype.process = function (t, e, i, n) { + t.connect(this.input); + var o = !1; + e && ((this._seconds = e), (o = !0)), + i && (this._decay = i), + n && (this._reverse = n), + o && this._buildImpulse(); + }), + (t.Reverb.prototype.set = function (t, e, i) { + var n = !1; + t && ((this._seconds = t), (n = !0)), + e && (this._decay = e), + i && (this._reverse = i), + n && this._buildImpulse(); + }), + (t.Reverb.prototype._buildImpulse = function () { + var t, + e, + i = this.ac.sampleRate, + n = i * this._seconds, + o = this._decay, + r = this.ac.createBuffer(2, n, i), + s = r.getChannelData(0), + a = r.getChannelData(1); + for (e = 0; n > e; e++) + (t = this._reverse ? n - e : e), + (s[e] = (2 * Math.random() - 1) * Math.pow(1 - t / n, o)), + (a[e] = (2 * Math.random() - 1) * Math.pow(1 - t / n, o)); + this._setBuffer(r); + }), + (t.Reverb.prototype.dispose = function () { + i.prototype.dispose.apply(this), this._teardownConvolverNode(); + }), + (t.Convolver = function (e, i, n) { + t.Reverb.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + e + ? ((this.impulses = []), this._loadBuffer(e, i, n)) + : ((this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse()); + }), + (t.Convolver.prototype = Object.create(t.Reverb.prototype)), + t.prototype.registerPreloadMethod("createConvolver", t.prototype), + (t.prototype.createConvolver = function (e, i, n) { + window.location.origin.indexOf("file://") > -1 && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var o = this, + r = new t.Convolver( + e, + function (t) { + "function" == typeof i && i(t), + "function" == typeof o._decrementPreload && + o._decrementPreload(); + }, + n + ); + return (r.impulses = []), r; + }), + (t.Convolver.prototype._loadBuffer = function (i, n, o) { + var i = t.prototype._checkFileFormats(i), + r = this, + s = new Error().stack, + a = t.prototype.getAudioContext(), + u = new XMLHttpRequest(); + u.open("GET", i, !0), + (u.responseType = "arraybuffer"), + (u.onload = function () { + if (200 === u.status) + a.decodeAudioData( + u.response, + function (t) { + var e = {}, + o = i.split("/"); + (e.name = o[o.length - 1]), + (e.audioBuffer = t), + r.impulses.push(e), + r._setBuffer(e.audioBuffer), + n && n(e); + }, + function () { + var t = new e("decodeAudioData", s, r.url), + i = "AudioContext error at decodeAudioData for " + r.url; + o + ? ((t.msg = i), o(t)) + : console.error( + i + "\n The error stack trace includes: \n" + t.stack + ); + } + ); + else { + var t = new e("loadConvolver", s, r.url), + c = + "Unable to load " + + r.url + + ". The request status was: " + + u.status + + " (" + + u.statusText + + ")"; + o + ? ((t.message = c), o(t)) + : console.error( + c + "\n The error stack trace includes: \n" + t.stack + ); + } + }), + (u.onerror = function () { + var t = new e("loadConvolver", s, r.url), + i = + "There was no response from the server at " + + r.url + + ". Check the url and internet connectivity."; + o + ? ((t.message = i), o(t)) + : console.error( + i + "\n The error stack trace includes: \n" + t.stack + ); + }), + u.send(); + }), + (t.Convolver.prototype.set = null), + (t.Convolver.prototype.process = function (t) { + t.connect(this.input); + }), + (t.Convolver.prototype.impulses = []), + (t.Convolver.prototype.addImpulse = function (t, e, i) { + window.location.origin.indexOf("file://") > -1 && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + this._loadBuffer(t, e, i); + }), + (t.Convolver.prototype.resetImpulse = function (t, e, i) { + window.location.origin.indexOf("file://") > -1 && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + (this.impulses = []), + this._loadBuffer(t, e, i); + }), + (t.Convolver.prototype.toggleImpulse = function (t) { + if ( + ("number" == typeof t && + t < this.impulses.length && + this._setBuffer(this.impulses[t].audioBuffer), + "string" == typeof t) + ) + for (var e = 0; e < this.impulses.length; e++) + if (this.impulses[e].name === t) { + this._setBuffer(this.impulses[e].audioBuffer); + break; + } + }), + (t.Convolver.prototype.dispose = function () { + t.Reverb.prototype.dispose.apply(this); + for (var e in this.impulses) + this.impulses[e] && (this.impulses[e] = null); + }); + })(c, Y); + var tt; + tt = (function (t) { + "use strict"; + return ( + (t.TimelineState = function (e) { + t.Timeline.call(this), (this._initial = e); + }), + t.extend(t.TimelineState, t.Timeline), + (t.TimelineState.prototype.getValueAtTime = function (t) { + var e = this.get(t); + return null !== e ? e.state : this._initial; + }), + (t.TimelineState.prototype.setStateAtTime = function (t, e) { + this.add({ state: t, time: e }); + }), + t.TimelineState + ); + })(n, F); + var et; + et = (function (t) { + "use strict"; + return ( + (t.Clock = function () { + t.Emitter.call(this); + var e = this.optionsObject( + arguments, + ["callback", "frequency"], + t.Clock.defaults + ); + (this.callback = e.callback), + (this._nextTick = 0), + (this._lastState = t.State.Stopped), + (this.frequency = new t.TimelineSignal( + e.frequency, + t.Type.Frequency + )), + this._readOnly("frequency"), + (this.ticks = 0), + (this._state = new t.TimelineState(t.State.Stopped)), + (this._boundLoop = this._loop.bind(this)), + this.context.on("tick", this._boundLoop); + }), + t.extend(t.Clock, t.Emitter), + (t.Clock.defaults = { + callback: t.noOp, + frequency: 1, + lookAhead: "auto", + }), + Object.defineProperty(t.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }), + (t.Clock.prototype.start = function (e, i) { + return ( + (e = this.toSeconds(e)), + this._state.getValueAtTime(e) !== t.State.Started && + this._state.add({ state: t.State.Started, time: e, offset: i }), + this + ); + }), + (t.Clock.prototype.stop = function (e) { + return ( + (e = this.toSeconds(e)), + this._state.cancel(e), + this._state.setStateAtTime(t.State.Stopped, e), + this + ); + }), + (t.Clock.prototype.pause = function (e) { + return ( + (e = this.toSeconds(e)), + this._state.getValueAtTime(e) === t.State.Started && + this._state.setStateAtTime(t.State.Paused, e), + this + ); + }), + (t.Clock.prototype._loop = function () { + for ( + var e = this.now(), + i = this.context.lookAhead, + n = this.context.updateInterval, + o = 2 * this.context.lag, + r = e + i + n + o; + r > this._nextTick && this._state; + + ) { + var s = this._state.getValueAtTime(this._nextTick); + if (s !== this._lastState) { + this._lastState = s; + var a = this._state.get(this._nextTick); + s === t.State.Started + ? ((this._nextTick = a.time), + this.isUndef(a.offset) || (this.ticks = a.offset), + this.emit("start", a.time, this.ticks)) + : s === t.State.Stopped + ? ((this.ticks = 0), this.emit("stop", a.time)) + : s === t.State.Paused && this.emit("pause", a.time); + } + var u = this._nextTick; + this.frequency && + ((this._nextTick += + 1 / this.frequency.getValueAtTime(this._nextTick)), + s === t.State.Started && (this.callback(u), this.ticks++)); + } + }), + (t.Clock.prototype.getStateAtTime = function (t) { + return (t = this.toSeconds(t)), this._state.getValueAtTime(t); + }), + (t.Clock.prototype.dispose = function () { + t.Emitter.prototype.dispose.call(this), + this.context.off("tick", this._boundLoop), + this._writable("frequency"), + this.frequency.dispose(), + (this.frequency = null), + (this._boundLoop = null), + (this._nextTick = 1 / 0), + (this.callback = null), + this._state.dispose(), + (this._state = null); + }), + t.Clock + ); + })(n, q, tt, o); + var it; + it = (function () { + var e = a, + i = et; + (t.Metro = function () { + (this.clock = new i({ callback: this.ontick.bind(this) })), + (this.syncedParts = []), + (this.bpm = 120), + this._init(), + (this.prevTick = 0), + (this.tatumTime = 0), + (this.tickCallback = function () {}); + }), + (t.Metro.prototype.ontick = function (t) { + var i = t - this.prevTick, + n = t - e.audiocontext.currentTime; + if (!(i - this.tatumTime <= -0.02)) { + this.prevTick = t; + var o = this; + this.syncedParts.forEach(function (t) { + t.isPlaying && + (t.incrementStep(n), + t.phrases.forEach(function (t) { + var e = t.sequence, + i = o.metroTicks % e.length; + 0 !== e[i] && + (o.metroTicks < e.length || !t.looping) && + t.callback(n, e[i]); + })); + }), + (this.metroTicks += 1), + this.tickCallback(n); + } + }), + (t.Metro.prototype.setBPM = function (t, i) { + var n = 60 / (t * this.tatums), + o = e.audiocontext.currentTime; + this.tatumTime = n; + var i = i || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, o), + this.clock.frequency.linearRampToValueAtTime(t, o + i), + (this.bpm = t); + }), + (t.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }), + (t.Metro.prototype._init = function () { + this.metroTicks = 0; + }), + (t.Metro.prototype.resetSync = function (t) { + this.syncedParts = [t]; + }), + (t.Metro.prototype.pushSync = function (t) { + this.syncedParts.push(t); + }), + (t.Metro.prototype.start = function (t) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.clock.start(n + i), this.setBPM(this.bpm); + }), + (t.Metro.prototype.stop = function (t) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.clock.stop(n + i); + }), + (t.Metro.prototype.beatLength = function (t) { + this.tatums = 1 / t / 4; + }); + })(a, et); + var nt; + nt = (function () { + function e(t) { + t.currentPart++, + t.currentPart >= t.parts.length + ? ((t.scoreStep = 0), t.onended()) + : ((t.scoreStep = 0), + t.parts[t.currentPart - 1].stop(), + t.parts[t.currentPart].start()); + } + var i = a, + n = 120; + (t.prototype.setBPM = function (t, e) { + n = t; + for (var o in i.parts) i.parts[o] && i.parts[o].setBPM(t, e); + }), + (t.Phrase = function (t, e, i) { + (this.phraseStep = 0), + (this.name = t), + (this.callback = e), + (this.sequence = i); + }), + (t.Part = function (e, o) { + (this.length = e || 0), + (this.partStep = 0), + (this.phrases = []), + (this.isPlaying = !1), + this.noLoop(), + (this.tatums = o || 0.0625), + (this.metro = new t.Metro()), + this.metro._init(), + this.metro.beatLength(this.tatums), + this.metro.setBPM(n), + i.parts.push(this), + (this.callback = function () {}); + }), + (t.Part.prototype.setBPM = function (t, e) { + this.metro.setBPM(t, e); + }), + (t.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }), + (t.Part.prototype.start = function (t) { + if (!this.isPlaying) { + (this.isPlaying = !0), this.metro.resetSync(this); + var e = t || 0; + this.metro.start(e); + } + }), + (t.Part.prototype.loop = function (t) { + (this.looping = !0), + (this.onended = function () { + this.partStep = 0; + }); + var e = t || 0; + this.start(e); + }), + (t.Part.prototype.noLoop = function () { + (this.looping = !1), + (this.onended = function () { + this.stop(); + }); + }), + (t.Part.prototype.stop = function (t) { + (this.partStep = 0), this.pause(t); + }), + (t.Part.prototype.pause = function (t) { + this.isPlaying = !1; + var e = t || 0; + this.metro.stop(e); + }), + (t.Part.prototype.addPhrase = function (e, i, n) { + var o; + if (3 === arguments.length) o = new t.Phrase(e, i, n); + else { + if (!(arguments[0] instanceof t.Phrase)) + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + o = arguments[0]; + } + this.phrases.push(o), + o.sequence.length > this.length && (this.length = o.sequence.length); + }), + (t.Part.prototype.removePhrase = function (t) { + for (var e in this.phrases) + this.phrases[e].name === t && this.phrases.splice(e, 1); + }), + (t.Part.prototype.getPhrase = function (t) { + for (var e in this.phrases) + if (this.phrases[e].name === t) return this.phrases[e]; + }), + (t.Part.prototype.replaceSequence = function (t, e) { + for (var i in this.phrases) + this.phrases[i].name === t && (this.phrases[i].sequence = e); + }), + (t.Part.prototype.incrementStep = function (t) { + this.partStep < this.length - 1 + ? (this.callback(t), (this.partStep += 1)) + : this.looping || + this.partStep !== this.length - 1 || + (console.log("done"), this.onended()); + }), + (t.Part.prototype.onStep = function (t) { + this.callback = t; + }), + (t.Score = function () { + (this.parts = []), (this.currentPart = 0); + var t = this; + for (var i in arguments) + arguments[i] && + this.parts[i] && + ((this.parts[i] = arguments[i]), + (this.parts[i].nextPart = this.parts[i + 1]), + (this.parts[i].onended = function () { + t.resetPart(i), e(t); + })); + this.looping = !1; + }), + (t.Score.prototype.onended = function () { + this.looping + ? this.parts[0].start() + : (this.parts[this.parts.length - 1].onended = function () { + this.stop(), this.resetParts(); + }), + (this.currentPart = 0); + }), + (t.Score.prototype.start = function () { + this.parts[this.currentPart].start(), (this.scoreStep = 0); + }), + (t.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(), + (this.currentPart = 0), + (this.scoreStep = 0); + }), + (t.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }), + (t.Score.prototype.loop = function () { + (this.looping = !0), this.start(); + }), + (t.Score.prototype.noLoop = function () { + this.looping = !1; + }), + (t.Score.prototype.resetParts = function () { + var t = this; + this.parts.forEach(function (e) { + t.resetParts[e]; + }); + }), + (t.Score.prototype.resetPart = function (t) { + this.parts[t].stop(), (this.parts[t].partStep = 0); + for (var e in this.parts[t].phrases) + this.parts[t] && (this.parts[t].phrases[e].phraseStep = 0); + }), + (t.Score.prototype.setBPM = function (t, e) { + for (var i in this.parts) this.parts[i] && this.parts[i].setBPM(t, e); + }); + })(a); + var ot; + ot = (function () { + var e = a, + i = et; + return ( + (t.SoundLoop = function (t, n) { + (this.callback = t), + (this.musicalTimeMode = "number" == typeof this._interval ? !1 : !0), + (this._interval = n || 1), + (this._timeSignature = 4), + (this._bpm = 60), + (this.isPlaying = !1), + (this.maxIterations = 1 / 0); + var o = this; + this.clock = new i({ + callback: function (t) { + var i = t - e.audiocontext.currentTime; + i > 0 && o.iterations <= o.maxIterations && o.callback(i); + }, + frequency: this._calcFreq(), + }); + }), + (t.SoundLoop.prototype.start = function (t) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.isPlaying || (this.clock.start(n + i), (this.isPlaying = !0)); + }), + (t.SoundLoop.prototype.stop = function (t) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.isPlaying && (this.clock.stop(n + i), (this.isPlaying = !1)); + }), + (t.SoundLoop.prototype.pause = function (t) { + var i = t || 0, + n = e.audiocontext.currentTime; + this.isPlaying && (this.clock.pause(n + i), (this.isPlaying = !1)); + }), + (t.SoundLoop.prototype.syncedStart = function (t, i) { + var n = i || 0, + o = e.audiocontext.currentTime; + if (t.isPlaying) { + if (t.isPlaying) { + var r = t.clock._nextTick - e.audiocontext.currentTime; + this.clock.start(o + r), (this.isPlaying = !0); + } + } else + t.clock.start(o + n), + (t.isPlaying = !0), + this.clock.start(o + n), + (this.isPlaying = !0); + }), + (t.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }), + (t.SoundLoop.prototype._calcFreq = function () { + return "number" == typeof this._interval + ? ((this.musicalTimeMode = !1), 1 / this._interval) + : "string" == typeof this._interval + ? ((this.musicalTimeMode = !0), + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4)) + : void 0; + }), + (t.SoundLoop.prototype._convertNotation = function (t) { + var e = t.slice(-1); + switch (((t = Number(t.slice(0, -1))), e)) { + case "m": + return this._measure(t); + case "n": + return this._note(t); + default: + console.warn( + "Specified interval is not formatted correctly. See Tone.js timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time" + ); + } + }), + (t.SoundLoop.prototype._measure = function (t) { + return t * this._timeSignature; + }), + (t.SoundLoop.prototype._note = function (t) { + return this._timeSignature / t; + }), + Object.defineProperty(t.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (t) { + this.musicalTimeMode || + console.warn( + 'Changing the BPM in "seconds" mode has no effect. BPM is only relevant in musicalTimeMode when the interval is specified as a string ("2n", "4n", "1m"...etc)' + ), + (this._bpm = t), + this._update(); + }, + }), + Object.defineProperty(t.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (t) { + this.musicalTimeMode || + console.warn( + 'Changing the timeSignature in "seconds" mode has no effect. BPM is only relevant in musicalTimeMode when the interval is specified as a string ("2n", "4n", "1m"...etc)' + ), + (this._timeSignature = t), + this._update(); + }, + }), + Object.defineProperty(t.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (t) { + (this.musicalTimeMode = "Number" == typeof t ? !1 : !0), + (this._interval = t), + this._update(); + }, + }), + Object.defineProperty(t.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }), + t.SoundLoop + ); + })(a, et); + var rt; + rt = (function () { + "use strict"; + var e = Y; + return ( + (t.Compressor = function () { + e.call(this), + (this.compressor = this.ac.createDynamicsCompressor()), + this.input.connect(this.compressor), + this.compressor.connect(this.wet); + }), + (t.Compressor.prototype = Object.create(e.prototype)), + (t.Compressor.prototype.process = function (t, e, i, n, o, r) { + t.connect(this.input), this.set(e, i, n, o, r); + }), + (t.Compressor.prototype.set = function (t, e, i, n, o) { + "undefined" != typeof t && this.attack(t), + "undefined" != typeof e && this.knee(e), + "undefined" != typeof i && this.ratio(i), + "undefined" != typeof n && this.threshold(n), + "undefined" != typeof o && this.release(o); + }), + (t.Compressor.prototype.attack = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.attack.value = t), + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.compressor.attack.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : "undefined" != typeof t && t.connect(this.compressor.attack), + this.compressor.attack.value + ); + }), + (t.Compressor.prototype.knee = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.knee.value = t), + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.compressor.knee.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : "undefined" != typeof t && t.connect(this.compressor.knee), + this.compressor.knee.value + ); + }), + (t.Compressor.prototype.ratio = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.ratio.value = t), + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.compressor.ratio.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : "undefined" != typeof t && t.connect(this.compressor.ratio), + this.compressor.ratio.value + ); + }), + (t.Compressor.prototype.threshold = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.threshold.value = t), + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.compressor.threshold.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : "undefined" != typeof t && t.connect(this.compressor.threshold), + this.compressor.threshold.value + ); + }), + (t.Compressor.prototype.release = function (t, e) { + var i = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.release.value = t), + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + i + ), + this.compressor.release.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + i + )) + : "undefined" != typeof number && + t.connect(this.compressor.release), + this.compressor.release.value + ); + }), + (t.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }), + (t.Compressor.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.compressor && + (this.compressor.disconnect(), delete this.compressor); + }), + t.Compressor + ); + })(a, Y, c); + var st; + st = (function () { + var e = a, + i = u.convertToWav, + n = e.audiocontext; + (t.SoundRecorder = function () { + (this.input = n.createGain()), + (this.output = n.createGain()), + (this.recording = !1), + (this.bufferSize = 1024), + (this._channels = 2), + this._clear(), + (this._jsNode = n.createScriptProcessor( + this.bufferSize, + this._channels, + 2 + )), + (this._jsNode.onaudioprocess = this._audioprocess.bind(this)), + (this._callback = function () {}), + this._jsNode.connect(t.soundOut._silentNode), + this.setInput(), + e.soundArray.push(this); + }), + (t.SoundRecorder.prototype.setInput = function (e) { + this.input.disconnect(), + (this.input = null), + (this.input = n.createGain()), + this.input.connect(this._jsNode), + this.input.connect(this.output), + e ? e.connect(this.input) : t.soundOut.output.connect(this.input); + }), + (t.SoundRecorder.prototype.record = function (t, e, i) { + (this.recording = !0), + e && (this.sampleLimit = Math.round(e * n.sampleRate)), + t && i + ? (this._callback = function () { + (this.buffer = this._getBuffer()), + t.setBuffer(this.buffer), + i(); + }) + : t && + (this._callback = function () { + (this.buffer = this._getBuffer()), t.setBuffer(this.buffer); + }); + }), + (t.SoundRecorder.prototype.stop = function () { + (this.recording = !1), this._callback(), this._clear(); + }), + (t.SoundRecorder.prototype._clear = function () { + (this._leftBuffers = []), + (this._rightBuffers = []), + (this.recordedSamples = 0), + (this.sampleLimit = null); + }), + (t.SoundRecorder.prototype._audioprocess = function (t) { + if (this.recording !== !1 && this.recording === !0) + if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) + this.stop(); + else { + var e = t.inputBuffer.getChannelData(0), + i = t.inputBuffer.getChannelData(1); + this._leftBuffers.push(new Float32Array(e)), + this._rightBuffers.push(new Float32Array(i)), + (this.recordedSamples += this.bufferSize); + } + }), + (t.SoundRecorder.prototype._getBuffer = function () { + var t = []; + return ( + t.push(this._mergeBuffers(this._leftBuffers)), + t.push(this._mergeBuffers(this._rightBuffers)), + t + ); + }), + (t.SoundRecorder.prototype._mergeBuffers = function (t) { + for ( + var e = new Float32Array(this.recordedSamples), + i = 0, + n = t.length, + o = 0; + n > o; + o++ + ) { + var r = t[o]; + e.set(r, i), (i += r.length); + } + return e; + }), + (t.SoundRecorder.prototype.dispose = function () { + this._clear(); + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + (this._callback = function () {}), + this.input && this.input.disconnect(), + (this.input = null), + (this._jsNode = null); + }), + (t.prototype.saveSound = function (e, n) { + const o = i(e.buffer); + t.prototype.writeFile([o], n, "wav"); + }); + })(a, u); + var at; + at = (function () { + (t.PeakDetect = function (t, e, i, n) { + (this.framesPerPeak = n || 20), + (this.framesSinceLastPeak = 0), + (this.decayRate = 0.95), + (this.threshold = i || 0.35), + (this.cutoff = 0), + (this.cutoffMult = 1.5), + (this.energy = 0), + (this.penergy = 0), + (this.currentValue = 0), + (this.isDetected = !1), + (this.f1 = t || 40), + (this.f2 = e || 2e4), + (this._onPeak = function () {}); + }), + (t.PeakDetect.prototype.update = function (t) { + var e = (this.energy = t.getEnergy(this.f1, this.f2) / 255); + e > this.cutoff && e > this.threshold && e - this.penergy > 0 + ? (this._onPeak(), + (this.isDetected = !0), + (this.cutoff = e * this.cutoffMult), + (this.framesSinceLastPeak = 0)) + : ((this.isDetected = !1), + this.framesSinceLastPeak <= this.framesPerPeak + ? this.framesSinceLastPeak++ + : ((this.cutoff *= this.decayRate), + (this.cutoff = Math.max(this.cutoff, this.threshold)))), + (this.currentValue = e), + (this.penergy = e); + }), + (t.PeakDetect.prototype.onPeak = function (t, e) { + var i = this; + i._onPeak = function () { + t(i.energy, e); + }; + }); + })(); + var ut; + ut = (function () { + var e = a; + (t.Gain = function () { + (this.ac = e.audiocontext), + (this.input = this.ac.createGain()), + (this.output = this.ac.createGain()), + (this.input.gain.value = 0.5), + this.input.connect(this.output), + e.soundArray.push(this); + }), + (t.Gain.prototype.setInput = function (t) { + t.connect(this.input); + }), + (t.Gain.prototype.connect = function (e) { + var i = e || t.soundOut.input; + this.output.connect(i.input ? i.input : i); + }), + (t.Gain.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.Gain.prototype.amp = function (t, i, n) { + var i = i || 0, + n = n || 0, + o = e.audiocontext.currentTime, + r = this.output.gain.value; + this.output.gain.cancelScheduledValues(o), + this.output.gain.linearRampToValueAtTime(r, o + n), + this.output.gain.linearRampToValueAtTime(t, o + n + i); + }), + (t.Gain.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + this.output && (this.output.disconnect(), delete this.output), + this.input && (this.input.disconnect(), delete this.input); + }); + })(a); + var ct; + ct = (function () { + var e = a; + return ( + (t.AudioVoice = function () { + (this.ac = e.audiocontext), + (this.output = this.ac.createGain()), + this.connect(), + e.soundArray.push(this); + }), + (t.AudioVoice.prototype.play = function (t, e, i, n) {}), + (t.AudioVoice.prototype.triggerAttack = function (t, e, i) {}), + (t.AudioVoice.prototype.triggerRelease = function (t) {}), + (t.AudioVoice.prototype.amp = function (t, e) {}), + (t.AudioVoice.prototype.connect = function (t) { + var i = t || e.input; + this.output.connect(i.input ? i.input : i); + }), + (t.AudioVoice.prototype.disconnect = function () { + this.output.disconnect(); + }), + (t.AudioVoice.prototype.dispose = function () { + this.output && (this.output.disconnect(), delete this.output); + }), + t.AudioVoice + ); + })(a); + var pt; + pt = (function () { + var e = a, + i = ct, + n = u.noteToFreq, + o = 0.15; + (t.MonoSynth = function () { + i.call(this), + (this.oscillator = new t.Oscillator()), + (this.env = new t.Envelope()), + this.env.setRange(1, 0), + this.env.setExp(!0), + this.setADSR(0.02, 0.25, 0.05, 0.35), + this.oscillator.disconnect(), + this.oscillator.connect(this.output), + this.env.disconnect(), + this.env.setInput(this.output.gain), + (this.oscillator.output.gain.value = 1), + this.oscillator.start(), + this.connect(), + e.soundArray.push(this); + }), + (t.MonoSynth.prototype = Object.create(t.AudioVoice.prototype)), + (t.MonoSynth.prototype.play = function (t, e, i, n) { + this.triggerAttack(t, e, ~~i), this.triggerRelease(~~i + (n || o)); + }), + (t.MonoSynth.prototype.triggerAttack = function (t, e, i) { + var i = ~~i, + o = n(t), + r = e || 0.1; + this.oscillator.freq(o, 0, i), this.env.ramp(this.output.gain, i, r); + }), + (t.MonoSynth.prototype.triggerRelease = function (t) { + var t = t || 0; + this.env.ramp(this.output.gain, t, 0); + }), + (t.MonoSynth.prototype.setADSR = function (t, e, i, n) { + this.env.setADSR(t, e, i, n); + }), + Object.defineProperties(t.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (t) { + this.env.setADSR( + t, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, + }, + decay: { + get: function () { + return this.env.dTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + t, + this.env.sPercent, + this.env.rTime + ); + }, + }, + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (t) { + this.env.setADSR(this.env.aTime, this.env.dTime, t, this.env.rTime); + }, + }, + release: { + get: function () { + return this.env.rTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + t + ); + }, + }, + }), + (t.MonoSynth.prototype.amp = function (t, e) { + var i = e || 0; + return ( + "undefined" != typeof t && this.oscillator.amp(t, i), + this.oscillator.amp().value + ); + }), + (t.MonoSynth.prototype.connect = function (t) { + var i = t || e.input; + this.output.connect(i.input ? i.input : i); + }), + (t.MonoSynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.MonoSynth.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this.env && this.env.dispose(), + this.oscillator && this.oscillator.dispose(); + }); + })(a, ct, u); + var ht; + ht = (function () { + var e = a, + i = q, + n = u.noteToFreq; + (t.PolySynth = function (n, o) { + (this.audiovoices = []), + (this.notes = {}), + (this._newest = 0), + (this._oldest = 0), + (this.maxVoices = o || 8), + (this.AudioVoice = void 0 === n ? t.MonoSynth : n), + (this._voicesInUse = new i(0)), + (this.output = e.audiocontext.createGain()), + this.connect(), + this._allocateVoices(), + e.soundArray.push(this); + }), + (t.PolySynth.prototype._allocateVoices = function () { + for (var t = 0; t < this.maxVoices; t++) + this.audiovoices.push(new this.AudioVoice()), + this.audiovoices[t].disconnect(), + this.audiovoices[t].connect(this.output); + }), + (t.PolySynth.prototype.play = function (t, e, i, n) { + var n = n || 1; + this.noteAttack(t, e, i), this.noteRelease(t, i + n); + }), + (t.PolySynth.prototype.noteADSR = function (t, i, n, o, r, s) { + var a = e.audiocontext.currentTime, + s = s || 0, + u = a + s; + this.audiovoices[this.notes[t].getValueAtTime(u)].setADSR(i, n, o, r); + }), + (t.PolySynth.prototype.setADSR = function (t, e, i, n) { + this.audiovoices.forEach(function (o) { + o.setADSR(t, e, i, n); + }); + }), + (t.PolySynth.prototype.noteAttack = function (o, r, s) { + var a, + s = ~~s, + u = e.audiocontext.currentTime + s, + c = n(o), + p = r || 0.1; + if ( + (this.notes[c] && + null !== this.notes[c].getValueAtTime(u) && + this.noteRelease(c, 0), + this._voicesInUse.getValueAtTime(u) < this.maxVoices) + ) + a = Math.max(~~this._voicesInUse.getValueAtTime(u), 0); + else { + a = this._oldest; + var h = t.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(h), + (this._oldest = (this._oldest + 1) % (this.maxVoices - 1)); + } + (this.notes[c] = new i()), this.notes[c].setValueAtTime(a, u); + var l = + null === this._voicesInUse._searchBefore(u) + ? 0 + : this._voicesInUse._searchBefore(u).value; + if ( + (this._voicesInUse.setValueAtTime(l + 1, u), + this._updateAfter(u, 1), + (this._newest = a), + "number" == typeof p) + ) { + var f = (1 / this._voicesInUse.getValueAtTime(u)) * 2; + p = p > f ? f : p; + } + this.audiovoices[a].triggerAttack(c, p, s); + }), + (t.PolySynth.prototype._updateAfter = function (t, e) { + if (null !== this._voicesInUse._searchAfter(t)) { + this._voicesInUse._searchAfter(t).value += e; + var i = this._voicesInUse._searchAfter(t).time; + this._updateAfter(i, e); + } + }), + (t.PolySynth.prototype.noteRelease = function (t, i) { + var o = e.audiocontext.currentTime, + r = i || 0, + s = o + r; + if (t) { + var a = n(t); + if (this.notes[a] && null !== this.notes[a].getValueAtTime(s)) { + var u = Math.max(~~this._voicesInUse.getValueAtTime(s).value, 1); + this._voicesInUse.setValueAtTime(u - 1, s), + u > 0 && this._updateAfter(s, -1), + this.audiovoices[this.notes[a].getValueAtTime(s)].triggerRelease( + r + ), + this.notes[a].dispose(), + delete this.notes[a], + (this._newest = + 0 === this._newest + ? 0 + : (this._newest - 1) % (this.maxVoices - 1)); + } else + console.warn("Cannot release a note that is not already playing"); + } else { + this.audiovoices.forEach(function (t) { + t.triggerRelease(r); + }), + this._voicesInUse.setValueAtTime(0, s); + for (var c in this.notes) + this.notes[c].dispose(), delete this.notes[c]; + } + }), + (t.PolySynth.prototype.connect = function (t) { + var i = t || e.input; + this.output.connect(i.input ? i.input : i); + }), + (t.PolySynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (t.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (t) { + t.dispose(); + }), + this.output && (this.output.disconnect(), delete this.output); + }); + })(a, q, u); + var lt; + lt = (function () { + function e(t) { + for ( + var e, + i = "number" == typeof t ? t : 50, + n = 44100, + o = new Float32Array(n), + r = Math.PI / 180, + s = 0; + n > s; + ++s + ) + (e = (2 * s) / n - 1), + (o[s] = ((3 + i) * e * 20 * r) / (Math.PI + i * Math.abs(e))); + return o; + } + var i = Y; + (t.Distortion = function (n, o) { + if ( + (i.call(this), + "undefined" == typeof n && (n = 0.25), + "number" != typeof n) + ) + throw new Error("amount must be a number"); + if (("undefined" == typeof o && (o = "2x"), "string" != typeof o)) + throw new Error("oversample must be a String"); + var r = t.prototype.map(n, 0, 1, 0, 2e3); + (this.waveShaperNode = this.ac.createWaveShaper()), + (this.amount = r), + (this.waveShaperNode.curve = e(r)), + (this.waveShaperNode.oversample = o), + this.input.connect(this.waveShaperNode), + this.waveShaperNode.connect(this.wet); + }), + (t.Distortion.prototype = Object.create(i.prototype)), + (t.Distortion.prototype.process = function (t, e, i) { + t.connect(this.input), this.set(e, i); + }), + (t.Distortion.prototype.set = function (i, n) { + if (i) { + var o = t.prototype.map(i, 0, 1, 0, 2e3); + (this.amount = o), (this.waveShaperNode.curve = e(o)); + } + n && (this.waveShaperNode.oversample = n); + }), + (t.Distortion.prototype.getAmount = function () { + return this.amount; + }), + (t.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }), + (t.Distortion.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this.waveShaperNode && + (this.waveShaperNode.disconnect(), (this.waveShaperNode = null)); + }); + })(Y); + var ft; + ft = (function () { + var t = a; + return t; + })( + e, + s, + a, + u, + c, + p, + h, + l, + f, + k, + O, + M, + E, + V, + R, + z, + Q, + H, + $, + J, + K, + it, + nt, + ot, + rt, + st, + at, + ut, + pt, + ht, + lt, + ct, + pt, + ht + ); +}); diff --git a/week1-intro/imageClassification-ml5/ImageClassification/index.html b/week1-intro/imageClassification-ml5/ImageClassification/index.html index 8281c73..9dde548 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification/index.html @@ -1,17 +1,15 @@ - - - - Image classification using MobileNet and p5.js - - - - - - - -

Image classification using MobileNet and p5.js

- - - - \ No newline at end of file + + + Image classification using MobileNet and p5.js + + + + + + + +

Image classification using MobileNet and p5.js

+ + + diff --git a/week1-intro/imageClassification-ml5/ImageClassification_Video/index.html b/week1-intro/imageClassification-ml5/ImageClassification_Video/index.html index 3e0f3ff..9690f6f 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification_Video/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification_Video/index.html @@ -1,18 +1,16 @@ + + + Webcam Image Classification using MobileNet and p5.js - - - Webcam Image Classification using MobileNet and p5.js + + - - + + - - - - -

Webcam Image Classification using MobileNet and p5.js

- - - - \ No newline at end of file + +

Webcam Image Classification using MobileNet and p5.js

+ + + diff --git a/week1-intro/imageClassification-ml5/ImageClassification_VideoScavengerHunt/index.html b/week1-intro/imageClassification-ml5/ImageClassification_VideoScavengerHunt/index.html index 40dfc9d..93ba435 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification_VideoScavengerHunt/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification_VideoScavengerHunt/index.html @@ -1,26 +1,26 @@ + + + + Webcam Image Classification with Speech Output using MobileNet, p5.js, + p5.speech + - - - Webcam Image Classification with Speech Output using MobileNet, p5.js, p5.speech + + - - + + + - - - - - - -

Webcam Scavenger Hunt Game using MobileNet, p5.js, p5.speech

-

Loading Model...

-

Please turn on the sound on your device.

- -

-

-

- - - - \ No newline at end of file + +

Webcam Scavenger Hunt Game using MobileNet, p5.js, p5.speech

+

Loading Model...

+

Please turn on the sound on your device.

+ +

+

+

+ + + diff --git a/week1-intro/imageClassification-ml5/ImageClassification_VideoSound/index.html b/week1-intro/imageClassification-ml5/ImageClassification_VideoSound/index.html index 2d01cfe..6f07d40 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification_VideoSound/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification_VideoSound/index.html @@ -1,26 +1,29 @@ + + + + Webcam Image Classification with Speech Output using MobileNet, p5.js, + p5.speech + - - - Webcam Image Classification with Speech Output using MobileNet, p5.js, p5.speech + + - - + + + - - - - - - -

Webcam Image Classification with Speech Output using MobileNet, p5.js, p5.speech

-

Loading Model...

-

Please turn on the sound on your device.

-

- I see ... -
with a confidence of .... -

- - - - \ No newline at end of file + +

+ Webcam Image Classification with Speech Output using MobileNet, p5.js, + p5.speech +

+

Loading Model...

+

Please turn on the sound on your device.

+

+ I see ...
with a confidence of + .... +

+ + + diff --git a/week1-intro/imageClassification-ml5/ImageClassification_VideoSoundTranslate/index.html b/week1-intro/imageClassification-ml5/ImageClassification_VideoSoundTranslate/index.html index 8cb9b0e..28c0d9e 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification_VideoSoundTranslate/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification_VideoSoundTranslate/index.html @@ -1,36 +1,49 @@ + + + + Webcam Image Classification with Speech Output using MobileNet, p5.js, + p5.speech, google translate API + - - - Webcam Image Classification with Speech Output using MobileNet, p5.js, p5.speech, google translate API + + + - - - + + - - - - -

Webcam Image Classification with Speech Output Translated to another language

-

Using MobileNet, p5.js, p5.speech, and Google translate API

-

Before you run this example, you need to put in your own Google API key in the sketch.js

-

You will need to register and generate and get Google API key and also enable the Google Translate API in the Google Console. - Read more here -

-

Loading Model...

-

Please turn on the sound on your device.

- -

- The MobileNet model labeled this as ... -
with a confidence of .... -

-

Translated result:

- - - - \ No newline at end of file + +

+ Webcam Image Classification with Speech Output Translated to another + language +

+

Using MobileNet, p5.js, p5.speech, and Google translate API

+

+ Before you run this example, you need to put in your own Google API key in + the sketch.js +

+

+ You will need to register and generate and get Google API key and also + enable the Google Translate API in the Google Console. Read more + here +

+

Loading Model...

+

Please turn on the sound on your device.

+ +

+ The MobileNet model labeled this as ... +
with a confidence of .... +

+

Translated result:

+ + + diff --git a/week1-intro/imageClassification-ml5/ImageClassification_Video_js/index.html b/week1-intro/imageClassification-ml5/ImageClassification_Video_js/index.html index f7197d1..f26296e 100755 --- a/week1-intro/imageClassification-ml5/ImageClassification_Video_js/index.html +++ b/week1-intro/imageClassification-ml5/ImageClassification_Video_js/index.html @@ -1,24 +1,24 @@ + + + Webcam Image Classification using MobileNet - - - Webcam Image Classification using MobileNet - - - - - - -

Webcam Image classification using MobileNet

-

If you are using a mobile phone, use Safari browser on ios(iPhone), or Chrome on android

-

Loading Model...

-

- The MobileNet model labeled this as ... -
with a confidence of .... -

-

- - - + + + +

Webcam Image classification using MobileNet

+

+ If you are using a mobile phone, use Safari browser on ios(iPhone), or + Chrome on android +

+

Loading Model...

+

+ The MobileNet model labeled this as ... +
with a confidence of .... +

+

+ + + diff --git a/week1-intro/p5+arduino+mobileNet/p5_code/index.html b/week1-intro/p5+arduino+mobileNet/p5_code/index.html index 7c1d4ab..e6c5b89 100644 --- a/week1-intro/p5+arduino+mobileNet/p5_code/index.html +++ b/week1-intro/p5+arduino+mobileNet/p5_code/index.html @@ -1,15 +1,19 @@ - + + + - - - - - + + + + - - - \ No newline at end of file + + diff --git a/week1-intro/p5+arduino+mobileNet/p5_code/ml5.min.js b/week1-intro/p5+arduino+mobileNet/p5_code/ml5.min.js deleted file mode 100644 index 842029e..0000000 --- a/week1-intro/p5+arduino+mobileNet/p5_code/ml5.min.js +++ /dev/null @@ -1,90 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ml5=e():t.ml5=e()}(window,function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=698)}([function(t,e,n){"use strict";n.r(e),function(t,r,i,a){n.d(e,"AdadeltaOptimizer",function(){return ml}),n.d(e,"AdagradOptimizer",function(){return vl}),n.d(e,"AdamOptimizer",function(){return gl}),n.d(e,"AdamaxOptimizer",function(){return bl}),n.d(e,"DataStorage",function(){return Zn}),n.d(e,"ENV",function(){return f}),n.d(e,"Environment",function(){return h}),n.d(e,"KernelBackend",function(){return Qn}),n.d(e,"MomentumOptimizer",function(){return wl}),n.d(e,"Optimizer",function(){return pl}),n.d(e,"RMSPropOptimizer",function(){return xl}),n.d(e,"Rank",function(){return bt}),n.d(e,"Reduction",function(){return Mu}),n.d(e,"SGDOptimizer",function(){return yl}),n.d(e,"Tensor",function(){return vt}),n.d(e,"TensorBuffer",function(){return ht}),n.d(e,"Variable",function(){return gt}),n.d(e,"abs",function(){return Oa}),n.d(e,"acos",function(){return Ta}),n.d(e,"acosh",function(){return Ia}),n.d(e,"add",function(){return Ms}),n.d(e,"addN",function(){return Rs}),n.d(e,"addStrict",function(){return Ds}),n.d(e,"all",function(){return cs}),n.d(e,"any",function(){return ls}),n.d(e,"argMax",function(){return fs}),n.d(e,"argMin",function(){return hs}),n.d(e,"asin",function(){return Ma}),n.d(e,"asinh",function(){return Ra}),n.d(e,"atan",function(){return Da}),n.d(e,"atan2",function(){return js}),n.d(e,"atanh",function(){return ja}),n.d(e,"avgPool",function(){return es}),n.d(e,"backend",function(){return $e}),n.d(e,"basicLSTMCell",function(){return gu}),n.d(e,"batchNorm",function(){return xo}),n.d(e,"batchNorm2d",function(){return ko}),n.d(e,"batchNorm3d",function(){return So}),n.d(e,"batchNorm4d",function(){return _o}),n.d(e,"batchNormalization",function(){return wo}),n.d(e,"batchNormalization2d",function(){return go}),n.d(e,"batchNormalization3d",function(){return bo}),n.d(e,"batchNormalization4d",function(){return yo}),n.d(e,"batchToSpaceND",function(){return Tr}),n.d(e,"browser",function(){return el}),n.d(e,"buffer",function(){return Nr}),n.d(e,"cast",function(){return Ir}),n.d(e,"ceil",function(){return za}),n.d(e,"clipByValue",function(){return Pa}),n.d(e,"clone",function(){return Mr}),n.d(e,"complex",function(){return Dn}),n.d(e,"concat",function(){return fr}),n.d(e,"concat1d",function(){return hr}),n.d(e,"concat2d",function(){return dr}),n.d(e,"concat3d",function(){return pr}),n.d(e,"concat4d",function(){return mr}),n.d(e,"conv1d",function(){return Po}),n.d(e,"conv2d",function(){return Lo}),n.d(e,"conv2dDerFilter",function(){return Bo}),n.d(e,"conv2dTranspose",function(){return Wo}),n.d(e,"conv3d",function(){return Fo}),n.d(e,"cos",function(){return La}),n.d(e,"cosh",function(){return Fa}),n.d(e,"cumsum",function(){return Rr}),n.d(e,"customGrad",function(){return On}),n.d(e,"deprecationWarn",function(){return De}),n.d(e,"depthToSpace",function(){return Dr}),n.d(e,"depthwiseConv2d",function(){return Uo}),n.d(e,"disableDeprecationWarnings",function(){return Re}),n.d(e,"dispose",function(){return Fe}),n.d(e,"disposeVariables",function(){return je}),n.d(e,"div",function(){return zs}),n.d(e,"divStrict",function(){return Ps}),n.d(e,"dot",function(){return Ho}),n.d(e,"dropout",function(){return Tu}),n.d(e,"elu",function(){return au}),n.d(e,"enableDebugMode",function(){return Me}),n.d(e,"enableProdMode",function(){return Ie}),n.d(e,"environment",function(){return m}),n.d(e,"equal",function(){return ws}),n.d(e,"equalStrict",function(){return xs}),n.d(e,"erf",function(){return Ba}),n.d(e,"exp",function(){return Ua}),n.d(e,"expandDims",function(){return jr}),n.d(e,"expm1",function(){return Va}),n.d(e,"eye",function(){return zr}),n.d(e,"fft",function(){return Su}),n.d(e,"fill",function(){return Kn}),n.d(e,"findBackend",function(){return Ge}),n.d(e,"findBackendFactory",function(){return Ke}),n.d(e,"floor",function(){return Wa}),n.d(e,"floorDiv",function(){return Ls}),n.d(e,"fused",function(){return nc}),n.d(e,"gather",function(){return mu}),n.d(e,"gatherND",function(){return Ou}),n.d(e,"getBackend",function(){return qe}),n.d(e,"grad",function(){return _n}),n.d(e,"grads",function(){return En}),n.d(e,"greater",function(){return ks}),n.d(e,"greaterEqual",function(){return Ss}),n.d(e,"greaterEqualStrict",function(){return _s}),n.d(e,"greaterStrict",function(){return Es}),n.d(e,"hammingWindow",function(){return Du}),n.d(e,"hannWindow",function(){return Ru}),n.d(e,"ifft",function(){return _u}),n.d(e,"imag",function(){return zn}),n.d(e,"image",function(){return tc}),n.d(e,"io",function(){return Jc}),n.d(e,"irfft",function(){return Cu}),n.d(e,"isFinite",function(){return eo}),n.d(e,"isInf",function(){return to}),n.d(e,"isNaN",function(){return Qa}),n.d(e,"keep",function(){return Be}),n.d(e,"leakyRelu",function(){return ou}),n.d(e,"less",function(){return Cs}),n.d(e,"lessEqual",function(){return As}),n.d(e,"lessEqualStrict",function(){return Ns}),n.d(e,"lessStrict",function(){return Os}),n.d(e,"linalg",function(){return Xu}),n.d(e,"linspace",function(){return Xn}),n.d(e,"localResponseNormalization",function(){return fu}),n.d(e,"log",function(){return qa}),n.d(e,"log1p",function(){return Ha}),n.d(e,"logSigmoid",function(){return Ga}),n.d(e,"logSoftmax",function(){return Rn}),n.d(e,"logSumExp",function(){return ds}),n.d(e,"logicalAnd",function(){return Qs}),n.d(e,"logicalNot",function(){return tu}),n.d(e,"logicalOr",function(){return eu}),n.d(e,"logicalXor",function(){return nu}),n.d(e,"losses",function(){return qu}),n.d(e,"matMul",function(){return qo}),n.d(e,"math",function(){return Qc}),n.d(e,"max",function(){return ps}),n.d(e,"maxPool",function(){return ts}),n.d(e,"maximum",function(){return Fs}),n.d(e,"maximumStrict",function(){return Bs}),n.d(e,"mean",function(){return ms}),n.d(e,"memory",function(){return ze}),n.d(e,"min",function(){return vs}),n.d(e,"minimum",function(){return Us}),n.d(e,"minimumStrict",function(){return Vs}),n.d(e,"mod",function(){return Ws}),n.d(e,"modStrict",function(){return qs}),n.d(e,"moments",function(){return gs}),n.d(e,"movingAverage",function(){return yu}),n.d(e,"mul",function(){return Hs}),n.d(e,"mulStrict",function(){return Gs}),n.d(e,"multiRNNCell",function(){return bu}),n.d(e,"multinomial",function(){return Pr}),n.d(e,"neg",function(){return Ka}),n.d(e,"nextFrame",function(){return El}),n.d(e,"norm",function(){return hu}),n.d(e,"notEqual",function(){return Ts}),n.d(e,"notEqualStrict",function(){return Is}),n.d(e,"oneHot",function(){return Lr}),n.d(e,"ones",function(){return Hn}),n.d(e,"onesLike",function(){return Yn}),n.d(e,"op",function(){return In}),n.d(e,"outerProduct",function(){return Go}),n.d(e,"pad",function(){return Fr}),n.d(e,"pad1d",function(){return Br}),n.d(e,"pad2d",function(){return Ur}),n.d(e,"pad3d",function(){return Vr}),n.d(e,"pad4d",function(){return Wr}),n.d(e,"pool",function(){return ns}),n.d(e,"pow",function(){return Ks}),n.d(e,"powStrict",function(){return Xs}),n.d(e,"prelu",function(){return su}),n.d(e,"print",function(){return Or}),n.d(e,"prod",function(){return ys}),n.d(e,"profile",function(){return Pe}),n.d(e,"rand",function(){return qr}),n.d(e,"randomNormal",function(){return Hr}),n.d(e,"randomUniform",function(){return Gr}),n.d(e,"range",function(){return $n}),n.d(e,"ready",function(){return We}),n.d(e,"real",function(){return jn}),n.d(e,"reciprocal",function(){return Xa}),n.d(e,"registerBackend",function(){return Xe}),n.d(e,"relu",function(){return uu}),n.d(e,"removeBackend",function(){return He}),n.d(e,"reshape",function(){return Kr}),n.d(e,"reverse",function(){return Ko}),n.d(e,"reverse1d",function(){return Xo}),n.d(e,"reverse2d",function(){return $o}),n.d(e,"reverse3d",function(){return Yo}),n.d(e,"reverse4d",function(){return Jo}),n.d(e,"rfft",function(){return Eu}),n.d(e,"round",function(){return $a}),n.d(e,"rsqrt",function(){return Ya}),n.d(e,"scalar",function(){return Ln}),n.d(e,"scatterND",function(){return ku}),n.d(e,"selu",function(){return cu}),n.d(e,"separableConv2d",function(){return Vo}),n.d(e,"serialization",function(){return al}),n.d(e,"setBackend",function(){return Ve}),n.d(e,"setdiff1dAsync",function(){return ti}),n.d(e,"sigmoid",function(){return Ja}),n.d(e,"sign",function(){return Za}),n.d(e,"sin",function(){return no}),n.d(e,"sinh",function(){return ro}),n.d(e,"slice",function(){return rs}),n.d(e,"slice1d",function(){return is}),n.d(e,"slice2d",function(){return as}),n.d(e,"slice3d",function(){return os}),n.d(e,"slice4d",function(){return ss}),n.d(e,"softmax",function(){return Mn}),n.d(e,"softplus",function(){return io}),n.d(e,"spaceToBatchND",function(){return Xr}),n.d(e,"sparseToDense",function(){return Nu}),n.d(e,"spectral",function(){return Au}),n.d(e,"split",function(){return vr}),n.d(e,"sqrt",function(){return ao}),n.d(e,"square",function(){return oo}),n.d(e,"squaredDifference",function(){return $s}),n.d(e,"squaredDifferenceStrict",function(){return Ys}),n.d(e,"squeeze",function(){return $r}),n.d(e,"stack",function(){return Yr}),n.d(e,"step",function(){return so}),n.d(e,"stridedSlice",function(){return wu}),n.d(e,"sub",function(){return Js}),n.d(e,"subStrict",function(){return Zs}),n.d(e,"sum",function(){return bs}),n.d(e,"tan",function(){return uo}),n.d(e,"tanh",function(){return co}),n.d(e,"tensor",function(){return Pn}),n.d(e,"tensor1d",function(){return Fn}),n.d(e,"tensor2d",function(){return Bn}),n.d(e,"tensor3d",function(){return Un}),n.d(e,"tensor4d",function(){return Vn}),n.d(e,"tensor5d",function(){return Wn}),n.d(e,"tensor6d",function(){return qn}),n.d(e,"tensor_util",function(){return It}),n.d(e,"test_util",function(){return fl}),n.d(e,"tidy",function(){return Le}),n.d(e,"tile",function(){return Jr}),n.d(e,"time",function(){return Ue}),n.d(e,"topk",function(){return xu}),n.d(e,"train",function(){return Sl}),n.d(e,"transpose",function(){return lu}),n.d(e,"truncatedNormal",function(){return Zr}),n.d(e,"unsortedSegmentSum",function(){return vu}),n.d(e,"unstack",function(){return Qr}),n.d(e,"util",function(){return at}),n.d(e,"valueAndGrad",function(){return Cn}),n.d(e,"valueAndGrads",function(){return An}),n.d(e,"variable",function(){return St}),n.d(e,"variableGrads",function(){return Nn}),n.d(e,"version_core",function(){return hl}),n.d(e,"webgl",function(){return dl}),n.d(e,"where",function(){return ru}),n.d(e,"whereAsync",function(){return iu}),n.d(e,"zeros",function(){return Gn}),n.d(e,"zerosLike",function(){return Jn}); -/** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -var o=function(t,e){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)};function s(t,e){function n(){this.constructor=t}o(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var u=function(){return(u=Object.assign||function(t){for(var e,n=1,r=arguments.length;n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0;)r=Math.random()*e|0,n=t[--e],t[e]=t[r],t[r]=n}function g(t,e,n){return Math.max(t,Math.min(e,n))}function b(t){return t%2==0?t:t+1}function y(t){for(var e=0,n=0;n=n?i():setTimeout(o,s)}};o()})}function I(t,e){for(var n=1,r=-1,i=0;i=0)n*=t[i];else if(-1===t[i]){if(-1!==r)throw Error("Shapes can only have 1 implicit size. Found -1 at dim "+r+" and dim "+i);r=i}else if(t[i]<0)throw Error("Shapes can not be < 0. Found "+t[i]+" at dim "+i);if(-1===r){if(e>0&&e!==n)throw Error("Size("+e+") must match the product of shape "+t);return t}if(0===n)throw Error("Cannot infer the missing size in ["+t+"] when there are 0 elements");if(e%n!=0)throw Error("The implicit shape can't be a fractional number. Got "+e+" / "+n);var a=t.slice();return a[r]=e/n,a}function M(t,e){var n=e.length;return w((t=null==t?e.map(function(t,e){return e}):[].concat(t)).every(function(t){return t>=-n&&to)&&1===t[o]&&(n.push(t[o]),r.push(o)),i[a]<=o&&a++}1!==t[o]&&(n.push(t[o]),r.push(o))}return{newShape:n,keptDims:r}}function D(t,e){var n=null;if(null==t||"float32"===t)n=new Float32Array(e);else if("int32"===t)n=new Int32Array(e);else{if("bool"!==t)throw new Error("Unknown data type "+t);n=new Uint8Array(e)}return n}function j(t,e){var n=null;if(null==t||"float32"===t)n=new Float32Array(e);else if("int32"===t)n=new Int32Array(e);else if("bool"===t)n=new Uint8Array(e);else{if("string"!==t)throw new Error("Unknown data type "+t);n=new Array(e)}return n}function z(t,e,n){if("float32"===e)for(var r=0;r=0;--r)n[r]=n[r+1]*t[r+1];return n}function $(t,e,n){if("string"===e)throw new Error("Cannot convert a string[] to a TypedArray");if(Array.isArray(t)&&(t=S(t)),n&&P(t,e),function(t,e){return t instanceof Float32Array&&"float32"===e||t instanceof Int32Array&&"int32"===e||t instanceof Uint8Array&&"bool"===e}(t,e))return t;if(null==e||"float32"===e||"complex64"===e)return new Float32Array(t);if("int32"===e)return new Int32Array(t);if("bool"===e){for(var r=new Uint8Array(t.length),i=0;i=0,function(){return"Tensor must have a shape comprised of positive integers but got shape ["+t+"]."})})}var et,nt=function(){if(null!=f.global.fetch)return f.global.fetch;if(f.get("IS_NODE"))return rt.fetchImport();throw new Error("Unable to find the fetch() method. Please add your own fetch() function to the global namespace.")},rt={fetchImport:function(){return n(486)}};function it(t,e){return null==et&&(et=nt()),et(t,e)}var at=Object.freeze({shuffle:v,clamp:g,nearestLargerEven:b,sum:y,randUniform:function(t,e){var n=Math.random();return e*n+(1-n)*t},distSquared:function(t,e){for(var n=0,r=0;r=this.shape[n]){var o="Requested out of range element at "+t+". Buffer shape="+this.shape;throw new Error(o)}n++}for(var s=t[t.length-1],u=0;u1)for(var c=0;c20){var l=3*s,f=Array.from(e.slice(0,l)),h=Array.from(e.slice(u-3*s,u));return"complex64"===r&&(f=ft(f),h=ft(h)),["["+f.map(function(t,e){return ct(t,a[e],r)}).join(", ")+", ..., "+h.map(function(t,e){return ct(t,a[u-3+e],r)}).join(", ")+"]"]}return["["+("complex64"===r?ft(e):Array.from(e)).map(function(t,e){return ct(t,a[e],r)}).join(", ")+"]"]}var d=n.slice(1),p=i.slice(1),m=i[0]*s,v=[];if(u>20){for(var g=0;g<3;g++){var b=(y=g*m)+m;v.push.apply(v,t(e.slice(y,b),d,r,p,a,!1))}for(v.push("..."),g=u-3;g0&&(t.unreliable=!0,null==t.reasons&&(t.reasons=[]),t.reasons.push("Memory usage by string tensors is approximate (2 bytes per character)")),t},t.prototype.profile=function(t){return c(this,void 0,void 0,function(){var e,n;return l(this,function(r){return this.state.profiling=!0,e=this.state.numBytes,n=this.state.numTensors,this.state.activeProfile.kernels=[],this.state.activeProfile.result=t(),this.state.profiling=!1,this.state.activeProfile.peakBytes=Math.max.apply(Math,this.state.activeProfile.kernels.map(function(t){return t.totalBytesSnapshot})),this.state.activeProfile.newBytes=this.state.numBytes-e,this.state.activeProfile.newTensors=this.state.numTensors-n,[2,this.state.activeProfile]})})},t.prototype.isTapeOn=function(){return this.state.gradientDepth>0&&0===this.state.kernelDepth},t.prototype.addTapeNode=function(t,e,n){var r={};t.forEach(function(t,e){r[e]=t});var i={id:this.state.nextTapeNodeId++,name:this.state.activeScope.name,inputs:r,outputs:[e],gradient:function(t){var e={};return n(t).forEach(function(t,n){e[n]=function(){return t}}),e}};this.state.activeTape.push(i)},t.prototype.keep=function(t){return t.kept=!0,t},t.prototype.startTape=function(){0===this.state.gradientDepth&&(this.state.activeTape=[]),this.state.gradientDepth++},t.prototype.endTape=function(){this.state.gradientDepth--},t.prototype.startScope=function(t){var e={track:[],name:"unnamed scope",id:this.state.nextScopeId++};t&&(e.name=t),this.state.scopeStack.push(e),this.state.activeScope=e},t.prototype.endScope=function(t){for(var e=this,n=Ot(t),r=new Set(n.map(function(t){return t.id})),i=0;i0,function(){return"gradients() received an empty list of xs."}),null!=n&&"float32"!==n.dtype)throw new Error("dy must have 'float32' dtype, but has '"+n.dtype+"'");var a=this.scopedRun(function(){return i.startTape()},function(){return i.endTape()},function(){return i.tidy("forward",t)});w(a instanceof vt,function(){return"The result y returned by f() must be a tensor."});var o=function(t,e,n){for(var r={},i={},a=0;a=0;a--)for(o=(p=t[a]).inputs,l=0;l0)throw new Error("Cannot compute gradient of y=f(x) with respect to x. Make sure that the f you passed encloses all operations that lead from x to y.");return this.tidy("backward",function(){var t,r,s={};s[a.id]=null==n?(r=J(_(t=a.shape),"float32"),vt.make(t,{values:r})):n,function(t,e,n){for(var r=function(r){var i=e[r],a=[];if(i.outputs.forEach(function(e){var n=t[e.id];if(null!=n)a.push(n);else{var r=vt.make(e.shape,{values:Z(e.size,e.dtype)},e.dtype);a.push(r)}}),null==i.gradient)throw new Error("Cannot compute gradient: gradient function not found for "+i.name+".");var o=i.gradient(1===i.outputs.length?a[0]:a),s=function(e){if(!(e in o))throw new Error("Cannot backprop through input "+e+". Available gradients found: "+Object.keys(o)+".");var r=n(function(){return o[e]()});if("float32"!==r.dtype)throw new Error("Error in gradient for op "+i.name+". The gradient of input "+e+" must have 'float32' dtype, but has '"+r.dtype+"'");var a=i.inputs[e];if(!E(r.shape,a.shape))throw new Error("Error in gradient for op "+i.name+". The gradient of input '"+e+"' has shape '"+r.shape+"', which does not match the shape of the input '"+a.shape+"'");if(null==t[a.id])t[a.id]=r;else{var s=t[a.id];t[a.id]=s.add(r),s.dispose()}};for(var u in i.inputs)s(u)},i=e.length-1;i>=0;i--)r(i)}(s,o,function(t){return i.tidy(t)});var u=e.map(function(t){return s[t.id]});return 0===i.state.gradientDepth&&(i.state.activeTape.forEach(function(t){for(var e in t.saved)t.saved[e].dispose()}),i.state.activeTape=null),{value:a,grads:u}})},t.prototype.customGrad=function(t){var e=this;return w(G(t),function(){return"The f passed in customGrad(f) must be a function."}),function(){for(var n,r=[],i=0;in||e>n)throw r="["+t+"x"+e+"]",new Error("Requested texture size "+r+" greater than WebGL maximum on this browser / GPU ["+n+"x"+n+"].")}function ie(t,e){return pe(t,e,function(){return t.createFramebuffer()},"Unable to create WebGLFramebuffer.")}function ae(t,e,n,r,i,a,o,s){var u=t.getAttribLocation(n,r);return-1!==u&&(Ft(t,e,function(){return t.bindBuffer(t.ARRAY_BUFFER,i)}),Ft(t,e,function(){return t.vertexAttribPointer(u,a,t.FLOAT,!1,o,s)}),Ft(t,e,function(){return t.enableVertexAttribArray(u)}),!0)}function oe(t,e,n,r){me(t,r),Ft(t,e,function(){return t.activeTexture(t.TEXTURE0+r)}),Ft(t,e,function(){return t.bindTexture(t.TEXTURE_2D,n)})}function se(t,e,n,r){return pe(t,e,function(){return t.getUniformLocation(n,r)},'uniform "'+r+'" not present in program.')}function ue(t,e,n){return t.getUniformLocation(e,n)}function ce(t,e,n,r,i,a){Ft(t,e,function(){return oe(t,e,r,a)}),Ft(t,e,function(){return t.uniform1i(i,a)})}function le(t,e,n,r){Ft(t,e,function(){return t.bindFramebuffer(t.FRAMEBUFFER,r)}),Ft(t,e,function(){return t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,n,0)})}function fe(t,e,n){Ft(t,e,function(){return t.bindFramebuffer(t.FRAMEBUFFER,n)}),Ft(t,e,function(){return t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,null,0)})}function he(t){var e=t.checkFramebufferStatus(t.FRAMEBUFFER);if(e!==t.FRAMEBUFFER_COMPLETE)throw new Error("Error binding framebuffer: "+de(t,e))}function de(t,e){switch(e){case t.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:return"FRAMEBUFFER_INCOMPLETE_ATTACHMENT";case t.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:return"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";case t.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:return"FRAMEBUFFER_INCOMPLETE_DIMENSIONS";case t.FRAMEBUFFER_UNSUPPORTED:return"FRAMEBUFFER_UNSUPPORTED";default:return"unknown error "+e}}function pe(t,e,n,r){var i=Ft(t,e,function(){return n()});if(null==i)throw new Error(r);return i}function me(t,e){var n=t.MAX_COMBINED_TEXTURE_IMAGE_UNITS-1,r=e+t.TEXTURE0;if(rn)throw new Error("textureUnit must be in [gl.TEXTURE0, gl.TEXTURE"+n+"].")}function ve(t,e){return void 0===e&&(e=2),_(t.slice(0,t.length-e))}function ge(t){if(0===t.length)throw Error("Cannot get rows and columns of an empty shape array.");return[t.length>1?t[t.length-2]:1,t[t.length-1]]}function be(t,e){var n;void 0===e&&(e=!1);var r=f.getNumber("WEBGL_MAX_TEXTURE_SIZE");if(e&&(r*=2,1===(t=t.map(function(e,n){return n>=t.length-2?b(t[n]):t[n]})).length&&(t=[2,t[0]])),2!==t.length){var i=R(t);t=i.newShape}var a=_(t);if(t.length<=1&&a<=r)return[1,a];if(2===t.length&&t[0]<=r&&t[1]<=r)return t;if(3===t.length&&t[0]*t[1]<=r&&t[2]<=r)return[t[0]*t[1],t[2]];if(3===t.length&&t[0]<=r&&t[1]*t[2]<=r)return[t[0],t[1]*t[2]];if(4===t.length&&t[0]*t[1]*t[2]<=r&&t[3]<=r)return[t[0]*t[1]*t[2],t[3]];if(4===t.length&&t[0]<=r&&t[1]*t[2]*t[3]<=r)return[t[0],t[1]*t[2]*t[3]];if(e){var o=ve(t),s=2,u=2;return t.length&&(s=(n=ge(t))[0],u=n[1]),N(a=o*(s/2)*(u/2)).map(function(t){return 2*t})}return N(a)}function ye(t){return t%2==0}function we(t,e){if(E(t=t.slice(-2),e=e.slice(-2)))return!0;if(!t.length||!e.length)return!0;if(0===t[0]||0===t[1]||0===e[0]||0===e[1])return!0;if(t.length!==e.length){var n=t.slice(-1)[0],r=e.slice(-1)[0];if(n===r)return!0;if(ye(n)&&ye(r)&&(1===t[0]||1===e[0]))return!0}return t[1]===e[1]&&ye(t[0])&&ye(e[0])}function xe(t){if(null==Kt){var e=Lt(t);Kt=e.getParameter(e.MAX_TEXTURE_SIZE)}return Kt}function ke(t){if(null==Xt){var e=Lt(t);Xt=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS)}return Math.min(16,Xt)}function Se(t){if(0===t)return 0;var e=Lt(t);return _e(e,"EXT_disjoint_timer_query_webgl2")&&2===t?2:_e(e,"EXT_disjoint_timer_query")?1:0}function _e(t,e){return null!=t.getExtension(e)}function Ee(t){try{if(null!=Lt(t))return!0}catch(t){return!1}return!1}function Ce(t){if(0===t)return!1;var e=Lt(t);if(1===t){if(!_e(e,"OES_texture_float"))return!1}else if(!_e(e,"EXT_color_buffer_float"))return!1;return Ne(e,t)}function Ae(t){if(0===t)return!1;var e=Lt(t);if(1===t){if(!_e(e,"OES_texture_float"))return!1;if(!_e(e,"WEBGL_color_buffer_float"))return!1}else if(!_e(e,"EXT_color_buffer_float"))return!1;return Ne(e,t)}function Ne(t,e){var n=t.createFramebuffer(),r=t.createTexture();t.bindTexture(t.TEXTURE_2D,r);var i=2===e?t.RGBA32F:t.RGBA;t.texImage2D(t.TEXTURE_2D,0,i,1,1,0,t.RGBA,t.FLOAT,null),t.bindFramebuffer(t.FRAMEBUFFER,n),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,r,0);var a=t.checkFramebufferStatus(t.FRAMEBUFFER)===t.FRAMEBUFFER_COMPLETE;return t.bindTexture(t.TEXTURE_2D,null),t.bindFramebuffer(t.FRAMEBUFFER,null),t.deleteTexture(r),t.deleteFramebuffer(n),a}function Oe(t){return 2===t&&null!=Lt(t).fenceSync}var Te=Object.freeze({callAndCheck:Ft,canBeRepresented:Vt,getWebGLErrorMessage:Wt,getExtensionOrThrow:qt,createVertexShader:Ht,createFragmentShader:Gt,createProgram:Yt,linkProgram:Jt,validateProgram:Zt,createStaticVertexBuffer:Qt,createStaticIndexBuffer:te,getNumChannels:ee,createTexture:ne,validateTextureSize:re,createFramebuffer:ie,bindVertexBufferToProgramAttribute:ae,bindTextureUnit:oe,unbindTextureUnit:function(t,e,n){me(t,n),Ft(t,e,function(){return t.activeTexture(t.TEXTURE0+n)}),Ft(t,e,function(){return t.bindTexture(t.TEXTURE_2D,null)})},getProgramUniformLocationOrThrow:se,getProgramUniformLocation:ue,bindTextureToProgramUniformSampler:ce,bindCanvasToFramebuffer:function(t,e){Ft(t,e,function(){return t.bindFramebuffer(t.FRAMEBUFFER,null)}),Ft(t,e,function(){return t.viewport(0,0,t.canvas.width,t.canvas.height)}),Ft(t,e,function(){return t.scissor(0,0,t.canvas.width,t.canvas.height)})},bindColorTextureToFramebuffer:le,unbindColorTextureFromFramebuffer:fe,validateFramebuffer:he,getFramebufferErrorMessage:de,getBatchDim:ve,getRowsCols:ge,getTextureShapeFromLogicalShape:be,isReshapeFree:we,get MAX_TEXTURE_SIZE(){return Kt},get MAX_TEXTURES_IN_SHADER(){return Xt},getWebGLMaxTextureSize:xe,getMaxTexturesInShader:ke,getWebGLDisjointQueryTimerVersion:Se,isWebGLVersionEnabled:Ee,isRenderToFloatTextureEnabled:Ce,isDownloadFloatTextureEnabled:Ae,isWebGLFenceEnabled:Oe});function Ie(){f.set("PROD",!0)}function Me(){f.set("DEBUG",!0)}function Re(){f.set("DEPRECATION_WARNINGS_ENABLED",!1),console.warn("TensorFlow.js deprecation warnings have been disabled.")}function De(t){f.getBool("DEPRECATION_WARNINGS_ENABLED")&&console.warn(t+" You can disable deprecation warnings with tf.disableDeprecationWarnings().")}function je(){Dt.disposeVariables()}function ze(){return Dt.memory()}function Pe(t){return Dt.profile(t)}function Le(t,e){return Dt.tidy(t,e)}function Fe(t){Ot(t).forEach(function(t){return t.dispose()})}function Be(t){return Dt.keep(t)}function Ue(t){return Dt.time(t)}function Ve(t){return Dt.setBackend(t)}function We(){return Dt.ready()}function qe(){return Dt.backendName}function He(t){Dt.removeBackend(t)}function Ge(t){return Dt.findBackend(t)}function Ke(t){return Dt.findBackendFactory(t)}function Xe(t,e,n){return void 0===n&&(n=1),Dt.registerBackend(t,e,n)}function $e(){return Dt.backend}function Ye(){for(var t=[],e=0;e=2*e+1||i%2==1?o.push(i):a.push(i);r.push.apply(r,a),r.push(0),r.push.apply(r,o)}return r}function Qe(t,e,n,r){void 0===r&&(r=!0);var i=[];r?i.push(t[0]/n):i.push(t[0]*n);for(var a=1;at.rank)throw new Error("index innermost dimension length must be <= tensor rank; saw: "+e.shape[e.rank-1]+" vs. "+t.rank);if(0===t.size)throw new Error("Requested more than 0 entries, but input is empty. Input shape: "+t.shape+".");for(var n=e.shape,r=n[n.length-1],i=1,a=0;a0}),f.registerFlag("WEBGL_VERSION",function(){return Ee(2)?2:Ee(1)?1:0}),f.registerFlag("WEBGL_BUFFER_SUPPORTED",function(){return 2===f.get("WEBGL_VERSION")}),f.registerFlag("WEBGL_CPU_FORWARD",function(){return!1}),f.registerFlag("WEBGL_PACK",function(){return f.getBool("HAS_WEBGL")}),f.registerFlag("WEBGL_PACK_NORMALIZATION",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_CLIP",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_DEPTHWISECONV",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_BINARY_OPERATIONS",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_ARRAY_OPERATIONS",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_IMAGE_OPERATIONS",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_PACK_REDUCE",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_LAZILY_UNPACK",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_CONV_IM2COL",function(){return f.getBool("WEBGL_PACK")}),f.registerFlag("WEBGL_MAX_TEXTURE_SIZE",function(){return xe(f.getNumber("WEBGL_VERSION"))}),f.registerFlag("WEBGL_MAX_TEXTURES_IN_SHADER",function(){return ke(f.getNumber("WEBGL_VERSION"))}),f.registerFlag("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION",function(){var t=f.getNumber("WEBGL_VERSION");return 0===t?0:Se(t)}),f.registerFlag("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE",function(){return f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0&&(t=navigator.userAgent||navigator.vendor||window.opera,!(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4))));var t}),f.registerFlag("WEBGL_RENDER_FLOAT32_ENABLED",function(){return Ce(f.getNumber("WEBGL_VERSION"))}),f.registerFlag("WEBGL_DOWNLOAD_FLOAT_ENABLED",function(){return Ae(f.getNumber("WEBGL_VERSION"))}),f.registerFlag("WEBGL_FENCE_API_ENABLED",function(){return Oe(f.getNumber("WEBGL_VERSION"))}),f.registerFlag("WEBGL_SIZE_UPLOAD_UNIFORM",function(){return f.getBool("WEBGL_RENDER_FLOAT32_ENABLED")?4:0}),mt=De;var hn=30;function dn(t){return t<=hn?t:K(t,Math.floor(Math.sqrt(t)))}function pn(t,e,n){for(var r=e.rank>1?e.shape[e.rank-1]:1,i=n.length,a=1,o=r;o0?a>=l[e]:a<=l[e]);a+=i)n+=1;return n}),[c,d,f]}function vn(t,e,n,r,i){var a=e[i],o=n[i]||1;(t&1<0?Number.MIN_SAFE_INTEGER:Number.MAX_SAFE_INTEGER);var s=r[i];return a<0&&(a+=s),g(0,a,s-1)}function gn(t,e,n,r,i){var a=e[i],o=n[i]||1;(t&1<0?Number.MAX_SAFE_INTEGER:Number.MIN_SAFE_INTEGER);var s=r[i];return a<0&&(a+=s),o>0?g(0,a,s):g(-1,a,s-1)}function bn(t,e,n){for(var r=n.length,i=0;i1){r=i;break}for(i=r+1;i0||n[i]!==t[i])return!1;return!0}function yn(t,e){for(var n=t.length>0?t[t.length-1]:1,r=0;r0,function(){return"Element arr["+r.join("][")+"] should be a primitive, but is an array of "+e.length+" elements"}),w(e.length===n[0],function(){return"Element arr["+r.join("][")+"] should have "+n[0]+" elements, but has "+e.length+" elements"});for(var i=n.slice(1),a=0;a=0&&(i=r),xn(r,i,e,n),null==t||!F(t)&&!Array.isArray(t)&&"number"!=typeof t&&"boolean"!=typeof t&&"string"!=typeof t){var a=null==t?"null":t.constructor.name;throw new Error("Argument '"+e+"' passed to '"+n+"' must be a Tensor or TensorLike, but got '"+a+"'")}var o=wn(t);F(t)||Array.isArray(t)||(t=[t]);var s="string"!==i?$(t,i,f.getBool("DEBUG")):S(t);return vt.make(o,{values:s},i)}function Sn(t,e,n,r){if(void 0===r&&(r="numeric"),!Array.isArray(t))throw new Error("Argument "+e+" passed to "+n+" must be a `Tensor[]` or `TensorLike[]`");return t.map(function(t,r){return kn(t,e+"["+r+"]",n)},r)}function _n(t){return w(G(t),function(){return"The f passed in grad(f) must be a function"}),function(e,n){var r=kn(e,"x","tf.grad",null),i=null!=n?kn(n,"dy","tf.grad"):null;return Dt.tidy(function(){var e=Dt.gradients(function(){return t(r)},[r],i),n=e.value,a=e.grads;return null!=i&&x(n.shape,i.shape,"The shape of dy passed in grad(f)(x, dy) must match the shape returned by f(x)"),Tn(a),a[0]})}}function En(t){return w(G(t),function(){return"The f passed in grads(f) must be a function"}),function(e,n){w(Array.isArray(e),function(){return"The args passed in grads(f)(args) must be an array of `Tensor`s or `TensorLike`s"});var r=Sn(e,"args","tf.grads",null),i=null!=n?kn(n,"dy","tf.grads"):null;return Dt.tidy(function(){var e=Dt.gradients(function(){return t.apply(void 0,r)},r,i),n=e.value,a=e.grads;return null!=i&&x(n.shape,i.shape,"The shape of dy passed in grads(f)([x1,...], dy) must match the shape returned by f([x1,...])"),Tn(a),a})}}function Cn(t){return w(G(t),function(){return"The f passed in valueAndGrad(f) must be a function"}),function(e,n){w(e instanceof vt,function(){return"The x passed in valueAndGrad(f)(x) must be a tensor"}),w(null==n||n instanceof vt,function(){return"The dy passed in valueAndGrad(f)(x, dy) must be a tensor"});var r=Dt.gradients(function(){return t(e)},[e],n),i=r.grads,a=r.value;return Tn(i),{grad:i[0],value:a}}}function An(t){return w(G(t),function(){return"The f passed in valueAndGrads(f) must be a function"}),function(e,n){w(Array.isArray(e)&&e.every(function(t){return t instanceof vt}),function(){return"The args passed in valueAndGrads(f)(args) must be array of tensors"}),w(null==n||n instanceof vt,function(){return"The dy passed in valueAndGrads(f)(args, dy) must be a tensor"});var r=Dt.gradients(function(){return t.apply(void 0,e)},e,n);return null!=n&&x(r.value.shape,n.shape,"The shape of dy passed in valueAndGrads(f)([x1,...], dy) must match the shape returned by f([x1,...])"),Tn(r.grads),r}}function Nn(t,e){if(w(G(t),function(){return"The f passed in variableGrads(f) must be a function"}),w(null==e||Array.isArray(e)&&e.every(function(t){return t instanceof gt}),function(){return"The varList passed in variableGrads(f, varList) must be an array of variables"}),null==e)for(var n in e=[],Dt.registeredVariables)e.push(Dt.registeredVariables[n]);var r=e.length;w((e=e.filter(function(t){return t.trainable})).length>0,function(){return"variableGrads() expects at least one of the input variables to be trainable, but none of the "+r+" variables is trainable."});var i=Dt.gradients(t,e,null,!0),a=i.value,o=i.grads;w(o.some(function(t){return null!=t}),function(){return"Cannot find a connection between any variable and the result of the loss function y=f(x). Please make sure the operations that use variables are inside the function f passed to minimize()."}),w(0===a.rank,function(){return"The f passed in variableGrads(f) must return a scalar, but it returned a rank-"+a.rank+" tensor"});var s={};return e.forEach(function(t,e){null!=o[e]&&(s[t.name]=o[e])}),{value:a,grads:s}}function On(t){return Dt.customGrad(t)}function Tn(t){if(t.filter(function(t){return null==t}).length>0)throw new Error("Cannot compute gradient of y=f(x) with respect to x. Make sure that\n the f you passed encloses all operations that lead from x to y.")}function In(t){var e=Object.keys(t);if(1!==e.length)throw new Error("Please provide an object with a single key (operation name) mapping to a function. Got an object with "+e.length+" keys.");var n=e[0],r=t[n];n.endsWith("_")&&(n=n.substring(0,n.length-1));var i=function(){for(var t=[],e=0;e1)return Gn([0],r);var i=Z(Math.abs(Math.ceil((e-t)/n)),r);ei}).sort(function(t,e){return e.score-t.score}),o=[],s=0;s=0;--h)if(ur(t,l,o[h])>=r){f=!0;break}if(!f&&(o.push(l),o.length>=n))break}return Fn(o,"int32")}function ur(t,e,n){var r=t.subarray(4*e,4*e+4),i=t.subarray(4*n,4*n+4),a=Math.min(r[0],r[2]),o=Math.min(r[1],r[3]),s=Math.max(r[0],r[2]),u=Math.max(r[1],r[3]),c=Math.min(i[0],i[2]),l=Math.min(i[1],i[3]),f=Math.max(i[0],i[2]),h=Math.max(i[1],i[3]),d=(s-a)*(u-o),p=(f-c)*(h-l);if(d<=0||p<=0)return 0;var m=Math.max(a,c),v=Math.max(o,l),g=Math.min(s,f),b=Math.min(u,h),y=Math.max(g-m,0)*Math.max(b-v,0);return y/(d+p-y)}function cr(t,e,n){var r=new Array(t.rank).fill(0),i=t.shape.slice();return e.map(function(e){i[n]=e;var a=t.slice(r,i);return r[n]+=e,a})}function lr(t,e,n,r,i){for(var a=e[e.length-1],o=[t.length/a,a],s=o[0],u=o[1],c=D(n,s*r),l=D("int32",s*r),f=0;f=1,function(){return"Pass at least one tensor to concat"});var n=Sn(t,"tensors","concat");e=M(e,n[0].shape)[0];var r=ln(n.map(function(t){return t.shape}),e);if(0===_(r))return Pn([],r);if(1===(n=n.filter(function(t){return t.size>0})).length)return n[0];var i=n.map(function(t){return t.shape});!function(t,e){var n=t[0].length;t.forEach(function(t,e){w(t.length===n,function(){return"Error in concat"+n+"D: rank of tensors["+e+"] must be the same as the rank of the rest ("+n+")"})}),w(e>=0&&e>>0,e=(r*=e)>>>0,e+=4294967296*(r-=e)}return 2.3283064365386963e-10*(e>>>0)});n.next=function(){var t=2091639*n.s0+2.3283064365386963e-10*n.c;return n.s0=n.s1,n.s1=n.s2,n.s2=t-(n.c=0|t)},n.c=1,n.s0=r(" "),n.s1=r(" "),n.s2=r(" "),n.s0-=r(t),n.s0<0&&(n.s0+=1),n.s1-=r(t),n.s1<0&&(n.s1+=1),n.s2-=r(t),n.s2<0&&(n.s2+=1),r=null}(t),i=e&&e.state,a=n.next;return a.int32=function(){return 4294967296*n.next()|0},a.double=function(){return a()+1.1102230246251565e-16*(2097152*a()|0)},a.quick=a,i&&("object"==typeof i&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.alea=i}(0,t)}),yr=gr(function(t){!function(t,e,n){function r(t,e){return e.x=t.x,e.y=t.y,e.z=t.z,e.w=t.w,e}function i(t,e){var n=new function(t){var e=this,n="";e.x=0,e.y=0,e.z=0,e.w=0,e.next=function(){var t=e.x^e.x<<11;return e.x=e.y,e.y=e.z,e.z=e.w,e.w^=e.w>>>19^t^t>>>8},t===(0|t)?e.x=t:n+=t;for(var r=0;r>>0)/4294967296};return a.double=function(){do{var t=((n.next()>>>11)+(n.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},a.int32=n.next,a.quick=a,i&&("object"==typeof i&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.xor128=i}(0,t)}),wr=gr(function(t){!function(t,e,n){function r(t,e){return e.x=t.x,e.y=t.y,e.z=t.z,e.w=t.w,e.v=t.v,e.d=t.d,e}function i(t,e){var n=new function(t){var e=this,n="";e.next=function(){var t=e.x^e.x>>>2;return e.x=e.y,e.y=e.z,e.z=e.w,e.w=e.v,(e.d=e.d+362437|0)+(e.v=e.v^e.v<<4^t^t<<1)|0},e.x=0,e.y=0,e.z=0,e.w=0,e.v=0,t===(0|t)?e.x=t:n+=t;for(var r=0;r>>4),e.next()}(t),i=e&&e.state,a=function(){return(n.next()>>>0)/4294967296};return a.double=function(){do{var t=((n.next()>>>11)+(n.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},a.int32=n.next,a.quick=a,i&&("object"==typeof i&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.xorwow=i}(0,t)}),xr=gr(function(t){!function(t,e,n){function r(t,e){return e.x=t.x.slice(),e.i=t.i,e}function i(t,e){null==t&&(t=+new Date);var n=new function(t){var e=this;e.next=function(){var t,n,r=e.x,i=e.i;return t=r[i],n=(t^=t>>>7)^t<<24,n^=(t=r[i+1&7])^t>>>10,n^=(t=r[i+3&7])^t>>>3,n^=(t=r[i+4&7])^t<<7,t=r[i+7&7],n^=(t^=t<<13)^t<<9,r[i]=n,e.i=i+1&7,n},function(t,e){var n,r=[];if(e===(0|e))r[0]=e;else for(e=""+e,n=0;n0;--n)t.next()}(e,t)}(t),i=e&&e.state,a=function(){return(n.next()>>>0)/4294967296};return a.double=function(){do{var t=((n.next()>>>11)+(n.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},a.int32=n.next,a.quick=a,i&&(i.x&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.xorshift7=i}(0,t)}),kr=gr(function(t){!function(t,e,n){function r(t,e){return e.i=t.i,e.w=t.w,e.X=t.X.slice(),e}function i(t,e){null==t&&(t=+new Date);var n=new function(t){var e=this;e.next=function(){var t,n,r=e.w,i=e.X,a=e.i;return e.w=r=r+1640531527|0,n=i[a+34&127],t=i[a=a+1&127],n^=n<<13,t^=t<<17,n^=n>>>15,t^=t>>>12,n=i[a]=n^t,e.i=a,n+(r^r>>>16)|0},function(t,e){var n,r,i,a,o,s=[],u=128;for(e===(0|e)?(r=e,e=null):(e+="\0",r=0,u=Math.max(u,e.length)),i=0,a=-32;a>>15,r^=r<<4,r^=r>>>13,a>=0&&(o=o+1640531527|0,i=0==(n=s[127&a]^=r+o)?i+1:0);for(i>=128&&(s[127&(e&&e.length||0)]=-1),i=127,a=512;a>0;--a)r=s[i+34&127],n=s[i=i+1&127],r^=r<<13,n^=n<<17,r^=r>>>15,n^=n>>>12,s[i]=r^n;t.w=o,t.X=s,t.i=i}(e,t)}(t),i=e&&e.state,a=function(){return(n.next()>>>0)/4294967296};return a.double=function(){do{var t=((n.next()>>>11)+(n.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},a.int32=n.next,a.quick=a,i&&(i.X&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.xor4096=i}(0,t)}),Sr=gr(function(t){!function(t,e,n){function r(t,e){return e.a=t.a,e.b=t.b,e.c=t.c,e.d=t.d,e}function i(t,e){var n=new function(t){var e=this,n="";e.next=function(){var t=e.b,n=e.c,r=e.d,i=e.a;return t=t<<25^t>>>7^n,n=n-r|0,r=r<<24^r>>>8^i,i=i-t|0,e.b=t=t<<20^t>>>12^n,e.c=n=n-r|0,e.d=r<<16^n>>>16^i,e.a=i-t|0},e.a=0,e.b=0,e.c=-1640531527,e.d=1367130551,t===Math.floor(t)?(e.a=t/4294967296|0,e.b=0|t):n+=t;for(var r=0;r>>0)/4294967296};return a.double=function(){do{var t=((n.next()>>>11)+(n.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},a.int32=n.next,a.quick=a,i&&("object"==typeof i&&r(i,n),a.state=function(){return r(n,{})}),a}e&&e.exports?e.exports=i:this.tychei=i}(0,t)}),_r=gr(function(t){!function(e,r){var i,a=this,o=256,s=6,u="random",c=r.pow(o,s),l=r.pow(2,52),f=2*l,h=o-1;function d(t,n,h){var d=[],b=v(function t(e,n){var r,i=[],a=typeof e;if(n&&"object"==a)for(r in e)try{i.push(t(e[r],n-1))}catch(t){}return i.length?i:"string"==a?e:e+"\0"}((n=1==n?{entropy:!0}:n||{}).entropy?[t,g(e)]:null==t?function(){try{var t;return i&&(t=i.randomBytes)?t=t(o):(t=new Uint8Array(o),(a.crypto||a.msCrypto).getRandomValues(t)),g(t)}catch(t){var n=a.navigator,r=n&&n.plugins;return[+new Date,a,r,a.screen,g(e)]}}():t,3),d),y=new p(d),w=function(){for(var t=y.g(s),e=c,n=0;t=f;)t/=2,e/=2,n>>>=1;return(t+n)/e};return w.int32=function(){return 0|y.g(4)},w.quick=function(){return y.g(4)/4294967296},w.double=w,v(g(y.S),e),(n.pass||h||function(t,e,n,i){return i&&(i.S&&m(i,y),t.state=function(){return m(y,{})}),n?(r[u]=t,e):t})(w,b,"global"in n?n.global:this==r,n.state)}function p(t){var e,n=t.length,r=this,i=0,a=r.i=r.j=0,s=r.S=[];for(n||(t=[n++]);i=1||0===o);var s=Math.sqrt(-2*Math.log(o)/o);e=this.mean+this.stdDev*i*s,n=this.mean+this.stdDev*a*s,this.truncated&&!this.isValidTruncated(e)||(r=!0)}return this.truncated&&!this.isValidTruncated(n)||(this.nextVal=this.convertValue(n)),this.convertValue(e)},t.prototype.convertValue=function(t){return null==this.dtype||"float32"===this.dtype?t:Math.round(t)},t.prototype.isValidTruncated=function(t){return t<=this.upper&&t>=this.lower},t}(),Ar=function(){function t(t,e,n,r){void 0===t&&(t=0),void 0===e&&(e=1),void 0===r&&(r=Math.random());var i=this;if(this.canReturnFloat=function(){return null==i.dtype||"float32"===i.dtype},this.min=t,this.range=e-t,this.dtype=n,!this.canReturnFloat()&&this.range<=1)throw new Error("The difference between "+t+" - "+e+" <= 1 and dtype is not float");this.random=Er(r.toString())}return t.prototype.convertValue=function(t){return this.canReturnFloat()?t:Math.round(t)},t.prototype.nextValue=function(){return this.convertValue(this.min+this.range*this.random())},t}();function Nr(t,e,n){return void 0===e&&(e="float32"),e=e||"float32",tt(t),new ht(t,e,n)}function Or(t,e){void 0===e&&(e=!1),console.log(t.toString(e))}var Tr=In({batchToSpaceND_:function(t,e,n){var r=kn(t,"x","batchToSpaceND"),i=e.reduce(function(t,e){return t*e});return w(r.rank>=1+e.length,function(){return"input rank is "+r.rank+" but should be > than blockShape.length "+e.length}),w(n.length===e.length,function(){return"crops.length is "+n.length+" but should be equal to blockShape.length "+e.length}),w(r.shape[0]%i==0,function(){return"input tensor batch is "+r.shape[0]+" but is not divisible by the product of the elements of blockShape "+e.join(" * ")+" === "+i}),Dt.runKernel(function(t){return t.batchToSpaceND(r,e,n)},{$x:r},function(t){return{$x:function(){return t.spaceToBatchND(e,n)}}})}}),Ir=In({cast_:function(t,e){var n=kn(t,"x","cast");return Dt.runKernel(function(t){return t.cast(n,e)},{$x:n},function(t){return{$x:function(){return t.clone()}}})}}),Mr=In({clone_:function(t){var e=kn(t,"x","clone",null);return Dt.runKernel(function(t){return vt.make(e.shape,{dataId:e.dataId},e.dtype)},{$x:e},function(t){return{$x:function(){return t.toFloat()}}})}}),Rr=In({cumsum_:function(t,e,n,r){void 0===e&&(e=0),void 0===n&&(n=!1),void 0===r&&(r=!1);var i=kn(t,"x","cumsum"),a=sn([e|=0],i.rank),o=i;null!=a&&(o=i.transpose(a));var s=cn(1,i.rank)[0],u=Dt.runKernel(function(t){return t.cumsum(o,s,n,r)},{permutedX:o},function(t){return{permutedX:function(){return t.cumsum(e,n,!r)}}});return null!=a&&(u=u.transpose(a)),u}}),Dr=In({depthToSpace_:function(t,e,n){void 0===n&&(n="NHWC");var r=kn(t,"x","depthToSpace"),i="NHWC"===n?r.shape[1]:r.shape[2],a="NHWC"===n?r.shape[2]:r.shape[3],o="NHWC"===n?r.shape[3]:r.shape[1];return w(i*e>=0,function(){return"Negative dimension size caused by overflow when multiplying\n "+i+" and "+e+" for depthToSpace with input shape\n "+r.shape}),w(a*e>=0,function(){return"Negative dimension size caused by overflow when multiplying\n "+a+" and "+e+" for depthToSpace with input shape\n "+r.shape}),w(o%(e*e)==0,function(){return"Dimension size must be evenly divisible by "+e*e+" but is "+o+" for depthToSpace with input shape "+r.shape}),Dt.runKernel(function(t){return t.depthToSpace(r,e,n)},{$x:r})}}),jr=In({expandDims_:function(t,e){void 0===e&&(e=0);var n=kn(t,"x","expandDims");w(e<=n.rank,function(){return"Axis must be <= rank of the tensor"});var r=n.shape.slice();return e<0&&(w(-(n.rank+1)<=e,function(){return"Axis must be in the interval ["+-(n.rank+1)+", "+n.rank+"]"}),e=n.rank+e+1),r.splice(e,0,1),Kr(n,r)}}),zr=In({eye_:function(t,e,n,r){void 0===r&&(r="float32"),null==e&&(e=t);for(var i=Nr([t,e],r),a=t<=e?t:e,o=0;o2)throw new Error("Rank of probabilities must be 1 or 2, but is "+o);n=n||Math.random();var s=1===o?i.as2D(1,-1):i,u=Dt.runKernel(function(t){return t.multinomial(s,r,e,n)},{logits2D:s});return 1===o?u.as1D():u}}),Lr=In({oneHot_:function(t,e,n,r){if(void 0===n&&(n=1),void 0===r&&(r=0),e<2)throw new Error("Error in oneHot: depth must be >=2, but it is "+e);var i=kn(t,"indices","oneHot","int32"),a=i.shape.concat([e]);return i=i.flatten(),Dt.runKernel(function(t){return t.oneHot(i,e,n,r)},{$indices:i},function(t){return{$indices:function(){return Gn(i.shape,"float32")}}}).reshape(a)}}),Fr=In({pad_:function(t,e,n){void 0===n&&(n=0);var r=kn(t,"x","pad");if(0===r.rank)throw new Error("pad(scalar) is not defined. Pass non-scalar to pad");var i=e.map(function(t){return t[0]});return Dt.runKernel(function(t){return t.pad(r,e,n)},{$x:r},function(t){return{$x:function(){return t.slice(i,r.shape)}}})}}),Br=In({pad1d_:function(t,e,n){return void 0===n&&(n=0),w(2===e.length,function(){return"Invalid number of paddings. Must be length of 2."}),Fr(t,[e],n)}}),Ur=In({pad2d_:function(t,e,n){return void 0===n&&(n=0),w(2===e.length&&2===e[0].length&&2===e[1].length,function(){return"Invalid number of paddings. Must be length of 2 each."}),Fr(t,e,n)}}),Vr=In({pad3d_:function(t,e,n){return void 0===n&&(n=0),w(3===e.length&&2===e[0].length&&2===e[1].length&&2===e[2].length,function(){return"Invalid number of paddings. Must be length of 2 each."}),Fr(t,e,n)}}),Wr=In({pad4d_:function(t,e,n){return void 0===n&&(n=0),w(4===e.length&&2===e[0].length&&2===e[1].length&&2===e[2].length&&2===e[3].length,function(){return"Invalid number of paddings. Must be length of 2 each."}),Fr(t,e,n)}}),qr=In({rand_:function(t,e,n){var r=_(t),i=null;if(null==n||"float32"===n)i=new Float32Array(r);else if("int32"===n)i=new Int32Array(r);else{if("bool"!==n)throw new Error("Unknown data type "+n);i=new Uint8Array(r)}for(var a=0;a=1+e.length,function(){return"input rank "+r.rank+" should be > than [blockShape] "+e.length}),w(n.length===e.length,function(){return"paddings.shape[0] "+n.length+" must be equal to [blockShape] "+e.length}),w(r.shape.reduce(function(t,r,i){return i>0&&i<=e.length?t&&(r+n[i-1][0]+n[i-1][1])%e[i-1]==0:t},!0),function(){return"input spatial dimensions "+r.shape.slice(1)+" with paddings "+n.toString()+" must be divisible by blockShapes "+e.toString()}),Dt.runKernel(function(t){return t.spaceToBatchND(r,e,n)},{$x:r},function(t){return{$x:function(){return t.batchToSpaceND(e,n)}}})}}),$r=In({squeeze_:function(t,e){var n=kn(t,"x","squeeze");return Kr(n,R(n.shape,e).newShape)}}),Yr=In({stack_:function(t,e){void 0===e&&(e=0);var n=Sn(t,"tensors","stack");if(w(n.length>=1,function(){return"Pass at least one tensor to tf.stack"}),1===n.length)return n[0].expandDims(e);var r=n[0].rank,i=n[0].shape,a=n[0].dtype;w(e<=r,function(){return"Axis must be <= rank of the tensor"}),n.forEach(function(t){x(i,t.shape,"All tensors passed to stack must have matching shapes")}),n.forEach(function(t){w(a===t.dtype,function(){return"All tensors passed to stack must have matching dtypes"})});var o=n.map(function(t){return t.expandDims(e)});return fr(o,e)}}),Jr=In({tile_:function(t,e){var n=kn(t,"x","tile");return w(n.rank===e.length,function(){return"Error in transpose: rank of input "+n.rank+" must match length of reps "+e+"."}),Dt.runKernel(function(t,r){var i=t.tile(n,e);return r([n]),i},{$x:n},function(t,n){var r=n[0];return{$x:function(){var n=Jn(r);if(1===r.rank)for(var i=0;i=-n.shape.length&&e1&&1===o&&r.unshift(a)}return r}function ai(t,e){for(var n=[],r=0;r1)&&n.unshift(a)}return n}function oi(t,e){for(var n=[],r=Math.max(t.length,e.length),i=0;i= "+this.outputShape[0]+" ? 0. : result.y;\n result.z = 0.;\n result.w = 0.;\n ";else{var o=ri("coords",i);a+="\n bool nextRowOutOfBounds =\n ("+o[i-2]+" + 1) >= "+this.outputShape[i-2]+";\n bool nextColOutOfBounds =\n ("+o[i-1]+" + 1) >= "+this.outputShape[i-1]+";\n result.y = nextColOutOfBounds ? 0. : result.y;\n result.z = nextRowOutOfBounds ? 0. : result.z;\n result.w = nextColOutOfBounds || nextRowOutOfBounds ? 0. : result.w;\n "}this.userCode="\n vec4 binaryOperation(vec4 a, vec4 b) {\n "+t+"\n }\n\n void main() {\n vec4 a = getAAtOutCoords();\n vec4 b = getBAtOutCoords();\n\n vec4 result = binaryOperation(a, b);\n "+a+"\n\n setOutput(result);\n }\n "},Ei=function(){function t(t){this.variableNames=["A"],this.outputShape=t,this.userCode="\n uniform float min;\n uniform float max;\n\n void main() {\n float value = getAAtOutCoords();\n if (isnan(value)) {\n setOutput(value);\n return;\n }\n\n setOutput(clamp(value, min, max));\n }\n "}return t.prototype.getCustomSetupFunc=function(t,e){var n=this;return function(r,i){null==n.minLoc&&(n.minLoc=r.getUniformLocationNoThrow(i,"min"),n.maxLoc=r.getUniformLocationNoThrow(i,"max")),r.gl.uniform1f(n.minLoc,t),r.gl.uniform1f(n.maxLoc,e)}},t}(),Ci=function(){function t(t){this.variableNames=["A"],this.usesPackedTextures=!0,this.outputShape=t,this.userCode="\n uniform float min;\n uniform float max;\n\n void main() {\n vec4 value = getAAtOutCoords();\n\n if (any(isnan(value))) {\n setOutput(value);\n return;\n }\n\n setOutput(clamp(value, vec4(min), vec4(max)));\n }\n "}return t.prototype.getCustomSetupFunc=function(t,e){var n=this;return function(r,i){null==n.minLoc&&(n.minLoc=r.getUniformLocationNoThrow(i,"min"),n.maxLoc=r.getUniformLocationNoThrow(i,"max")),r.gl.uniform1f(n.minLoc,t),r.gl.uniform1f(n.maxLoc,e)}},t}();function Ai(t,e){if(1===t)return""+e;if(2===t)return e+".y";if(3===t)return e+".z";if(4===t)return e+".w";throw Error("Cumulative sum for rank "+t+" is not yet supported")}var Ni,Oi,Ti=function(){function t(t,e,n){this.variableNames=["x"],this.outputShape=[],this.outputShape=t,this.blockSize=e,this.dataFormat=n,this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int h = "+this.getHeightCoordString()+";\n int w = "+this.getWidthCoordString()+";\n int d = "+this.getDepthCoordString()+";\n\n int in_h = h / "+e+";\n int offset_h = imod(h, "+e+");\n int in_w = w / "+e+";\n int offset_w = imod(w, "+e+");\n int offset_d = (offset_h * "+e+" + offset_w) *\n "+this.getOutputDepthSize()+";\n int in_d = d + offset_d;\n\n float result = "+this.getInputSamplingString()+";\n setOutput(result);\n }\n "}return t.prototype.getHeightCoordString=function(){return"NHWC"===this.dataFormat?"coords[1]":"coords[2]"},t.prototype.getWidthCoordString=function(){return"NHWC"===this.dataFormat?"coords[2]":"coords[3]"},t.prototype.getDepthCoordString=function(){return"NHWC"===this.dataFormat?"coords[3]":"coords[1]"},t.prototype.getOutputDepthSize=function(){return"NHWC"===this.dataFormat?this.outputShape[3]:this.outputShape[1]},t.prototype.getInputSamplingString=function(){return"NHWC"===this.dataFormat?"getX(b, in_h, in_w, in_d)":"getX(b, in_d, in_h, in_w)"},t}(),Ii=function(t,e,n){this.variableNames=["real","imag"];var r=e[1];this.outputShape=e;var i=n?"2.0 * "+Math.PI:"-2.0 * "+Math.PI,a=n?r+".0":"1.0";this.userCode="\n const float exponentMultiplier = "+i+";\n\n float unaryOpComplex(float real, float expR, float imag, float expI) {\n "+t+"\n }\n\n float mulMatDFT(int batch, int index) {\n float indexRatio = float(index) / float("+r+");\n float exponentMultiplierTimesIndexRatio =\n exponentMultiplier * indexRatio;\n\n float result = 0.0;\n\n for (int i = 0; i < "+r+"; i++) {\n // x = (-2|2 * PI / N) * index * i;\n float x = exponentMultiplierTimesIndexRatio * float(i);\n float expR = cos(x);\n float expI = sin(x);\n float real = getReal(batch, i);\n float imag = getImag(batch, i);\n\n result +=\n unaryOpComplex(real, expR, imag, expI) / "+a+";\n }\n\n return result;\n }\n\n void main() {\n ivec2 coords = getOutputCoords();\n setOutput(mulMatDFT(coords[0], coords[1]));\n }\n "},Mi=function(){function t(t,e){this.outputShape=[],this.variableNames=["x"],this.outputShape=t,this.userCode="\n uniform float value;\n void main() {\n // Input can be obtained from uniform value.\n setOutput(value);\n }\n "}return t.prototype.getCustomSetupFunc=function(t){var e=this;return function(n,r){null==e.valueLoc&&(e.valueLoc=n.getUniformLocationNoThrow(r,"value")),n.gl.uniform1f(e.valueLoc,t)}},t}();function Ri(t,e){return[e,t]}function Di(t,e){return t*e}function ji(t,e,n){var r=function(t,e){if(t%e!=0)throw new Error("unpackedSize ("+t+") must be a multiple of "+e);return t/e}(t.length,n);if(e.length= "+r);for(var i=0,a=0;a= "+a);for(var o=r%2==1,s=n%2==1,u=Math.floor(r/2),c=Math.floor(n/2),l=Math.ceil(r/2),f=l*Math.ceil(n/2),h=b(n)*b(r),d=0;d= "+r);for(var i=0,a=0;a0?(e=this.beginQuery(),this.endQuery(),n=function(){return r.isQueryAvailable(e,f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION"))}):n=function(){return!0};return{query:e,isFencePassed:n}},t.prototype.downloadMatrixFromPackedTexture=function(t,e,n,r,i,a){var o=this;return this.downloadMatrixDriver(t,function(){return aa(o.gl,o.debug,e,n,r,i,a,o.textureConfig)})},t.prototype.createProgram=function(t){this.throwIfDisposed();var e=this.gl,n=Gt(e,this.debug,t),r=Fi(e,this.debug),i=Yt(e,this.debug);return Ft(e,this.debug,function(){return e.attachShader(i,r)}),Ft(e,this.debug,function(){return e.attachShader(i,n)}),Jt(e,this.debug,i),this.debug&&Zt(e,this.debug,i),this.vertexAttrsAreBound||(this.setProgram(i),this.vertexAttrsAreBound=$i(e,this.debug,this.program,this.vertexBuffer)),i},t.prototype.deleteProgram=function(t){var e=this;this.throwIfDisposed(),t===this.program&&(this.program=null),null!=t&&Ft(this.gl,this.debug,function(){return e.gl.deleteProgram(t)})},t.prototype.setProgram=function(t){var e=this;this.throwIfDisposed(),this.program=t,null!=this.program&&this.debug&&Zt(this.gl,this.debug,this.program),Ft(this.gl,this.debug,function(){return e.gl.useProgram(t)})},t.prototype.getUniformLocation=function(t,e,n){return void 0===n&&(n=!0),this.throwIfDisposed(),n?se(this.gl,this.debug,t,e):ue(this.gl,t,e)},t.prototype.getAttributeLocation=function(t,e){var n=this;return this.throwIfDisposed(),Ft(this.gl,this.debug,function(){return n.gl.getAttribLocation(t,e)})},t.prototype.getUniformLocationNoThrow=function(t,e){return this.throwIfDisposed(),this.gl.getUniformLocation(t,e)},t.prototype.setInputMatrixTexture=function(t,e,n){this.throwIfDisposed(),this.throwIfNoProgram(),ce(this.gl,this.debug,this.program,t,e,n)},t.prototype.setOutputMatrixTexture=function(t,e,n){this.setOutputMatrixTextureDriver(t,n,e)},t.prototype.setOutputPackedMatrixTexture=function(t,e,n){this.throwIfDisposed();var r=zi(e,n),i=r[0],a=r[1];this.setOutputMatrixTextureDriver(t,i,a)},t.prototype.setOutputMatrixWriteRegion=function(t,e,n,r){this.setOutputMatrixWriteRegionDriver(n,t,r,e)},t.prototype.setOutputPackedMatrixWriteRegion=function(t,e,n,r){throw new Error("setOutputPackedMatrixWriteRegion not implemented.")},t.prototype.debugValidate=function(){null!=this.program&&Zt(this.gl,this.debug,this.program),he(this.gl)},t.prototype.executeProgram=function(){this.throwIfDisposed(),this.throwIfNoProgram();var t=this.gl;this.debug&&this.debugValidate(),Ft(t,this.debug,function(){return t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0)})},t.prototype.blockUntilAllProgramsCompleted=function(){var t=this;this.throwIfDisposed(),Ft(this.gl,this.debug,function(){return t.gl.finish()})},t.prototype.getQueryTimerExtension=function(){return null==this.disjointQueryTimerExtension&&(this.disjointQueryTimerExtension=qt(this.gl,this.debug,2===f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")?"EXT_disjoint_timer_query_webgl2":"EXT_disjoint_timer_query")),this.disjointQueryTimerExtension},t.prototype.getQueryTimerExtensionWebGL2=function(){return this.getQueryTimerExtension()},t.prototype.getQueryTimerExtensionWebGL1=function(){return this.getQueryTimerExtension()},t.prototype.beginQuery=function(){if(2===f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")){var t=this.gl,e=this.getQueryTimerExtensionWebGL2(),n=t.createQuery();return t.beginQuery(e.TIME_ELAPSED_EXT,n),n}var r=this.getQueryTimerExtensionWebGL1(),i=r.createQueryEXT();return r.beginQueryEXT(r.TIME_ELAPSED_EXT,i),i},t.prototype.endQuery=function(){if(2!==f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")){var t=this.getQueryTimerExtensionWebGL1();t.endQueryEXT(t.TIME_ELAPSED_EXT)}else{var e=this.gl,n=this.getQueryTimerExtensionWebGL2();e.endQuery(n.TIME_ELAPSED_EXT)}},t.prototype.waitForQueryAndGetTime=function(t){return c(this,void 0,void 0,function(){var e=this;return l(this,function(n){switch(n.label){case 0:return[4,T(function(){return e.disposed||e.isQueryAvailable(t,f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION"))})];case 1:return n.sent(),[2,this.getQueryTime(t,f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION"))]}})})},t.prototype.getQueryTime=function(t,e){if(0===e)return null;if(2===e){var n=this.gl;return n.getQueryParameter(t,n.QUERY_RESULT)/1e6}var r=this.getQueryTimerExtensionWebGL1();return r.getQueryObjectEXT(t,r.QUERY_RESULT_EXT)/1e6},t.prototype.isQueryAvailable=function(t,e){if(0===e)return!0;if(2===e){var n=this.gl,r=this.getQueryTimerExtensionWebGL2(),i=n.getQueryParameter(t,n.QUERY_RESULT_AVAILABLE);return null==this.disjoint&&(this.disjoint=this.gl.getParameter(r.GPU_DISJOINT_EXT)),i&&!this.disjoint}return i=(r=this.getQueryTimerExtensionWebGL1()).getQueryObjectEXT(t,r.QUERY_RESULT_AVAILABLE_EXT),null==this.disjoint&&(this.disjoint=this.gl.getParameter(r.GPU_DISJOINT_EXT)),i&&!this.disjoint},t.prototype.pollFence=function(t){var e=this;return new Promise(function(n){e.addItemToPoll(function(){return t.isFencePassed()},function(){return n()})})},t.prototype.pollItems=function(){for(var t=function(t){for(var e=0;e1||T(function(){return n.pollItems(),0===n.itemsToPoll.length})},t.prototype.bindTextureToFrameBuffer=function(t){this.throwIfDisposed(),le(this.gl,this.debug,t,this.framebuffer),this.debug&&he(this.gl)},t.prototype.unbindTextureToFrameBuffer=function(){null!=this.outputTexture?(le(this.gl,this.debug,this.outputTexture,this.framebuffer),this.debug&&he(this.gl)):fe(this.gl,this.debug,this.framebuffer)},t.prototype.downloadMatrixDriver=function(t,e){this.bindTextureToFrameBuffer(t);var n=e();return this.unbindTextureToFrameBuffer(),n},t.prototype.setOutputMatrixTextureDriver=function(t,e,n){this.throwIfDisposed();var r=this.gl;le(r,this.debug,t,this.framebuffer),this.debug&&he(r),this.outputTexture=t,Ft(r,this.debug,function(){return r.viewport(0,0,e,n)}),Ft(r,this.debug,function(){return r.scissor(0,0,e,n)})},t.prototype.setOutputMatrixWriteRegionDriver=function(t,e,n,r){var i=this;this.throwIfDisposed(),Ft(this.gl,this.debug,function(){return i.gl.scissor(t,e,n,r)})},t.prototype.throwIfDisposed=function(){if(this.disposed)throw new Error("Attempted to use disposed GPGPUContext.")},t.prototype.throwIfNoProgram=function(){if(null==this.program)throw new Error("No GPU program is currently set.")},t}();function ua(t,e){if(t.length!==e.length)throw Error("Binary was compiled with "+t.length+" inputs, but was executed with "+e.length+" inputs");t.forEach(function(t,n){var r=t.logicalShape,i=e[n],a=i.shape;if(!E(r,a))throw Error("Binary was compiled with different shapes than the current args. Shapes "+r+" and "+a+" must match");if(!t.isUniform||!i.isUniform){var o=t.texShape,s=i.isUniform?null:i.texData.texShape;if(!E(o,s))throw Error("Binary was compiled with different texture shapes than the current args. Shape "+o+" and "+s+" must match")}})}var ca=function(t,e,n,r,i,a){void 0===n&&(n=!1),void 0===r&&(r=!1),void 0===i&&(i=!1),void 0===a&&(a=null),this.variableNames=["matrixA","matrixB"],this.usesPackedTextures=!0,this.outputShape=e;var o=n?t[1]:t[2],s=Math.ceil(o/2),u=n?"i * 2, rc.y":"rc.y, i * 2",c=r?"rc.z, i * 2":"i * 2, rc.z",l=n?["a.xxyy","a.zzww"]:["a.xxzz","a.yyww"],f=r?["b.xzxz","b.ywyw"]:["b.xyxy","b.zwzw"],h="",d="";a&&(h="vec4 activation(vec4 x) {\n "+a+"\n }",d="result = activation(result);");var p=i?"result += getBiasAtOutCoords();":"";i&&this.variableNames.push("bias"),this.userCode="\n "+h+"\n\n const float sharedDimension = "+s+".0;\n\n vec4 dot2x2ARowBCol(ivec3 rc) {\n vec4 result = vec4(0);\n for (int i = 0; i < "+s+"; i++) {\n vec4 a = getMatrixA(rc.x, "+u+");\n vec4 b = getMatrixB(rc.x, "+c+");\n\n result += ("+l[0]+" * "+f[0]+") + ("+l[1]+" * "+f[1]+");\n }\n return result;\n }\n\n void main() {\n ivec3 rc = getOutputCoords();\n vec4 result = dot2x2ARowBCol(rc);\n\n "+p+"\n\n "+d+"\n\n setOutput(result);\n }\n "},la=function(){function t(t,e,n){this.variableNames=["probs"],this.outputShape=[t,n],this.userCode="\n uniform float seed;\n\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n\n float r = random(seed);\n float cdf = 0.0;\n\n for (int i = 0; i < "+(e-1)+"; i++) {\n cdf += getProbs(batch, i);\n\n if (r < cdf) {\n setOutput(float(i));\n return;\n }\n }\n\n // If no other event happened, last event happened.\n setOutput(float("+(e-1)+"));\n }\n "}return t.prototype.getCustomSetupFunc=function(t){var e=this;return function(n,r){null==e.seedLoc&&(e.seedLoc=n.getUniformLocation(r,"seed")),n.gl.uniform1f(e.seedLoc,t)}},t}(),fa=function(t,e,n){if(this.variableNames=["x"],"avg"===e&&n)throw new Error("Cannot compute positions for average pool.");var r=t.filterWidth,i=t.strideHeight,a=t.strideWidth,o=t.dilationHeight,s=t.dilationWidth,u=t.effectiveFilterHeight,c=t.effectiveFilterWidth,l=t.padInfo.top,f=t.padInfo.left;this.outputShape=t.outShape;var h="avg"===e,d="0.0";if(h||(d="-1.0 / 1e-20"),n)this.userCode="\n const ivec2 strides = ivec2("+i+", "+a+");\n const ivec2 pads = ivec2("+l+", "+f+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // max/min x(?, ?, d) to get y(yR, yC, d).\n // ? = to be determined\n float minMaxValue = 0.0;\n float minMaxValueFound = 0.0;\n int minMaxPosition = 0;\n float avgValue = 0.0;\n\n for (int wR = 0; wR < "+u+";\n wR += "+o+") {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int wC = 0; wC < "+c+";\n wC += "+s+") {\n int xC = xCCorner + wC;\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n float value = getX(batch, xR, xC, d);\n\n // If a min / max value has already been found, use it. If not,\n // use the current value.\n float currMinMaxValue = mix(\n value, minMaxValue, minMaxValueFound);\n if (value >= currMinMaxValue) {\n minMaxValue = value;\n minMaxValueFound = 1.0;\n minMaxPosition = wR * "+c+" + wC;\n }\n }\n }\n setOutput(float(minMaxPosition));\n }\n ";else{var p=e+"("+e+"("+e+"(minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])";"avg"===e&&(p="avgValue / count");var m=4*Math.floor(r/4),v=r%4,g="\n if ("+h+") {\n avgValue += dot(values, ones);\n } else {\n minMaxValue = max(values, minMaxValue);\n }\n ";this.userCode="\n const ivec2 strides = ivec2("+i+", "+a+");\n const ivec2 pads = ivec2("+l+", "+f+");\n const float initializationValue = "+d+";\n const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n float count = 0.0;\n\n float getValue(int batch, int xR, int xC, int d) {\n if (xC < 0 || xC >= "+t.inWidth+") {\n return initializationValue;\n }\n count += 1.0;\n return getX(batch, xR, xC, d);\n }\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // max/min x(?, ?, d) to get y(yR, yC, d).\n // ? = to be determined\n vec4 minMaxValue = vec4("+d+");\n float avgValue = 0.0;\n count = 0.0;\n\n for (int wR = 0; wR < "+u+";\n wR += "+o+") {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int wC = 0; wC < "+m+"; wC += 4) {\n int xC = xCCorner + wC * "+s+";\n\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + "+s+", d),\n getValue(batch, xR, xC + 2 * "+s+", d),\n getValue(batch, xR, xC + 3 * "+s+", d)\n );\n\n "+g+"\n }\n\n int xC = xCCorner + "+m+";\n if ("+(1===v)+") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n initializationValue,\n initializationValue,\n initializationValue\n );\n\n "+g+"\n } else if ("+(2===v)+") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + "+s+", d),\n initializationValue,\n initializationValue\n );\n\n "+g+"\n } else if ("+(3===v)+") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + "+s+", d),\n getValue(batch, xR, xC + 2 * "+s+", d),\n initializationValue\n );\n\n "+g+"\n }\n }\n setOutput("+p+");\n }\n "}},ha=function(t,e,n,r,i,a,o){void 0===o&&(o=!0),this.variableNames=["updates","indices","defaultValue"],this.outputShape=a;var s=vi(i.length),u=vi(a.length),c="";1===n?c="i":2===n&&(c="i, j");var l="getIndices("+c+")",f="";1===r?f="i":2===r&&(f="i, coords[1]");var h="getUpdates("+f+")",d=e>1?"strides[j]":"strides";this.userCode="\n "+s+" strides = "+s+"("+i+");\n\n void main() {\n "+u+" coords = getOutputCoords();\n float sum = 0.0;\n bool found = false;\n for (int i = 0; i < "+t+"; i++) {\n int flattenedIndex = 0;\n for (int j = 0; j < "+e+"; j++) {\n int index = round("+l+");\n flattenedIndex += index * "+d+";\n }\n if (flattenedIndex == coords[0]) {\n sum += "+h+";\n found = true;\n }\n }\n setOutput(mix(getDefaultValue(), sum, float(found)));\n }\n "},da=function(){function t(t){this.variableNames=["source"],this.outputShape=t,this.rank=t.length;var e,n=vi(this.rank),r="uniform int start["+this.rank+"];",i=function(t){if(1===t)return"sourceLoc";if(t<=6)return pa.slice(0,t).map(function(t){return"sourceLoc."+t}).join(",");throw Error("Slicing for rank "+t+" is not yet supported")}(this.rank);e="\n "+n+" sourceLoc;\n "+n+" coords = getOutputCoords();\n "+t.map(function(t,e){return"sourceLoc."+pa[e]+" = start["+e+"] + coords."+pa[e]+";"}).join("\n")+"\n ",this.userCode="\n "+r+"\n void main() {\n "+e+"\n setOutput(getSource("+i+"));\n }\n "}return t.prototype.getCustomSetupFunc=function(t){var e=this;if(t.length!==this.rank)throw Error("The rank ("+this.rank+") of the program must match the length of start ("+t.length+")");return function(n,r){null==e.startLoc&&(e.startLoc=n.getUniformLocationNoThrow(r,"start"),null==e.startLoc)||n.gl.uniform1iv(e.startLoc,t)}},t}(),pa=["x","y","z","w","u","v"],ma=function(){function t(t){this.variableNames=["source"],this.usesPackedTextures=!0,this.outputShape=t,this.rank=t.length;var e=vi(this.rank),n=ri("coords",this.rank),r=ri("sourceLoc",this.rank),i=1===this.rank?"sourceLoc":"vec2("+r.slice(-2).join()+")",a="getChannel(getSource("+r.join()+"), "+i+")",o="\n result.x = "+a+";\n if (++"+n[this.rank-1]+" < "+t[this.rank-1]+") {\n ++"+r[this.rank-1]+";\n result.y = "+a+";\n --"+r[this.rank-1]+";\n }\n ",s=1===this.rank?"":"\n --"+n[this.rank-1]+";\n if (++"+n[this.rank-2]+" < "+t[this.rank-2]+") {\n ++"+r[this.rank-2]+";\n result.z = "+a+";\n if (++"+n[this.rank-1]+" < "+t[this.rank-1]+") {\n ++"+r[this.rank-1]+";\n result.w = "+a+";\n }\n }\n ",u=this.rank<=4?"sourceLoc = coords +\n "+e+"("+t.map(function(t,e){return"start["+e+"]"}).join()+");":t.map(function(t,e){return r[e]+" = "+n[e]+" + start["+e+"];"}).join("\n");this.userCode="\n uniform int start["+this.rank+"];\n void main() {\n "+e+" coords = getOutputCoords();\n "+e+" sourceLoc;\n "+u+" \n vec4 result = vec4(0.);\n "+o+"\n "+s+"\n setOutput(result);\n }\n "}return t.prototype.getCustomSetupFunc=function(t){var e=this;if(t.length!==this.rank)throw Error("The rank ("+this.rank+") of the program must match the length of start ("+t.length+")");return function(n,r){null==e.startLoc&&(e.startLoc=n.getUniformLocationNoThrow(r,"start"),null==e.startLoc)||n.gl.uniform1iv(e.startLoc,t)}},t}(),va=function(){function t(t){this.gpgpu=t,this.numUsedTextures=0,this.numFreeTextures=0,this.freeTextures={},this.logEnabled=!1,this.usedTextures={}}return t.prototype.acquireTexture=function(t,e,n){var r,i=ga(e,n),a=ba(t,i,n);if(a in this.freeTextures||(this.freeTextures[a]=[]),a in this.usedTextures||(this.usedTextures[a]=[]),this.freeTextures[a].length>0){this.numFreeTextures--,this.numUsedTextures++,this.log();var o=this.freeTextures[a].shift();return this.usedTextures[a].push(o),o}return this.numUsedTextures++,this.log(),i===Oi.PACKED_2X2_FLOAT32?r=this.gpgpu.createPackedMatrixTexture(t[0],t[1]):i===Oi.PACKED_2X2_FLOAT16?r=this.gpgpu.createFloat16PackedMatrixTexture(t[0],t[1]):i===Oi.UNPACKED_FLOAT32?r=this.gpgpu.createFloat32MatrixTexture(t[0],t[1]):i===Oi.UNPACKED_FLOAT16?r=this.gpgpu.createFloat16MatrixTexture(t[0],t[1]):i===Oi.PACKED_4X1_UNSIGNED_BYTE&&(r=this.gpgpu.createUnsignedBytesMatrixTexture(t[0],t[1])),this.usedTextures[a].push(r),r},t.prototype.releaseTexture=function(t,e,n,r){if(null!=this.freeTextures){var i=ba(e,ga(n,r),r);i in this.freeTextures||(this.freeTextures[i]=[]),this.freeTextures[i].push(t),this.numFreeTextures++,this.numUsedTextures--;var a=this.usedTextures[i],o=a.indexOf(t);if(o<0)throw new Error("Cannot release a texture that was never provided by this texture manager");a.splice(o,1),this.log()}},t.prototype.log=function(){if(this.logEnabled){var t=this.numFreeTextures+this.numUsedTextures;console.log("Free/Used",this.numFreeTextures+" / "+this.numUsedTextures,"("+t+")")}},t.prototype.getNumUsedTextures=function(){return this.numUsedTextures},t.prototype.getNumFreeTextures=function(){return this.numFreeTextures},t.prototype.dispose=function(){var t=this;if(null!=this.freeTextures){for(var e in this.freeTextures)this.freeTextures[e].forEach(function(e){t.gpgpu.deleteMatrixTexture(e)});for(var e in this.usedTextures)this.usedTextures[e].forEach(function(e){t.gpgpu.deleteMatrixTexture(e)});this.freeTextures=null,this.usedTextures=null,this.numUsedTextures=0,this.numFreeTextures=0}},t}();function ga(t,e){if(t===Ni.UPLOAD)return e?Oi.PACKED_2X2_FLOAT32:Oi.UNPACKED_FLOAT32;if(t===Ni.RENDER||null==t)return e?f.getBool("WEBGL_RENDER_FLOAT32_ENABLED")?Oi.PACKED_2X2_FLOAT32:Oi.PACKED_2X2_FLOAT16:f.getBool("WEBGL_RENDER_FLOAT32_ENABLED")?Oi.UNPACKED_FLOAT32:Oi.UNPACKED_FLOAT16;if(t===Ni.DOWNLOAD||t===Ni.PIXELS)return Oi.PACKED_4X1_UNSIGNED_BYTE;throw new Error("Unknown logical texture type "+t)}function ba(t,e,n){return t[0]+"_"+t[1]+"_"+e+"_"+n}var ya=function(t,e){this.variableNames=["A"],this.outputShape=t,this.userCode="\n float unaryOperation(float x) {\n "+e+"\n }\n\n void main() {\n float x = getAAtOutCoords();\n float y = unaryOperation(x);\n\n setOutput(y);\n }\n "},wa="if (isnan(x)) return x;",xa=wa+"\n return (x < 0.0) ? 0.0 : x;\n",ka="return exp(x);",Sa="\n vec4 result = x * vec4(greaterThanEqual(x, vec4(0.0)));\n bvec4 isNaN = isnan(x);\n\n result.r = isNaN.r ? x.r : result.r;\n result.g = isNaN.g ? x.g : result.g;\n result.b = isNaN.b ? x.b : result.b;\n result.a = isNaN.a ? x.a : result.a;\n\n return result;\n",_a=function(t,e){this.variableNames=["A"],this.usesPackedTextures=!0,this.outputShape=t,this.userCode="\n vec4 unaryOperation(vec4 x) {\n "+e+"\n }\n\n void main() {\n vec4 x = getAAtOutCoords();\n vec4 y = unaryOperation(x);\n\n setOutput(y);\n }\n "},Ea={},Ca=600,Aa=function(){function t(t){if(this.gpgpu=t,this.pendingRead=new WeakMap,this.pendingDisposal=new WeakSet,this.dataRefCount=new WeakMap,this.numBytesInGPU=0,this.uploadWaitMs=0,this.downloadWaitMs=0,this.warnedAboutMemory=!1,this.disposed=!1,!f.getBool("HAS_WEBGL"))throw new Error("WebGL is not supported on this device");if(null==t){var e=Lt(f.getNumber("WEBGL_VERSION"));this.binaryCache=(n=f.getNumber("WEBGL_VERSION"))in Ea?Ea[n]:(Ea[n]={},Ea[n]),this.gpgpu=new sa(e),this.canvas=e.canvas,this.gpgpuCreatedLocally=!0}else this.binaryCache={},this.gpgpuCreatedLocally=!1,this.canvas=t.gl.canvas;var n;this.textureManager=new va(this.gpgpu),this.numMBBeforeWarning=null==f.global.screen?1024:f.global.screen.height*f.global.screen.width*window.devicePixelRatio*Ca/1024/1024,this.texData=new Zn(Dt)}return t.prototype.register=function(t,e,n){if(this.texData.has(t))throw new Error("Data buffer is already registered");this.texData.set(t,{shape:e,dtype:n})},t.prototype.fromPixels=function(t,e){if(null==t)throw new Error("pixels passed to tf.browser.fromPixels() can not be null");var n=[t.height,t.width],r=[t.height,t.width,e];if(f.getBool("IS_BROWSER")){if(!(t instanceof HTMLVideoElement||t instanceof HTMLImageElement||t instanceof HTMLCanvasElement||t instanceof ImageData))throw new Error("pixels passed to tf.browser.fromPixels() must be either an HTMLVideoElement, HTMLImageElement, HTMLCanvasElement or ImageData, but was "+t.constructor.name);if(t instanceof HTMLVideoElement){if(null==this.fromPixels2DContext){if("complete"!==document.readyState)throw new Error("The DOM is not ready yet. Please call tf.browser.fromPixels() once the DOM is ready. One way to do that is to add an event listener for `DOMContentLoaded` on the document object");this.fromPixels2DContext=document.createElement("canvas").getContext("2d")}this.fromPixels2DContext.canvas.width=t.width,this.fromPixels2DContext.canvas.height=t.height,this.fromPixels2DContext.drawImage(t,0,0,t.width,t.height),t=this.fromPixels2DContext.canvas}}var i=this.makeTensorHandle(n,"int32");this.texData.get(i.dataId).usage=Ni.PIXELS,this.gpgpu.uploadPixelDataToTexture(this.getTexture(i.dataId),t);var a=new function(t){this.variableNames=["A"];var e=si(),n=t[0],r=t[1];this.outputShape=t,this.userCode="\n void main() {\n ivec3 coords = getOutputCoords();\n int texR = coords[0];\n int texC = coords[1];\n int depth = coords[2];\n vec2 uv = (vec2(texC, texR) + halfCR) / vec2("+r+".0, "+n+".0);\n\n vec4 values = "+e.texture2D+"(A, uv);\n float value;\n if (depth == 0) {\n value = values.r;\n } else if (depth == 1) {\n value = values.g;\n } else if (depth == 2) {\n value = values.b;\n } else if (depth == 3) {\n value = values.a;\n }\n\n setOutput(floor(value * 255.0 + 0.5));\n }\n "}(r),o=this.compileAndRun(a,[i]);return this.disposeData(i.dataId),o},t.prototype.makeTensorHandle=function(t,e){var n={};return this.register(n,t,e),{dataId:n,shape:t,dtype:e}},t.prototype.write=function(t,e){if(null==e)throw new Error("MathBackendWebGL.write(): values can not be null");if(f.getBool("DEBUG"))for(var n=0;n FLOAT_MAX) {\n return vec4(0.0, 0.0, 128.0, 127.0) / 255.0;\n } else if(v < -FLOAT_MAX) {\n return vec4(0.0, 0.0, 128.0, 255.0) / 255.0;\n }\n\n highp vec4 c = vec4(0,0,0,0);\n\n highp float e = floor(log2(av));\n highp float m = exp2(fract(log2(av))) - 1.0;\n\n c[2] = floor(128.0 * m);\n m -= c[2] / 128.0;\n c[1] = floor(32768.0 * m);\n m -= c[1] / 32768.0;\n c[0] = floor(8388608.0 * m);\n\n highp float ebias = e + 127.0;\n c[3] = floor(ebias / 2.0);\n ebias -= c[3] * 2.0;\n c[2] += floor(ebias) * 128.0;\n\n c[3] += 128.0 * step(0.0, -v);\n\n return c / 255.0;\n }\n\n void main() {\n float x = getAAtOutCoords();\n "+e.output+" = encode_float(x);\n }\n "}(i);return n.compileAndRun(e,[{shape:i,dtype:a,dataId:t}],d,null)}),m=this.texData.get(p.dataId),v=this.gpgpu.downloadByteEncodedFloatMatrixFromOutputTexture(m.texture,m.texShape[0],m.texShape[1]).subarray(0,u);return this.disposeData(d.dataId),v},t.prototype.time=function(t){return c(this,void 0,void 0,function(){var e,n,r,i,a,o,s;return l(this,function(u){switch(u.label){case 0:return e=this.activeTimers,n=[],r=!1,null==this.programTimersStack?(this.programTimersStack=n,r=!0):this.activeTimers.push(n),this.activeTimers=n,t(),i=S(this.activeTimers.map(function(t){return t.query})).filter(function(t){return null!=t}),a=S(this.activeTimers.map(function(t){return t.name})).filter(function(t){return null!=t}),this.activeTimers=e,r&&(this.programTimersStack=null),[4,Promise.all(i)];case 1:return o=u.sent(),s={uploadWaitMs:this.uploadWaitMs,downloadWaitMs:this.downloadWaitMs,kernelMs:y(o),getExtraProfileInfo:function(){return o.map(function(t,e){return{name:a[e],ms:t}}).map(function(t){return t.name+": "+t.ms}).join(", ")},wallMs:null},this.uploadWaitMs=0,this.downloadWaitMs=0,[2,s]}})})},t.prototype.memory=function(){return{unreliable:!1,numBytesInGPU:this.numBytesInGPU}},t.prototype.startTimer=function(){return f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0?this.gpgpu.beginQuery():{startMs:performance.now(),endMs:null}},t.prototype.endTimer=function(t){return f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0?(this.gpgpu.endQuery(),t):(t.endMs=performance.now(),t)},t.prototype.getQueryTime=function(t){return c(this,void 0,void 0,function(){var e;return l(this,function(n){return f.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0?[2,this.gpgpu.waitForQueryAndGetTime(t)]:[2,(e=t).endMs-e.startMs]})})},t.prototype.disposeData=function(t){if(!this.pendingDisposal.has(t))if(this.pendingRead.has(t))this.pendingDisposal.add(t);else if(this.texData.has(t)){this.releaseGPUData(t);var e=this.texData.get(t).complexTensors;null!=e&&(e.real.dispose(),e.imag.dispose()),this.texData.delete(t)}},t.prototype.releaseGPUData=function(t){var e=this.texData.get(t),n=e.texture,r=e.dtype,i=e.texShape,a=e.usage,o=e.isPacked,s=e.slice,u=s&&s.origDataId||t,c=this.dataRefCount.get(u);c>1?this.dataRefCount.set(u,c-1):(this.dataRefCount.delete(u),null!=n&&(this.numBytesInGPU-=this.computeBytes(i,r),this.textureManager.releaseTexture(n,i,a,o)));var l=this.texData.get(t);l.texture=null,l.texShape=null,l.isPacked=!1,l.slice=null},t.prototype.getTexture=function(t){return this.uploadToGPU(t),this.texData.get(t).texture},t.prototype.getCPUBackend=function(){return f.getBool("WEBGL_CPU_FORWARD")?(null==this.cpuBackend&&(this.cpuBackend=Dt.findBackend("cpu")),this.cpuBackend):null},t.prototype.shouldExecuteOnCPU=function(t,e){var n=this;return void 0===e&&(e=128),null!=this.getCPUBackend()&&t.every(function(t){return null==n.texData.get(t.dataId).texture&&t.size4)throw new Error("WebGL backend: Reverse of rank-"+n+" tensor is not yet supported");this.outputShape=t;var r=ri("rc",n),i=r[n-1]+" + 1 < "+this.outputShape[n-1],a=r[n-2]+" + 1 < "+this.outputShape[n-2],o=vi(n);function s(n){var r=t.map(function(r,i){return function(n,r){return-1!==e.indexOf(n)&&1!==t[n]?t[n]+" - "+r[n]+" - 1":""+r[n]}(i,n)});return"getChannel(getX("+r.join(",")+"), vec2("+r.slice(-2).join(",")+"))"}this.userCode=1===n?"\n void main(){\n int rc = getOutputCoords();\n vec4 result = vec4(0.);\n result.r = getChannel(getX("+t[0]+" - rc - 1),\n "+t[0]+" - rc - 1);\n if("+i+"){\n result.g = getChannel(getX("+t[0]+" - (rc + 1) - 1),\n "+t[0]+" - (rc + 1) - 1);\n }\n setOutput(result);\n }\n ":"\n void main() {\n "+o+" rc = getOutputCoords();\n vec4 result = vec4(0.);\n result.r = "+s(r.slice())+";\n if("+i+"){\n result.g = "+function(t){return t[n-1]="("+t[n-1]+" + 1)",s(t)}(r.slice())+";\n }\n if("+a+") {\n result.b = "+function(t){return t[n-2]="("+t[n-2]+" + 1)",s(t)}(r.slice())+";\n if("+i+") {\n result.a = "+function(t){return t[n-1]="("+t[n-1]+" + 1)",t[n-2]="("+t[n-2]+" + 1)",s(t)}(r.slice())+";\n }\n }\n setOutput(result);\n }\n "}(t.shape,e):new function(t,e){this.variableNames=["x"];var n=t.length;if(n>4)throw new Error("WebGL backend: Reverse of rank-"+n+" tensor is not yet supported");if(this.outputShape=t,1!==n){var r=t.map(function(n,r){return function(n){return-1!==e.indexOf(n)&&1!==t[n]?t[n]+" - coords["+n+"] - 1":"coords["+n+"]"}(r)}).join(","),i=vi(n);this.userCode="\n void main() {\n "+i+" coords = getOutputCoords();\n setOutput(getX("+r+"));\n }\n "}else this.userCode="\n void main() {\n int coord = getOutputCoords();\n setOutput(getX("+t[0]+" - coord - 1));\n }\n "}(t.shape,e);return this.compileAndRun(n,[t])},t.prototype.concat=function(t,e){if(this.shouldExecuteOnCPU(t))return this.cpuBackend.concat(t,e);if(1===t.length)return t[0];if(t.length>f.getNumber("WEBGL_MAX_TEXTURES_IN_SHADER")){var n=Math.floor(t.length/2),r=this.concat(t.slice(0,n),e),i=this.concat(t.slice(n),e);return this.concat([r,i],e)}if(f.getBool("WEBGL_PACK_ARRAY_OPERATIONS")&&t[0].rank>1){var a=new function(t,e){this.usesPackedTextures=!0,this.outputShape=[],this.outputShape=ln(t,e);var n=this.outputShape,r=n.length,i=vi(r),a=ri("coords",r),o=["x","y","z","w","u","v"].slice(0,r);this.variableNames=t.map(function(t,e){return"T"+e});var s=new Array(t.length-1);s[0]=t[0][e];for(var u=1;u1e3){n&&(t=t.transpose([0,2,1])),r&&(e=e.transpose([0,2,1]));var u=1===a?t:t.as3D(s,o,1),c=1===a?2:1,l=1===a?e.as3D(s,1,o):e;return this.multiply(u,l).sum(c,!0)}var f=Et(t.dtype,e.dtype),h=new ca(t.shape,[s,i,a],n,r),d=this.makePackedTensor(h.outputShape,f);return this.compileAndRun(h,[t,e],d)},t.prototype.fusedBatchMatMul=function(t,e,n,r,i,a){var o=n?t.shape[2]:t.shape[1],s=r?e.shape[1]:e.shape[2],u=t.shape[0],c=Et(t.dtype,e.dtype),l=new ca(t.shape,[u,o,s],n,r,!!i,a?function(t,e){if(void 0===e&&(e=!1),"linear"===t)return"return x;";if("relu"===t)return e?Sa:xa;throw new Error("Activation "+t+" has not been implemented for the WebGL backend.")}(a,!0):null),f=this.makePackedTensor(l.outputShape,c),h=[t,e];return i&&h.push(i),this.compileAndRun(l,h,f)},t.prototype.multiply=function(t,e){if("complex64"===t.dtype){var n=this.texData.get(t.dataId),r=this.texData.get(e.dataId),i=new yi("return areal * breal - aimag * bimag;",t.shape,e.shape),a=new yi("return areal * bimag + aimag * breal;",t.shape,e.shape),o=[this.makeComplexComponentTensorHandle(t,n.complexTensors.real),this.makeComplexComponentTensorHandle(t,n.complexTensors.imag),this.makeComplexComponentTensorHandle(e,r.complexTensors.real),this.makeComplexComponentTensorHandle(e,r.complexTensors.imag)],s=this.compileAndRun(i,o),u=this.compileAndRun(a,o),c=this.complex(s,u);return s.dispose(),u.dispose(),c}if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.multiply(t,e);if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,ki,t.dtype);var l=new Si(ki,t.shape,e.shape),h=this.makeOutputArray(l.outputShape,t.dtype);return this.compileAndRun(l,[t,e],h)},t.prototype.batchNormalization=function(t,e,n,r,i,a){var o=[t,e,n],s=null;null!=a&&(s=a.shape,o.push(a));var u=null;if(null!=i&&(u=i.shape,o.push(i)),f.getBool("WEBGL_PACK_NORMALIZATION")){var c=new function(t,e,n,r,i,a){this.usesPackedTextures=!0,this.variableNames=["x","mean","variance"],oi(t,e),oi(t,n);var o="vec4(0.0)";null!=r&&(oi(t,r),this.variableNames.push("offset"),o="getOffsetAtOutCoords()");var s="vec4(1.0)";null!=i&&(oi(t,i),this.variableNames.push("scale"),s="getScaleAtOutCoords()"),this.outputShape=t,this.userCode="\n void main() {\n vec4 offset = "+o+";\n vec4 scale = "+s+";\n\n vec4 x = getXAtOutCoords();\n vec4 mean = getMeanAtOutCoords();\n vec4 variance = getVarianceAtOutCoords();\n\n vec4 inv = scale * inversesqrt(variance + vec4("+a+"));\n\n setOutput((x - mean) * inv + offset);\n }\n "}(t.shape,e.shape,n.shape,s,u,r);return this.compileAndRun(c,o)}var l=new function(t,e,n,r,i,a){this.outputShape=[],this.variableNames=["x","mean","variance"],oi(t,e),oi(t,n);var o="0.0";null!=r&&(oi(t,r),this.variableNames.push("offset"),o="getOffsetAtOutCoords()");var s="1.0";null!=i&&(oi(t,i),this.variableNames.push("scale"),s="getScaleAtOutCoords()"),this.outputShape=t,this.userCode="\n void main() {\n float x = getXAtOutCoords();\n float mean = getMeanAtOutCoords();\n float variance = getVarianceAtOutCoords();\n float offset = "+o+";\n float scale = "+s+";\n float inv = scale * inversesqrt(variance + float("+a+"));\n setOutput(dot(vec3(x, -mean, offset), vec3(inv, inv, 1)));\n }\n "}(t.shape,e.shape,n.shape,s,u,r);return this.compileAndRun(l,o)},t.prototype.localResponseNormalization4D=function(t,e,n,r,i){var a=f.getBool("WEBGL_PACK_NORMALIZATION")?new function(t,e,n,r,i){this.variableNames=["x"],this.outputShape=[],this.usesPackedTextures=!0;var a,o=e,s=t[3]-1;this.outputShape=t;var u="float("+n+") + float("+r+") * sum";a=.5===i?"inversesqrt("+u+")":1===i?"1.0/("+u+")":"exp(log("+u+") * float(-"+i+"));",this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords.x;\n int r = coords.y;\n int c = coords.z;\n int d = coords.w;\n\n bool hasNextCol = d < "+this.outputShape[3]+";\n bool hasNextRow = c < "+this.outputShape[2]+";\n\n vec4 sum = vec4(0.);\n vec4 xFragAtOutputCoords = getX(b, r, c, d);\n\n vec4 xAtOutputCoords = vec4(\n getChannel(xFragAtOutputCoords, vec2(c, d)),\n hasNextCol ?\n getChannel(xFragAtOutputCoords, vec2(c, d + 1)) : 0.0,\n hasNextRow ?\n getChannel(xFragAtOutputCoords , vec2(c + 1, d)) : 0.0,\n (hasNextRow && hasNextCol) ?\n getChannel(xFragAtOutputCoords, vec2(c + 1, d + 1)) : 0.0\n );\n\n int firstChannel = d - "+o+";\n vec2 cache = vec2(0.);\n if(firstChannel >= 0){\n vec4 firstChannelFrag = getX(b, r, c, firstChannel);\n cache.x = getChannel(firstChannelFrag, vec2(c, firstChannel));\n if(hasNextRow){\n cache.y = getChannel(firstChannelFrag, vec2(c + 1, firstChannel));\n }\n }\n\n ivec2 depth = ivec2(d, d + 1);\n for (int j = - "+o+"; j <= "+o+"; j++) {\n ivec2 idx = depth + j;\n bvec2 aboveLowerBound = greaterThanEqual(idx, ivec2(0));\n bvec2 belowUpperBound = lessThanEqual(idx, ivec2("+s+"));\n\n bool depthInRange = aboveLowerBound.x && belowUpperBound.x;\n bool depthPlusOneInRange = aboveLowerBound.y && belowUpperBound.y;\n\n if(depthInRange || depthPlusOneInRange){\n vec4 z = vec4(0.);\n vec4 xFragAtCurrentDepth;\n z.xz = cache.xy;\n if(depthPlusOneInRange && hasNextCol){\n xFragAtCurrentDepth = idx.y != d ?\n getX(b, r, c, idx.y) : xFragAtOutputCoords;\n z.y = getChannel(xFragAtCurrentDepth, vec2(c, idx.y));\n if(hasNextRow){\n z.w = getChannel(xFragAtCurrentDepth, vec2(c + 1, idx.y));\n }\n }\n cache.xy = z.yw;\n sum += z * z;\n }\n }\n vec4 result = xAtOutputCoords * "+a+";\n setOutput(result);\n }\n "}(t.shape,e,n,r,i):new function(t,e,n,r,i){this.variableNames=["x"],this.outputShape=[];var a,o=e,s=t[3]-1;this.outputShape=t;var u="float("+n+") + float("+r+") * sum";a=.5===i?"inversesqrt("+u+")":1===i?"1.0/("+u+")":"exp(log("+u+") * float(-"+i+"));",this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int r = coords[1];\n int c = coords[2];\n int d = coords[3];\n float x = getX(b, r, c, d);\n float sum = 0.0;\n for (int j = -"+o+"; j <= "+o+"; j++) {\n int idx = d + j;\n if (idx >= 0 && idx <= "+s+") {\n float z = getX(b, r, c, idx);\n sum += z * z;\n }\n }\n float val = x * "+a+";\n setOutput(val);\n }\n "}(t.shape,e,n,r,i);return this.compileAndRun(a,[t])},t.prototype.LRNGrad=function(t,e,n,r,i,a,o){var s=new function(t,e,n,r,i){this.variableNames=["inputImage","outputImage","dy"],this.outputShape=[],this.outputShape=t,this.depth=t[3],this.depthRadius=e,this.bias=n,this.alpha=r,this.beta=i,this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int r = coords[1];\n int c = coords[2];\n\n float result = 0.0;\n for (int d = 0; d < "+this.depth+"; ++d) {\n int depthBegin = int(max(0.0, float(d - "+e+")));\n int depthEnd = int(min(float("+this.depth+"),\n float(d + "+e+" + 1)));\n\n const int MIN_DEPTH_BEGIN = 0;\n const int MAX_DEPTH_END = "+this.depth+";\n\n float norm = 0.0;\n for (int k = MIN_DEPTH_BEGIN; k < MAX_DEPTH_END; ++k) {\n if (k < depthBegin){\n continue;\n }\n else if (k >= depthBegin && k < depthEnd) {\n norm += getInputImage(b, r, c, k) * getInputImage(b, r, c, k);\n }\n else {\n break;\n }\n }\n\n norm = float("+r+") * norm + float("+n+");\n\n for(int k = MIN_DEPTH_BEGIN; k < MAX_DEPTH_END; ++k){\n if (k < depthBegin){\n continue;\n }\n else if (k >= depthBegin && k < depthEnd){\n float dyi = -2.0 * float("+r+")\n * float("+i+")\n * getInputImage(b ,r ,c, k) * getOutputImage(b, r, c, d)\n / norm;\n if (k == d) {\n dyi += pow(norm, -1.0 * "+i+");\n }\n if (k == coords[3]) {\n dyi *= getDy(b, r, c, d);\n result += dyi;\n }\n }\n else {\n break;\n }\n }\n }\n setOutput(result);\n }\n "}(e.shape,r,i,a,o);return this.compileAndRun(s,[e,n,t])},t.prototype.tile=function(t,e){var n=new function(t,e){this.variableNames=["A"];for(var n=new Array(t.length),r=0;r5)throw Error("Tile for rank "+e+" is not yet supported");if(1===e)return"imod(resRC, "+t[0]+")";for(var n=["resRC.x","resRC.y","resRC.z","resRC.w","resRC.u"],r=[],i=0;i= end":"any(lessThan(rc, start)) || any(greaterThanEqual(rc, end))",d="",p=0,m=1===r?2:4;p= end) {\n setOutput(float("+n+"));\n } else {\n setOutput(getX(outC - start));\n }\n }\n "}(t.shape,e,n);return this.compileAndRun(r,[t])},t.prototype.transpose=function(t,e){if(this.shouldExecuteOnCPU([t]))return this.cpuBackend.transpose(t,e);var n=f.getBool("WEBGL_PACK_ARRAY_OPERATIONS")?new function(t,e){this.variableNames=["A"],this.usesPackedTextures=!0;for(var n=new Array(t.length),r=0;r6)throw Error("Packed transpose for rank "+this.rank+" is not yet supported.");var i=vi(this.rank),a=ni("rc",this.rank),o=new Array(this.rank);for(r=0;r6)throw Error("Transpose for rank "+e+" is not yet supported");for(var n=["resRC.x","resRC.y","resRC.z","resRC.w","resRC.u","resRC.v"],r=new Array(e),i=0;i4)throw Error("Gather for rank "+n+" is not yet supported");if(1===n)return"int(getIndices(resRC))";for(var r=["resRC.x","resRC.y","resRC.z","resRC.w"],i=[],a=0;a 4 with a WebGL backend not implemented yet"});var r=e.reduce(function(t,e){return t*e}),i=Je(t.shape,e,r),a=Ze(i.length,e.length),o=Qe(t.shape,e,r),s=tn(n,e.length),u=en(o,n,e.length);return t.reshape(i).transpose(a).reshape(o).slice(s,u)},t.prototype.spaceToBatchND=function(t,e,n){w(t.rank<=4,function(){return"spaceToBatchND for rank > 4 with a WebGL backend not implemented yet"});var r=e.reduce(function(t,e){return t*e}),i=[[0,0]];i.push.apply(i,n);for(var a=1+e.length;a= 1.0 && floatedReducedAllValue >= 1.0);\n ",h="bvec4"):"any"===e&&(o="0.0",f="\n bool reducedAnyValue = any(values);\n float floatedReducedAnyValue = float(reducedAnyValue);\n anyValue = float(anyValue >= 1.0 || floatedReducedAnyValue >= 1.0);\n ",h="bvec4");var d="";i%n>0&&(d="\n if (inIdx < 0 || inIdx >= "+i+") {\n return initializationValue;\n }\n "),this.userCode="\n const float initializationValue = "+o+";\n const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n float getValue(int batch, int inIdx) {\n "+d+"\n return getX(batch, inIdx);\n }\n\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n int outIdx = coords[1];\n int inOffset = outIdx * "+n+";\n\n vec4 minMaxValue = vec4("+o+");\n float prodValue = 1.0;\n float sumValue = 0.0;\n float allValue = 1.0;\n float anyValue = 0.0;\n\n for (int i = 0; i < "+c+"; i += 4) {\n int inIdx = inOffset + i;\n "+h+" values = "+h+"(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n getValue(batch, inIdx + 3)\n );\n\n "+f+"\n }\n\n int inIdx = inOffset + "+c+";\n if ("+(1===l)+") {\n "+h+" values = "+h+"(\n getValue(batch, inIdx),\n initializationValue,\n initializationValue,\n initializationValue\n );\n\n "+f+"\n } else if ("+(2===l)+") {\n "+h+" values = "+h+"(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n initializationValue,\n initializationValue\n );\n\n "+f+"\n } else if ("+(3===l)+") {\n "+h+" values = "+h+"(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n initializationValue\n );\n\n "+f+"\n }\n setOutput("+u+");\n }\n "}({windowSize:dn(i),inSize:i,batchSize:r},e),o=a.outputShape,s=o[0],u=o[1],c=this.makeOutputArray([s,u],n);return this.compileAndRun(a,[t],c),1===c.shape[1]?c:this.reduce(c,e,n)},t.prototype.argReduce=function(t,e,n){void 0===n&&(n=null);var r=t.shape[0],i=t.shape[1];null!=n&&(r=n.shape[0],i=n.shape[1]);var a=new function(t,e,n){this.variableNames=["A"];var r=t.windowSize,i=t.batchSize,a=t.inSize,o=Math.ceil(a/r);n||this.variableNames.push("bestIndicesA"),this.outputShape=[i,o];var s="max"===e?">":"<",u=n?"inOffset + i;":"round(getBestIndicesA(batch, inOffset + i));";this.userCode="\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n int outIdx = coords[1];\n int inOffset = outIdx * "+r+";\n\n int bestIndex = inOffset;\n float bestValue = getA(batch, bestIndex);\n\n for (int i = 0; i < "+r+"; i++) {\n int inIdx = "+u+";\n float candidate = getA(batch, inIdx);\n if (candidate "+s+" bestValue) {\n bestValue = candidate;\n bestIndex = inIdx;\n }\n }\n setOutput(float(bestIndex));\n }\n "}({windowSize:dn(i),inSize:i,batchSize:r},e,null==n),o=a.outputShape,s=o[0],u=o[1],c=this.makeOutputArray([s,u],"int32"),l=[t];return null!=n&&l.push(n),this.compileAndRun(a,l,c),1===c.shape[1]?c:this.argReduce(t,e,c)},t.prototype.argReducePacked=function(t,e,n){void 0===n&&(n=null);var r=null!=n?n.shape:t.shape,i=new function(t,e,n,r){this.variableNames=["A"],this.usesPackedTextures=!0,w(t.length>2,function(){return"Packed arg"+(n.charAt(0).toUpperCase()+n.slice(1))+" supports only inputs with rank above 2."});var i=t[t.length-1],a=Math.ceil(i/e);this.outputShape=t.slice(0,-1),a>1&&this.outputShape.push(a),r||this.variableNames.push("bestIndicesA");var o,s,u=this.outputShape,c=u.length,l=vi(c),f=ri("coords",c);if(1===a){var h=vi(s=c+1);o="\n "+h+" sourceLocR = "+h+"("+f.join()+", 0);\n ++"+f[c-1]+";\n "+h+" sourceLocG = "+h+"("+f.join()+", 0);\n ++"+f[c-2]+";\n "+h+" sourceLocA = "+h+"("+f.join()+", 0);\n --"+f[c-1]+";\n "+h+" sourceLocB = "+h+"("+f.join()+", 0);\n --"+f[c-2]+";"}else s=c,o="\n "+l+" sourceLocR = coords;\n ++"+f[c-1]+";\n "+l+" sourceLocG = coords;\n ++"+f[c-2]+";\n "+l+" sourceLocA = coords;\n --"+f[c-1]+";\n "+l+" sourceLocB = coords;\n --"+f[c-2]+";";var d=["x","y","z","w","u","v"].slice(0,s),p="."+d[s-1],m=d.map(function(t){return"int "+t}),v=ri("sourceLocR",s-1).concat("inIdx.r"),g=ri("sourceLocG",s-1).concat("inIdx.g"),b=ri("sourceLocB",s-1).concat("inIdx.b"),y=ri("sourceLocA",s-1).concat("inIdx.a"),x="max"===n?"greaterThan":"lessThan",k=r?"":"\n inIdx = round(vec4(getBestIndicesAChannel("+v.join()+"),\n getBestIndicesAChannel("+g.join()+"),\n getBestIndicesAChannel("+b.join()+"),\n getBestIndicesAChannel("+y.join()+")));",S="vec4(\n getAChannel("+v.join()+"),\n hasNextCol ? getAChannel("+g.join()+") : 0.,\n hasNextRow ? getAChannel("+b.join()+") : 0.,\n hasNextRow && hasNextCol ? getAChannel("+y.join()+") : 0.)",_=r?"":"\n float getBestIndicesAChannel("+m.join()+") {\n return getChannel(getBestIndicesA("+d.join()+"),\n vec2("+d.slice(-2).join()+"));\n }";this.userCode="\n float getAChannel("+m.join()+") {\n return getChannel(getA("+d.join()+"),\n vec2("+d.slice(-2).join()+"));\n }\n "+_+"\n void main() {\n "+l+" coords = getOutputCoords();\n bool hasNextCol = "+f[c-1]+" < "+(u[c-1]-1)+";\n bool hasNextRow = "+f[c-2]+" < "+(u[c-2]-1)+";\n "+o+"\n ivec4 srcIdx = ivec4(sourceLocR"+p+", sourceLocG"+p+",\n sourceLocB"+p+", sourceLocA"+p+") * "+e+";\n ivec4 inIdx = srcIdx;\n vec4 bestIndex = vec4(inIdx);\n vec4 bestValue = "+S+";\n\n for (int i = 0; i < "+e+"; i++) {\n inIdx = srcIdx;\n "+k+"\n vec4 candidate = "+S+";\n bvec4 nan = isnan(candidate);\n bvec4 replace = bvec4(\n vec4("+x+"(candidate, bestValue)) * (vec4(1.0) - vec4(nan)));\n\n bestValue = vec4(replace.x ? candidate.x : bestValue.x,\n replace.y ? candidate.y : bestValue.y,\n replace.z ? candidate.z : bestValue.z,\n replace.w ? candidate.w : bestValue.w);\n bestIndex = mix(bestIndex, vec4(inIdx), vec4(replace));\n srcIdx++;\n }\n setOutput(bestIndex);\n }\n "}(r,dn(r[r.length-1]),e,null==n),a=this.makePackedTensor(i.outputShape,"int32"),o=null==n?[t]:[t,n];return this.compileAndRun(i,o,a),a.rank===t.rank?this.argReducePacked(t,e,a):a},t.prototype.sum=function(t,e){on("sum",e,t.rank);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i),o=Ct(t.dtype);return this.reduce(a,"sum",o).reshape(r)},t.prototype.prod=function(t,e){if(this.shouldExecuteOnCPU([t]))return this.cpuBackend.prod(t,e);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i),o=Ct(t.dtype);return this.reduce(a,"prod",o).reshape(r)},t.prototype.unsortedSegmentSum=function(t,e,n){var r=0,i=sn([r],t.rank),a=t;null!=i&&(a=t.transpose(i),r=cn(1,t.rank)[0]);var o=function(t,e,n){for(var r=[],i=t.length,a=0;ae||n===t?r=!0:n=K(t,n+1);return n}(o,i),u=new function(t,e){this.variableNames=["x","segmentIds"];var n=t.windowSize,r=t.batchSize,i=t.inSize,a=t.numSegments,o=a*Math.ceil(i/n);this.outputShape=[r,o];var s=4*Math.floor(n/4),u=n%4,c="\n sumValue += dot(values, segFilter);\n ",l="";i%n>0&&(l="\n if (inIdx < 0 || inIdx >= "+i+") {\n return initializationValue;\n }\n ");var f="";i%n>0&&(f="\n if (inIdx < 0 || inIdx >= "+i+") {\n return -1.0;\n }\n "),this.userCode="\n const float initializationValue = 0.0;\n\n float getValue(int batch, int inIdx) {\n "+l+"\n return getX(batch, inIdx);\n }\n\n float getSegmentIdAtIndex(int inIdx) {\n "+f+"\n return getSegmentIds(inIdx);\n }\n\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n int outIdx = coords[1];\n int inOffset = int(floor(float(outIdx) / float(\n "+a+")) * float("+n+"));\n int currentSeg = int(mod(float(outIdx), float("+a+")));\n\n float sumValue = 0.0;\n\n for (int i = 0; i < "+s+"; i += 4) {\n int inIdx = inOffset + i;\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n getValue(batch, inIdx + 3)\n );\n\n vec4 segFilter = vec4(\n int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 2)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 3)) == currentSeg ? 1 : 0\n );\n\n "+c+"\n }\n\n int inIdx = inOffset + "+s+";\n if ("+(1===u)+") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n initializationValue,\n initializationValue,\n initializationValue\n );\n\n int inIdxSeg = int(getSegmentIdAtIndex(inIdx));\n\n vec4 segFilter = vec4(\n int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n 0,\n 0,\n 0\n );\n\n "+c+"\n } else if ("+(2===u)+") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n initializationValue,\n initializationValue\n );\n\n vec4 segFilter = vec4(\n int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n 0,\n 0\n );\n\n "+c+"\n } else if ("+(3===u)+") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n initializationValue\n );\n\n vec4 segFilter = vec4(\n int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n int(getSegmentIdAtIndex(inIdx + 2)) == currentSeg ? 1 : 0,\n 0\n );\n\n "+c+"\n }\n setOutput(sumValue);\n }\n "}({windowSize:s,inSize:o,batchSize:a,numSegments:i},e),c=u.outputShape,l=c[0],f=c[1],h=this.makeOutputArray([l,f],r);return this.compileAndRun(u,[t,n],h),h.shape[1]===i?h:(n=$n(0,i).tile([o/s]),this.segOpCompute(h,e,n,r,i))},t.prototype.argMinMaxReduce=function(t,e,n){var r=[e];if(on("arg"+n.charAt(0).toUpperCase()+n.slice(1),r,t.rank),!f.getBool("WEBGL_PACK_REDUCE")||t.rank<=2){var i=rn(t.shape,r),a=i[0],o=_(i[1]),s=t.as2D(-1,o);return this.argReduce(s,n).reshape(a)}return this.argReducePacked(t,n)},t.prototype.argMin=function(t,e){return this.argMinMaxReduce(t,e,"min")},t.prototype.argMax=function(t,e){return this.argMinMaxReduce(t,e,"max")},t.prototype.cumsum=function(t,e,n,r){if(e!==t.rank-1)throw new Error("WebGL cumsum shader expects an inner-most axis="+(t.rank-1)+" but got axis="+e);var i=new function(t,e,n){this.variableNames=["x"],this.outputShape=t;var r=t.length,i=t[t.length-1],a=n?"<":">";this.userCode="\n int getIndex(int i) {\n "+(n?"return "+i+" -i - 1;":"return i;")+"\n }\n\n void main() {\n "+vi(r)+" coords = getOutputCoords();\n int end = "+Ai(r,"coords")+";\n float val = 0.0;\n for (int i = "+i+" - 1; i >= 0; i -= 1) {\n int idx = getIndex(i);\n if (idx "+a+" end) {\n continue;\n }\n if (idx == end && "+e+") {\n continue;\n }\n "+Ai(r,"coords")+" = idx;\n val += getX("+function(t,e){if(1===t)return""+e;if(2===t)return e+".x, "+e+".y";if(3===t)return e+".x, "+e+".y, "+e+".z";if(4===t)return e+".x, "+e+".y, "+e+".z, "+e+".w";throw Error("Cumulative sum for rank "+t+" is not yet supported")}(r,"coords")+");\n }\n setOutput(val);\n }\n "}(t.shape,n,r);return this.compileAndRun(i,[t])},t.prototype.equal=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(equal(a, b));\n","bool");var n=new Si("return float(a == b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.notEqual=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(notEqual(a, b));\n","bool");var n=new Si("return float(a != b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.less=function(t,e){if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.less(t,e);if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(lessThan(a, b));\n","bool");var n=new Si("return float(a < b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.lessEqual=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(lessThanEqual(a, b));\n","bool");var n=new Si("return float(a <= b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.greater=function(t,e){if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.greater(t,e);if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(greaterThan(a, b));\n","bool");var n=new Si("return float(a > b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.greaterEqual=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(greaterThanEqual(a, b));\n","bool");var n=new Si("return float(a >= b);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.logicalNot=function(t){var e=new ya(t.shape,"return float(!(x >= 1.0));");return this.compileAndRun(e,[t])},t.prototype.logicalAnd=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return vec4(\n vec4(greaterThanEqual(a, vec4(1.0))) *\n vec4(greaterThanEqual(b, vec4(1.0))));\n","bool");var n=new Si("return float(a >= 1.0 && b >= 1.0);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.logicalOr=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n return min(\n vec4(greaterThanEqual(a, vec4(1.0))) +\n vec4(greaterThanEqual(b, vec4(1.0))),\n vec4(1.0));\n","bool");var n=new Si("return float(a >= 1.0 || b >= 1.0);",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"bool");return this.compileAndRun(n,[t,e],r)},t.prototype.select=function(t,e,n){var r=new function(t,e,n){var r,i;if(this.variableNames=["c","a","b"],this.outputShape=e,n>4)throw Error("Where for rank "+n+" is not yet supported");if(1===n)i="resRC",r="resRC";else{for(var a=["resRC.x","resRC.y","resRC.z","resRC.w"],o=[],s=[],u=0;u= 1.0) {\n setOutput(getA("+i+"));\n } else {\n setOutput(getB("+i+"));\n }\n }\n "}(t.rank,e.shape,e.rank),i=this.makeOutputArray(r.outputShape,Et(e.dtype,n.dtype));return this.compileAndRun(r,[t,e,n],i)},t.prototype.where=function(t){Ye("tf.where() in webgl locks the UI thread. Call tf.whereAsync() instead");var e=t.dataSync();return ei(t.shape,e)},t.prototype.topk=function(t,e,n){return lr(t.dataSync(),t.shape,t.dtype,e)},t.prototype.min=function(t,e){on("min",e,t.rank);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i);return this.reduce(a,"min",a.dtype).reshape(r)},t.prototype.minimum=function(t,e){if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.minimum(t,e);var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 result = vec4(min(a, b));\n vec4 isNaN = min(vec4(isnan(a)) + vec4(isnan(b)), vec4(1.0));\n \n result.r = isNaN.r > 0. ? NAN : result.r;\n result.g = isNaN.g > 0. ? NAN : result.g;\n result.b = isNaN.b > 0. ? NAN : result.b;\n result.a = isNaN.a > 0. ? NAN : result.a;\n\n return result;\n",t.shape,e.shape):new Si("\n if (isnan(a)) return a;\n if (isnan(b)) return b;\n\n return min(a, b);\n",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.mod=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 result = mod(a, b);\n vec4 isNaN = vec4(equal(b, vec4(0.0)));\n \n result.r = isNaN.r > 0. ? NAN : result.r;\n result.g = isNaN.g > 0. ? NAN : result.g;\n result.b = isNaN.b > 0. ? NAN : result.b;\n result.a = isNaN.a > 0. ? NAN : result.a;\n\n return result;\n",t.shape,e.shape):new Si("if (b == 0.0) return NAN;\n return mod(a, b);",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.max=function(t,e){if(this.shouldExecuteOnCPU([t]))return this.cpuBackend.max(t,e);on("max",e,t.rank);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i);return this.reduce(a,"max",a.dtype).reshape(r)},t.prototype.maximum=function(t,e){if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.maximum(t,e);var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 result = vec4(max(a, b));\n vec4 isNaN = min(vec4(isnan(a)) + vec4(isnan(b)), vec4(1.0));\n \n result.r = isNaN.r > 0. ? NAN : result.r;\n result.g = isNaN.g > 0. ? NAN : result.g;\n result.b = isNaN.b > 0. ? NAN : result.b;\n result.a = isNaN.a > 0. ? NAN : result.a;\n\n return result;\n",t.shape,e.shape):new Si("\n if (isnan(a)) return a;\n if (isnan(b)) return b;\n\n return max(a, b);\n",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.all=function(t,e){on("all",e,t.rank);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i);return this.reduce(a,"all",a.dtype).reshape(r)},t.prototype.any=function(t,e){on("any",e,t.rank);var n=rn(t.shape,e),r=n[0],i=_(n[1]),a=t.as2D(-1,i);return this.reduce(a,"any",a.dtype).reshape(r)},t.prototype.squaredDifference=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("return (a - b) * (a - b);",t.shape,e.shape):new Si("return (a - b) * (a - b);",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.realDivide=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n // vec4 one = vec4(equal(a, b));\n // return one + (vec4(1.0) - one) * a / b;\n vec4 result = a / b;\n if(b.x == 0.0) {\n result.x = NAN;\n } else if(a.x == b.x) {\n result.x = 1.;\n }\n if(b.y == 0.0) {\n result.y = NAN;\n } else if(a.y == b.y) {\n result.y = 1.;\n }\n if(b.z == 0.0) {\n result.z = NAN;\n } else if(a.z == b.z) {\n result.z = 1.;\n }\n if(b.w == 0.0) {\n result.w = NAN;\n } else if(a.w == b.w) {\n result.w = 1.;\n }\n \n return result;\n","float32",!0);var n=new Si("\nif (b == 0.0) {\n return NAN;\n} \nif (a == b) {\n return 1.0;\n};\nreturn a / b;",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"float32");return this.compileAndRun(n,[t,e],r)},t.prototype.floorDiv=function(t,e){if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,"\n ivec4 ia = round(a);\n ivec4 ib = round(b);\n bvec4 cond = notEqual(ib, ivec4(0));\n ivec4 result = ivec4(0);\n vec4 s = sign(a) * sign(b);\n\n // Windows (D3D) wants guaranteed non-zero int division at compile-time.\n if (cond[0]) {\n result[0] = idiv(ia[0], ib[0], s[0]);\n }\n if (cond[1]) {\n result[1] = idiv(ia[1], ib[1], s[1]);\n }\n if (cond[2]) {\n result[2] = idiv(ia[2], ib[2], s[2]);\n }\n if (cond[3]) {\n result[3] = idiv(ia[3], ib[3], s[3]);\n }\n return vec4(result);\n","int32");var n=new Si("\n float s = sign(a) * sign(b);\n int ia = round(a);\n int ib = round(b);\n if (ib != 0) {\n // Windows (D3D) wants guaranteed non-zero int division at compile-time.\n return float(idiv(ia, ib, s));\n } else {\n return NAN;\n }\n",t.shape,e.shape),r=this.makeOutputArray(n.outputShape,"int32");return this.compileAndRun(n,[t,e],r)},t.prototype.add=function(t,e){if("complex64"===t.dtype&&"complex64"===e.dtype)return this.complexSeparableBinaryOp(t,e,wi);if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.add(t,e);var n=Et(t.dtype,e.dtype);if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,wi,n);var r=new Si(wi,t.shape,e.shape),i=this.makeOutputArray(r.outputShape,n);return this.compileAndRun(r,[t,e],i)},t.prototype.packedBinaryOp=function(t,e,n,r,i){void 0===i&&(i=!1);var a=new _i(n,t.shape,e.shape,i),o=this.makePackedTensor(a.outputShape,r);return this.compileAndRun(a,[t,e],o)},t.prototype.complexSeparableBinaryOp=function(t,e,n){var r=this,i=this.texData.get(t.dataId),a=this.texData.get(e.dataId),o=[[i.complexTensors.real,a.complexTensors.real],[i.complexTensors.imag,a.complexTensors.imag]].map(function(i){var a=i[0],o=i[1],s=r.makeComplexComponentTensorHandle(t,a),u=r.makeComplexComponentTensorHandle(e,o),c=new Si(n,t.shape,e.shape),l=r.makeOutputArray(c.outputShape,Et(a.dtype,o.dtype));return r.compileAndRun(c,[s,u],l)}),s=o[0],u=o[1],c=this.complex(s,u);return s.dispose(),u.dispose(),c},t.prototype.makeComplexComponentTensorHandle=function(t,e){return{dataId:e.dataId,dtype:e.dtype,shape:t.shape}},t.prototype.addN=function(t){if(1===t.length)return t[0];if(t.length>f.get("WEBGL_MAX_TEXTURES_IN_SHADER")){var e=Math.floor(t.length/2),n=this.addN(t.slice(0,e)),r=this.addN(t.slice(e));return this.addN([n,r])}var i=t.map(function(t){return t.dtype}).reduce(function(t,e){return Et(t,e)}),a=t.map(function(t){return t.shape}),o=f.getBool("WEBGL_PACK"),s=o?new function(t,e){this.outputShape=[],this.usesPackedTextures=!0,this.outputShape=t,this.variableNames=e.map(function(t,e){return"T"+e});var n=[];this.variableNames.forEach(function(t){n.push("vec4 v"+t+" = get"+t+"AtOutCoords();")});var r=this.variableNames.map(function(t){return"v"+t}).join(" + ");this.userCode="\n void main() {\n "+n.join("\n ")+"\n\n vec4 result = "+r+";\n setOutput(result);\n }\n "}(t[0].shape,a):new function(t,e){this.outputShape=[],this.outputShape=t,this.variableNames=e.map(function(t,e){return"T"+e});var n=[];this.variableNames.forEach(function(t){n.push("float v"+t+" = get"+t+"AtOutCoords();")});var r=this.variableNames.map(function(t){return"v"+t}).join(" + ");this.userCode="\n void main() {\n "+n.join("\n ")+"\n\n float result = "+r+";\n setOutput(result);\n }\n "}(t[0].shape,a),u=o?this.makePackedTensor(s.outputShape,i):this.makeOutputArray(s.outputShape,i);return this.compileAndRun(s,t,u)},t.prototype.subtract=function(t,e){if("complex64"===t.dtype&&"complex64"===e.dtype)return this.complexSeparableBinaryOp(t,e,xi);if(this.shouldExecuteOnCPU([t,e]))return this.cpuBackend.subtract(t,e);var n=Et(t.dtype,e.dtype);if(f.getBool("WEBGL_PACK_BINARY_OPERATIONS"))return this.packedBinaryOp(t,e,xi,t.dtype);var r=new Si(xi,t.shape,e.shape),i=this.makeOutputArray(r.outputShape,n);return this.compileAndRun(r,[t,e],i)},t.prototype.pow=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS"),r=n?new _i("\n // isModRound1 has 1 for components with round(mod(b, 2.0)) == 1, 0 otherwise.\n vec4 isModRound1 = vec4(equal(round(mod(b, 2.0)), ivec4(1)));\n vec4 multiplier = sign(a) * isModRound1 + (vec4(1.0) - isModRound1);\n vec4 result = multiplier * pow(abs(a), b);\n\n vec4 isNaN = vec4(lessThan(a, vec4(0.0))) * vec4(lessThan(floor(b), b));\n \n result.r = isNaN.r > 0. ? NAN : result.r;\n result.g = isNaN.g > 0. ? NAN : result.g;\n result.b = isNaN.b > 0. ? NAN : result.b;\n result.a = isNaN.a > 0. ? NAN : result.a;\n\n return result;\n",t.shape,e.shape):new Si("\nif(a < 0.0 && floor(b) < b){\n return NAN;\n}\nreturn (round(mod(b, 2.0)) != 1) ?\n pow(abs(a), b) : sign(a) * pow(abs(a), b);\n",t.shape,e.shape),i=Et(t.dtype,e.dtype),a=n?this.makePackedTensor(r.outputShape,i):this.makeOutputArray(r.outputShape,i);return this.compileAndRun(r,[t,e],a)},t.prototype.ceil=function(t){var e=new ya(t.shape,"return ceil(x);");return this.compileAndRun(e,[t])},t.prototype.floor=function(t){var e=new ya(t.shape,"return floor(x);");return this.compileAndRun(e,[t])},t.prototype.sign=function(t){var e=new ya(t.shape,"\n if (isnan(x)) { return 0.0; }\n return sign(x);\n");return this.compileAndRun(e,[t])},t.prototype.isNaN=function(t){var e=new ya(t.shape,"return float(isnan(x));"),n=this.makeOutputArray(e.outputShape,"bool");return this.compileAndRun(e,[t],n)},t.prototype.isInf=function(t){var e=new ya(t.shape,"return float(isinf(x));"),n=this.makeOutputArray(e.outputShape,"bool");return this.compileAndRun(e,[t],n)},t.prototype.isFinite=function(t){var e=new ya(t.shape,"return float(!isnan(x) && !isinf(x));"),n=this.makeOutputArray(e.outputShape,"bool");return this.compileAndRun(e,[t],n)},t.prototype.round=function(t){var e=new ya(t.shape,"\n // OpenGL ES does not support round function.\n // The algorithm is based on banker's rounding.\n float base = floor(x);\n if ((x - base) < 0.5) {\n return floor(x);\n } else if ((x - base) > 0.5) {\n return ceil(x);\n } else {\n if (mod(base, 2.0) == 0.0) {\n return base;\n } else {\n return base + 1.0;\n }\n }\n");return this.compileAndRun(e,[t])},t.prototype.exp=function(t){var e;return e=f.getBool("WEBGL_PACK")?new _a(t.shape,ka):new ya(t.shape,ka),this.compileAndRun(e,[t])},t.prototype.expm1=function(t){var e=new ya(t.shape,"return exp(x) - 1.0;");return this.compileAndRun(e,[t])},t.prototype.log=function(t){var e;return e=f.getBool("WEBGL_PACK")?new _a(t.shape,"\n vec4 result = log(x);\n vec4 isNaN = vec4(lessThan(x, vec4(0.0)));\n result.r = isNaN.r == 1.0 ? NAN : result.r;\n result.g = isNaN.g == 1.0 ? NAN : result.g;\n result.b = isNaN.b == 1.0 ? NAN : result.b;\n result.a = isNaN.a == 1.0 ? NAN : result.a;\n\n return result;\n"):new ya(t.shape,"if (x < 0.0) return NAN;\n return log(x);"),this.compileAndRun(e,[t])},t.prototype.log1p=function(t){var e=new ya(t.shape,"return log(1.0 + x);");return this.compileAndRun(e,[t])},t.prototype.sqrt=function(t){var e=new ya(t.shape,"return sqrt(x);");return this.compileAndRun(e,[t])},t.prototype.rsqrt=function(t){if(this.shouldExecuteOnCPU([t]))return this.cpuBackend.rsqrt(t);var e=new ya(t.shape,"return inversesqrt(x);");return this.compileAndRun(e,[t])},t.prototype.square=function(t){var e=new ya(t.shape,"return x * x;");return this.compileAndRun(e,[t])},t.prototype.reciprocal=function(t){var e=new ya(t.shape,"return 1.0 / x;");return this.compileAndRun(e,[t])},t.prototype.relu=function(t){var e;return e=f.getBool("WEBGL_PACK")?new _a(t.shape,Sa):new ya(t.shape,xa),this.compileAndRun(e,[t])},t.prototype.prelu=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 aLessThanZero = vec4(lessThan(a, vec4(0.)));\n return (aLessThanZero * (b * a)) + ((vec4(1.0) - aLessThanZero) * a);\n",t.shape,e.shape):new Si("return (a < 0.) ? b * a : a;",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.elu=function(t){var e=new ya(t.shape,"return (x >= 0.0) ? x : (exp(x) - 1.0);");return this.compileAndRun(e,[t])},t.prototype.eluDer=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 bGTEZero = vec4(greaterThanEqual(b, vec4(0.)));\n return (bGTEZero * a) + ((vec4(1.0) - bGTEZero) * (a * (b + vec4(1.0))));\n",t.shape,e.shape):new Si("return (b >= 1.0) ? a : a * (b + 1.0);",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.selu=function(t){var e=new ya(t.shape,"\n // Stable and Attracting Fixed Point (0, 1) for Normalized Weights.\n // see: https://arxiv.org/abs/1706.02515\n float scaleAlpha = 1.7580993408473768;\n float scale = 1.0507009873554805;\n return (x >= 0.0) ? scale * x : scaleAlpha * (exp(x) - 1.0);\n");return this.compileAndRun(e,[t])},t.prototype.int=function(t){var e=new ya(t.shape,"return float(int(x));"),n=this.makeOutputArray(e.outputShape,"int32");return this.compileAndRun(e,[t],n)},t.prototype.clip=function(t,e,n){var r,i=(r=f.getBool("WEBGL_PACK_CLIP")?new Ci(t.shape):new Ei(t.shape)).getCustomSetupFunc(e,n);return this.compileAndRun(r,[t],null,i)},t.prototype.abs=function(t){var e=new ya(t.shape,"return abs(x);");return this.compileAndRun(e,[t])},t.prototype.complexAbs=function(t){var e=this.texData.get(t.dataId),n=new function(t){this.variableNames=["real","imag"],this.outputShape=t,this.userCode="\n void main() {\n float re = abs(getRealAtOutCoords());\n float im = abs(getImagAtOutCoords());\n float mx = max(re, im);\n\n // sadly the length function in glsl is not underflow-safe\n // (at least not on Intel GPUs). So the safe solution is\n // to ensure underflow-safety in all cases.\n setOutput(\n mx == 0.0 ? 0.0 : mx * length(vec2(1, min(re, im)/mx))\n );\n }\n "}(t.shape),r=[this.makeComplexComponentTensorHandle(t,e.complexTensors.real),this.makeComplexComponentTensorHandle(t,e.complexTensors.imag)];return this.compileAndRun(n,r)},t.prototype.sigmoid=function(t){var e=new ya(t.shape,"return 1.0 / (1.0 + exp(-1.0 * x));");return this.compileAndRun(e,[t])},t.prototype.softplus=function(t){var e=new ya(t.shape,"\n float epsilon = 1.1920928955078125e-7;\n float threshold = log(epsilon) + 2.0;\n\n bool too_large = x > -threshold;\n bool too_small = x < threshold;\n\n float result;\n float exp_x = exp(x);\n\n if (too_large){\n result = x;\n }\n else if (too_small){\n result = exp_x;\n }\n else{\n result = log(exp_x + 1.0);\n }\n return result;\n");return this.compileAndRun(e,[t])},t.prototype.sin=function(t){var e=new ya(t.shape,"if (isnan(x)) return x;\n return sin(x);\n");return this.compileAndRun(e,[t])},t.prototype.cos=function(t){var e=new ya(t.shape,"if (isnan(x)) return x;\n return cos(x);\n");return this.compileAndRun(e,[t])},t.prototype.tan=function(t){var e=new ya(t.shape,"return tan(x);");return this.compileAndRun(e,[t])},t.prototype.asin=function(t){var e=new ya(t.shape,"return asin(x);");return this.compileAndRun(e,[t])},t.prototype.acos=function(t){var e=new ya(t.shape,"return acos(x);");return this.compileAndRun(e,[t])},t.prototype.atan=function(t){var e=new ya(t.shape,"if (isnan(x)) return x;\n return atan(x);\n");return this.compileAndRun(e,[t])},t.prototype.atan2=function(t,e){var n=f.getBool("WEBGL_PACK_BINARY_OPERATIONS")?new _i("\n vec4 result = atan(a, b);\n vec4 isNaN = min(vec4(isnan(a)) + vec4(isnan(b)), vec4(1.0));\n \n result.r = isNaN.r > 0. ? NAN : result.r;\n result.g = isNaN.g > 0. ? NAN : result.g;\n result.b = isNaN.b > 0. ? NAN : result.b;\n result.a = isNaN.a > 0. ? NAN : result.a;\n\n return result;\n",t.shape,e.shape):new Si("\n if (isnan(a)) return a;\n if (isnan(b)) return b;\n\n return atan(a, b);\n",t.shape,e.shape);return this.compileAndRun(n,[t,e])},t.prototype.sinh=function(t){var e=new ya(t.shape,"\n float e2x = exp(x);\n return (e2x - 1.0 / e2x) / 2.0;\n");return this.compileAndRun(e,[t])},t.prototype.cosh=function(t){var e=new ya(t.shape,"\n float e2x = exp(-x);\n return (e2x + 1.0 / e2x) / 2.0;\n");return this.compileAndRun(e,[t])},t.prototype.tanh=function(t){var e=new ya(t.shape,"\n float e2x = exp(-2.0 * abs(x));\n return sign(x) * (1.0 - e2x) / (1.0 + e2x);\n");return this.compileAndRun(e,[t])},t.prototype.asinh=function(t){var e=new ya(t.shape,"return log(x + sqrt(x * x + 1.0));");return this.compileAndRun(e,[t])},t.prototype.acosh=function(t){var e=new ya(t.shape,"if (isnan(x)) return x;\n if (x < 1.0) return NAN;\n return log(x + sqrt(x * x - 1.0));");return this.compileAndRun(e,[t])},t.prototype.atanh=function(t){var e=new ya(t.shape,"if (isnan(x)) return x;\n if ((x < -1.0) || (x > 1.0)) return NAN;\n return (log(1.0 + x) - log(1.0 - x)) / 2.0;");return this.compileAndRun(e,[t])},t.prototype.erf=function(t){var e=new ya(t.shape,'\n // Error function is calculated approximately with elementary function.\n // See "Handbook of Mathematical Functions with Formulas,\n // Graphs, and Mathematical Tables", Abramowitz and Stegun.\n float p = 0.3275911;\n float a1 = 0.254829592;\n float a2 = -0.284496736;\n float a3 = 1.421413741;\n float a4 = -1.453152027;\n float a5 = 1.061405429;\n\n float t = 1.0 / (1.0 + p * x);\n return 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);\n');return this.compileAndRun(e,[t])},t.prototype.step=function(t,e){var n=new ya(t.shape,function(t){return void 0===t&&(t=0),wa+"\n return x > 0.0 ? 1.0 : float("+t+");\n "}(e));return this.compileAndRun(n,[t])},t.prototype.conv2dByMatMul=function(t,e,n){var r=t.shape,i=this.texData.get(t.dataId),a=n.inChannels,o=r[0]*r[1]*r[2],s=n.outChannels,u=(1===o||1===s)&&a>1e3,c=r[2]%2!=0&&!!i.isPacked;if(u||!f.getBool("WEBGL_LAZILY_UNPACK")||!f.getBool("WEBGL_PACK_BINARY_OPERATIONS")||!c){var l=this.reshape(t,[1,r[0]*r[1]*r[2],n.inChannels]),h=this.reshape(e,[1,n.inChannels,n.outChannels]);return this.reshape(this.batchMatMul(l,h,!1,!1),n.outShape)}var d=vt.make([1,r[0]*r[1]*(r[2]+1),n.inChannels],{dataId:t.dataId},t.dtype,this),p=i.shape;i.shape=i.shape.slice(),i.shape[i.shape.length-2]++,w(we(i.shape,d.shape),function(){return"packed reshape "+i.shape+" to "+d.shape+" isn't free"});var m=this.reshape(e,[1,n.inChannels,n.outChannels]),v=this.batchMatMul(d,m,!1,!1),g=this.texData.get(v.dataId);return w(g.isPacked,function(){return"batchMatMul result is expected to be packed"}),i.shape=p,g.shape=n.outShape,vt.make(n.outShape,{dataId:v.dataId},v.dtype,this)},t.prototype.conv2dWithIm2Row=function(t,e,n){var r=n.filterWidth,i=n.filterHeight,a=n.inChannels,o=n.outWidth,s=n.outHeight,u=r*i*a,c=s*o,l=[u,c],f=t.squeeze([0]),h=e.reshape([1,u,-1]),d=new function(t,e,n){this.variableNames=["A"],this.usesPackedTextures=!0,this.outputShape=t;var r=n.filterWidth,i=n.inChannels,a=n.strideWidth,o=n.strideHeight,s=n.padInfo,u=n.outWidth,c=n.dilationWidth,l=n.dilationHeight,f=s.left,h=s.top,d=i*r,p=si();this.userCode="\n void main() {\n ivec2 rc = getOutputCoords();\n\n vec4 result = vec4(0);\n\n for(int row=0; row<=1; row++) {\n for(int col=0; col<=1; col++) {\n int blockIndex = rc.y + col;\n int pos = rc.x + row;\n\n if(blockIndex >= "+t[1]+" || pos >= "+t[0]+") continue;\n\n int offsetY = int(blockIndex / ("+u+")) * "+o+" - "+h+";\n int d0 = offsetY + "+l+" * (pos / "+d+");\n\n if(d0 >= "+e[0]+" || d0 < 0) continue;\n\n int offsetX = int(mod(float(blockIndex), "+u+".) * "+a+". - "+f+".);\n int d1 = offsetX + "+c+" * (int(mod(float(pos), "+d+".) / "+i+".));\n\n if(d1 >= "+e[1]+" || d1 < 0) continue;\n\n vec2 innerDims = vec2(d1, int(mod(float(pos), "+i+".)));\n result[row * 2 + col] = getChannel(getA(d0, int(innerDims.x),\n int(innerDims.y)), innerDims);\n }\n }\n\n "+p.output+" = result;\n }\n "}(l,f.shape,n),p=this.compileAndRun(d,[f]).reshape([1,l[0],l[1]]),m=new ca(p.shape,[1,c,n.outChannels],!0,!1);return this.compileAndRun(m,[p,h]).reshape([1,s,o,n.outChannels])},t.prototype.conv2d=function(t,e,n){if(1===n.filterHeight&&1===n.filterWidth&&1===n.dilationHeight&&1===n.dilationWidth&&1===n.strideHeight&&1===n.strideWidth&&("SAME"===n.padInfo.type||"VALID"===n.padInfo.type))return this.conv2dByMatMul(t,e,n);if(f.getBool("WEBGL_CONV_IM2COL")&&1===t.shape[0])return this.conv2dWithIm2Row(t,e,n);var r=new function(t){this.variableNames=["x","W"],this.outputShape=t.outShape;var e=t.padInfo.top,n=t.padInfo.left,r=t.strideHeight,i=t.strideWidth,a=t.dilationHeight,o=t.dilationWidth,s=t.filterHeight,u=t.filterWidth,c=4*Math.floor(t.inChannels/4),l=t.inChannels%4;this.userCode="\n const ivec2 strides = ivec2("+r+", "+i+");\n const ivec2 pads = ivec2("+e+", "+n+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d2 = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // Convolve x(?, ?, d1) with w(:, :, d1, d2) to get y(yR, yC, d2).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < "+s+"; wR++) {\n int xR = xRCorner + wR * "+a+";\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int wC = 0; wC < "+u+"; wC++) {\n int xC = xCCorner + wC * "+o+";\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n for (int d1 = 0; d1 < "+c+"; d1 += 4) {\n vec4 xValues = vec4(\n getX(batch, xR, xC, d1),\n getX(batch, xR, xC, d1 + 1),\n getX(batch, xR, xC, d1 + 2),\n getX(batch, xR, xC, d1 + 3)\n );\n vec4 wValues = vec4(\n getW(wR, wC, d1, d2),\n getW(wR, wC, d1 + 1, d2),\n getW(wR, wC, d1 + 2, d2),\n getW(wR, wC, d1 + 3, d2)\n );\n\n dotProd += dot(xValues, wValues);\n }\n\n if ("+(1===l)+") {\n dotProd +=\n getX(batch, xR, xC, "+c+") *\n getW(wR, wC, "+c+", d2);\n } else if ("+(2===l)+") {\n vec2 xValues = vec2(\n getX(batch, xR, xC, "+c+"),\n getX(batch, xR, xC, "+c+" + 1)\n );\n vec2 wValues = vec2(\n getW(wR, wC, "+c+", d2),\n getW(wR, wC, "+c+" + 1, d2)\n );\n dotProd += dot(xValues, wValues);\n } else if ("+(3===l)+") {\n vec3 xValues = vec3(\n getX(batch, xR, xC, "+c+"),\n getX(batch, xR, xC, "+c+" + 1),\n getX(batch, xR, xC, "+c+" + 2)\n );\n vec3 wValues = vec3(\n getW(wR, wC, "+c+", d2),\n getW(wR, wC, "+c+" + 1, d2),\n getW(wR, wC, "+c+" + 2, d2)\n );\n dotProd += dot(xValues, wValues);\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.conv2dDerInput=function(t,e,n){var r=new function(t){this.variableNames=["dy","W"],this.outputShape=t.inShape;var e=t.filterHeight,n=t.filterWidth,r=t.strideHeight,i=t.strideWidth,a=e-1-t.padInfo.top,o=n-1-t.padInfo.left;this.userCode="\n const ivec2 pads = ivec2("+a+", "+o+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d1 = coords[3];\n\n ivec2 dyCorner = coords.yz - pads;\n int dyRCorner = dyCorner.x;\n int dyCCorner = dyCorner.y;\n\n // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < "+e+"; wR++) {\n float dyR = float(dyRCorner + wR) / "+r+".0;\n\n if (dyR < 0.0 || dyR >= "+t.outHeight+".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n int wRPerm = "+e+" - 1 - wR;\n\n for (int wC = 0; wC < "+n+"; wC++) {\n float dyC = float(dyCCorner + wC) / "+i+".0;\n\n if (dyC < 0.0 || dyC >= "+t.outWidth+".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n int wCPerm = "+n+" - 1 - wC;\n\n for (int d2 = 0; d2 < "+t.outChannels+"; d2++) {\n float xValue = getDy(batch, idyR, idyC, d2);\n float wValue = getW(wRPerm, wCPerm, d1, d2);\n dotProd += xValue * wValue;\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.conv2dDerFilter=function(t,e,n){var r=new function(t){this.variableNames=["x","dy"],this.outputShape=t.filterShape;var e=t.strideHeight,n=t.strideWidth,r=t.padInfo.top,i=t.padInfo.left;this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int wR = coords.x;\n int wC = coords.y;\n int d1 = coords.z;\n int d2 = coords.w;\n\n // Convolve x(?, ?, d1) with dy(:, :, d2) to get dw(wR, wC, d1, d2).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n\n for (int b = 0; b < "+t.batchSize+"; b++) {\n for (int yR = 0; yR < "+t.outHeight+"; yR++) {\n int xR = wR + yR * "+e+" - "+r+";\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int yC = 0; yC < "+t.outWidth+"; yC++) {\n int xC = wC + yC * "+n+" - "+i+";\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n float dyValue = getDy(b, yR, yC, d2);\n float xValue = getX(b, xR, xC, d1);\n dotProd += (xValue * dyValue);\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.depthwiseConv2D=function(t,e,n){var r;return f.getBool("WEBGL_PACK_DEPTHWISECONV")&&n.strideWidth<=2&&n.outChannels/n.inChannels==1?(r=new function(t){this.variableNames=["x","W"],this.usesPackedTextures=!0,this.outputShape=t.outShape;for(var e=t.inHeight,n=t.inWidth,r=t.padInfo.top,i=t.padInfo.left,a=t.strideHeight,o=t.strideWidth,s=t.dilationHeight,u=t.dilationWidth,c=t.filterHeight,l=t.filterWidth,f=l,h="int xR; int xC; int xCOffset;",d=0;d= 0 && xR < "+e+" && xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+p+" = getX(batch, xR, xCOffset, d1);\n } else {\n xTexelR"+d+"C"+p+" = vec4(0.);\n }\n\n xCOffset = xC + 1 - 2;\n if(xR >= 0 && xR < "+e+" && xCOffset >= 0 && xCOffset < "+n+") {\n vec4 previous = getX(batch, xR, xCOffset, d1);\n xR"+d+"C"+p+" = vec4(previous.zw, xTexelR"+d+"C"+p+".xy);\n } else {\n xR"+d+"C"+p+" = vec4(0, 0, xTexelR"+d+"C"+p+".xy);\n }\n ":"\n if(xR >= 0 && xR < "+e+" && xC >= 0 && xC < "+n+") {\n xTexelR"+d+"C"+p+" = getX(batch, xR, xC, d1);\n } else {\n xTexelR"+d+"C"+p+" = vec4(0.);\n }\n\n xR"+d+"C"+p+" = xTexelR"+d+"C"+p+";\n ",p+1= 0 && xR < "+e+" &&\n xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+(p+2)+" = getX(batch, xR, xCOffset, d1);\n }\n ",u>1&&(h+="\n xCOffset -= 2;\n if(xR >= 0 && xR < "+e+" &&\n xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+p+" = getX(batch, xR, xCOffset, d1);\n } else {\n xTexelR"+d+"C"+p+" = vec4(0.);\n }\n "),h+="\n xR"+d+"C"+(p+1)+" = vec4(\n xTexelR"+d+"C"+p+".zw, xTexelR"+d+"C"+(p+2)+".xy);\n "):h+="\n xCOffset = xC + "+v+";\n\n if(xR >= 0 && xR < "+e+" &&\n xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+(p+2)+" = getX(batch, xR, xCOffset, d1);\n }\n\n xR"+d+"C"+(p+1)+" = xTexelR"+d+"C"+(p+2)+";\n "}}else p= 0 && xR < "+e+") {\n ",i%2==1?(h+="\n xCOffset = xC + 1 - "+o+";\n if(xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+p+" = getX(batch, xR, xCOffset, d1);\n } else {\n xTexelR"+d+"C"+p+" = vec4(0.);\n }\n\n if(xC + 1 >= 0 && xC + 1 < "+n+") {\n xTexelR"+d+"C"+(p+2)+" = getX(batch, xR, xC + 1, d1);\n } else {\n xTexelR"+d+"C"+(p+2)+" = vec4(0.);\n }\n\n xR"+d+"C"+p+" = vec4(\n xTexelR"+d+"C"+p+".zw, xTexelR"+d+"C"+(p+2)+".zw);\n ",p+1= 0 && xCOffset < "+n+") {\n final = getX(batch, xR, xCOffset, d1);\n }\n xR"+d+"C"+(p+1)+" = vec4(xTexelR"+d+"C"+(p+2)+".xy, final.xy);\n ")):(h+="\n if(xC >= 0 && xC < "+n+") {\n xTexelR"+d+"C"+p+" = getX(batch, xR, xC, d1);\n } else {\n xTexelR"+d+"C"+p+" = vec4(0.);\n }\n\n xCOffset = xC + "+o+";\n if(xCOffset >= 0 && xCOffset < "+n+") {\n xTexelR"+d+"C"+(p+2)+" = getX(batch, xR, xCOffset, d1);\n } else {\n xTexelR"+d+"C"+(p+2)+" = vec4(0.);\n }\n\n xR"+d+"C"+p+" = vec4(\n xTexelR"+d+"C"+p+".xy, xTexelR"+d+"C"+(p+2)+".xy);\n ",p+1= "+e+") {\n continue;\n }\n\n for (int wC = 0; wC < "+l+"; wC++) {\n int xC = xCCorner + wC * "+u+";\n\n if (xC < 0 || xC >= "+n+") {\n continue;\n }\n\n float xVal = getX(batch, xR, xC, d1);\n float wVal = getW(wR, wC, d1, q);\n dotProd += xVal * wVal;\n }\n }\n setOutput(dotProd);\n }\n "}(n),this.compileAndRun(r,[t,e]))},t.prototype.depthwiseConv2DDerInput=function(t,e,n){var r=new function(t){this.variableNames=["dy","W"],this.outputShape=t.inShape;var e=t.filterHeight,n=t.filterWidth,r=t.strideHeight,i=t.strideWidth,a=e-1-t.padInfo.top,o=n-1-t.padInfo.left,s=t.outChannels/t.inChannels;this.userCode="\n const ivec2 pads = ivec2("+a+", "+o+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d1 = coords[3];\n ivec2 dyCorner = coords.yz - pads;\n int dyRCorner = dyCorner.x;\n int dyCCorner = dyCorner.y;\n\n float dotProd = 0.0;\n\n for (int wR = 0; wR < "+e+"; wR++) {\n float dyR = float(dyRCorner + wR) / "+r+".0;\n\n if (dyR < 0.0 || dyR >= "+t.outHeight+".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n int wRPerm = "+e+" - 1 - wR;\n\n for (int wC = 0; wC < "+n+"; wC++) {\n float dyC = float(dyCCorner + wC) / "+i+".0;\n\n if (dyC < 0.0 || dyC >= "+t.outWidth+".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n int wCPerm = "+n+" - 1 - wC;\n\n // TODO: Vec4 over the channelMul\n for (int dm = 0; dm < "+s+"; dm++) {\n int d2 = d1 * "+s+" + dm;\n float xValue = getDy(batch, idyR, idyC, d2);\n float wValue = getW(wRPerm, wCPerm, d1, dm);\n dotProd += xValue * wValue;\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.depthwiseConv2DDerFilter=function(t,e,n){var r=new function(t){this.variableNames=["x","dy"],this.outputShape=t.filterShape;var e=t.strideHeight,n=t.strideWidth,r=t.padInfo.top,i=t.padInfo.left,a=t.outChannels/t.inChannels;this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int wR = coords.x;\n int wC = coords.y;\n int d1 = coords.z;\n int dm = coords.w;\n int d2 = d1 * "+a+" + dm;\n\n float dotProd = 0.0;\n\n // TODO: Vec4 over the batch size\n for (int b = 0; b < "+t.batchSize+"; b++) {\n for (int yR = 0; yR < "+t.outHeight+"; yR++) {\n int xR = wR + yR * "+e+" - "+r+";\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int yC = 0; yC < "+t.outWidth+"; yC++) {\n int xC = wC + yC * "+n+" - "+i+";\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n float dyValue = getDy(b, yR, yC, d2);\n float xValue = getX(b, xR, xC, d1);\n dotProd += (xValue * dyValue);\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.conv3d=function(t,e,n){var r=new function(t){this.variableNames=["x","W"],this.outputShape=t.outShape;var e=t.padInfo.front,n=t.padInfo.top,r=t.padInfo.left,i=t.strideDepth,a=t.strideHeight,o=t.strideWidth,s=t.dilationDepth,u=t.dilationHeight,c=t.dilationWidth,l=t.filterDepth,f=t.filterHeight,h=t.filterWidth,d=4*Math.floor(t.inChannels/4),p=t.inChannels%4;this.userCode="\n const ivec3 strides = ivec3("+i+", "+a+", "+o+");\n const ivec3 pads = ivec3("+e+", "+n+", "+r+");\n\n void main() {\n ivec5 coords = getOutputCoords();\n int batch = coords.x;\n int d2 = coords.u;\n\n ivec3 xFRCCorner = ivec3(coords.y, coords.z, coords.w) * strides - pads;\n int xFCorner = xFRCCorner.x;\n int xRCorner = xFRCCorner.y;\n int xCCorner = xFRCCorner.z;\n\n // Convolve x(?, ?, ?, d1) with w(:, :, :, d1, d2) to get\n // y(yF, yR, yC, d2). ? = to be determined. : = across all\n // values in that axis.\n float dotProd = 0.0;\n for (int wF = 0; wF < "+l+"; wF++) {\n int xF = xFCorner + wF * "+s+";\n\n if (xF < 0 || xF >= "+t.inDepth+") {\n continue;\n }\n\n for (int wR = 0; wR < "+f+"; wR++) {\n int xR = xRCorner + wR * "+u+";\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int wC = 0; wC < "+h+"; wC++) {\n int xC = xCCorner + wC * "+c+";\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n for (int d1 = 0; d1 < "+d+"; d1 += 4) {\n vec4 xValues = vec4(\n getX(batch, xF, xR, xC, d1),\n getX(batch, xF, xR, xC, d1 + 1),\n getX(batch, xF, xR, xC, d1 + 2),\n getX(batch, xF, xR, xC, d1 + 3)\n );\n vec4 wValues = vec4(\n getW(wF, wR, wC, d1, d2),\n getW(wF, wR, wC, d1 + 1, d2),\n getW(wF, wR, wC, d1 + 2, d2),\n getW(wF, wR, wC, d1 + 3, d2)\n );\n\n dotProd += dot(xValues, wValues);\n }\n\n if ("+(1===p)+") {\n dotProd +=\n getX(batch, xF, xR, xC, "+d+") *\n getW(wF, wR, wC, "+d+", d2);\n } else if ("+(2===p)+") {\n vec2 xValues = vec2(\n getX(batch, xF, xR, xC, "+d+"),\n getX(batch, xF, xR, xC, "+d+" + 1)\n );\n vec2 wValues = vec2(\n getW(wF, wR, wC, "+d+", d2),\n getW(wF, wR, wC, "+d+" + 1, d2)\n );\n dotProd += dot(xValues, wValues);\n } else if ("+(3===p)+") {\n vec3 xValues = vec3(\n getX(batch, xF, xR, xC, "+d+"),\n getX(batch, xF, xR, xC, "+d+" + 1),\n getX(batch, xF, xR, xC, "+d+" + 2)\n );\n vec3 wValues = vec3(\n getW(wF, wR, wC, "+d+", d2),\n getW(wF, wR, wC, "+d+" + 1, d2),\n getW(wF, wR, wC, "+d+" + 2, d2)\n );\n dotProd += dot(xValues, wValues);\n }\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.conv3dDerInput=function(t,e,n){var r=new function(t){this.variableNames=["dy","W"],this.outputShape=t.inShape;var e=t.filterDepth,n=t.filterHeight,r=t.filterWidth,i=t.strideDepth,a=t.strideHeight,o=t.strideWidth,s=e-1-t.padInfo.front,u=n-1-t.padInfo.top,c=r-1-t.padInfo.left;this.userCode="\n const ivec3 pads = ivec3("+s+", "+u+", "+c+");\n\n void main() {\n ivec5 coords = getOutputCoords();\n int batch = coords.x;\n int d1 = coords.u;\n\n\n ivec3 dyCorner = ivec3(coords.y, coords.z, coords.w) - pads;\n int dyFCorner = dyCorner.x;\n int dyRCorner = dyCorner.y;\n int dyCCorner = dyCorner.z;\n\n float dotProd = 0.0;\n for (int wF = 0; wF < "+e+"; wF++) {\n float dyF = float(dyFCorner + wF) / "+i+".0;\n\n if (dyF < 0.0 || dyF >= "+t.outDepth+".0 || fract(dyF) > 0.0) {\n continue;\n }\n int idyF = int(dyF);\n\n int wFPerm = "+e+" - 1 - wF;\n\n for (int wR = 0; wR < "+n+"; wR++) {\n float dyR = float(dyRCorner + wR) / "+a+".0;\n\n if (dyR < 0.0 || dyR >= "+t.outHeight+".0 ||\n fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n int wRPerm = "+n+" - 1 - wR;\n\n for (int wC = 0; wC < "+r+"; wC++) {\n float dyC = float(dyCCorner + wC) / "+o+".0;\n\n if (dyC < 0.0 || dyC >= "+t.outWidth+".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n int wCPerm = "+r+" - 1 - wC;\n\n for (int d2 = 0; d2 < "+t.outChannels+"; d2++) {\n float xValue = getDy(batch, idyF, idyR, idyC, d2);\n float wValue = getW(wFPerm, wRPerm, wCPerm, d1, d2);\n dotProd += xValue * wValue;\n }\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.conv3dDerFilter=function(t,e,n){var r=new function(t){this.variableNames=["x","dy"],this.outputShape=t.filterShape;var e=t.strideDepth,n=t.strideHeight,r=t.strideWidth,i=t.padInfo.front,a=t.padInfo.top,o=t.padInfo.left;this.userCode="\n void main() {\n ivec5 coords = getOutputCoords();\n int wF = coords.x;\n int wR = coords.y;\n int wC = coords.z;\n int d1 = coords.w;\n int d2 = coords.u;\n\n float dotProd = 0.0;\n\n for (int b = 0; b < "+t.batchSize+"; b++) {\n for (int yF = 0; yF < "+t.outDepth+"; yF++) {\n int xF = wF + yF * "+e+" - "+i+";\n\n if (xF < 0 || xF >= "+t.inDepth+") {\n continue;\n }\n\n for (int yR = 0; yR < "+t.outHeight+"; yR++) {\n int xR = wR + yR * "+n+" - "+a+";\n\n if (xR < 0 || xR >= "+t.inHeight+") {\n continue;\n }\n\n for (int yC = 0; yC < "+t.outWidth+"; yC++) {\n int xC = wC + yC * "+r+" - "+o+";\n\n if (xC < 0 || xC >= "+t.inWidth+") {\n continue;\n }\n\n float dyValue = getDy(b, yF, yR, yC, d2);\n float xValue = getX(b, xF, xR, xC, d1);\n dotProd += (xValue * dyValue);\n }\n }\n }\n }\n setOutput(dotProd);\n }\n "}(n);return this.compileAndRun(r,[t,e])},t.prototype.maxPool=function(t,e){var n=new fa(e,"max",!1),r=this.makeOutputArray(n.outputShape,t.dtype);return this.compileAndRun(n,[t],r)},t.prototype.avgPool=function(t,e){var n=new fa(e,"avg",!1),r=this.makeOutputArray(n.outputShape,"float32");return this.compileAndRun(n,[t],r)},t.prototype.maxPoolBackprop=function(t,e,n,r){var i=new fa(r,"max",!0),a=this.compileAndRun(i,[e]),o=new function(t){this.variableNames=["dy","maxPos"],this.outputShape=t.inShape;var e=t.strideHeight,n=t.strideWidth,r=t.dilationHeight,i=t.effectiveFilterHeight,a=t.effectiveFilterWidth,o=i-1-t.padInfo.top,s=a-1-t.padInfo.left,u=i*a-1;this.userCode="\n const ivec2 pads = ivec2("+o+", "+s+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n\n ivec2 dyRCCorner = coords.yz - pads;\n int dyRCorner = dyRCCorner.x;\n int dyCCorner = dyRCCorner.y;\n\n // Convolve dy(?, ?, d) with pos mask(:, :, d) to get dx(xR, xC, d).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < "+i+";\n wR += "+r+") {\n float dyR = float(dyRCorner + wR) / "+e+".0;\n\n if (dyR < 0.0 || dyR >= "+t.outHeight+".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n for (int wC = 0; wC < "+a+"; wC++) {\n float dyC = float(dyCCorner + wC) / "+n+".0;\n\n if (dyC < 0.0 || dyC >= "+t.outWidth+".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n float dyValue = getDy(b, idyR, idyC, d);\n int maxPosValue = "+u+" - int(getMaxPos(b, idyR, idyC, d));\n\n // Get the current value, check it against the value from the\n // position matrix.\n int curPosValue = wR * "+a+" + wC;\n float mask = float(maxPosValue == curPosValue ? 1.0 : 0.0);\n\n dotProd += dyValue * mask;\n }\n }\n setOutput(dotProd);\n }\n "}(r),s=this.makeOutputArray(o.outputShape,e.dtype),u=this.compileAndRun(o,[t,a],s);return a.dispose(),u},t.prototype.avgPoolBackprop=function(t,e,n){var r=new function(t){this.variableNames=["dy"],this.outputShape=t.inShape;var e=t.filterHeight,n=t.filterWidth,r=t.strideHeight,i=t.strideWidth,a=t.dilationHeight,o=t.dilationWidth,s=t.effectiveFilterHeight,u=t.effectiveFilterWidth,c=s-1-t.padInfo.top,l=u-1-t.padInfo.left,f=1/(e*n);this.userCode="\n const ivec2 pads = ivec2("+c+", "+l+");\n const float avgMultiplier = float("+f+");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n\n ivec2 dyRCCorner = coords.yz - pads;\n int dyRCorner = dyRCCorner.x;\n int dyCCorner = dyRCCorner.y;\n\n // Convolve dy(?, ?, d) with pos mask(:, :, d) to get dx(xR, xC, d).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < "+s+";\n wR += "+a+") {\n float dyR = float(dyRCorner + wR) / "+r+".0;\n\n if (dyR < 0.0 || dyR >= "+t.outHeight+".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n for (int wC = 0; wC < "+u+";\n wC+= "+o+") {\n float dyC = float(dyCCorner + wC) / "+i+".0;\n\n if (dyC < 0.0 || dyC >= "+t.outWidth+".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n float dyValue = getDy(b, idyR, idyC, d);\n\n dotProd += dyValue * avgMultiplier;\n }\n }\n setOutput(dotProd);\n }\n "}(n),i=this.makeOutputArray(r.outputShape,e.dtype);return this.compileAndRun(r,[t],i)},t.prototype.cast=function(t,e){return tr(t,e,this)},t.prototype.unstack=function(t,e){for(var n=t.shape[e],r=new Array(t.rank-1),i=0,a=0;a1?a-1:a,r&&n>1?o-1:o],c=[r&&e>1?e-1:e,r&&n>1?n-1:n];this.userCode="\n const vec3 effectiveInputOverOutputRatioRC = vec3(\n "+u[0]/c[0]+",\n "+u[1]/c[1]+",\n "+u[1]/c[1]+");\n const vec3 inputShapeRC = vec3("+a+".0, "+o+".0,\n "+o+".0);\n\n float getAValue(int b, int r, int c, int d) {\n return getChannel(getA(b, r, c, d), vec2(c, d));\n }\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n // Calculate values for next column in yRC.z.\n ivec3 yRC = coords.yzz + ivec3(0, 0, 1);\n\n // Fractional source index.\n vec3 sourceFracIndexRC = vec3(yRC) * effectiveInputOverOutputRatioRC;\n\n // Compute the four integer indices.\n ivec3 sourceFloorRC = ivec3(sourceFracIndexRC);\n ivec3 sourceCeilRC = ivec3(\n min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));\n \n // Should we calculate next column and row elements in 2x2 packed cell.\n bool hasNextCol = d < "+(s-1)+"; \n bool hasNextRow = coords.z < "+(n-1)+";\n\n // In parallel, construct four corners for all four components in\n // packed 2x2 cell.\n vec4 topLeft = vec4(\n getAValue(b, sourceFloorRC.x, sourceFloorRC.y, d),\n hasNextCol ? getAValue(b, sourceFloorRC.x, sourceFloorRC.y, d + 1)\n : 0.0,\n hasNextRow ? getAValue(b, sourceFloorRC.x, sourceFloorRC.z, d)\n : 0.0,\n (hasNextRow && hasNextCol) ?\n getAValue(b, sourceFloorRC.x, sourceFloorRC.z, d + 1) : 0.0);\n\n vec4 bottomLeft = vec4(\n getAValue(b, sourceCeilRC.x, sourceFloorRC.y, d),\n hasNextCol ? getAValue(b, sourceCeilRC.x, sourceFloorRC.y, d + 1)\n : 0.0,\n hasNextRow ? getAValue(b, sourceCeilRC.x, sourceFloorRC.z, d)\n : 0.0,\n (hasNextRow && hasNextCol) ?\n getAValue(b, sourceCeilRC.x, sourceFloorRC.z, d + 1) : 0.0);\n\n vec4 topRight = vec4(\n getAValue(b, sourceFloorRC.x, sourceCeilRC.y, d),\n hasNextCol ? getAValue(b, sourceFloorRC.x, sourceCeilRC.y, d + 1)\n : 0.0,\n hasNextRow ? getAValue(b, sourceFloorRC.x, sourceCeilRC.z, d)\n : 0.0,\n (hasNextRow && hasNextCol) ?\n getAValue(b, sourceFloorRC.x, sourceCeilRC.z, d + 1) : 0.0);\n\n vec4 bottomRight = vec4(\n getAValue(b, sourceCeilRC.x, sourceCeilRC.y, d),\n hasNextCol ? getAValue(b, sourceCeilRC.x, sourceCeilRC.y, d + 1)\n : 0.0,\n hasNextRow ? getAValue(b, sourceCeilRC.x, sourceCeilRC.z, d)\n : 0.0,\n (hasNextRow && hasNextCol) ?\n getAValue(b, sourceCeilRC.x, sourceCeilRC.z, d + 1) : 0.0);\n\n vec3 fracRC = sourceFracIndexRC - vec3(sourceFloorRC);\n\n vec4 top = mix(topLeft, topRight, fracRC.yyzz);\n vec4 bottom = mix(bottomLeft, bottomRight, fracRC.yyzz);\n vec4 newValue = mix(top, bottom, fracRC.x);\n\n setOutput(newValue);\n }\n "}(t.shape,e,n,r):new function(t,e,n,r){this.variableNames=["A"],this.outputShape=[];var i=t[0],a=t[1],o=t[2],s=t[3];this.outputShape=[i,e,n,s];var u=[r&&e>1?a-1:a,r&&n>1?o-1:o],c=[r&&e>1?e-1:e,r&&n>1?n-1:n];this.userCode="\n const vec2 effectiveInputOverOutputRatioRC = vec2(\n "+u[0]/c[0]+",\n "+u[1]/c[1]+");\n const vec2 inputShapeRC = vec2("+a+".0, "+o+".0);\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n ivec2 yRC = coords.yz;\n\n // Fractional source index.\n vec2 sourceFracIndexRC = vec2(yRC) * effectiveInputOverOutputRatioRC;\n\n // Compute the four integer indices.\n ivec2 sourceFloorRC = ivec2(sourceFracIndexRC);\n ivec2 sourceCeilRC = ivec2(\n min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));\n\n float topLeft = getA(b, sourceFloorRC.x, sourceFloorRC.y, d);\n float bottomLeft = getA(b, sourceCeilRC.x, sourceFloorRC.y, d);\n float topRight = getA(b, sourceFloorRC.x, sourceCeilRC.y, d);\n float bottomRight = getA(b, sourceCeilRC.x, sourceCeilRC.y, d);\n\n vec2 fracRC = sourceFracIndexRC - vec2(sourceFloorRC);\n\n float top = topLeft + (topRight - topLeft) * fracRC.y;\n float bottom = bottomLeft + (bottomRight - bottomLeft) * fracRC.y;\n float newValue = top + (bottom - top) * fracRC.x;\n\n setOutput(newValue);\n }\n "}(t.shape,e,n,r);return this.compileAndRun(i,[t])},t.prototype.resizeBilinearBackprop=function(t,e,n){var r=new function(t,e,n){this.variableNames=["dy"],this.outputShape=[],this.outputShape=e.shape;var r=e.shape,i=r[1],a=r[2],o=t.shape,s=o[1],u=o[2],c=[n&&s>1?i-1:i,n&&u>1?a-1:a],l=[n&&s>1?s-1:s,n&&u>1?u-1:u],f=c[0]/l[0],h=c[1]/l[1],d=1/f,p=1/h,m=2*Math.ceil(d)+2,v=2*Math.ceil(p)+2;this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n int r = coords[1];\n int c = coords[2];\n\n float accumulator = 0.0;\n\n const float heightScale = float("+f+");\n const float widthScale = float("+h+");\n\n const float invHeightScale = float("+d+");\n const float invWidthScale = float("+p+");\n\n const int winHeight = int("+m+");\n const int winWidth = int("+v+");\n\n // Compute bounds for where in dy we will look\n float startRLerp = floor(float(r) * invHeightScale);\n int startDyR = int(startRLerp - float(winHeight / 2));\n\n float startCLerp = floor(float(c) * invWidthScale);\n int startDyC = int(startCLerp - float(winWidth / 2));\n\n // Loop over dy\n for (int dyROffset = 0; dyROffset < winHeight; dyROffset++) {\n int dyR = dyROffset + startDyR;\n\n // Guard against the window exceeding the bounds of dy\n if (dyR < 0 || dyR >= "+s+") {\n continue;\n }\n\n for (int dyCOffset = 0; dyCOffset < winWidth; dyCOffset++) {\n int dyC = dyCOffset + startDyC;\n\n // Guard against the window exceeding the bounds of dy\n if (dyC < 0 || dyC >= "+u+") {\n continue;\n }\n\n float dxR = float(dyR) * heightScale;\n int topDxRIndex = int(floor(dxR));\n int bottomDxRIndex = int(min(ceil(dxR), "+(i-1)+".0));\n float dxRLerp = dxR - float(topDxRIndex);\n float inverseDxRLerp = 1.0 - dxRLerp;\n\n float dxC = float(dyC) * widthScale;\n int leftDxCIndex = int(floor(dxC));\n int rightDxCIndex = int(min(ceil(dxC), "+(a-1)+".0));\n float dxCLerp = dxC - float(leftDxCIndex);\n float inverseDxCLerp = 1.0 - dxCLerp;\n\n if (r == topDxRIndex && c == leftDxCIndex) {\n // topLeft\n accumulator +=\n getDy(b, dyR, dyC, d) * inverseDxRLerp * inverseDxCLerp;\n }\n\n if (r == topDxRIndex && c == rightDxCIndex) {\n // topRight\n accumulator += getDy(b, dyR, dyC, d) * inverseDxRLerp * dxCLerp;\n }\n\n if (r == bottomDxRIndex && c == leftDxCIndex) {\n // bottomLeft\n accumulator += getDy(b, dyR, dyC, d) * dxRLerp * inverseDxCLerp;\n }\n\n if (r == bottomDxRIndex && c == rightDxCIndex) {\n // bottomRight\n accumulator += getDy(b, dyR, dyC, d) * dxRLerp * dxCLerp;\n }\n }\n }\n // End loop over dy\n\n setOutput(accumulator);\n }\n "}(t,e,n);return this.compileAndRun(r,[t])},t.prototype.resizeNearestNeighbor=function(t,e,n,r){var i=new function(t,e,n,r){this.variableNames=["A"],this.outputShape=[];var i=t[0],a=t[1],o=t[2],s=t[3];this.outputShape=[i,e,n,s];var u=[r&&e>1?a-1:a,r&&n>1?o-1:o],c=[r&&e>1?e-1:e,r&&n>1?n-1:n],l=r?"0.5":"0.0";this.userCode="\n const vec2 effectiveInputOverOutputRatioRC = vec2(\n "+u[0]/c[0]+",\n "+u[1]/c[1]+");\n const vec2 inputShapeRC = vec2("+a+".0, "+o+".0);\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n ivec2 yRC = coords.yz;\n\n // Fractional source index.\n vec2 sourceFracIndexRC = vec2(yRC) * effectiveInputOverOutputRatioRC;\n\n // Compute the coordinators of nearest neighbor point.\n ivec2 sourceNearestRC = ivec2(\n min(inputShapeRC - 1.0, floor(sourceFracIndexRC + "+l+")));\n\n float newValue = getA(b, sourceNearestRC.x, sourceNearestRC.y, d);\n\n setOutput(newValue);\n }\n "}(t.shape,e,n,r);return this.compileAndRun(i,[t])},t.prototype.resizeNearestNeighborBackprop=function(t,e,n){var r=new function(t,e,n){this.variableNames=["dy"],this.outputShape=[],this.outputShape=e.shape;var r=e.shape,i=r[1],a=r[2],o=t.shape,s=o[1],u=o[2],c=[n&&s>1?i-1:i,n&&u>1?a-1:a],l=[n&&s>1?s-1:s,n&&u>1?u-1:u],f=c[0]/l[0],h=c[1]/l[1],d=1/f,p=1/h,m=2*Math.ceil(d)+2,v=2*Math.ceil(p)+2;this.userCode="\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n int r = coords[1];\n int c = coords[2];\n\n float accumulator = 0.0;\n\n const float heightScale = float("+f+");\n const float widthScale = float("+h+");\n\n const float invHeightScale = float("+d+");\n const float invWidthScale = float("+p+");\n\n const int winHeight = int("+m+");\n const int winWidth = int("+v+");\n\n // Compute bounds for where in dy we will look\n float startRLerp = floor(float(r) * invHeightScale);\n int startDyR = int(floor(startRLerp - float(winHeight / 2)));\n\n float startCLerp = floor(float(c) * invWidthScale);\n int startDyC = int(floor(startCLerp - float(winWidth / 2)));\n\n // Loop over dy\n for (int dyROffset = 0; dyROffset < winHeight; dyROffset++) {\n int dyR = dyROffset + startDyR;\n\n // Guard against the window exceeding the bounds of dy\n if (dyR < 0 || dyR >= "+s+") {\n continue;\n }\n\n for (int dyCOffset = 0; dyCOffset < winWidth; dyCOffset++) {\n int dyC = dyCOffset + startDyC;\n\n // Guard against the window exceeding the bounds of dy\n if (dyC < 0 || dyC >= "+u+") {\n continue;\n }\n\n float sourceFracRow =\n float("+c[0]+") *\n (float(dyR) / float("+l[0]+"));\n\n float sourceFracCol =\n float("+c[1]+") *\n (float(dyC) / float("+l[1]+"));\n\n int sourceNearestRow = int(min(\n float(int("+i+") - 1),\n "+n+" ? float(round(sourceFracRow)) :\n float(floor(sourceFracRow))));\n\n int sourceNearestCol = int(min(\n float(int("+a+") - 1),\n "+n+" ? float(round(sourceFracCol)) :\n float(floor(sourceFracCol))));\n\n if (r == sourceNearestRow && c == sourceNearestCol) {\n accumulator += getDy(b, dyR, dyC, d);\n }\n }\n }\n // End loop over dy\n\n setOutput(accumulator);\n }\n "}(t,e,n);return this.compileAndRun(r,[t])},t.prototype.multinomial=function(t,e,n,r){var i=e?t:Mn(t),a=i.shape[0],o=i.shape[1],s=new la(a,o,n),u=this.makeOutputArray(s.outputShape,"int32"),c=s.getCustomSetupFunc(r);return this.compileAndRun(s,[i],u,c)},t.prototype.oneHot=function(t,e,n,r){var i=new function(t,e,n,r){this.variableNames=["indices"],this.outputShape=[t,e],this.userCode="\n void main() {\n ivec2 coords = getOutputCoords();\n int index = round(getIndices(coords.x));\n setOutput(mix(float("+r+"), float("+n+"),\n float(index == coords.y)));\n }\n "}(t.size,e,n,r);return this.compileAndRun(i,[t])},t.prototype.nonMaxSuppression=function(t,e,n,r,i){return Ye("tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead"),sr(t.dataSync(),e.dataSync(),n,r,i)},t.prototype.cropAndResize=function(t,e,n,r,i,a){var o=new function(t,e,n,r,i){this.variableNames=["Image","Boxes","BoxInd"],this.outputShape=[];var a=t[0],o=t[1],s=t[2],u=t[3],c=e[0],l=n[0],f=n[1];this.outputShape=[c,l,f,u];var h="bilinear"===r?1:0,d=[o-1+".0",s-1+".0"],p=d[0],m=d[1],v=l>1?[""+(o-1)/(l-1),"(y2-y1) * height_ratio","y1*"+p+" + float(y)*(height_scale)"]:["0.0","0.0","0.5 * (y1+y2) * "+p],g=v[0],b=v[1],y=v[2],w=f>1?[""+(s-1)/(f-1),"(x2-x1) * width_ratio","x1*"+m+" + float(x)*(width_scale)"]:["0.0","0.0","0.5 * (x1+x2) * "+m],x=w[0],k=w[1],S=w[2];this.userCode="\n const float height_ratio = float("+g+");\n const float width_ratio = float("+x+");\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int y = coords[1];\n int x = coords[2];\n int d = coords[3];\n\n // get box vals\n float y1 = getBoxes(b,0);\n float x1 = getBoxes(b,1);\n float y2 = getBoxes(b,2);\n float x2 = getBoxes(b,3);\n\n // get image in batch index\n int bInd = round(getBoxInd(b));\n if(bInd < 0 || bInd >= "+a+") {\n return;\n }\n\n float height_scale = "+b+";\n float width_scale = "+k+";\n\n float in_y = "+y+";\n if( in_y < 0.0 || in_y > "+p+" ) {\n setOutput(float("+i+"));\n return;\n }\n float in_x = "+S+";\n if( in_x < 0.0 || in_x > "+m+" ) {\n setOutput(float("+i+"));\n return;\n }\n\n vec2 sourceFracIndexCR = vec2(in_x,in_y);\n if("+h+" == 1) {\n // Compute the four integer indices.\n ivec2 sourceFloorCR = ivec2(sourceFracIndexCR);\n ivec2 sourceCeilCR = ivec2(ceil(sourceFracIndexCR));\n\n float topLeft = getImage(b, sourceFloorCR.y, sourceFloorCR.x, d);\n float bottomLeft = getImage(b, sourceCeilCR.y, sourceFloorCR.x, d);\n float topRight = getImage(b, sourceFloorCR.y, sourceCeilCR.x, d);\n float bottomRight = getImage(b, sourceCeilCR.y, sourceCeilCR.x, d);\n\n vec2 fracCR = sourceFracIndexCR - vec2(sourceFloorCR);\n\n float top = topLeft + (topRight - topLeft) * fracCR.x;\n float bottom = bottomLeft + (bottomRight - bottomLeft) * fracCR.x;\n float newValue = top + (bottom - top) * fracCR.y;\n setOutput(newValue);\n } else {\n // Compute the coordinators of nearest neighbor point.\n ivec2 sourceNearestCR = ivec2(floor(\n sourceFracIndexCR + vec2(0.5,0.5)));\n float newValue = getImage(b, sourceNearestCR.y, sourceNearestCR.x, d);\n setOutput(newValue);\n }\n }\n "}(t.shape,e.shape,r,i,a);return this.compileAndRun(o,[t,e,n])},t.prototype.depthToSpace=function(t,e,n){w(e>1,function(){return"blockSize should be > 1 for depthToSpace, but was: "+e});var r=t.shape[0],i="NHWC"===n?t.shape[1]:t.shape[2],a="NHWC"===n?t.shape[2]:t.shape[3],o="NHWC"===n?t.shape[3]:t.shape[1],s=i*e,u=a*e,c=o/(e*e),l=new Ti("NHWC"===n?[r,s,u,c]:[r,c,s,u],e,n);return this.compileAndRun(l,[t])},t.prototype.split=function(t,e,n){return cr(t,e,n)},t.prototype.scatterND=function(t,e,n){var r=pn(0,t,n),i=r.sliceRank,a=r.numUpdates,o=r.sliceSize,s=r.strides,u=r.outputSize,c=[u/o,o],l=t.reshape([a,i]),f=e.reshape([a,o]);if(0===u)return er(Pn([]),n);var h=Ln(0),d=new ha(a,i,l.rank,f.rank,s,c);return this.compileAndRun(d,[f,l,h]).reshape(n)},t.prototype.sparseToDense=function(t,e,n,r){var i=pn(0,t,n),a=i.sliceRank,o=i.numUpdates,s=i.strides,u=i.outputSize,c=new ha(o,a,t.rank,e.rank,s,[u,1],!1);return this.compileAndRun(c,[e,t,r]).reshape(n)},t.prototype.fft=function(t){return this.fftImpl(t,!1)},t.prototype.ifft=function(t){return this.fftImpl(t,!0)},t.prototype.fftImpl=function(t,e){var n=this.texData.get(t.dataId),r=new Ii("return real * expR - imag * expI;",t.shape,e),i=new Ii("return real * expI + imag * expR;",t.shape,e),a=[this.makeComplexComponentTensorHandle(t,n.complexTensors.real),this.makeComplexComponentTensorHandle(t,n.complexTensors.imag)],o=this.compileAndRun(r,a),s=this.compileAndRun(i,a),u=this.complex(o,s).as2D(t.shape[0],t.shape[1]);return o.dispose(),s.dispose(),u},t.prototype.gatherND=function(t,e){var n=e.shape,r=n[n.length-1],i=fn(t,e),a=i[0],o=i[1],s=i[2],u=i[3],c=e.reshape([o,r]),l=t.reshape([t.size/s,s]),f=new function(t,e,n){this.sliceDim=t,this.strides=e,this.variableNames=["x","indices"],this.outputShape=n;var r=vi(e.length),i=vi(n.length),a=this.sliceDim>1?"strides[j]":"strides";this.userCode="\n "+r+" strides = "+r+"("+this.strides+");\n void main() {\n "+i+" coords = getOutputCoords();\n int flattenIndex = 0;\n for (int j = 0; j < "+this.sliceDim+"; j++) {\n int index = round(getIndices(coords[0], j));\n flattenIndex += index * "+a+";\n }\n setOutput(getX(flattenIndex, coords[1]));\n }\n "}(r,u,[o,s]);return this.compileAndRun(f,[l,c]).reshape(a)},t.prototype.fill=function(t,e,n){if("string"===(n=n||H(e))){var r=j(n,_(t));return r.fill(e),vt.make(t,{values:r},n)}var i=new Mi(t,e),a=i.getCustomSetupFunc(e),o=this.makeOutputArray(t,n);return this.compileAndRun(i,[],o,a)},t.prototype.onesLike=function(t){if("string"===t.dtype)throw new Error("onesLike is not supported under string dtype");return this.fill(t.shape,1,t.dtype)},t.prototype.zerosLike=function(t){return this.fill(t.shape,"string"===t.dtype?"":0,t.dtype)},t.prototype.linspace=function(t,e,n){return nr(t,e,n)},t.prototype.makeOutputArray=function(t,e){return vt.make(t,{},e,this)},t.prototype.makePackedTensor=function(t,e){var n=vt.make(t,{},e,this);return this.texData.get(n.dataId).isPacked=!0,n},t.prototype.unpackTensor=function(t){var e=new function(t){this.variableNames=["A"],this.usesPackedTextures=!0,this.outputShape=t;var e=t.length,n=ri("rc",e),r=vi(e),i=function(t,e){if(1===t)return"rc";for(var n="",r=0;r "+e[0];for(var r="",i=t-2;i= "+e[i],i= "+e+";\n bool rEdge = rp1 >= "+n+";\n "}(e,t[t.length-1],t[t.length-2],n),o=function(t,e){var n=t.length,r=function(t,e){for(var n=[],r=0;r<=1;r++)for(var i=0;i<=1;i++){for(var a=(0===r?"r":"rp1")+", "+(0===i?"c":"cp1"),o=2;o= "+t[0]+" ? 0. : getA(rc + 1),\n 0, 0":"getA("+r[0]+"),\n cEdge ? 0. : getA("+r[1]+"),\n rEdge ? 0. : getA("+r[2]+"),\n rEdge || cEdge ? 0. : getA("+r[3]+")"}(t,n);this.userCode="\n void main() {\n "+r+" rc = getOutputCoords();\n\n if("+i+") {\n setOutput(vec4(0));\n } else {\n "+a+"\n\n setOutput(vec4("+o+"));\n }\n }\n "}}(t.shape);return this.compileAndRun(e,[t],this.makePackedTensor(t.shape,t.dtype))},t.prototype.packedReshape=function(t,e){var n=t.reshape([ve(t.shape)].concat(ge(t.shape))),r=new function(t,e){this.variableNames=["A"],this.usesPackedTextures=!0,this.outputShape=t;for(var n="",r=0;r<4;r++){var i="thisRC = rc;";r%2==1&&(i+="thisRC.z += 1;"),r>1&&(i+="thisRC.y += 1;"),n+="\n "+i+"\n "+(r>0?"if(thisRC.y < rows && thisRC.z < cols){":"")+"\n int flatIndex = getFlatIndex(thisRC);\n\n ivec3 inputRC = inputCoordsFromReshapedOutCoords(flatIndex);\n vec2 inputRCInnerDims = vec2(float(inputRC.y),float(inputRC.z));\n\n result["+r+"] =\n getChannel(getA(inputRC.x, inputRC.y, inputRC.z), inputRCInnerDims);\n "+(r>0?"}":"")+"\n "}this.userCode="\n \n ivec3 inputCoordsFromReshapedOutCoords(int index) {\n "+ui(["r","c","d"],e)+"\n return ivec3(r, c, d);\n }\n \n "+function(t){return"\n int getFlatIndex(ivec3 coords) {\n return round("+function(t,e){if(t.length!==e.length)throw new Error("Vectors to be dotted must be of the same length -got "+t.length+" and "+e.length);for(var n=[],r=Math.floor(t.length/4),i=t.length%4,a=0;a0,n=t.isUniform?"uniform":t.texData.texShape;r+=t.shape+"_"+n+"_"+e});var i=t.userCode;return t.constructor.name+"_"+r+"_"+i}(t,0,s),c=this.getAndSaveBinary(u,function(){return function(t,e,n,r){var i=e.userCode,a=n.map(function(t,n){var r={logicalShape:t.shape,texShape:t.isUniform?null:t.texData.texShape,isUniform:t.isUniform,isPacked:!t.isUniform&&t.texData.isPacked,flatOffset:null};return null!=t.texData&&null!=t.texData.slice&&t.texData.slice.flatOffset>0&&(r.flatOffset=t.texData.slice.flatOffset),{name:e.variableNames[n],shapeInfo:r}}),o=a.map(function(t){return t.shapeInfo}),s={logicalShape:r.shape,texShape:r.texData.texShape,isUniform:!1,isPacked:r.texData.isPacked,flatOffset:null},u=function(t,e,n,r){var i=[];t.forEach(function(t){var e=_(t.shapeInfo.logicalShape);t.shapeInfo.isUniform?i.push("uniform float "+t.name+(e>1?"["+e+"]":"")+";"):(i.push("uniform sampler2D "+t.name+";"),i.push("uniform int offset"+t.name+";"))});var a,o,s=i.join("\n"),u=t.map(function(t){return function(t,e,n){void 0===n&&(n=!1);var r="";r+=n?function t(e){var n;switch(e.shapeInfo.logicalShape.length){case 0:return"\n vec4 get"+(n=e.name).charAt(0).toUpperCase()+n.slice(1)+"() {\n return "+si().texture2D+"("+n+", halfCR);\n }\n ";case 1:return function(t){var e=t.name,n="get"+e.charAt(0).toUpperCase()+e.slice(1),r=t.shapeInfo.texShape,i=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)],a=si();return"\n vec4 "+n+"(int index) {\n vec2 uv = packedUVfrom1D(\n "+i[0]+", "+i[1]+", index);\n return "+a.texture2D+"("+e+", uv);\n }\n "}(e);case 2:return function(t){var e=t.shapeInfo.logicalShape,n=t.name,r="get"+n.charAt(0).toUpperCase()+n.slice(1),i=t.shapeInfo.texShape,a=i[0],o=i[1],s=si();if(null!=i&&E(e,i))return"\n vec4 "+r+"(int row, int col) {\n vec2 uv = (vec2(col, row) + halfCR) / vec2("+o+".0, "+a+".0);\n\n return "+s.texture2D+"("+n+", uv);\n }\n ";var u=[Math.ceil(i[0]/2),Math.ceil(i[1]/2)];return"\n vec4 "+r+"(int row, int col) {\n vec2 uv = packedUVfrom2D("+Math.ceil(e[1]/2)+", "+u[0]+", "+u[1]+", row, col);\n return "+s.texture2D+"("+n+", uv);\n }\n "}(e);case 3:return function(e){var n=e.shapeInfo.logicalShape,r=e.name,i="get"+r.charAt(0).toUpperCase()+r.slice(1),a=e.shapeInfo.texShape,o=[Math.ceil(a[0]/2),Math.ceil(a[1]/2)];if(1===n[0]){var s=gi(e,n.slice(1));return"\n "+t(s)+"\n vec4 "+i+"(int b, int row, int col) {\n return "+i+"("+bi(["b","row","col"],[1,2])+");\n }\n "}var u=o[0],c=o[1],l=Math.ceil(n[2]/2);return"\n vec4 "+i+"(int b, int row, int col) {\n vec2 uv = packedUVfrom3D(\n "+u+", "+c+", "+l*Math.ceil(n[1]/2)+", "+l+", b, row, col);\n return "+si().texture2D+"("+r+", uv);\n }\n "}(e);default:return function(t){for(var e=t.shapeInfo.logicalShape,n=e.length,r=t.name,i="get"+r.charAt(0).toUpperCase()+r.slice(1),a=t.shapeInfo.texShape,o=[Math.ceil(a[0]/2),Math.ceil(a[1]/2)],s=o[0],u=o[1],c=Math.ceil(e[n-1]/2),l=c*Math.ceil(e[n-2]/2),f="int b, int row, int col",h="b * "+l+" + (row / 2) * "+c+" + (col / 2)",d=2;d=1?"coords = 0;":c.map(function(t){return"coords."+h[t+f]+" = 0;"}).join("\n"),r=u<2&&s>0?"coords":t.shapeInfo.logicalShape.map(function(t,e){return"coords."+h[e+f]}).join(", ");var d="return outputValue;",p=1===_(t.shapeInfo.logicalShape),m=1===_(e.logicalShape);if(1!==s||p||m){if(p&&!m)d=1===u?"\n return vec4(outputValue.x, outputValue.x, 0., 0.);\n ":"\n return vec4(outputValue.x);\n ";else if(c.length){var v=s-2,g=s-1;c.indexOf(v)>-1&&c.indexOf(g)>-1?d="return vec4(outputValue.x);":c.indexOf(v)>-1?d="return vec4(outputValue.x, outputValue.y, outputValue.x, outputValue.y);":c.indexOf(g)>-1&&(d="return vec4(outputValue.xx, outputValue.zz);")}}else d="\n return vec4(outputValue.xy, outputValue.xy);\n ";return"\n vec4 "+o+"() {\n "+l+" coords = getOutputCoords();\n "+n+"\n vec4 outputValue = get"+a+"("+r+");\n "+d+"\n }\n "}(t,e):function(t,e){var n=t.name,r=n.charAt(0).toUpperCase()+n.slice(1),i="get"+r+"AtOutCoords",a=e.texShape,o=t.shapeInfo.texShape,s=t.shapeInfo.logicalShape.length,u=e.logicalShape.length;if(!t.shapeInfo.isUniform&&s===u&&null==t.shapeInfo.flatOffset&&E(o,a))return"\n float "+i+"() {\n return sampleTexture("+n+", resultUV);\n }\n ";var c=vi(u),l=ii(t.shapeInfo.logicalShape,e.logicalShape),f=u-s,h=["x","y","z","w","u","v"];return"\n float "+i+"() {\n "+c+" coords = getOutputCoords();\n "+(0===s?"":u<2&&l.length>=1?"coords = 0;":l.map(function(t){return"coords."+h[t+f]+" = 0;"}).join("\n"))+"\n return get"+r+"("+(u<2&&s>0?"coords":t.shapeInfo.logicalShape.map(function(t,e){return"coords."+h[e+f]}).join(", "))+");\n }\n "}(t,e)),r}(t,e,r)}).join("\n"),c=e.texShape,l=si(),f="\n float sampleTexture(sampler2D textureSampler, vec2 uv) {\n return "+l.texture2D+"(textureSampler, uv).r;\n }\n ",h=function(t){return t.version+"\n precision highp float;\n precision highp int;\n precision highp sampler2D;\n "+t.varyingFs+" vec2 resultUV;\n "+t.defineOutput+"\n const vec2 halfCR = vec2(0.5, 0.5);\n\n struct ivec5\n {\n int x;\n int y;\n int z;\n int w;\n int u;\n };\n\n struct ivec6\n {\n int x;\n int y;\n int z;\n int w;\n int u;\n int v;\n };\n\n uniform float NAN;\n #define isnan(value) isnan_custom(value)\n "+t.defineSpecialNaN+"\n bvec4 isnan_custom(vec4 val) {\n return bvec4(isnan(val.x), isnan(val.y), isnan(val.z), isnan(val.w));\n }\n\n "+t.defineSpecialInf+"\n "+t.defineRound+"\n\n int imod(int x, int y) {\n return x - y * (x / y);\n }\n\n int idiv(int a, int b, float sign) {\n int res = a / b;\n int mod = imod(a, b);\n if (sign < 0. && mod != 0) {\n res -= 1;\n }\n return res;\n }\n\n //Based on the work of Dave Hoskins\n //https://www.shadertoy.com/view/4djSRW\n #define HASHSCALE1 443.8975\n float random(float seed){\n vec2 p = resultUV * seed;\n vec3 p3 = fract(vec3(p.xyx) * HASHSCALE1);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.x + p3.y) * p3.z);\n }\n\n "+li+"\n "+fi+"\n "+hi+"\n "}(l);return e.isPacked?(a=function(t,e){switch(t.length){case 0:return"\n int getOutputCoords() {\n return 0;\n }\n ";case 1:return function(t,e){var n=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)];return 1===n[0]?"\n int getOutputCoords() {\n return 2 * int(resultUV.x * "+n[1]+".0);\n }\n ":1===n[1]?"\n int getOutputCoords() {\n return 2 * int(resultUV.y * "+n[0]+".0);\n }\n ":"\n int getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2("+n[0]+", "+n[1]+"));\n return resTexRC.x * "+n[1]+" + resTexRC.y;\n }\n "}(0,e);case 2:return function(t,e){var n=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)];if(E(t,e))return"\n ivec2 getOutputCoords() {\n return 2 * ivec2(resultUV.yx * vec2("+n[0]+", "+n[1]+"));\n }\n ";var r=Math.ceil(t[1]/2);return"\n ivec2 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2("+n[0]+", "+n[1]+"));\n\n int index = resTexRC.x * "+n[1]+" + resTexRC.y;\n int r = 2 * (index / "+r+");\n int c = imod(index, "+r+") * 2;\n\n return ivec2(r, c);\n }\n "}(t,e);case 3:return n=t,r=e,i=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)],o=(a=Math.ceil(n[2]/2))*Math.ceil(n[1]/2),"\n ivec3 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2("+i[0]+", "+i[1]+"));\n int index = resTexRC.x * "+i[1]+" + resTexRC.y;\n\n int b = index / "+o+";\n index -= b * "+o+";\n\n int r = 2 * (index / "+a+");\n int c = imod(index, "+a+") * 2;\n\n return ivec3(b, r, c);\n }\n ";default:return function(t,e){for(var n=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)],r=Math.ceil(t[t.length-1]/2),i=r*Math.ceil(t[t.length-2]/2),a=i,o="",s="b, r, c",u=2;u0?32:16})),this.floatPrecisionValue},t.prototype.epsilon=function(){return 32===this.floatPrecision()?1e-7:1e-4},t.prototype.uploadToGPU=function(t){var e,n=this.texData.get(t),r=n.shape,i=n.dtype,a=n.values,o=n.texture,s=n.usage,u=n.isPacked;if(null==o){var c,l=null!=this.activeTimers;l&&(c=performance.now());var f=be(r,u);n.texShape=f;var h=this.acquireTexture(f,s,i,u);if(n.texture=h,null!=a){if(u){var d=ve(r),p=1,m=1;r.length&&(p=(e=ge(r))[0],m=e[1]),this.gpgpu.uploadMatrixToPackedTexture(h,d,p,m,f[0],f[1],Na(a))}else this.gpgpu.uploadMatrixToTexture(h,f[0],f[1],Na(a));n.values=null,l&&(this.uploadWaitMs+=performance.now()-c)}}},t.prototype.convertAndCacheOnCPU=function(t,e){var n=this.texData.get(t),r=n.dtype;return this.releaseGPUData(t),n.usage=Ni.UPLOAD,null!=e&&(n.values=function(t,e){if("float32"===e||"complex64"===e)return t;if("int32"===e||"bool"===e){for(var n="int32"===e?new Int32Array(t.length):new Uint8Array(t.length),r=0;r1024*this.numMBBeforeWarning*1024){var i=(this.numBytesInGPU/1024/1024).toFixed(2);this.warnedAboutMemory=!0,console.warn("High memory usage in GPU: "+i+" MB, most likely due to a memory leak")}return this.textureManager.acquireTexture(t,e,r)},t.prototype.computeBytes=function(t,e){return t[0]*t[1]*B(e)},t}();function Na(t){return t instanceof Float32Array?t:new Float32Array(t)}jt()&&Dt.registerBackend("webgl",function(){return new Aa},2);var Oa=In({abs_:function(t){var e=kn(t,"x","abs");return"complex64"===e.dtype?Dt.runKernel(function(t){return t.complexAbs(e)},{$x:e}):Dt.runKernel(function(t,n){var r=t.abs(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.toFloat().step(-1))}}})}}),Ta=In({acos_:function(t){var e=kn(t,"x","acos");return Dt.runKernel(function(t,n){var r=t.acos(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.divStrict(Ln(1).sub(n.toFloat().square()).sqrt()).neg()}}})}}),Ia=In({acosh_:function(t){var e=kn(t,"x","acosh");return Dt.runKernel(function(t,n){var r=t.acosh(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.divStrict(n.toFloat().square().sub(1).sqrt())}}})}}),Ma=In({asin_:function(t){var e=kn(t,"x","asin");return Dt.runKernel(function(t,n){var r=t.asin(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.divStrict(Ln(1).sub(n.toFloat().square()).sqrt())}}})}}),Ra=In({asinh_:function(t){var e=kn(t,"x","asinh");return Dt.runKernel(function(t,n){var r=t.asinh(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.divStrict(Ln(1).add(n.toFloat().square()).sqrt())}}})}}),Da=In({atan_:function(t){var e=kn(t,"x","atan");return Dt.runKernel(function(t,n){var r=t.atan(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.toFloat().square().add(1))}}})}}),ja=In({atanh_:function(t){var e=kn(t,"x","atanh");return Dt.runKernel(function(t,n){var r=t.atanh(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(Ln(1).sub(n.toFloat().square()))}}})}}),za=In({ceil_:function(t){var e=kn(t,"x","ceil");return Dt.runKernel(function(t){return t.ceil(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),Pa=In({clipByValue_:function(t,e,n){var r=kn(t,"x","clipByValue");return w(e<=n,function(){return"Error in clip: min ("+e+") must be less than or equal to max ("+n+")."}),Dt.runKernel(function(t,i){var a=t.clip(r,e,n);return i([r]),a},{$x:r},function(t,r){var i=r[0];return{$x:function(){return t.where(i.greaterEqual(e).logicalAnd(i.lessEqual(n)),Jn(t))}}})}}),La=In({cos_:function(t){var e=kn(t,"x","cos");return Dt.runKernel(function(t,n){var r=t.cos(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return n.toFloat().sin().neg().mul(t)}}})}}),Fa=In({cosh_:function(t){var e=kn(t,"x","cosh");return Dt.runKernel(function(t,n){var r=t.cosh(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return n.toFloat().sinh().mulStrict(t)}}})}}),Ba=In({erf_:function(t){var e=kn(t,"x","erf");return w("int32"===e.dtype||"float32"===e.dtype,function(){return"Input dtype must be `int32` or `float32`."}),"int32"===e.dtype&&(e=e.toFloat()),Dt.runKernel(function(t,n){var r=t.erf(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.square().neg().exp().mul(2/Math.sqrt(Math.PI)))}}})}}),Ua=In({exp_:function(t){var e=kn(t,"x","exp");return Dt.runKernel(function(t,n){var r=t.exp(e);return n([r]),r},{$x:e},function(t,e){return{$x:function(){return t.mulStrict(e[0])}}})}}),Va=In({expm1_:function(t){var e=kn(t,"x","expm1");return Dt.runKernel(function(t,n){var r=t.expm1(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.exp())}}})}}),Wa=In({floor_:function(t){var e=kn(t,"x","floor");return Dt.runKernel(function(t){return t.floor(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),qa=In({log_:function(t){var e=kn(t,"x","log");return Dt.runKernel(function(t,n){var r=t.log(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.toFloat())}}})}}),Ha=In({log1p_:function(t){var e=kn(t,"x","log1p");return Dt.runKernel(function(t,n){var r=t.log1p(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.add(1))}}})}}),Ga=In({logSigmoid_:function(t){var e=kn(t,"x","logSigmoid");return Dt.runKernel(function(t,n){var r=t.softplus(e.neg()).neg();return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.neg().sigmoid())}}})}}),Ka=In({neg_:function(t){var e=kn(t,"x","neg");return Dt.runKernel(function(t){return t.neg(e)},{$x:e},function(t){return{$x:function(){return t.neg()}}})}}),Xa=In({reciprocal_:function(t){var e=kn(t,"x","reciprocal");return Dt.runKernel(function(t,n){var r=t.reciprocal(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.square().neg())}}})}}),$a=In({round_:function(t){var e=kn(t,"x","round");return Dt.runKernel(function(t){return t.round(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),Ya=In({rsqrt_:function(t){var e=kn(t,"x","rsqrt");return Dt.runKernel(function(t,n){var r=t.rsqrt(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.pow(1.5).mul(2)).neg()}}})}}),Ja=In({sigmoid_:function(t){var e=kn(t,"x","sigmoid");return Dt.runKernel(function(t,n){var r=t.sigmoid(e);return n([r]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.mul(Ln(1).sub(n)))}}})}}),Za=In({sign_:function(t){var e=kn(t,"x","sign");return Dt.runKernel(function(t){return t.sign(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),Qa=In({isNaN_:function(t){var e=kn(t,"x","isNaN");return Dt.runKernel(function(t){return t.isNaN(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),to=In({isInf_:function(t){var e=kn(t,"x","isInf");return Dt.runKernel(function(t){return t.isInf(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),eo=In({isFinite_:function(t){var e=kn(t,"x","isFinite");return Dt.runKernel(function(t){return t.isFinite(e)},{$x:e},function(t){return{$x:function(){return Jn(t)}}})}}),no=In({sin_:function(t){var e=kn(t,"x","sin");return Dt.runKernel(function(t,n){var r=t.sin(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return n.toFloat().cos().mul(t)}}})}}),ro=In({sinh_:function(t){var e=kn(t,"x","sinh");return Dt.runKernel(function(t,n){var r=t.sinh(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return n.toFloat().cosh().mulStrict(t)}}})}}),io=In({softplus_:function(t){var e=kn(t,"x","softplus");return Dt.runKernel(function(t,n){var r=t.softplus(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.sigmoid())}}})}}),ao=In({sqrt_:function(t){var e=kn(t,"x","sqrt");return Dt.runKernel(function(t,n){var r=t.sqrt(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.toFloat().sqrt().mul(2))}}})}}),oo=In({square_:function(t){var e=kn(t,"x","square");return Dt.runKernel(function(t,n){return n([e]),t.square(e)},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mul(n.toFloat().mul(2))}}})}}),so=In({step_:function(t,e){void 0===e&&(e=0);var n=kn(t,"x","step");return Dt.runKernel(function(t){return t.step(n,e)},{$x:n},function(t){return{$x:function(){return Jn(t)}}})}}),uo=In({tan_:function(t){var e=kn(t,"x","tan");return Dt.runKernel(function(t,n){var r=t.tan(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.div(n.cos().square())}}})}}),co=In({tanh_:function(t){var e=kn(t,"x","tanh");return Dt.runKernel(function(t,n){var r=t.tanh(e);return n([r]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return Ln(1).sub(n.square()).mulStrict(t)}}})}});function lo(t,e,n,r,i,a){var o,s,u=kn(t,"x","batchNorm"),c=kn(e,"mean","batchNorm"),l=kn(n,"variance","batchNorm");return null!=i&&(o=kn(i,"scale","batchNorm")),null!=r&&(s=kn(r,"offset","batchNorm")),w(2===u.rank,function(){return"Error in batchNorm3D: x must be rank 3 but got rank "+u.rank+"."}),w(2===c.rank||1===c.rank,function(){return"Error in batchNorm2D: mean must be rank 2 or rank 1 but got rank "+c.rank+"."}),w(2===l.rank||1===l.rank,function(){return"Error in batchNorm2D: variance must be rank 2 or rank 1 but got rank "+l.rank+"."}),null!=o&&w(2===o.rank||1===o.rank,function(){return"Error in batchNorm2D: scale must be rank 2 or rank 1 but got rank "+o.rank+"."}),null!=s&&w(2===s.rank||1===s.rank,function(){return"Error in batchNorm2D: offset must be rank 2 or rank 1 but got rank "+s.rank+"."}),po(u,c,l,s,o,a)}function fo(t,e,n,r,i,a){var o,s,u=kn(t,"x","batchNorm"),c=kn(e,"mean","batchNorm"),l=kn(n,"variance","batchNorm");return null!=i&&(o=kn(i,"scale","batchNorm")),null!=r&&(s=kn(r,"offset","batchNorm")),w(3===u.rank,function(){return"Error in batchNorm3D: x must be rank 3 but got rank "+u.rank+"."}),w(3===c.rank||1===c.rank,function(){return"Error in batchNorm3D: mean must be rank 3 or rank 1 but got rank "+c.rank+"."}),w(3===l.rank||1===l.rank,function(){return"Error in batchNorm3D: variance must be rank 3 or rank 1 but got rank "+l.rank+"."}),null!=o&&w(3===o.rank||1===o.rank,function(){return"Error in batchNorm3D: scale must be rank 3 or rank 1 but got rank "+o.rank+"."}),null!=s&&w(3===s.rank||1===s.rank,function(){return"Error in batchNorm3D: offset must be rank 3 or rank 1 but got rank "+s.rank+"."}),po(u,c,l,s,o,a)}function ho(t,e,n,r,i,a){var o,s,u=kn(t,"x","batchNorm"),c=kn(e,"mean","batchNorm"),l=kn(n,"variance","batchNorm");return null!=i&&(o=kn(i,"scale","batchNorm")),null!=r&&(s=kn(r,"offset","batchNorm")),w(4===u.rank,function(){return"Error in batchNorm4D: x must be rank 4 but got rank "+u.rank+"."}),w(4===c.rank||1===c.rank,function(){return"Error in batchNorm4D: mean must be rank 4 or rank 1 but got rank "+c.rank+"."}),w(4===l.rank||1===l.rank,function(){return"Error in batchNorm4D: variance must be rank 4 or rank 1 but got rank "+l.rank+"."}),null!=o&&w(4===o.rank||1===o.rank,function(){return"Error in batchNorm4D: scale must be rank 4 or rank 1 but got rank "+o.rank+"."}),null!=s&&w(4===s.rank||1===s.rank,function(){return"Error in batchNorm4D: offset must be rank 4 or rank 1 but got rank "+s.rank+"."}),po(u,c,l,s,o,a)}function po(t,e,n,r,i,a){null==a&&(a=.001);var o,s,u,c=kn(t,"x","batchNorm"),l=kn(e,"mean","batchNorm"),f=kn(n,"variance","batchNorm");return null!=i&&(o=kn(i,"scale","batchNorm")),null!=r&&(s=kn(r,"offset","batchNorm")),w(l.rank===f.rank,function(){return"Batch normalization gradient requires mean and variance to have equal ranks."}),w(null==s||l.rank===s.rank,function(){return"Batch normalization gradient requires mean and offset to have equal ranks."}),w(null==o||l.rank===o.rank,function(){return"Batch normalization gradient requires mean and scale to have equal ranks."}),u=0===c.rank||1===c.rank?c.as4D(1,1,1,c.size):2===c.rank?c.as4D(1,1,c.shape[0],c.shape[1]):3===c.rank?c.as4D(1,c.shape[0],c.shape[1],c.shape[2]):c,Dt.runKernel(function(t,e){var n=t.batchNormalization(u,mo(l),mo(f),a,mo(o),mo(s));return e([c,l,f,o]),n},{$x:c,$mean:l,$variance:f,$scale:o,$offset:s},function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],s=null==o?Ln(1):o,c=ai(r.shape,u.shape),l=[];if(1===r.rank){for(var f=0;f=2&&o.rank>=2&&a.rank===o.rank,function(){return"Error in matMul: inputs must have the same rank of at least 2, got ranks "+a.rank+" and "+o.rank+"."}),w(E(f,h),function(){return"Error in matMul: outer dimensions ("+f+") and ("+h+") of Tensors with shapes "+a.shape+" and "+o.shape+" must match."}),w(s===u,function(){return"Error in matMul: inner shapes ("+s+") and ("+u+") of Tensors with shapes "+a.shape+" and "+o.shape+" and transposeA="+n+" and transposeB="+r+" must match."});var m=a.shape.slice(0,-2).concat([c,l]),v=n?a.as3D(d,s,c):a.as3D(d,c,s),g=r?o.as3D(p,l,u):o.as3D(p,u,l);return Dt.runKernel(function(t,e){var i=t.batchMatMul(v,g,n,r);return e([v,g]),i},{$a:v,$b:g},function(t,e){var i=e,a=i[0],o=i[1];return n||r?!n&&r?{$a:function(){return t.matMul(o,!1,!1)},$b:function(){return t.matMul(a,!0,!1)}}:n&&!r?{$a:function(){return o.matMul(t,!1,!0)},$b:function(){return a.matMul(t,!1,!1)}}:{$a:function(){return o.matMul(t,!0,!0)},$b:function(){return t.matMul(a,!0,!0)}}:{$a:function(){return t.matMul(o,!1,!0)},$b:function(){return a.matMul(t,!0,!1)}}}).reshape(m)}}),Ho=In({dot_:function(t,e){var n=kn(t,"t1","dot"),r=kn(e,"t2","dot");w(!(1!==n.rank&&2!==n.rank||1!==r.rank&&2!==r.rank),function(){return"Error in dot: inputs must all be rank 1 or 2, but got ranks "+n.rank+" and "+r.rank+"."});var i=1===n.rank?n.size:n.shape[1],a=1===r.rank?r.size:r.shape[0];return w(i===a,function(){return"Error in dot: inner dimensions of inputs must match, but got "+i+" and "+a+"."}),1===n.rank&&1===r.rank?n.as2D(1,-1).matMul(r.as2D(-1,1)).asScalar():1===n.rank&&2===r.rank?n.as2D(1,-1).matMul(r.as2D(r.shape[0],r.shape[1])).as1D():2===n.rank&&1===r.rank?n.matMul(r.as2D(-1,1)).as1D():n.matMul(r.as2D(r.shape[0],r.shape[1]))}}),Go=In({outerProduct_:function(t,e){var n=kn(t,"v1","outerProduct"),r=kn(e,"v2","outerProduct");return w(1===n.rank&&1===r.rank,function(){return"Error in outerProduct: inputs must be rank 1, but got ranks "+n.rank+" and "+r.rank+"."}),n.as2D(-1,1).matMul(r.as2D(1,-1))}}),Ko=In({reverse_:function(t,e){var n=kn(t,"x","reverse");if(0===n.rank)return n.clone();var r=M(e,n.shape);return Dt.runKernel(function(t){return t.reverse(n,r)},{$x:n},function(t){return{$x:function(){return t.reverse(r)}}}).reshapeAs(n)}}),Xo=In({reverse1d_:function(t){var e=kn(t,"x","reverse");return w(1===e.rank,function(){return"Error in reverse1D: x must be rank 1 but got rank "+e.rank+"."}),Ko(e,0)}}),$o=In({reverse2d_:function(t,e){var n=kn(t,"x","reverse");return w(2===n.rank,function(){return"Error in reverse2D: x must be rank 2 but got rank "+n.rank+"."}),Ko(n,e)}}),Yo=In({reverse3d_:function(t,e){var n=kn(t,"x","reverse");return w(3===n.rank,function(){return"Error in reverse3D: x must be rank 3 but got rank "+n.rank+"."}),Ko(n,e)}}),Jo=In({reverse4d_:function(t,e){var n=kn(t,"x","reverse");return w(4===n.rank,function(){return"Error in reverse4D: x must be rank 4 but got rank "+n.rank+"."}),Ko(n,e)}});function Zo(t,e,n,r,i,a){var o=kn(t,"x","maxPool"),s=o,u=!1;3===o.rank&&(u=!0,s=o.as4D(1,o.shape[0],o.shape[1],o.shape[2])),null==r&&(r=[1,1]),w(4===s.rank,function(){return"Error in maxPool: input must be rank 4 but got rank "+s.rank+"."}),w(Ro(n,r),function(){return"Error in maxPool: Either strides or dilations must be 1. Got strides "+n+" and dilations '"+r+"'"}),null!=a&&w(C(i),function(){return"Error in maxPool: pad must be an integer when using, dimRoundingMode "+a+" but got pad "+i+"."});var c=Eo(s.shape,e,n,r,i,a),l=Dt.runKernel(function(t,e){var n=t.maxPool(s,c);return e([s,n]),n},{x:s},function(t,a){var o=a[0],s=a[1];return{x:function(){return function(t,e,n,r,i,a,o,s){var u=kn(t,"dy","maxPoolBackprop"),c=kn(e,"input","maxPoolBackprop"),l=kn(n,"output","maxPoolBackprop");w(c.rank===u.rank,function(){return"Rank of input ("+c.rank+") does not match rank of dy ("+u.rank+")"}),null==a&&(a=[1,1]),w(Ro(i,a),function(){return"Error in maxPoolBackProp: Either strides or dilations must be 1. Got strides "+i+" and dilations '"+a+"'"}),w(4===u.rank,function(){return"Error in maxPoolBackprop: dy must be rank 4 but got rank "+u.rank+"."}),w(4===c.rank,function(){return"Error in maxPoolBackprop: input must be rank 4 but got rank "+c.rank+"."});var f=Eo(c.shape,r,i,a,o,void 0);return Dt.runKernel(function(t){return t.maxPoolBackprop(u,c,l,f)},{$dy:u,$input:c})}(t,o,s,e,n,r,i)}}});return u?l.as3D(l.shape[1],l.shape[2],l.shape[3]):l}function Qo(t,e,n,r,i,a){var o=kn(t,"x","avgPool","float32");null==r&&(r=[1,1]),w(Ro(n,r),function(){return"Error in avgPool: Either strides or dilations must be 1. Got strides "+n+" and dilations '"+r+"'"});var s=o,u=!1;3===o.rank&&(u=!0,s=o.as4D(1,o.shape[0],o.shape[1],o.shape[2])),w(4===s.rank,function(){return"Error in avgPool: x must be rank 4 but got rank "+s.rank+"."}),null!=a&&w(C(i),function(){return"Error in avgPool: pad must be an integer when using, dimRoundingMode "+a+" but got pad "+i+"."});var c=Eo(s.shape,e,n,r,i,a),l=Dt.runKernel(function(t){return t.avgPool(s,c)},{x:s},function(t){return{x:function(){return function(t,e,n,r,i,a){var o=kn(t,"dy","avgPoolBackprop"),s=kn(e,"input","avgPoolBackprop");w(s.rank===o.rank,function(){return"Rank of input ("+s.rank+") does not match rank of dy ("+o.rank+")"}),null==i&&(i=[1,1]),w(Ro(r,i),function(){return"Error in avgPoolBackprop: Either strides or dilations must be 1. Got strides "+r+" and dilations '"+i+"'"});var u=s,c=o,l=!1;3===s.rank&&(l=!0,u=s.as4D(1,s.shape[0],s.shape[1],s.shape[2]),c=o.as4D(1,o.shape[0],o.shape[1],o.shape[2])),w(4===c.rank,function(){return"Error in avgPoolBackprop: dy must be rank 4 but got rank "+c.rank+"."}),w(4===u.rank,function(){return"Error in avgPoolBackprop: input must be rank 4 but got rank "+u.rank+"."});var f=Eo(u.shape,n,r,i,a),h=Dt.runKernel(function(t){return t.avgPoolBackprop(c,u,f)},{dy4D:c,input4D:u});return l?h.as3D(h.shape[1],h.shape[2],h.shape[3]):h}(t,s,e,n,r,i)}}});return l=l.cast(o.dtype),u?l.as3D(l.shape[1],l.shape[2],l.shape[3]):l}var ts=In({maxPool_:function(t,e,n,r,i){return Zo(t,e,n,1,r,i)}}),es=In({avgPool_:function(t,e,n,r,i){return Qo(t,e,n,1,r,i)}}),ns=In({pool_:function(t,e,n,r,i,a){null==i&&(i=[1,1]),null==a&&(a=1),0===r&&(r="valid");var o=kn(t,"x","maxPool"),s=o,u=!1;3===o.rank&&(u=!0,s=o.as4D(1,o.shape[0],o.shape[1],o.shape[2])),w(Ro(a,i),function(){return"Error in pool: Either strides or dilations must be 1. Got strides "+a+" and dilations '"+i+"'"});var c,l=Eo(s.shape,e,a,i,r),f=[l.dilationHeight,l.dilationWidth];c="same"===r?function(t,e){var n=t.map(function(t,n){return t+(t-1)*(e[n]-1)}).map(function(t){return t-1}),r=n.map(function(t){return Math.floor(t/2)}),i=n.map(function(t,e){return t-r[e]});return n.map(function(t,e){return[r[e],i[e]]})}([l.filterHeight,l.filterWidth],f):[[0,0],[0,0]];var h=1===f[0]&&1===f[1],d=function(t,e,n){var r=n.map(function(t){return t[0]}),i=n.map(function(t){return t[1]}),a=t.concat(r,i),o=e.map(function(t,e){return(t-a[e]%t)%t}),s=i.map(function(t,e){return t+o[e]});return[e.map(function(t,e){return[r[e],s[e]]}),e.map(function(t,e){return[0,o[e]]})]}([l.inHeight,l.inWidth],f,c),p=d[0],m=d[1],v=h?r:"valid",g=h?s:Xr(s,f,p),b=("avg"===n?function(){return Qo(g,e,a,1,v)}:function(){return Zo(g,e,a,1,v)})(),y=h?b:Tr(b,f,m);return u?y.as3D(y.shape[1],y.shape[2],y.shape[3]):y}}),rs=In({slice_:function(t,e,n){var r,i,a=kn(t,"x","slice");if(0===a.rank)throw new Error("Slicing scalar is not possible");r="number"==typeof e?[e].concat(new Array(a.rank-1).fill(0)):e.length=0?t:(w(-1===t,function(){return"Bad value in size"}),a.shape[e]-r[e])}),function(t,e,n){w(t.rank===e.length,function(){return"Error in slice"+t.rank+"D: Length of begin "+e+" must match the rank of the array ("+t.rank+")."}),w(t.rank===n.length,function(){return"Error in slice"+t.rank+"D: Length of size "+n+" must match the rank of the array ("+t.rank+")."});for(var r=function(r){w(e[r]+n[r]<=t.shape[r],function(){return"Error in slice"+t.rank+"D: begin["+r+"] + size["+r+"] ("+(e[r]+n[r])+") would overflow input.shape["+r+"] ("+t.shape[r]+")"})},i=0;i0&&(e=e.sum(n)),e.reshape(r.shape)},$b:function(){var e=t,n=ai(i.shape,a);return n.length>0&&(e=e.sum(n)),e.reshape(i.shape)}}})}}),Rs=In({addN_:function(t){w(Array.isArray(t),function(){return"The argument passed to tf.addN() must be a list of tensors"}),w(t.length>=1,function(){return"Must pass at least one tensor to tf.addN(), but got "+t.length});var e=t.map(function(t,e){return kn(t,"tensors"+e,"addN")}),n=e[0];e.forEach(function(t){if(t.dtype!==n.dtype)throw new Error("All tensors passed to tf.addN() must have the same dtype")}),e.forEach(function(t){if(!E(t.shape,n.shape))throw new Error("All tensors passed to tf.addN() must have the same shape")});var r=e;return Dt.runKernel(function(t){return t.addN(e)},r,function(t){var n={};return e.forEach(function(e,r){n[r]=function(){return t.clone()}}),n})}}),Ds=In({addStrict_:function(t,e){var n=kn(t,"a","addStrict"),r=kn(e,"b","addStrict");return x(n.shape,r.shape,"Error in addStrict: "),n.add(r)}}),js=In({atan2_:function(t,e){var n,r=kn(t,"a","atan2"),i=kn(e,"b","atan2");n=At(r,i),r=n[0],i=n[1];var a=oi(r.shape,i.shape);return Dt.runKernel(function(t,e){var n=t.atan2(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){var e=Ms(n.square(),r.square()),i=t.mul(r.div(e)),o=ai(n.shape,a);return o.length>0&&(i=i.sum(o)),i.reshape(n.shape)},$b:function(){var e=Ms(n.square(),r.square()),i=Ka(t.mul(n.div(e))),o=ai(r.shape,a);return o.length>0&&(i=i.sum(o)),i.reshape(r.shape)}}})}}),zs=In({div_:function(t,e){var n,r=kn(t,"a","div"),i=kn(e,"b","div");if(n=At(r,i),r=n[0],i=n[1],"int32"===r.dtype&&"int32"===i.dtype)return Ls(r,i);var a=oi(r.shape,i.shape);return Dt.runKernel(function(t,e){var n=t.realDivide(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){var e=t.div(r.toFloat()),i=ai(n.shape,a);return i.length>0?e.sum(i).reshape(n.shape):e},$b:function(){var e=t.mul(n.toFloat()),i=ai(r.shape,a);i.length>0&&(e=e.sum(i).reshape(r.shape));var o=r.square();return e.div(o.toFloat()).neg()}}})}}),Ps=In({divStrict_:function(t,e){var n=kn(t,"a","div"),r=kn(e,"b","div");return x(n.shape,r.shape,"Error in divideStrict: "),n.div(r)}}),Ls=In({floorDiv_:function(t,e){var n,r=kn(t,"a","floorDiv"),i=kn(e,"b","floorDiv");n=At(r,i),r=n[0],i=n[1];var a=oi(r.shape,i.shape);return Dt.runKernel(function(t,e){var n=t.floorDiv(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){var e=t.div(r.toFloat()),i=ai(n.shape,a);return i.length>0?e.sum(i).reshape(n.shape):e},$b:function(){var e=t.mul(n.toFloat()),i=ai(r.shape,a);i.length>0&&(e=e.sum(i).reshape(r.shape));var o=r.square();return e.div(o.toFloat()).neg()}}})}}),Fs=In({maximum_:function(t,e){var n,r=kn(t,"a","maximum"),i=kn(e,"b","maximum");return n=At(r,i),r=n[0],i=n[1],"bool"===r.dtype&&(r=r.toInt(),i=i.toInt()),oi(r.shape,i.shape),Dt.runKernel(function(t,e){var n=t.maximum(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){return t.mul(n.greaterEqual(r).toFloat())},$b:function(){return t.mul(n.less(r).toFloat())}}})}}),Bs=In({maximumStrict_:function(t,e){var n=kn(t,"a","maximumStrict"),r=kn(e,"b","maximumStrict");return x(n.shape,r.shape,"Error in maximumStrict: "),n.maximum(r)}}),Us=In({minimum_:function(t,e){var n,r=kn(t,"a","minimum"),i=kn(e,"b","minimum");return n=At(r,i),r=n[0],i=n[1],"bool"===r.dtype&&(r=r.toInt(),i=i.toInt()),oi(r.shape,i.shape),Dt.runKernel(function(t,e){var n=t.minimum(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){return t.mul(n.lessEqual(r).toFloat())},$b:function(){return t.mul(n.greater(r).toFloat())}}})}}),Vs=In({minimumStrict_:function(t,e){var n=kn(t,"a","minimumStrict"),r=kn(e,"b","minimumStrict");return x(n.shape,r.shape,"Error in minimumStrict: "),n.minimum(r)}}),Ws=In({mod_:function(t,e){var n,r=kn(t,"a","mod"),i=kn(e,"b","mod");n=At(r,i),r=n[0],i=n[1];var a=oi(r.shape,i.shape);return Dt.runKernel(function(t,e){var n=t.mod(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){var e=ai(n.shape,a);return e.length>0?t.sum(e).reshape(n.shape):t},$b:function(){var e=t.mul(n.div(r).floor().neg()),i=ai(r.shape,a);return i.length>0?e.sum(i).reshape(r.shape):e}}})}}),qs=In({modStrict_:function(t,e){var n=kn(t,"a","modStrict"),r=kn(e,"b","modStrict");return x(n.shape,r.shape,"Error in modStrict: "),n.mod(r)}}),Hs=In({mul_:function(t,e){var n,r=kn(t,"a","mul"),i=kn(e,"b","mul");n=At(r,i),r=n[0],i=n[1];var a=oi(r.shape,i.shape);return Dt.runKernel(function(t,e){var n=t.multiply(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1];return{$a:function(){var e=t.mul(r.toFloat()),i=ai(n.shape,a);return i.length>0?e.sum(i).reshape(n.shape):e},$b:function(){var e=t.mul(n.toFloat()),i=ai(r.shape,a);return i.length>0?e.sum(i).reshape(r.shape):e}}})}}),Gs=In({mulStrict_:function(t,e){var n=kn(t,"a","mul"),r=kn(e,"b","mul");return x(n.shape,r.shape,"Error in multiplyStrict: "),n.mul(r)}}),Ks=In({pow_:function(t,e){var n=kn(t,"base","pow"),r=kn(e,"exp","pow"),i=oi(n.shape,r.shape);return t=n.cast(Et(n.dtype,r.dtype)),e=r.cast(Et(n.dtype,r.dtype)),Dt.runKernel(function(t,e){var i=t.pow(n,r);return e([n,r,i]),i},{$base:n,$exp:r},function(t,e){var n=e[0],r=e[1],a=e[2];return{$base:function(){var e=r.toFloat(),a=t.mul(e.mul(n.pow(e.sub(Ln(1))))),o=ai(n.shape,i);return o.length>0&&(a=a.sum(o)),a.reshape(n.shape)},$exp:function(){var e=n.greater(0),o=n.log().where(e,Jn(n)),s=t.mul(a.mul(o)),u=ai(r.shape,i);return u.length>0&&(s=s.sum(u)),s.reshape(r.shape)}}})}}),Xs=In({powStrict_:function(t,e){return x(t.shape,e.shape,"Error in powStrict: "),t.pow(e)}}),$s=In({squaredDifference_:function(t,e){var n,r=kn(t,"a","squaredDifference"),i=kn(e,"b","squaredDifference");return n=At(r,i),r=n[0],i=n[1],oi(r.shape,i.shape),Dt.runKernel(function(t,e){var n=t.squaredDifference(r,i);return e([r,i]),n},{$a:r,$b:i},function(t,e){var n=e[0],r=e[1],i=Ln(2);return{$a:function(){return t.mul(n.sub(r).mul(i))},$b:function(){return t.mul(r.sub(n).mul(i))}}})}}),Ys=In({squaredDifferenceStrict_:function(t,e){var n=kn(t,"a","squaredDifferenceStrict"),r=kn(e,"b","squaredDifferenceStrict");return x(n.shape,r.shape,"Error in squaredDifferenceStrict: "),n.squaredDifference(r)}}),Js=In({sub_:function(t,e){var n,r=kn(t,"a","sub"),i=kn(e,"b","sub");n=At(r,i),r=n[0],i=n[1];var a=oi(r.shape,i.shape);return Dt.runKernel(function(t){return t.subtract(r,i)},{$a:r,$b:i},function(t){return{$a:function(){var e=t,n=ai(r.shape,a);return n.length>0&&(e=e.sum(n)),e.reshape(r.shape)},$b:function(){var e=t,n=ai(i.shape,a);return n.length>0&&(e=e.sum(n)),e.neg().reshape(i.shape)}}})}}),Zs=In({subStrict_:function(t,e){var n=kn(t,"a","subStrict"),r=kn(e,"b","subStrict");return x(n.shape,r.shape,"Error in subStrict: "),n.sub(r)}}),Qs=In({logicalAnd_:function(t,e){var n=kn(t,"a","logicalAnd","bool"),r=kn(e,"b","logicalAnd","bool");return oi(n.shape,r.shape),Dt.runKernel(function(t){return t.logicalAnd(n,r)},{$a:n,$b:r})}}),tu=In({logicalNot_:function(t){var e=kn(t,"x","logicalNot","bool");return Dt.runKernel(function(t){return t.logicalNot(e)},{$x:e})}}),eu=In({logicalOr_:function(t,e){var n=kn(t,"a","logicalOr","bool"),r=kn(e,"b","logicalOr","bool");return oi(n.shape,r.shape),Dt.runKernel(function(t){return t.logicalOr(n,r)},{$a:n,$b:r})}}),nu=In({logicalXor_:function(t,e){var n=kn(t,"a","logicalXor","bool"),r=kn(e,"b","logicalXor","bool");return oi(n.shape,r.shape),eu(t,e).logicalAnd(Qs(t,e).logicalNot())}}),ru=In({where_:function(t,e,n){var r=kn(e,"a","where"),i=kn(n,"b","where"),a=kn(t,"condition","where","bool");return x(r.shape,i.shape,"Error in where: "),1===a.rank?w(a.shape[0]===r.shape[0],function(){return"The first dimension of `a` must match the size of `condition`."}):x(a.shape,i.shape,"Error in where: "),Dt.runKernel(function(t,e){var n=t.select(a,r,i);return e([a]),n},{$condition:a,$a:r,$b:i},function(t,e){var n=e[0];return{$condition:function(){return Jn(n).toFloat()},$a:function(){return t.mul(n.cast(t.dtype))},$b:function(){return t.mul(n.logicalNot().cast(t.dtype))}}})}}),iu=function(t){return c(this,void 0,void 0,function(){var e,n,r;return l(this,function(i){switch(i.label){case 0:return[4,(e=kn(t,"condition","whereAsync","bool")).data()];case 1:return n=i.sent(),r=ei(e.shape,n),t!==e&&e.dispose(),[2,r]}})})},au=In({elu_:function(t){var e=kn(t,"x","elu");return Dt.runKernel(function(t,n){var r=t.elu(e);return n([r]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return Dt.runKernel(function(e){return e.eluDer(t,n)},{dy:t,y:n})}}})}}),ou=In({leakyRelu_:function(t,e){void 0===e&&(e=.2);var n=kn(t,"x","leakyRelu");return Fs(Ln(e).mul(n),n)}}),su=In({prelu_:function(t,e){var n=kn(t,"x","prelu"),r=kn(e,"alpha","prelu");return Dt.runKernel(function(t,e){var i=t.prelu(n,r);return e([n,r]),i},{$x:n,$alpha:r},function(t,e){var n=e[0],r=e[1],i=n.greater(0);return{$x:function(){return ru(i,t,t.mul(r))},$alpha:function(){var e=ru(i,Jn(t),t.mul(n)),a=ai(r.shape,t.shape);return a.length>0&&(e=e.sum(a)),e.reshape(r.shape)}}})}}),uu=In({relu_:function(t){var e=kn(t,"x","relu");return"bool"===e.dtype?e.toInt():Dt.runKernel(function(t,n){var r=t.relu(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){return t.mulStrict(n.step().toFloat())}}})}}),cu=In({selu_:function(t){var e=kn(t,"x","selu");return Dt.runKernel(function(t,n){var r=t.selu(e);return n([e]),r},{$x:e},function(t,e){var n=e[0];return{$x:function(){var e=n.greater(Ln(0)),r=Ln(1.7580993408473768),i=Ln(1.0507009873554805),a=t.mul(i),o=t.mul(r).mul(n.toFloat().exp());return ru(e,a,o)}}})}}),lu=In({transpose_:function(t,e){var n=kn(t,"x","transpose");return null==e&&(e=n.shape.map(function(t,e){return e}).reverse()),w(n.rank===e.length,function(){return"Error in transpose: rank of input "+n.rank+" must match length of perm "+e+"."}),e.forEach(function(t){w(t>=0&&ti)throw new Error("'k' passed to topk() must be <= the last dimension ("+i+") but got "+e);var a=Dt.runKernel(function(t){return t.topk(r,e,n)},{$x:r});return{values:a[0],indices:a[1]}}}),ku=In({scatterND_:function(t,e,n){var r=kn(t,"indices","scatterND","int32"),i=kn(e,"updates","scatterND");return function(t,e,n){if(e.rank<1)throw new Error("tf.scatterND() expects the indices to be rank 1 or higher, but the rank was "+e.rank+".");if(t.rank<1)throw new Error("tf.scatterND() expects the updates to be rank 1 or higher, but the rank was "+t.rank+".");if("int32"!==e.dtype)throw new Error("The dtype of 'indices' should be int32, but got dtype: "+e.dtype);if(n.length<1)throw new Error("Output rank must be greater or equal to 1, but got shape: "+n);if(0===n.length){if(0===e.size)throw new Error("Indices specified for empty output. indices shape: "+e.shape);if(0===t.size)throw new Error("Updates specified for empty output. updates shape: "+t.shape)}!function(t,e,n){var r=e.rank>1?e.shape[e.rank-1]:1,i=e.rank>1?e.rank-1:1,a="Must have updates.shape = indices.shape[:batchDim] + shape[sliceDim:], got updates.shape: "+n.shape+", indices.shape: "+e.shape+", shape: "+t+", sliceDim: "+r+", and batchDim: "+i+".";if(n.rank2)throw new Error("sparseIndices should be a scalar, vector, or matrix, but got shape "+t.shape+".");var i=t.rank>0?t.shape[0]:1,a=t.rank>1?t.shape[1]:1;if(n.length!==a)throw new Error("outputShape has incorrect number of elements:, "+n.length+", should be: "+a+".");var o=e.size;if(0!==e.rank&&(1!==e.rank||o!==i))throw new Error("sparseValues has incorrect shape "+e.shape+", should be [] or ["+i+"]");if(e.dtype!==r.dtype)throw new Error("sparseValues.dtype must match defaultValues.dtype")}(i,a,n,o),Dt.runKernel(function(t){return t.sparseToDense(i,a,n,o)},{$sparseIndices:i,$sparseValues:a,$defaultValue:o})}}),Ou=In({gatherND_:function(t,e){var n=kn(e,"indices","gatherND","int32"),r=kn(t,"x","gatherND");return Dt.runKernel(function(t){return t.gatherND(r,n)},{$x:r,$indices:n})}}),Tu=In({dropout_:function(t,e,n,r){if(null!=n&&!E(t.shape,n))throw new Error("Non-default noise shape is not implemented yet: "+JSON.stringify(n));var i=Gr(t.shape,0,1,"float32",r).greater(e);return i=i.div(Js(1,e)),t.mul(i)}});function Iu(t,e,n){for(var r=1-t%2,i=new Float32Array(t),a=0;a1?s.div(Ln(o)):s}if(n===Mu.SUM_BY_NONZERO_WEIGHTS){if(null==i)return a.sum().div(Ln(r.size));var u=i.mul(Hn(r.shape)).notEqual(Ln(0)).sum().toFloat();return a.sum().div(u)}throw Error("Unknown reduction: "+n)}}),Pu=In({cosineDistance_:function(t,e,n,r,i){void 0===i&&(i=Mu.SUM_BY_NONZERO_WEIGHTS);var a=kn(t,"labels","cosineDistance"),o=kn(e,"predictions","cosineDistance"),s=null;null!=r&&(s=kn(r,"weights","cosineDistance")),x(a.shape,o.shape,"Error in cosineDistance: ");var u=Ln(1).sub(a.mul(o).sum(n,!0));return zu(u,s,i)}}),Lu=In({hingeLoss_:function(t,e,n,r){void 0===r&&(r=Mu.SUM_BY_NONZERO_WEIGHTS);var i=kn(t,"labels","hingeLoss"),a=kn(e,"predictions","hingeLoss"),o=null;null!=n&&(o=kn(n,"weights","hingeLoss")),x(i.shape,a.shape,"Error in hingeLoss: ");var s=Ln(1);i=Ln(2).mul(i).sub(s);var u=s.sub(i.mul(a)).relu();return zu(u,o,r)}}),Fu=In({huberLoss_:function(t,e,n,r,i){void 0===r&&(r=1),void 0===i&&(i=Mu.SUM_BY_NONZERO_WEIGHTS);var a=kn(t,"labels","huberLoss"),o=kn(e,"predictions","huberLoss"),s=null;null!=n&&(s=kn(n,"weights","huberLoss")),x(a.shape,o.shape,"Error in huberLoss: ");var u=Ln(r),c=o.sub(a).abs(),l=Us(c,u),f=c.sub(l),h=Ln(.5).mul(l.square()).add(u.mul(f));return zu(h,s,i)}}),Bu=In({logLoss_:function(t,e,n,r,i){void 0===r&&(r=1e-7),void 0===i&&(i=Mu.SUM_BY_NONZERO_WEIGHTS);var a=kn(t,"labels","logLoss"),o=kn(e,"predictions","logLoss"),s=null;null!=n&&(s=kn(n,"weights","logLoss")),x(a.shape,o.shape,"Error in logLoss: ");var u=Ln(1),c=Ln(r),l=a.mul(o.add(c).log()).neg().sub(u.sub(a).mul(u.sub(o).add(c).log()));return zu(l,s,i)}}),Uu=In({meanSquaredError_:function(t,e,n,r){void 0===r&&(r=Mu.SUM_BY_NONZERO_WEIGHTS);var i=kn(t,"labels","meanSquaredError"),a=kn(e,"predictions","meanSquaredError"),o=null;null!=n&&(o=kn(n,"weights","meanSquaredError")),x(i.shape,a.shape,"Error in meanSquaredError: ");var s=i.squaredDifference(a);return zu(s,o,r)}}),Vu=In({sigmoidCrossEntropy_:function(t,e,n,r,i){void 0===r&&(r=0),void 0===i&&(i=Mu.SUM_BY_NONZERO_WEIGHTS);var a=kn(t,"multiClassLabels","sigmoidCrossEntropy"),o=kn(e,"logits","sigmoidCrossEntropy"),s=null;if(null!=n&&(s=kn(n,"weights","sigmoidCrossEntropy")),x(a.shape,o.shape,"Error in sigmoidCrossEntropy: "),r>0){var u=Ln(r),c=Ln(1),l=Ln(.5);a=a.mul(c.sub(u)).add(l.mul(u))}var f=function(t,e){var n=kn(t,"labels","sigmoidCrossEntropyWithLogits"),r=kn(e,"logits","sigmoidCrossEntropyWithLogits");x(n.shape,r.shape,"Error in sigmoidCrossEntropyWithLogits: ");var i=r.relu(),a=r.mul(n),o=r.abs().neg().exp().log1p();return i.sub(a).add(o)}(a,o);return zu(f,s,i)}}),Wu=In({softmaxCrossEntropy_:function(t,e,n,r,i){void 0===r&&(r=0),void 0===i&&(i=Mu.SUM_BY_NONZERO_WEIGHTS);var a=kn(t,"onehotLabels","softmaxCrossEntropy"),o=kn(e,"logits","softmaxCrossEntropy"),s=null;if(null!=n&&(s=kn(n,"weights","softmaxCrossEntropy")),x(a.shape,o.shape,"Error in softmaxCrossEntropy: "),r>0){var u=Ln(r),c=Ln(1),l=Ln(a.shape[1]);a=a.mul(c.sub(u)).add(u.div(l))}var f=function(t,e,n){if(void 0===n&&(n=-1),-1===n&&(n=e.rank-1),n!==e.rank-1)throw Error("Softmax cross entropy along a non-last dimension is not yet supported. Labels / logits was rank "+e.rank+" and dim was "+n);return On(function(t,e,r){var i=e.logSumExp([n],!0),a=e.toFloat().sub(i);return r([t,a]),{value:a.mul(t).neg().sum([n]),gradFunc:function(t,e){var r=e[0],i=e[1],a=an(t.shape,[n]);return[t.reshape(a).mul(r.toFloat().sub(i.exp())),t.reshape(a).mul(i.exp().sub(r.toFloat()))]}}})(t,e)}(a,o);return zu(f,s,i)}}),qu=Object.freeze({get Reduction(){return Mu},absoluteDifference:ju,computeWeightedLoss:zu,cosineDistance:Pu,hingeLoss:Lu,huberLoss:Fu,logLoss:Bu,meanSquaredError:Uu,sigmoidCrossEntropy:Vu,softmaxCrossEntropy:Wu});function Hu(t,e){return void 0===e&&(e=!1),Dt.tidy(function(){if(2!==t.shape.length)throw new Error("qr2d() requires a 2D Tensor, but got a "+t.shape.length+"D Tensor.");for(var n=t.shape[0],r=t.shape[1],i=zr(n),a=t.clone(),o=Bn([[1]],[1,1]),s=o.clone(),u=n>=r?r:n,c=function(t){var e,u=a,c=s,l=i;e=Dt.tidy(function(){var e=a.slice([t,t],[n-t,1]),u=e.norm(),c=a.slice([t,t],[1,1]),l=c.sign().neg(),f=c.sub(l.mul(u)),h=e.div(f);s=1===h.shape[0]?o.clone():o.concat(h.slice([1,0],[h.shape[0]-1,h.shape[1]]),0);var d=l.matMul(f).div(u).neg(),p=a.slice([t,0],[n-t,r]),m=d.mul(s);a=0===t?p.sub(m.matMul(s.transpose().matMul(p))):a.slice([0,0],[t,r]).concat(p.sub(m.matMul(s.transpose().matMul(p))),0);var v=i.slice([0,t],[n,i.shape[1]-t]);return i=0===t?v.sub(v.matMul(s).matMul(m.transpose())):i.slice([0,0],[n,t]).concat(v.sub(v.matMul(s).matMul(m.transpose())),1),[s,a,i]}),s=e[0],a=e[1],i=e[2],Fe([u,c,l])},l=0;lr&&(i=i.slice([0,0],[n,r]),a=a.slice([0,0],[r,r])),[i,a]})}var Gu=In({gramSchmidt_:function(t){var e;if(Array.isArray(t)){e=!1,w(null!=t&&t.length>0,function(){return"Gram-Schmidt process: input must not be null, undefined, or empty"});for(var n=t[0].shape[0],r=function(e){w(t[e].shape[0]===n,function(){return"Gram-Schmidt: Non-unique lengths found in the input vectors: ("+t[e].shape[0]+" vs. "+n+")"})},i=1;i0)for(var n=0;n= 2, but got rank "+t.rank);if(2===t.rank)return Hu(t,e);var n=t.shape.slice(0,t.shape.length-2).reduce(function(t,e){return t*e}),r=[],i=[];return Qr(t.reshape([n,t.shape[t.shape.length-2],t.shape[t.shape.length-1]]),0).forEach(function(t){var n=Hu(t,e),a=n[0],o=n[1];r.push(a),i.push(o)}),[Yr(r,0).reshape(t.shape),Yr(i,0).reshape(t.shape)]}}),Xu=Object.freeze({gramSchmidt:Gu,qr:Ku});function $u(t,e,n,r,i){null==r&&(r=.5),null==i&&(i=Number.NEGATIVE_INFINITY);var a=t.shape[0];return n=Math.min(n,a),w(0<=r&&r<=1,function(){return"iouThreshold must be in [0, 1], but was '"+r+"'"}),w(2===t.rank,function(){return"boxes must be a 2D tensor, but was of rank '"+t.rank+"'"}),w(4===t.shape[1],function(){return"boxes must have 4 columns, but 2nd dimension was "+t.shape[1]}),w(1===e.rank,function(){return"scores must be a 1D tensor"}),w(e.shape[0]===a,function(){return"scores has incompatible shape with boxes. Expected "+a+", but was "+e.shape[0]}),{maxOutputSize:n,iouThreshold:r,scoreThreshold:i}}var Yu=In({resizeBilinear_:function(t,e,n){void 0===n&&(n=!1);var r=kn(t,"images","resizeBilinear");w(3===r.rank||4===r.rank,function(){return"Error in resizeBilinear: x must be rank 3 or 4, but got rank "+r.rank+"."}),w(2===e.length,function(){return"Error in resizeBilinear: new shape must 2D, but got shape "+e+"."});var i=r,a=!1;3===r.rank&&(a=!0,i=r.as4D(1,r.shape[0],r.shape[1],r.shape[2]));var o=e[0],s=e[1],u=Dt.runKernel(function(t,e){return e([i]),t.resizeBilinear(i,o,s,n)},{batchImages:i},function(t,e){return{batchImages:function(){return Dt.runKernel(function(r){return r.resizeBilinearBackprop(t,e[0],n)},{})}}});return a?u.as3D(u.shape[1],u.shape[2],u.shape[3]):u}}),Ju=In({resizeNearestNeighbor_:function(t,e,n){void 0===n&&(n=!1);var r=kn(t,"images","resizeNearestNeighbor");w(3===r.rank||4===r.rank,function(){return"Error in resizeNearestNeighbor: x must be rank 3 or 4, but got rank "+r.rank+"."}),w(2===e.length,function(){return"Error in resizeNearestNeighbor: new shape must 2D, but got shape "+e+"."}),w("float32"===r.dtype||"int32"===r.dtype,function(){return"`images` must have `int32` or `float32` as dtype"});var i=r,a=!1;3===r.rank&&(a=!0,i=r.as4D(1,r.shape[0],r.shape[1],r.shape[2]));var o=e[0],s=e[1],u=Dt.runKernel(function(t,e){return e([i]),t.resizeNearestNeighbor(i,o,s,n)},{batchImages:i},function(t,e){return{batchImages:function(){return Dt.runKernel(function(r){return r.resizeNearestNeighborBackprop(t,e[0],n)},{})}}});return a?u.as3D(u.shape[1],u.shape[2],u.shape[3]):u}}),Zu=In({nonMaxSuppression_:function(t,e,n,r,i){void 0===r&&(r=.5),void 0===i&&(i=Number.NEGATIVE_INFINITY);var a=kn(t,"boxes","nonMaxSuppression"),o=kn(e,"scores","nonMaxSuppression"),s=$u(a,o,n,r,i);return n=s.maxOutputSize,r=s.iouThreshold,i=s.scoreThreshold,Dt.runKernel(function(t){return t.nonMaxSuppression(a,o,n,r,i)},{$boxes:a})}}),Qu=In({cropAndResize_:function(t,e,n,r,i,a){var o=kn(t,"image","cropAndResize","float32"),s=kn(e,"boxes","cropAndResize","float32"),u=kn(n,"boxInd","cropAndResize","int32");i=i||"bilinear",a=a||0;var c=s.shape[0];return w(4===o.rank,function(){return"Error in cropAndResize: image must be rank 4,but got rank "+o.rank+"."}),w(2===s.rank&&4===s.shape[1],function(){return"Error in cropAndResize: boxes must be have size ["+c+",4] but had shape "+s.shape+"."}),w(1===u.rank&&u.shape[0]===c,function(){return"Error in cropAndResize: boxInd must be have size ["+c+"] but had shape "+s.shape+"."}),w(2===r.length,function(){return"Error in cropAndResize: cropSize must be of length 2, but got length "+r.length+"."}),w(r[0]>=1&&r[1]>=1,function(){return"cropSize must be atleast [1,1], but was "+r}),w("bilinear"===i||"nearest"===i,function(){return"method must be bilinear or nearest, but was "+i}),Dt.runKernel(function(t,e){return t.cropAndResize(o,s,u,r,i,a)},{$image:o,$boxes:s})}}),tc=Object.freeze({resizeBilinear:Yu,resizeNearestNeighbor:Ju,nonMaxSuppression:Zu,nonMaxSuppressionAsync:function(t,e,n,r,i){return void 0===r&&(r=.5),void 0===i&&(i=Number.NEGATIVE_INFINITY),c(this,void 0,void 0,function(){var a,o,s,u,c,f;return l(this,function(l){switch(l.label){case 0:return a=kn(t,"boxes","nonMaxSuppressionAsync"),o=kn(e,"scores","nonMaxSuppressionAsync"),s=$u(a,o,n,r,i),n=s.maxOutputSize,r=s.iouThreshold,i=s.scoreThreshold,[4,a.data()];case 1:return u=l.sent(),[4,o.data()];case 2:return c=l.sent(),f=sr(u,c,n,r,i),a!==t&&a.dispose(),o!==e&&o.dispose(),[2,f]}})})},cropAndResize:Qu}),ec=In({matMul_:function(t,e,n,r,i,a){var o;void 0===n&&(n=!1),void 0===r&&(r=!1),void 0===a&&(a="linear");var s=kn(t,"a","fused matMul"),u=kn(e,"b","fused matMul");o=At(s,u),s=o[0],u=o[1];var c=n?s.shape[s.rank-2]:s.shape[s.rank-1],l=r?u.shape[u.rank-1]:u.shape[u.rank-2],f=n?s.shape[s.rank-1]:s.shape[s.rank-2],h=r?u.shape[u.rank-2]:u.shape[u.rank-1],d=s.shape.slice(0,-2),p=u.shape.slice(0,-2),m=_(d),v=_(p);w(s.rank>=2&&u.rank>=2&&s.rank===u.rank,function(){return"Error in fused matMul: inputs must have the same rank of at least 2, got ranks "+s.rank+" and "+u.rank+"."}),w(E(d,p),function(){return"Error in fused matMul: outer dimensions ("+d+") and ("+p+") of Tensors with shapes "+s.shape+" and "+u.shape+" must match."}),w(c===l,function(){return"Error in fused matMul: inner shapes ("+c+") and ("+l+") of Tensors with shapes "+s.shape+" and "+u.shape+" and transposeA="+n+" and transposeB="+r+" must match."});var g,b=s.shape.slice(0,-2).concat([f,h]),y=n?s.as3D(m,c,f):s.as3D(m,f,c),x=r?u.as3D(v,h,l):u.as3D(v,l,h);null!=i&&oi(b,(g=At(g=kn(i,"bias","fused matMul"),s)[0]).shape);var k={$a:y,$b:x};return null!=i&&(k.$bias=g),Dt.runKernel(function(t,e){var i=t.fusedBatchMatMul(y,x,n,r,g,a);return e([y,x,i]),i},k,function(t,e){var o,s=e[0],u=e[1],c=e[2];if(null==a||"linear"===a)o=t;else{if("relu"!==a)throw new Error("Gradient for activation "+a+" has not been implemented yet.");o=t.mul(c.step())}var l={};return null!=i&&(l={$bias:function(){var t=o,e=ai(g.shape,o.shape);return e.length>0&&(t=t.sum(e)),t.reshape(g.shape)}}),n||r?!n&&r?Object.assign({$a:function(){return o.matMul(u,!1,!1)},$b:function(){return o.matMul(s,!0,!1)}},l):n&&!r?Object.assign({$a:function(){return u.matMul(o,!1,!0)},$b:function(){return s.matMul(o,!1,!1)}},l):Object.assign({$a:function(){return u.matMul(o,!0,!0)},$b:function(){return o.matMul(s,!0,!0)}},l):Object.assign({$a:function(){return o.matMul(u,!1,!0)},$b:function(){return s.matMul(o,!0,!1)}},l)}).reshape(b)}}),nc=Object.freeze({matMul:ec}),rc=Object.freeze({image:tc,linalg:Xu,losses:qu,spectral:Au,fused:nc,op:In,batchNormalization2d:go,batchNormalization3d:bo,batchNormalization4d:yo,batchNormalization:wo,batchNorm:xo,batchNorm2d:ko,batchNorm3d:So,batchNorm4d:_o,complex:Dn,real:jn,imag:zn,concat:fr,concat1d:hr,concat2d:dr,concat3d:pr,concat4d:mr,split:vr,conv1d:Po,conv2d:Lo,conv3d:Fo,conv2dDerFilter:Bo,depthwiseConv2d:Uo,separableConv2d:Vo,conv2dTranspose:Wo,matMul:qo,dot:Ho,outerProduct:Go,reverse:Ko,reverse1d:Xo,reverse2d:$o,reverse3d:Yo,reverse4d:Jo,maxPool:ts,avgPool:es,pool:ns,slice:rs,slice1d:is,slice2d:as,slice3d:os,slice4d:ss,abs:Oa,acos:Ta,acosh:Ia,asin:Ma,asinh:Ra,atan:Da,atanh:ja,ceil:za,clipByValue:Pa,cos:La,cosh:Fa,erf:Ba,exp:Ua,expm1:Va,floor:Wa,log:qa,log1p:Ha,logSigmoid:Ga,neg:Ka,reciprocal:Xa,round:$a,rsqrt:Ya,sigmoid:Ja,sign:Za,isNaN:Qa,isInf:to,isFinite:eo,sin:no,sinh:ro,softplus:io,sqrt:ao,square:oo,step:so,tan:uo,tanh:co,all:cs,any:ls,argMax:fs,argMin:hs,logSumExp:ds,max:ps,mean:ms,min:vs,moments:gs,sum:bs,prod:ys,equal:ws,equalStrict:xs,greater:ks,greaterEqual:Ss,greaterEqualStrict:_s,greaterStrict:Es,less:Cs,lessEqual:As,lessEqualStrict:Ns,lessStrict:Os,notEqual:Ts,notEqualStrict:Is,add:Ms,addN:Rs,addStrict:Ds,atan2:js,div:zs,divStrict:Ps,floorDiv:Ls,maximum:Fs,maximumStrict:Bs,minimum:Us,minimumStrict:Vs,mod:Ws,modStrict:qs,mul:Hs,mulStrict:Gs,pow:Ks,powStrict:Xs,squaredDifference:$s,squaredDifferenceStrict:Ys,sub:Js,subStrict:Zs,elu:au,leakyRelu:ou,prelu:su,relu:uu,selu:cu,logicalAnd:Qs,logicalNot:tu,logicalOr:eu,logicalXor:nu,where:ru,whereAsync:iu,buffer:Nr,print:Or,batchToSpaceND:Tr,cast:Ir,clone:Mr,cumsum:Rr,depthToSpace:Dr,expandDims:jr,eye:zr,multinomial:Pr,oneHot:Lr,pad:Fr,pad1d:Br,pad2d:Ur,pad3d:Vr,pad4d:Wr,rand:qr,randomNormal:Hr,randomUniform:Gr,reshape:Kr,spaceToBatchND:Xr,squeeze:$r,stack:Yr,tile:Jr,truncatedNormal:Zr,unstack:Qr,setdiff1dAsync:ti,fill:Kn,linspace:Xn,ones:Hn,range:$n,scalar:Ln,tensor:Pn,tensor1d:Fn,tensor2d:Bn,tensor3d:Un,tensor4d:Vn,tensor5d:Wn,tensor6d:qn,zeros:Gn,onesLike:Yn,zerosLike:Jn,transpose:lu,softmax:Mn,logSoftmax:Rn,localResponseNormalization:fu,norm:hu,gather:mu,unsortedSegmentSum:vu,basicLSTMCell:gu,multiRNNCell:bu,movingAverage:yu,stridedSlice:wu,topk:xu,scatterND:ku,fft:Su,ifft:_u,rfft:Eu,irfft:Cu,sparseToDense:Nu,gatherND:Ou,dropout:Tu,hannWindow:Ru,hammingWindow:Du}),ic=function(){function t(){this.blockSize=48,this.firstUse=!0,f.get("IS_BROWSER")&&(this.fromPixels2DContext=document.createElement("canvas").getContext("2d")),this.data=new Zn(Dt)}return t.prototype.register=function(t,e,n){if(this.firstUse&&(this.firstUse=!1,f.get("IS_NODE")&&Ye("\n============================\nHi there 👋. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.\n============================\n")),this.data.has(t))throw new Error("Data buffer is already registered");this.data.set(t,{dtype:n})},t.prototype.write=function(t,e){if(null==e)throw new Error("MathBackendCPU.write(): values can not be null");this.data.get(t).values=e},t.prototype.fromPixels=function(t,e){if(null==t)throw new Error("pixels passed to tf.browser.fromPixels() can not be null");var n,r;if(f.get("IS_NODE")&&null==t.getContext)throw new Error("When running in node, pixels must be an HTMLCanvasElement like the one returned by the `canvas` npm package");if(null!=t.getContext)n=t.getContext("2d").getImageData(0,0,t.width,t.height).data;else if(t instanceof ImageData)n=t.data;else{if(!(t instanceof HTMLImageElement||t instanceof HTMLVideoElement))throw new Error("pixels passed to tf.browser.fromPixels() must be either an HTMLVideoElement, HTMLImageElement, HTMLCanvasElement or ImageData, but was "+t.constructor.name);if(null==this.fromPixels2DContext)throw new Error("Can't read pixels from HTMLImageElement outside the browser.");this.fromPixels2DContext.canvas.width=t.width,this.fromPixels2DContext.canvas.height=t.height,this.fromPixels2DContext.drawImage(t,0,0,t.width,t.height),n=this.fromPixels2DContext.getImageData(0,0,t.width,t.height).data}if(4===e)r=new Int32Array(n);else{var i=t.width*t.height;r=new Int32Array(i*e);for(var a=0;ah&&(h=m,d=p)}u[l]=d}return o},t.prototype.cumsum=function(t,e,n,r){if(this.assertNotComplex(t,"cumsum"),e!==t.rank-1)throw new Error("backend.cumsum in CPU expects an inner-most axis="+(t.rank-1)+" but got axis="+e);for(var i=Et(t.dtype,"int32"),a=Gn(t.shape,i),o=a.dataSync(),s=t.dataSync(),u=t.shape[t.rank-1],c=r?function(t,e){return t+u-e-1}:function(t,e){return t+e},l=0;le?1:0})},t.prototype.greaterEqual=function(t,e){return this.assertNotComplex([t,e],"greaterEqual"),this.broadcastedBinaryOp(t,e,"bool",function(t,e){return t>=e?1:0})},t.prototype.logicalNot=function(t){this.assertNotComplex(t,"logicalNot");for(var e=t.dataSync(),n=new Uint8Array(e.length),r=0;r1||1===e.rank?1:e.shape[1],l=0;l=0&&e>=0?n:(n+e)%e})},t.prototype.max=function(t,e){this.assertNotComplex(t,"max"),on("max",e,t.rank);for(var n=rn(t.shape,e),r=n[0],i=n[1],a=Gn(r,t.dtype),o=_(i),s=a.dataSync(),u=t.dataSync(),c=0;cf&&(f=d)}s[c]=f}return a},t.prototype.maximum=function(t,e){return this.assertNotComplex([t,e],"maximum"),this.broadcastedBinaryOp(t,e,t.dtype,function(t,e){return Math.max(t,e)})},t.prototype.all=function(t,e){this.assertNotComplex(t,"all"),on("all",e,t.rank);for(var n=rn(t.shape,e),r=n[0],i=n[1],a=Gn(r,t.dtype),o=_(i),s=a.dataSync(),u=t.dataSync(),c=0;c0?n[r]=1:n[r]=0;return vt.make(t.shape,{values:n})},t.prototype.isNaN=function(t){this.assertNotComplex(t,"x");for(var e=t.dataSync(),n=new Uint8Array(e.length),r=0;r.5?n[r]=Math.ceil(e[r]):n[r]=i%2==0?i:i+1}return vt.make(t.shape,{values:n})},t.prototype.exp=function(t){this.assertNotComplex(t,"exp");for(var e=t.dataSync(),n=new Float32Array(e.length),r=0;r=0?i:Math.exp(i)-1}return vt.make(t.shape,{values:e})},t.prototype.eluDer=function(t,e){this.assertNotComplex([t,e],"eluDer");for(var n=new Float32Array(e.size),r=e.dataSync(),i=t.dataSync(),a=0;a=1?i[a]:i[a]*(o+1)}return vt.make(e.shape,{values:n})},t.prototype.selu=function(t){this.assertNotComplex(t,"selu");for(var e=new Float32Array(t.size),n=t.dataSync(),r=0;r=0?1.0507009873554805*i:1.7580993408473768*(Math.exp(i)-1)}return vt.make(t.shape,{values:e})},t.prototype.clip=function(t,e,n){this.assertNotComplex(t,"clip");for(var r=new Float32Array(t.size),i=t.dataSync(),a=0;an?n:o-e,s=r[i]0?1:e}return vt.make(t.shape,{values:n})},t.prototype.conv2d=function(t,e,n){this.assertNotComplex([t,e],"conv2d");for(var r=n.filterHeight,i=n.filterWidth,a=n.dilationHeight,o=n.dilationWidth,s=n.padInfo.left,u=n.padInfo.top,c=Nr(n.outShape,t.dtype),l=t.dataSync(),f=e.dataSync(),h=c.values,d=0;d=n.inHeight))for(var x=y*e.strides[0],k=p+w*t.strides[1],S=0;S=n.inWidth))for(var N=x+C*e.strides[1],O=k+A*n.inChannels,T=N,I=0;I=n.inDepth))for(var _=k*e.strides[0],E=g+S*t.strides[1],C=0;C=n.inHeight))for(var I=_+O*e.strides[1],M=E+T*t.strides[2],R=0;R=n.inWidth))for(var L=I+z*e.strides[2],F=M+P*n.inChannels,B=L,U=0;U=n.inHeight))for(var k=w*e.strides[0],S=m+x*t.strides[1],_=0;_=n.inWidth))for(var O=k+A*e.strides[1],T=S+N*n.inChannels,I=E,M=O,R=0;RI?I=P:"avg"===n&&(M+=P,R++)}if(isNaN(I))break}p[C+A*g+x]="avg"===n?M/R:I}return d.toTensor()},t.prototype.maxPool=function(t,e){return this.pool(t,e,"max")},t.prototype.maxPoolPositions=function(t,e){for(var n=Nr(e.outShape,"int32"),r=e.strideHeight,i=e.strideWidth,a=e.dilationHeight,o=e.dilationWidth,s=e.effectiveFilterHeight,u=e.effectiveFilterWidth,c=e.padInfo.top,l=e.padInfo.left,f=t.bufferSync(),h=0;hk&&(k=N,S=E*u+A)}n.set(S,h,p,b,d)}}return n.toTensor()},t.prototype.maxPoolBackprop=function(t,e,n,r){this.assertNotComplex([e,n],"maxPoolBackprop");for(var i=this.maxPoolPositions(e,r),a=r.strideHeight,o=r.strideWidth,s=r.dilationHeight,u=r.dilationWidth,c=r.effectiveFilterHeight,l=r.effectiveFilterWidth,f=l-1-r.padInfo.left,h=c-1-r.padInfo.top,d=Nr(e.shape,"float32"),p=i.bufferSync(),m=t.bufferSync(),v=0;v=r.outHeight||Math.floor(_)!==_))for(var E=0;E=r.outWidth||Math.floor(C)!==C)){var A=c*l-1-p.get(v,_,C,g)===S*l+E?1:0;0!==A&&(k+=m.get(v,_,C,g)*A)}}}d.set(k,v,b,y,g)}return d.toTensor()},t.prototype.avgPoolBackprop=function(t,e,n){this.assertNotComplex([t,e],"avgPoolBackprop");for(var r=n.strideHeight,i=n.strideWidth,a=n.filterHeight,o=n.filterWidth,s=n.dilationHeight,u=n.dilationWidth,c=n.effectiveFilterHeight,l=n.effectiveFilterWidth,f=l-1-n.padInfo.left,h=c-1-n.padInfo.top,d=Nr(e.shape,"float32"),p=1/(a*o),m=t.bufferSync(),v=0;v=n.outHeight||Math.floor(_)!==_))for(var E=0;E=n.outWidth||Math.floor(C)!==C||(k+=m.get(v,_,C,g))}}d.set(k*p,v,b,y,g)}return d.toTensor()},t.prototype.cast=function(t,e){return tr(t,e,this)},t.prototype.reshape=function(t,e){return er(t,e)},t.prototype.avgPool=function(t,e){return this.assertNotComplex(t,"avgPool"),this.pool(t,e,"avg").toFloat()},t.prototype.resizeBilinear=function(t,e,n,r){this.assertNotComplex(t,"resizeBilinear");for(var i=t.shape,a=i[0],o=i[1],s=i[2],u=i[3],c=t.dataSync(),l=new Float32Array(_([a,e,n,u])),f=[r&&e>1?o-1:o,r&&n>1?s-1:s],h=[r&&e>1?e-1:e,r&&n>1?n-1:n],d=0,p=f[0]/h[0],m=f[1]/h[1],v=0;v1?a-1:a,n&&l>1?o-1:o],d=[n&&c>1?c-1:c,n&&l>1?l-1:l],p=h[0]/d[0],m=h[1]/d[1],v=t.dataSync(),g=0,b=0;b1?o-1:o,r&&n>1?s-1:s],h=[r&&e>1?e-1:e,r&&n>1?n-1:n],d=f[0]/h[0],p=f[1]/h[1],m=0,v=0;v1?a-1:a,n&&l>1?o-1:o],p=[n&&c>1?c-1:c,n&&l>1?l-1:l],m=d[0]/p[0],v=d[1]/p[1],g=1/m,b=1/v,y=2*Math.ceil(g)+2,w=2*Math.ceil(b)+2,x=0;x=c)){var j=k+D*t.strides[1],z=D*m;if(S===Math.min(a-1,n?Math.round(z):Math.floor(z)))for(var P=0;P=l)){var F=j+L*t.strides[2],B=L*v;A===Math.min(o-1,n?Math.round(B):Math.floor(B))&&(M+=h[F+I])}}}}f[N+I]=M}return Vn(f,e.shape,e.dtype)},t.prototype.batchNormalization=function(t,e,n,r,i,a){this.assertNotComplex([t,e,n,i,a],"batchNorm");for(var o=t.dataSync(),s=e.dataSync(),u=n.dataSync(),c=i?i.dataSync():new Float32Array([1]),l=a?a.dataSync():new Float32Array([0]),f=new Float32Array(o.length),h=l.length,d=c.length,p=u.length,m=s.length,v=0,g=0,b=0,y=0,w=0;w=h&&(v=0),g>=m&&(g=0),b>=d&&(b=0),y>=p&&(y=0);return Vn(f,t.shape)},t.prototype.localResponseNormalization4D=function(t,e,n,r,i){this.assertNotComplex(t,"localResponseNormalization4D");var a=t.shape[3],o=a-1,s=t.dataSync(),u=t.size,c=new Float32Array(u);function l(t){for(var n=t%a,r=t-n+Math.max(0,n-e),i=t-n+Math.min(n+e,o),u=0;r<=i;r++){var c=s[r];u+=c*c}return u}for(var f=0;f=0&&a[o]1,function(){return"blockSize should be > 1 for depthToSpace, but was: "+e});for(var r=t.shape[0],i=t.shape[1],a=t.shape[2],o=t.shape[3],s=i*e,u=a*e,c=o/(e*e),l=t.dataSync(),f=new Float32Array(r*s*u*c),h=0,d=0;d=s))for(var A=h>1?(_-k)*(u-1)/(h-1):0,N=d>1?(E-S)*(c-1)/(d-1):0,O=0;O1?k*(u-1)+O*A:.5*(k+_)*(u-1);if(T<0||T>u-1)for(var I=0;I1?S*(c-1)+I*N:.5*(S+E)*(c-1))<0||H>c-1)for(M=0;M1?S*(c-1)+I*N:.5*(S+E)*(c-1))<0||H>c-1)for(M=0;M=t.size/s)throw new Error("Invalid indices: "+d+" does not index into "+t.shape);for(var g=0;g=r/i)throw new Error("Invalid indices: "+m+" does not index into "+n);for(var y=0;y0,function(){return"scheme must not be an empty string."});var r=t.getInstance();w(null==r.managers[e],function(){return"A model store manager is already registered for scheme '"+e+"'."}),r.managers[e]=n},t.getManager=function(t){var e=this.getInstance().managers[t];if(null==e)throw new Error("Cannot find model manager for scheme '"+t+"'");return e},t.getSchemes=function(){return Object.keys(this.getInstance().managers)},t}();function mc(t){if(-1===t.indexOf(dc))throw new Error("The url string provided does not contain a scheme. Supported schemes are: "+pc.getSchemes().join(","));return{scheme:t.split(dc)[0],path:t.split(dc)[1]}}function vc(t,e,n){return void 0===n&&(n=!1),c(this,void 0,void 0,function(){var r,i,a,o,s,u,c,f,h;return l(this,function(l){switch(l.label){case 0:return w(t!==e,function(){return"Old path and new path are the same: '"+t+"'"}),w((r=hc.getLoadHandlers(t)).length>0,function(){return"Copying failed because no load handler is found for source URL "+t+"."}),w(r.length<2,function(){return"Copying failed because more than one ("+r.length+") load handlers for source URL "+t+"."}),i=r[0],w((a=hc.getSaveHandlers(e)).length>0,function(){return"Copying failed because no save handler is found for destination URL "+e+"."}),w(a.length<2,function(){return"Copying failed because more than one ("+r.length+") save handlers for destination URL "+e+"."}),o=a[0],s=mc(t).scheme,u=mc(t).path,c=s===mc(t).scheme,[4,i.load()];case 1:return f=l.sent(),n&&c?[4,pc.getManager(s).removeModel(u)]:[3,3];case 2:l.sent(),l.label=3;case 3:return[4,o.save(f)];case 4:return h=l.sent(),!n||c?[3,6]:[4,pc.getManager(s).removeModel(u)];case 5:l.sent(),l.label=6;case 6:return[2,h.modelArtifactsInfo]}})})}var gc="models_store",bc="model_info_store";function yc(){if(!f.getBool("IS_BROWSER"))throw new Error("Failed to obtain IndexedDB factory because the current environmentis not a web browser.");var t=window,e=t.indexedDB||t.mozIndexedDB||t.webkitIndexedDB||t.msIndexedDB||t.shimIndexedDB;if(null==e)throw new Error("The current browser does not appear to support IndexedDB.");return e}function wc(t){var e=t.result;e.createObjectStore(gc,{keyPath:"modelPath"}),e.createObjectStore(bc,{keyPath:"modelPath"})}var xc=function(){function t(t){if(this.indexedDB=yc(),null==t||!t)throw new Error("For IndexedDB, modelPath must not be null, undefined or empty.");this.modelPath=t}return t.prototype.save=function(t){return c(this,void 0,void 0,function(){return l(this,function(e){if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserLocalStorage.save() does not support saving model topology in binary formats yet.");return[2,this.databaseAction(this.modelPath,t)]})})},t.prototype.load=function(){return c(this,void 0,void 0,function(){return l(this,function(t){return[2,this.databaseAction(this.modelPath)]})})},t.prototype.databaseAction=function(t,e){var n=this;return new Promise(function(t,r){var i=n.indexedDB.open("tensorflowjs",1);i.onupgradeneeded=function(){return wc(i)},i.onsuccess=function(){var a=i.result;if(null==e){var o=a.transaction(gc,"readonly"),s=o.objectStore(gc).get(n.modelPath);s.onsuccess=function(){if(null==s.result)return a.close(),r(new Error("Cannot find model with path '"+n.modelPath+"' in IndexedDB."));t(s.result.modelArtifacts)},s.onerror=function(t){return a.close(),r(s.error)},o.oncomplete=function(){return a.close()}}else{var u,c=fc(e),l=a.transaction(bc,"readwrite"),f=l.objectStore(bc),h=f.put({modelPath:n.modelPath,modelArtifactsInfo:c});h.onsuccess=function(){var i=(u=a.transaction(gc,"readwrite")).objectStore(gc).put({modelPath:n.modelPath,modelArtifacts:e,modelArtifactsInfo:c});i.onsuccess=function(){return t({modelArtifactsInfo:c})},i.onerror=function(t){var e=(f=l.objectStore(bc)).delete(n.modelPath);e.onsuccess=function(){return a.close(),r(i.error)},e.onerror=function(t){return a.close(),r(i.error)}}},h.onerror=function(t){return a.close(),r(h.error)},l.oncomplete=function(){null==u?a.close():u.oncomplete=function(){return a.close()}}}},i.onerror=function(t){return r(i.error)}})},t.URL_SCHEME="indexeddb://",t}(),kc=function(t){return f.getBool("IS_BROWSER")&&!Array.isArray(t)&&t.startsWith(xc.URL_SCHEME)?(e=t.slice(xc.URL_SCHEME.length),new xc(e)):null;var e};hc.registerSaveRouter(kc),hc.registerLoadRouter(kc);var Sc=function(){function t(){this.indexedDB=yc()}return t.prototype.listModels=function(){return c(this,void 0,void 0,function(){var t=this;return l(this,function(e){return[2,new Promise(function(e,n){var r=t.indexedDB.open("tensorflowjs",1);r.onupgradeneeded=function(){return wc(r)},r.onsuccess=function(){var t=r.result,i=t.transaction(bc,"readonly"),a=i.objectStore(bc).getAll();a.onsuccess=function(){for(var t={},n=0,r=a.result;n0,function(){return"promises must be a none empty array"})}(t),function(t,e){w(t>=0&&t<=1,function(){return"Progress fraction must be in range [0, 1], but got startFraction "+t}),w(e>=0&&e<=1,function(){return"Progress fraction must be in range [0, 1], but got endFraction "+e}),w(e>=t,function(){return"startFraction must be no more than endFraction, but got startFraction "+t+" and endFraction "+e})}(n=null==n?0:n,r=null==r?1:r);var i=0;return Promise.all(t.map(function(a){return a.then(function(a){var o=n+ ++i/t.length*(r-n);return e(o),a}),a}))}function Wc(t,e){return c(this,void 0,void 0,function(){var n,r,i,a,o,s,u,c,f;return l(this,function(l){switch(l.label){case 0:return null==e&&(e={}),n=null==e.fetchFunc?it:e.fetchFunc,r=t.map(function(t){return n(t,e.requestInit)}),i=0,a=.5,null!=e.onProgress?[3,2]:[4,Promise.all(r)];case 1:return o=l.sent(),[3,4];case 2:return[4,Vc(r,e.onProgress,i,a)];case 3:o=l.sent(),l.label=4;case 4:return s=o.map(function(t){return t.arrayBuffer()}),u=.5,c=1,null!=e.onProgress?[3,6]:[4,Promise.all(s)];case 5:return f=l.sent(),[3,8];case 6:return[4,Vc(s,e.onProgress,u,c)];case 7:f=l.sent(),l.label=8;case 8:return[2,f]}})})}function qc(t){var e=this;return function(n,r,i){return void 0===r&&(r=""),c(e,void 0,void 0,function(){var e,a,o,s,u,c,f,h,d,p;return l(this,function(l){switch(l.label){case 0:if(e=n.map(function(){return!1}),a={},o=null!=i?i.map(function(){return!1}):[],s=[],n.forEach(function(t,n){var r=0;t.weights.forEach(function(t){var u="quantization"in t?t.quantization.dtype:t.dtype,c=ac[u]*_(t.shape),l=function(){e[n]=!0,null==a[n]&&(a[n]=[]),a[n].push({manifestEntry:t,groupOffset:r,sizeBytes:c})};null!=i?i.forEach(function(e,n){e===t.name&&(l(),o[n]=!0)}):l(),s.push(t.name),r+=c})}),!o.every(function(t){return t}))throw u=i.filter(function(t,e){return!o[e]}),new Error("Could not find weights in manifest with names: "+u.join(", ")+". \nManifest JSON has weights with names: "+s.join(", ")+".");return c=e.reduce(function(t,e,n){return e&&t.push(n),t},[]),f=[],c.forEach(function(t){n[t].paths.forEach(function(t){var e=r+(r.endsWith("/")?"":"/")+t;f.push(e)})}),[4,t(f)];case 1:return h=l.sent(),d={},p=0,c.forEach(function(t){for(var e=n[t].paths.length,r=0,i=0;i0,function(){return"URL path for http must not be null, undefined or empty."}),Array.isArray(t)&&w(2===t.length,function(){return"URL paths for http must have a length of 2, (actual length is "+t.length+")."}),this.path=t,null!=e.requestInit&&null!=e.requestInit.body)throw new Error("requestInit is expected to have no pre-existing body, but has one.");this.requestInit=e.requestInit||{}}return t.prototype.save=function(t){return c(this,void 0,void 0,function(){var e,n,r,i;return l(this,function(a){switch(a.label){case 0:if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserHTTPRequest.save() does not support saving model topology in binary formats yet.");return(e=Object.assign({method:this.DEFAULT_METHOD},this.requestInit)).body=new FormData,n=[{paths:["./model.weights.bin"],weights:t.weightSpecs}],r={modelTopology:t.modelTopology,format:t.format,generatedBy:t.generatedBy,convertedBy:t.convertedBy,weightsManifest:n},e.body.append("model.json",new Blob([JSON.stringify(r)],{type:"application/json"}),"model.json"),null!=t.weightData&&e.body.append("model.weights.bin",new Blob([t.weightData],{type:"application/octet-stream"}),"model.weights.bin"),[4,this.fetch(this.path,e)];case 1:if((i=a.sent()).ok)return[2,{modelArtifactsInfo:fc(t),responses:[i]}];throw new Error("BrowserHTTPRequest.save() failed due to HTTP response status "+i.status+".")}})})},t.prototype.load=function(){return c(this,void 0,void 0,function(){var t,e,n,r,i,a,o,s;return l(this,function(u){switch(u.label){case 0:return[4,this.fetch(this.path,this.requestInit)];case 1:if(!(t=u.sent()).ok)throw new Error("Request to "+this.path+" failed with status code "+t.status+". Please verify this URL points to the model JSON of the model to load.");u.label=2;case 2:return u.trys.push([2,4,,5]),[4,t.json()];case 3:return e=u.sent(),[3,5];case 4:throw u.sent(),n="Failed to parse model JSON of response from "+this.path+".",this.path.endsWith(".pb")?n+=" Your path contains a .pb file extension. Support for .pb models have been removed in TensorFlow.js 1.0 in favor of .json models. You can re-convert your Python TensorFlow model using the TensorFlow.js 1.0 conversion scripts or you can convert your.pb models with the 'pb2json'NPM script in the tensorflow/tfjs-converter repository.":n+=" Please make sure the server is serving valid JSON for this request.",new Error(n);case 5:if(r=e.modelTopology,i=e.weightsManifest,null==r&&null==i)throw new Error("The JSON from HTTP path "+this.path+" contains neither model topology or manifest for weights.");return null==i?[3,7]:[4,this.loadWeights(i)];case 6:s=u.sent(),a=s[0],o=s[1],u.label=7;case 7:return[2,{modelTopology:r,weightSpecs:a,weightData:o}]}})})},t.prototype.loadWeights=function(t){return c(this,void 0,void 0,function(){var e,n,r,i,a,o,s,u,c,f,h;return l(this,function(l){switch(l.label){case 0:for(e=Array.isArray(this.path)?this.path[1]:this.path,n=function(t){var e=t.lastIndexOf("/"),n=t.lastIndexOf("?");return[t.substring(0,e)+"/",n>e?t.substring(n):""]}(e),r=n[0],i=n[1],a=this.weightPathPrefix||r,o=[],s=0,u=t;s0&&(t=u({weightSpecs:this.weightSpecs},t)),null!=this.weightData&&this.weightData.byteLength>0&&(t=u({weightData:this.weightData},t)),[2,t]})})},t}(),Yc=function(){function t(t){this.saveHandler=t}return t.prototype.save=function(t){return c(this,void 0,void 0,function(){return l(this,function(e){return[2,this.saveHandler(t)]})})},t}(),Jc=Object.freeze({browserFiles:function(t){return new Uc(t)},browserHTTPRequest:function(t,e){return Xc(t,e)},concatenateArrayBuffers:cc,decodeWeights:oc,encodeWeights:function(t){return c(this,void 0,void 0,function(){var e,n,r,i;return l(this,function(a){switch(a.label){case 0:for(r in e=[],n=[],t){if("float32"!==(i=t[r]).dtype&&"int32"!==i.dtype&&"bool"!==i.dtype)throw new Error("Unsupported dtype in weight '"+r+"': "+i.dtype);e.push({name:r,shape:i.shape,dtype:i.dtype}),n.push(i.data())}return[4,Promise.all(n)];case 1:return[2,{data:function(t){if(null===t)throw new Error("Invalid input value: "+JSON.stringify(t));var e=0,n=[];t.forEach(function(t){if(e+=t.byteLength,n.push(t.byteLength===t.buffer.byteLength?t:new t.constructor(t)),!(t instanceof Float32Array||t instanceof Int32Array||t instanceof Uint8Array))throw new Error("Unsupported TypedArray subtype: "+t.constructor.name)});var r=new Uint8Array(e),i=0;return n.forEach(function(t){r.set(new Uint8Array(t.buffer),i),i+=t.byteLength}),r.buffer}(a.sent()),specs:e}]}})})},fromMemory:function(t,e,n){return new $c(t,e,n)},getLoadHandlers:function(t,e){return hc.getLoadHandlers(t)},getModelArtifactsInfoForJSON:fc,getSaveHandlers:function(t){return hc.getSaveHandlers(t)},http:Xc,isHTTPScheme:Gc,loadWeights:function(t,e,n,r){return void 0===e&&(e=""),c(this,void 0,void 0,function(){return l(this,function(i){return[2,qc(function(t){return Wc(t,{requestInit:r})})(t,e,n)]})})},registerLoadRouter:function(t){return hc.registerLoadRouter(t)},registerSaveRouter:function(t){return hc.registerSaveRouter(t)},weightsLoaderFactory:qc,withSaveHandler:function(t){return new Yc(t)},copyModel:function(t,e){return c(this,void 0,void 0,function(){return l(this,function(n){return[2,vc(t,e,!1)]})})},listModels:function(){return c(this,void 0,void 0,function(){var t,e,n,r,i,a,o;return l(this,function(s){switch(s.label){case 0:t=pc.getSchemes(),e={},n=0,r=t,s.label=1;case 1:return n0&&Number.isInteger(n),function(){return"If provided, numClasses must be a positive integer, but got "+n}),w(1===r.rank,function(){return"Expected the rank of labels to be 1, but got "+r.rank}),w(1===i.rank,function(){return"Expected the rank of predictions to be 1, but got "+i.rank}),w(r.shape[0]===i.shape[0],function(){return"Mismatch in the number of examples: "+r.shape[0]+" vs. "+i.shape[0]+". Labels and predictions should have the same number of elements."}),w(n>0&&Number.isInteger(n),function(){return"numClasses is required to be a positive integer, but got "+n});var a=Lr(r.asType("int32"),n),o=Lr(i.asType("int32"),n);return a.transpose().matMul(o).asType("int32")}}),Qc=Object.freeze({confusionMatrix:Zc}),tl=In({fromPixels_:function(t,e){if(void 0===e&&(e=3),e>4)throw new Error("Cannot construct Tensor with more than 4 channels from pixels.");return Dt.fromPixels(t,e)}}),el=Object.freeze({toPixels:function(t,e){return c(this,void 0,void 0,function(){var n,r,i,a,o,s,u,c,f,h,d,p,m,v,g,b,y,w,x,k,S,_,E;return l(this,function(l){switch(l.label){case 0:if(n=kn(t,"img","toPixels"),t instanceof vt||(n=n.toInt()),2!==n.rank&&3!==n.rank)throw new Error("toPixels only supports rank 2 or 3 tensors, got rank "+n.rank+".");if(r=n.shape.slice(0,2),i=r[0],a=r[1],(o=2===n.rank?1:n.shape[2])>4||2===o)throw new Error("toPixels only supports depth of size 1, 3 or 4 but got "+o);return[4,n.data()];case 1:return s=l.sent(),u=n.min(),c=n.max(),[4,Promise.all([u.data(),c.data()])];case 2:if(f=l.sent(),h=f[0],d=f[1],p=h[0],m=d[0],u.dispose(),c.dispose(),"float32"===n.dtype){if(p<0||m>1)throw new Error("Tensor values for a float32 Tensor must be in the range [0 - 1] but got range ["+p+" - "+m+"].")}else{if("int32"!==n.dtype)throw new Error("Unsupported type for toPixels: "+n.dtype+". Please use float32 or int32 tensors.");if(p<0||m>255)throw new Error("Tensor values for a int32 Tensor must be in the range [0 - 255] but got range ["+p+" - "+m+"].")}for(v="float32"===n.dtype?255:1,g=new Uint8ClampedArray(a*i*4),b=0;b0,function(){return"Class being registered has an empty-string as its className, which is disallowed."}),rl.register(t)}var al=Object.freeze({Serializable:nl,SerializationMap:rl,registerClass:il}),ol=.001,sl=.1;function ul(){return 32===Dt.backend.floatPrecision()?ol:sl}function cl(t,e,n){var r=!0;if((F(t)||F(e))&&(r=!1),F(t)&&F(e)&&(r=!0),r){var i=t.constructor.name,a=e.constructor.name;if(i!==a)throw new Error("Arrays are of different type. Actual: "+i+". Expected: "+a)}if(Array.isArray(t)&&Array.isArray(e)){var o=wn(t),s=wn(e);if(!E(o,s))throw new Error("Arrays have different shapes. Actual: ["+o+"]. Expected: ["+s+"]")}var u=F(t)?t:S(t),c=F(e)?e:S(e);if(u.length!==c.length)throw new Error("Arrays have different lengths actual: "+u.length+" vs expected: "+c.length+".\nActual: "+u+".\nExpected: "+c+".");for(var l=0;ln)}var fl=Object.freeze({TEST_EPSILON_FLOAT16:sl,expectArraysClose:function(t,e,n){return null==n&&(n=ul()),cl(t,e,function(t,e){return ll(t,e,n)})},testEpsilon:ul,expectPromiseToFail:function(t,e){t().then(function(){return e.fail()},function(){return e()})},expectArraysEqual:function(t,e){var n="string"==typeof e||"number"==typeof e||"boolean"==typeof e?[e]:e;return V(t)||V(t[0])||V(e)||V(e[0])?cl(t,n,function(t,e){return t==e}):cl(t,e,function(t,e){return ll(t,e,0)})},expectNumbersClose:function(t,e,n){if(null==n&&(n=ul()),!ll(t,e,n))throw new Error("Numbers differ: actual === "+t+", expected === "+e)},expectValuesInRange:function(t,e,n){for(var r=0;rn)throw new Error("Value out of range:"+t[r]+" low: "+e+", high: "+n)},expectArrayBuffersEqual:function(t,e){expect(new Float32Array(t)).toEqual(new Float32Array(e))}}),hl="1.1.2",dl=Object.freeze({gpgpu_util:oa,webgl_util:Te,MathBackendWebGL:Aa,GPGPUContext:sa}),pl=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return s(e,t),e.prototype.minimize=function(t,e,n){void 0===e&&(e=!1);var r=this.computeGradients(t,n),i=r.value,a=r.grads;return this.applyGradients(a),Object.keys(a).forEach(function(t){return a[t].dispose()}),e?i:(i.dispose(),null)},e.prototype.computeGradients=function(t,e){return Nn(t,e)},e.prototype.dispose=function(){},e}(nl);Object.defineProperty(pl,Symbol.hasInstance,{value:function(t){return null!=t.minimize&&null!=t.computeGradients&&null!=t.applyGradients}});var ml=function(t){function e(e,n,r){void 0===r&&(r=null);var i=t.call(this)||this;return i.learningRate=e,i.rho=n,i.epsilon=r,i.accumulatedGrads={},i.accumulatedUpdates={},null==r&&(i.epsilon=Dt.backend.epsilon()),i}return s(e,t),e.prototype.applyGradients=function(t){var e=this,n=function(n){var i=Dt.registeredVariables[n];null==r.accumulatedGrads[n]&&Le(function(){e.accumulatedGrads[n]=Jn(i).variable(!1)}),null==r.accumulatedUpdates[n]&&Le(function(){e.accumulatedUpdates[n]=Jn(i).variable(!1)});var a=t[n],o=r.accumulatedGrads[n],s=r.accumulatedUpdates[n];Le(function(){var t=o.mul(e.rho).add(a.square().mul(1-e.rho)),r=s.add(e.epsilon).sqrt().div(o.add(e.epsilon).sqrt()).mul(a),u=s.mul(e.rho).add(r.square().mul(1-e.rho));e.accumulatedGrads[n].assign(t),e.accumulatedUpdates[n].assign(u);var c=r.mul(-e.learningRate).add(i);i.assign(c)})},r=this;for(var i in t)n(i)},e.prototype.dispose=function(){var t=this;null!=this.accumulatedUpdates&&(Object.keys(this.accumulatedUpdates).forEach(function(e){return t.accumulatedUpdates[e].dispose()}),Object.keys(this.accumulatedGrads).forEach(function(e){return t.accumulatedGrads[e].dispose()}))},e.prototype.getConfig=function(){return{learningRate:this.learningRate,rho:this.rho,epsilon:this.epsilon}},e.fromConfig=function(t,e){return new t(e.learningRate,e.rho,e.epsilon)},e.className="AdadeltaOptimizer",e}(pl);il(ml);var vl=function(t){function e(e,n){void 0===n&&(n=.1);var r=t.call(this)||this;return r.learningRate=e,r.initialAccumulatorValue=n,r.accumulatedGrads={},r}return s(e,t),e.prototype.applyGradients=function(t){var e=this,n=function(n){var i=Dt.registeredVariables[n];null==r.accumulatedGrads[n]&&Le(function(){e.accumulatedGrads[n]=Kn(i.shape,e.initialAccumulatorValue).variable(!1)});var a=t[n],o=r.accumulatedGrads[n];Le(function(){var t=o.add(a.square());e.accumulatedGrads[n].assign(t);var r=a.div(t.add(Dt.backend.epsilon()).sqrt()).mul(-e.learningRate).add(i);i.assign(r)})},r=this;for(var i in t)n(i)},e.prototype.dispose=function(){var t=this;null!=this.accumulatedGrads&&Object.keys(this.accumulatedGrads).forEach(function(e){return t.accumulatedGrads[e].dispose()})},e.prototype.getConfig=function(){return{learningRate:this.learningRate,initialAccumulatorValue:this.initialAccumulatorValue}},e.fromConfig=function(t,e){return new t(e.learningRate,e.initialAccumulatorValue)},e.className="AdagradOptimizer",e}(pl);il(vl);var gl=function(t){function e(e,n,r,i){void 0===i&&(i=null);var a=t.call(this)||this;return a.learningRate=e,a.beta1=n,a.beta2=r,a.epsilon=i,a.accumulatedFirstMoment={},a.accumulatedSecondMoment={},Le(function(){a.accBeta1=Ln(n).variable(),a.accBeta2=Ln(r).variable()}),null==i&&(a.epsilon=Dt.backend.epsilon()),a}return s(e,t),e.prototype.applyGradients=function(t){var e=this;Le(function(){var n=Js(1,e.accBeta1),r=Js(1,e.accBeta2);for(var i in t){var a=Dt.registeredVariables[i];if(null==e.accumulatedFirstMoment[i]){var o=!1;e.accumulatedFirstMoment[i]=Jn(a).variable(o)}null==e.accumulatedSecondMoment[i]&&(o=!1,e.accumulatedSecondMoment[i]=Jn(a).variable(o));var s=t[i],u=e.accumulatedFirstMoment[i],c=e.accumulatedSecondMoment[i],l=u.mul(e.beta1).add(s.mul(1-e.beta1)),f=c.mul(e.beta2).add(s.square().mul(1-e.beta2)),h=l.div(n),d=f.div(r);e.accumulatedFirstMoment[i].assign(l),e.accumulatedSecondMoment[i].assign(f);var p=h.div(d.sqrt().add(e.epsilon)).mul(-e.learningRate).add(a);a.assign(p)}e.accBeta1.assign(e.accBeta1.mul(e.beta1)),e.accBeta2.assign(e.accBeta2.mul(e.beta2))})},e.prototype.dispose=function(){var t=this;this.accBeta1.dispose(),this.accBeta2.dispose(),null!=this.accumulatedFirstMoment&&Object.keys(this.accumulatedFirstMoment).forEach(function(e){return t.accumulatedFirstMoment[e].dispose()}),null!=this.accumulatedSecondMoment&&Object.keys(this.accumulatedSecondMoment).forEach(function(e){return t.accumulatedSecondMoment[e].dispose()})},e.prototype.getConfig=function(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon}},e.fromConfig=function(t,e){return new t(e.learningRate,e.beta1,e.beta2,e.epsilon)},e.className="AdamOptimizer",e}(pl);il(gl);var bl=function(t){function e(e,n,r,i,a){void 0===i&&(i=null),void 0===a&&(a=0);var o=t.call(this)||this;return o.learningRate=e,o.beta1=n,o.beta2=r,o.epsilon=i,o.decay=a,o.accumulatedFirstMoment={},o.accumulatedWeightedInfNorm={},Le(function(){o.iteration=Ln(0).variable(),o.accBeta1=Ln(n).variable()}),null==i&&(o.epsilon=Dt.backend.epsilon()),o}return s(e,t),e.prototype.applyGradients=function(t){var e=this;Le(function(){var n=Js(1,e.accBeta1),r=zs(-e.learningRate,e.iteration.mul(e.decay).add(1));for(var i in t){var a=Dt.registeredVariables[i];if(null==e.accumulatedFirstMoment[i]){var o=!1;e.accumulatedFirstMoment[i]=Jn(a).variable(o)}null==e.accumulatedWeightedInfNorm[i]&&(o=!1,e.accumulatedWeightedInfNorm[i]=Jn(a).variable(o));var s=t[i],u=e.accumulatedFirstMoment[i],c=e.accumulatedWeightedInfNorm[i],l=u.mul(e.beta1).add(s.mul(1-e.beta1)),f=c.mul(e.beta2),h=s.abs(),d=f.maximum(h);e.accumulatedFirstMoment[i].assign(l),e.accumulatedWeightedInfNorm[i].assign(d);var p=r.div(n).mul(l.div(d.add(e.epsilon))).add(a);a.assign(p)}e.iteration.assign(e.iteration.add(1)),e.accBeta1.assign(e.accBeta1.mul(e.beta1))})},e.prototype.dispose=function(){var t=this;this.accBeta1.dispose(),this.iteration.dispose(),null!=this.accumulatedFirstMoment&&Object.keys(this.accumulatedFirstMoment).forEach(function(e){return t.accumulatedFirstMoment[e].dispose()}),null!=this.accumulatedWeightedInfNorm&&Object.keys(this.accumulatedWeightedInfNorm).forEach(function(e){return t.accumulatedWeightedInfNorm[e].dispose()})},e.prototype.getConfig=function(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon,decay:this.decay}},e.fromConfig=function(t,e){return new t(e.learningRate,e.beta1,e.beta2,e.epsilon,e.decay)},e.className="AdamaxOptimizer",e}(pl);il(bl);var yl=function(t){function e(e){var n=t.call(this)||this;return n.learningRate=e,n.setLearningRate(e),n}return s(e,t),e.prototype.applyGradients=function(t){var e=this;Object.keys(t).forEach(function(n){var r=t[n],i=Dt.registeredVariables[n];Le(function(){var t=e.c.mul(r).add(i);i.assign(t)})})},e.prototype.setLearningRate=function(t){this.learningRate=t,null!=this.c&&this.c.dispose(),this.c=Be(Ln(-t))},e.prototype.dispose=function(){this.c.dispose()},e.prototype.getConfig=function(){return{learningRate:this.learningRate}},e.fromConfig=function(t,e){return new t(e.learningRate)},e.className="SGDOptimizer",e}(pl);il(yl);var wl=function(t){function e(e,n,r){void 0===r&&(r=!1);var i=t.call(this,e)||this;return i.learningRate=e,i.momentum=n,i.useNesterov=r,i.m=Ln(i.momentum),i.accumulations={},i}return s(e,t),e.prototype.applyGradients=function(t){var e=this,n=function(n){var i=Dt.registeredVariables[n];null==r.accumulations[n]&&Le(function(){e.accumulations[n]=Jn(i).variable(!1)});var a=r.accumulations[n],o=t[n];Le(function(){var t,r=e.m.mul(a).add(o);t=e.useNesterov?e.c.mul(o.add(r.mul(e.m))).add(i):e.c.mul(r).add(i),e.accumulations[n].assign(r),i.assign(t)})},r=this;for(var i in t)n(i)},e.prototype.dispose=function(){if(t.prototype.dispose.call(this),this.m.dispose(),null!=this.accumulations)for(var e in this.accumulations)this.accumulations[e].dispose()},e.prototype.setMomentum=function(t){this.momentum=t},e.prototype.getConfig=function(){return{learningRate:this.learningRate,momentum:this.momentum,useNesterov:this.useNesterov}},e.fromConfig=function(t,e){return new t(e.learningRate,e.momentum,e.useNesterov)},e.className="MomentumOptimizer",e}(yl);il(wl);var xl=function(t){function e(e,n,r,i,a){void 0===n&&(n=.9),void 0===r&&(r=0),void 0===i&&(i=null),void 0===a&&(a=!1);var o=t.call(this)||this;return o.learningRate=e,o.decay=n,o.momentum=r,o.epsilon=i,o.accumulatedMeanSquares={},o.accumulatedMeanGrads={},o.accumulatedMoments={},o.centered=a,null==i&&(o.epsilon=Dt.backend.epsilon()),o}return s(e,t),e.prototype.applyGradients=function(t){var e=this,n=function(n){var i=Dt.registeredVariables[n];null==r.accumulatedMeanSquares[n]&&Le(function(){e.accumulatedMeanSquares[n]=Jn(i).variable(!1)}),null==r.accumulatedMeanGrads[n]&&r.centered&&Le(function(){e.accumulatedMeanGrads[n]=Jn(i).variable(!1)}),null==r.accumulatedMoments[n]&&Le(function(){e.accumulatedMoments[n]=Jn(i).variable(!1)});var a=r.accumulatedMeanSquares[n],o=r.accumulatedMeanGrads[n],s=r.accumulatedMoments[n],u=t[n];Le(function(){var t=a.mul(e.decay).add(u.square().mul(1-e.decay));if(e.centered){var r=o.mul(e.decay).add(u.mul(1-e.decay)),c=s.mul(e.momentum).add(u.mul(e.learningRate).div(t.sub(r.square().add(e.epsilon)).sqrt()));e.accumulatedMeanSquares[n].assign(t),e.accumulatedMeanGrads[n].assign(r),e.accumulatedMoments[n].assign(c);var l=i.sub(c);i.assign(l)}else{var f=a.mul(e.decay).add(u.square().mul(1-e.decay));c=s.mul(e.momentum).add(u.mul(e.learningRate).div(f.add(e.epsilon).sqrt())),e.accumulatedMeanSquares[n].assign(f),e.accumulatedMoments[n].assign(c),l=i.sub(c),i.assign(l)}})},r=this;for(var i in t)n(i)},e.prototype.dispose=function(){var t=this;null!=this.accumulatedMeanSquares&&Object.keys(this.accumulatedMeanSquares).forEach(function(e){return t.accumulatedMeanSquares[e].dispose()}),null!=this.accumulatedMeanGrads&&this.centered&&Object.keys(this.accumulatedMeanGrads).forEach(function(e){return t.accumulatedMeanGrads[e].dispose()}),null!=this.accumulatedMoments&&Object.keys(this.accumulatedMoments).forEach(function(e){return t.accumulatedMoments[e].dispose()})},e.prototype.getConfig=function(){return{learningRate:this.learningRate,decay:this.decay,momentum:this.momentum,epsilon:this.epsilon,centered:this.centered}},e.fromConfig=function(t,e){return new t(e.learningRate,e.decay,e.momentum,e.epsilon,e.centered)},e.className="RMSPropOptimizer",e}(pl);il(xl);var kl=function(){function t(){}return t.sgd=function(t){return new yl(t)},t.momentum=function(t,e,n){return void 0===n&&(n=!1),new wl(t,e,n)},t.rmsprop=function(t,e,n,r,i){return void 0===e&&(e=.9),void 0===n&&(n=0),void 0===r&&(r=null),void 0===i&&(i=!1),new xl(t,e,n,r,i)},t.adam=function(t,e,n,r){return void 0===t&&(t=.001),void 0===e&&(e=.9),void 0===n&&(n=.999),void 0===r&&(r=null),new gl(t,e,n,r)},t.adadelta=function(t,e,n){return void 0===t&&(t=.001),void 0===e&&(e=.95),void 0===n&&(n=null),new ml(t,e,n)},t.adamax=function(t,e,n,r,i){return void 0===t&&(t=.002),void 0===e&&(e=.9),void 0===n&&(n=.999),void 0===r&&(r=null),void 0===i&&(i=0),new bl(t,e,n,r,i)},t.adagrad=function(t,e){return void 0===e&&(e=.1),new vl(t,e)},t}(),Sl={sgd:kl.sgd,momentum:kl.momentum,adadelta:kl.adadelta,adagrad:kl.adagrad,rmsprop:kl.rmsprop,adamax:kl.adamax,adam:kl.adam},_l="undefined"!=typeof requestAnimationFrame?requestAnimationFrame:void 0!==a?a:function(t){return t()};function El(){return new Promise(function(t){return _l(function(){return t()})})}pt=rc}.call(this,n(46),n(31),n(16).Buffer,n(255).setImmediate)},function(t,e,n){"use strict";n.r(e);var r=n(0),i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,e)}; -/** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */function a(t,e){function n(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var o,s=function(){return(s=Object.assign||function(t){for(var e,n=1,r=arguments.length;n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e?1:0}(t,e)}function A(t){if(null==t)return t;for(var e=[],n=0,r=t;n=0),g(r>=n),Array.isArray(t)&&t.length>=n&&t.length<=r&&t.every(function(t){return typeof t===e})}function I(t,e){Array.isArray(t)?(r.util.assert(t.length>0,function(){return e+" is unexpectedly an empty array."}),t.forEach(function(t,n){return I(t,"element "+(n+1)+" of "+e)})):r.util.assert(Number.isInteger(t)&&t>0,function(){return"Expected "+e+" to be a positive integer, but got "+function t(e){return null===e?"null":Array.isArray(e)?"["+e.map(function(e){return t(e)}).join(",")+"]":"string"==typeof e?'"'+e+'"':""+e}(t)+"."})}function M(t,e){return Object(r.tidy)(function(){return Object(r.sqrt)(Object(r.sum)(Object(r.mulStrict)(t,t),e,!0))})}var R=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.getConfig=function(){return{}},e}(r.serialization.Serializable),D=function(t){function e(e){var n=t.call(this)||this;return n.defaultMaxValue=2,n.defaultAxis=0,n.maxValue=null!=e.maxValue?e.maxValue:n.defaultMaxValue,n.axis=null!=e.axis?e.axis:n.defaultAxis,n}return a(e,t),e.prototype.apply=function(t){var e=this;return Object(r.tidy)(function(){var n=M(t,e.axis),i=Object(r.clipByValue)(n,0,e.maxValue);return Object(r.mul)(t,Object(r.div)(i,Object(r.add)(l(),n)))})},e.prototype.getConfig=function(){return{maxValue:this.maxValue,axis:this.axis}},e.className="MaxNorm",e}(R);r.serialization.registerClass(D);var j=function(t){function e(e){var n=t.call(this)||this;return n.defaultAxis=0,n.axis=null!=e.axis?e.axis:n.defaultAxis,n}return a(e,t),e.prototype.apply=function(t){var e=this;return Object(r.tidy)(function(){return Object(r.div)(t,Object(r.add)(l(),M(t,e.axis)))})},e.prototype.getConfig=function(){return{axis:this.axis}},e.className="UnitNorm",e}(R);r.serialization.registerClass(j);var z=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.relu)(t)},e.className="NonNeg",e}(R);r.serialization.registerClass(z);var P=function(t){function e(e){var n=t.call(this)||this;return n.defaultMinValue=0,n.defaultMaxValue=1,n.defaultRate=1,n.defaultAxis=0,n.minValue=null!=e.minValue?e.minValue:n.defaultMinValue,n.maxValue=null!=e.maxValue?e.maxValue:n.defaultMaxValue,n.rate=null!=e.rate?e.rate:n.defaultRate,n.axis=null!=e.axis?e.axis:n.defaultAxis,n}return a(e,t),e.prototype.apply=function(t){var e=this;return Object(r.tidy)(function(){var n=M(t,e.axis),i=Object(r.add)(Object(r.mul)(e.rate,Object(r.clipByValue)(n,e.minValue,e.maxValue)),Object(r.mul)(1-e.rate,n));return Object(r.mul)(t,Object(r.div)(i,Object(r.add)(l(),n)))})},e.prototype.getConfig=function(){return{minValue:this.minValue,maxValue:this.maxValue,rate:this.rate,axis:this.axis}},e.className="MinMaxNorm",e}(R);r.serialization.registerClass(P);var L={maxNorm:"MaxNorm",minMaxNorm:"MinMaxNorm",nonNeg:"NonNeg",unitNorm:"UnitNorm"};function F(t){return _(t)}function B(t,e){return void 0===e&&(e={}),E(t,r.serialization.SerializationMap.getMap().classNameMap,e,"constraint")}function U(t){return null==t?null:"string"==typeof t?B({className:t in L?L[t]:t,config:{}}):t instanceof R?t:B(t)}var V=Object.freeze({maxNorm:function(t){return new D(t)},unitNorm:function(t){return new j(t)},nonNeg:function(){return new z},minMaxNorm:function(t){return new P(t)}}),W=["channelsFirst","channelsLast"],q=["valid","same","causal"],H=["max","avg"],G=["sum","mul","concat","ave"],K=new Map;function X(t){O(W,"DataFormat",t)}function $(t){O(q,"PaddingMode",t)}var Y=[],J="/";function Z(t,e){Y.push(t);try{var n=e();return Y.pop(),n}catch(t){throw Y.pop(),t}}function Q(t){if(!nt(t))throw new Error("Not a valid tensor name: '"+t+"'");return(0===Y.length?"":Y.join(J)+J)+t}function tt(t){if(!nt(t))throw new Error("Not a valid tensor name: '"+t+"'");K.has(t)||K.set(t,0);var e=K.get(t);if(K.set(t,K.get(t)+1),e>0){var n=t+"_"+e;return K.set(n,1),n}return t}var et=new RegExp(/^[A-Za-z][-A-Za-z0-9\._\/]*$/);function nt(t){return!!t.match(et)}function rt(t){return t===parseInt(t.toString(),10)}function it(t,e,n){null==e&&(e=0),null==n&&(n=t.length);for(var r=1,i=e;i= 2 but got x shape = "+t.shape+" and y shape = "+e.shape);if(e.rank>=3&&(u=t.shape.slice(-1)[0])!==(f=e.shape.slice(-2)[0]))throw new p("If rank y >= 3, then the second last dim of y must equal the last dim of x but got x shape = "+t.shape+" and y shape = "+e.shape);if(2===t.rank&&2===e.rank){var a=!1,o=!1;return r.fused.matMul(t,e,a,o,i?xt(t.rank,i,"channelsLast"):null,n)}var s=t.shape.slice(),u=s.pop();t=t.reshape([-1,u]);var c=e.shape.slice(),l=c.pop(),f=c.pop(),h=c.concat([l]),d=Array.from({length:e.rank},function(t,n){return 0===n?e.rank-2:n<=e.rank-2?n-1:n});e=e.transpose(d).reshape([f,-1]);var m=s.concat(h);return a=!1,o=!1,r.fused.matMul(t,e,a,o,i?xt(t.rank,i,"channelsLast"):null,n).reshape(m)}function yt(t,e,n){return Object(r.tidy)(function(){return e=Array.isArray(e)?Object(r.tensor1d)(e,"int32"):e.toInt(),Object(r.gather)(t,e,n)})}function wt(t){return Object(r.mulStrict)(t,t)}function xt(t,e,n){var r=e.shape;if(1!==e.rank&&e.rank!==t)throw new d("Unexpected bias dimensions: "+e.rank+"; expected it to be 1 or "+t);if(5===t){if("channelsFirst"===n)return 1===r.length?e.reshape([1,r[0],1,1,1]):e.reshape([1,r[3],r[0],r[1],r[2]]);if("channelsLast"===n)return 1===r.length?e.reshape([1,1,1,1,r[0]]):e.reshape([1].concat(r))}else if(4===t){if("channelsFirst"===n)return 1===r.length?e.reshape([1,r[0],1,1]):e.reshape([1,r[2],r[0],r[1]]);if("channelsLast"===n)return 1===r.length?e.reshape([1,1,1,r[0]]):e.reshape([1].concat(r))}else if(3===t){if("channelsFirst"===n)return 1===r.length?e.reshape([1,r[0],1]):e.reshape([1,r[1],r[0]]);if("channelsLast"===n)return 1===r.length?e.reshape([1,1,r[0]]):e.reshape([1].concat(r))}else if(t<3)return e;throw new d("Unsupported input rank by biasAdd: "+e.rank)}function kt(t,e,n){return Object(r.tidy)(function(){return null==n&&(n="channelsLast"),X(n),t.add(xt(t.rank,e,n))})}function St(t,e,n,i){return Object(r.tidy)(function(){if(null!=n&&!r.util.arraysEqual(t.shape,n))throw new p("Non-default noise shape is not implemented yet: "+JSON.stringify(n));if(null!=i)throw new p("seed is not implemented for dropout yet.");var a=Object(r.step)(Object(r.add)(-e,Object(r.randomUniform)(t.shape,0,1,"float32")));return a=Object(r.mul)(1/(1-e),a),Object(r.mul)(t,a)})}function _t(t,e,n){return void 0===n&&(n=!1),n?t():e()}var Et=["fanIn","fanOut","fanAvg"],Ct=["normal","uniform","truncatedNormal"],At=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.fromConfigUsesCustomObjects=function(){return!1},e.prototype.getConfig=function(){return{}},e}(r.serialization.Serializable),Nt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t,e){return Object(r.zeros)(t,e)},e.className="Zeros",e}(At);r.serialization.registerClass(Nt);var Ot=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t,e){return Object(r.ones)(t,e)},e.className="Ones",e}(At);r.serialization.registerClass(Ot);var Tt=function(t){function e(e){var n=t.call(this)||this;if("object"!=typeof e)throw new d("Expected argument of type ConstantConfig but got "+e);if(void 0===e.value)throw new d("config must have value set but got "+e);return n.value=e.value,n}return a(e,t),e.prototype.apply=function(t,e){var n=this;return Object(r.tidy)(function(){return Object(r.mul)(Object(r.scalar)(n.value),Object(r.ones)(t,e))})},e.prototype.getConfig=function(){return{value:this.value}},e.className="Constant",e}(At);r.serialization.registerClass(Tt);var It=function(t){function e(e){var n=t.call(this)||this;return n.DEFAULT_MINVAL=-.05,n.DEFAULT_MAXVAL=.05,n.minval=e.minval||n.DEFAULT_MINVAL,n.maxval=e.maxval||n.DEFAULT_MAXVAL,n.seed=e.seed,n}return a(e,t),e.prototype.apply=function(t,e){return Object(r.randomUniform)(t,this.minval,this.maxval,e)},e.prototype.getConfig=function(){return{minval:this.minval,maxval:this.maxval,seed:this.seed}},e.className="RandomUniform",e}(At);r.serialization.registerClass(It);var Mt=function(t){function e(e){var n=t.call(this)||this;return n.DEFAULT_MEAN=0,n.DEFAULT_STDDEV=.05,n.mean=e.mean||n.DEFAULT_MEAN,n.stddev=e.stddev||n.DEFAULT_STDDEV,n.seed=e.seed,n}return a(e,t),e.prototype.apply=function(t,e){if("float32"!==(e=e||"float32")&&"int32"!==e)throw new p("randomNormal does not support dType "+e+".");return gt(t,this.mean,this.stddev,e,this.seed)},e.prototype.getConfig=function(){return{mean:this.mean,stddev:this.stddev,seed:this.seed}},e.className="RandomNormal",e}(At);r.serialization.registerClass(Mt);var Rt=function(t){function e(e){var n=t.call(this)||this;return n.DEFAULT_MEAN=0,n.DEFAULT_STDDEV=.05,n.mean=e.mean||n.DEFAULT_MEAN,n.stddev=e.stddev||n.DEFAULT_STDDEV,n.seed=e.seed,n}return a(e,t),e.prototype.apply=function(t,e){if("float32"!==(e=e||"float32")&&"int32"!==e)throw new p("truncatedNormal does not support dType "+e+".");return Object(r.truncatedNormal)(t,this.mean,this.stddev,e,this.seed)},e.prototype.getConfig=function(){return{mean:this.mean,stddev:this.stddev,seed:this.seed}},e.className="TruncatedNormal",e}(At);r.serialization.registerClass(Rt);var Dt=function(t){function e(e){var n=t.call(this)||this;return n.gain=null!=e.gain?e.gain:1,n}return a(e,t),e.prototype.apply=function(t,e){var n=this;return Object(r.tidy)(function(){if(2!==t.length||t[0]!==t[1])throw new d("Identity matrix initializer can only be used for 2D square matrices.");return Object(r.mul)(n.gain,Object(r.eye)(t[0]))})},e.prototype.getConfig=function(){return{gain:this.gain}},e.className="Identity",e}(At);r.serialization.registerClass(Dt);var jt=function(t){function e(e){var n=t.call(this)||this;if(e.scale<0)throw new d("scale must be a positive float. Got: "+e.scale);return n.scale=null==e.scale?1:e.scale,n.mode=null==e.mode?"fanIn":e.mode,function(t){O(Et,"FanMode",t)}(n.mode),n.distribution=null==e.distribution?"normal":e.distribution,function(t){O(Ct,"Distribution",t)}(n.distribution),n.seed=e.seed,n}return a(e,t),e.prototype.apply=function(t,e){var n=function(t,e){var n,r;if(void 0===e&&(e="channelsLast"),X(e),2===t.length)n=t[0],r=t[1];else if(-1!==[3,4,5].indexOf(t.length))if("channelsFirst"===e){var i=it(t,2);n=t[1]*i,r=t[0]*i}else"channelsLast"===e&&(i=it(t,0,t.length-2),n=t[t.length-2]*i,r=t[t.length-1]*i);else{var a=it(t);n=Math.sqrt(a),r=Math.sqrt(a)}return[n,r]}(t),i=n[0],a=n[1],o=this.scale;if("fanIn"===this.mode?o/=Math.max(1,i):"fanOut"===this.mode?o/=Math.max(1,a):o/=Math.max(1,(i+a)/2),"normal"===this.distribution){var s=Math.sqrt(o);if("float32"!==(e=e||"float32")&&"int32"!==e)throw new p(this.getClassName()+" does not support dType "+e+".");return Object(r.truncatedNormal)(t,0,s,e,this.seed)}var u=Math.sqrt(3*o);return Object(r.randomUniform)(t,-u,u,e)},e.prototype.getConfig=function(){return{scale:this.scale,mode:this.mode,distribution:this.distribution,seed:this.seed}},e.className="VarianceScaling",e}(At);r.serialization.registerClass(jt);var zt=function(t){function e(e){return t.call(this,{scale:1,mode:"fanAvg",distribution:"uniform",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="GlorotUniform",e}(jt);r.serialization.registerClass(zt);var Pt=function(t){function e(e){return t.call(this,{scale:1,mode:"fanAvg",distribution:"normal",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="GlorotNormal",e}(jt);r.serialization.registerClass(Pt);var Lt=function(t){function e(e){return t.call(this,{scale:2,mode:"fanIn",distribution:"normal",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="HeNormal",e}(jt);r.serialization.registerClass(Lt);var Ft=function(t){function e(e){return t.call(this,{scale:2,mode:"fanIn",distribution:"uniform",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="HeUniform",e}(jt);r.serialization.registerClass(Ft);var Bt=function(t){function e(e){return t.call(this,{scale:1,mode:"fanIn",distribution:"normal",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="LeCunNormal",e}(jt);r.serialization.registerClass(Bt);var Ut=function(t){function e(e){return t.call(this,{scale:1,mode:"fanIn",distribution:"uniform",seed:null==e?null:e.seed})||this}return a(e,t),e.prototype.getClassName=function(){return jt.className},e.className="LeCunNormal",e}(jt);r.serialization.registerClass(Ut);var Vt=function(t){function e(e){var n=t.call(this)||this;if(n.DEFAULT_GAIN=1,n.gain=null==e.gain?n.DEFAULT_GAIN:e.gain,n.seed=e.seed,null!=n.seed)throw new p("Random seed is not implemented for Orthogonal Initializer yet.");return n}return a(e,t),e.prototype.apply=function(t,e){var n=this;return Object(r.tidy)(function(){if(2!==t.length)throw new p("The Orthogonal Initializer does not support non-2D shapes yet.");t[0]*t[1]>2e3&&console.warn("Orthogonal initializer is being called on a matrix with more than 2000 ("+t[0]*t[1]+") elements: Slowness may result.");var e=gt(t[0]>t[1]?[t[1],t[0]]:t,0,1,"float32"),i=r.linalg.gramSchmidt(e);return t[0]>t[1]&&(i=i.transpose()),Object(r.mul)(n.gain,i)})},e.prototype.getConfig=function(){return{gain:this.gain,seed:this.seed}},e.className="Orthogonal",e}(At);r.serialization.registerClass(Vt);var Wt={constant:"Constant",glorotNormal:"GlorotNormal",glorotUniform:"GlorotUniform",heNormal:"HeNormal",heUniform:"HeUniform",identity:"Identity",leCunNormal:"LeCunNormal",leCunUniform:"LeCunUniform",ones:"Ones",orthogonal:"Orthogonal",randomNormal:"RandomNormal",randomUniform:"RandomUniform",truncatedNormal:"TruncatedNormal",varianceScaling:"VarianceScaling",zeros:"Zeros"};function qt(t,e){return void 0===e&&(e={}),E(t,r.serialization.SerializationMap.getMap().classNameMap,e,"initializer")}function Ht(t){return _(t)}function Gt(t){if("string"==typeof t){var e=t in Wt?Wt[t]:t;if("GlorotNormal"===e)return new Pt;if("GlorotUniform"===e)return new zt;if("HeNormal"===e)return new Lt;if("HeUniform"===e)return new Ft;if("LeCunNormal"===e)return new Bt;if("LeCunUniform"===e)return new Ut;var n={};return n.className=e,n.config={},qt(n)}return t instanceof At?t:qt(t)}var Kt=Object.freeze({zeros:function(){return new Nt},ones:function(){return new Ot},constant:function(t){return new Tt(t)},randomUniform:function(t){return new It(t)},randomNormal:function(t){return new Mt(t)},truncatedNormal:function(t){return new Rt(t)},identity:function(t){return new Dt(t)},varianceScaling:function(t){return new jt(t)},glorotUniform:function(t){return new zt(t)},glorotNormal:function(t){return new Pt(t)},heNormal:function(t){return new Lt(t)},heUniform:function(t){return new Ft(t)},leCunNormal:function(t){return new Bt(t)},leCunUniform:function(t){return new Ut(t)},orthogonal:function(t){return new Vt(t)}}),Xt=0;function $t(){return Xt++}var Yt={};function Jt(t){return void 0===t&&(t=""),t in Yt||(Yt[t]=0),Yt[t]+=1,t+Yt[t].toString()}function Zt(t){return Array.isArray(t)&&Array.isArray(t[0])}function Qt(t){return 0===t.length?[]:Array.isArray(t[0])?t:[t]}function te(t){var e;if(Array.isArray(t)){if(1!==t.length)throw new d("Expected Tensor length to be 1; got "+t.length);e=t[0]}else e=t;return e}function ee(t){if(Array.isArray(t)&&Array.isArray(t[0])){if(1===t.length)return(t=t)[0];throw new d("Expected exactly 1 Shape; got "+t.length)}return t}function ne(t){for(var e=0,n=0,r=t;n1)throw new f("Layer "+this.name+' has multiple inbound nodes, hence the notion of "layer input" is ill-defined. Use `getInputAt(nodeIndex)` instead.');if(0===this.inboundNodes.length)throw new f("Layer "+this.name+" is not connected, no input to return.");return y(this.getNodeAtIndex(0,"input").inputTensors)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"output",{get:function(){if(0===this.inboundNodes.length)throw new f("Layer "+this.name+" has no inbound nodes.");if(this.inboundNodes.length>1)throw new f("Layer "+this.name+' has multiple inbound nodes, hence the notion of "layer output" is ill-defined. Use `getOutputAt(nodeIndex)` instead.');return y(this.getNodeAtIndex(0,"output").outputTensors)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"losses",{get:function(){return this._losses},enumerable:!0,configurable:!0}),e.prototype.calculateLosses=function(){return this.losses.map(function(t){return t()})},Object.defineProperty(e.prototype,"updates",{get:function(){return this._updates},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"built",{get:function(){return this._built},set:function(t){this._built=t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"trainable",{get:function(){return this.trainable_},set:function(t){this._trainableWeights.forEach(function(e){return e.trainable=t}),this.trainable_=t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"trainableWeights",{get:function(){return this.trainable_?this._trainableWeights.filter(function(t){return t.trainable}):[]},set:function(t){this._trainableWeights=t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"nonTrainableWeights",{get:function(){return this.trainable?this._trainableWeights.filter(function(t){return!t.trainable}).concat(this._nonTrainableWeights):this._trainableWeights.concat(this._nonTrainableWeights)},set:function(t){this._nonTrainableWeights=t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"weights",{get:function(){return this.trainableWeights.concat(this.nonTrainableWeights)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"stateful",{get:function(){return this._stateful},enumerable:!0,configurable:!0}),e.prototype.resetStates=function(){if(!this.stateful)throw new Error("Cannot call the resetStates() method of a non-stateful Layer object.")},e.prototype.assertInputCompatibility=function(t){if(t=w(t),null!=this.inputSpec&&0!==this.inputSpec.length){var e=w(this.inputSpec);if(t.length!==e.length)throw new d("Layer "+this.name+" expects "+e.length+" inputs, but it received "+t.length+" input tensors. Input received: "+t);for(var n=0;n=0?o[u]:o[o.length+u];if(null!=c&&-1===[c,null].indexOf(l))throw new d("Input "+n+" is incompatible with layer "+this.name+": expected axis "+u+" of input shape to have value "+c+" but got shape "+o+".")}}if(null!=i.shape)for(var f=0;f0&&Array.isArray(m[0])?m.map(function(r,i){return new ce(g,r,n,w(t),e,n.name,i)}):new ce(g,m,n,w(t),e,n.name),n.addInboundNode(t,v,null,null,d,m,e),n._refCount++,null!=n.activityRegularizer)throw new p("Layer invocation in the presence of activity regularizer(s) is not supported yet.");return v})},e.prototype.warnOnIncompatibleInputShape=function(t){if(null!=this.batchInputShape)if(t.length!==this.batchInputShape.length)console.warn("The rank of the input tensor provided (shape: "+JSON.stringify(t)+") does not match that of the batchInputShape ("+JSON.stringify(this.batchInputShape)+") of the layer "+this.name);else{var e=!1;this.batchInputShape.forEach(function(n,r){null!=n&&null!=t[r]&&t[r]!==n&&(e=!0)}),e&&console.warn("The shape of the input tensor ("+JSON.stringify(t)+") does not match the expectation of layer "+this.name+": "+JSON.stringify(this.batchInputShape))}},Object.defineProperty(e.prototype,"outputShape",{get:function(){if(null==this.inboundNodes||0===this.inboundNodes.length)throw new f("The layer "+this.name+" has never been called and thus has no defined output shape.");for(var t=[],e=0,n=this.inboundNodes;e0?[4,Promise.all(e)]:[3,2];case 1:for(u=c.sent(),l=0;l=0&&Number.isInteger(e),function(){return"Verbosity level is expected to be an integer >= 0, but got "+e}),t.checkForDuplicate(n),null==t.constructors[e]&&(t.constructors[e]=[]),t.constructors[e].push(n)},t.checkForDuplicate=function(e){for(var n in t.constructors)t.constructors[+n].forEach(function(t){if(t===e)throw new d("Duplicate callback constructor.")})},t.clear=function(){t.constructors={}},t.createCallbacks=function(e){var n=[];for(var r in t.constructors){var i=+r;e>=i&&n.push.apply(n,t.constructors[i])}return n.map(function(t){return new t})},t.constructors={},t}();function Ce(t,e,n,r,i,a,o,s,u){var c=new ke,l=[new xe].concat(Ee.createCallbacks(e));null!=t&&l.push.apply(l,t),l.push(c);var f=new we(l);return f.setParams({epochs:n,initialEpoch:r,samples:i,steps:a,batchSize:o,verbose:e,doValidation:s,metrics:u}),{callbackList:f,history:c}}function Ae(t,e){return Object(r.tidy)(function(){"float32"!==t.dtype&&(t=t.asType("float32"));var n=Object(r.sum)(wt(t),e,!0),i=Object(r.fill)(n.shape,l()),a=Object(r.sqrt)(Object(r.maximum)(n,i));return Object(r.div)(t,a)})}function Ne(t,e){return Object(r.tidy)(function(){return Object(r.mean)(wt(Object(r.sub)(e,t)),-1)})}function Oe(t,e){return Object(r.tidy)(function(){return Object(r.mean)(Object(r.abs)(Object(r.sub)(e,t)),-1)})}function Te(t,e){return Object(r.tidy)(function(){var n=Object(r.sub)(t,e),i=Object(r.clipByValue)(Object(r.abs)(t),l(),Number.MAX_VALUE),a=Object(r.abs)(Object(r.div)(n,i));return Object(r.mul)(100,Object(r.mean)(a,-1))})}function Ie(t,e){return Object(r.tidy)(function(){var n=Object(r.clipByValue)(e,l(),Number.MAX_VALUE),i=Object(r.log)(Object(r.add)(1,n)),a=Object(r.clipByValue)(t,l(),Number.MAX_VALUE),o=Object(r.log)(Object(r.add)(1,a));return Object(r.mean)(wt(Object(r.sub)(i,o)),-1)})}function Me(t,e){return Object(r.tidy)(function(){var n=Object(r.maximum)(0,Object(r.sub)(1,Object(r.mul)(t,e)));return Object(r.mean)(wt(n),-1)})}function Re(t,e){return Object(r.tidy)(function(){var n=Object(r.maximum)(0,Object(r.sub)(1,Object(r.mul)(t,e)));return Object(r.mean)(n,-1)})}function De(t,e){return Object(r.tidy)(function(){var n=Object(r.sum)(Object(r.mul)(t,e),-1),i=Object(r.max)(Object(r.mul)(Object(r.sub)(1,t),e),-1);return Object(r.maximum)(0,Object(r.add)(1,Object(r.sub)(i,n)))})}function je(t,e){return Object(r.tidy)(function(){var n=Math.log(2),i=Object(r.sub)(e,t),a=Object(r.sub)(Object(r.add)(i,Object(r.softplus)(Object(r.mul)(-2,i))),n);return Object(r.mean)(a,-1)})}function ze(t,e,n){return void 0===n&&(n=!1),Object(r.tidy)(function(){if(n)e=Object(r.softmax)(e);else{var i=Object(r.sum)(e,e.shape.length-1,!0);e=Object(r.div)(e,i)}return e=Object(r.clipByValue)(e,l(),1-l()),Object(r.neg)(Object(r.sum)(Object(r.mul)(t.toFloat(),Object(r.log)(e)),e.shape.length-1))})}function Pe(t,e){return Object(r.tidy)(function(){var n=Object(r.floor)(function(t){var e=[it(t.shape)];return t.reshape(e)}(t)).toInt(),i=(e=Object(r.clipByValue)(e,l(),1-l())).shape;return ze(Object(r.oneHot)(n,i[i.length-1]).reshape(i),e,!1)})}function Le(t,e){return Object(r.tidy)(function(){var n;return n=Object(r.clipByValue)(e,l(),1-l()),n=Object(r.log)(Object(r.div)(n,Object(r.sub)(1,n))),Object(r.mean)(function(t,e){if(!r.util.arraysEqual(t.shape,e.shape))throw new d("logits and labels must have the same shape, but got shapes "+JSON.stringify(t.shape)+" and "+JSON.stringify(e.shape));return Object(r.tidy)(function(){var n=e.relu(),r=e.abs().neg();return n.sub(e.mul(t)).add(r.exp().log1p())})}(t,n),-1)})}function Fe(t,e){return Object(r.tidy)(function(){var n=Object(r.clipByValue)(t,l(),1),i=Object(r.clipByValue)(e,l(),1);return Object(r.sum)(Object(r.mul)(t,Object(r.log)(Object(r.div)(n,i))),-1)})}function Be(t,e){return Object(r.tidy)(function(){var n=Object(r.log)(Object(r.add)(l(),e));return Object(r.mean)(Object(r.sub)(e,Object(r.mul)(t,n)),-1)})}function Ue(t,e){return Object(r.tidy)(function(){var n=Ae(t,-1),i=Ae(e,-1),a=Object(r.mul)(n,i);return Object(r.neg)(Object(r.sum)(a,-1))})}function Ve(t){var e={meanSquaredError:Ne,meanAbsoluteError:Oe,meanAbsolutePercentageError:Te,meanSquaredLogarithmicError:Ie,squaredHinge:Me,hinge:Re,categoricalHinge:De,logcosh:je,categoricalCrossentropy:ze,sparseCategoricalCrossentropy:Pe,binaryCrossentropy:Le,kullbackLeiblerDivergence:Fe,poisson:Be,cosineProximity:Ue};if("string"==typeof t){if(t in e)return e[t];var n="Unknown loss "+t;throw t.toLowerCase().includes("softmaxcrossentropy")&&(n="Unknown loss "+t+'. Use "categoricalCrossentropy" as the string name for tf.losses.softmaxCrossEntropy'),new d(n)}return t}function We(t,e){return Object(r.tidy)(function(){var n=Object(r.mul)(.5,Object(r.onesLike)(e)),i=ct(Object(r.greater)(e,n),t.dtype);return Object(r.mean)(Object(r.equal)(t,i),-1)})}function qe(t,e){return Object(r.tidy)(function(){return ct(Object(r.equal)(Object(r.argMax)(t,-1),Object(r.argMax)(e,-1)),"float32")})}function He(t,e){return Object(r.tidy)(function(){return Object(r.logicalAnd)(t.equal(1),e.equal(1)).sum().cast("float32")})}function Ge(t,e){return Object(r.tidy)(function(){var n=He(t,e),i=function(t,e){return Object(r.tidy)(function(){return Object(r.logicalAnd)(t.equal(0),e.equal(1)).sum().cast("float32")})}(t,e),a=n.add(i);return Object(r.where)(Object(r.greater)(a,0),n.div(a),0).cast("float32")})}function Ke(t,e){return Le(t,e)}function Xe(t,e){return t.rank===e.rank&&(t=t.squeeze([t.rank-1])),(e=e.argMax(-1)).dtype!==t.dtype&&(e=e.asType(t.dtype)),Object(r.equal)(t,e).asType("float32")}var $e=Ne,Ye=Ne,Je=Oe,Ze=Oe,Qe=Te,tn=Te,en=ze,nn=Ue,rn=Pe;function an(t,e,n){void 0===n&&(n=console.log);for(var r="",i=0;i0&&(r=r.slice(0,r.length-1)+" "),r=(r+=t[i]).slice(0,e[i]),r+=" ".repeat(e[i]-r.length);n(r)}function on(t,e,n){var r;try{r=JSON.stringify(t.outputShape)}catch(t){r="multiple"}an([t.name+" ("+t.getClassName()+")",r,t.countParams().toString()],e,n)}function sn(t,e,n,r){var i;try{i=JSON.stringify(t.outputShape)}catch(t){i="multiple"}for(var a=[],o=0,s=t.inboundNodes;o0&&-1===n.indexOf(u)))for(var c=0;c0,function(){return"Expected at least one fetch, got none"});var n=[],i={};if(1===t.length){var a=mn(t[0],e);n=a.sorted,i=a.recipientMap}else for(var o=new Set,s=0,u=t;si.maxNumTensors&&(i.maxNumTensors=x),x0;){var l=u[u.length-1];if(n.has(l.name))u.pop();else{var f=c[c.length-1]===u.length-1;if(0===l.inputs.length||f)u.pop(),r.push(l),n.add(l.name),f&&c.pop();else{c.push(u.length-1);for(var h=0,d=l.inputs;h0&&Number.isInteger(t),function(){return"batchSize is required to be a positive integer, but got "+t})}function kn(t,e,n){return null==t?[null]:Array.isArray(t)?t.map(function(t){return ft(t,e,n-e)}):ft(t,e,n-e)}function Sn(t,e){return Object(r.tidy)(function(){return null==t?null:Array.isArray(t)?t.map(function(t){return Sn(t,e)}):yt(t,"int32"===e.dtype?e:e.toInt())})}function _n(t,e){for(var n=[],r=0,i=null;r=t&&(i=t),n.push([r,i]),r=i;return n}function En(t,e,n,i){return void 0===i&&(i={}),u(this,void 0,void 0,function(){var a,o,s,l,f,h,m,v,g,b,y,w,x,k,S,_,E,C,A;return c(this,function(N){switch(N.label){case 0:if(t.isTraining)throw new Error("Cannot start training because another fit() call is ongoing.");t.isTraining=!0,N.label=1;case 1:if(N.trys.push([1,,3,4]),xn(m=null==i.batchSize?32:i.batchSize),v=t.standardizeUserData(e,n,!1,m),a=v[0],o=v[1],g=!1,b=void 0,null!=i.validationData&&i.validationData.length>0){if(g=!0,2!==i.validationData.length)throw 3===i.validationData.length?new p("validationData including sample weights is not supported yet."):new d("When passing validation data, it must contain 2 (valX, valY) or 3 (valX, valY, valSampleWeight) items; "+i.validationData+" is invalid.");s=i.validationData[0],l=i.validationData[1],y=t.standardizeUserData(s,l,!0,m),f=y[0],h=y[1],b=f.concat(h)}else null!=i.validationSplit&&i.validationSplit>0&&i.validationSplit<1?(g=!0,w=Math.floor(a[0].shape[0]*(1-i.validationSplit)),x=a[0].shape[0],f=kn(a,w,x),a=kn(a,0,w),h=kn(o,w,x),o=kn(o,0,w),b=f.concat(h)):null!=i.validationSteps&&(g=!0);return k=a.concat(o),t.checkTrainableWeightsConsistency(),S=t.makeTrainFunction(),_=t.getDedupedMetricsNames(),E=void 0,C=void 0,g?(t.makeTestFunction(),E=t.testFunction,C=_.slice().concat(_.map(function(t){return"val_"+t}))):(E=null,b=[],C=_.slice()),A=_e(i.callbacks,i.yieldEvery),[4,function(t,e,n,i,a,o,s,l,f,h,d,m,v,g,b){return u(this,void 0,void 0,function(){var u,b,y,w,x,k,S,_;return c(this,function(E){switch(E.label){case 0:return null==a&&(a=32),null==o&&(o=1),null==d&&(d=!0),null==v&&(v=0),u=!1,null!=f&&null!=h&&(u=!0),null!=(b=t.checkNumSamples(n,a,g,"steps_per_epoch"))&&(y=ut(0,b)),null==s&&(s=1),w=Ce(l,s,o,v,b,g,a,u,m),x=w.callbackList,k=w.history,x.setModel(t),t.history=k,[4,x.onTrainBegin()];case 1:E.sent(),t.stopTraining_=!1,S=function(o){var s,l,m,v,g;return c(this,function(w){switch(w.label){case 0:return[4,x.onEpochBegin(o)];case 1:return w.sent(),s={},[3,2];case 2:if("batch"===d)throw new p("batch shuffling is not implemneted yet");d&&r.util.shuffle(y),l=Object(r.tensor1d)(y),m=_n(b,a),v=function(o){var d;return c(this,function(c){switch(c.label){case 0:return d={},[4,x.onBatchBegin(o,d)];case 1:return c.sent(),Object(r.tidy)(function(){var c=m[o][0],p=m[o][1],v=ft(l,c,p-c);d.batch=o,d.size=p-c;for(var g=Sn(n,v),b=e(g),y=0;y0)a=!0;else if(On(t)){for(var o in t)if(t.hasOwnProperty(o)){a=!0;break}}else a=!0;if(a)throw new d("Error when checking model "+i+" expected no data, but got "+t)}return[]}if(null==t)return e.map(function(t){return null});var s;if(On(t)){t=t,s=[];for(var u=0,c=e;u1)throw new d("The model "+i+" expects "+e.length+" Tensor(s), but only received one Tensor. Found: Tensor with shape "+t.shape);s=[t]}if(s=Cn(s),null!=n)for(var f=0;f=0&&m!==v)throw new d("Error when checking "+i+": expected "+e[f]+" to have shape ["+n[f]+"], but got array with shape ["+h.shape+"].")}}return s}function In(t,e,n,r,i){var a;if(void 0===r&&(r=!0),void 0===i&&(i=""),Array.isArray(t)){if(t.length!==e.length)throw new d("Error when checking model "+i+": the Array of Tensors that you are passing to your model is not the size the the model expected. Expected to see "+e.length+" Tensor(s), but instead got "+t.length+" Tensors(s).");a=t}else{if(e.length>1)throw new d("The model expects "+e.length+" "+i+" Tensors, but only received one Tensor. Found: array with shape "+JSON.stringify(t.shape)+".");a=[t]}if(null!=n)for(var o=0;o1||1===s.length&&s[0].inboundLayers.length>1){e=!1;break}r.push.apply(r,s)}if(e)for(var u=0,c=t.layers;u1&&(e.metricsTensors.push([n,t]),e.metricsNames.push(e.outputNames[t]+"_loss"))}});var v=function(t,e){if(null==t||Array.isArray(t)&&0===t.length)return e.map(function(t){return[]});if(Array.isArray(t))return e.map(function(e){return t});if(null!=t){for(var n=[],r=0,i=e;r1&&(n=e.outputNames[t]+"_"+n),e.metricsNames.push(n),e.metricsTensors.push([r,t])}(t,r,c)},s=0,u=v[t];s0)throw new p("Verbose mode is not implemented yet.");return r.util.assert(!i||n.batches>0&&Number.isInteger(n.batches),function(){return"Test loop expects `batches` to be a positive integer, but received "+JSON.stringify(n.batches)}),"function"==typeof e.next?(u=e,[3,3]):[3,1];case 1:return[4,e.iterator()];case 2:u=v.sent(),v.label=3;case 3:s=u,l=0,f=0,h=function(){var e;return c(this,function(u){switch(u.label){case 0:return[4,s.next()];case 1:return e=u.sent(),o=Object(r.tidy)(function(){if(e.value){var n=bn(t,e.value),i=Object(r.tidy)(function(){return a(n)});if(Object(r.dispose)(n),0===f)for(var s=0;s0&&Object(r.dispose)(n)};for(s=0;s0){var l=[];throw e.forEach(function(e,n){null==e&&l.push(t[n])}),new d("Cannot find SymbolicTensors for output name(s): "+JSON.stringify(l))}return e},e.prototype.predictLoop=function(t,e,n){var i=this;return void 0===e&&(e=32),void 0===n&&(n=!1),Object(r.tidy)(function(){var a=i.checkNumSamples(t);if(n)throw new p("Verbose predictLoop() is not implemented yet.");for(var o=_n(a,e),s=i.outputs.map(function(t){return[]}),u=function(e){Object(r.tidy)(function(){var n=o[e][0],r=o[e][1],a=kn(t,n,r),s=[];if(Array.isArray(a))for(var u=0;u1)throw new d("All input Tensors (x) should have the same number of samples. Got array shapes: "+JSON.stringify(t.map(function(t){return t.shape})));if(a.length>1)throw new d("All target Tensors (y) should have the same number of samples. Got array shapes: "+JSON.stringify(e.map(function(t){return t.shape})));if(i.length>0&&a.length>0&&!r.util.arraysEqual(i,a))throw new d("Input Tensors should have the same number of samples as target Tensors. Found "+i[0]+" input sample(s) and "+a[0]+" target sample(s).")}(t=Tn(t,this.feedInputNames,this.feedInputShapes,!1,"input"),e=Tn(e,this.feedOutputNames,a,!1,"target")),function(t,e,n){for(var r=[Ne,Le,ze],i=0;i0&&t[0].shape[0]%i!=0)throw new d("In a stateful network, you should only pass inputs with a number of samples that is divisible by the batch size "+i+". Found: "+t[0].shape[0]+" sample(s).");return[t,e,null]},e.prototype.testLoop=function(t,e,n,i,a){var o=this;return void 0===i&&(i=0),Object(r.tidy)(function(){var s=o.checkNumSamples(e,n,a,"steps"),u=[];if(i>0)throw new p("Verbose mode is not implemented yet.");if(null!=a)throw new p("steps mode in testLoop() is not implemented yet");for(var c=_n(s,n),l=Object(r.tensor1d)(ut(0,s)),f=0;f1&&(i+="_"+b(t.slice(0,n),r)),e.push(i)}return e},e.prototype.makeTrainFunction=function(){var t=this;return function(e){var n=e.slice(0,t.inputs.length),i=e.slice(t.inputs.length,t.inputs.length+t.outputs.length),a=[],o=t.collectedTrainableWeights.map(function(t){return t.read()});return[t.optimizer_.minimize(function(){for(var e=[],o=0;o0&&Number.isInteger(n.epochs),function(){return"For fitDataset(), config.epochs is expected to be a positive integer, but got "+n.epochs}),r.util.assert(!i||n.batchesPerEpoch>0&&Number.isInteger(n.batchesPerEpoch),function(){return"For fitDataset(), config.batchesPerEpoch is expected to be a positive integer if specified, but got "+n.batchesPerEpoch}),r.util.assert(null==n.validationSplit,function(){return"`validationSplit` is not supported by `fitDataset()`. Use validationData instead."}),t.isTraining)throw new Error("Cannot start training because another fit() call is ongoing.");t.isTraining=!0,c.label=1;case 1:return c.trys.push([1,,22,23]),a=null!=n.validationData,o=void 0,s=void 0,a&&(wn(n.validationData)?r.util.assert(null==n.validationBatches||n.validationBatches>0&&Number.isInteger(n.validationBatches),function(){return"For fitDataset() with dataset-based validation, config.validationBatches is expected not to be provided, or to be a positive integer, but got "+n.validationBatches}):(u=function(t){if(3===t.length)throw new p("Validation with sample weights is not implemented yet.");return{xs:t[0],ys:t[1]}}(n.validationData),o=u.xs,s=u.ys)),l=t.makeTrainFunction(),f=t.getDedupedMetricsNames(),h=void 0,h=a?f.slice().concat(f.map(function(t){return"val_"+t})):f.slice(),d=_e(n.callbacks,n.yieldEvery),m=null==n.verbose?1:n.verbose,v=Ce(d,m,n.epochs,null,null,function(t,e){var n=null;return null!=e.batchesPerEpoch?n=e.batchesPerEpoch:Number.isFinite(t.size)&&(n=t.size),n}(e,n),null,a,h),g=v.callbackList,b=v.history,g.setModel(t),t.history=b,[4,g.onTrainBegin()];case 2:return c.sent(),t.stopTraining_=!1,y=null==n.initialEpoch?0:n.initialEpoch,[4,e.iterator()];case 3:x=c.sent(),c.label=4;case 4:return y=n.batchesPerEpoch:E.done)?a?(I=void 0,wn(n.validationData)?(M=w,[4,t.evaluateDataset(n.validationData,{batches:n.validationBatches})]):[3,13]):[3,15]:[3,16];case 12:return I=M.apply(void 0,[c.sent()]),[3,14];case 13:I=w(t.evaluate(o,s,{batchSize:null==n.validationBatchSize?gn:n.validationBatchSize,verbose:0})),c.label=14;case 14:for(R=0;R1)throw new d("Found more than one ("+n.length+") save handlers for URL '"+t+"'");t=n[0]}if(null==t.save)throw new d("LayersModel.save() cannot proceed because the IOHandler provided does not have the `save` attribute defined.");return[4,r.io.encodeWeights(this.getNamedWeights(e))];case 1:return i=u.sent(),a=!1,o=null,s=this.toJSON(o,a),[2,t.save({modelTopology:s,weightData:i.data,weightSpecs:i.specs,format:"layers-model",generatedBy:"TensorFlow.js tfjs-layers v1.1.2",convertedBy:null})]}})})},e.className="Model",e}(function(t){function e(n){var r=t.call(this,{})||this;if(r.containerNodes=new Set,r.name=n.name,null==r.name){var i=r.getClassName().toLowerCase();r.name=Jt(i)}if(r.supportsMasking=!1,r.trainable_=!0,r.updatable=!0,Array.isArray(n.inputs)?r.inputs=n.inputs.slice():r.inputs=[n.inputs],Array.isArray(n.outputs)?r.outputs=n.outputs.slice():r.outputs=[n.outputs],A(r.inputs).length!==r.inputs.length)throw new d("The list of inputs passed to the model is redundant. All inputs should only appear once. Found: "+r.inputs.map(function(t){return t.name}));A(r.outputs).length!==r.outputs.length&&console.warn("The list of outputs passed to the model is redundant. All outputs should only appear once. Found: "+r.outputs.map(function(t){return t.name})),r.inputLayers=[],r.inputLayersNodeIndices=[],r.inputLayersTensorIndices=[],r.outputLayers=[],r.outputLayersNodeIndices=[],r.outputLayersTensorIndices=[],r.layers=[];for(var a=0,o=r.outputs;a1 nodes"),g(0===c,"input layer has >1 tensors"),r.inputLayers.push(s),r.inputLayersNodeIndices.push(u),r.inputLayersTensorIndices.push(c);r.inputNames=[],r.outputNames=[],r.feedInputShapes=[],r.feedInputNames=[],r.feedOutputNames=[];for(var p=0;p=0;)i.splice(i.indexOf(u),1);S.push(u)}},E=[],N=[],O=0,T=r.outputs;Or?1:0});for(var K=0,X=G;K0)throw new d("Container instance unexpectedly contains _trainableWeights.The trainable weights of a Container are a union of the trainable weights of its consituent Layers. Its own _trainableWeights must remain an empty Array.");if(!this.trainable)return[];for(var t=[],e=0,n=this.layers;e0)throw new d(f.length+" of "+r+" weights are not set: "+f)}oe(c)},e.prototype.updatedConfig=function(){var t=this.getConfig(),e={};return e.className=this.getClassName(),e.config=t,e.kerasVersion="tfjs-layers 1.1.2",e.backend="TensorFlow.js",e},e.prototype.toJSON=function(t,e){void 0===e&&(e=!0);var n=function t(e,n){if(null===e||void 0===e)return null;if("string"==typeof e)return x(e);if("number"==typeof e||"boolean"==typeof e)return e;if(e instanceof Array){for(var r=[],i=e.length,a=0;a1)for(var s=0,u=o;s0){for(var d=[],p=0;p0&&t.apply(y(r),n)}function u(t){var n=t.name,a=un(t,null!=e.customObjects?e.customObjects:{});a.setFastWeightInitDuringBuild(r),i[n]=a,t.inboundNodes.forEach(function(t){if(!(t instanceof Array))throw new d("Corrupted configuration, expected array for nodeData: "+t);o(a,t)})}for(var c=e.name,l=e.layers,f=0,h=l;f0)&&(n=e.sourceLayer,r=e.nodeIndex),0===n.inboundNodes.length)return[e];var i=n.inboundNodes[r];if(0===i.inboundLayers.length)return i.inputTensors;for(var a=[],o=0;o1)throw new d("Found more than one ("+n.length+") load handlers for URL '"+t+"'");t=n[0]}return[2,function(t,e,n){return u(this,void 0,void 0,function(){var e,i,a,o,s,u;return c(this,function(c){switch(c.label){case 0:if(null==n&&(n={}),null==t.load)throw new d("Cannot proceed with model loading because the IOHandler provided does not have the `load` method implemented.");return[4,t.load()];case 1:if(e=c.sent(),null!=(i=e.modelTopology).model_config&&(i=i.model_config),a=null==n.strict||n.strict,o=null!=e.weightData&&null!=e.weightSpecs&&a,s=un(ln(i),void 0,o),null!=e.weightData){if(null==e.weightSpecs)throw new d("LayersModel artifacts contains weight data, but not weight specs. Therefore loading of weights cannot proceed.");u=r.io.decodeWeights(e.weightData,e.weightSpecs),s.loadWeights(u,a),Object(r.dispose)(u)}return[2,s]}})})}(t,0,e)]})})}(t,e)}function Pn(t){return me(t)}function Ln(t,e){Ee.registerCallbackConstructor(t,e)}r.serialization.registerClass(Rn);var Fn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.getConfig=function(){return{}},e}(r.serialization.Serializable),Bn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t,e){return void 0===e&&(e=1),function(t,e){if(void 0===e&&(e=1),1!==e)throw new p("Support for alpha values other than 1 ("+e+") is not implemented yet.");return Object(r.elu)(t)}(t,e)},e.className="elu",e}(Fn);r.serialization.registerClass(Bn);var Un=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.selu)(t)},e.className="selu",e}(Fn);r.serialization.registerClass(Un);var Vn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.relu)(t)},e.className="relu",e}(Fn);r.serialization.registerClass(Vn);var Wn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.tidy)(function(){return Object(r.minimum)(6,Object(r.relu)(t))})},e.className="relu6",e}(Fn);r.serialization.registerClass(Wn);var qn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return t},e.className="linear",e}(Fn);r.serialization.registerClass(qn);var Hn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.sigmoid)(t)},e.className="sigmoid",e}(Fn);r.serialization.registerClass(Hn);var Gn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return function(t){return Object(r.tidy)(function(){var e=Object(r.add)(.5,Object(r.mul)(.2,t));return Object(r.clipByValue)(e,0,1)})}(t)},e.className="hardSigmoid",e}(Fn);r.serialization.registerClass(Gn);var Kn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.softplus)(t)},e.className="softplus",e}(Fn);r.serialization.registerClass(Kn);var Xn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return function(t){return Object(r.tidy)(function(){return Object(r.div)(t,Object(r.abs)(t).add(1))})}(t)},e.className="softsign",e}(Fn);r.serialization.registerClass(Xn);var $n=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t){return Object(r.tanh)(t)},e.className="tanh",e}(Fn);r.serialization.registerClass($n);var Yn=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.apply=function(t,e){return void 0===e&&(e=-1),Object(r.softmax)(t,e)},e.className="softmax",e}(Fn);function Jn(t){return t.getClassName()}function Zn(t,e){return void 0===e&&(e={}),E(t,r.serialization.SerializationMap.getMap().classNameMap,e,"activation")}function Qn(t){var e;return null==t?Zn(e={className:"linear",config:{}}):"string"==typeof t?((e={}).className=t,e.config={},Zn(e)):t instanceof Fn?t:Zn(t)}r.serialization.registerClass(Yn);var tr=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e}(r.serialization.Serializable),er=function(t){function e(e){var n=t.call(this)||this;return n.l1=null==e||null==e.l1?.01:e.l1,n.l2=null==e||null==e.l2?.01:e.l2,n.hasL1=0!==n.l1,n.hasL2=0!==n.l2,n}return a(e,t),e.prototype.apply=function(t){var e=this;return Object(r.tidy)(function(){var n=Object(r.zeros)([1]);return e.hasL1&&(n=Object(r.add)(n,Object(r.sum)(Object(r.mul)(e.l1,Object(r.abs)(t))))),e.hasL2&&(n=Object(r.add)(n,Object(r.sum)(Object(r.mul)(e.l2,wt(t))))),n.asScalar()})},e.prototype.getConfig=function(){return{l1:this.l1,l2:this.l2}},e.fromConfig=function(t,e){return new t({l1:e.l1,l2:e.l2})},e.className="L1L2",e}(tr);r.serialization.registerClass(er);var nr={l1l2:"L1L2"};function rr(t){return _(t)}function ir(t,e){return void 0===e&&(e={}),E(t,r.serialization.SerializationMap.getMap().classNameMap,e,"regularizer")}function ar(t){return null==t?null:"string"==typeof t?ir({className:t in nr?nr[t]:t,config:{}}):t instanceof tr?t:ir(t)}var or=function(t){function e(e){var n=t.call(this,null==e?{}:e)||this;return n.supportsMasking=!0,null!=e&&(n.maxValue=e.maxValue),n}return a(e,t),e.prototype.call=function(t,e){t=te(t);var n=Object(r.relu)(t);return null!=this.maxValue&&(n=Object(r.clipByValue)(n,0,this.maxValue)),n},e.prototype.computeOutputShape=function(t){return t},e.prototype.getConfig=function(){var e={maxValue:this.maxValue},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e.className="ReLU",e}(de);r.serialization.registerClass(or);var sr=function(t){function e(e){var n=t.call(this,null==e?{}:e)||this;return n.DEFAULT_ALPHA=.3,null==e&&(e={}),n.alpha=null==e.alpha?n.DEFAULT_ALPHA:e.alpha,n}return a(e,t),e.prototype.call=function(t,e){var n=te(t);return Object(r.leakyRelu)(n,this.alpha)},e.prototype.computeOutputShape=function(t){return t},e.prototype.getConfig=function(){var e={alpha:this.alpha},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e.className="LeakyReLU",e}(de);r.serialization.registerClass(sr);var ur=function(t){function e(e){var n=t.call(this,null==e?{}:e)||this;if(n.DEFAULT_ALPHA_INITIALIZER="zeros",null==e&&(e={}),n.supportsMasking=!0,n.alphaInitializer=Gt(e.alphaInitializer||n.DEFAULT_ALPHA_INITIALIZER),n.alphaRegularizer=ar(e.alphaRegularizer),n.alphaConstraint=U(e.alphaConstraint),null==e.sharedAxes)n.sharedAxes=null;else if(Array.isArray(e.sharedAxes))n.sharedAxes=e.sharedAxes;else{if("number"!=typeof e.sharedAxes)throw new d("Expected sharedAxes to be a number or an array of numbers, but got "+e.sharedAxes);n.sharedAxes=[e.sharedAxes]}return n}return a(e,t),e.prototype.build=function(t){var e=(t=ee(t)).slice(1);if(null!=this.sharedAxes)for(var n=0,r=this.sharedAxes;n 0 but got "+JSON.stringify(t.filters))},e}(vr),br=function(t){function e(n){var r=t.call(this,2,n)||this;return e.verifyArgs(n),r}return a(e,t),e.prototype.getConfig=function(){var e=t.prototype.getConfig.call(this);return delete e.rank,e},e.verifyArgs=function(t){if("number"!=typeof t.kernelSize&&!T(t.kernelSize,"number",1,2))throw new d("Conv2D expects config.kernelSize to be number or number[] with length 1 or 2, but received "+JSON.stringify(t.kernelSize)+".")},e.className="Conv2D",e}(gr);r.serialization.registerClass(br);var yr=function(t){function e(n){var r=t.call(this,3,n)||this;return e.verifyArgs(n),r}return a(e,t),e.prototype.getConfig=function(){var e=t.prototype.getConfig.call(this);return delete e.rank,e},e.verifyArgs=function(t){if("number"!=typeof t.kernelSize&&(!Array.isArray(t.kernelSize)||1!==t.kernelSize.length&&3!==t.kernelSize.length))throw new d("Conv3D expects config.kernelSize to be number or [number, number, number], but received "+JSON.stringify(t.kernelSize)+".")},e.className="Conv3D",e}(gr);r.serialization.registerClass(yr);var wr=function(t){function e(e){var n=t.call(this,e)||this;if(n.inputSpec=[new ue({ndim:4})],"same"!==n.padding&&"valid"!==n.padding)throw new d("Conv2DTranspose currently supports only padding modes 'same' and 'valid', but received padding mode "+n.padding);return n}return a(e,t),e.prototype.build=function(t){var e;if(4!==(t=ee(t)).length)throw new d("Input should have rank 4; Received input shape: "+JSON.stringify(t));var n="channelsFirst"===this.dataFormat?1:t.length-1;if(null==t[n])throw new d("The channel dimension of the inputs should be defined. Found `None`.");var r=t[n],i=this.kernelSize.concat([this.filters,r]);this.kernel=this.addWeight("kernel",i,"float32",this.kernelInitializer,this.kernelRegularizer,!0,this.kernelConstraint),this.useBias&&(this.bias=this.addWeight("bias",[this.filters],"float32",this.biasInitializer,this.biasRegularizer,!0,this.biasConstraint)),this.inputSpec=[new ue({ndim:4,axes:(e={},e[n]=r,e)})],this.built=!0},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){var e=te(t);if(4!==e.shape.length)throw new d("Conv2DTranspose.call() expects input tensor to be rank-4, but received a tensor of rank-"+e.shape.length);var i,a,o=e.shape,s=o[0];"channelsFirst"===n.dataFormat?(i=2,a=3):(i=1,a=2);var u=o[i],c=o[a],l=n.kernelSize[0],f=n.kernelSize[1],h=n.strides[0],p=n.strides[1],m=[s,pr(u,h,l,n.padding),pr(c,p,f,n.padding),n.filters];"channelsLast"!==n.dataFormat&&(e=Object(r.transpose)(e,[0,2,3,1]));var v=Object(r.conv2dTranspose)(e,n.kernel.read(),m,n.strides,n.padding);return"channelsLast"!==n.dataFormat&&(v=Object(r.transpose)(v,[0,3,1,2])),null!=n.bias&&(v=kt(v,n.bias.read(),n.dataFormat)),null!=n.activation&&(v=n.activation.apply(v)),v})},e.prototype.computeOutputShape=function(t){var e,n,r,i=(t=ee(t)).slice();"channelsFirst"===this.dataFormat?(e=1,n=2,r=3):(e=3,n=1,r=2);var a=this.kernelSize[0],o=this.kernelSize[1],s=this.strides[0],u=this.strides[1];return i[e]=this.filters,i[n]=pr(i[n],s,a,this.padding),i[r]=pr(i[r],u,o,this.padding),i},e.prototype.getConfig=function(){var e=t.prototype.getConfig.call(this);return delete e.dilationRate,e},e.className="Conv2DTranspose",e}(br);r.serialization.registerClass(wr);var xr=function(t){function e(e){return t.call(this,2,e)||this}return a(e,t),e.className="SeparableConv2D",e}(function(t){function e(e,n){var r=t.call(this,e,n)||this;if(r.DEFAULT_DEPTHWISE_INITIALIZER="glorotUniform",r.DEFAULT_POINTWISE_INITIALIZER="glorotUniform",r.depthwiseKernel=null,r.pointwiseKernel=null,null==n.filters)throw new d("The `filters` configuration field is required by SeparableConv, but is unspecified.");if(null!=n.kernelInitializer||null!=n.kernelRegularizer||null!=n.kernelConstraint)throw new d("Fields kernelInitializer, kernelRegularizer and kernelConstraint are invalid for SeparableConv2D. Use depthwiseInitializer, depthwiseRegularizer, depthwiseConstraint, pointwiseInitializer, pointwiseRegularizer and pointwiseConstraint instead.");if(null!=n.padding&&"same"!==n.padding&&"valid"!==n.padding)throw new d("SeparableConv"+r.rank+"D supports only padding modes: 'same' and 'valid', but received "+JSON.stringify(n.padding));return r.depthMultiplier=null==n.depthMultiplier?1:n.depthMultiplier,r.depthwiseInitializer=Gt(n.depthwiseInitializer||r.DEFAULT_DEPTHWISE_INITIALIZER),r.depthwiseRegularizer=ar(n.depthwiseRegularizer),r.depthwiseConstraint=U(n.depthwiseConstraint),r.pointwiseInitializer=Gt(n.depthwiseInitializer||r.DEFAULT_POINTWISE_INITIALIZER),r.pointwiseRegularizer=ar(n.pointwiseRegularizer),r.pointwiseConstraint=U(n.pointwiseConstraint),r}return a(e,t),e.prototype.build=function(t){var e;if((t=ee(t)).length1)throw new d("Can not merge tensors with different batch sizes. Got tensors with shapes: "+JSON.stringify(t)+".");for(var i=null==t[0]?null:t[0].slice(1),a=1;a1){var b=ut(1,u).concat([0]);e.push(Object(r.transpose)(d,b)),l=!0}else e.push(d)}var y=n.mergeFunction(e),w=y.rank;if(l)if(null==w){var x=y.shape;v=[m=x[x.length-1]].concat(x.slice(0,x.length-1)),y=Object(r.transpose)(y.reshape([-1,m]),[1,0]).reshape(v)}else w>1&&(b=[w-1].concat(ut(0,w-1)),y=Object(r.transpose)(y,b));return y}return n.mergeFunction(t)})},e.prototype.computeOutputShape=function(t){var e;e=null==(t=t)[0]?null:t[0].slice(1);for(var n=1;n1)throw new d("A `Concatenate` layer requires inputs with matching shapes except for the concat axis. Got input shapes: "+JSON.stringify(t))}},e.prototype.mergeFunction=function(t){var e=this;return Object(r.tidy)(function(){return pt(t,e.axis)})},e.prototype.computeOutputShape=function(t){if(!Array.isArray(t)||!Array.isArray(t[0]))throw new d("A `Concatenate` layer should be called on a list of inputs.");for(var e=t,n=e[0].slice(),r=this.axis<0?n.length+this.axis:this.axis,i=0,a=e.slice(1);i3||n.length>3)throw new p("Dot layer does not support tensors of 4D or higher rank yet.");var i=this.interpretAxes(e,n);if(e[i[0]]!==n[i[1]])throw new d("Dimension incompatibility: "+e[i[0]]+" !== "+n[i[1]])},e.prototype.mergeFunction=function(t){if(2!==t.length)throw new d("A `Dot` layer must be called on exactly 2 inputs, but received "+t.length+" input(s).");var e,n=t[0],i=t[1];return e=Array.isArray(this.axes)?this.axes.map(function(e,n){return Vr(e,t[n].shape.length)}):[Vr(this.axes,n.shape.length),Vr(this.axes,i.shape.length)],this.normalize&&(n=Ae(n,e[0]),i=Ae(i,e[1])),function(t,e,n){if(t.shape.length>3||e.shape.length>3)throw new p("batchDot is not implemented for tensors of 4D or higher rank yet");if(r.util.assert(t.shape.length>=2,function(){return"batchDot requires the rank of x to be >= 2, but got "+t.shape.length}),r.util.assert(t.shape.length>=2,function(){return"batchDot requires the rank of y to be >= 2, but got "+e.shape.length}),"number"==typeof n&&(n=[n,n]),"complex64"===t.dtype||"complex64"===e.dtype)throw new p("batchDot is not implemented for complex64-type Tensors yet.");var i=t.shape.length,a=e.shape.length;null==n&&(n=[i-1,a-2]);var o=n;return Object(r.tidy)(function(){var n,r;if(i>a){n=i-a;for(var s=[],u=0;ui){for(n=a-i,s=[],u=0;u0){var f,h=[];for(u=f=i>a?i+a-3:i-1;u3||n.length>3)throw new p("Dot layer does not support tensors of 4D or higher rank yet.");var i=this.interpretAxes(e,n);e.splice(i[0],1),n.splice(i[1],1),n.splice(0,1);var a=e.concat(n);return 1===a.length&&a.push(1),a},e.prototype.computeMask=function(t,e){return null},e.prototype.getConfig=function(){var e={axes:this.axes,normalize:this.normalize},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e.className="Dot",e}(jr);function qr(t,e,n,i,a,o){var s;if(void 0===o&&(o=.001),2===t.rank)s=Object(r.batchNorm2d)(t,e,n,i,a,o);else if(3===t.rank)s=Object(r.batchNorm3d)(t,e,n,i,a,o);else{if(4!==t.rank)throw new p("batchNormalization is not implemented for array of rank "+t.rank+" yet");s=Object(r.batchNorm4d)(t,e,n,i,a,o)}return s}r.serialization.registerClass(Wr);var Hr=function(t){function e(e){var n=this;return null==e&&(e={}),(n=t.call(this,e)||this).supportsMasking=!0,n.axis=null==e.axis?-1:e.axis,n.momentum=null==e.momentum?.99:e.momentum,n.epsilon=null==e.epsilon?.001:e.epsilon,n.center=null==e.center||e.center,n.scale=null==e.scale||e.scale,n.betaInitializer=Gt(e.betaInitializer||"zeros"),n.gammaInitializer=Gt(e.gammaInitializer||"ones"),n.movingMeanInitializer=Gt(e.movingMeanInitializer||"zeros"),n.movingVarianceInitializer=Gt(e.movingVarianceInitializer||"ones"),n.betaConstraint=U(e.betaConstraint),n.gammaConstraint=U(e.gammaConstraint),n.betaRegularizer=ar(e.betaRegularizer),n.gammaRegularizer=ar(e.gammaRegularizer),n}return a(e,t),e.prototype.build=function(t){var e;t=ee(t);var n=this.axis>=0?this.axis:this.axis+t.length,r=t[n];if(null==r)throw new d("Axis "+n+" of input tensor should have a defined dimension but the layer received an input with shape "+JSON.stringify(t)+".");this.inputSpec=[new ue({ndim:t.length,axes:(e={},e[n]=r,e)})];var i=[r];this.scale&&(this.gamma=this.addWeight("gamma",i,null,this.gammaInitializer,this.gammaRegularizer,!0,this.gammaConstraint)),this.center&&(this.beta=this.addWeight("beta",i,null,this.betaInitializer,this.betaRegularizer,!0,this.betaConstraint)),this.movingMean=this.addWeight("moving_mean",i,null,this.movingMeanInitializer,null,!1),this.movingVariance=this.addWeight("moving_variance",i,null,this.movingVarianceInitializer,null,!1),this.built=!0},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){var i=null!=e.training&&e.training,a=te(t),o=a.shape,s=o.length,u=ut(0,s),c=n.axis>=0?n.axis:n.axis+s;u.splice(c,1);var l=v(1,s);l[c]=o[c];var f=u.slice();f.sort();var h=!r.util.arraysEqual(f,ut(0,s).slice(0,s-1));if(!i)return function(){if(h){var t=n.movingMean.read().reshape(l),e=n.movingVariance.read().reshape(l),r=n.center?n.beta.read().reshape(l):null,i=n.scale?n.gamma.read().reshape(l):null;return qr(a,t,e,r,i,n.epsilon)}return qr(a,n.movingMean.read(),n.movingVariance.read(),null==n.beta?null:n.beta.read(),null==n.gamma?null:n.gamma.read(),n.epsilon)}();var d=function(t,e,n,i,a){return void 0===a&&(a=.001),r.util.arraysEqual(i.slice().sort(),ut(0,t.rank-1))?function(t,e,n,i,a){return void 0===a&&(a=.001),Object(r.tidy)(function(){var o=Object(r.moments)(t,i),s=o.mean,u=o.variance;return[qr(t,s,u,n,e,a),s,u]})}(t,e,n,i,a):function(t,e,n,i,a){return void 0===a&&(a=.001),Object(r.tidy)(function(){for(var o=Object(r.moments)(t,i),s=o.mean,u=o.variance,c=[],l=0,f=ut(0,t.rank);l=0?t[2]+this.padding[0][0]+this.padding[0][1]:null,n=null!=t[3]&&t[3]>=0?t[3]+this.padding[1][0]+this.padding[1][1]:null,[t[0],t[1],e,n]):(e=null!=t[1]&&t[1]>=0?t[1]+this.padding[0][0]+this.padding[0][1]:null,n=null!=t[2]&&t[2]>=0?t[2]+this.padding[1][0]+this.padding[1][1]:null,[t[0],e,n,t[3]])},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){return function(t,e,n){return Object(r.tidy)(function(){if(4!==t.rank)throw new d("temporalPadding expects input tensor to be 4-D, but received a "+t.rank+"-D tensor.");if(null==e&&(e=[[1,1],[1,1]]),2!==e.length||2!==e[0].length||2!==e[1].length)throw new d("spatial2dPadding expects `padding` to be an Array of two Arrays, each of which is an Array of two integers.");if(null==n&&(n="channelsLast"),"channelsLast"!==n&&"channelsFirst"!==n)throw new d("Unknown data format: "+n+". Supported data formats are 'channelsLast' and 'channelsFirst.");var i;return i="channelsFirst"===n?[[0,0],[0,0],e[0],e[1]]:[[0,0],e[0],e[1],[0,0]],Object(r.pad)(t,i)})}(te(t),n.padding,n.dataFormat)})},e.prototype.getConfig=function(){var e={padding:this.padding,dataFormat:this.dataFormat},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e.className="ZeroPadding2D",e}(de);function Kr(t,e,n,i,a,o){return Object(r.tidy)(function(){var s;X(a),O(H,"PoolMode",o),$(i),null==n&&(n=[1,1]),null==i&&(i="valid"),null==a&&(a="channelsLast"),null==o&&(o="max"),t=mr(t,a);var u="same"===i?"same":"valid";return s="max"===o?Object(r.maxPool)(t,e,n,u):Object(r.avgPool)(t,e,n,u),"channelsFirst"===a&&(s=Object(r.transpose)(s,[0,3,1,2])),s})}r.serialization.registerClass(Gr);var Xr=function(t){function e(e){var n=this;if(null==e.poolSize&&(e.poolSize=2),n=t.call(this,e)||this,"number"==typeof e.poolSize)n.poolSize=[e.poolSize];else{if(!Array.isArray(e.poolSize)||1!==e.poolSize.length||"number"!=typeof e.poolSize[0])throw new d("poolSize for 1D convolutional layer must be a number or an Array of a single number, but received "+JSON.stringify(e.poolSize));n.poolSize=e.poolSize}if(I(n.poolSize,"poolSize"),null==e.strides)n.strides=n.poolSize;else if("number"==typeof e.strides)n.strides=[e.strides];else{if(!Array.isArray(e.strides)||1!==e.strides.length||"number"!=typeof e.strides[0])throw new d("strides for 1D convolutional layer must be a number or an Array of a single number, but received "+JSON.stringify(e.strides));n.strides=e.strides}return I(n.strides,"strides"),n.padding=null==e.padding?"valid":e.padding,$(n.padding),n.inputSpec=[new ue({ndim:3})],n}return a(e,t),e.prototype.computeOutputShape=function(t){var e=dr((t=ee(t))[1],this.poolSize[0],this.padding,this.strides[0]);return[t[0],e,t[2]]},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){n.invokeCallHook(t,e),t=lt(te(t),2);var i=n.poolingFunction(te(t),[n.poolSize[0],1],[n.strides[0],1],n.padding,"channelsLast");return Object(r.squeeze)(i,[2])})},e.prototype.getConfig=function(){var e={poolSize:this.poolSize,padding:this.padding,strides:this.strides},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e}(de),$r=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e.prototype.poolingFunction=function(t,e,n,r,i){return X(i),$(r),Kr(t,e,n,r,i,"max")},e.className="MaxPooling1D",e}(Xr);r.serialization.registerClass($r);var Yr=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e.prototype.poolingFunction=function(t,e,n,r,i){return X(i),$(r),Kr(t,e,n,r,i,"avg")},e.className="AveragePooling1D",e}(Xr);r.serialization.registerClass(Yr);var Jr=function(t){function e(e){var n=this;if(null==e.poolSize&&(e.poolSize=[2,2]),(n=t.call(this,e)||this).poolSize=Array.isArray(e.poolSize)?e.poolSize:[e.poolSize,e.poolSize],null==e.strides)n.strides=n.poolSize;else if(Array.isArray(e.strides)){if(2!==e.strides.length)throw new d("If the strides property of a 2D pooling layer is an Array, it is expected to have a length of 2, but received length "+e.strides.length+".");n.strides=e.strides}else n.strides=[e.strides,e.strides];return I(n.poolSize,"poolSize"),I(n.strides,"strides"),n.padding=null==e.padding?"valid":e.padding,n.dataFormat=null==e.dataFormat?"channelsLast":e.dataFormat,X(n.dataFormat),$(n.padding),n.inputSpec=[new ue({ndim:4})],n}return a(e,t),e.prototype.computeOutputShape=function(t){t=ee(t);var e="channelsFirst"===this.dataFormat?t[2]:t[1],n="channelsFirst"===this.dataFormat?t[3]:t[2];return e=dr(e,this.poolSize[0],this.padding,this.strides[0]),n=dr(n,this.poolSize[1],this.padding,this.strides[1]),"channelsFirst"===this.dataFormat?[t[0],t[1],e,n]:[t[0],e,n,t[3]]},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){return n.invokeCallHook(t,e),n.poolingFunction(te(t),n.poolSize,n.strides,n.padding,n.dataFormat)})},e.prototype.getConfig=function(){var e={poolSize:this.poolSize,padding:this.padding,strides:this.strides,dataFormat:this.dataFormat},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e}(de),Zr=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e.prototype.poolingFunction=function(t,e,n,r,i){return X(i),$(r),Kr(t,e,n,r,i,"max")},e.className="MaxPooling2D",e}(Jr);r.serialization.registerClass(Zr);var Qr=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e.prototype.poolingFunction=function(t,e,n,r,i){return X(i),$(r),Kr(t,e,n,r,i,"avg")},e.className="AveragePooling2D",e}(Jr);r.serialization.registerClass(Qr);var ti=function(t){function e(e){var n=t.call(this,e)||this;return n.inputSpec=[new ue({ndim:3})],n}return a(e,t),e.prototype.computeOutputShape=function(t){return[t[0],t[2]]},e.prototype.call=function(t,e){throw new p},e}(de),ei=function(t){function e(e){return t.call(this,e||{})||this}return a(e,t),e.prototype.call=function(t,e){return Object(r.tidy)(function(){var e=te(t);return Object(r.mean)(e,1)})},e.className="GlobalAveragePooling1D",e}(ti);r.serialization.registerClass(ei);var ni=function(t){function e(e){return t.call(this,e||{})||this}return a(e,t),e.prototype.call=function(t,e){return Object(r.tidy)(function(){var e=te(t);return Object(r.max)(e,1)})},e.className="GlobalMaxPooling1D",e}(ti);r.serialization.registerClass(ni);var ri=function(t){function e(e){var n=t.call(this,e)||this;return n.dataFormat=null==e.dataFormat?"channelsLast":e.dataFormat,X(n.dataFormat),n.inputSpec=[new ue({ndim:4})],n}return a(e,t),e.prototype.computeOutputShape=function(t){return t=t,"channelsLast"===this.dataFormat?[t[0],t[3]]:[t[0],t[1]]},e.prototype.call=function(t,e){throw new p},e.prototype.getConfig=function(){var e={dataFormat:this.dataFormat},n=t.prototype.getConfig.call(this);return Object.assign(e,n),e},e}(de),ii=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){var e=te(t);return"channelsLast"===n.dataFormat?Object(r.mean)(e,[1,2]):Object(r.mean)(e,[2,3])})},e.className="GlobalAveragePooling2D",e}(ri);r.serialization.registerClass(ii);var ai=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){var e=te(t);return"channelsLast"===n.dataFormat?Object(r.max)(e,[1,2]):Object(r.max)(e,[2,3])})},e.className="GlobalMaxPooling2D",e}(ri);function oi(t,e,n,r){if(Array.isArray(t)){if(null!=e||null!=n)throw new d("When inputs is an array, neither initialState or constants should be provided");null!=r&&(n=t.slice(t.length-r,t.length),t=t.slice(0,t.length-r)),t.length>1&&(e=t.slice(1,t.length)),t=t[0]}function i(t){return null==t||Array.isArray(t)?t:[t]}return{inputs:t,initialState:e=i(e),constants:n=i(n)}}function si(t,e,n,i,a,o,s,u){return void 0===i&&(i=!1),void 0===s&&(s=!1),void 0===u&&(u=!1),Object(r.tidy)(function(){var c=e.shape.length;if(c<3)throw new d("Input should be at least 3D, but is "+c+"D.");var l=[1,0].concat(ut(2,c));if(e=Object(r.transpose)(e,l),null!=o)throw new p("The rnn() functoin of the deeplearn.js backend does not support constants yet.");s&&console.warn("Backend rnn(): the unroll = true option is not applicable to the imperative deeplearn.js backend."),null!=a&&((a=a.asType("bool").asType("float32")).rank===c-1&&(a=Object(r.expandDims)(a,-1)),a=Object(r.transpose)(a,l)),i&&(e=Object(r.reverse)(e,0),null!=a&&(a=Object(r.reverse)(a,0)));var f,h,m=[],v=n,g=e.shape[0],b=Object(r.unstack)(e);null!=a&&(h=Object(r.unstack)(a));for(var y,w=function(e){var n=b[e],i=Object(r.tidy)(function(){return t(n,v)});if(null==a)f=i[0],v=i[1];else{var o=Object(r.tidy)(function(){var t=h[e],n=Object(r.onesLike)(t).sub(t);return{output:i[0].mul(t).addStrict(v[0].mul(n)),newStates:v.map(function(e,r){return i[1][r].mul(t).addStrict(e.mul(n))})}});f=o.output,v=o.newStates}u&&m.push(f)},x=0;x1?vt(n,[1,t]):n}):e.cell.stateSize>1?[vt(n,[1,e.cell.stateSize])]:[n]})},Object.defineProperty(e.prototype,"trainableWeights",{get:function(){return this.trainable?this.cell.trainableWeights:[]},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"nonTrainableWeights",{get:function(){return this.trainable?this.cell.nonTrainableWeights:this.cell.weights},enumerable:!0,configurable:!0}),e.prototype.setFastWeightInitDuringBuild=function(e){t.prototype.setFastWeightInitDuringBuild.call(this,e),null!=this.cell&&this.cell.setFastWeightInitDuringBuild(e)},e.prototype.getConfig=function(){var e={returnSequences:this.returnSequences,returnState:this.returnState,goBackwards:this.goBackwards,stateful:this.stateful,unroll:this.unroll};null!=this.numConstants&&(e.numConstants=this.numConstants);var n=this.cell.getConfig();e.cell={className:this.cell.getClassName(),config:n};var r=t.prototype.getConfig.call(this);return Object.assign(e,r),e},e.className="RNN",e}(de);r.serialization.registerClass(ui);var ci=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e}(de),li=function(t){function e(e){var n=t.call(this,e)||this;return n.DEFAULT_ACTIVATION="tanh",n.DEFAULT_KERNEL_INITIALIZER="glorotNormal",n.DEFAULT_RECURRENT_INITIALIZER="orthogonal",n.DEFAULT_BIAS_INITIALIZER="zeros",n.units=e.units,I(n.units,"units"),n.activation=Qn(null==e.activation?n.DEFAULT_ACTIVATION:e.activation),n.useBias=null==e.useBias||e.useBias,n.kernelInitializer=Gt(e.kernelInitializer||n.DEFAULT_KERNEL_INITIALIZER),n.recurrentInitializer=Gt(e.recurrentInitializer||n.DEFAULT_RECURRENT_INITIALIZER),n.biasInitializer=Gt(e.biasInitializer||n.DEFAULT_BIAS_INITIALIZER),n.kernelRegularizer=ar(e.kernelRegularizer),n.recurrentRegularizer=ar(e.recurrentRegularizer),n.biasRegularizer=ar(e.biasRegularizer),n.kernelConstraint=U(e.kernelConstraint),n.recurrentConstraint=U(e.recurrentConstraint),n.biasConstraint=U(e.biasConstraint),n.dropout=ot([1,st([0,null==e.dropout?0:e.dropout])]),n.recurrentDropout=ot([1,st([0,null==e.recurrentDropout?0:e.recurrentDropout])]),n.stateSize=n.units,n.dropoutMask=null,n.recurrentDropoutMask=null,n}return a(e,t),e.prototype.build=function(t){t=ee(t),this.kernel=this.addWeight("kernel",[t[t.length-1],this.units],null,this.kernelInitializer,this.kernelRegularizer,!0,this.kernelConstraint),this.recurrentKernel=this.addWeight("recurrent_kernel",[this.units,this.units],null,this.recurrentInitializer,this.recurrentRegularizer,!0,this.recurrentConstraint),this.useBias?this.bias=this.addWeight("bias",[this.units],null,this.biasInitializer,this.biasRegularizer,!0,this.biasConstraint):this.bias=null,this.built=!0},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){if(2!==(t=t).length)throw new d("SimpleRNNCell expects 2 input Tensors, got "+t.length+".");var i=t[1];t=t[0];var a,o=null!=e.training&&e.training;01){for(var o=[],s=0;s= 3D, but received input shape "+JSON.stringify(e));this.inputSpec=[{shape:e}];var n=[e[0]].concat(e.slice(2));this.layer.built||(this.layer.build(n),this.layer.built=!0),t.prototype.build.call(this,e)},e.prototype.computeOutputShape=function(t){var e=[(t=ee(t))[0]].concat(t.slice(2)),n=this.layer.computeOutputShape(e),r=t[1];return[n[0],r].concat(n.slice(1))},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){return si(function(t,r){return[te(n.layer.call(t,e)),[]]},t=te(t),[],!1,null,null,!1,!0)[1]})},e.className="TimeDistributed",e}(bi);r.serialization.registerClass(yi);var wi="concat",xi=function(t){function e(e){var n=t.call(this,e)||this,r=e.layer.getConfig(),i={};i.className=e.layer.getClassName(),i.config=r,n.forwardLayer=un(i),r.goBackwards=!0!==r.goBackwards;var a={};if(a.className=e.layer.getClassName(),a.config=r,n.backwardLayer=un(a),n.forwardLayer.name="forward_"+n.forwardLayer.name,n.backwardLayer.name="backward_"+n.backwardLayer.name,n.mergeMode=void 0===e.mergeMode?wi:e.mergeMode,function(t){O(G,"BidirectionalMergeMode",t)}(n.mergeMode),e.weights)throw new p("weights support is not implemented for Bidirectional layer yet.");return n._stateful=e.layer.stateful,n.returnSequences=e.layer.returnSequences,n.returnState=e.layer.returnState,n.supportsMasking=!0,n._trainable=!0,n.inputSpec=e.layer.inputSpec,n.numConstants=null,n}return a(e,t),Object.defineProperty(e.prototype,"trainable",{get:function(){return this._trainable},set:function(t){this._trainable=t,null!=this.forwardLayer&&(this.forwardLayer.trainable=t),null!=this.backwardLayer&&(this.backwardLayer.trainable=t)},enumerable:!0,configurable:!0}),e.prototype.getWeights=function(){return this.forwardLayer.getWeights().concat(this.backwardLayer.getWeights())},e.prototype.setWeights=function(t){var e=t.length,n=Math.floor(e/2);this.forwardLayer.setWeights(t.slice(0,n)),this.backwardLayer.setWeights(t.slice(n))},e.prototype.computeOutputShape=function(t){var e,n,r,i=this.forwardLayer.computeOutputShape(t);return Array.isArray(i)&&Array.isArray(i[0])||(i=[i]),i=i,this.returnState?(r=i.slice(1),e=i[0]):e=i[0],e=e,"concat"===this.mergeMode?(e[e.length-1]*=2,n=[e]):n=null==this.mergeMode?[e,e.slice()]:[e],this.returnState?null==this.mergeMode?n.concat(r).concat(r.slice()):[e].concat(r).concat(r.slice()):y(n)},e.prototype.apply=function(e,n){var r=null==n?null:n.initialState,i=null==n?null:n.constants;null==n&&(n={});var a=oi(e,r,i,this.numConstants);if(e=a.inputs,r=a.initialState,i=a.constants,Array.isArray(e)&&(r=e.slice(1),e=e[0]),(null==r||0===r.length)&&null==i)return t.prototype.apply.call(this,e,n);var o=[],s=[];if(null!=r){var u=r.length;if(u%2>0)throw new d("When passing `initialState` to a Bidrectional RNN, the state should be an Array containing the states of the underlying RNNs.");n.initialState=r,o.push.apply(o,r);var c=r.map(function(t){return new ue({shape:t.shape})});this.forwardLayer.stateSpec=c.slice(0,u/2),this.backwardLayer.stateSpec=c.slice(u/2),s.push.apply(s,c)}if(null!=i)throw new p("Support for constants in Bidirectional layers is not implemented yet.");for(var l=o[0]instanceof ce,f=0,h=o;f0&&n.rate<1?_t(function(){var t=Math.sqrt(n.rate/(1-n.rate));return bt(r,gt(r.shape,1,t))},function(){return r},e.training||!1):r})},e.className="GaussianDropout",e}(de);r.serialization.registerClass(Si);var _i=function(t){function e(e){var n=t.call(this,e)||this;return n.supportsMasking=!0,n.rate=e.rate,n.noiseShape=e.noiseShape,n}return a(e,t),e.prototype._getNoiseShape=function(t){return this.noiseShape||te(t).shape},e.prototype.computeOutputShape=function(t){return t},e.prototype.getConfig=function(){var e=t.prototype.getConfig.call(this),n={rate:this.rate};return Object.assign(n,e),n},e.prototype.call=function(t,e){var n=this;return Object(r.tidy)(function(){if(n.rate<1&&n.rate>0){var i=n._getNoiseShape(t);return _t(function(){var e=te(t),a=-1.7580993408473766,o=Object(r.greaterEqual)(Object(r.randomUniform)(i),n.rate);o=ct(o,"float32");var s=Math.pow((1-n.rate)*(1+n.rate*Math.pow(a,2)),-.5),u=-s*a*n.rate;return bt(e,o).add(o.add(-1).mul(a)).mul(s).add(u)},function(){return te(t)},e.training||!1)}return t})},e.className="AlphaDropout",e}(de);function Ei(t){return new Yr(t)}function Ci(t){return new Qr(t)}function Ai(t){return new ni(t)}function Ni(t){return new ai(t)}function Oi(t){return new $r(t)}function Ti(t){return new Zr(t)}r.serialization.registerClass(_i);var Ii=Ai,Mi=Ni,Ri=Oi,Di=Ti,ji=Object.freeze({inputLayer:function(t){return new pe(t)},elu:function(t){return new cr(t)},reLU:function(t){return new or(t)},leakyReLU:function(t){return new sr(t)},prelu:function(t){return new ur(t)},softmax:function(t){return new fr(t)},thresholdedReLU:function(t){return new lr(t)},conv1d:function(t){return new kr(t)},conv2d:function(t){return new br(t)},conv2dTranspose:function(t){return new wr(t)},conv3d:function(t){return new yr(t)},separableConv2d:function(t){return new xr(t)},cropping2D:function(t){return new Sr(t)},upSampling2d:function(t){return new _r(t)},depthwiseConv2d:function(t){return new Er(t)},activation:function(t){return new Or(t)},dense:function(t){return new Ar(t)},dropout:function(t){return new Cr(t)},flatten:function(t){return new Nr(t)},repeatVector:function(t){return new Tr(t)},reshape:function(t){return new Ir(t)},permute:function(t){return new Mr(t)},embedding:function(t){return new Dr(t)},add:function(t){return new zr(t)},average:function(t){return new Lr(t)},concatenate:function(t){return new Ur(t)},maximum:function(t){return new Fr(t)},minimum:function(t){return new Br(t)},multiply:function(t){return new Pr(t)},dot:function(t){return new Wr(t)},batchNormalization:function(t){return new Hr(t)},zeroPadding2d:function(t){return new Gr(t)},averagePooling1d:Ei,avgPool1d:function(t){return Ei(t)},avgPooling1d:function(t){return Ei(t)},averagePooling2d:Ci,avgPool2d:function(t){return Ci(t)},avgPooling2d:function(t){return Ci(t)},globalAveragePooling1d:function(t){return new ei(t)},globalAveragePooling2d:function(t){return new ii(t)},globalMaxPooling1d:Ai,globalMaxPooling2d:Ni,maxPooling1d:Oi,maxPooling2d:Ti,gru:function(t){return new di(t)},gruCell:function(t){return new hi(t)},lstm:function(t){return new mi(t)},lstmCell:function(t){return new pi(t)},simpleRNN:function(t){return new fi(t)},simpleRNNCell:function(t){return new li(t)},rnn:function(t){return new ui(t)},stackedRNNCells:function(t){return new vi(t)},bidirectional:function(t){return new xi(t)},timeDistributed:function(t){return new yi(t)},globalMaxPool1d:Ii,globalMaxPool2d:Mi,maxPool1d:Ri,maxPool2d:Di,Layer:de,RNN:ui,RNNCell:ci,input:Pn,gaussianNoise:function(t){return new ki(t)},gaussianDropout:function(t){return new Si(t)},alphaDropout:function(t){return new _i(t)},masking:function(t){return new Rr(t)}}),zi=Object.freeze({binaryAccuracy:function(t,e){return We(t,e)},binaryCrossentropy:function(t,e){return Ke(t,e)},sparseCategoricalAccuracy:function(t,e){return Xe(t,e)},categoricalAccuracy:function(t,e){return qe(t,e)},categoricalCrossentropy:function(t,e){return en(t,e)},precision:function(t,e){return Ge(t,e)},recall:function(t,e){return function(t,e){return Object(r.tidy)(function(){var n=He(t,e),i=function(t,e){return Object(r.tidy)(function(){return Object(r.logicalAnd)(t.equal(1),e.equal(0)).sum().cast("float32")})}(t,e),a=n.add(i);return Object(r.where)(Object(r.greater)(a,0),n.div(a),0).cast("float32")})}(t,e)},cosineProximity:function(t,e){return Ue(t,e)},meanAbsoluteError:function(t,e){return Oe(t,e)},meanAbsolutePercentageError:function(t,e){return Te(t,e)},MAPE:function(t,e){return Te(t,e)},mape:function(t,e){return Te(t,e)},meanSquaredError:function(t,e){return Ne(t,e)},MSE:function(t,e){return Ne(t,e)},mse:function(t,e){return Ne(t,e)}}),Pi=Object.freeze({modelFromJSON:function(t,e){return u(this,void 0,void 0,function(){var n,i,a,o,s,u,l,f;return c(this,function(c){switch(c.label){case 0:return"modelTopology"in t||(t={modelTopology:t}),null!=(n=(t=t).modelTopology).model_config&&(n=n.model_config),i=ln(n),a=un(i,e),null==t.weightsManifest?[3,2]:[4,r.io.loadWeights(t.weightsManifest,t.pathPrefix,a.weights.map(function(t){return t.originalName}))];case 1:for(o=c.sent(),s={},u=0,l=a.weights;ue}var Vi=function(t){function e(e){var n=t.call(this)||this;if(null==e&&(e={}),e.restoreBestWeights)throw new p("restoreBestWeights = True is not implemented in EarlyStopping yet.");return n.monitor=e.monitor||"val_loss",n.minDelta=Math.abs(e.minDelta||0),n.patience=e.patience||0,n.verbose=e.verbose||0,n.mode=e.mode||"auto",n.baseline=e.baseline,-1===["auto","min","max"].indexOf(n.mode)&&(console.warn("EarlyStopping mode '"+n.mode+"' is invalid. Falling back to mode 'auto'."),n.mode="auto"),"min"===n.mode?n.monitorFunc=Bi:"max"===n.mode?n.monitorFunc=Ui:-1!==n.monitor.indexOf("acc")?n.monitorFunc=Ui:n.monitorFunc=Bi,n.monitorFunc===Bi&&(n.minDelta*=-1),n}return a(e,t),e.prototype.onTrainBegin=function(t){return u(this,void 0,void 0,function(){return c(this,function(t){return this.wait=0,this.stoppedEpoch=0,null!=this.baseline?this.best=this.baseline:this.best=this.monitorFunc===Bi?1/0:-1/0,[2]})})},e.prototype.onEpochEnd=function(t,e){return u(this,void 0,void 0,function(){var n;return c(this,function(r){switch(r.label){case 0:return[4,ve(e)];case 1:return r.sent(),null==(n=this.getMonitorValue(e))?[2]:(this.monitorFunc(n-this.minDelta,this.best)?(this.best=n,this.wait=0):(this.wait++,this.wait>=this.patience&&(this.stoppedEpoch=t,this.model.stopTraining=!0)),[2])}})})},e.prototype.onTrainEnd=function(t){return u(this,void 0,void 0,function(){return c(this,function(t){return this.stoppedEpoch>0&&this.verbose&&console.log("Epoch "+this.stoppedEpoch+": early stopping."),[2]})})},e.prototype.getMonitorValue=function(t){null==t&&(t={});var e=t[this.monitor];return null==e&&console.warn("Metric for EarlyStopping "+this.monitor+" is not available. Available metrics are: "+Object.keys(t)),e},e}(Fi),Wi={earlyStopping:function(t){return new Vi(t)}},qi=n(138),Hi=n(137);n.d(e,"version",function(){return Gi}),n.d(e,"AdadeltaOptimizer",function(){return r.AdadeltaOptimizer}),n.d(e,"AdagradOptimizer",function(){return r.AdagradOptimizer}),n.d(e,"AdamOptimizer",function(){return r.AdamOptimizer}),n.d(e,"AdamaxOptimizer",function(){return r.AdamaxOptimizer}),n.d(e,"DataStorage",function(){return r.DataStorage}),n.d(e,"ENV",function(){return r.ENV}),n.d(e,"Environment",function(){return r.Environment}),n.d(e,"KernelBackend",function(){return r.KernelBackend}),n.d(e,"MomentumOptimizer",function(){return r.MomentumOptimizer}),n.d(e,"Optimizer",function(){return r.Optimizer}),n.d(e,"RMSPropOptimizer",function(){return r.RMSPropOptimizer}),n.d(e,"Rank",function(){return r.Rank}),n.d(e,"Reduction",function(){return r.Reduction}),n.d(e,"SGDOptimizer",function(){return r.SGDOptimizer}),n.d(e,"Tensor",function(){return r.Tensor}),n.d(e,"TensorBuffer",function(){return r.TensorBuffer}),n.d(e,"Variable",function(){return r.Variable}),n.d(e,"abs",function(){return r.abs}),n.d(e,"acos",function(){return r.acos}),n.d(e,"acosh",function(){return r.acosh}),n.d(e,"add",function(){return r.add}),n.d(e,"addN",function(){return r.addN}),n.d(e,"addStrict",function(){return r.addStrict}),n.d(e,"all",function(){return r.all}),n.d(e,"any",function(){return r.any}),n.d(e,"argMax",function(){return r.argMax}),n.d(e,"argMin",function(){return r.argMin}),n.d(e,"asin",function(){return r.asin}),n.d(e,"asinh",function(){return r.asinh}),n.d(e,"atan",function(){return r.atan}),n.d(e,"atan2",function(){return r.atan2}),n.d(e,"atanh",function(){return r.atanh}),n.d(e,"avgPool",function(){return r.avgPool}),n.d(e,"backend",function(){return r.backend}),n.d(e,"basicLSTMCell",function(){return r.basicLSTMCell}),n.d(e,"batchNorm",function(){return r.batchNorm}),n.d(e,"batchNorm2d",function(){return r.batchNorm2d}),n.d(e,"batchNorm3d",function(){return r.batchNorm3d}),n.d(e,"batchNorm4d",function(){return r.batchNorm4d}),n.d(e,"batchNormalization",function(){return r.batchNormalization}),n.d(e,"batchNormalization2d",function(){return r.batchNormalization2d}),n.d(e,"batchNormalization3d",function(){return r.batchNormalization3d}),n.d(e,"batchNormalization4d",function(){return r.batchNormalization4d}),n.d(e,"batchToSpaceND",function(){return r.batchToSpaceND}),n.d(e,"browser",function(){return r.browser}),n.d(e,"buffer",function(){return r.buffer}),n.d(e,"cast",function(){return r.cast}),n.d(e,"ceil",function(){return r.ceil}),n.d(e,"clipByValue",function(){return r.clipByValue}),n.d(e,"clone",function(){return r.clone}),n.d(e,"complex",function(){return r.complex}),n.d(e,"concat",function(){return r.concat}),n.d(e,"concat1d",function(){return r.concat1d}),n.d(e,"concat2d",function(){return r.concat2d}),n.d(e,"concat3d",function(){return r.concat3d}),n.d(e,"concat4d",function(){return r.concat4d}),n.d(e,"conv1d",function(){return r.conv1d}),n.d(e,"conv2d",function(){return r.conv2d}),n.d(e,"conv2dDerFilter",function(){return r.conv2dDerFilter}),n.d(e,"conv2dTranspose",function(){return r.conv2dTranspose}),n.d(e,"conv3d",function(){return r.conv3d}),n.d(e,"cos",function(){return r.cos}),n.d(e,"cosh",function(){return r.cosh}),n.d(e,"cumsum",function(){return r.cumsum}),n.d(e,"customGrad",function(){return r.customGrad}),n.d(e,"deprecationWarn",function(){return r.deprecationWarn}),n.d(e,"depthToSpace",function(){return r.depthToSpace}),n.d(e,"depthwiseConv2d",function(){return r.depthwiseConv2d}),n.d(e,"disableDeprecationWarnings",function(){return r.disableDeprecationWarnings}),n.d(e,"dispose",function(){return r.dispose}),n.d(e,"disposeVariables",function(){return r.disposeVariables}),n.d(e,"div",function(){return r.div}),n.d(e,"divStrict",function(){return r.divStrict}),n.d(e,"dot",function(){return r.dot}),n.d(e,"dropout",function(){return r.dropout}),n.d(e,"elu",function(){return r.elu}),n.d(e,"enableDebugMode",function(){return r.enableDebugMode}),n.d(e,"enableProdMode",function(){return r.enableProdMode}),n.d(e,"environment",function(){return r.environment}),n.d(e,"equal",function(){return r.equal}),n.d(e,"equalStrict",function(){return r.equalStrict}),n.d(e,"erf",function(){return r.erf}),n.d(e,"exp",function(){return r.exp}),n.d(e,"expandDims",function(){return r.expandDims}),n.d(e,"expm1",function(){return r.expm1}),n.d(e,"eye",function(){return r.eye}),n.d(e,"fft",function(){return r.fft}),n.d(e,"fill",function(){return r.fill}),n.d(e,"findBackend",function(){return r.findBackend}),n.d(e,"findBackendFactory",function(){return r.findBackendFactory}),n.d(e,"floor",function(){return r.floor}),n.d(e,"floorDiv",function(){return r.floorDiv}),n.d(e,"fused",function(){return r.fused}),n.d(e,"gather",function(){return r.gather}),n.d(e,"gatherND",function(){return r.gatherND}),n.d(e,"getBackend",function(){return r.getBackend}),n.d(e,"grad",function(){return r.grad}),n.d(e,"grads",function(){return r.grads}),n.d(e,"greater",function(){return r.greater}),n.d(e,"greaterEqual",function(){return r.greaterEqual}),n.d(e,"greaterEqualStrict",function(){return r.greaterEqualStrict}),n.d(e,"greaterStrict",function(){return r.greaterStrict}),n.d(e,"hammingWindow",function(){return r.hammingWindow}),n.d(e,"hannWindow",function(){return r.hannWindow}),n.d(e,"ifft",function(){return r.ifft}),n.d(e,"imag",function(){return r.imag}),n.d(e,"image",function(){return r.image}),n.d(e,"io",function(){return r.io}),n.d(e,"irfft",function(){return r.irfft}),n.d(e,"isFinite",function(){return r.isFinite}),n.d(e,"isInf",function(){return r.isInf}),n.d(e,"isNaN",function(){return r.isNaN}),n.d(e,"keep",function(){return r.keep}),n.d(e,"leakyRelu",function(){return r.leakyRelu}),n.d(e,"less",function(){return r.less}),n.d(e,"lessEqual",function(){return r.lessEqual}),n.d(e,"lessEqualStrict",function(){return r.lessEqualStrict}),n.d(e,"lessStrict",function(){return r.lessStrict}),n.d(e,"linalg",function(){return r.linalg}),n.d(e,"linspace",function(){return r.linspace}),n.d(e,"localResponseNormalization",function(){return r.localResponseNormalization}),n.d(e,"log",function(){return r.log}),n.d(e,"log1p",function(){return r.log1p}),n.d(e,"logSigmoid",function(){return r.logSigmoid}),n.d(e,"logSoftmax",function(){return r.logSoftmax}),n.d(e,"logSumExp",function(){return r.logSumExp}),n.d(e,"logicalAnd",function(){return r.logicalAnd}),n.d(e,"logicalNot",function(){return r.logicalNot}),n.d(e,"logicalOr",function(){return r.logicalOr}),n.d(e,"logicalXor",function(){return r.logicalXor}),n.d(e,"losses",function(){return r.losses}),n.d(e,"matMul",function(){return r.matMul}),n.d(e,"math",function(){return r.math}),n.d(e,"max",function(){return r.max}),n.d(e,"maxPool",function(){return r.maxPool}),n.d(e,"maximum",function(){return r.maximum}),n.d(e,"maximumStrict",function(){return r.maximumStrict}),n.d(e,"mean",function(){return r.mean}),n.d(e,"memory",function(){return r.memory}),n.d(e,"min",function(){return r.min}),n.d(e,"minimum",function(){return r.minimum}),n.d(e,"minimumStrict",function(){return r.minimumStrict}),n.d(e,"mod",function(){return r.mod}),n.d(e,"modStrict",function(){return r.modStrict}),n.d(e,"moments",function(){return r.moments}),n.d(e,"movingAverage",function(){return r.movingAverage}),n.d(e,"mul",function(){return r.mul}),n.d(e,"mulStrict",function(){return r.mulStrict}),n.d(e,"multiRNNCell",function(){return r.multiRNNCell}),n.d(e,"multinomial",function(){return r.multinomial}),n.d(e,"neg",function(){return r.neg}),n.d(e,"nextFrame",function(){return r.nextFrame}),n.d(e,"norm",function(){return r.norm}),n.d(e,"notEqual",function(){return r.notEqual}),n.d(e,"notEqualStrict",function(){return r.notEqualStrict}),n.d(e,"oneHot",function(){return r.oneHot}),n.d(e,"ones",function(){return r.ones}),n.d(e,"onesLike",function(){return r.onesLike}),n.d(e,"op",function(){return r.op}),n.d(e,"outerProduct",function(){return r.outerProduct}),n.d(e,"pad",function(){return r.pad}),n.d(e,"pad1d",function(){return r.pad1d}),n.d(e,"pad2d",function(){return r.pad2d}),n.d(e,"pad3d",function(){return r.pad3d}),n.d(e,"pad4d",function(){return r.pad4d}),n.d(e,"pool",function(){return r.pool}),n.d(e,"pow",function(){return r.pow}),n.d(e,"powStrict",function(){return r.powStrict}),n.d(e,"prelu",function(){return r.prelu}),n.d(e,"print",function(){return r.print}),n.d(e,"prod",function(){return r.prod}),n.d(e,"profile",function(){return r.profile}),n.d(e,"rand",function(){return r.rand}),n.d(e,"randomNormal",function(){return r.randomNormal}),n.d(e,"randomUniform",function(){return r.randomUniform}),n.d(e,"range",function(){return r.range}),n.d(e,"ready",function(){return r.ready}),n.d(e,"real",function(){return r.real}),n.d(e,"reciprocal",function(){return r.reciprocal}),n.d(e,"registerBackend",function(){return r.registerBackend}),n.d(e,"relu",function(){return r.relu}),n.d(e,"removeBackend",function(){return r.removeBackend}),n.d(e,"reshape",function(){return r.reshape}),n.d(e,"reverse",function(){return r.reverse}),n.d(e,"reverse1d",function(){return r.reverse1d}),n.d(e,"reverse2d",function(){return r.reverse2d}),n.d(e,"reverse3d",function(){return r.reverse3d}),n.d(e,"reverse4d",function(){return r.reverse4d}),n.d(e,"rfft",function(){return r.rfft}),n.d(e,"round",function(){return r.round}),n.d(e,"rsqrt",function(){return r.rsqrt}),n.d(e,"scalar",function(){return r.scalar}),n.d(e,"scatterND",function(){return r.scatterND}),n.d(e,"selu",function(){return r.selu}),n.d(e,"separableConv2d",function(){return r.separableConv2d}),n.d(e,"serialization",function(){return r.serialization}),n.d(e,"setBackend",function(){return r.setBackend}),n.d(e,"setdiff1dAsync",function(){return r.setdiff1dAsync}),n.d(e,"sigmoid",function(){return r.sigmoid}),n.d(e,"sign",function(){return r.sign}),n.d(e,"sin",function(){return r.sin}),n.d(e,"sinh",function(){return r.sinh}),n.d(e,"slice",function(){return r.slice}),n.d(e,"slice1d",function(){return r.slice1d}),n.d(e,"slice2d",function(){return r.slice2d}),n.d(e,"slice3d",function(){return r.slice3d}),n.d(e,"slice4d",function(){return r.slice4d}),n.d(e,"softmax",function(){return r.softmax}),n.d(e,"softplus",function(){return r.softplus}),n.d(e,"spaceToBatchND",function(){return r.spaceToBatchND}),n.d(e,"sparseToDense",function(){return r.sparseToDense}),n.d(e,"spectral",function(){return r.spectral}),n.d(e,"split",function(){return r.split}),n.d(e,"sqrt",function(){return r.sqrt}),n.d(e,"square",function(){return r.square}),n.d(e,"squaredDifference",function(){return r.squaredDifference}),n.d(e,"squaredDifferenceStrict",function(){return r.squaredDifferenceStrict}),n.d(e,"squeeze",function(){return r.squeeze}),n.d(e,"stack",function(){return r.stack}),n.d(e,"step",function(){return r.step}),n.d(e,"stridedSlice",function(){return r.stridedSlice}),n.d(e,"sub",function(){return r.sub}),n.d(e,"subStrict",function(){return r.subStrict}),n.d(e,"sum",function(){return r.sum}),n.d(e,"tan",function(){return r.tan}),n.d(e,"tanh",function(){return r.tanh}),n.d(e,"tensor",function(){return r.tensor}),n.d(e,"tensor1d",function(){return r.tensor1d}),n.d(e,"tensor2d",function(){return r.tensor2d}),n.d(e,"tensor3d",function(){return r.tensor3d}),n.d(e,"tensor4d",function(){return r.tensor4d}),n.d(e,"tensor5d",function(){return r.tensor5d}),n.d(e,"tensor6d",function(){return r.tensor6d}),n.d(e,"tensor_util",function(){return r.tensor_util}),n.d(e,"test_util",function(){return r.test_util}),n.d(e,"tidy",function(){return r.tidy}),n.d(e,"tile",function(){return r.tile}),n.d(e,"time",function(){return r.time}),n.d(e,"topk",function(){return r.topk}),n.d(e,"train",function(){return r.train}),n.d(e,"transpose",function(){return r.transpose}),n.d(e,"truncatedNormal",function(){return r.truncatedNormal}),n.d(e,"unsortedSegmentSum",function(){return r.unsortedSegmentSum}),n.d(e,"unstack",function(){return r.unstack}),n.d(e,"util",function(){return r.util}),n.d(e,"valueAndGrad",function(){return r.valueAndGrad}),n.d(e,"valueAndGrads",function(){return r.valueAndGrads}),n.d(e,"variable",function(){return r.variable}),n.d(e,"variableGrads",function(){return r.variableGrads}),n.d(e,"version_core",function(){return r.version_core}),n.d(e,"webgl",function(){return r.webgl}),n.d(e,"where",function(){return r.where}),n.d(e,"whereAsync",function(){return r.whereAsync}),n.d(e,"zeros",function(){return r.zeros}),n.d(e,"zerosLike",function(){return r.zerosLike}),n.d(e,"constraints",function(){return V}),n.d(e,"initializers",function(){return Kt}),n.d(e,"layers",function(){return ji}),n.d(e,"metrics",function(){return zi}),n.d(e,"models",function(){return Pi}),n.d(e,"regularizers",function(){return Li}),n.d(e,"CallbackList",function(){return we}),n.d(e,"CustomCallback",function(){return Se}),n.d(e,"History",function(){return ke}),n.d(e,"Callback",function(){return Fi}),n.d(e,"callbacks",function(){return Wi}),n.d(e,"EarlyStopping",function(){return Vi}),n.d(e,"InputSpec",function(){return ue}),n.d(e,"SymbolicTensor",function(){return ce}),n.d(e,"LayersModel",function(){return Mn}),n.d(e,"input",function(){return Pn}),n.d(e,"loadLayersModel",function(){return zn}),n.d(e,"model",function(){return Dn}),n.d(e,"registerCallbackConstructor",function(){return Ln}),n.d(e,"sequential",function(){return jn}),n.d(e,"RNN",function(){return ui}),n.d(e,"Sequential",function(){return Rn}),n.d(e,"LayerVariable",function(){return ie}),n.d(e,"version_layers",function(){return"1.1.2"}),n.d(e,"GraphModel",function(){return qi.a}),n.d(e,"loadGraphModel",function(){return qi.b}),n.d(e,"version_converter",function(){return qi.c}),n.d(e,"data",function(){return Hi});var Gi={"tfjs-core":r.version_core,"tfjs-data":Hi.version_data,"tfjs-layers":"1.1.2","tfjs-converter":qi.c,tfjs:"1.1.2"}},function(t,e,n){var r=n(6),i=n(43),a=n(30),o=n(29),s=n(42),u=function(t,e,n){var c,l,f,h,d=t&u.F,p=t&u.G,m=t&u.S,v=t&u.P,g=t&u.B,b=p?r:m?r[e]||(r[e]={}):(r[e]||{}).prototype,y=p?i:i[e]||(i[e]={}),w=y.prototype||(y.prototype={});for(c in p&&(n=e),n)f=((l=!d&&b&&void 0!==b[c])?b:n)[c],h=g&&l?s(f,r):v&&"function"==typeof f?s(Function.call,f):f,b&&o(b,c,f,t&u.U),y[c]!=f&&a(y,c,h),v&&w[c]!=f&&(w[c]=f)};r.core=i,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,t.exports=u},function(t,e,n){var r=n(8);t.exports=function(t){if(!r(t))throw TypeError(t+" is not an object!");return t}},function(t,e){"function"==typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}},function(t,e,n){var r=n(16),i=r.Buffer;function a(t,e){for(var n in t)e[n]=t[n]}function o(t,e,n){return i(t,e,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?t.exports=r:(a(r,e),e.Buffer=o),a(i,o),o.from=function(t,e,n){if("number"==typeof t)throw new TypeError("Argument must not be a number");return i(t,e,n)},o.alloc=function(t,e,n){if("number"!=typeof t)throw new TypeError("Argument must be a number");var r=i(t);return void 0!==e?"string"==typeof n?r.fill(e,n):r.fill(e):r.fill(0),r},o.allocUnsafe=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return i(t)},o.allocUnsafeSlow=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return r.SlowBuffer(t)}},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,n){"use strict";e.__esModule=!0;var r=function(t){return t&&t.__esModule?t:{default:t}}(n(44));e.default=function(t){return function(){var e=t.apply(this,arguments);return new r.default(function(t,n){return function i(a,o){try{var s=e[a](o),u=s.value}catch(t){return void n(t)}if(!s.done)return r.default.resolve(u).then(function(t){i("next",t)},function(t){i("throw",t)});t(u)}("next")})}}},function(t,e,n){t.exports=n(400)},function(t,e,n){var r=n(136)("wks"),i=n(75),a=n(6).Symbol,o="function"==typeof a;(t.exports=function(t){return r[t]||(r[t]=o&&a[t]||(o?a:i)("Symbol."+t))}).store=r},function(t,e,n){var r=n(40),i=Math.min;t.exports=function(t){return t>0?i(r(t),9007199254740991):0}},function(t,e,n){"use strict";e.__esModule=!0;var r=function(t){return t&&t.__esModule?t:{default:t}}(n(386));e.default=function(){function t(t,e){for(var n=0;n - * @license MIT - */ -var r=n(489),i=n(488),a=n(256);function o(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(t,e){if(o()=o())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o().toString(16)+" bytes");return 0|t}function p(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var r=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return B(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(t).length;default:if(r)return B(t).length;e=(""+e).toLowerCase(),r=!0}}function m(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function v(t,e,n,r,i){if(0===t.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=i?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(i)return-1;n=t.length-1}else if(n<0){if(!i)return-1;n=0}if("string"==typeof e&&(e=u.from(e,r)),u.isBuffer(e))return 0===e.length?-1:g(t,e,n,r,i);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):g(t,[e],n,r,i);throw new TypeError("val must be string, number or Buffer")}function g(t,e,n,r,i){var a,o=1,s=t.length,u=e.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(t.length<2||e.length<2)return-1;o=2,s/=2,u/=2,n/=2}function c(t,e){return 1===o?t[e]:t.readUInt16BE(e*o)}if(i){var l=-1;for(a=n;as&&(n=s-u),a=n;a>=0;a--){for(var f=!0,h=0;hi&&(r=i):r=i;var a=e.length;if(a%2!=0)throw new TypeError("Invalid hex string");r>a/2&&(r=a/2);for(var o=0;o>8,i=n%256,a.push(i),a.push(r);return a}(e,t.length-n),t,n,r)}function _(t,e,n){return 0===e&&n===t.length?r.fromByteArray(t):r.fromByteArray(t.slice(e,n))}function E(t,e,n){n=Math.min(t.length,n);for(var r=[],i=e;i239?4:c>223?3:c>191?2:1;if(i+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(a=t[i+1]))&&(u=(31&c)<<6|63&a)>127&&(l=u);break;case 3:a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&(u=(15&c)<<12|(63&a)<<6|63&o)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&(u=(15&c)<<18|(63&a)<<12|(63&o)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),i+=f}return function(t){var e=t.length;if(e<=C)return String.fromCharCode.apply(String,t);for(var n="",r=0;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return O(this,e,n);case"utf8":case"utf-8":return E(this,e,n);case"ascii":return A(this,e,n);case"latin1":case"binary":return N(this,e,n);case"base64":return _(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return T(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(t){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===u.compare(this,t)},u.prototype.inspect=function(){var t="",n=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(t+=" ... ")),""},u.prototype.compare=function(t,e,n,r,i){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),e<0||n>t.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&e>=n)return 0;if(r>=i)return-1;if(e>=n)return 1;if(e>>>=0,n>>>=0,r>>>=0,i>>>=0,this===t)return 0;for(var a=i-r,o=n-e,s=Math.min(a,o),c=this.slice(r,i),l=t.slice(e,n),f=0;fi)&&(n=i),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var a=!1;;)switch(r){case"hex":return b(this,t,e,n);case"utf8":case"utf-8":return y(this,t,e,n);case"ascii":return w(this,t,e,n);case"latin1":case"binary":return x(this,t,e,n);case"base64":return k(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,t,e,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var C=4096;function A(t,e,n){var r="";n=Math.min(t.length,n);for(var i=e;ir)&&(n=r);for(var i="",a=e;an)throw new RangeError("Trying to access beyond buffer length")}function M(t,e,n,r,i,a){if(!u.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||et.length)throw new RangeError("Index out of range")}function R(t,e,n,r){e<0&&(e=65535+e+1);for(var i=0,a=Math.min(t.length-n,2);i>>8*(r?i:1-i)}function D(t,e,n,r){e<0&&(e=4294967295+e+1);for(var i=0,a=Math.min(t.length-n,4);i>>8*(r?i:3-i)&255}function j(t,e,n,r,i,a){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function z(t,e,n,r,a){return a||j(t,0,n,4),i.write(t,e,n,r,23,4),n+4}function P(t,e,n,r,a){return a||j(t,0,n,8),i.write(t,e,n,r,52,8),n+8}u.prototype.slice=function(t,e){var n,r=this.length;if(t=~~t,e=void 0===e?r:~~e,t<0?(t+=r)<0&&(t=0):t>r&&(t=r),e<0?(e+=r)<0&&(e=0):e>r&&(e=r),e0&&(i*=256);)r+=this[t+--e]*i;return r},u.prototype.readUInt8=function(t,e){return e||I(t,1,this.length),this[t]},u.prototype.readUInt16LE=function(t,e){return e||I(t,2,this.length),this[t]|this[t+1]<<8},u.prototype.readUInt16BE=function(t,e){return e||I(t,2,this.length),this[t]<<8|this[t+1]},u.prototype.readUInt32LE=function(t,e){return e||I(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},u.prototype.readUInt32BE=function(t,e){return e||I(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},u.prototype.readIntLE=function(t,e,n){t|=0,e|=0,n||I(t,e,this.length);for(var r=this[t],i=1,a=0;++a=(i*=128)&&(r-=Math.pow(2,8*e)),r},u.prototype.readIntBE=function(t,e,n){t|=0,e|=0,n||I(t,e,this.length);for(var r=e,i=1,a=this[t+--r];r>0&&(i*=256);)a+=this[t+--r]*i;return a>=(i*=128)&&(a-=Math.pow(2,8*e)),a},u.prototype.readInt8=function(t,e){return e||I(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},u.prototype.readInt16LE=function(t,e){e||I(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(t,e){e||I(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(t,e){return e||I(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},u.prototype.readInt32BE=function(t,e){return e||I(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},u.prototype.readFloatLE=function(t,e){return e||I(t,4,this.length),i.read(this,t,!0,23,4)},u.prototype.readFloatBE=function(t,e){return e||I(t,4,this.length),i.read(this,t,!1,23,4)},u.prototype.readDoubleLE=function(t,e){return e||I(t,8,this.length),i.read(this,t,!0,52,8)},u.prototype.readDoubleBE=function(t,e){return e||I(t,8,this.length),i.read(this,t,!1,52,8)},u.prototype.writeUIntLE=function(t,e,n,r){t=+t,e|=0,n|=0,r||M(this,t,e,n,Math.pow(2,8*n)-1,0);var i=1,a=0;for(this[e]=255&t;++a=0&&(a*=256);)this[e+i]=t/a&255;return e+n},u.prototype.writeUInt8=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,1,255,0),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},u.prototype.writeUInt16LE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):R(this,t,e,!0),e+2},u.prototype.writeUInt16BE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):R(this,t,e,!1),e+2},u.prototype.writeUInt32LE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):D(this,t,e,!0),e+4},u.prototype.writeUInt32BE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):D(this,t,e,!1),e+4},u.prototype.writeIntLE=function(t,e,n,r){if(t=+t,e|=0,!r){var i=Math.pow(2,8*n-1);M(this,t,e,n,i-1,-i)}var a=0,o=1,s=0;for(this[e]=255&t;++a>0)-s&255;return e+n},u.prototype.writeIntBE=function(t,e,n,r){if(t=+t,e|=0,!r){var i=Math.pow(2,8*n-1);M(this,t,e,n,i-1,-i)}var a=n-1,o=1,s=0;for(this[e+a]=255&t;--a>=0&&(o*=256);)t<0&&0===s&&0!==this[e+a+1]&&(s=1),this[e+a]=(t/o>>0)-s&255;return e+n},u.prototype.writeInt8=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,1,127,-128),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},u.prototype.writeInt16LE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):R(this,t,e,!0),e+2},u.prototype.writeInt16BE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):R(this,t,e,!1),e+2},u.prototype.writeInt32LE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):D(this,t,e,!0),e+4},u.prototype.writeInt32BE=function(t,e,n){return t=+t,e|=0,n||M(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):D(this,t,e,!1),e+4},u.prototype.writeFloatLE=function(t,e,n){return z(this,t,e,!0,n)},u.prototype.writeFloatBE=function(t,e,n){return z(this,t,e,!1,n)},u.prototype.writeDoubleLE=function(t,e,n){return P(this,t,e,!0,n)},u.prototype.writeDoubleBE=function(t,e,n){return P(this,t,e,!1,n)},u.prototype.copy=function(t,e,n,r){if(n||(n=0),r||0===r||(r=this.length),e>=t.length&&(e=t.length),e||(e=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),t.length-e=0;--i)t[i+e]=this[i+n];else if(a<1e3||!u.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,t||(t=0),"number"==typeof t)for(a=e;a55295&&n<57344){if(!i){if(n>56319){(e-=3)>-1&&a.push(239,191,189);continue}if(o+1===r){(e-=3)>-1&&a.push(239,191,189);continue}i=n;continue}if(n<56320){(e-=3)>-1&&a.push(239,191,189),i=n;continue}n=65536+(i-55296<<10|n-56320)}else i&&(e-=3)>-1&&a.push(239,191,189);if(i=null,n<128){if((e-=1)<0)break;a.push(n)}else if(n<2048){if((e-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;a.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return a}function U(t){return r.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(L,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function V(t,e,n,r){for(var i=0;i=e.length||i>=t.length);++i)e[i+n]=t[i];return i}}).call(this,n(31))},function(t,e,n){var r=n(3),i=n(294),a=n(52),o=Object.defineProperty;e.f=n(18)?Object.defineProperty:function(t,e,n){if(r(t),e=a(e,!0),r(n),i)try{return o(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){t.exports=!n(7)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e,n){(function(t){!function(t,e){"use strict";function r(t,e){if(!t)throw new Error(e||"Assertion failed")}function i(t,e){t.super_=e;var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}function a(t,e,n){if(a.isBN(t))return t;this.negative=0,this.words=null,this.length=0,this.red=null,null!==t&&("le"!==e&&"be"!==e||(n=e,e=10),this._init(t||0,e||10,n||"be"))}var o;"object"==typeof t?t.exports=a:e.BN=a,a.BN=a,a.wordSize=26;try{o=n(450).Buffer}catch(t){}function s(t,e,n){for(var r=0,i=Math.min(t.length,n),a=e;a=49&&o<=54?o-49+10:o>=17&&o<=22?o-17+10:15&o}return r}function u(t,e,n,r){for(var i=0,a=Math.min(t.length,n),o=e;o=49?s-49+10:s>=17?s-17+10:s}return i}a.isBN=function(t){return t instanceof a||null!==t&&"object"==typeof t&&t.constructor.wordSize===a.wordSize&&Array.isArray(t.words)},a.max=function(t,e){return t.cmp(e)>0?t:e},a.min=function(t,e){return t.cmp(e)<0?t:e},a.prototype._init=function(t,e,n){if("number"==typeof t)return this._initNumber(t,e,n);if("object"==typeof t)return this._initArray(t,e,n);"hex"===e&&(e=16),r(e===(0|e)&&e>=2&&e<=36);var i=0;"-"===(t=t.toString().replace(/\s+/g,""))[0]&&i++,16===e?this._parseHex(t,i):this._parseBase(t,e,i),"-"===t[0]&&(this.negative=1),this.strip(),"le"===n&&this._initArray(this.toArray(),e,n)},a.prototype._initNumber=function(t,e,n){t<0&&(this.negative=1,t=-t),t<67108864?(this.words=[67108863&t],this.length=1):t<4503599627370496?(this.words=[67108863&t,t/67108864&67108863],this.length=2):(r(t<9007199254740992),this.words=[67108863&t,t/67108864&67108863,1],this.length=3),"le"===n&&this._initArray(this.toArray(),e,n)},a.prototype._initArray=function(t,e,n){if(r("number"==typeof t.length),t.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(t.length/3),this.words=new Array(this.length);for(var i=0;i=0;i-=3)o=t[i]|t[i-1]<<8|t[i-2]<<16,this.words[a]|=o<>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);else if("le"===n)for(i=0,a=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);return this.strip()},a.prototype._parseHex=function(t,e){this.length=Math.ceil((t.length-e)/6),this.words=new Array(this.length);for(var n=0;n=e;n-=6)i=s(t,n,n+6),this.words[r]|=i<>>26-a&4194303,(a+=24)>=26&&(a-=26,r++);n+6!==e&&(i=s(t,e,n+6),this.words[r]|=i<>>26-a&4194303),this.strip()},a.prototype._parseBase=function(t,e,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=e)r++;r--,i=i/e|0;for(var a=t.length-n,o=a%r,s=Math.min(a,a-o)+n,c=0,l=n;l1&&0===this.words[this.length-1];)this.length--;return this._normSign()},a.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},a.prototype.inspect=function(){return(this.red?""};var c=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],l=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],f=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function h(t,e,n){n.negative=e.negative^t.negative;var r=t.length+e.length|0;n.length=r,r=r-1|0;var i=0|t.words[0],a=0|e.words[0],o=i*a,s=67108863&o,u=o/67108864|0;n.words[0]=s;for(var c=1;c>>26,f=67108863&u,h=Math.min(c,e.length-1),d=Math.max(0,c-t.length+1);d<=h;d++){var p=c-d|0;l+=(o=(i=0|t.words[p])*(a=0|e.words[d])+f)/67108864|0,f=67108863&o}n.words[c]=0|f,u=0|l}return 0!==u?n.words[c]=0|u:n.length--,n.strip()}a.prototype.toString=function(t,e){var n;if(t=t||10,e=0|e||1,16===t||"hex"===t){n="";for(var i=0,a=0,o=0;o>>24-i&16777215)||o!==this.length-1?c[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,o--)}for(0!==a&&(n=a.toString(16)+n);n.length%e!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(t===(0|t)&&t>=2&&t<=36){var h=l[t],d=f[t];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var m=p.modn(d).toString(t);n=(p=p.idivn(d)).isZero()?m+n:c[h-m.length]+m+n}for(this.isZero()&&(n="0"+n);n.length%e!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},a.prototype.toNumber=function(){var t=this.words[0];return 2===this.length?t+=67108864*this.words[1]:3===this.length&&1===this.words[2]?t+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-t:t},a.prototype.toJSON=function(){return this.toString(16)},a.prototype.toBuffer=function(t,e){return r(void 0!==o),this.toArrayLike(o,t,e)},a.prototype.toArray=function(t,e){return this.toArrayLike(Array,t,e)},a.prototype.toArrayLike=function(t,e,n){var i=this.byteLength(),a=n||Math.max(1,i);r(i<=a,"byte array longer than desired length"),r(a>0,"Requested array length <= 0"),this.strip();var o,s,u="le"===e,c=new t(a),l=this.clone();if(u){for(s=0;!l.isZero();s++)o=l.andln(255),l.iushrn(8),c[s]=o;for(;s=4096&&(n+=13,e>>>=13),e>=64&&(n+=7,e>>>=7),e>=8&&(n+=4,e>>>=4),e>=2&&(n+=2,e>>>=2),n+e},a.prototype._zeroBits=function(t){if(0===t)return 26;var e=t,n=0;return 0==(8191&e)&&(n+=13,e>>>=13),0==(127&e)&&(n+=7,e>>>=7),0==(15&e)&&(n+=4,e>>>=4),0==(3&e)&&(n+=2,e>>>=2),0==(1&e)&&n++,n},a.prototype.bitLength=function(){var t=this.words[this.length-1],e=this._countBits(t);return 26*(this.length-1)+e},a.prototype.zeroBits=function(){if(this.isZero())return 0;for(var t=0,e=0;et.length?this.clone().ior(t):t.clone().ior(this)},a.prototype.uor=function(t){return this.length>t.length?this.clone().iuor(t):t.clone().iuor(this)},a.prototype.iuand=function(t){var e;e=this.length>t.length?t:this;for(var n=0;nt.length?this.clone().iand(t):t.clone().iand(this)},a.prototype.uand=function(t){return this.length>t.length?this.clone().iuand(t):t.clone().iuand(this)},a.prototype.iuxor=function(t){var e,n;this.length>t.length?(e=this,n=t):(e=t,n=this);for(var r=0;rt.length?this.clone().ixor(t):t.clone().ixor(this)},a.prototype.uxor=function(t){return this.length>t.length?this.clone().iuxor(t):t.clone().iuxor(this)},a.prototype.inotn=function(t){r("number"==typeof t&&t>=0);var e=0|Math.ceil(t/26),n=t%26;this._expand(e),n>0&&e--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-n),this.strip()},a.prototype.notn=function(t){return this.clone().inotn(t)},a.prototype.setn=function(t,e){r("number"==typeof t&&t>=0);var n=t/26|0,i=t%26;return this._expand(n+1),this.words[n]=e?this.words[n]|1<t.length?(n=this,r=t):(n=t,r=this);for(var i=0,a=0;a>>26;for(;0!==i&&a>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;at.length?this.clone().iadd(t):t.clone().iadd(this)},a.prototype.isub=function(t){if(0!==t.negative){t.negative=0;var e=this.iadd(t);return t.negative=1,e._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(t),this.negative=1,this._normSign();var n,r,i=this.cmp(t);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=t):(n=t,r=this);for(var a=0,o=0;o>26,this.words[o]=67108863&e;for(;0!==a&&o>26,this.words[o]=67108863&e;if(0===a&&o>>13,d=0|o[1],p=8191&d,m=d>>>13,v=0|o[2],g=8191&v,b=v>>>13,y=0|o[3],w=8191&y,x=y>>>13,k=0|o[4],S=8191&k,_=k>>>13,E=0|o[5],C=8191&E,A=E>>>13,N=0|o[6],O=8191&N,T=N>>>13,I=0|o[7],M=8191&I,R=I>>>13,D=0|o[8],j=8191&D,z=D>>>13,P=0|o[9],L=8191&P,F=P>>>13,B=0|s[0],U=8191&B,V=B>>>13,W=0|s[1],q=8191&W,H=W>>>13,G=0|s[2],K=8191&G,X=G>>>13,$=0|s[3],Y=8191&$,J=$>>>13,Z=0|s[4],Q=8191&Z,tt=Z>>>13,et=0|s[5],nt=8191&et,rt=et>>>13,it=0|s[6],at=8191&it,ot=it>>>13,st=0|s[7],ut=8191&st,ct=st>>>13,lt=0|s[8],ft=8191<,ht=lt>>>13,dt=0|s[9],pt=8191&dt,mt=dt>>>13;n.negative=t.negative^e.negative,n.length=19;var vt=(c+(r=Math.imul(f,U))|0)+((8191&(i=(i=Math.imul(f,V))+Math.imul(h,U)|0))<<13)|0;c=((a=Math.imul(h,V))+(i>>>13)|0)+(vt>>>26)|0,vt&=67108863,r=Math.imul(p,U),i=(i=Math.imul(p,V))+Math.imul(m,U)|0,a=Math.imul(m,V);var gt=(c+(r=r+Math.imul(f,q)|0)|0)+((8191&(i=(i=i+Math.imul(f,H)|0)+Math.imul(h,q)|0))<<13)|0;c=((a=a+Math.imul(h,H)|0)+(i>>>13)|0)+(gt>>>26)|0,gt&=67108863,r=Math.imul(g,U),i=(i=Math.imul(g,V))+Math.imul(b,U)|0,a=Math.imul(b,V),r=r+Math.imul(p,q)|0,i=(i=i+Math.imul(p,H)|0)+Math.imul(m,q)|0,a=a+Math.imul(m,H)|0;var bt=(c+(r=r+Math.imul(f,K)|0)|0)+((8191&(i=(i=i+Math.imul(f,X)|0)+Math.imul(h,K)|0))<<13)|0;c=((a=a+Math.imul(h,X)|0)+(i>>>13)|0)+(bt>>>26)|0,bt&=67108863,r=Math.imul(w,U),i=(i=Math.imul(w,V))+Math.imul(x,U)|0,a=Math.imul(x,V),r=r+Math.imul(g,q)|0,i=(i=i+Math.imul(g,H)|0)+Math.imul(b,q)|0,a=a+Math.imul(b,H)|0,r=r+Math.imul(p,K)|0,i=(i=i+Math.imul(p,X)|0)+Math.imul(m,K)|0,a=a+Math.imul(m,X)|0;var yt=(c+(r=r+Math.imul(f,Y)|0)|0)+((8191&(i=(i=i+Math.imul(f,J)|0)+Math.imul(h,Y)|0))<<13)|0;c=((a=a+Math.imul(h,J)|0)+(i>>>13)|0)+(yt>>>26)|0,yt&=67108863,r=Math.imul(S,U),i=(i=Math.imul(S,V))+Math.imul(_,U)|0,a=Math.imul(_,V),r=r+Math.imul(w,q)|0,i=(i=i+Math.imul(w,H)|0)+Math.imul(x,q)|0,a=a+Math.imul(x,H)|0,r=r+Math.imul(g,K)|0,i=(i=i+Math.imul(g,X)|0)+Math.imul(b,K)|0,a=a+Math.imul(b,X)|0,r=r+Math.imul(p,Y)|0,i=(i=i+Math.imul(p,J)|0)+Math.imul(m,Y)|0,a=a+Math.imul(m,J)|0;var wt=(c+(r=r+Math.imul(f,Q)|0)|0)+((8191&(i=(i=i+Math.imul(f,tt)|0)+Math.imul(h,Q)|0))<<13)|0;c=((a=a+Math.imul(h,tt)|0)+(i>>>13)|0)+(wt>>>26)|0,wt&=67108863,r=Math.imul(C,U),i=(i=Math.imul(C,V))+Math.imul(A,U)|0,a=Math.imul(A,V),r=r+Math.imul(S,q)|0,i=(i=i+Math.imul(S,H)|0)+Math.imul(_,q)|0,a=a+Math.imul(_,H)|0,r=r+Math.imul(w,K)|0,i=(i=i+Math.imul(w,X)|0)+Math.imul(x,K)|0,a=a+Math.imul(x,X)|0,r=r+Math.imul(g,Y)|0,i=(i=i+Math.imul(g,J)|0)+Math.imul(b,Y)|0,a=a+Math.imul(b,J)|0,r=r+Math.imul(p,Q)|0,i=(i=i+Math.imul(p,tt)|0)+Math.imul(m,Q)|0,a=a+Math.imul(m,tt)|0;var xt=(c+(r=r+Math.imul(f,nt)|0)|0)+((8191&(i=(i=i+Math.imul(f,rt)|0)+Math.imul(h,nt)|0))<<13)|0;c=((a=a+Math.imul(h,rt)|0)+(i>>>13)|0)+(xt>>>26)|0,xt&=67108863,r=Math.imul(O,U),i=(i=Math.imul(O,V))+Math.imul(T,U)|0,a=Math.imul(T,V),r=r+Math.imul(C,q)|0,i=(i=i+Math.imul(C,H)|0)+Math.imul(A,q)|0,a=a+Math.imul(A,H)|0,r=r+Math.imul(S,K)|0,i=(i=i+Math.imul(S,X)|0)+Math.imul(_,K)|0,a=a+Math.imul(_,X)|0,r=r+Math.imul(w,Y)|0,i=(i=i+Math.imul(w,J)|0)+Math.imul(x,Y)|0,a=a+Math.imul(x,J)|0,r=r+Math.imul(g,Q)|0,i=(i=i+Math.imul(g,tt)|0)+Math.imul(b,Q)|0,a=a+Math.imul(b,tt)|0,r=r+Math.imul(p,nt)|0,i=(i=i+Math.imul(p,rt)|0)+Math.imul(m,nt)|0,a=a+Math.imul(m,rt)|0;var kt=(c+(r=r+Math.imul(f,at)|0)|0)+((8191&(i=(i=i+Math.imul(f,ot)|0)+Math.imul(h,at)|0))<<13)|0;c=((a=a+Math.imul(h,ot)|0)+(i>>>13)|0)+(kt>>>26)|0,kt&=67108863,r=Math.imul(M,U),i=(i=Math.imul(M,V))+Math.imul(R,U)|0,a=Math.imul(R,V),r=r+Math.imul(O,q)|0,i=(i=i+Math.imul(O,H)|0)+Math.imul(T,q)|0,a=a+Math.imul(T,H)|0,r=r+Math.imul(C,K)|0,i=(i=i+Math.imul(C,X)|0)+Math.imul(A,K)|0,a=a+Math.imul(A,X)|0,r=r+Math.imul(S,Y)|0,i=(i=i+Math.imul(S,J)|0)+Math.imul(_,Y)|0,a=a+Math.imul(_,J)|0,r=r+Math.imul(w,Q)|0,i=(i=i+Math.imul(w,tt)|0)+Math.imul(x,Q)|0,a=a+Math.imul(x,tt)|0,r=r+Math.imul(g,nt)|0,i=(i=i+Math.imul(g,rt)|0)+Math.imul(b,nt)|0,a=a+Math.imul(b,rt)|0,r=r+Math.imul(p,at)|0,i=(i=i+Math.imul(p,ot)|0)+Math.imul(m,at)|0,a=a+Math.imul(m,ot)|0;var St=(c+(r=r+Math.imul(f,ut)|0)|0)+((8191&(i=(i=i+Math.imul(f,ct)|0)+Math.imul(h,ut)|0))<<13)|0;c=((a=a+Math.imul(h,ct)|0)+(i>>>13)|0)+(St>>>26)|0,St&=67108863,r=Math.imul(j,U),i=(i=Math.imul(j,V))+Math.imul(z,U)|0,a=Math.imul(z,V),r=r+Math.imul(M,q)|0,i=(i=i+Math.imul(M,H)|0)+Math.imul(R,q)|0,a=a+Math.imul(R,H)|0,r=r+Math.imul(O,K)|0,i=(i=i+Math.imul(O,X)|0)+Math.imul(T,K)|0,a=a+Math.imul(T,X)|0,r=r+Math.imul(C,Y)|0,i=(i=i+Math.imul(C,J)|0)+Math.imul(A,Y)|0,a=a+Math.imul(A,J)|0,r=r+Math.imul(S,Q)|0,i=(i=i+Math.imul(S,tt)|0)+Math.imul(_,Q)|0,a=a+Math.imul(_,tt)|0,r=r+Math.imul(w,nt)|0,i=(i=i+Math.imul(w,rt)|0)+Math.imul(x,nt)|0,a=a+Math.imul(x,rt)|0,r=r+Math.imul(g,at)|0,i=(i=i+Math.imul(g,ot)|0)+Math.imul(b,at)|0,a=a+Math.imul(b,ot)|0,r=r+Math.imul(p,ut)|0,i=(i=i+Math.imul(p,ct)|0)+Math.imul(m,ut)|0,a=a+Math.imul(m,ct)|0;var _t=(c+(r=r+Math.imul(f,ft)|0)|0)+((8191&(i=(i=i+Math.imul(f,ht)|0)+Math.imul(h,ft)|0))<<13)|0;c=((a=a+Math.imul(h,ht)|0)+(i>>>13)|0)+(_t>>>26)|0,_t&=67108863,r=Math.imul(L,U),i=(i=Math.imul(L,V))+Math.imul(F,U)|0,a=Math.imul(F,V),r=r+Math.imul(j,q)|0,i=(i=i+Math.imul(j,H)|0)+Math.imul(z,q)|0,a=a+Math.imul(z,H)|0,r=r+Math.imul(M,K)|0,i=(i=i+Math.imul(M,X)|0)+Math.imul(R,K)|0,a=a+Math.imul(R,X)|0,r=r+Math.imul(O,Y)|0,i=(i=i+Math.imul(O,J)|0)+Math.imul(T,Y)|0,a=a+Math.imul(T,J)|0,r=r+Math.imul(C,Q)|0,i=(i=i+Math.imul(C,tt)|0)+Math.imul(A,Q)|0,a=a+Math.imul(A,tt)|0,r=r+Math.imul(S,nt)|0,i=(i=i+Math.imul(S,rt)|0)+Math.imul(_,nt)|0,a=a+Math.imul(_,rt)|0,r=r+Math.imul(w,at)|0,i=(i=i+Math.imul(w,ot)|0)+Math.imul(x,at)|0,a=a+Math.imul(x,ot)|0,r=r+Math.imul(g,ut)|0,i=(i=i+Math.imul(g,ct)|0)+Math.imul(b,ut)|0,a=a+Math.imul(b,ct)|0,r=r+Math.imul(p,ft)|0,i=(i=i+Math.imul(p,ht)|0)+Math.imul(m,ft)|0,a=a+Math.imul(m,ht)|0;var Et=(c+(r=r+Math.imul(f,pt)|0)|0)+((8191&(i=(i=i+Math.imul(f,mt)|0)+Math.imul(h,pt)|0))<<13)|0;c=((a=a+Math.imul(h,mt)|0)+(i>>>13)|0)+(Et>>>26)|0,Et&=67108863,r=Math.imul(L,q),i=(i=Math.imul(L,H))+Math.imul(F,q)|0,a=Math.imul(F,H),r=r+Math.imul(j,K)|0,i=(i=i+Math.imul(j,X)|0)+Math.imul(z,K)|0,a=a+Math.imul(z,X)|0,r=r+Math.imul(M,Y)|0,i=(i=i+Math.imul(M,J)|0)+Math.imul(R,Y)|0,a=a+Math.imul(R,J)|0,r=r+Math.imul(O,Q)|0,i=(i=i+Math.imul(O,tt)|0)+Math.imul(T,Q)|0,a=a+Math.imul(T,tt)|0,r=r+Math.imul(C,nt)|0,i=(i=i+Math.imul(C,rt)|0)+Math.imul(A,nt)|0,a=a+Math.imul(A,rt)|0,r=r+Math.imul(S,at)|0,i=(i=i+Math.imul(S,ot)|0)+Math.imul(_,at)|0,a=a+Math.imul(_,ot)|0,r=r+Math.imul(w,ut)|0,i=(i=i+Math.imul(w,ct)|0)+Math.imul(x,ut)|0,a=a+Math.imul(x,ct)|0,r=r+Math.imul(g,ft)|0,i=(i=i+Math.imul(g,ht)|0)+Math.imul(b,ft)|0,a=a+Math.imul(b,ht)|0;var Ct=(c+(r=r+Math.imul(p,pt)|0)|0)+((8191&(i=(i=i+Math.imul(p,mt)|0)+Math.imul(m,pt)|0))<<13)|0;c=((a=a+Math.imul(m,mt)|0)+(i>>>13)|0)+(Ct>>>26)|0,Ct&=67108863,r=Math.imul(L,K),i=(i=Math.imul(L,X))+Math.imul(F,K)|0,a=Math.imul(F,X),r=r+Math.imul(j,Y)|0,i=(i=i+Math.imul(j,J)|0)+Math.imul(z,Y)|0,a=a+Math.imul(z,J)|0,r=r+Math.imul(M,Q)|0,i=(i=i+Math.imul(M,tt)|0)+Math.imul(R,Q)|0,a=a+Math.imul(R,tt)|0,r=r+Math.imul(O,nt)|0,i=(i=i+Math.imul(O,rt)|0)+Math.imul(T,nt)|0,a=a+Math.imul(T,rt)|0,r=r+Math.imul(C,at)|0,i=(i=i+Math.imul(C,ot)|0)+Math.imul(A,at)|0,a=a+Math.imul(A,ot)|0,r=r+Math.imul(S,ut)|0,i=(i=i+Math.imul(S,ct)|0)+Math.imul(_,ut)|0,a=a+Math.imul(_,ct)|0,r=r+Math.imul(w,ft)|0,i=(i=i+Math.imul(w,ht)|0)+Math.imul(x,ft)|0,a=a+Math.imul(x,ht)|0;var At=(c+(r=r+Math.imul(g,pt)|0)|0)+((8191&(i=(i=i+Math.imul(g,mt)|0)+Math.imul(b,pt)|0))<<13)|0;c=((a=a+Math.imul(b,mt)|0)+(i>>>13)|0)+(At>>>26)|0,At&=67108863,r=Math.imul(L,Y),i=(i=Math.imul(L,J))+Math.imul(F,Y)|0,a=Math.imul(F,J),r=r+Math.imul(j,Q)|0,i=(i=i+Math.imul(j,tt)|0)+Math.imul(z,Q)|0,a=a+Math.imul(z,tt)|0,r=r+Math.imul(M,nt)|0,i=(i=i+Math.imul(M,rt)|0)+Math.imul(R,nt)|0,a=a+Math.imul(R,rt)|0,r=r+Math.imul(O,at)|0,i=(i=i+Math.imul(O,ot)|0)+Math.imul(T,at)|0,a=a+Math.imul(T,ot)|0,r=r+Math.imul(C,ut)|0,i=(i=i+Math.imul(C,ct)|0)+Math.imul(A,ut)|0,a=a+Math.imul(A,ct)|0,r=r+Math.imul(S,ft)|0,i=(i=i+Math.imul(S,ht)|0)+Math.imul(_,ft)|0,a=a+Math.imul(_,ht)|0;var Nt=(c+(r=r+Math.imul(w,pt)|0)|0)+((8191&(i=(i=i+Math.imul(w,mt)|0)+Math.imul(x,pt)|0))<<13)|0;c=((a=a+Math.imul(x,mt)|0)+(i>>>13)|0)+(Nt>>>26)|0,Nt&=67108863,r=Math.imul(L,Q),i=(i=Math.imul(L,tt))+Math.imul(F,Q)|0,a=Math.imul(F,tt),r=r+Math.imul(j,nt)|0,i=(i=i+Math.imul(j,rt)|0)+Math.imul(z,nt)|0,a=a+Math.imul(z,rt)|0,r=r+Math.imul(M,at)|0,i=(i=i+Math.imul(M,ot)|0)+Math.imul(R,at)|0,a=a+Math.imul(R,ot)|0,r=r+Math.imul(O,ut)|0,i=(i=i+Math.imul(O,ct)|0)+Math.imul(T,ut)|0,a=a+Math.imul(T,ct)|0,r=r+Math.imul(C,ft)|0,i=(i=i+Math.imul(C,ht)|0)+Math.imul(A,ft)|0,a=a+Math.imul(A,ht)|0;var Ot=(c+(r=r+Math.imul(S,pt)|0)|0)+((8191&(i=(i=i+Math.imul(S,mt)|0)+Math.imul(_,pt)|0))<<13)|0;c=((a=a+Math.imul(_,mt)|0)+(i>>>13)|0)+(Ot>>>26)|0,Ot&=67108863,r=Math.imul(L,nt),i=(i=Math.imul(L,rt))+Math.imul(F,nt)|0,a=Math.imul(F,rt),r=r+Math.imul(j,at)|0,i=(i=i+Math.imul(j,ot)|0)+Math.imul(z,at)|0,a=a+Math.imul(z,ot)|0,r=r+Math.imul(M,ut)|0,i=(i=i+Math.imul(M,ct)|0)+Math.imul(R,ut)|0,a=a+Math.imul(R,ct)|0,r=r+Math.imul(O,ft)|0,i=(i=i+Math.imul(O,ht)|0)+Math.imul(T,ft)|0,a=a+Math.imul(T,ht)|0;var Tt=(c+(r=r+Math.imul(C,pt)|0)|0)+((8191&(i=(i=i+Math.imul(C,mt)|0)+Math.imul(A,pt)|0))<<13)|0;c=((a=a+Math.imul(A,mt)|0)+(i>>>13)|0)+(Tt>>>26)|0,Tt&=67108863,r=Math.imul(L,at),i=(i=Math.imul(L,ot))+Math.imul(F,at)|0,a=Math.imul(F,ot),r=r+Math.imul(j,ut)|0,i=(i=i+Math.imul(j,ct)|0)+Math.imul(z,ut)|0,a=a+Math.imul(z,ct)|0,r=r+Math.imul(M,ft)|0,i=(i=i+Math.imul(M,ht)|0)+Math.imul(R,ft)|0,a=a+Math.imul(R,ht)|0;var It=(c+(r=r+Math.imul(O,pt)|0)|0)+((8191&(i=(i=i+Math.imul(O,mt)|0)+Math.imul(T,pt)|0))<<13)|0;c=((a=a+Math.imul(T,mt)|0)+(i>>>13)|0)+(It>>>26)|0,It&=67108863,r=Math.imul(L,ut),i=(i=Math.imul(L,ct))+Math.imul(F,ut)|0,a=Math.imul(F,ct),r=r+Math.imul(j,ft)|0,i=(i=i+Math.imul(j,ht)|0)+Math.imul(z,ft)|0,a=a+Math.imul(z,ht)|0;var Mt=(c+(r=r+Math.imul(M,pt)|0)|0)+((8191&(i=(i=i+Math.imul(M,mt)|0)+Math.imul(R,pt)|0))<<13)|0;c=((a=a+Math.imul(R,mt)|0)+(i>>>13)|0)+(Mt>>>26)|0,Mt&=67108863,r=Math.imul(L,ft),i=(i=Math.imul(L,ht))+Math.imul(F,ft)|0,a=Math.imul(F,ht);var Rt=(c+(r=r+Math.imul(j,pt)|0)|0)+((8191&(i=(i=i+Math.imul(j,mt)|0)+Math.imul(z,pt)|0))<<13)|0;c=((a=a+Math.imul(z,mt)|0)+(i>>>13)|0)+(Rt>>>26)|0,Rt&=67108863;var Dt=(c+(r=Math.imul(L,pt))|0)+((8191&(i=(i=Math.imul(L,mt))+Math.imul(F,pt)|0))<<13)|0;return c=((a=Math.imul(F,mt))+(i>>>13)|0)+(Dt>>>26)|0,Dt&=67108863,u[0]=vt,u[1]=gt,u[2]=bt,u[3]=yt,u[4]=wt,u[5]=xt,u[6]=kt,u[7]=St,u[8]=_t,u[9]=Et,u[10]=Ct,u[11]=At,u[12]=Nt,u[13]=Ot,u[14]=Tt,u[15]=It,u[16]=Mt,u[17]=Rt,u[18]=Dt,0!==c&&(u[19]=c,n.length++),n};function p(t,e,n){return(new m).mulp(t,e,n)}function m(t,e){this.x=t,this.y=e}Math.imul||(d=h),a.prototype.mulTo=function(t,e){var n=this.length+t.length;return 10===this.length&&10===t.length?d(this,t,e):n<63?h(this,t,e):n<1024?function(t,e,n){n.negative=e.negative^t.negative,n.length=t.length+e.length;for(var r=0,i=0,a=0;a>>26)|0)>>>26,o&=67108863}n.words[a]=s,r=o,o=i}return 0!==r?n.words[a]=r:n.length--,n.strip()}(this,t,e):p(this,t,e)},m.prototype.makeRBT=function(t){for(var e=new Array(t),n=a.prototype._countBits(t)-1,r=0;r>=1;return r},m.prototype.permute=function(t,e,n,r,i,a){for(var o=0;o>>=1)i++;return 1<>>=13,n[2*o+1]=8191&a,a>>>=13;for(o=2*e;o>=26,e+=i/67108864|0,e+=a>>>26,this.words[n]=67108863&a}return 0!==e&&(this.words[n]=e,this.length++),this},a.prototype.muln=function(t){return this.clone().imuln(t)},a.prototype.sqr=function(){return this.mul(this)},a.prototype.isqr=function(){return this.imul(this.clone())},a.prototype.pow=function(t){var e=function(t){for(var e=new Array(t.bitLength()),n=0;n>>i}return e}(t);if(0===e.length)return new a(1);for(var n=this,r=0;r=0);var e,n=t%26,i=(t-n)/26,a=67108863>>>26-n<<26-n;if(0!==n){var o=0;for(e=0;e>>26-n}o&&(this.words[e]=o,this.length++)}if(0!==i){for(e=this.length-1;e>=0;e--)this.words[e+i]=this.words[e];for(e=0;e=0),i=e?(e-e%26)/26:0;var a=t%26,o=Math.min((t-a)/26,this.length),s=67108863^67108863>>>a<o)for(this.length-=o,c=0;c=0&&(0!==l||c>=i);c--){var f=0|this.words[c];this.words[c]=l<<26-a|f>>>a,l=f&s}return u&&0!==l&&(u.words[u.length++]=l),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},a.prototype.ishrn=function(t,e,n){return r(0===this.negative),this.iushrn(t,e,n)},a.prototype.shln=function(t){return this.clone().ishln(t)},a.prototype.ushln=function(t){return this.clone().iushln(t)},a.prototype.shrn=function(t){return this.clone().ishrn(t)},a.prototype.ushrn=function(t){return this.clone().iushrn(t)},a.prototype.testn=function(t){r("number"==typeof t&&t>=0);var e=t%26,n=(t-e)/26,i=1<=0);var e=t%26,n=(t-e)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==e&&n++,this.length=Math.min(n,this.length),0!==e){var i=67108863^67108863>>>e<=67108864;e++)this.words[e]-=67108864,e===this.length-1?this.words[e+1]=1:this.words[e+1]++;return this.length=Math.max(this.length,e+1),this},a.prototype.isubn=function(t){if(r("number"==typeof t),r(t<67108864),t<0)return this.iaddn(-t);if(0!==this.negative)return this.negative=0,this.iaddn(t),this.negative=1,this;if(this.words[0]-=t,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var e=0;e>26)-(u/67108864|0),this.words[i+n]=67108863&a}for(;i>26,this.words[i+n]=67108863&a;if(0===s)return this.strip();for(r(-1===s),s=0,i=0;i>26,this.words[i]=67108863&a;return this.negative=1,this.strip()},a.prototype._wordDiv=function(t,e){var n=(this.length,t.length),r=this.clone(),i=t,o=0|i.words[i.length-1];0!=(n=26-this._countBits(o))&&(i=i.ushln(n),r.iushln(n),o=0|i.words[i.length-1]);var s,u=r.length-i.length;if("mod"!==e){(s=new a(null)).length=u+1,s.words=new Array(s.length);for(var c=0;c=0;f--){var h=67108864*(0|r.words[i.length+f])+(0|r.words[i.length+f-1]);for(h=Math.min(h/o|0,67108863),r._ishlnsubmul(i,h,f);0!==r.negative;)h--,r.negative=0,r._ishlnsubmul(i,1,f),r.isZero()||(r.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),r.strip(),"div"!==e&&0!==n&&r.iushrn(n),{div:s||null,mod:r}},a.prototype.divmod=function(t,e,n){return r(!t.isZero()),this.isZero()?{div:new a(0),mod:new a(0)}:0!==this.negative&&0===t.negative?(s=this.neg().divmod(t,e),"mod"!==e&&(i=s.div.neg()),"div"!==e&&(o=s.mod.neg(),n&&0!==o.negative&&o.iadd(t)),{div:i,mod:o}):0===this.negative&&0!==t.negative?(s=this.divmod(t.neg(),e),"mod"!==e&&(i=s.div.neg()),{div:i,mod:s.mod}):0!=(this.negative&t.negative)?(s=this.neg().divmod(t.neg(),e),"div"!==e&&(o=s.mod.neg(),n&&0!==o.negative&&o.isub(t)),{div:s.div,mod:o}):t.length>this.length||this.cmp(t)<0?{div:new a(0),mod:this}:1===t.length?"div"===e?{div:this.divn(t.words[0]),mod:null}:"mod"===e?{div:null,mod:new a(this.modn(t.words[0]))}:{div:this.divn(t.words[0]),mod:new a(this.modn(t.words[0]))}:this._wordDiv(t,e);var i,o,s},a.prototype.div=function(t){return this.divmod(t,"div",!1).div},a.prototype.mod=function(t){return this.divmod(t,"mod",!1).mod},a.prototype.umod=function(t){return this.divmod(t,"mod",!0).mod},a.prototype.divRound=function(t){var e=this.divmod(t);if(e.mod.isZero())return e.div;var n=0!==e.div.negative?e.mod.isub(t):e.mod,r=t.ushrn(1),i=t.andln(1),a=n.cmp(r);return a<0||1===i&&0===a?e.div:0!==e.div.negative?e.div.isubn(1):e.div.iaddn(1)},a.prototype.modn=function(t){r(t<=67108863);for(var e=(1<<26)%t,n=0,i=this.length-1;i>=0;i--)n=(e*n+(0|this.words[i]))%t;return n},a.prototype.idivn=function(t){r(t<=67108863);for(var e=0,n=this.length-1;n>=0;n--){var i=(0|this.words[n])+67108864*e;this.words[n]=i/t|0,e=i%t}return this.strip()},a.prototype.divn=function(t){return this.clone().idivn(t)},a.prototype.egcd=function(t){r(0===t.negative),r(!t.isZero());var e=this,n=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i=new a(1),o=new a(0),s=new a(0),u=new a(1),c=0;e.isEven()&&n.isEven();)e.iushrn(1),n.iushrn(1),++c;for(var l=n.clone(),f=e.clone();!e.isZero();){for(var h=0,d=1;0==(e.words[0]&d)&&h<26;++h,d<<=1);if(h>0)for(e.iushrn(h);h-- >0;)(i.isOdd()||o.isOdd())&&(i.iadd(l),o.isub(f)),i.iushrn(1),o.iushrn(1);for(var p=0,m=1;0==(n.words[0]&m)&&p<26;++p,m<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(s.isOdd()||u.isOdd())&&(s.iadd(l),u.isub(f)),s.iushrn(1),u.iushrn(1);e.cmp(n)>=0?(e.isub(n),i.isub(s),o.isub(u)):(n.isub(e),s.isub(i),u.isub(o))}return{a:s,b:u,gcd:n.iushln(c)}},a.prototype._invmp=function(t){r(0===t.negative),r(!t.isZero());var e=this,n=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i,o=new a(1),s=new a(0),u=n.clone();e.cmpn(1)>0&&n.cmpn(1)>0;){for(var c=0,l=1;0==(e.words[0]&l)&&c<26;++c,l<<=1);if(c>0)for(e.iushrn(c);c-- >0;)o.isOdd()&&o.iadd(u),o.iushrn(1);for(var f=0,h=1;0==(n.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(n.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);e.cmp(n)>=0?(e.isub(n),o.isub(s)):(n.isub(e),s.isub(o))}return(i=0===e.cmpn(1)?o:s).cmpn(0)<0&&i.iadd(t),i},a.prototype.gcd=function(t){if(this.isZero())return t.abs();if(t.isZero())return this.abs();var e=this.clone(),n=t.clone();e.negative=0,n.negative=0;for(var r=0;e.isEven()&&n.isEven();r++)e.iushrn(1),n.iushrn(1);for(;;){for(;e.isEven();)e.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=e.cmp(n);if(i<0){var a=e;e=n,n=a}else if(0===i||0===n.cmpn(1))break;e.isub(n)}return n.iushln(r)},a.prototype.invm=function(t){return this.egcd(t).a.umod(t)},a.prototype.isEven=function(){return 0==(1&this.words[0])},a.prototype.isOdd=function(){return 1==(1&this.words[0])},a.prototype.andln=function(t){return this.words[0]&t},a.prototype.bincn=function(t){r("number"==typeof t);var e=t%26,n=(t-e)/26,i=1<>>26,s&=67108863,this.words[o]=s}return 0!==a&&(this.words[o]=a,this.length++),this},a.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},a.prototype.cmpn=function(t){var e,n=t<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this.strip(),this.length>1)e=1;else{n&&(t=-t),r(t<=67108863,"Number is too big");var i=0|this.words[0];e=i===t?0:it.length)return 1;if(this.length=0;n--){var r=0|this.words[n],i=0|t.words[n];if(r!==i){ri&&(e=1);break}}return e},a.prototype.gtn=function(t){return 1===this.cmpn(t)},a.prototype.gt=function(t){return 1===this.cmp(t)},a.prototype.gten=function(t){return this.cmpn(t)>=0},a.prototype.gte=function(t){return this.cmp(t)>=0},a.prototype.ltn=function(t){return-1===this.cmpn(t)},a.prototype.lt=function(t){return-1===this.cmp(t)},a.prototype.lten=function(t){return this.cmpn(t)<=0},a.prototype.lte=function(t){return this.cmp(t)<=0},a.prototype.eqn=function(t){return 0===this.cmpn(t)},a.prototype.eq=function(t){return 0===this.cmp(t)},a.red=function(t){return new k(t)},a.prototype.toRed=function(t){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),t.convertTo(this)._forceRed(t)},a.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},a.prototype._forceRed=function(t){return this.red=t,this},a.prototype.forceRed=function(t){return r(!this.red,"Already a number in reduction context"),this._forceRed(t)},a.prototype.redAdd=function(t){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,t)},a.prototype.redIAdd=function(t){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,t)},a.prototype.redSub=function(t){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,t)},a.prototype.redISub=function(t){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,t)},a.prototype.redShl=function(t){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,t)},a.prototype.redMul=function(t){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.mul(this,t)},a.prototype.redIMul=function(t){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.imul(this,t)},a.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},a.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},a.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},a.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},a.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},a.prototype.redPow=function(t){return r(this.red&&!t.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,t)};var v={k256:null,p224:null,p192:null,p25519:null};function g(t,e){this.name=t,this.p=new a(e,16),this.n=this.p.bitLength(),this.k=new a(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function b(){g.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function y(){g.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function w(){g.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function x(){g.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function k(t){if("string"==typeof t){var e=a._prime(t);this.m=e.p,this.prime=e}else r(t.gtn(1),"modulus must be greater than 1"),this.m=t,this.prime=null}function S(t){k.call(this,t),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new a(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}g.prototype._tmp=function(){var t=new a(null);return t.words=new Array(Math.ceil(this.n/13)),t},g.prototype.ireduce=function(t){var e,n=t;do{this.split(n,this.tmp),e=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(e>this.n);var r=e0?n.isub(this.p):n.strip(),n},g.prototype.split=function(t,e){t.iushrn(this.n,0,e)},g.prototype.imulK=function(t){return t.imul(this.k)},i(b,g),b.prototype.split=function(t,e){for(var n=Math.min(t.length,9),r=0;r>>22,i=a}i>>>=22,t.words[r-10]=i,0===i&&t.length>10?t.length-=10:t.length-=9},b.prototype.imulK=function(t){t.words[t.length]=0,t.words[t.length+1]=0,t.length+=2;for(var e=0,n=0;n>>=26,t.words[n]=i,e=r}return 0!==e&&(t.words[t.length++]=e),t},a._prime=function(t){if(v[t])return v[t];var e;if("k256"===t)e=new b;else if("p224"===t)e=new y;else if("p192"===t)e=new w;else{if("p25519"!==t)throw new Error("Unknown prime "+t);e=new x}return v[t]=e,e},k.prototype._verify1=function(t){r(0===t.negative,"red works only with positives"),r(t.red,"red works only with red numbers")},k.prototype._verify2=function(t,e){r(0==(t.negative|e.negative),"red works only with positives"),r(t.red&&t.red===e.red,"red works only with red numbers")},k.prototype.imod=function(t){return this.prime?this.prime.ireduce(t)._forceRed(this):t.umod(this.m)._forceRed(this)},k.prototype.neg=function(t){return t.isZero()?t.clone():this.m.sub(t)._forceRed(this)},k.prototype.add=function(t,e){this._verify2(t,e);var n=t.add(e);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},k.prototype.iadd=function(t,e){this._verify2(t,e);var n=t.iadd(e);return n.cmp(this.m)>=0&&n.isub(this.m),n},k.prototype.sub=function(t,e){this._verify2(t,e);var n=t.sub(e);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},k.prototype.isub=function(t,e){this._verify2(t,e);var n=t.isub(e);return n.cmpn(0)<0&&n.iadd(this.m),n},k.prototype.shl=function(t,e){return this._verify1(t),this.imod(t.ushln(e))},k.prototype.imul=function(t,e){return this._verify2(t,e),this.imod(t.imul(e))},k.prototype.mul=function(t,e){return this._verify2(t,e),this.imod(t.mul(e))},k.prototype.isqr=function(t){return this.imul(t,t.clone())},k.prototype.sqr=function(t){return this.mul(t,t)},k.prototype.sqrt=function(t){if(t.isZero())return t.clone();var e=this.m.andln(3);if(r(e%2==1),3===e){var n=this.m.add(new a(1)).iushrn(2);return this.pow(t,n)}for(var i=this.m.subn(1),o=0;!i.isZero()&&0===i.andln(1);)o++,i.iushrn(1);r(!i.isZero());var s=new a(1).toRed(this),u=s.redNeg(),c=this.m.subn(1).iushrn(1),l=this.m.bitLength();for(l=new a(2*l*l).toRed(this);0!==this.pow(l,c).cmp(u);)l.redIAdd(u);for(var f=this.pow(l,i),h=this.pow(t,i.addn(1).iushrn(1)),d=this.pow(t,i),p=o;0!==d.cmp(s);){for(var m=d,v=0;0!==m.cmp(s);v++)m=m.redSqr();r(v=0;r--){for(var c=e.words[r],l=u-1;l>=0;l--){var f=c>>l&1;i!==n[0]&&(i=this.sqr(i)),0!==f||0!==o?(o<<=1,o|=f,(4==++s||0===r&&0===l)&&(i=this.mul(i,n[o]),s=0,o=0)):s=0}u=26}return i},k.prototype.convertTo=function(t){var e=t.umod(this.m);return e===t?e.clone():e},k.prototype.convertFrom=function(t){var e=t.clone();return e.red=null,e},a.mont=function(t){return new S(t)},i(S,k),S.prototype.convertTo=function(t){return this.imod(t.ushln(this.shift))},S.prototype.convertFrom=function(t){var e=this.imod(t.mul(this.rinv));return e.red=null,e},S.prototype.imul=function(t,e){if(t.isZero()||e.isZero())return t.words[0]=0,t.length=1,t;var n=t.imul(e),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},S.prototype.mul=function(t,e){if(t.isZero()||e.isZero())return new a(0)._forceRed(this);var n=t.mul(e),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},S.prototype.invm=function(t){return this.imod(t._invmp(this.m).mul(this.r2))._forceRed(this)}}(void 0===t||t,this)}).call(this,n(451)(t))},function(t,e,n){var r=n(51);t.exports=function(t){return Object(r(t))}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t,e){return e&&t.then(function(t){return e(void 0,t),t}).catch(function(t){return e(t),t}),t}},function(t,e,n){var r=n(25),i=n(15),a=n(53),o=n(57),s=n(65),u=function(t,e,n){var c,l,f,h=t&u.F,d=t&u.G,p=t&u.S,m=t&u.P,v=t&u.B,g=t&u.W,b=d?i:i[e]||(i[e]={}),y=b.prototype,w=d?r:p?r[e]:(r[e]||{}).prototype;for(c in d&&(n=e),n)(l=!h&&w&&void 0!==w[c])&&s(b,c)||(f=l?w[c]:n[c],b[c]=d&&"function"!=typeof w[c]?n[c]:v&&l?a(f,r):g&&w[c]==f?function(t){var e=function(e,n,r){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(e);case 2:return new t(e,n)}return new t(e,n,r)}return t.apply(this,arguments)};return e.prototype=t.prototype,e}(f):m&&"function"==typeof f?a(Function.call,f):f,m&&((b.virtual||(b.virtual={}))[c]=f,t&u.R&&y&&!y[c]&&o(y,c,f)))};u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,t.exports=u},function(t,e,n){"use strict";e.__esModule=!0;var r=o(n(382)),i=o(n(380)),a="function"==typeof i.default&&"symbol"==typeof r.default?function(t){return typeof t}:function(t){return t&&"function"==typeof i.default&&t.constructor===i.default&&t!==i.default.prototype?"symbol":typeof t};function o(t){return t&&t.__esModule?t:{default:t}}e.default="function"==typeof i.default&&"symbol"===a(r.default)?function(t){return void 0===t?"undefined":a(t)}:function(t){return t&&"function"==typeof i.default&&t.constructor===i.default&&t!==i.default.prototype?"symbol":void 0===t?"undefined":a(t)}},function(t,e,n){var r=n(164)("wks"),i=n(120),a=n(25).Symbol,o="function"==typeof a;(t.exports=function(t){return r[t]||(r[t]=o&&a[t]||(o?a:i)("Symbol."+t))}).store=r},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,n){"use strict";var r=e;r.version=n(444).version,r.utils=n(443),r.rand=n(232),r.curve=n(115),r.curves=n(438),r.ec=n(430),r.eddsa=n(426)},function(t,e,n){var r=n(2),i=n(7),a=n(51),o=/"/g,s=function(t,e,n,r){var i=String(a(t)),s="<"+e;return""!==n&&(s+=" "+n+'="'+String(r).replace(o,""")+'"'),s+">"+i+""};t.exports=function(t,e){var n={};n[t]=e(s),r(r.P+r.F*i(function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}),"String",n)}},function(t,e,n){var r=n(6),i=n(30),a=n(36),o=n(75)("src"),s=Function.toString,u=(""+s).split("toString");n(43).inspectSource=function(t){return s.call(t)},(t.exports=function(t,e,n,s){var c="function"==typeof n;c&&(a(n,"name")||i(n,"name",e)),t[e]!==n&&(c&&(a(n,o)||i(n,o,t[e]?""+t[e]:u.join(String(e)))),t===r?t[e]=n:s?t[e]?t[e]=n:i(t,e,n):(delete t[e],i(t,e,n)))})(Function.prototype,"toString",function(){return"function"==typeof this&&this[o]||s.call(this)})},function(t,e,n){var r=n(17),i=n(76);t.exports=n(18)?function(t,e,n){return r.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e){function n(t,e){if(!t)throw new Error(e||"Assertion failed")}t.exports=n,n.equal=function(t,e,n){if(t!=e)throw new Error(n||"Assertion failed: "+t+" != "+e)}},function(t,e,n){var r=n(36),i=n(20),a=n(196)("IE_PROTO"),o=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=i(t),r(t,a)?t[a]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?o:null}},function(t,e,n){var r=n(106),i=n(76),a=n(35),o=n(52),s=n(36),u=n(294),c=Object.getOwnPropertyDescriptor;e.f=n(18)?c:function(t,e){if(t=a(t),e=o(e,!0),u)try{return c(t,e)}catch(t){}if(s(t,e))return i(!r.f.call(t,e),t[e])}},function(t,e,n){var r=n(107),i=n(51);t.exports=function(t){return r(i(t))}},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,n){var r=n(48),i=n(258),a=n(169),o=Object.defineProperty;e.f=n(47)?Object.defineProperty:function(t,e,n){if(r(t),e=a(e,!0),r(n),i)try{return o(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){"use strict";var r=n(7);t.exports=function(t,e){return!!t&&r(function(){e?t.call(null,function(){},1):t.call(null)})}},function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){var r=n(26);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,i){return t.call(e,n,r,i)}}return function(){return t.apply(e,arguments)}}},function(t,e){var n=t.exports={version:"2.6.1"};"number"==typeof __e&&(__e=n)},function(t,e,n){t.exports={default:n(398),__esModule:!0}},function(t,e,n){"use strict";var r=n(32),i=n(4);function a(t,e){return 55296==(64512&t.charCodeAt(e))&&!(e<0||e+1>=t.length)&&56320==(64512&t.charCodeAt(e+1))}function o(t){return(t>>>24|t>>>8&65280|t<<8&16711680|(255&t)<<24)>>>0}function s(t){return 1===t.length?"0"+t:t}function u(t){return 7===t.length?"0"+t:6===t.length?"00"+t:5===t.length?"000"+t:4===t.length?"0000"+t:3===t.length?"00000"+t:2===t.length?"000000"+t:1===t.length?"0000000"+t:t}e.inherits=i,e.toArray=function(t,e){if(Array.isArray(t))return t.slice();if(!t)return[];var n=[];if("string"==typeof t)if(e){if("hex"===e)for((t=t.replace(/[^a-z0-9]+/gi,"")).length%2!=0&&(t="0"+t),i=0;i>6|192,n[r++]=63&o|128):a(t,i)?(o=65536+((1023&o)<<10)+(1023&t.charCodeAt(++i)),n[r++]=o>>18|240,n[r++]=o>>12&63|128,n[r++]=o>>6&63|128,n[r++]=63&o|128):(n[r++]=o>>12|224,n[r++]=o>>6&63|128,n[r++]=63&o|128)}else for(i=0;i>>0}return o},e.split32=function(t,e){for(var n=new Array(4*t.length),r=0,i=0;r>>24,n[i+1]=a>>>16&255,n[i+2]=a>>>8&255,n[i+3]=255&a):(n[i+3]=a>>>24,n[i+2]=a>>>16&255,n[i+1]=a>>>8&255,n[i]=255&a)}return n},e.rotr32=function(t,e){return t>>>e|t<<32-e},e.rotl32=function(t,e){return t<>>32-e},e.sum32=function(t,e){return t+e>>>0},e.sum32_3=function(t,e,n){return t+e+n>>>0},e.sum32_4=function(t,e,n,r){return t+e+n+r>>>0},e.sum32_5=function(t,e,n,r,i){return t+e+n+r+i>>>0},e.sum64=function(t,e,n,r){var i=t[e],a=r+t[e+1]>>>0,o=(a>>0,t[e+1]=a},e.sum64_hi=function(t,e,n,r){return(e+r>>>0>>0},e.sum64_lo=function(t,e,n,r){return e+r>>>0},e.sum64_4_hi=function(t,e,n,r,i,a,o,s){var u=0,c=e;return u+=(c=c+r>>>0)>>0)>>0)>>0},e.sum64_4_lo=function(t,e,n,r,i,a,o,s){return e+r+a+s>>>0},e.sum64_5_hi=function(t,e,n,r,i,a,o,s,u,c){var l=0,f=e;return l+=(f=f+r>>>0)>>0)>>0)>>0)>>0},e.sum64_5_lo=function(t,e,n,r,i,a,o,s,u,c){return e+r+a+s+c>>>0},e.rotr64_hi=function(t,e,n){return(e<<32-n|t>>>n)>>>0},e.rotr64_lo=function(t,e,n){return(t<<32-n|e>>>n)>>>0},e.shr64_hi=function(t,e,n){return t>>>n},e.shr64_lo=function(t,e,n){return(t<<32-n|e>>>n)>>>0}},function(t,e){var n,r,i=t.exports={};function a(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function s(t){if(n===setTimeout)return setTimeout(t,0);if((n===a||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:a}catch(t){n=a}try{r="function"==typeof clearTimeout?clearTimeout:o}catch(t){r=o}}();var u,c=[],l=!1,f=-1;function h(){l&&u&&(l=!1,u.length?c=u.concat(c):f=-1,c.length&&d())}function d(){if(!l){var t=s(h);l=!0;for(var e=c.length;e;){for(u=c,c=[];++f1)for(var n=1;nx;x++)if((h||x in b)&&(v=y(m=b[x],x,g),t))if(n)k[x]=v;else if(v)switch(t){case 3:return!0;case 5:return m;case 6:return x;case 2:k.push(m)}else if(l)return!1;return f?-1:c||l?l:k}}},function(t,e,n){var r=n(2),i=n(43),a=n(7);t.exports=function(t,e){var n=(i.Object||{})[t]||Object[t],o={};o[t]=e(n),r(r.S+r.F*a(function(){n(1)}),"Object",o)}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){var r=n(8);t.exports=function(t,e){if(!r(t))return t;var n,i;if(e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;if("function"==typeof(n=t.valueOf)&&!r(i=n.call(t)))return i;if(!e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,e,n){var r=n(103);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,i){return t.call(e,n,r,i)}}return function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(271),i=n(2),a=n(136)("metadata"),o=a.store||(a.store=new(n(268))),s=function(t,e,n){var i=o.get(t);if(!i){if(!n)return;o.set(t,i=new r)}var a=i.get(e);if(!a){if(!n)return;i.set(e,a=new r)}return a};t.exports={store:o,map:s,has:function(t,e,n){var r=s(e,n,!1);return void 0!==r&&r.has(t)},get:function(t,e,n){var r=s(e,n,!1);return void 0===r?void 0:r.get(t)},set:function(t,e,n,r){s(n,r,!0).set(t,e)},keys:function(t,e){var n=s(t,e,!1),r=[];return n&&n.forEach(function(t,e){r.push(e)}),r},key:function(t){return void 0===t||"symbol"==typeof t?t:String(t)},exp:function(t){i(i.S,"Reflect",t)}}},function(t,e,n){"use strict";if(n(18)){var r=n(59),i=n(6),a=n(7),o=n(2),s=n(125),u=n(172),c=n(42),l=n(69),f=n(76),h=n(30),d=n(67),p=n(40),m=n(12),v=n(266),g=n(73),b=n(52),y=n(36),w=n(87),x=n(8),k=n(20),S=n(183),_=n(72),E=n(33),C=n(71).f,A=n(181),N=n(75),O=n(11),T=n(49),I=n(135),M=n(104),R=n(178),D=n(85),j=n(130),z=n(70),P=n(179),L=n(277),F=n(17),B=n(34),U=F.f,V=B.f,W=i.RangeError,q=i.TypeError,H=i.Uint8Array,G=Array.prototype,K=u.ArrayBuffer,X=u.DataView,$=T(0),Y=T(2),J=T(3),Z=T(4),Q=T(5),tt=T(6),et=I(!0),nt=I(!1),rt=R.values,it=R.keys,at=R.entries,ot=G.lastIndexOf,st=G.reduce,ut=G.reduceRight,ct=G.join,lt=G.sort,ft=G.slice,ht=G.toString,dt=G.toLocaleString,pt=O("iterator"),mt=O("toStringTag"),vt=N("typed_constructor"),gt=N("def_constructor"),bt=s.CONSTR,yt=s.TYPED,wt=s.VIEW,xt=T(1,function(t,e){return Ct(M(t,t[gt]),e)}),kt=a(function(){return 1===new H(new Uint16Array([1]).buffer)[0]}),St=!!H&&!!H.prototype.set&&a(function(){new H(1).set({})}),_t=function(t,e){var n=p(t);if(n<0||n%e)throw W("Wrong offset!");return n},Et=function(t){if(x(t)&&yt in t)return t;throw q(t+" is not a typed array!")},Ct=function(t,e){if(!(x(t)&&vt in t))throw q("It is not a typed array constructor!");return new t(e)},At=function(t,e){return Nt(M(t,t[gt]),e)},Nt=function(t,e){for(var n=0,r=e.length,i=Ct(t,r);r>n;)i[n]=e[n++];return i},Ot=function(t,e,n){U(t,e,{get:function(){return this._d[n]}})},Tt=function(t){var e,n,r,i,a,o,s=k(t),u=arguments.length,l=u>1?arguments[1]:void 0,f=void 0!==l,h=A(s);if(void 0!=h&&!S(h)){for(o=h.call(s),r=[],e=0;!(a=o.next()).done;e++)r.push(a.value);s=r}for(f&&u>2&&(l=c(l,arguments[2],2)),e=0,n=m(s.length),i=Ct(this,n);n>e;e++)i[e]=f?l(s[e],e):s[e];return i},It=function(){for(var t=0,e=arguments.length,n=Ct(this,e);e>t;)n[t]=arguments[t++];return n},Mt=!!H&&a(function(){dt.call(new H(1))}),Rt=function(){return dt.apply(Mt?ft.call(Et(this)):Et(this),arguments)},Dt={copyWithin:function(t,e){return L.call(Et(this),t,e,arguments.length>2?arguments[2]:void 0)},every:function(t){return Z(Et(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return P.apply(Et(this),arguments)},filter:function(t){return At(this,Y(Et(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return Q(Et(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return tt(Et(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){$(Et(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return nt(Et(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return et(Et(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return ct.apply(Et(this),arguments)},lastIndexOf:function(t){return ot.apply(Et(this),arguments)},map:function(t){return xt(Et(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return st.apply(Et(this),arguments)},reduceRight:function(t){return ut.apply(Et(this),arguments)},reverse:function(){for(var t,e=Et(this).length,n=Math.floor(e/2),r=0;r1?arguments[1]:void 0)},sort:function(t){return lt.call(Et(this),t)},subarray:function(t,e){var n=Et(this),r=n.length,i=g(t,r);return new(M(n,n[gt]))(n.buffer,n.byteOffset+i*n.BYTES_PER_ELEMENT,m((void 0===e?r:g(e,r))-i))}},jt=function(t,e){return At(this,ft.call(Et(this),t,e))},zt=function(t){Et(this);var e=_t(arguments[1],1),n=this.length,r=k(t),i=m(r.length),a=0;if(i+e>n)throw W("Wrong length!");for(;a255?255:255&r),i.v[d](n*e+i.o,r,kt)}(this,n,t)},enumerable:!0})};y?(p=n(function(t,n,r,i){l(t,p,c,"_d");var a,o,s,u,f=0,d=0;if(x(n)){if(!(n instanceof K||"ArrayBuffer"==(u=w(n))||"SharedArrayBuffer"==u))return yt in n?Nt(p,n):Tt.call(p,n);a=n,d=_t(r,e);var g=n.byteLength;if(void 0===i){if(g%e)throw W("Wrong length!");if((o=g-d)<0)throw W("Wrong length!")}else if((o=m(i)*e)+d>g)throw W("Wrong length!");s=o/e}else s=v(n),a=new K(o=s*e);for(h(t,"_d",{b:a,o:d,l:o,e:s,v:new X(a)});f2&&void 0!==arguments[2]?arguments[2]:function(){},r=t,i=document.createElement("video");return r.onplay=function(){var t=r.captureStream();i.srcObject=t,i.width=e,i.height=e,i.autoplay=!0,i.playsinline=!0,i.muted=!0,n()},i},e.cropImage=a,e.imgToTensor=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return i.tidy(function(){var n=i.browser.fromPixels(t);return e&&(n=i.image.resizeBilinear(n,e)),a(n).expandDims(0).toFloat().div(i.scalar(127)).sub(i.scalar(1))})}},function(t,e,n){"use strict";e.__esModule=!0;var r=a(n(366)),i=a(n(363));function a(t){return t&&t.__esModule?t:{default:t}}e.default=function(t,e){if(Array.isArray(t))return t;if((0,r.default)(Object(t)))return function(t,e){var n=[],r=!0,a=!1,o=void 0;try{for(var s,u=(0,i.default)(t);!(r=(s=u.next()).done)&&(n.push(s.value),!e||n.length!==e);r=!0);}catch(t){a=!0,o=t}finally{try{!r&&u.return&&u.return()}finally{if(a)throw o}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(t,e,n){"use strict";var r=n(118),i=Object.keys||function(t){var e=[];for(var n in t)e.push(n);return e};t.exports=f;var a=n(97);a.inherits=n(4);var o=n(252),s=n(158);a.inherits(f,o);for(var u=i(s.prototype),c=0;cy;y++)if((v=e?b(o(p=t[y])[0],p[1]):b(t[y]))===c||v===l)return v}else for(m=g.call(t);!(p=m.next()).done;)if((v=i(m,b,p.value,e))===c||v===l)return v}).BREAK=c,e.RETURN=l},function(t,e){t.exports=function(t,e,n,r){if(!(t instanceof e)||void 0!==r&&r in t)throw TypeError(n+": incorrect invocation!");return t}},function(t,e,n){"use strict";var r=n(6),i=n(17),a=n(18),o=n(11)("species");t.exports=function(t){var e=r[t];a&&e&&!e[o]&&i.f(e,o,{configurable:!0,get:function(){return this}})}},function(t,e,n){var r=n(292),i=n(195).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,i)}},function(t,e,n){var r=n(3),i=n(291),a=n(195),o=n(196)("IE_PROTO"),s=function(){},u=function(){var t,e=n(198)("iframe"),r=a.length;for(e.style.display="none",n(194).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" - + + - - - - - + - -

Image Regression using Feature Extraction with MobileNet. Built with p5.js

-

(Train a Neural Network to move the red square)

-
-
Loading base model... | Loading video...
-

- -

-
-

- -

0 Sample Images

- + + -
-

-
-

-
-

- - + +

+ Image Regression using Feature Extraction with MobileNet. Built with p5.js +

+

(Train a Neural Network to move the red square)

+
+
+ Loading base model... | + Loading video... +
+

+ +

+
+

+ +

+

0 Sample Images

- \ No newline at end of file +
+

+
+


+ + + diff --git a/week2-imageClassifier/KNNClassification_VideoSound/index.html b/week2-imageClassifier/KNNClassification_VideoSound/index.html index cdbafd5..1932e1d 100755 --- a/week2-imageClassifier/KNNClassification_VideoSound/index.html +++ b/week2-imageClassifier/KNNClassification_VideoSound/index.html @@ -1,39 +1,48 @@ + + + + KNN Classification on Webcam Images with Speech Output Using mobileNet. + Built with p5.js + - - - KNN Classification on Webcam Images with Speech Output Using mobileNet. Built with p5.js - - - - - - - - + + + + - -

KNN Classification on Webcam Images with Speech Output Using mobileNet. Built with p5.js

-
-

Loading Model...

-

- -

0 "Hello" examples

+ + + + +

+ KNN Classification on Webcam Images with Speech Output Using mobileNet. + Built with p5.js +

+
+

Loading Model...

+
+

+ +

+

0 "Hello" examples


0 "Goodbye" examples

- -
-

-
-
-

-

- KNN Classifier with mobileNet model labeled this - as Class: ... - with a confidence of ... -

- - - \ No newline at end of file +
+

+
+
+

+

+ KNN Classifier with mobileNet model labeled this as Class: + ... with a confidence of + ... +

+ + + diff --git a/week2-imageClassifier/KNNClassification_VideoSquare/index.html b/week2-imageClassifier/KNNClassification_VideoSquare/index.html index ff41d38..2cc0492 100755 --- a/week2-imageClassifier/KNNClassification_VideoSquare/index.html +++ b/week2-imageClassifier/KNNClassification_VideoSquare/index.html @@ -1,44 +1,56 @@ + + + + KNN Classification on Webcam Images with mobileNet. Built with p5.js + - - - KNN Classification on Webcam Images with mobileNet. Built with p5.js - - - - - - - + + + - -

KNN Classification on Webcam Images that moves a square on the canvas with mobileNet. Built with p5.js

-
-

Loading Model...


-

- ⬆️ -

0 Up examples

+ + -
➡️ + +

+ KNN Classification on Webcam Images that moves a square on the canvas with + mobileNet. Built with p5.js +

+
+

Loading Model...

+
+

+ ⬆️ +

+

0 Up examples

+ +
➡️

0 Right examples

-
⬇️ +
⬇️

0 Down examples

-
⬅️ +
⬅️

0 Left examples

- -
-

-
-
-

-

- KNN Classifier with mobileNet model labeled this - as Class: ... - with a confidence of ... -

- - - \ No newline at end of file +
+

+
+
+

+

+ KNN Classifier with mobileNet model labeled this as Class: + ... with a confidence of + ... +

+ + + diff --git a/week3-pose/PoseNet/index.html b/week3-pose/PoseNet/index.html index 3595ca2..862448f 100755 --- a/week3-pose/PoseNet/index.html +++ b/week3-pose/PoseNet/index.html @@ -6,21 +6,21 @@ --> + + + PoseNet example using p5.js - - - PoseNet example using p5.js - - - - - - - - -

PoseNet example using p5.js

-

Loading model...

- - + + + + + +

PoseNet example using p5.js

+

Loading model...

+ + diff --git a/week3-pose/PoseNet_KNNClassification/index.html b/week3-pose/PoseNet_KNNClassification/index.html index 05c1933..542ed0a 100755 --- a/week3-pose/PoseNet_KNNClassification/index.html +++ b/week3-pose/PoseNet_KNNClassification/index.html @@ -13,7 +13,7 @@ - + - - - - -

Style Transfer Image Example using p5.js

-

Loading Models...

- -

Input Image:

- input img - - - - - - - - + + + Style Transfer Image Example using p5.js + + + + + + + + + +

Style Transfer Image Example using p5.js

+

Loading Models...

+ +

Input Image:

+ input img + + + + + + + diff --git a/week5-styleTransfer/styleTransfer-ml5/StyleTransfer_Video/index.html b/week5-styleTransfer/styleTransfer-ml5/StyleTransfer_Video/index.html index 30fb2e2..d4df35d 100644 --- a/week5-styleTransfer/styleTransfer-ml5/StyleTransfer_Video/index.html +++ b/week5-styleTransfer/styleTransfer-ml5/StyleTransfer_Video/index.html @@ -6,35 +6,37 @@ --> - - - Style Transfer Mirror Example using p5.js + + + Style Transfer Mirror Example using p5.js - - - - - - + + + - + + - -

Style Transfer Mirror Example using p5.js

-

Loading model...

-

Sytle image:

- -
-
- - + + +

Style Transfer Mirror Example using p5.js

+

Loading model...

+

Sytle image:

+ +
+
+ + diff --git a/week6-pix2pix/pix2pix-ml5/Pix2Pix_callback/index.html b/week6-pix2pix/pix2pix-ml5/Pix2Pix_callback/index.html index abb1e9a..5eee890 100644 --- a/week6-pix2pix/pix2pix-ml5/Pix2Pix_callback/index.html +++ b/week6-pix2pix/pix2pix-ml5/Pix2Pix_callback/index.html @@ -6,51 +6,57 @@ --> - - - - Pix2Pix Edges2Pikachu Example - - - - - - - - - -

Pix2Pix Edges2Pichaku Example

-

1. Wait until the model is loaded

-

2. Press your mouse to draw a Pikachu on the left side of the canvas.

-

3. A colored Pikachu image will automatically appear on the right side of the canvas in ~2 seconds. You could also click the "Transfer" button to generate an new image.

-

4. You could click the "Clear" button to clear the canvas and draw again.

-

Loading Model... Please wait...

-
-
-
-
-
- + + + Pix2Pix Edges2Pikachu Example + + + + + + + + + +

Pix2Pix Edges2Pichaku Example

+

1. Wait until the model is loaded

+

2. Press your mouse to draw a Pikachu on the left side of the canvas.

+

+ 3. A colored Pikachu image will automatically appear on the right side of + the canvas in ~2 seconds. You could also click the "Transfer" button to + generate an new image. +

+

+ 4. You could click the "Clear" button to clear the canvas and draw again. +

+

Loading Model... Please wait...

+
+
+
+
+
+ +
+
+
-
-
-
-
- - - + + diff --git a/week7-runway/CycleGAN/libraries/p5.sound.js b/week7-runway/CycleGAN/libraries/p5.sound.js index 33b1304..80b238d 100644 --- a/week7-runway/CycleGAN/libraries/p5.sound.js +++ b/week7-runway/CycleGAN/libraries/p5.sound.js @@ -1,4 +1,4 @@ -/*! p5.sound.js v0.3.11 2019-03-14 */ +/*! p5.sound.js vlatest1 2019-03-14 */ /** * p5.sound extends p5 with Web Audio functionality including audio input, @@ -44,7 +44,7 @@ */ /** - * p5.sound + * p5.sound * https://p5js.org/reference/#/libraries/p5.sound * * From the Processing Foundation and contributors @@ -65,20 +65,20 @@ */ (function (root, factory) { - if (typeof define === 'function' && define.amd) - define('p5.sound', ['p5'], function (p5) { (factory(p5));}); - else if (typeof exports === 'object') - factory(require('../p5')); - else - factory(root['p5']); -}(this, function (p5) { - -var shims; -'use strict'; /** - * This module has shims - */ -shims = function () { - /* AudioContext Monkeypatch + if (typeof define === "function" && define.amd) + define("p5.sound", ["p5"], function (p5) { + factory(p5); + }); + else if (typeof exports === "object") factory(require("../p5")); + else factory(root["p5"]); +})(this, function (p5) { + var shims; + ("use strict"); + /** + * This module has shims + */ + shims = (function () { + /* AudioContext Monkeypatch Copyright 2013 Chris Wilson Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -90,100 +90,63 @@ shims = function () { See the License for the specific language governing permissions and limitations under the License. */ - (function () { - function fixSetTarget(param) { - if (!param) - // if NYI, just return - return; - if (!param.setTargetAtTime) - param.setTargetAtTime = param.setTargetValueAtTime; - } - if (window.hasOwnProperty('webkitAudioContext') && !window.hasOwnProperty('AudioContext')) { - window.AudioContext = window.webkitAudioContext; - if (typeof AudioContext.prototype.createGain !== 'function') - AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; - if (typeof AudioContext.prototype.createDelay !== 'function') - AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode; - if (typeof AudioContext.prototype.createScriptProcessor !== 'function') - AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode; - if (typeof AudioContext.prototype.createPeriodicWave !== 'function') - AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable; - AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain; - AudioContext.prototype.createGain = function () { - var node = this.internal_createGain(); - fixSetTarget(node.gain); - return node; - }; - AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay; - AudioContext.prototype.createDelay = function (maxDelayTime) { - var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay(); - fixSetTarget(node.delayTime); - return node; - }; - AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource; - AudioContext.prototype.createBufferSource = function () { - var node = this.internal_createBufferSource(); - if (!node.start) { - node.start = function (when, offset, duration) { - if (offset || duration) - this.noteGrainOn(when || 0, offset, duration); - else - this.noteOn(when || 0); - }; - } else { - node.internal_start = node.start; - node.start = function (when, offset, duration) { - if (typeof duration !== 'undefined') - node.internal_start(when || 0, offset, duration); - else - node.internal_start(when || 0, offset || 0); - }; - } - if (!node.stop) { - node.stop = function (when) { - this.noteOff(when || 0); - }; - } else { - node.internal_stop = node.stop; - node.stop = function (when) { - node.internal_stop(when || 0); - }; - } - fixSetTarget(node.playbackRate); - return node; - }; - AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor; - AudioContext.prototype.createDynamicsCompressor = function () { - var node = this.internal_createDynamicsCompressor(); - fixSetTarget(node.threshold); - fixSetTarget(node.knee); - fixSetTarget(node.ratio); - fixSetTarget(node.reduction); - fixSetTarget(node.attack); - fixSetTarget(node.release); - return node; - }; - AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter; - AudioContext.prototype.createBiquadFilter = function () { - var node = this.internal_createBiquadFilter(); - fixSetTarget(node.frequency); - fixSetTarget(node.detune); - fixSetTarget(node.Q); - fixSetTarget(node.gain); - return node; - }; - if (typeof AudioContext.prototype.createOscillator !== 'function') { - AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator; - AudioContext.prototype.createOscillator = function () { - var node = this.internal_createOscillator(); + (function () { + function fixSetTarget(param) { + if (!param) + // if NYI, just return + return; + if (!param.setTargetAtTime) + param.setTargetAtTime = param.setTargetValueAtTime; + } + if ( + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") + ) { + window.AudioContext = window.webkitAudioContext; + if (typeof AudioContext.prototype.createGain !== "function") + AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode; + if (typeof AudioContext.prototype.createDelay !== "function") + AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode; + if (typeof AudioContext.prototype.createScriptProcessor !== "function") + AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode; + if (typeof AudioContext.prototype.createPeriodicWave !== "function") + AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable; + AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain; + AudioContext.prototype.createGain = function () { + var node = this.internal_createGain(); + fixSetTarget(node.gain); + return node; + }; + AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay; + AudioContext.prototype.createDelay = function (maxDelayTime) { + var node = maxDelayTime + ? this.internal_createDelay(maxDelayTime) + : this.internal_createDelay(); + fixSetTarget(node.delayTime); + return node; + }; + AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource; + AudioContext.prototype.createBufferSource = function () { + var node = this.internal_createBufferSource(); if (!node.start) { - node.start = function (when) { - this.noteOn(when || 0); + node.start = function (when, offset, duration) { + if (offset || duration) + this.noteGrainOn(when || 0, offset, duration); + else this.noteOn(when || 0); }; } else { node.internal_start = node.start; - node.start = function (when) { - node.internal_start(when || 0); + node.start = function (when, offset, duration) { + if (typeof duration !== "undefined") + node.internal_start(when || 0, offset, duration); + else node.internal_start(when || 0, offset || 0); }; } if (!node.stop) { @@ -196,205 +159,267 @@ shims = function () { node.internal_stop(when || 0); }; } - if (!node.setPeriodicWave) - node.setPeriodicWave = node.setWaveTable; + fixSetTarget(node.playbackRate); + return node; + }; + AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor; + AudioContext.prototype.createDynamicsCompressor = function () { + var node = this.internal_createDynamicsCompressor(); + fixSetTarget(node.threshold); + fixSetTarget(node.knee); + fixSetTarget(node.ratio); + fixSetTarget(node.reduction); + fixSetTarget(node.attack); + fixSetTarget(node.release); + return node; + }; + AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter; + AudioContext.prototype.createBiquadFilter = function () { + var node = this.internal_createBiquadFilter(); fixSetTarget(node.frequency); fixSetTarget(node.detune); + fixSetTarget(node.Q); + fixSetTarget(node.gain); return node; }; - } - } - if (window.hasOwnProperty('webkitOfflineAudioContext') && !window.hasOwnProperty('OfflineAudioContext')) { - window.OfflineAudioContext = window.webkitOfflineAudioContext; - } - }(window)); - // <-- end MonkeyPatch. - // Polyfill for AudioIn, also handled by p5.dom createCapture - navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - /** - * Determine which filetypes are supported (inspired by buzz.js) - * The audio element (el) will only be used to test browser support for various audio formats - */ - var el = document.createElement('audio'); - p5.prototype.isSupported = function () { - return !!el.canPlayType; - }; - var isOGGSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"'); - }; - var isMP3Supported = function () { - return !!el.canPlayType && el.canPlayType('audio/mpeg;'); - }; - var isWAVSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"'); - }; - var isAACSupported = function () { - return !!el.canPlayType && (el.canPlayType('audio/x-m4a;') || el.canPlayType('audio/aac;')); - }; - var isAIFSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/x-aiff;'); - }; - p5.prototype.isFileSupported = function (extension) { - switch (extension.toLowerCase()) { - case 'mp3': - return isMP3Supported(); - case 'wav': - return isWAVSupported(); - case 'ogg': - return isOGGSupported(); - case 'aac': - case 'm4a': - case 'mp4': - return isAACSupported(); - case 'aif': - case 'aiff': - return isAIFSupported(); - default: - return false; - } - }; -}(); -var StartAudioContext; -(function (root, factory) { - if (true) { - StartAudioContext = function () { - return factory(); - }(); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(); - } else { - root.StartAudioContext = factory(); - } -}(this, function () { - var TapListener = function (element, context) { - this._dragged = false; - this._element = element; - this._bindedMove = this._moved.bind(this); - this._bindedEnd = this._ended.bind(this, context); - element.addEventListener('touchstart', this._bindedEnd); - element.addEventListener('touchmove', this._bindedMove); - element.addEventListener('touchend', this._bindedEnd); - element.addEventListener('mouseup', this._bindedEnd); - }; - TapListener.prototype._moved = function (e) { - this._dragged = true; - }; - TapListener.prototype._ended = function (context) { - if (!this._dragged) { - startContext(context); - } - this._dragged = false; - }; - TapListener.prototype.dispose = function () { - this._element.removeEventListener('touchstart', this._bindedEnd); - this._element.removeEventListener('touchmove', this._bindedMove); - this._element.removeEventListener('touchend', this._bindedEnd); - this._element.removeEventListener('mouseup', this._bindedEnd); - this._bindedMove = null; - this._bindedEnd = null; - this._element = null; - }; - function startContext(context) { - var buffer = context.createBuffer(1, 1, context.sampleRate); - var source = context.createBufferSource(); - source.buffer = buffer; - source.connect(context.destination); - source.start(0); - if (context.resume) { - context.resume(); - } - } - function isStarted(context) { - return context.state === 'running'; - } - function onStarted(context, callback) { - function checkLoop() { - if (isStarted(context)) { - callback(); - } else { - requestAnimationFrame(checkLoop); - if (context.resume) { - context.resume(); + if (typeof AudioContext.prototype.createOscillator !== "function") { + AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator; + AudioContext.prototype.createOscillator = function () { + var node = this.internal_createOscillator(); + if (!node.start) { + node.start = function (when) { + this.noteOn(when || 0); + }; + } else { + node.internal_start = node.start; + node.start = function (when) { + node.internal_start(when || 0); + }; + } + if (!node.stop) { + node.stop = function (when) { + this.noteOff(when || 0); + }; + } else { + node.internal_stop = node.stop; + node.stop = function (when) { + node.internal_stop(when || 0); + }; + } + if (!node.setPeriodicWave) node.setPeriodicWave = node.setWaveTable; + fixSetTarget(node.frequency); + fixSetTarget(node.detune); + return node; + }; } } - } - if (isStarted(context)) { - callback(); + if ( + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") + ) { + window.OfflineAudioContext = window.webkitOfflineAudioContext; + } + })(window); + // <-- end MonkeyPatch. + // Polyfill for AudioIn, also handled by p5.dom createCapture + navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia; + /** + * Determine which filetypes are supported (inspired by buzz.js) + * The audio element (el) will only be used to test browser support for various audio formats + */ + var el = document.createElement("audio"); + p5.prototype.isSupported = function () { + return !!el.canPlayType; + }; + var isOGGSupported = function () { + return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"'); + }; + var isMP3Supported = function () { + return !!el.canPlayType && el.canPlayType("audio/mpeg;"); + }; + var isWAVSupported = function () { + return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"'); + }; + var isAACSupported = function () { + return ( + !!el.canPlayType && + (el.canPlayType("audio/x-m4a;") || el.canPlayType("audio/aac;")) + ); + }; + var isAIFSupported = function () { + return !!el.canPlayType && el.canPlayType("audio/x-aiff;"); + }; + p5.prototype.isFileSupported = function (extension) { + switch (extension.toLowerCase()) { + case "mp3": + return isMP3Supported(); + case "wav": + return isWAVSupported(); + case "ogg": + return isOGGSupported(); + case "aac": + case "m4a": + case "mp4": + return isAACSupported(); + case "aif": + case "aiff": + return isAIFSupported(); + default: + return false; + } + }; + })(); + var StartAudioContext; + (function (root, factory) { + if (true) { + StartAudioContext = (function () { + return factory(); + })(); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(); } else { - checkLoop(); - } - } - function bindTapListener(element, tapListeners, context) { - if (Array.isArray(element) || NodeList && element instanceof NodeList) { - for (var i = 0; i < element.length; i++) { - bindTapListener(element[i], tapListeners, context); - } - } else if (typeof element === 'string') { - bindTapListener(document.querySelectorAll(element), tapListeners, context); - } else if (element.jquery && typeof element.toArray === 'function') { - bindTapListener(element.toArray(), tapListeners, context); - } else if (Element && element instanceof Element) { - var tap = new TapListener(element, context); - tapListeners.push(tap); - } - } - function StartAudioContext(context, elements, callback) { - var promise = new Promise(function (success) { - onStarted(context, success); - }); - var tapListeners = []; - if (!elements) { - elements = document.body; - } - bindTapListener(elements, tapListeners, context); - promise.then(function () { - for (var i = 0; i < tapListeners.length; i++) { - tapListeners[i].dispose(); + root.StartAudioContext = factory(); + } + })(this, function () { + var TapListener = function (element, context) { + this._dragged = false; + this._element = element; + this._bindedMove = this._moved.bind(this); + this._bindedEnd = this._ended.bind(this, context); + element.addEventListener("touchstart", this._bindedEnd); + element.addEventListener("touchmove", this._bindedMove); + element.addEventListener("touchend", this._bindedEnd); + element.addEventListener("mouseup", this._bindedEnd); + }; + TapListener.prototype._moved = function (e) { + this._dragged = true; + }; + TapListener.prototype._ended = function (context) { + if (!this._dragged) { + startContext(context); + } + this._dragged = false; + }; + TapListener.prototype.dispose = function () { + this._element.removeEventListener("touchstart", this._bindedEnd); + this._element.removeEventListener("touchmove", this._bindedMove); + this._element.removeEventListener("touchend", this._bindedEnd); + this._element.removeEventListener("mouseup", this._bindedEnd); + this._bindedMove = null; + this._bindedEnd = null; + this._element = null; + }; + function startContext(context) { + var buffer = context.createBuffer(1, 1, context.sampleRate); + var source = context.createBufferSource(); + source.buffer = buffer; + source.connect(context.destination); + source.start(0); + if (context.resume) { + context.resume(); + } + } + function isStarted(context) { + return context.state === "running"; + } + function onStarted(context, callback) { + function checkLoop() { + if (isStarted(context)) { + callback(); + } else { + requestAnimationFrame(checkLoop); + if (context.resume) { + context.resume(); + } + } } - tapListeners = null; - if (callback) { + if (isStarted(context)) { callback(); + } else { + checkLoop(); } - }); - return promise; - } - return StartAudioContext; -})); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Tone; -Tone_core_Tone = function () { - 'use strict'; - var Tone = function (inputs, outputs) { - if (this.isUndef(inputs) || inputs === 1) { - this.input = this.context.createGain(); - } else if (inputs > 1) { - this.input = new Array(inputs); } - if (this.isUndef(outputs) || outputs === 1) { - this.output = this.context.createGain(); - } else if (outputs > 1) { - this.output = new Array(inputs); - } - }; - Tone.prototype.set = function (params, value, rampTime) { - if (this.isObject(params)) { - rampTime = value; - } else if (this.isString(params)) { - var tmpObj = {}; - tmpObj[params] = value; - params = tmpObj; + function bindTapListener(element, tapListeners, context) { + if (Array.isArray(element) || (NodeList && element instanceof NodeList)) { + for (var i = 0; i < element.length; i++) { + bindTapListener(element[i], tapListeners, context); + } + } else if (typeof element === "string") { + bindTapListener( + document.querySelectorAll(element), + tapListeners, + context + ); + } else if (element.jquery && typeof element.toArray === "function") { + bindTapListener(element.toArray(), tapListeners, context); + } else if (Element && element instanceof Element) { + var tap = new TapListener(element, context); + tapListeners.push(tap); + } + } + function StartAudioContext(context, elements, callback) { + var promise = new Promise(function (success) { + onStarted(context, success); + }); + var tapListeners = []; + if (!elements) { + elements = document.body; + } + bindTapListener(elements, tapListeners, context); + promise.then(function () { + for (var i = 0; i < tapListeners.length; i++) { + tapListeners[i].dispose(); + } + tapListeners = null; + if (callback) { + callback(); + } + }); + return promise; } - paramLoop: - for (var attr in params) { + return StartAudioContext; + }); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Tone; + Tone_core_Tone = (function () { + "use strict"; + var Tone = function (inputs, outputs) { + if (this.isUndef(inputs) || inputs === 1) { + this.input = this.context.createGain(); + } else if (inputs > 1) { + this.input = new Array(inputs); + } + if (this.isUndef(outputs) || outputs === 1) { + this.output = this.context.createGain(); + } else if (outputs > 1) { + this.output = new Array(inputs); + } + }; + Tone.prototype.set = function (params, value, rampTime) { + if (this.isObject(params)) { + rampTime = value; + } else if (this.isString(params)) { + var tmpObj = {}; + tmpObj[params] = value; + params = tmpObj; + } + paramLoop: for (var attr in params) { value = params[attr]; var parent = this; - if (attr.indexOf('.') !== -1) { - var attrSplit = attr.split('.'); + if (attr.indexOf(".") !== -1) { + var attrSplit = attr.split("."); for (var i = 0; i < attrSplit.length - 1; i++) { parent = parent[attrSplit[i]]; if (parent instanceof Tone) { attrSplit.splice(0, i + 1); - var innerParam = attrSplit.join('.'); + var innerParam = attrSplit.join("."); parent.set(innerParam, value); continue paramLoop; } @@ -405,7 +430,10 @@ Tone_core_Tone = function () { if (this.isUndef(param)) { continue; } - if (Tone.Signal && param instanceof Tone.Signal || Tone.Param && param instanceof Tone.Param) { + if ( + (Tone.Signal && param instanceof Tone.Signal) || + (Tone.Param && param instanceof Tone.Param) + ) { if (param.value !== value) { if (this.isUndef(rampTime)) { param.value = value; @@ -423,1089 +451,1116 @@ Tone_core_Tone = function () { parent[attr] = value; } } - return this; - }; - Tone.prototype.get = function (params) { - if (this.isUndef(params)) { - params = this._collectDefaults(this.constructor); - } else if (this.isString(params)) { - params = [params]; - } - var ret = {}; - for (var i = 0; i < params.length; i++) { - var attr = params[i]; - var parent = this; - var subRet = ret; - if (attr.indexOf('.') !== -1) { - var attrSplit = attr.split('.'); - for (var j = 0; j < attrSplit.length - 1; j++) { - var subAttr = attrSplit[j]; - subRet[subAttr] = subRet[subAttr] || {}; - subRet = subRet[subAttr]; - parent = parent[subAttr]; - } - attr = attrSplit[attrSplit.length - 1]; - } - var param = parent[attr]; - if (this.isObject(params[attr])) { - subRet[attr] = param.get(); - } else if (Tone.Signal && param instanceof Tone.Signal) { - subRet[attr] = param.value; - } else if (Tone.Param && param instanceof Tone.Param) { - subRet[attr] = param.value; - } else if (param instanceof AudioParam) { - subRet[attr] = param.value; - } else if (param instanceof Tone) { - subRet[attr] = param.get(); - } else if (!this.isFunction(param) && !this.isUndef(param)) { - subRet[attr] = param; + return this; + }; + Tone.prototype.get = function (params) { + if (this.isUndef(params)) { + params = this._collectDefaults(this.constructor); + } else if (this.isString(params)) { + params = [params]; } - } - return ret; - }; - Tone.prototype._collectDefaults = function (constr) { - var ret = []; - if (!this.isUndef(constr.defaults)) { - ret = Object.keys(constr.defaults); - } - if (!this.isUndef(constr._super)) { - var superDefs = this._collectDefaults(constr._super); - for (var i = 0; i < superDefs.length; i++) { - if (ret.indexOf(superDefs[i]) === -1) { - ret.push(superDefs[i]); + var ret = {}; + for (var i = 0; i < params.length; i++) { + var attr = params[i]; + var parent = this; + var subRet = ret; + if (attr.indexOf(".") !== -1) { + var attrSplit = attr.split("."); + for (var j = 0; j < attrSplit.length - 1; j++) { + var subAttr = attrSplit[j]; + subRet[subAttr] = subRet[subAttr] || {}; + subRet = subRet[subAttr]; + parent = parent[subAttr]; + } + attr = attrSplit[attrSplit.length - 1]; + } + var param = parent[attr]; + if (this.isObject(params[attr])) { + subRet[attr] = param.get(); + } else if (Tone.Signal && param instanceof Tone.Signal) { + subRet[attr] = param.value; + } else if (Tone.Param && param instanceof Tone.Param) { + subRet[attr] = param.value; + } else if (param instanceof AudioParam) { + subRet[attr] = param.value; + } else if (param instanceof Tone) { + subRet[attr] = param.get(); + } else if (!this.isFunction(param) && !this.isUndef(param)) { + subRet[attr] = param; } } - } - return ret; - }; - Tone.prototype.toString = function () { - for (var className in Tone) { - var isLetter = className[0].match(/^[A-Z]$/); - var sameConstructor = Tone[className] === this.constructor; - if (this.isFunction(Tone[className]) && isLetter && sameConstructor) { - return className; + return ret; + }; + Tone.prototype._collectDefaults = function (constr) { + var ret = []; + if (!this.isUndef(constr.defaults)) { + ret = Object.keys(constr.defaults); + } + if (!this.isUndef(constr._super)) { + var superDefs = this._collectDefaults(constr._super); + for (var i = 0; i < superDefs.length; i++) { + if (ret.indexOf(superDefs[i]) === -1) { + ret.push(superDefs[i]); + } + } } - } - return 'Tone'; - }; - Object.defineProperty(Tone.prototype, 'numberOfInputs', { - get: function () { - if (this.input) { - if (this.isArray(this.input)) { - return this.input.length; - } else { - return 1; + return ret; + }; + Tone.prototype.toString = function () { + for (var className in Tone) { + var isLetter = className[0].match(/^[A-Z]$/); + var sameConstructor = Tone[className] === this.constructor; + if (this.isFunction(Tone[className]) && isLetter && sameConstructor) { + return className; } - } else { - return 0; } - } - }); - Object.defineProperty(Tone.prototype, 'numberOfOutputs', { - get: function () { - if (this.output) { - if (this.isArray(this.output)) { - return this.output.length; + return "Tone"; + }; + Object.defineProperty(Tone.prototype, "numberOfInputs", { + get: function () { + if (this.input) { + if (this.isArray(this.input)) { + return this.input.length; + } else { + return 1; + } } else { - return 1; + return 0; } - } else { - return 0; - } - } - }); - Tone.prototype.dispose = function () { - if (!this.isUndef(this.input)) { - if (this.input instanceof AudioNode) { - this.input.disconnect(); + }, + }); + Object.defineProperty(Tone.prototype, "numberOfOutputs", { + get: function () { + if (this.output) { + if (this.isArray(this.output)) { + return this.output.length; + } else { + return 1; + } + } else { + return 0; + } + }, + }); + Tone.prototype.dispose = function () { + if (!this.isUndef(this.input)) { + if (this.input instanceof AudioNode) { + this.input.disconnect(); + } + this.input = null; } - this.input = null; - } - if (!this.isUndef(this.output)) { - if (this.output instanceof AudioNode) { - this.output.disconnect(); + if (!this.isUndef(this.output)) { + if (this.output instanceof AudioNode) { + this.output.disconnect(); + } + this.output = null; } - this.output = null; - } - return this; - }; - Tone.prototype.connect = function (unit, outputNum, inputNum) { - if (Array.isArray(this.output)) { - outputNum = this.defaultArg(outputNum, 0); - this.output[outputNum].connect(unit, 0, inputNum); - } else { - this.output.connect(unit, outputNum, inputNum); - } - return this; - }; - Tone.prototype.disconnect = function (destination, outputNum, inputNum) { - if (this.isArray(this.output)) { - if (this.isNumber(destination)) { - this.output[destination].disconnect(); - } else { + return this; + }; + Tone.prototype.connect = function (unit, outputNum, inputNum) { + if (Array.isArray(this.output)) { outputNum = this.defaultArg(outputNum, 0); - this.output[outputNum].disconnect(destination, 0, inputNum); - } - } else { - this.output.disconnect.apply(this.output, arguments); - } - }; - Tone.prototype.connectSeries = function () { - if (arguments.length > 1) { - var currentUnit = arguments[0]; - for (var i = 1; i < arguments.length; i++) { - var toUnit = arguments[i]; - currentUnit.connect(toUnit); - currentUnit = toUnit; + this.output[outputNum].connect(unit, 0, inputNum); + } else { + this.output.connect(unit, outputNum, inputNum); } - } - return this; - }; - Tone.prototype.chain = function () { - if (arguments.length > 0) { - var currentUnit = this; - for (var i = 0; i < arguments.length; i++) { - var toUnit = arguments[i]; - currentUnit.connect(toUnit); - currentUnit = toUnit; + return this; + }; + Tone.prototype.disconnect = function (destination, outputNum, inputNum) { + if (this.isArray(this.output)) { + if (this.isNumber(destination)) { + this.output[destination].disconnect(); + } else { + outputNum = this.defaultArg(outputNum, 0); + this.output[outputNum].disconnect(destination, 0, inputNum); + } + } else { + this.output.disconnect.apply(this.output, arguments); } - } - return this; - }; - Tone.prototype.fan = function () { - if (arguments.length > 0) { - for (var i = 0; i < arguments.length; i++) { - this.connect(arguments[i]); + }; + Tone.prototype.connectSeries = function () { + if (arguments.length > 1) { + var currentUnit = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + var toUnit = arguments[i]; + currentUnit.connect(toUnit); + currentUnit = toUnit; + } } - } - return this; - }; - AudioNode.prototype.chain = Tone.prototype.chain; - AudioNode.prototype.fan = Tone.prototype.fan; - Tone.prototype.defaultArg = function (given, fallback) { - if (this.isObject(given) && this.isObject(fallback)) { - var ret = {}; - for (var givenProp in given) { - ret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]); + return this; + }; + Tone.prototype.chain = function () { + if (arguments.length > 0) { + var currentUnit = this; + for (var i = 0; i < arguments.length; i++) { + var toUnit = arguments[i]; + currentUnit.connect(toUnit); + currentUnit = toUnit; + } } - for (var fallbackProp in fallback) { - ret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]); + return this; + }; + Tone.prototype.fan = function () { + if (arguments.length > 0) { + for (var i = 0; i < arguments.length; i++) { + this.connect(arguments[i]); + } } - return ret; - } else { - return this.isUndef(given) ? fallback : given; - } - }; - Tone.prototype.optionsObject = function (values, keys, defaults) { - var options = {}; - if (values.length === 1 && this.isObject(values[0])) { - options = values[0]; - } else { - for (var i = 0; i < keys.length; i++) { - options[keys[i]] = values[i]; + return this; + }; + AudioNode.prototype.chain = Tone.prototype.chain; + AudioNode.prototype.fan = Tone.prototype.fan; + Tone.prototype.defaultArg = function (given, fallback) { + if (this.isObject(given) && this.isObject(fallback)) { + var ret = {}; + for (var givenProp in given) { + ret[givenProp] = this.defaultArg( + fallback[givenProp], + given[givenProp] + ); + } + for (var fallbackProp in fallback) { + ret[fallbackProp] = this.defaultArg( + given[fallbackProp], + fallback[fallbackProp] + ); + } + return ret; + } else { + return this.isUndef(given) ? fallback : given; } - } - if (!this.isUndef(defaults)) { - return this.defaultArg(options, defaults); - } else { - return options; - } - }; - Tone.prototype.isUndef = function (val) { - return typeof val === 'undefined'; - }; - Tone.prototype.isFunction = function (val) { - return typeof val === 'function'; - }; - Tone.prototype.isNumber = function (arg) { - return typeof arg === 'number'; - }; - Tone.prototype.isObject = function (arg) { - return Object.prototype.toString.call(arg) === '[object Object]' && arg.constructor === Object; - }; - Tone.prototype.isBoolean = function (arg) { - return typeof arg === 'boolean'; - }; - Tone.prototype.isArray = function (arg) { - return Array.isArray(arg); - }; - Tone.prototype.isString = function (arg) { - return typeof arg === 'string'; - }; - Tone.noOp = function () { - }; - Tone.prototype._readOnly = function (property) { - if (Array.isArray(property)) { - for (var i = 0; i < property.length; i++) { - this._readOnly(property[i]); + }; + Tone.prototype.optionsObject = function (values, keys, defaults) { + var options = {}; + if (values.length === 1 && this.isObject(values[0])) { + options = values[0]; + } else { + for (var i = 0; i < keys.length; i++) { + options[keys[i]] = values[i]; + } } - } else { - Object.defineProperty(this, property, { - writable: false, - enumerable: true - }); - } - }; - Tone.prototype._writable = function (property) { - if (Array.isArray(property)) { - for (var i = 0; i < property.length; i++) { - this._writable(property[i]); + if (!this.isUndef(defaults)) { + return this.defaultArg(options, defaults); + } else { + return options; } - } else { - Object.defineProperty(this, property, { writable: true }); - } - }; - Tone.State = { - Started: 'started', - Stopped: 'stopped', - Paused: 'paused' - }; - Tone.prototype.equalPowerScale = function (percent) { - var piFactor = 0.5 * Math.PI; - return Math.sin(percent * piFactor); - }; - Tone.prototype.dbToGain = function (db) { - return Math.pow(2, db / 6); - }; - Tone.prototype.gainToDb = function (gain) { - return 20 * (Math.log(gain) / Math.LN10); - }; - Tone.prototype.intervalToFrequencyRatio = function (interval) { - return Math.pow(2, interval / 12); - }; - Tone.prototype.now = function () { - return Tone.context.now(); - }; - Tone.now = function () { - return Tone.context.now(); - }; - Tone.extend = function (child, parent) { - if (Tone.prototype.isUndef(parent)) { - parent = Tone; - } - function TempConstructor() { - } - TempConstructor.prototype = parent.prototype; - child.prototype = new TempConstructor(); - child.prototype.constructor = child; - child._super = parent; - }; - var audioContext; - Object.defineProperty(Tone, 'context', { - get: function () { - return audioContext; - }, - set: function (context) { - if (Tone.Context && context instanceof Tone.Context) { - audioContext = context; + }; + Tone.prototype.isUndef = function (val) { + return typeof val === "undefined"; + }; + Tone.prototype.isFunction = function (val) { + return typeof val === "function"; + }; + Tone.prototype.isNumber = function (arg) { + return typeof arg === "number"; + }; + Tone.prototype.isObject = function (arg) { + return ( + Object.prototype.toString.call(arg) === "[object Object]" && + arg.constructor === Object + ); + }; + Tone.prototype.isBoolean = function (arg) { + return typeof arg === "boolean"; + }; + Tone.prototype.isArray = function (arg) { + return Array.isArray(arg); + }; + Tone.prototype.isString = function (arg) { + return typeof arg === "string"; + }; + Tone.noOp = function () {}; + Tone.prototype._readOnly = function (property) { + if (Array.isArray(property)) { + for (var i = 0; i < property.length; i++) { + this._readOnly(property[i]); + } } else { - audioContext = new Tone.Context(context); + Object.defineProperty(this, property, { + writable: false, + enumerable: true, + }); } - if (Tone.Context) { - Tone.Context.emit('init', audioContext); + }; + Tone.prototype._writable = function (property) { + if (Array.isArray(property)) { + for (var i = 0; i < property.length; i++) { + this._writable(property[i]); + } + } else { + Object.defineProperty(this, property, { writable: true }); } - } - }); - Object.defineProperty(Tone.prototype, 'context', { - get: function () { - return Tone.context; - } - }); - Tone.setContext = function (ctx) { - Tone.context = ctx; - }; - Object.defineProperty(Tone.prototype, 'blockTime', { - get: function () { - return 128 / this.context.sampleRate; - } - }); - Object.defineProperty(Tone.prototype, 'sampleTime', { - get: function () { - return 1 / this.context.sampleRate; - } - }); - Object.defineProperty(Tone, 'supported', { - get: function () { - var hasAudioContext = window.hasOwnProperty('AudioContext') || window.hasOwnProperty('webkitAudioContext'); - var hasPromises = window.hasOwnProperty('Promise'); - var hasWorkers = window.hasOwnProperty('Worker'); - return hasAudioContext && hasPromises && hasWorkers; - } - }); - Tone.version = 'r10'; - if (!window.TONE_SILENCE_VERSION_LOGGING) { - } - return Tone; -}(); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Emitter; -Tone_core_Emitter = function (Tone) { - 'use strict'; - Tone.Emitter = function () { - this._events = {}; - }; - Tone.extend(Tone.Emitter); - Tone.Emitter.prototype.on = function (event, callback) { - var events = event.split(/\W+/); - for (var i = 0; i < events.length; i++) { - var eventName = events[i]; - if (!this._events.hasOwnProperty(eventName)) { - this._events[eventName] = []; - } - this._events[eventName].push(callback); - } - return this; - }; - Tone.Emitter.prototype.off = function (event, callback) { - var events = event.split(/\W+/); - for (var ev = 0; ev < events.length; ev++) { - event = events[ev]; - if (this._events.hasOwnProperty(event)) { - if (Tone.prototype.isUndef(callback)) { - this._events[event] = []; + }; + Tone.State = { + Started: "started", + Stopped: "stopped", + Paused: "paused", + }; + Tone.prototype.equalPowerScale = function (percent) { + var piFactor = 0.5 * Math.PI; + return Math.sin(percent * piFactor); + }; + Tone.prototype.dbToGain = function (db) { + return Math.pow(2, db / 6); + }; + Tone.prototype.gainToDb = function (gain) { + return 20 * (Math.log(gain) / Math.LN10); + }; + Tone.prototype.intervalToFrequencyRatio = function (interval) { + return Math.pow(2, interval / 12); + }; + Tone.prototype.now = function () { + return Tone.context.now(); + }; + Tone.now = function () { + return Tone.context.now(); + }; + Tone.extend = function (child, parent) { + if (Tone.prototype.isUndef(parent)) { + parent = Tone; + } + function TempConstructor() {} + TempConstructor.prototype = parent.prototype; + child.prototype = new TempConstructor(); + child.prototype.constructor = child; + child._super = parent; + }; + var audioContext; + Object.defineProperty(Tone, "context", { + get: function () { + return audioContext; + }, + set: function (context) { + if (Tone.Context && context instanceof Tone.Context) { + audioContext = context; } else { - var eventList = this._events[event]; - for (var i = 0; i < eventList.length; i++) { - if (eventList[i] === callback) { - eventList.splice(i, 1); + audioContext = new Tone.Context(context); + } + if (Tone.Context) { + Tone.Context.emit("init", audioContext); + } + }, + }); + Object.defineProperty(Tone.prototype, "context", { + get: function () { + return Tone.context; + }, + }); + Tone.setContext = function (ctx) { + Tone.context = ctx; + }; + Object.defineProperty(Tone.prototype, "blockTime", { + get: function () { + return 128 / this.context.sampleRate; + }, + }); + Object.defineProperty(Tone.prototype, "sampleTime", { + get: function () { + return 1 / this.context.sampleRate; + }, + }); + Object.defineProperty(Tone, "supported", { + get: function () { + var hasAudioContext = + window.hasOwnProperty("AudioContext") || + window.hasOwnProperty("webkitAudioContext"); + var hasPromises = window.hasOwnProperty("Promise"); + var hasWorkers = window.hasOwnProperty("Worker"); + return hasAudioContext && hasPromises && hasWorkers; + }, + }); + Tone.version = "r10"; + if (!window.TONE_SILENCE_VERSION_LOGGING) { + } + return Tone; + })(); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Emitter; + Tone_core_Emitter = (function (Tone) { + "use strict"; + Tone.Emitter = function () { + this._events = {}; + }; + Tone.extend(Tone.Emitter); + Tone.Emitter.prototype.on = function (event, callback) { + var events = event.split(/\W+/); + for (var i = 0; i < events.length; i++) { + var eventName = events[i]; + if (!this._events.hasOwnProperty(eventName)) { + this._events[eventName] = []; + } + this._events[eventName].push(callback); + } + return this; + }; + Tone.Emitter.prototype.off = function (event, callback) { + var events = event.split(/\W+/); + for (var ev = 0; ev < events.length; ev++) { + event = events[ev]; + if (this._events.hasOwnProperty(event)) { + if (Tone.prototype.isUndef(callback)) { + this._events[event] = []; + } else { + var eventList = this._events[event]; + for (var i = 0; i < eventList.length; i++) { + if (eventList[i] === callback) { + eventList.splice(i, 1); + } } } } } - } - return this; - }; - Tone.Emitter.prototype.emit = function (event) { - if (this._events) { - var args = Array.apply(null, arguments).slice(1); - if (this._events.hasOwnProperty(event)) { - var eventList = this._events[event]; - for (var i = 0, len = eventList.length; i < len; i++) { - eventList[i].apply(this, args); + return this; + }; + Tone.Emitter.prototype.emit = function (event) { + if (this._events) { + var args = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(event)) { + var eventList = this._events[event]; + for (var i = 0, len = eventList.length; i < len; i++) { + eventList[i].apply(this, args); + } } } + return this; + }; + Tone.Emitter.mixin = function (object) { + var functions = ["on", "off", "emit"]; + object._events = {}; + for (var i = 0; i < functions.length; i++) { + var func = functions[i]; + var emitterFunc = Tone.Emitter.prototype[func]; + object[func] = emitterFunc; + } + }; + Tone.Emitter.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._events = null; + return this; + }; + return Tone.Emitter; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Context; + Tone_core_Context = (function (Tone) { + if ( + !window.hasOwnProperty("AudioContext") && + window.hasOwnProperty("webkitAudioContext") + ) { + window.AudioContext = window.webkitAudioContext; } - return this; - }; - Tone.Emitter.mixin = function (object) { - var functions = [ - 'on', - 'off', - 'emit' - ]; - object._events = {}; - for (var i = 0; i < functions.length; i++) { - var func = functions[i]; - var emitterFunc = Tone.Emitter.prototype[func]; - object[func] = emitterFunc; - } - }; - Tone.Emitter.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._events = null; - return this; - }; - return Tone.Emitter; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Context; -Tone_core_Context = function (Tone) { - if (!window.hasOwnProperty('AudioContext') && window.hasOwnProperty('webkitAudioContext')) { - window.AudioContext = window.webkitAudioContext; - } - Tone.Context = function (context) { - Tone.Emitter.call(this); - if (!context) { - context = new window.AudioContext(); - } - this._context = context; - for (var prop in this._context) { - this._defineProperty(this._context, prop); - } - this._latencyHint = 'interactive'; - this._lookAhead = 0.1; - this._updateInterval = this._lookAhead / 3; - this._computedUpdateInterval = 0; - this._worker = this._createWorker(); - this._constants = {}; - }; - Tone.extend(Tone.Context, Tone.Emitter); - Tone.Emitter.mixin(Tone.Context); - Tone.Context.prototype._defineProperty = function (context, prop) { - if (this.isUndef(this[prop])) { - Object.defineProperty(this, prop, { - get: function () { - if (typeof context[prop] === 'function') { - return context[prop].bind(context); - } else { - return context[prop]; + Tone.Context = function (context) { + Tone.Emitter.call(this); + if (!context) { + context = new window.AudioContext(); + } + this._context = context; + for (var prop in this._context) { + this._defineProperty(this._context, prop); + } + this._latencyHint = "interactive"; + this._lookAhead = 0.1; + this._updateInterval = this._lookAhead / 3; + this._computedUpdateInterval = 0; + this._worker = this._createWorker(); + this._constants = {}; + }; + Tone.extend(Tone.Context, Tone.Emitter); + Tone.Emitter.mixin(Tone.Context); + Tone.Context.prototype._defineProperty = function (context, prop) { + if (this.isUndef(this[prop])) { + Object.defineProperty(this, prop, { + get: function () { + if (typeof context[prop] === "function") { + return context[prop].bind(context); + } else { + return context[prop]; + } + }, + set: function (val) { + context[prop] = val; + }, + }); + } + }; + Tone.Context.prototype.now = function () { + return this._context.currentTime; + }; + Tone.Context.prototype._createWorker = function () { + window.URL = window.URL || window.webkitURL; + var blob = new Blob([ + "var timeoutTime = " + + (this._updateInterval * 1000).toFixed(1) + + ";" + + "self.onmessage = function(msg){" + + "\ttimeoutTime = parseInt(msg.data);" + + "};" + + "function tick(){" + + "\tsetTimeout(tick, timeoutTime);" + + "\tself.postMessage('tick');" + + "}" + + "tick();", + ]); + var blobUrl = URL.createObjectURL(blob); + var worker = new Worker(blobUrl); + worker.addEventListener( + "message", + function () { + this.emit("tick"); + }.bind(this) + ); + worker.addEventListener( + "message", + function () { + var now = this.now(); + if (this.isNumber(this._lastUpdate)) { + var diff = now - this._lastUpdate; + this._computedUpdateInterval = Math.max( + diff, + this._computedUpdateInterval * 0.97 + ); } - }, - set: function (val) { - context[prop] = val; + this._lastUpdate = now; + }.bind(this) + ); + return worker; + }; + Tone.Context.prototype.getConstant = function (val) { + if (this._constants[val]) { + return this._constants[val]; + } else { + var buffer = this._context.createBuffer( + 1, + 128, + this._context.sampleRate + ); + var arr = buffer.getChannelData(0); + for (var i = 0; i < arr.length; i++) { + arr[i] = val; } - }); - } - }; - Tone.Context.prototype.now = function () { - return this._context.currentTime; - }; - Tone.Context.prototype._createWorker = function () { - window.URL = window.URL || window.webkitURL; - var blob = new Blob(['var timeoutTime = ' + (this._updateInterval * 1000).toFixed(1) + ';' + 'self.onmessage = function(msg){' + '\ttimeoutTime = parseInt(msg.data);' + '};' + 'function tick(){' + '\tsetTimeout(tick, timeoutTime);' + '\tself.postMessage(\'tick\');' + '}' + 'tick();']); - var blobUrl = URL.createObjectURL(blob); - var worker = new Worker(blobUrl); - worker.addEventListener('message', function () { - this.emit('tick'); - }.bind(this)); - worker.addEventListener('message', function () { - var now = this.now(); - if (this.isNumber(this._lastUpdate)) { - var diff = now - this._lastUpdate; - this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97); - } - this._lastUpdate = now; - }.bind(this)); - return worker; - }; - Tone.Context.prototype.getConstant = function (val) { - if (this._constants[val]) { - return this._constants[val]; - } else { - var buffer = this._context.createBuffer(1, 128, this._context.sampleRate); - var arr = buffer.getChannelData(0); - for (var i = 0; i < arr.length; i++) { - arr[i] = val; - } - var constant = this._context.createBufferSource(); - constant.channelCount = 1; - constant.channelCountMode = 'explicit'; - constant.buffer = buffer; - constant.loop = true; - constant.start(0); - this._constants[val] = constant; - return constant; - } - }; - Object.defineProperty(Tone.Context.prototype, 'lag', { - get: function () { - var diff = this._computedUpdateInterval - this._updateInterval; - diff = Math.max(diff, 0); - return diff; - } - }); - Object.defineProperty(Tone.Context.prototype, 'lookAhead', { - get: function () { - return this._lookAhead; - }, - set: function (lA) { - this._lookAhead = lA; - } - }); - Object.defineProperty(Tone.Context.prototype, 'updateInterval', { - get: function () { - return this._updateInterval; - }, - set: function (interval) { - this._updateInterval = Math.max(interval, Tone.prototype.blockTime); - this._worker.postMessage(Math.max(interval * 1000, 1)); - } - }); - Object.defineProperty(Tone.Context.prototype, 'latencyHint', { - get: function () { - return this._latencyHint; - }, - set: function (hint) { - var lookAhead = hint; - this._latencyHint = hint; - if (this.isString(hint)) { - switch (hint) { - case 'interactive': - lookAhead = 0.1; - this._context.latencyHint = hint; - break; - case 'playback': - lookAhead = 0.8; - this._context.latencyHint = hint; - break; - case 'balanced': - lookAhead = 0.25; - this._context.latencyHint = hint; - break; - case 'fastest': - lookAhead = 0.01; - break; + var constant = this._context.createBufferSource(); + constant.channelCount = 1; + constant.channelCountMode = "explicit"; + constant.buffer = buffer; + constant.loop = true; + constant.start(0); + this._constants[val] = constant; + return constant; + } + }; + Object.defineProperty(Tone.Context.prototype, "lag", { + get: function () { + var diff = this._computedUpdateInterval - this._updateInterval; + diff = Math.max(diff, 0); + return diff; + }, + }); + Object.defineProperty(Tone.Context.prototype, "lookAhead", { + get: function () { + return this._lookAhead; + }, + set: function (lA) { + this._lookAhead = lA; + }, + }); + Object.defineProperty(Tone.Context.prototype, "updateInterval", { + get: function () { + return this._updateInterval; + }, + set: function (interval) { + this._updateInterval = Math.max(interval, Tone.prototype.blockTime); + this._worker.postMessage(Math.max(interval * 1000, 1)); + }, + }); + Object.defineProperty(Tone.Context.prototype, "latencyHint", { + get: function () { + return this._latencyHint; + }, + set: function (hint) { + var lookAhead = hint; + this._latencyHint = hint; + if (this.isString(hint)) { + switch (hint) { + case "interactive": + lookAhead = 0.1; + this._context.latencyHint = hint; + break; + case "playback": + lookAhead = 0.8; + this._context.latencyHint = hint; + break; + case "balanced": + lookAhead = 0.25; + this._context.latencyHint = hint; + break; + case "fastest": + lookAhead = 0.01; + break; + } + } + this.lookAhead = lookAhead; + this.updateInterval = lookAhead / 3; + }, + }); + function shimConnect() { + var nativeConnect = AudioNode.prototype.connect; + var nativeDisconnect = AudioNode.prototype.disconnect; + function toneConnect(B, outNum, inNum) { + if (B.input) { + if (Array.isArray(B.input)) { + if (Tone.prototype.isUndef(inNum)) { + inNum = 0; + } + this.connect(B.input[inNum]); + } else { + this.connect(B.input, outNum, inNum); + } + } else { + try { + if (B instanceof AudioNode) { + nativeConnect.call(this, B, outNum, inNum); + } else { + nativeConnect.call(this, B, outNum); + } + } catch (e) { + throw new Error("error connecting to node: " + B + "\n" + e); + } } } - this.lookAhead = lookAhead; - this.updateInterval = lookAhead / 3; - } - }); - function shimConnect() { - var nativeConnect = AudioNode.prototype.connect; - var nativeDisconnect = AudioNode.prototype.disconnect; - function toneConnect(B, outNum, inNum) { - if (B.input) { - if (Array.isArray(B.input)) { + function toneDisconnect(B, outNum, inNum) { + if (B && B.input && Array.isArray(B.input)) { if (Tone.prototype.isUndef(inNum)) { inNum = 0; } - this.connect(B.input[inNum]); + this.disconnect(B.input[inNum], outNum, inNum); + } else if (B && B.input) { + this.disconnect(B.input, outNum, inNum); } else { - this.connect(B.input, outNum, inNum); - } - } else { - try { - if (B instanceof AudioNode) { - nativeConnect.call(this, B, outNum, inNum); - } else { - nativeConnect.call(this, B, outNum); + try { + nativeDisconnect.apply(this, arguments); + } catch (e) { + throw new Error("error disconnecting node: " + B + "\n" + e); } - } catch (e) { - throw new Error('error connecting to node: ' + B + '\n' + e); } } - } - function toneDisconnect(B, outNum, inNum) { - if (B && B.input && Array.isArray(B.input)) { - if (Tone.prototype.isUndef(inNum)) { - inNum = 0; - } - this.disconnect(B.input[inNum], outNum, inNum); - } else if (B && B.input) { - this.disconnect(B.input, outNum, inNum); - } else { - try { - nativeDisconnect.apply(this, arguments); - } catch (e) { - throw new Error('error disconnecting node: ' + B + '\n' + e); - } + if (AudioNode.prototype.connect !== toneConnect) { + AudioNode.prototype.connect = toneConnect; + AudioNode.prototype.disconnect = toneDisconnect; } } - if (AudioNode.prototype.connect !== toneConnect) { - AudioNode.prototype.connect = toneConnect; - AudioNode.prototype.disconnect = toneDisconnect; - } - } - if (Tone.supported) { - shimConnect(); - Tone.context = new Tone.Context(); - } else { - console.warn('This browser does not support Tone.js'); - } - return Tone.Context; -}(Tone_core_Tone); -var audiocontext; -'use strict'; -audiocontext = function (StartAudioContext, Context, Tone) { - // Create the Audio Context - const audiocontext = new window.AudioContext(); - Tone.context.dispose(); - Tone.setContext(audiocontext); - /** - *

Returns the Audio Context for this sketch. Useful for users - * who would like to dig deeper into the Web Audio API - * .

- * - *

Some browsers require users to startAudioContext - * with a user gesture, such as touchStarted in the example below.

- * - * @method getAudioContext - * @return {Object} AudioContext for this sketch - * @example - *
- * function draw() { - * background(255); - * textAlign(CENTER); - * - * if (getAudioContext().state !== 'running') { - * text('click to start audio', width/2, height/2); - * } else { - * text('audio is enabled', width/2, height/2); - * } - * } - * - * function touchStarted() { - * if (getAudioContext().state !== 'running') { - * getAudioContext().resume(); - * } - * var synth = new p5.MonoSynth(); - * synth.play('A4', 0.5, 0, 0.2); - * } - * - *
- */ - p5.prototype.getAudioContext = function () { - return audiocontext; - }; - /** - *

It is a good practice to give users control over starting audio playback. - * This practice is enforced by Google Chrome's autoplay policy as of r70 - * (info), iOS Safari, and other browsers. - *

- * - *

- * userStartAudio() starts the Audio Context on a user gesture. It utilizes - * the StartAudioContext library by - * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext. - *

- * - *

Starting the audio context on a user gesture can be as simple as userStartAudio(). - * Optional parameters let you decide on a specific element that will start the audio context, - * and/or call a function once the audio context is started.

- * @param {Element|Array} [element(s)] This argument can be an Element, - * Selector String, NodeList, p5.Element, - * jQuery Element, or an Array of any of those. - * @param {Function} [callback] Callback to invoke when the AudioContext has started - * @return {Promise} Returns a Promise which is resolved when - * the AudioContext state is 'running' - * @method userStartAudio - * @example - *
- * function setup() { - * var myDiv = createDiv('click to start audio'); - * myDiv.position(0, 0); - * - * var mySynth = new p5.MonoSynth(); - * - * // This won't play until the context has started - * mySynth.play('A6'); - * - * // Start the audio context on a click/touch event - * userStartAudio().then(function() { - * myDiv.remove(); - * }); - * } - *
- */ - p5.prototype.userStartAudio = function (elements, callback) { - var elt = elements; - if (elements instanceof p5.Element) { - elt = elements.elt; - } else if (elements instanceof Array && elements[0] instanceof p5.Element) { - elt = elements.map(function (e) { - return e.elt; - }); - } - return StartAudioContext(audiocontext, elt, callback); - }; - return audiocontext; -}(StartAudioContext, Tone_core_Context, Tone_core_Tone); -var master; -'use strict'; -master = function (audiocontext) { - /** - * Master contains AudioContext and the master sound output. - */ - var Master = function () { - this.input = audiocontext.createGain(); - this.output = audiocontext.createGain(); - //put a hard limiter on the output - this.limiter = audiocontext.createDynamicsCompressor(); - this.limiter.threshold.value = -3; - this.limiter.ratio.value = 20; - this.limiter.knee.value = 1; - this.audiocontext = audiocontext; - this.output.disconnect(); - // connect input to limiter - this.input.connect(this.limiter); - // connect limiter to output - this.limiter.connect(this.output); - // meter is just for global Amplitude / FFT analysis - this.meter = audiocontext.createGain(); - this.fftMeter = audiocontext.createGain(); - this.output.connect(this.meter); - this.output.connect(this.fftMeter); - // connect output to destination - this.output.connect(this.audiocontext.destination); - // an array of all sounds in the sketch - this.soundArray = []; - // an array of all musical parts in the sketch - this.parts = []; - // file extensions to search for - this.extensions = []; - }; - // create a single instance of the p5Sound / master output for use within this sketch - var p5sound = new Master(); - /** - * Returns a number representing the master amplitude (volume) for sound - * in this sketch. - * - * @method getMasterVolume - * @return {Number} Master amplitude (volume) for sound in this sketch. - * Should be between 0.0 (silence) and 1.0. - */ - p5.prototype.getMasterVolume = function () { - return p5sound.output.gain.value; - }; - /** - *

Scale the output of all sound in this sketch

- * Scaled between 0.0 (silence) and 1.0 (full volume). - * 1.0 is the maximum amplitude of a digital sound, so multiplying - * by greater than 1.0 may cause digital distortion. To - * fade, provide a rampTime parameter. For more - * complex fades, see the Envelope class. - * - * Alternately, you can pass in a signal source such as an - * oscillator to modulate the amplitude with an audio signal. - * - *

How This Works: When you load the p5.sound module, it - * creates a single instance of p5sound. All sound objects in this - * module output to p5sound before reaching your computer's output. - * So if you change the amplitude of p5sound, it impacts all of the - * sound in this module.

- * - *

If no value is provided, returns a Web Audio API Gain Node

- * - * @method masterVolume - * @param {Number|Object} volume Volume (amplitude) between 0.0 - * and 1.0 or modulating signal/oscillator - * @param {Number} [rampTime] Fade for t seconds - * @param {Number} [timeFromNow] Schedule this event to happen at - * t seconds in the future - */ - p5.prototype.masterVolume = function (vol, rampTime, tFromNow) { - if (typeof vol === 'number') { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = p5sound.output.gain.value; - p5sound.output.gain.cancelScheduledValues(now + tFromNow); - p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(p5sound.output.gain); + if (Tone.supported) { + shimConnect(); + Tone.context = new Tone.Context(); } else { - // return the Gain Node - return p5sound.output.gain; - } - }; - /** - * `p5.soundOut` is the p5.sound master output. It sends output to - * the destination of this window's web audio context. It contains - * Web Audio API nodes including a dyanmicsCompressor (.limiter), - * and Gain Nodes for .input and .output. - * - * @property {Object} soundOut - */ - p5.prototype.soundOut = p5.soundOut = p5sound; - /** - * a silent connection to the DesinationNode - * which will ensure that anything connected to it - * will not be garbage collected - * - * @private - */ - p5.soundOut._silentNode = p5sound.audiocontext.createGain(); - p5.soundOut._silentNode.gain.value = 0; - p5.soundOut._silentNode.connect(p5sound.audiocontext.destination); - return p5sound; -}(audiocontext); -var helpers; -'use strict'; -helpers = function () { - var p5sound = master; - /** - * @for p5 - */ - /** - * Returns a number representing the sample rate, in samples per second, - * of all sound objects in this audio context. It is determined by the - * sampling rate of your operating system's sound card, and it is not - * currently possile to change. - * It is often 44100, or twice the range of human hearing. - * - * @method sampleRate - * @return {Number} samplerate samples per second - */ - p5.prototype.sampleRate = function () { - return p5sound.audiocontext.sampleRate; - }; - /** - * Returns the closest MIDI note value for - * a given frequency. - * - * @method freqToMidi - * @param {Number} frequency A freqeuncy, for example, the "A" - * above Middle C is 440Hz - * @return {Number} MIDI note value - */ - p5.prototype.freqToMidi = function (f) { - var mathlog2 = Math.log(f / 440) / Math.log(2); - var m = Math.round(12 * mathlog2) + 69; - return m; - }; - /** - * Returns the frequency value of a MIDI note value. - * General MIDI treats notes as integers where middle C - * is 60, C# is 61, D is 62 etc. Useful for generating - * musical frequencies with oscillators. - * - * @method midiToFreq - * @param {Number} midiNote The number of a MIDI note - * @return {Number} Frequency value of the given MIDI note - * @example - *
- * var notes = [60, 64, 67, 72]; - * var i = 0; - * - * function setup() { - * osc = new p5.Oscillator('Triangle'); - * osc.start(); - * frameRate(1); - * } - * - * function draw() { - * var freq = midiToFreq(notes[i]); - * osc.freq(freq); - * i++; - * if (i >= notes.length){ - * i = 0; - * } - * } - *
- */ - var midiToFreq = p5.prototype.midiToFreq = function (m) { - return 440 * Math.pow(2, (m - 69) / 12); - }; - // This method converts ANSI notes specified as a string "C4", "Eb3" to a frequency - var noteToFreq = function (note) { - if (typeof note !== 'string') { - return note; - } - var wholeNotes = { - A: 21, - B: 23, - C: 24, - D: 26, - E: 28, - F: 29, - G: 31 - }; - var value = wholeNotes[note[0].toUpperCase()]; - var octave = ~~note.slice(-1); - value += 12 * (octave - 1); - switch (note[1]) { - case '#': - value += 1; - break; - case 'b': - value -= 1; - break; - default: - break; - } - return midiToFreq(value); - }; - /** - * List the SoundFile formats that you will include. LoadSound - * will search your directory for these extensions, and will pick - * a format that is compatable with the client's web browser. - * Here is a free online file - * converter. - * - * @method soundFormats - * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg' - * @example - *
- * function preload() { - * // set the global sound formats - * soundFormats('mp3', 'ogg'); - * - * // load either beatbox.mp3, or .ogg, depending on browser - * mySound = loadSound('assets/beatbox.mp3'); - * } - * - * function setup() { - * mySound.play(); - * } - *
- */ - p5.prototype.soundFormats = function () { - // reset extensions array - p5sound.extensions = []; - // add extensions - for (var i = 0; i < arguments.length; i++) { - arguments[i] = arguments[i].toLowerCase(); - if ([ - 'mp3', - 'wav', - 'ogg', - 'm4a', - 'aac' - ].indexOf(arguments[i]) > -1) { - p5sound.extensions.push(arguments[i]); + console.warn("This browser does not support Tone.js"); + } + return Tone.Context; + })(Tone_core_Tone); + var audiocontext; + ("use strict"); + audiocontext = (function (StartAudioContext, Context, Tone) { + // Create the Audio Context + const audiocontext = new window.AudioContext(); + Tone.context.dispose(); + Tone.setContext(audiocontext); + /** + *

Returns the Audio Context for this sketch. Useful for users + * who would like to dig deeper into the Web Audio API + * .

+ * + *

Some browsers require users to startAudioContext + * with a user gesture, such as touchStarted in the example below.

+ * + * @method getAudioContext + * @return {Object} AudioContext for this sketch + * @example + *
+ * function draw() { + * background(255); + * textAlign(CENTER); + * + * if (getAudioContext().state !== 'running') { + * text('click to start audio', width/2, height/2); + * } else { + * text('audio is enabled', width/2, height/2); + * } + * } + * + * function touchStarted() { + * if (getAudioContext().state !== 'running') { + * getAudioContext().resume(); + * } + * var synth = new p5.MonoSynth(); + * synth.play('A4', 0.5, 0, 0.2); + * } + * + *
+ */ + p5.prototype.getAudioContext = function () { + return audiocontext; + }; + /** + *

It is a good practice to give users control over starting audio playback. + * This practice is enforced by Google Chrome's autoplay policy as of r70 + * (info), iOS Safari, and other browsers. + *

+ * + *

+ * userStartAudio() starts the Audio Context on a user gesture. It utilizes + * the StartAudioContext library by + * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext. + *

+ * + *

Starting the audio context on a user gesture can be as simple as userStartAudio(). + * Optional parameters let you decide on a specific element that will start the audio context, + * and/or call a function once the audio context is started.

+ * @param {Element|Array} [element(s)] This argument can be an Element, + * Selector String, NodeList, p5.Element, + * jQuery Element, or an Array of any of those. + * @param {Function} [callback] Callback to invoke when the AudioContext has started + * @return {Promise} Returns a Promise which is resolved when + * the AudioContext state is 'running' + * @method userStartAudio + * @example + *
+ * function setup() { + * var myDiv = createDiv('click to start audio'); + * myDiv.position(0, 0); + * + * var mySynth = new p5.MonoSynth(); + * + * // This won't play until the context has started + * mySynth.play('A6'); + * + * // Start the audio context on a click/touch event + * userStartAudio().then(function() { + * myDiv.remove(); + * }); + * } + *
+ */ + p5.prototype.userStartAudio = function (elements, callback) { + var elt = elements; + if (elements instanceof p5.Element) { + elt = elements.elt; + } else if ( + elements instanceof Array && + elements[0] instanceof p5.Element + ) { + elt = elements.map(function (e) { + return e.elt; + }); + } + return StartAudioContext(audiocontext, elt, callback); + }; + return audiocontext; + })(StartAudioContext, Tone_core_Context, Tone_core_Tone); + var master; + ("use strict"); + master = (function (audiocontext) { + /** + * Master contains AudioContext and the master sound output. + */ + var Master = function () { + this.input = audiocontext.createGain(); + this.output = audiocontext.createGain(); + //put a hard limiter on the output + this.limiter = audiocontext.createDynamicsCompressor(); + this.limiter.threshold.value = -3; + this.limiter.ratio.value = 20; + this.limiter.knee.value = 1; + this.audiocontext = audiocontext; + this.output.disconnect(); + // connect input to limiter + this.input.connect(this.limiter); + // connect limiter to output + this.limiter.connect(this.output); + // meter is just for global Amplitude / FFT analysis + this.meter = audiocontext.createGain(); + this.fftMeter = audiocontext.createGain(); + this.output.connect(this.meter); + this.output.connect(this.fftMeter); + // connect output to destination + this.output.connect(this.audiocontext.destination); + // an array of all sounds in the sketch + this.soundArray = []; + // an array of all musical parts in the sketch + this.parts = []; + // file extensions to search for + this.extensions = []; + }; + // create a single instance of the p5Sound / master output for use within this sketch + var p5sound = new Master(); + /** + * Returns a number representing the master amplitude (volume) for sound + * in this sketch. + * + * @method getMasterVolume + * @return {Number} Master amplitude (volume) for sound in this sketch. + * Should be between 0.0 (silence) and 1.0. + */ + p5.prototype.getMasterVolume = function () { + return p5sound.output.gain.value; + }; + /** + *

Scale the output of all sound in this sketch

+ * Scaled between 0.0 (silence) and 1.0 (full volume). + * 1.0 is the maximum amplitude of a digital sound, so multiplying + * by greater than 1.0 may cause digital distortion. To + * fade, provide a rampTime parameter. For more + * complex fades, see the Envelope class. + * + * Alternately, you can pass in a signal source such as an + * oscillator to modulate the amplitude with an audio signal. + * + *

How This Works: When you load the p5.sound module, it + * creates a single instance of p5sound. All sound objects in this + * module output to p5sound before reaching your computer's output. + * So if you change the amplitude of p5sound, it impacts all of the + * sound in this module.

+ * + *

If no value is provided, returns a Web Audio API Gain Node

+ * + * @method masterVolume + * @param {Number|Object} volume Volume (amplitude) between 0.0 + * and 1.0 or modulating signal/oscillator + * @param {Number} [rampTime] Fade for t seconds + * @param {Number} [timeFromNow] Schedule this event to happen at + * t seconds in the future + */ + p5.prototype.masterVolume = function (vol, rampTime, tFromNow) { + if (typeof vol === "number") { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = p5sound.output.gain.value; + p5sound.output.gain.cancelScheduledValues(now + tFromNow); + p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + p5sound.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(p5sound.output.gain); } else { - throw arguments[i] + ' is not a valid sound format!'; + // return the Gain Node + return p5sound.output.gain; } - } - }; - p5.prototype.disposeSound = function () { - for (var i = 0; i < p5sound.soundArray.length; i++) { - p5sound.soundArray[i].dispose(); - } - }; - // register removeSound to dispose of p5sound SoundFiles, Convolvers, - // Oscillators etc when sketch ends - p5.prototype.registerMethod('remove', p5.prototype.disposeSound); - p5.prototype._checkFileFormats = function (paths) { - var path; - // if path is a single string, check to see if extension is provided - if (typeof paths === 'string') { - path = paths; - // see if extension is provided - var extTest = path.split('.').pop(); - // if an extension is provided... - if ([ - 'mp3', - 'wav', - 'ogg', - 'm4a', - 'aac' - ].indexOf(extTest) > -1) { - if (p5.prototype.isFileSupported(extTest)) { - path = path; + }; + /** + * `p5.soundOut` is the p5.sound master output. It sends output to + * the destination of this window's web audio context. It contains + * Web Audio API nodes including a dyanmicsCompressor (.limiter), + * and Gain Nodes for .input and .output. + * + * @property {Object} soundOut + */ + p5.prototype.soundOut = p5.soundOut = p5sound; + /** + * a silent connection to the DesinationNode + * which will ensure that anything connected to it + * will not be garbage collected + * + * @private + */ + p5.soundOut._silentNode = p5sound.audiocontext.createGain(); + p5.soundOut._silentNode.gain.value = 0; + p5.soundOut._silentNode.connect(p5sound.audiocontext.destination); + return p5sound; + })(audiocontext); + var helpers; + ("use strict"); + helpers = (function () { + var p5sound = master; + /** + * @for p5 + */ + /** + * Returns a number representing the sample rate, in samples per second, + * of all sound objects in this audio context. It is determined by the + * sampling rate of your operating system's sound card, and it is not + * currently possile to change. + * It is often 44100, or twice the range of human hearing. + * + * @method sampleRate + * @return {Number} samplerate samples per second + */ + p5.prototype.sampleRate = function () { + return p5sound.audiocontext.sampleRate; + }; + /** + * Returns the closest MIDI note value for + * a given frequency. + * + * @method freqToMidi + * @param {Number} frequency A freqeuncy, for example, the "A" + * above Middle C is 440Hz + * @return {Number} MIDI note value + */ + p5.prototype.freqToMidi = function (f) { + var mathlog2 = Math.log(f / 440) / Math.log(2); + var m = Math.round(12 * mathlog2) + 69; + return m; + }; + /** + * Returns the frequency value of a MIDI note value. + * General MIDI treats notes as integers where middle C + * is 60, C# is 61, D is 62 etc. Useful for generating + * musical frequencies with oscillators. + * + * @method midiToFreq + * @param {Number} midiNote The number of a MIDI note + * @return {Number} Frequency value of the given MIDI note + * @example + *
+ * var notes = [60, 64, 67, 72]; + * var i = 0; + * + * function setup() { + * osc = new p5.Oscillator('Triangle'); + * osc.start(); + * frameRate(1); + * } + * + * function draw() { + * var freq = midiToFreq(notes[i]); + * osc.freq(freq); + * i++; + * if (i >= notes.length){ + * i = 0; + * } + * } + *
+ */ + var midiToFreq = (p5.prototype.midiToFreq = function (m) { + return 440 * Math.pow(2, (m - 69) / 12); + }); + // This method converts ANSI notes specified as a string "C4", "Eb3" to a frequency + var noteToFreq = function (note) { + if (typeof note !== "string") { + return note; + } + var wholeNotes = { + A: 21, + B: 23, + C: 24, + D: 26, + E: 28, + F: 29, + G: 31, + }; + var value = wholeNotes[note[0].toUpperCase()]; + var octave = ~~note.slice(-1); + value += 12 * (octave - 1); + switch (note[1]) { + case "#": + value += 1; + break; + case "b": + value -= 1; + break; + default: + break; + } + return midiToFreq(value); + }; + /** + * List the SoundFile formats that you will include. LoadSound + * will search your directory for these extensions, and will pick + * a format that is compatable with the client's web browser. + * Here is a free online file + * converter. + * + * @method soundFormats + * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg' + * @example + *
+ * function preload() { + * // set the global sound formats + * soundFormats('mp3', 'ogg'); + * + * // load either beatbox.mp3, or .ogg, depending on browser + * mySound = loadSound('assets/beatbox.mp3'); + * } + * + * function setup() { + * mySound.play(); + * } + *
+ */ + p5.prototype.soundFormats = function () { + // reset extensions array + p5sound.extensions = []; + // add extensions + for (var i = 0; i < arguments.length; i++) { + arguments[i] = arguments[i].toLowerCase(); + if (["mp3", "wav", "ogg", "m4a", "aac"].indexOf(arguments[i]) > -1) { + p5sound.extensions.push(arguments[i]); + } else { + throw arguments[i] + " is not a valid sound format!"; + } + } + }; + p5.prototype.disposeSound = function () { + for (var i = 0; i < p5sound.soundArray.length; i++) { + p5sound.soundArray[i].dispose(); + } + }; + // register removeSound to dispose of p5sound SoundFiles, Convolvers, + // Oscillators etc when sketch ends + p5.prototype.registerMethod("remove", p5.prototype.disposeSound); + p5.prototype._checkFileFormats = function (paths) { + var path; + // if path is a single string, check to see if extension is provided + if (typeof paths === "string") { + path = paths; + // see if extension is provided + var extTest = path.split(".").pop(); + // if an extension is provided... + if (["mp3", "wav", "ogg", "m4a", "aac"].indexOf(extTest) > -1) { + if (p5.prototype.isFileSupported(extTest)) { + path = path; + } else { + var pathSplit = path.split("."); + var pathCore = pathSplit[pathSplit.length - 1]; + for (var i = 0; i < p5sound.extensions.length; i++) { + var extension = p5sound.extensions[i]; + var supported = p5.prototype.isFileSupported(extension); + if (supported) { + pathCore = ""; + if (pathSplit.length === 2) { + pathCore += pathSplit[0]; + } + for (var i = 1; i <= pathSplit.length - 2; i++) { + var p = pathSplit[i]; + pathCore += "." + p; + } + path = pathCore += "."; + path = path += extension; + break; + } + } + } } else { - var pathSplit = path.split('.'); - var pathCore = pathSplit[pathSplit.length - 1]; for (var i = 0; i < p5sound.extensions.length; i++) { var extension = p5sound.extensions[i]; var supported = p5.prototype.isFileSupported(extension); if (supported) { - pathCore = ''; - if (pathSplit.length === 2) { - pathCore += pathSplit[0]; - } - for (var i = 1; i <= pathSplit.length - 2; i++) { - var p = pathSplit[i]; - pathCore += '.' + p; - } - path = pathCore += '.'; - path = path += extension; + path = path + "." + extension; break; } } } - } else { - for (var i = 0; i < p5sound.extensions.length; i++) { - var extension = p5sound.extensions[i]; + } else if (typeof paths === "object") { + for (var i = 0; i < paths.length; i++) { + var extension = paths[i].split(".").pop(); var supported = p5.prototype.isFileSupported(extension); if (supported) { - path = path + '.' + extension; + // console.log('.'+extension + ' is ' + supported + + // ' supported by your browser.'); + path = paths[i]; break; } } } - } else if (typeof paths === 'object') { - for (var i = 0; i < paths.length; i++) { - var extension = paths[i].split('.').pop(); - var supported = p5.prototype.isFileSupported(extension); - if (supported) { - // console.log('.'+extension + ' is ' + supported + - // ' supported by your browser.'); - path = paths[i]; - break; + return path; + }; + /** + * Used by Osc and Envelope to chain signal math + */ + p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { + // if this type of math already exists in the chain, replace it + for (var i in o.mathOps) { + if (o.mathOps[i] instanceof type) { + o.mathOps[i].dispose(); + thisChain = i; + if (thisChain < o.mathOps.length - 1) { + nextChain = o.mathOps[i + 1]; + } } } - } - return path; - }; - /** - * Used by Osc and Envelope to chain signal math - */ - p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { - // if this type of math already exists in the chain, replace it - for (var i in o.mathOps) { - if (o.mathOps[i] instanceof type) { - o.mathOps[i].dispose(); - thisChain = i; - if (thisChain < o.mathOps.length - 1) { - nextChain = o.mathOps[i + 1]; - } + o.mathOps[thisChain - 1].disconnect(); + o.mathOps[thisChain - 1].connect(math); + math.connect(nextChain); + o.mathOps[thisChain] = math; + return o; + }; + // helper methods to convert audio file as .wav format, + // will use as saving .wav file and saving blob object + // Thank you to Matt Diamond's RecorderJS (MIT License) + // https://github.com/mattdiamond/Recorderjs + function convertToWav(audioBuffer) { + var leftChannel, rightChannel; + leftChannel = audioBuffer.getChannelData(0); + // handle mono files + if (audioBuffer.numberOfChannels > 1) { + rightChannel = audioBuffer.getChannelData(1); + } else { + rightChannel = leftChannel; + } + var interleaved = interleave(leftChannel, rightChannel); + // create the buffer and view to create the .WAV file + var buffer = new window.ArrayBuffer(44 + interleaved.length * 2); + var view = new window.DataView(buffer); + // write the WAV container, + // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf + // RIFF chunk descriptor + writeUTFBytes(view, 0, "RIFF"); + view.setUint32(4, 36 + interleaved.length * 2, true); + writeUTFBytes(view, 8, "WAVE"); + // FMT sub-chunk + writeUTFBytes(view, 12, "fmt "); + view.setUint32(16, 16, true); + view.setUint16(20, 1, true); + // stereo (2 channels) + view.setUint16(22, 2, true); + view.setUint32(24, p5sound.audiocontext.sampleRate, true); + view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true); + view.setUint16(32, 4, true); + view.setUint16(34, 16, true); + // data sub-chunk + writeUTFBytes(view, 36, "data"); + view.setUint32(40, interleaved.length * 2, true); + // write the PCM samples + var lng = interleaved.length; + var index = 44; + var volume = 1; + for (var i = 0; i < lng; i++) { + view.setInt16(index, interleaved[i] * (32767 * volume), true); + index += 2; + } + return view; + } + // helper methods to save waves + function interleave(leftChannel, rightChannel) { + var length = leftChannel.length + rightChannel.length; + var result = new Float32Array(length); + var inputIndex = 0; + for (var index = 0; index < length; ) { + result[index++] = leftChannel[inputIndex]; + result[index++] = rightChannel[inputIndex]; + inputIndex++; + } + return result; + } + function writeUTFBytes(view, offset, string) { + var lng = string.length; + for (var i = 0; i < lng; i++) { + view.setUint8(offset + i, string.charCodeAt(i)); } } - o.mathOps[thisChain - 1].disconnect(); - o.mathOps[thisChain - 1].connect(math); - math.connect(nextChain); - o.mathOps[thisChain] = math; - return o; - }; - // helper methods to convert audio file as .wav format, - // will use as saving .wav file and saving blob object - // Thank you to Matt Diamond's RecorderJS (MIT License) - // https://github.com/mattdiamond/Recorderjs - function convertToWav(audioBuffer) { - var leftChannel, rightChannel; - leftChannel = audioBuffer.getChannelData(0); - // handle mono files - if (audioBuffer.numberOfChannels > 1) { - rightChannel = audioBuffer.getChannelData(1); - } else { - rightChannel = leftChannel; - } - var interleaved = interleave(leftChannel, rightChannel); - // create the buffer and view to create the .WAV file - var buffer = new window.ArrayBuffer(44 + interleaved.length * 2); - var view = new window.DataView(buffer); - // write the WAV container, - // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf - // RIFF chunk descriptor - writeUTFBytes(view, 0, 'RIFF'); - view.setUint32(4, 36 + interleaved.length * 2, true); - writeUTFBytes(view, 8, 'WAVE'); - // FMT sub-chunk - writeUTFBytes(view, 12, 'fmt '); - view.setUint32(16, 16, true); - view.setUint16(20, 1, true); - // stereo (2 channels) - view.setUint16(22, 2, true); - view.setUint32(24, p5sound.audiocontext.sampleRate, true); - view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true); - view.setUint16(32, 4, true); - view.setUint16(34, 16, true); - // data sub-chunk - writeUTFBytes(view, 36, 'data'); - view.setUint32(40, interleaved.length * 2, true); - // write the PCM samples - var lng = interleaved.length; - var index = 44; - var volume = 1; - for (var i = 0; i < lng; i++) { - view.setInt16(index, interleaved[i] * (32767 * volume), true); - index += 2; - } - return view; - } - // helper methods to save waves - function interleave(leftChannel, rightChannel) { - var length = leftChannel.length + rightChannel.length; - var result = new Float32Array(length); - var inputIndex = 0; - for (var index = 0; index < length;) { - result[index++] = leftChannel[inputIndex]; - result[index++] = rightChannel[inputIndex]; - inputIndex++; - } - return result; - } - function writeUTFBytes(view, offset, string) { - var lng = string.length; - for (var i = 0; i < lng; i++) { - view.setUint8(offset + i, string.charCodeAt(i)); - } - } - return { - convertToWav: convertToWav, - midiToFreq: midiToFreq, - noteToFreq: noteToFreq - }; -}(master); -var errorHandler; -'use strict'; -errorHandler = function () { - /* + return { + convertToWav: convertToWav, + midiToFreq: midiToFreq, + noteToFreq: noteToFreq, + }; + })(master); + var errorHandler; + ("use strict"); + errorHandler = (function () { + /* Helper function to generate an error with a custom stack trace that points to the sketch and removes other parts of the stack trace. @@ -1524,11356 +1579,12106 @@ errorHandler = function () { @property {String} failedPath path to the file that failed to load @return {Error} returns a custom Error object */ - var CustomError = function (name, errorTrace, failedPath) { - var err = new Error(); - var tempStack, splitStack; - err.name = name; - err.originalStack = err.stack + errorTrace; - tempStack = err.stack + errorTrace; - err.failedPath = failedPath; - // only print the part of the stack trace that refers to the user code: - var splitStack = tempStack.split('\n'); - splitStack = splitStack.filter(function (ln) { - return !ln.match(/(p5.|native code|globalInit)/g); - }); - err.stack = splitStack.join('\n'); - return err; - }; - return CustomError; -}(); -var panner; -'use strict'; -panner = function () { - var p5sound = master; - var ac = p5sound.audiocontext; - // Stereo panner - // if there is a stereo panner node use it - if (typeof ac.createStereoPanner !== 'undefined') { - p5.Panner = function (input, output) { - this.stereoPanner = this.input = ac.createStereoPanner(); - input.connect(this.stereoPanner); - this.stereoPanner.connect(output); - }; - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = ac.currentTime + time; - this.stereoPanner.pan.linearRampToValueAtTime(val, t); - }; - //not implemented because stereopanner - //node does not require this and will automatically - //convert single channel or multichannel to stereo. - //tested with single and stereo, not with (>2) multichannel - p5.Panner.prototype.inputChannels = function () { - }; - p5.Panner.prototype.connect = function (obj) { - this.stereoPanner.connect(obj); - }; - p5.Panner.prototype.disconnect = function () { - if (this.stereoPanner) { - this.stereoPanner.disconnect(); - } - }; - } else { - // if there is no createStereoPanner object - // such as in safari 7.1.7 at the time of writing this - // use this method to create the effect - p5.Panner = function (input, output, numInputChannels) { - this.input = ac.createGain(); - input.connect(this.input); - this.left = ac.createGain(); - this.right = ac.createGain(); - this.left.channelInterpretation = 'discrete'; - this.right.channelInterpretation = 'discrete'; - // if input is stereo - if (numInputChannels > 1) { - this.splitter = ac.createChannelSplitter(2); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); - } else { - this.input.connect(this.left); - this.input.connect(this.right); - } - this.output = ac.createChannelMerger(2); - this.left.connect(this.output, 0, 1); - this.right.connect(this.output, 0, 0); - this.output.connect(output); - }; - // -1 is left, +1 is right - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = ac.currentTime + time; - var v = (val + 1) / 2; - var rightVal = Math.cos(v * Math.PI / 2); - var leftVal = Math.sin(v * Math.PI / 2); - this.left.gain.linearRampToValueAtTime(leftVal, t); - this.right.gain.linearRampToValueAtTime(rightVal, t); - }; - p5.Panner.prototype.inputChannels = function (numChannels) { - if (numChannels === 1) { - this.input.disconnect(); - this.input.connect(this.left); - this.input.connect(this.right); - } else if (numChannels === 2) { - if (typeof (this.splitter === 'undefined')) { - this.splitter = ac.createChannelSplitter(2); - } - this.input.disconnect(); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); - } - }; - p5.Panner.prototype.connect = function (obj) { - this.output.connect(obj); - }; - p5.Panner.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } + var CustomError = function (name, errorTrace, failedPath) { + var err = new Error(); + var tempStack, splitStack; + err.name = name; + err.originalStack = err.stack + errorTrace; + tempStack = err.stack + errorTrace; + err.failedPath = failedPath; + // only print the part of the stack trace that refers to the user code: + var splitStack = tempStack.split("\n"); + splitStack = splitStack.filter(function (ln) { + return !ln.match(/(p5.|native code|globalInit)/g); + }); + err.stack = splitStack.join("\n"); + return err; }; - } -}(master); -var soundfile; -'use strict'; -soundfile = function () { - var CustomError = errorHandler; - var p5sound = master; - var ac = p5sound.audiocontext; - var midiToFreq = helpers.midiToFreq; - var convertToWav = helpers.convertToWav; - /** - *

SoundFile object with a path to a file.

- * - *

The p5.SoundFile may not be available immediately because - * it loads the file information asynchronously.

- * - *

To do something with the sound as soon as it loads - * pass the name of a function as the second parameter.

- * - *

Only one file path is required. However, audio file formats - * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all - * web browsers. If you want to ensure compatability, instead of a single - * file path, you may include an Array of filepaths, and the browser will - * choose a format that works.

- * - * @class p5.SoundFile - * @constructor - * @param {String|Array} path path to a sound file (String). Optionally, - * you may include multiple file formats in - * an array. Alternately, accepts an object - * from the HTML5 File API, or a p5.File. - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if file fails to - * load. This function will receive an error or - * XMLHttpRequest object with information - * about what went wrong. - * @param {Function} [whileLoadingCallback] Name of a function to call while file - * is loading. That function will - * receive progress of the request to - * load the sound file - * (between 0 and 1) as its first - * parameter. This progress - * does not account for the additional - * time needed to decode the audio data. - * - * @example - *
- * - * function preload() { - * soundFormats('mp3', 'ogg'); - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * mySound.setVolume(0.1); - * mySound.play(); - * } - * - *
- */ - p5.SoundFile = function (paths, onload, onerror, whileLoading) { - if (typeof paths !== 'undefined') { - if (typeof paths === 'string' || typeof paths[0] === 'string') { - var path = p5.prototype._checkFileFormats(paths); - this.url = path; - } else if (typeof paths === 'object') { - if (!(window.File && window.FileReader && window.FileList && window.Blob)) { - // The File API isn't supported in this browser - throw 'Unable to load file because the File API is not supported'; - } - } - // if type is a p5.File...get the actual file - if (paths.file) { - paths = paths.file; - } - this.file = paths; - } - // private _onended callback, set by the method: onended(callback) - this._onended = function () { - }; - this._looping = false; - this._playing = false; - this._paused = false; - this._pauseTime = 0; - // cues for scheduling events with addCue() removeCue() - this._cues = []; - this._cueIDCounter = 0; - // position of the most recently played sample - this._lastPos = 0; - this._counterNode = null; - this._scopeNode = null; - // array of sources so that they can all be stopped! - this.bufferSourceNodes = []; - // current source - this.bufferSourceNode = null; - this.buffer = null; - this.playbackRate = 1; - this.input = p5sound.audiocontext.createGain(); - this.output = p5sound.audiocontext.createGain(); - this.reversed = false; - // start and end of playback / loop - this.startTime = 0; - this.endTime = null; - this.pauseTime = 0; - // "restart" would stop playback before retriggering - this.mode = 'sustain'; - // time that playback was started, in millis - this.startMillis = null; - // stereo panning - this.panPosition = 0; - this.panner = new p5.Panner(this.output, p5sound.input, 2); - // it is possible to instantiate a soundfile with no path - if (this.url || this.file) { - this.load(onload, onerror); - } - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - if (typeof whileLoading === 'function') { - this._whileLoading = whileLoading; + return CustomError; + })(); + var panner; + ("use strict"); + panner = (function () { + var p5sound = master; + var ac = p5sound.audiocontext; + // Stereo panner + // if there is a stereo panner node use it + if (typeof ac.createStereoPanner !== "undefined") { + p5.Panner = function (input, output) { + this.stereoPanner = this.input = ac.createStereoPanner(); + input.connect(this.stereoPanner); + this.stereoPanner.connect(output); + }; + p5.Panner.prototype.pan = function (val, tFromNow) { + var time = tFromNow || 0; + var t = ac.currentTime + time; + this.stereoPanner.pan.linearRampToValueAtTime(val, t); + }; + //not implemented because stereopanner + //node does not require this and will automatically + //convert single channel or multichannel to stereo. + //tested with single and stereo, not with (>2) multichannel + p5.Panner.prototype.inputChannels = function () {}; + p5.Panner.prototype.connect = function (obj) { + this.stereoPanner.connect(obj); + }; + p5.Panner.prototype.disconnect = function () { + if (this.stereoPanner) { + this.stereoPanner.disconnect(); + } + }; } else { - this._whileLoading = function () { + // if there is no createStereoPanner object + // such as in safari 7.1.7 at the time of writing this + // use this method to create the effect + p5.Panner = function (input, output, numInputChannels) { + this.input = ac.createGain(); + input.connect(this.input); + this.left = ac.createGain(); + this.right = ac.createGain(); + this.left.channelInterpretation = "discrete"; + this.right.channelInterpretation = "discrete"; + // if input is stereo + if (numInputChannels > 1) { + this.splitter = ac.createChannelSplitter(2); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } else { + this.input.connect(this.left); + this.input.connect(this.right); + } + this.output = ac.createChannelMerger(2); + this.left.connect(this.output, 0, 1); + this.right.connect(this.output, 0, 0); + this.output.connect(output); + }; + // -1 is left, +1 is right + p5.Panner.prototype.pan = function (val, tFromNow) { + var time = tFromNow || 0; + var t = ac.currentTime + time; + var v = (val + 1) / 2; + var rightVal = Math.cos((v * Math.PI) / 2); + var leftVal = Math.sin((v * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(leftVal, t); + this.right.gain.linearRampToValueAtTime(rightVal, t); + }; + p5.Panner.prototype.inputChannels = function (numChannels) { + if (numChannels === 1) { + this.input.disconnect(); + this.input.connect(this.left); + this.input.connect(this.right); + } else if (numChannels === 2) { + if (typeof (this.splitter === "undefined")) { + this.splitter = ac.createChannelSplitter(2); + } + this.input.disconnect(); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } + }; + p5.Panner.prototype.connect = function (obj) { + this.output.connect(obj); + }; + p5.Panner.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } }; } - this._onAudioProcess = _onAudioProcess.bind(this); - this._clearOnEnd = _clearOnEnd.bind(this); - }; - // register preload handling of loadSound - p5.prototype.registerPreloadMethod('loadSound', p5.prototype); - /** - * loadSound() returns a new p5.SoundFile from a specified - * path. If called during preload(), the p5.SoundFile will be ready - * to play in time for setup() and draw(). If called outside of - * preload, the p5.SoundFile will not be ready immediately, so - * loadSound accepts a callback as the second parameter. Using a - * - * local server is recommended when loading external files. - * - * @method loadSound - * @param {String|Array} path Path to the sound file, or an array with - * paths to soundfiles in multiple formats - * i.e. ['sound.ogg', 'sound.mp3']. - * Alternately, accepts an object: either - * from the HTML5 File API, or a p5.File. - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is - * an error loading the file. - * @param {Function} [whileLoading] Name of a function to call while file is loading. - * This function will receive the percentage loaded - * so far, from 0.0 to 1.0. - * @return {SoundFile} Returns a p5.SoundFile - * @example - *
- * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * mySound.setVolume(0.1); - * mySound.play(); - * } - *
- */ - p5.prototype.loadSound = function (path, callback, onerror, whileLoading) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - var self = this; - var s = new p5.SoundFile(path, function () { - if (typeof callback === 'function') { - callback.apply(self, arguments); + })(master); + var soundfile; + ("use strict"); + soundfile = (function () { + var CustomError = errorHandler; + var p5sound = master; + var ac = p5sound.audiocontext; + var midiToFreq = helpers.midiToFreq; + var convertToWav = helpers.convertToWav; + /** + *

SoundFile object with a path to a file.

+ * + *

The p5.SoundFile may not be available immediately because + * it loads the file information asynchronously.

+ * + *

To do something with the sound as soon as it loads + * pass the name of a function as the second parameter.

+ * + *

Only one file path is required. However, audio file formats + * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all + * web browsers. If you want to ensure compatability, instead of a single + * file path, you may include an Array of filepaths, and the browser will + * choose a format that works.

+ * + * @class p5.SoundFile + * @constructor + * @param {String|Array} path path to a sound file (String). Optionally, + * you may include multiple file formats in + * an array. Alternately, accepts an object + * from the HTML5 File API, or a p5.File. + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if file fails to + * load. This function will receive an error or + * XMLHttpRequest object with information + * about what went wrong. + * @param {Function} [whileLoadingCallback] Name of a function to call while file + * is loading. That function will + * receive progress of the request to + * load the sound file + * (between 0 and 1) as its first + * parameter. This progress + * does not account for the additional + * time needed to decode the audio data. + * + * @example + *
+ * + * function preload() { + * soundFormats('mp3', 'ogg'); + * mySound = loadSound('assets/doorbell.mp3'); + * } + * + * function setup() { + * mySound.setVolume(0.1); + * mySound.play(); + * } + * + *
+ */ + p5.SoundFile = function (paths, onload, onerror, whileLoading) { + if (typeof paths !== "undefined") { + if (typeof paths === "string" || typeof paths[0] === "string") { + var path = p5.prototype._checkFileFormats(paths); + this.url = path; + } else if (typeof paths === "object") { + if ( + !( + window.File && + window.FileReader && + window.FileList && + window.Blob + ) + ) { + // The File API isn't supported in this browser + throw "Unable to load file because the File API is not supported"; + } + } + // if type is a p5.File...get the actual file + if (paths.file) { + paths = paths.file; + } + this.file = paths; + } + // private _onended callback, set by the method: onended(callback) + this._onended = function () {}; + this._looping = false; + this._playing = false; + this._paused = false; + this._pauseTime = 0; + // cues for scheduling events with addCue() removeCue() + this._cues = []; + this._cueIDCounter = 0; + // position of the most recently played sample + this._lastPos = 0; + this._counterNode = null; + this._scopeNode = null; + // array of sources so that they can all be stopped! + this.bufferSourceNodes = []; + // current source + this.bufferSourceNode = null; + this.buffer = null; + this.playbackRate = 1; + this.input = p5sound.audiocontext.createGain(); + this.output = p5sound.audiocontext.createGain(); + this.reversed = false; + // start and end of playback / loop + this.startTime = 0; + this.endTime = null; + this.pauseTime = 0; + // "restart" would stop playback before retriggering + this.mode = "sustain"; + // time that playback was started, in millis + this.startMillis = null; + // stereo panning + this.panPosition = 0; + this.panner = new p5.Panner(this.output, p5sound.input, 2); + // it is possible to instantiate a soundfile with no path + if (this.url || this.file) { + this.load(onload, onerror); + } + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + if (typeof whileLoading === "function") { + this._whileLoading = whileLoading; + } else { + this._whileLoading = function () {}; } - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); + this._onAudioProcess = _onAudioProcess.bind(this); + this._clearOnEnd = _clearOnEnd.bind(this); + }; + // register preload handling of loadSound + p5.prototype.registerPreloadMethod("loadSound", p5.prototype); + /** + * loadSound() returns a new p5.SoundFile from a specified + * path. If called during preload(), the p5.SoundFile will be ready + * to play in time for setup() and draw(). If called outside of + * preload, the p5.SoundFile will not be ready immediately, so + * loadSound accepts a callback as the second parameter. Using a + * + * local server is recommended when loading external files. + * + * @method loadSound + * @param {String|Array} path Path to the sound file, or an array with + * paths to soundfiles in multiple formats + * i.e. ['sound.ogg', 'sound.mp3']. + * Alternately, accepts an object: either + * from the HTML5 File API, or a p5.File. + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is + * an error loading the file. + * @param {Function} [whileLoading] Name of a function to call while file is loading. + * This function will receive the percentage loaded + * so far, from 0.0 to 1.0. + * @return {SoundFile} Returns a p5.SoundFile + * @example + *
+ * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * + * function setup() { + * mySound.setVolume(0.1); + * mySound.play(); + * } + *
+ */ + p5.prototype.loadSound = function (path, callback, onerror, whileLoading) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); } - }, onerror, whileLoading); - return s; - }; - /** - * This is a helper function that the p5.SoundFile calls to load - * itself. Accepts a callback (the name of another function) - * as an optional parameter. - * - * @private - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is an error - */ - p5.SoundFile.prototype.load = function (callback, errorCallback) { - var self = this; - var errorTrace = new Error().stack; - if (this.url !== undefined && this.url !== '') { - var request = new XMLHttpRequest(); - request.addEventListener('progress', function (evt) { - self._updateProgress(evt); - }, false); - request.open('GET', this.url, true); - request.responseType = 'arraybuffer'; - request.onload = function () { - if (request.status === 200) { - // on sucess loading file: - if (!self.panner) - return; - ac.decodeAudioData(request.response, // success decoding buffer: - function (buff) { - if (!self.panner) - return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); - if (callback) { - callback(self); - } - }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 - function () { - if (!self.panner) - return; - var err = new CustomError('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; + var self = this; + var s = new p5.SoundFile( + path, + function () { + if (typeof callback === "function") { + callback.apply(self, arguments); + } + if (typeof self._decrementPreload === "function") { + self._decrementPreload(); + } + }, + onerror, + whileLoading + ); + return s; + }; + /** + * This is a helper function that the p5.SoundFile calls to load + * itself. Accepts a callback (the name of another function) + * as an optional parameter. + * + * @private + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is an error + */ + p5.SoundFile.prototype.load = function (callback, errorCallback) { + var self = this; + var errorTrace = new Error().stack; + if (this.url !== undefined && this.url !== "") { + var request = new XMLHttpRequest(); + request.addEventListener( + "progress", + function (evt) { + self._updateProgress(evt); + }, + false + ); + request.open("GET", this.url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status === 200) { + // on sucess loading file: + if (!self.panner) return; + ac.decodeAudioData( + request.response, // success decoding buffer: + function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); + if (callback) { + callback(self); + } + }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 + function () { + if (!self.panner) return; + var err = new CustomError( + "decodeAudioData", + errorTrace, + self.url + ); + var msg = + "AudioContext error at decodeAudioData for " + self.url; + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + ); + } else { + if (!self.panner) return; + var err = new CustomError("loadSound", errorTrace, self.url); + var msg = + "Unable to load " + + self.url + + ". The request status was: " + + request.status + + " (" + + request.statusText + + ")"; if (errorCallback) { - err.msg = msg; + err.message = msg; errorCallback(err); } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); } - }); - } else { - if (!self.panner) - return; - var err = new CustomError('loadSound', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + } + }; + // if there is another error, aside from 404... + request.onerror = function () { + var err = new CustomError("loadSound", errorTrace, self.url); + var msg = + "There was no response from the server at " + + self.url + + ". Check the url and internet connectivity."; if (errorCallback) { err.message = msg; errorCallback(err); } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); } - } - }; - // if there is another error, aside from 404... - request.onerror = function () { - var err = new CustomError('loadSound', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }; - request.send(); - } else if (this.file !== undefined) { - var reader = new FileReader(); - reader.onload = function () { - if (!self.panner) - return; - ac.decodeAudioData(reader.result, function (buff) { - if (!self.panner) - return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); - if (callback) { - callback(self); + }; + request.send(); + } else if (this.file !== undefined) { + var reader = new FileReader(); + reader.onload = function () { + if (!self.panner) return; + ac.decodeAudioData(reader.result, function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); + if (callback) { + callback(self); + } + }); + }; + reader.onerror = function (e) { + if (!self.panner) return; + if (onerror) { + onerror(e); } - }); - }; - reader.onerror = function (e) { - if (!self.panner) - return; - if (onerror) { - onerror(e); - } - }; - reader.readAsArrayBuffer(this.file); - } - }; - // TO DO: use this method to create a loading bar that shows progress during file upload/decode. - p5.SoundFile.prototype._updateProgress = function (evt) { - if (evt.lengthComputable) { - var percentComplete = evt.loaded / evt.total * 0.99; - this._whileLoading(percentComplete, evt); - } else { - // Unable to compute progress information since the total size is unknown - this._whileLoading('size unknown'); - } - }; - /** - * Returns true if the sound file finished loading successfully. - * - * @method isLoaded - * @return {Boolean} - */ - p5.SoundFile.prototype.isLoaded = function () { - if (this.buffer) { - return true; - } else { - return false; - } - }; - /** - * Play the p5.SoundFile - * - * @method play - * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) amplitude (volume) - * of playback - * @param {Number} [cueStart] (optional) cue start time in seconds - * @param {Number} [duration] (optional) duration of playback in seconds - */ - p5.SoundFile.prototype.play = function (startTime, rate, amp, _cueStart, duration) { - if (!this.output) { - console.warn('SoundFile.play() called after dispose'); - return; - } - var self = this; - var now = p5sound.audiocontext.currentTime; - var cueStart, cueEnd; - var time = startTime || 0; - if (time < 0) { - time = 0; - } - time = time + now; - if (typeof rate !== 'undefined') { - this.rate(rate); - } - if (typeof amp !== 'undefined') { - this.setVolume(amp); - } - // TO DO: if already playing, create array of buffers for easy stop() - if (this.buffer) { - // reset the pause time (if it was paused) - this._pauseTime = 0; - // handle restart playmode - if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) { - this.bufferSourceNode.stop(time); - this._counterNode.stop(time); + }; + reader.readAsArrayBuffer(this.file); } - //dont create another instance if already playing - if (this.mode === 'untildone' && this.isPlaying()) { + }; + // TO DO: use this method to create a loading bar that shows progress during file upload/decode. + p5.SoundFile.prototype._updateProgress = function (evt) { + if (evt.lengthComputable) { + var percentComplete = (evt.loaded / evt.total) * 0.99; + this._whileLoading(percentComplete, evt); + } else { + // Unable to compute progress information since the total size is unknown + this._whileLoading("size unknown"); + } + }; + /** + * Returns true if the sound file finished loading successfully. + * + * @method isLoaded + * @return {Boolean} + */ + p5.SoundFile.prototype.isLoaded = function () { + if (this.buffer) { + return true; + } else { + return false; + } + }; + /** + * Play the p5.SoundFile + * + * @method play + * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) amplitude (volume) + * of playback + * @param {Number} [cueStart] (optional) cue start time in seconds + * @param {Number} [duration] (optional) duration of playback in seconds + */ + p5.SoundFile.prototype.play = function ( + startTime, + rate, + amp, + _cueStart, + duration + ) { + if (!this.output) { + console.warn("SoundFile.play() called after dispose"); return; } - // make a new source and counter. They are automatically assigned playbackRate and buffer - this.bufferSourceNode = this._initSourceNode(); - // garbage collect counterNode and create a new one - delete this._counterNode; - this._counterNode = this._initCounterNode(); - if (_cueStart) { - if (_cueStart >= 0 && _cueStart < this.buffer.duration) { - // this.startTime = cueStart; - cueStart = _cueStart; + var self = this; + var now = p5sound.audiocontext.currentTime; + var cueStart, cueEnd; + var time = startTime || 0; + if (time < 0) { + time = 0; + } + time = time + now; + if (typeof rate !== "undefined") { + this.rate(rate); + } + if (typeof amp !== "undefined") { + this.setVolume(amp); + } + // TO DO: if already playing, create array of buffers for easy stop() + if (this.buffer) { + // reset the pause time (if it was paused) + this._pauseTime = 0; + // handle restart playmode + if (this.mode === "restart" && this.buffer && this.bufferSourceNode) { + this.bufferSourceNode.stop(time); + this._counterNode.stop(time); + } + //dont create another instance if already playing + if (this.mode === "untildone" && this.isPlaying()) { + return; + } + // make a new source and counter. They are automatically assigned playbackRate and buffer + this.bufferSourceNode = this._initSourceNode(); + // garbage collect counterNode and create a new one + delete this._counterNode; + this._counterNode = this._initCounterNode(); + if (_cueStart) { + if (_cueStart >= 0 && _cueStart < this.buffer.duration) { + // this.startTime = cueStart; + cueStart = _cueStart; + } else { + throw "start time out of range"; + } + } else { + cueStart = 0; + } + if (duration) { + // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error + duration = + duration <= this.buffer.duration - cueStart + ? duration + : this.buffer.duration; + } + // if it was paused, play at the pause position + if (this._paused) { + this.bufferSourceNode.start(time, this.pauseTime, duration); + this._counterNode.start(time, this.pauseTime, duration); } else { - throw 'start time out of range'; + this.bufferSourceNode.start(time, cueStart, duration); + this._counterNode.start(time, cueStart, duration); } + this._playing = true; + this._paused = false; + // add source to sources array, which is used in stopAll() + this.bufferSourceNodes.push(this.bufferSourceNode); + this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; + this.bufferSourceNode.addEventListener("ended", this._clearOnEnd); } else { - cueStart = 0; + throw "not ready to play file, buffer has yet to load. Try preload()"; } - if (duration) { - // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error - duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration; + // if looping, will restart at original time + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + if (this._looping === true) { + cueEnd = duration ? duration : cueStart - 1e-15; + this.bufferSourceNode.loopStart = cueStart; + this.bufferSourceNode.loopEnd = cueEnd; + this._counterNode.loopStart = cueStart; + this._counterNode.loopEnd = cueEnd; } - // if it was paused, play at the pause position - if (this._paused) { - this.bufferSourceNode.start(time, this.pauseTime, duration); - this._counterNode.start(time, this.pauseTime, duration); + }; + /** + * p5.SoundFile has two play modes: restart and + * sustain. Play Mode determines what happens to a + * p5.SoundFile if it is triggered while in the middle of playback. + * In sustain mode, playback will continue simultaneous to the + * new playback. In restart mode, play() will stop playback + * and start over. With untilDone, a sound will play only if it's + * not already playing. Sustain is the default mode. + * + * @method playMode + * @param {String} str 'restart' or 'sustain' or 'untilDone' + * @example + *
+ * var mySound; + * function preload(){ + * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * function mouseClicked() { + * mySound.playMode('sustain'); + * mySound.play(); + * } + * function keyPressed() { + * mySound.playMode('restart'); + * mySound.play(); + * } + * + *
+ */ + p5.SoundFile.prototype.playMode = function (str) { + var s = str.toLowerCase(); + // if restart, stop all other sounds from playing + if (s === "restart" && this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + var now = p5sound.audiocontext.currentTime; + this.bufferSourceNodes[i].stop(now); + } + } + // set play mode to effect future playback + if (s === "restart" || s === "sustain" || s === "untildone") { + this.mode = s; } else { - this.bufferSourceNode.start(time, cueStart, duration); - this._counterNode.start(time, cueStart, duration); + throw 'Invalid play mode. Must be either "restart" or "sustain"'; } - this._playing = true; - this._paused = false; - // add source to sources array, which is used in stopAll() - this.bufferSourceNodes.push(this.bufferSourceNode); - this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; - this.bufferSourceNode.addEventListener('ended', this._clearOnEnd); - } else { - throw 'not ready to play file, buffer has yet to load. Try preload()'; - } - // if looping, will restart at original time - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; - if (this._looping === true) { - cueEnd = duration ? duration : cueStart - 1e-15; - this.bufferSourceNode.loopStart = cueStart; - this.bufferSourceNode.loopEnd = cueEnd; - this._counterNode.loopStart = cueStart; - this._counterNode.loopEnd = cueEnd; - } - }; - /** - * p5.SoundFile has two play modes: restart and - * sustain. Play Mode determines what happens to a - * p5.SoundFile if it is triggered while in the middle of playback. - * In sustain mode, playback will continue simultaneous to the - * new playback. In restart mode, play() will stop playback - * and start over. With untilDone, a sound will play only if it's - * not already playing. Sustain is the default mode. - * - * @method playMode - * @param {String} str 'restart' or 'sustain' or 'untilDone' - * @example - *
- * var mySound; - * function preload(){ - * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * function mouseClicked() { - * mySound.playMode('sustain'); - * mySound.play(); - * } - * function keyPressed() { - * mySound.playMode('restart'); - * mySound.play(); - * } - * - *
- */ - p5.SoundFile.prototype.playMode = function (str) { - var s = str.toLowerCase(); - // if restart, stop all other sounds from playing - if (s === 'restart' && this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - var now = p5sound.audiocontext.currentTime; - this.bufferSourceNodes[i].stop(now); + }; + /** + * Pauses a file that is currently playing. If the file is not + * playing, then nothing will happen. + * + * After pausing, .play() will resume from the paused + * position. + * If p5.SoundFile had been set to loop before it was paused, + * it will continue to loop after it is unpaused with .play(). + * + * @method pause + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @example + *
+ * var soundFile; + * + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); + * } + * function setup() { + * background(0, 255, 0); + * soundFile.setVolume(0.1); + * soundFile.loop(); + * } + * function keyTyped() { + * if (key == 'p') { + * soundFile.pause(); + * background(255, 0, 0); + * } + * } + * + * function keyReleased() { + * if (key == 'p') { + * soundFile.play(); + * background(0, 255, 0); + * } + * } + * + *
+ */ + p5.SoundFile.prototype.pause = function (startTime) { + var now = p5sound.audiocontext.currentTime; + var time = startTime || 0; + var pTime = time + now; + if (this.isPlaying() && this.buffer && this.bufferSourceNode) { + this.pauseTime = this.currentTime(); + this.bufferSourceNode.stop(pTime); + this._counterNode.stop(pTime); + this._paused = true; + this._playing = false; + this._pauseTime = this.currentTime(); + } else { + this._pauseTime = 0; } - } - // set play mode to effect future playback - if (s === 'restart' || s === 'sustain' || s === 'untildone') { - this.mode = s; - } else { - throw 'Invalid play mode. Must be either "restart" or "sustain"'; - } - }; - /** - * Pauses a file that is currently playing. If the file is not - * playing, then nothing will happen. - * - * After pausing, .play() will resume from the paused - * position. - * If p5.SoundFile had been set to loop before it was paused, - * it will continue to loop after it is unpaused with .play(). - * - * @method pause - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @example - *
- * var soundFile; - * - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); - * } - * function setup() { - * background(0, 255, 0); - * soundFile.setVolume(0.1); - * soundFile.loop(); - * } - * function keyTyped() { - * if (key == 'p') { - * soundFile.pause(); - * background(255, 0, 0); - * } - * } - * - * function keyReleased() { - * if (key == 'p') { - * soundFile.play(); - * background(0, 255, 0); - * } - * } - * - *
- */ - p5.SoundFile.prototype.pause = function (startTime) { - var now = p5sound.audiocontext.currentTime; - var time = startTime || 0; - var pTime = time + now; - if (this.isPlaying() && this.buffer && this.bufferSourceNode) { - this.pauseTime = this.currentTime(); - this.bufferSourceNode.stop(pTime); - this._counterNode.stop(pTime); - this._paused = true; - this._playing = false; - this._pauseTime = this.currentTime(); - } else { - this._pauseTime = 0; - } - }; - /** - * Loop the p5.SoundFile. Accepts optional parameters to set the - * playback rate, playback volume, loopStart, loopEnd. - * - * @method loop - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) playback volume - * @param {Number} [cueLoopStart] (optional) startTime in seconds - * @param {Number} [duration] (optional) loop duration in seconds - */ - p5.SoundFile.prototype.loop = function (startTime, rate, amp, loopStart, duration) { - this._looping = true; - this.play(startTime, rate, amp, loopStart, duration); - }; - /** - * Set a p5.SoundFile's looping flag to true or false. If the sound - * is currently playing, this change will take effect when it - * reaches the end of the current playback. - * - * @method setLoop - * @param {Boolean} Boolean set looping to true or false - */ - p5.SoundFile.prototype.setLoop = function (bool) { - if (bool === true) { + }; + /** + * Loop the p5.SoundFile. Accepts optional parameters to set the + * playback rate, playback volume, loopStart, loopEnd. + * + * @method loop + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) playback volume + * @param {Number} [cueLoopStart] (optional) startTime in seconds + * @param {Number} [duration] (optional) loop duration in seconds + */ + p5.SoundFile.prototype.loop = function ( + startTime, + rate, + amp, + loopStart, + duration + ) { this._looping = true; - } else if (bool === false) { - this._looping = false; - } else { - throw 'Error: setLoop accepts either true or false'; - } - if (this.bufferSourceNode) { - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; - } - }; - /** - * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. - * - * @method isLooping - * @return {Boolean} - */ - p5.SoundFile.prototype.isLooping = function () { - if (!this.bufferSourceNode) { + this.play(startTime, rate, amp, loopStart, duration); + }; + /** + * Set a p5.SoundFile's looping flag to true or false. If the sound + * is currently playing, this change will take effect when it + * reaches the end of the current playback. + * + * @method setLoop + * @param {Boolean} Boolean set looping to true or false + */ + p5.SoundFile.prototype.setLoop = function (bool) { + if (bool === true) { + this._looping = true; + } else if (bool === false) { + this._looping = false; + } else { + throw "Error: setLoop accepts either true or false"; + } + if (this.bufferSourceNode) { + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + } + }; + /** + * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. + * + * @method isLooping + * @return {Boolean} + */ + p5.SoundFile.prototype.isLooping = function () { + if (!this.bufferSourceNode) { + return false; + } + if (this._looping === true && this.isPlaying() === true) { + return true; + } return false; - } - if (this._looping === true && this.isPlaying() === true) { - return true; - } - return false; - }; - /** - * Returns true if a p5.SoundFile is playing, false if not (i.e. - * paused or stopped). - * - * @method isPlaying - * @return {Boolean} - */ - p5.SoundFile.prototype.isPlaying = function () { - return this._playing; - }; - /** - * Returns true if a p5.SoundFile is paused, false if not (i.e. - * playing or stopped). - * - * @method isPaused - * @return {Boolean} - */ - p5.SoundFile.prototype.isPaused = function () { - return this._paused; - }; - /** - * Stop soundfile playback. - * - * @method stop - * @param {Number} [startTime] (optional) schedule event to occur - * in seconds from now - */ - p5.SoundFile.prototype.stop = function (timeFromNow) { - var time = timeFromNow || 0; - if (this.mode === 'sustain' || this.mode === 'untildone') { - this.stopAll(time); - this._playing = false; - this.pauseTime = 0; - this._paused = false; - } else if (this.buffer && this.bufferSourceNode) { + }; + /** + * Returns true if a p5.SoundFile is playing, false if not (i.e. + * paused or stopped). + * + * @method isPlaying + * @return {Boolean} + */ + p5.SoundFile.prototype.isPlaying = function () { + return this._playing; + }; + /** + * Returns true if a p5.SoundFile is paused, false if not (i.e. + * playing or stopped). + * + * @method isPaused + * @return {Boolean} + */ + p5.SoundFile.prototype.isPaused = function () { + return this._paused; + }; + /** + * Stop soundfile playback. + * + * @method stop + * @param {Number} [startTime] (optional) schedule event to occur + * in seconds from now + */ + p5.SoundFile.prototype.stop = function (timeFromNow) { + var time = timeFromNow || 0; + if (this.mode === "sustain" || this.mode === "untildone") { + this.stopAll(time); + this._playing = false; + this.pauseTime = 0; + this._paused = false; + } else if (this.buffer && this.bufferSourceNode) { + var now = p5sound.audiocontext.currentTime; + var t = time || 0; + this.pauseTime = 0; + this.bufferSourceNode.stop(now + t); + this._counterNode.stop(now + t); + this._playing = false; + this._paused = false; + } + }; + /** + * Stop playback on all of this soundfile's sources. + * @private + */ + p5.SoundFile.prototype.stopAll = function (_time) { var now = p5sound.audiocontext.currentTime; - var t = time || 0; - this.pauseTime = 0; - this.bufferSourceNode.stop(now + t); - this._counterNode.stop(now + t); - this._playing = false; - this._paused = false; - } - }; - /** - * Stop playback on all of this soundfile's sources. - * @private - */ - p5.SoundFile.prototype.stopAll = function (_time) { - var now = p5sound.audiocontext.currentTime; - var time = _time || 0; - if (this.buffer && this.bufferSourceNode) { - for (var i in this.bufferSourceNodes) { - const bufferSourceNode = this.bufferSourceNodes[i]; - if (!!bufferSourceNode) { - try { - bufferSourceNode.stop(now + time); - } catch (e) { + var time = _time || 0; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + const bufferSourceNode = this.bufferSourceNodes[i]; + if (!!bufferSourceNode) { + try { + bufferSourceNode.stop(now + time); + } catch (e) {} } } + this._counterNode.stop(now + time); + this._onended(this); + } + }; + /** + * Multiply the output volume (amplitude) of a sound file + * between 0.0 (silence) and 1.0 (full volume). + * 1.0 is the maximum amplitude of a digital sound, so multiplying + * by greater than 1.0 may cause digital distortion. To + * fade, provide a rampTime parameter. For more + * complex fades, see the Envelope class. + * + * Alternately, you can pass in a signal source such as an + * oscillator to modulate the amplitude with an audio signal. + * + * @method setVolume + * @param {Number|Object} volume Volume (amplitude) between 0.0 + * and 1.0 or modulating signal/oscillator + * @param {Number} [rampTime] Fade for t seconds + * @param {Number} [timeFromNow] Schedule this event to happen at + * t seconds in the future + */ + p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) { + if (typeof vol === "number") { + var rampTime = _rampTime || 0; + var tFromNow = _tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now + tFromNow); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(this.output.gain); + } else { + // return the Gain Node + return this.output.gain; + } + }; + // same as setVolume, to match Processing Sound + p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume; + // these are the same thing + p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume; + p5.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }; + /** + * Set the stereo panning of a p5.sound object to + * a floating point number between -1.0 (left) and 1.0 (right). + * Default is 0.0 (center). + * + * @method pan + * @param {Number} [panValue] Set the stereo panner + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @example + *
+ * + * var ball = {}; + * var soundFile; + * + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/beatbox.mp3'); + * } + * + * function draw() { + * background(0); + * ball.x = constrain(mouseX, 0, width); + * ellipse(ball.x, height/2, 20, 20) + * } + * + * function mousePressed(){ + * // map the ball's x location to a panning degree + * // between -1.0 (left) and 1.0 (right) + * var panning = map(ball.x, 0., width,-1.0, 1.0); + * soundFile.pan(panning); + * soundFile.play(); + * } + *
+ */ + p5.SoundFile.prototype.pan = function (pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + }; + /** + * Returns the current stereo pan position (-1.0 to 1.0) + * + * @method getPan + * @return {Number} Returns the stereo pan setting of the Oscillator + * as a number between -1.0 (left) and 1.0 (right). + * 0.0 is center and default. + */ + p5.SoundFile.prototype.getPan = function () { + return this.panPosition; + }; + /** + * Set the playback rate of a sound file. Will change the speed and the pitch. + * Values less than zero will reverse the audio buffer. + * + * @method rate + * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, + * .5 is half-speed, 2.0 is twice as fast. + * Values less than zero play backwards. + * @example + *
+ * var song; + * + * function preload() { + * song = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * song.loop(); + * } + * + * function draw() { + * background(200); + * + * // Set the rate to a range between 0.1 and 4 + * // Changing the rate also alters the pitch + * var speed = map(mouseY, 0.1, height, 0, 2); + * speed = constrain(speed, 0.01, 4); + * song.rate(speed); + * + * // Draw a circle to show what is going on + * stroke(0); + * fill(51, 100); + * ellipse(mouseX, 100, 48, 48); + * } + * + * + *
+ * + */ + p5.SoundFile.prototype.rate = function (playbackRate) { + var reverse = false; + if (typeof playbackRate === "undefined") { + return this.playbackRate; + } + this.playbackRate = playbackRate; + if (playbackRate === 0) { + playbackRate = 1e-13; + } else if (playbackRate < 0 && !this.reversed) { + playbackRate = Math.abs(playbackRate); + reverse = true; + } else if (playbackRate > 0 && this.reversed) { + reverse = true; + } + if (this.bufferSourceNode) { + var now = p5sound.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(now); + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(playbackRate), + now + ); + this._counterNode.playbackRate.cancelScheduledValues(now); + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(playbackRate), + now + ); + } + if (reverse) { + this.reverseBuffer(); } - this._counterNode.stop(now + time); - this._onended(this); - } - }; - /** - * Multiply the output volume (amplitude) of a sound file - * between 0.0 (silence) and 1.0 (full volume). - * 1.0 is the maximum amplitude of a digital sound, so multiplying - * by greater than 1.0 may cause digital distortion. To - * fade, provide a rampTime parameter. For more - * complex fades, see the Envelope class. - * - * Alternately, you can pass in a signal source such as an - * oscillator to modulate the amplitude with an audio signal. - * - * @method setVolume - * @param {Number|Object} volume Volume (amplitude) between 0.0 - * and 1.0 or modulating signal/oscillator - * @param {Number} [rampTime] Fade for t seconds - * @param {Number} [timeFromNow] Schedule this event to happen at - * t seconds in the future - */ - p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) { - if (typeof vol === 'number') { - var rampTime = _rampTime || 0; - var tFromNow = _tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now + tFromNow); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(this.output.gain); - } else { - // return the Gain Node - return this.output.gain; - } - }; - // same as setVolume, to match Processing Sound - p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume; - // these are the same thing - p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume; - p5.SoundFile.prototype.getVolume = function () { - return this.output.gain.value; - }; - /** - * Set the stereo panning of a p5.sound object to - * a floating point number between -1.0 (left) and 1.0 (right). - * Default is 0.0 (center). - * - * @method pan - * @param {Number} [panValue] Set the stereo panner - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @example - *
- * - * var ball = {}; - * var soundFile; - * - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/beatbox.mp3'); - * } - * - * function draw() { - * background(0); - * ball.x = constrain(mouseX, 0, width); - * ellipse(ball.x, height/2, 20, 20) - * } - * - * function mousePressed(){ - * // map the ball's x location to a panning degree - * // between -1.0 (left) and 1.0 (right) - * var panning = map(ball.x, 0., width,-1.0, 1.0); - * soundFile.pan(panning); - * soundFile.play(); - * } - *
- */ - p5.SoundFile.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); - }; - /** - * Returns the current stereo pan position (-1.0 to 1.0) - * - * @method getPan - * @return {Number} Returns the stereo pan setting of the Oscillator - * as a number between -1.0 (left) and 1.0 (right). - * 0.0 is center and default. - */ - p5.SoundFile.prototype.getPan = function () { - return this.panPosition; - }; - /** - * Set the playback rate of a sound file. Will change the speed and the pitch. - * Values less than zero will reverse the audio buffer. - * - * @method rate - * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, - * .5 is half-speed, 2.0 is twice as fast. - * Values less than zero play backwards. - * @example - *
- * var song; - * - * function preload() { - * song = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * song.loop(); - * } - * - * function draw() { - * background(200); - * - * // Set the rate to a range between 0.1 and 4 - * // Changing the rate also alters the pitch - * var speed = map(mouseY, 0.1, height, 0, 2); - * speed = constrain(speed, 0.01, 4); - * song.rate(speed); - * - * // Draw a circle to show what is going on - * stroke(0); - * fill(51, 100); - * ellipse(mouseX, 100, 48, 48); - * } - * - * - *
- * - */ - p5.SoundFile.prototype.rate = function (playbackRate) { - var reverse = false; - if (typeof playbackRate === 'undefined') { return this.playbackRate; - } - this.playbackRate = playbackRate; - if (playbackRate === 0) { - playbackRate = 1e-13; - } else if (playbackRate < 0 && !this.reversed) { - playbackRate = Math.abs(playbackRate); - reverse = true; - } else if (playbackRate > 0 && this.reversed) { - reverse = true; - } - if (this.bufferSourceNode) { - var now = p5sound.audiocontext.currentTime; - this.bufferSourceNode.playbackRate.cancelScheduledValues(now); - this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - this._counterNode.playbackRate.cancelScheduledValues(now); - this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - } - if (reverse) { - this.reverseBuffer(); - } - return this.playbackRate; - }; - // TO DO: document this - p5.SoundFile.prototype.setPitch = function (num) { - var newPlaybackRate = midiToFreq(num) / midiToFreq(60); - this.rate(newPlaybackRate); - }; - p5.SoundFile.prototype.getPlaybackRate = function () { - return this.playbackRate; - }; - /** - * Returns the duration of a sound file in seconds. - * - * @method duration - * @return {Number} The duration of the soundFile in seconds. - */ - p5.SoundFile.prototype.duration = function () { - // Return Duration - if (this.buffer) { - return this.buffer.duration; - } else { - return 0; - } - }; - /** - * Return the current position of the p5.SoundFile playhead, in seconds. - * Time is relative to the normal buffer direction, so if `reverseBuffer` - * has been called, currentTime will count backwards. - * - * @method currentTime - * @return {Number} currentTime of the soundFile in seconds. - */ - p5.SoundFile.prototype.currentTime = function () { - return this.reversed ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate : this._lastPos / ac.sampleRate; - }; - /** - * Move the playhead of the song to a position, in seconds. Start timing - * and playback duration. If none are given, will reset the file to play - * entire duration from start to finish. - * - * @method jump - * @param {Number} cueTime cueTime of the soundFile in seconds. - * @param {Number} duration duration in seconds. - */ - p5.SoundFile.prototype.jump = function (cueTime, duration) { - if (cueTime < 0 || cueTime > this.buffer.duration) { - throw 'jump time out of range'; - } - if (duration > this.buffer.duration - cueTime) { - throw 'end time out of range'; - } - var cTime = cueTime || 0; - var dur = duration || undefined; - if (this.isPlaying()) { - this.stop(0); - } - this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); - }; - /** - * Return the number of channels in a sound file. - * For example, Mono = 1, Stereo = 2. - * - * @method channels - * @return {Number} [channels] - */ - p5.SoundFile.prototype.channels = function () { - return this.buffer.numberOfChannels; - }; - /** - * Return the sample rate of the sound file. - * - * @method sampleRate - * @return {Number} [sampleRate] - */ - p5.SoundFile.prototype.sampleRate = function () { - return this.buffer.sampleRate; - }; - /** - * Return the number of samples in a sound file. - * Equal to sampleRate * duration. - * - * @method frames - * @return {Number} [sampleCount] - */ - p5.SoundFile.prototype.frames = function () { - return this.buffer.length; - }; - /** - * Returns an array of amplitude peaks in a p5.SoundFile that can be - * used to draw a static waveform. Scans through the p5.SoundFile's - * audio buffer to find the greatest amplitudes. Accepts one - * parameter, 'length', which determines size of the array. - * Larger arrays result in more precise waveform visualizations. - * - * Inspired by Wavesurfer.js. - * - * @method getPeaks - * @params {Number} [length] length is the size of the returned array. - * Larger length results in more precision. - * Defaults to 5*width of the browser window. - * @returns {Float32Array} Array of peaks. - */ - p5.SoundFile.prototype.getPeaks = function (length) { - if (this.buffer) { - // set length to window's width if no length is provided - if (!length) { - length = window.width * 5; + }; + // TO DO: document this + p5.SoundFile.prototype.setPitch = function (num) { + var newPlaybackRate = midiToFreq(num) / midiToFreq(60); + this.rate(newPlaybackRate); + }; + p5.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }; + /** + * Returns the duration of a sound file in seconds. + * + * @method duration + * @return {Number} The duration of the soundFile in seconds. + */ + p5.SoundFile.prototype.duration = function () { + // Return Duration + if (this.buffer) { + return this.buffer.duration; + } else { + return 0; + } + }; + /** + * Return the current position of the p5.SoundFile playhead, in seconds. + * Time is relative to the normal buffer direction, so if `reverseBuffer` + * has been called, currentTime will count backwards. + * + * @method currentTime + * @return {Number} currentTime of the soundFile in seconds. + */ + p5.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate + : this._lastPos / ac.sampleRate; + }; + /** + * Move the playhead of the song to a position, in seconds. Start timing + * and playback duration. If none are given, will reset the file to play + * entire duration from start to finish. + * + * @method jump + * @param {Number} cueTime cueTime of the soundFile in seconds. + * @param {Number} duration duration in seconds. + */ + p5.SoundFile.prototype.jump = function (cueTime, duration) { + if (cueTime < 0 || cueTime > this.buffer.duration) { + throw "jump time out of range"; + } + if (duration > this.buffer.duration - cueTime) { + throw "end time out of range"; } + var cTime = cueTime || 0; + var dur = duration || undefined; + if (this.isPlaying()) { + this.stop(0); + } + this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); + }; + /** + * Return the number of channels in a sound file. + * For example, Mono = 1, Stereo = 2. + * + * @method channels + * @return {Number} [channels] + */ + p5.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }; + /** + * Return the sample rate of the sound file. + * + * @method sampleRate + * @return {Number} [sampleRate] + */ + p5.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }; + /** + * Return the number of samples in a sound file. + * Equal to sampleRate * duration. + * + * @method frames + * @return {Number} [sampleCount] + */ + p5.SoundFile.prototype.frames = function () { + return this.buffer.length; + }; + /** + * Returns an array of amplitude peaks in a p5.SoundFile that can be + * used to draw a static waveform. Scans through the p5.SoundFile's + * audio buffer to find the greatest amplitudes. Accepts one + * parameter, 'length', which determines size of the array. + * Larger arrays result in more precise waveform visualizations. + * + * Inspired by Wavesurfer.js. + * + * @method getPeaks + * @params {Number} [length] length is the size of the returned array. + * Larger length results in more precision. + * Defaults to 5*width of the browser window. + * @returns {Float32Array} Array of peaks. + */ + p5.SoundFile.prototype.getPeaks = function (length) { if (this.buffer) { - var buffer = this.buffer; - var sampleSize = buffer.length / length; - var sampleStep = ~~(sampleSize / 10) || 1; - var channels = buffer.numberOfChannels; - var peaks = new Float32Array(Math.round(length)); - for (var c = 0; c < channels; c++) { - var chan = buffer.getChannelData(c); - for (var i = 0; i < length; i++) { - var start = ~~(i * sampleSize); - var end = ~~(start + sampleSize); - var max = 0; - for (var j = start; j < end; j += sampleStep) { - var value = chan[j]; - if (value > max) { - max = value; - } else if (-value > max) { - max = value; + // set length to window's width if no length is provided + if (!length) { + length = window.width * 5; + } + if (this.buffer) { + var buffer = this.buffer; + var sampleSize = buffer.length / length; + var sampleStep = ~~(sampleSize / 10) || 1; + var channels = buffer.numberOfChannels; + var peaks = new Float32Array(Math.round(length)); + for (var c = 0; c < channels; c++) { + var chan = buffer.getChannelData(c); + for (var i = 0; i < length; i++) { + var start = ~~(i * sampleSize); + var end = ~~(start + sampleSize); + var max = 0; + for (var j = start; j < end; j += sampleStep) { + var value = chan[j]; + if (value > max) { + max = value; + } else if (-value > max) { + max = value; + } + } + if (c === 0 || Math.abs(max) > peaks[i]) { + peaks[i] = max; } - } - if (c === 0 || Math.abs(max) > peaks[i]) { - peaks[i] = max; } } + return peaks; } - return peaks; + } else { + throw "Cannot load peaks yet, buffer is not loaded"; } - } else { - throw 'Cannot load peaks yet, buffer is not loaded'; - } - }; - /** - * Reverses the p5.SoundFile's buffer source. - * Playback must be handled separately (see example). - * - * @method reverseBuffer - * @example - *
- * var drum; - * - * function preload() { - * drum = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * drum.reverseBuffer(); - * drum.play(); - * } - * - * - *
- */ - p5.SoundFile.prototype.reverseBuffer = function () { - if (this.buffer) { - var currentPos = this._lastPos / ac.sampleRate; - var curVol = this.getVolume(); - this.setVolume(0, 0.001); - const numChannels = this.buffer.numberOfChannels; - for (var i = 0; i < numChannels; i++) { - this.buffer.getChannelData(i).reverse(); - } - // set reversed flag - this.reversed = !this.reversed; - if (currentPos) { - this.jump(this.duration() - currentPos); - } - this.setVolume(curVol, 0.001); - } else { - throw 'SoundFile is not done loading'; - } - }; - /** - * Schedule an event to be called when the soundfile - * reaches the end of a buffer. If the soundfile is - * playing through once, this will be called when it - * ends. If it is looping, it will be called when - * stop is called. - * - * @method onended - * @param {Function} callback function to call when the - * soundfile has ended. - */ - p5.SoundFile.prototype.onended = function (callback) { - this._onended = callback; - return this; - }; - p5.SoundFile.prototype.add = function () { - }; - p5.SoundFile.prototype.dispose = function () { - var now = p5sound.audiocontext.currentTime; - // remove reference to soundfile - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.stop(now); - if (this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - if (this.bufferSourceNodes[i] !== null) { - this.bufferSourceNodes[i].disconnect(); + }; + /** + * Reverses the p5.SoundFile's buffer source. + * Playback must be handled separately (see example). + * + * @method reverseBuffer + * @example + *
+ * var drum; + * + * function preload() { + * drum = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * drum.reverseBuffer(); + * drum.play(); + * } + * + * + *
+ */ + p5.SoundFile.prototype.reverseBuffer = function () { + if (this.buffer) { + var currentPos = this._lastPos / ac.sampleRate; + var curVol = this.getVolume(); + this.setVolume(0, 0.001); + const numChannels = this.buffer.numberOfChannels; + for (var i = 0; i < numChannels; i++) { + this.buffer.getChannelData(i).reverse(); + } + // set reversed flag + this.reversed = !this.reversed; + if (currentPos) { + this.jump(this.duration() - currentPos); + } + this.setVolume(curVol, 0.001); + } else { + throw "SoundFile is not done loading"; + } + }; + /** + * Schedule an event to be called when the soundfile + * reaches the end of a buffer. If the soundfile is + * playing through once, this will be called when it + * ends. If it is looping, it will be called when + * stop is called. + * + * @method onended + * @param {Function} callback function to call when the + * soundfile has ended. + */ + p5.SoundFile.prototype.onended = function (callback) { + this._onended = callback; + return this; + }; + p5.SoundFile.prototype.add = function () {}; + p5.SoundFile.prototype.dispose = function () { + var now = p5sound.audiocontext.currentTime; + // remove reference to soundfile + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.stop(now); + if (this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + if (this.bufferSourceNodes[i] !== null) { + this.bufferSourceNodes[i].disconnect(); + try { + this.bufferSourceNodes[i].stop(now); + } catch (e) { + console.warning("no buffer source node to dispose"); + } + this.bufferSourceNodes[i] = null; + } + } + if (this.isPlaying()) { try { - this.bufferSourceNodes[i].stop(now); + this._counterNode.stop(now); } catch (e) { - console.warning('no buffer source node to dispose'); + console.log(e); } - this.bufferSourceNodes[i] = null; + this._counterNode = null; } } - if (this.isPlaying()) { - try { - this._counterNode.stop(now); - } catch (e) { - console.log(e); - } - this._counterNode = null; + if (this.output) { + this.output.disconnect(); + this.output = null; } - } - if (this.output) { - this.output.disconnect(); - this.output = null; - } - if (this.panner) { - this.panner.disconnect(); - this.panner = null; - } - }; - /** - * Connects the output of a p5sound object to input of another - * p5.sound object. For example, you may connect a p5.SoundFile to an - * FFT or an Effect. If no parameter is given, it will connect to - * the master output. Most p5sound objects connect to the master - * output when they are created. - * - * @method connect - * @param {Object} [object] Audio object that accepts an input - */ - p5.SoundFile.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(p5sound.input); - } else { - if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); + if (this.panner) { + this.panner.disconnect(); + this.panner = null; + } + }; + /** + * Connects the output of a p5sound object to input of another + * p5.sound object. For example, you may connect a p5.SoundFile to an + * FFT or an Effect. If no parameter is given, it will connect to + * the master output. Most p5sound objects connect to the master + * output when they are created. + * + * @method connect + * @param {Object} [object] Audio object that accepts an input + */ + p5.SoundFile.prototype.connect = function (unit) { + if (!unit) { + this.panner.connect(p5sound.input); } else { - this.panner.connect(unit); + if (unit.hasOwnProperty("input")) { + this.panner.connect(unit.input); + } else { + this.panner.connect(unit); + } } - } - }; - /** - * Disconnects the output of this p5sound object. - * - * @method disconnect - */ - p5.SoundFile.prototype.disconnect = function () { - if (this.panner) { - this.panner.disconnect(); - } - }; - /** - */ - p5.SoundFile.prototype.getLevel = function () { - console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'); - }; - /** - * Reset the source for this SoundFile to a - * new path (URL). - * - * @method setPath - * @param {String} path path to audio file - * @param {Function} callback Callback - */ - p5.SoundFile.prototype.setPath = function (p, callback) { - var path = p5.prototype._checkFileFormats(p); - this.url = path; - this.load(callback); - }; - /** - * Replace the current Audio Buffer with a new Buffer. - * - * @method setBuffer - * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays - * will create a stereo source. 1 will create - * a mono source. - */ - p5.SoundFile.prototype.setBuffer = function (buf) { - var numChannels = buf.length; - var size = buf[0].length; - var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate); - if (!(buf[0] instanceof Float32Array)) { - buf[0] = new Float32Array(buf[0]); - } - for (var channelNum = 0; channelNum < numChannels; channelNum++) { - var channel = newBuffer.getChannelData(channelNum); - channel.set(buf[channelNum]); - } - this.buffer = newBuffer; - // set numbers of channels on input to the panner - this.panner.inputChannels(numChannels); - }; - ////////////////////////////////////////////////// - // script processor node with an empty buffer to help - // keep a sample-accurate position in playback buffer. - // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV - // Copyright [2015] [Sonoport (Asia) Pte. Ltd.], - // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0 - //////////////////////////////////////////////////////////////////////////////////// - var _createCounterBuffer = function (buffer) { - const len = buffer.length; - const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate); - const arrayBuffer = audioBuf.getChannelData(0); - for (var index = 0; index < len; index++) { - arrayBuffer[index] = index; - } - return audioBuf; - }; - // initialize counterNode, set its initial buffer and playbackRate - p5.SoundFile.prototype._initCounterNode = function () { - var self = this; - var now = ac.currentTime; - var cNode = ac.createBufferSource(); - // dispose of scope node if it already exists - if (self._scopeNode) { - self._scopeNode.disconnect(); - self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess); - delete self._scopeNode; - } - self._scopeNode = ac.createScriptProcessor(256, 1, 1); - // create counter buffer of the same length as self.buffer - cNode.buffer = _createCounterBuffer(self.buffer); - cNode.playbackRate.setValueAtTime(self.playbackRate, now); - cNode.connect(self._scopeNode); - self._scopeNode.connect(p5.soundOut._silentNode); - self._scopeNode.addEventListener('audioprocess', self._onAudioProcess); - return cNode; - }; - // initialize sourceNode, set its initial buffer and playbackRate - p5.SoundFile.prototype._initSourceNode = function () { - var bufferSourceNode = ac.createBufferSource(); - bufferSourceNode.buffer = this.buffer; - bufferSourceNode.playbackRate.value = this.playbackRate; - bufferSourceNode.connect(this.output); - return bufferSourceNode; - }; - /** - * processPeaks returns an array of timestamps where it thinks there is a beat. - * - * This is an asynchronous function that processes the soundfile in an offline audio context, - * and sends the results to your callback function. - * - * The process involves running the soundfile through a lowpass filter, and finding all of the - * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, - * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. - * - * @method processPeaks - * @param {Function} callback a function to call once this data is returned - * @param {Number} [initThreshold] initial threshold defaults to 0.9 - * @param {Number} [minThreshold] minimum threshold defaults to 0.22 - * @param {Number} [minPeaks] minimum number of peaks defaults to 200 - * @return {Array} Array of timestamped peaks - */ - p5.SoundFile.prototype.processPeaks = function (callback, _initThreshold, _minThreshold, _minPeaks) { - var bufLen = this.buffer.length; - var sampleRate = this.buffer.sampleRate; - var buffer = this.buffer; - var allPeaks = []; - var initialThreshold = _initThreshold || 0.9, threshold = initialThreshold, minThreshold = _minThreshold || 0.22, minPeaks = _minPeaks || 200; - // Create offline context - var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate); - // create buffer source - var source = offlineContext.createBufferSource(); - source.buffer = buffer; - // Create filter. TO DO: allow custom setting of filter - var filter = offlineContext.createBiquadFilter(); - filter.type = 'lowpass'; - source.connect(filter); - filter.connect(offlineContext.destination); - // start playing at time:0 - source.start(0); - offlineContext.startRendering(); - // Render the song - // act on the result - offlineContext.oncomplete = function (e) { - if (!self.panner) - return; - var filteredBuffer = e.renderedBuffer; - var bufferData = filteredBuffer.getChannelData(0); - // step 1: - // create Peak instances, add them to array, with strength and sampleIndex - do { - allPeaks = getPeaksAtThreshold(bufferData, threshold); - threshold -= 0.005; - } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold); - // step 2: - // find intervals for each peak in the sampleIndex, add tempos array - var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); - // step 3: find top tempos - var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate); - // sort top intervals - var topTempos = groups.sort(function (intA, intB) { - return intB.count - intA.count; - }).splice(0, 5); - // set this SoundFile's tempo to the top tempo ?? - this.tempo = topTempos[0].tempo; - // step 4: - // new array of peaks at top tempo within a bpmVariance - var bpmVariance = 5; - var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance); - callback(tempoPeaks); - }; - }; - // process peaks - var Peak = function (amp, i) { - this.sampleIndex = i; - this.amplitude = amp; - this.tempos = []; - this.intervals = []; - }; - // 1. for processPeaks() Function to identify peaks above a threshold - // returns an array of peak indexes as frames (samples) of the original soundfile - function getPeaksAtThreshold(data, threshold) { - var peaksObj = {}; - var length = data.length; - for (var i = 0; i < length; i++) { - if (data[i] > threshold) { - var amp = data[i]; - var peak = new Peak(amp, i); - peaksObj[i] = peak; - // Skip forward ~ 1/8s to get past this peak. - i += 6000; - } - i++; - } - return peaksObj; - } - // 2. for processPeaks() - function countIntervalsBetweenNearbyPeaks(peaksObj) { - var intervalCounts = []; - var peaksArray = Object.keys(peaksObj).sort(); - for (var index = 0; index < peaksArray.length; index++) { - // find intervals in comparison to nearby peaks - for (var i = 0; i < 10; i++) { - var startPeak = peaksObj[peaksArray[index]]; - var endPeak = peaksObj[peaksArray[index + i]]; - if (startPeak && endPeak) { - var startPos = startPeak.sampleIndex; - var endPos = endPeak.sampleIndex; - var interval = endPos - startPos; - // add a sample interval to the startPeak in the allPeaks array - if (interval > 0) { - startPeak.intervals.push(interval); - } - // tally the intervals and return interval counts - var foundInterval = intervalCounts.some(function (intervalCount) { - if (intervalCount.interval === interval) { - intervalCount.count++; - return intervalCount; + }; + /** + * Disconnects the output of this p5sound object. + * + * @method disconnect + */ + p5.SoundFile.prototype.disconnect = function () { + if (this.panner) { + this.panner.disconnect(); + } + }; + /** + */ + p5.SoundFile.prototype.getLevel = function () { + console.warn( + "p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead" + ); + }; + /** + * Reset the source for this SoundFile to a + * new path (URL). + * + * @method setPath + * @param {String} path path to audio file + * @param {Function} callback Callback + */ + p5.SoundFile.prototype.setPath = function (p, callback) { + var path = p5.prototype._checkFileFormats(p); + this.url = path; + this.load(callback); + }; + /** + * Replace the current Audio Buffer with a new Buffer. + * + * @method setBuffer + * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays + * will create a stereo source. 1 will create + * a mono source. + */ + p5.SoundFile.prototype.setBuffer = function (buf) { + var numChannels = buf.length; + var size = buf[0].length; + var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate); + if (!(buf[0] instanceof Float32Array)) { + buf[0] = new Float32Array(buf[0]); + } + for (var channelNum = 0; channelNum < numChannels; channelNum++) { + var channel = newBuffer.getChannelData(channelNum); + channel.set(buf[channelNum]); + } + this.buffer = newBuffer; + // set numbers of channels on input to the panner + this.panner.inputChannels(numChannels); + }; + ////////////////////////////////////////////////// + // script processor node with an empty buffer to help + // keep a sample-accurate position in playback buffer. + // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV + // Copyright [2015] [Sonoport (Asia) Pte. Ltd.], + // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0 + //////////////////////////////////////////////////////////////////////////////////// + var _createCounterBuffer = function (buffer) { + const len = buffer.length; + const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate); + const arrayBuffer = audioBuf.getChannelData(0); + for (var index = 0; index < len; index++) { + arrayBuffer[index] = index; + } + return audioBuf; + }; + // initialize counterNode, set its initial buffer and playbackRate + p5.SoundFile.prototype._initCounterNode = function () { + var self = this; + var now = ac.currentTime; + var cNode = ac.createBufferSource(); + // dispose of scope node if it already exists + if (self._scopeNode) { + self._scopeNode.disconnect(); + self._scopeNode.removeEventListener( + "audioprocess", + self._onAudioProcess + ); + delete self._scopeNode; + } + self._scopeNode = ac.createScriptProcessor(256, 1, 1); + // create counter buffer of the same length as self.buffer + cNode.buffer = _createCounterBuffer(self.buffer); + cNode.playbackRate.setValueAtTime(self.playbackRate, now); + cNode.connect(self._scopeNode); + self._scopeNode.connect(p5.soundOut._silentNode); + self._scopeNode.addEventListener("audioprocess", self._onAudioProcess); + return cNode; + }; + // initialize sourceNode, set its initial buffer and playbackRate + p5.SoundFile.prototype._initSourceNode = function () { + var bufferSourceNode = ac.createBufferSource(); + bufferSourceNode.buffer = this.buffer; + bufferSourceNode.playbackRate.value = this.playbackRate; + bufferSourceNode.connect(this.output); + return bufferSourceNode; + }; + /** + * processPeaks returns an array of timestamps where it thinks there is a beat. + * + * This is an asynchronous function that processes the soundfile in an offline audio context, + * and sends the results to your callback function. + * + * The process involves running the soundfile through a lowpass filter, and finding all of the + * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, + * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. + * + * @method processPeaks + * @param {Function} callback a function to call once this data is returned + * @param {Number} [initThreshold] initial threshold defaults to 0.9 + * @param {Number} [minThreshold] minimum threshold defaults to 0.22 + * @param {Number} [minPeaks] minimum number of peaks defaults to 200 + * @return {Array} Array of timestamped peaks + */ + p5.SoundFile.prototype.processPeaks = function ( + callback, + _initThreshold, + _minThreshold, + _minPeaks + ) { + var bufLen = this.buffer.length; + var sampleRate = this.buffer.sampleRate; + var buffer = this.buffer; + var allPeaks = []; + var initialThreshold = _initThreshold || 0.9, + threshold = initialThreshold, + minThreshold = _minThreshold || 0.22, + minPeaks = _minPeaks || 200; + // Create offline context + var offlineContext = new window.OfflineAudioContext( + 1, + bufLen, + sampleRate + ); + // create buffer source + var source = offlineContext.createBufferSource(); + source.buffer = buffer; + // Create filter. TO DO: allow custom setting of filter + var filter = offlineContext.createBiquadFilter(); + filter.type = "lowpass"; + source.connect(filter); + filter.connect(offlineContext.destination); + // start playing at time:0 + source.start(0); + offlineContext.startRendering(); + // Render the song + // act on the result + offlineContext.oncomplete = function (e) { + if (!self.panner) return; + var filteredBuffer = e.renderedBuffer; + var bufferData = filteredBuffer.getChannelData(0); + // step 1: + // create Peak instances, add them to array, with strength and sampleIndex + do { + allPeaks = getPeaksAtThreshold(bufferData, threshold); + threshold -= 0.005; + } while ( + Object.keys(allPeaks).length < minPeaks && + threshold >= minThreshold + ); + // step 2: + // find intervals for each peak in the sampleIndex, add tempos array + var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); + // step 3: find top tempos + var groups = groupNeighborsByTempo( + intervalCounts, + filteredBuffer.sampleRate + ); + // sort top intervals + var topTempos = groups + .sort(function (intA, intB) { + return intB.count - intA.count; + }) + .splice(0, 5); + // set this SoundFile's tempo to the top tempo ?? + this.tempo = topTempos[0].tempo; + // step 4: + // new array of peaks at top tempo within a bpmVariance + var bpmVariance = 5; + var tempoPeaks = getPeaksAtTopTempo( + allPeaks, + topTempos[0].tempo, + filteredBuffer.sampleRate, + bpmVariance + ); + callback(tempoPeaks); + }; + }; + // process peaks + var Peak = function (amp, i) { + this.sampleIndex = i; + this.amplitude = amp; + this.tempos = []; + this.intervals = []; + }; + // 1. for processPeaks() Function to identify peaks above a threshold + // returns an array of peak indexes as frames (samples) of the original soundfile + function getPeaksAtThreshold(data, threshold) { + var peaksObj = {}; + var length = data.length; + for (var i = 0; i < length; i++) { + if (data[i] > threshold) { + var amp = data[i]; + var peak = new Peak(amp, i); + peaksObj[i] = peak; + // Skip forward ~ 1/8s to get past this peak. + i += 6000; + } + i++; + } + return peaksObj; + } + // 2. for processPeaks() + function countIntervalsBetweenNearbyPeaks(peaksObj) { + var intervalCounts = []; + var peaksArray = Object.keys(peaksObj).sort(); + for (var index = 0; index < peaksArray.length; index++) { + // find intervals in comparison to nearby peaks + for (var i = 0; i < 10; i++) { + var startPeak = peaksObj[peaksArray[index]]; + var endPeak = peaksObj[peaksArray[index + i]]; + if (startPeak && endPeak) { + var startPos = startPeak.sampleIndex; + var endPos = endPeak.sampleIndex; + var interval = endPos - startPos; + // add a sample interval to the startPeak in the allPeaks array + if (interval > 0) { + startPeak.intervals.push(interval); } - }); - // store with JSON like formatting - if (!foundInterval) { - intervalCounts.push({ - interval: interval, - count: 1 + // tally the intervals and return interval counts + var foundInterval = intervalCounts.some(function (intervalCount) { + if (intervalCount.interval === interval) { + intervalCount.count++; + return intervalCount; + } }); + // store with JSON like formatting + if (!foundInterval) { + intervalCounts.push({ + interval: interval, + count: 1, + }); + } } } } + return intervalCounts; } - return intervalCounts; - } - // 3. for processPeaks --> find tempo - function groupNeighborsByTempo(intervalCounts, sampleRate) { - var tempoCounts = []; - intervalCounts.forEach(function (intervalCount) { - try { - // Convert an interval to tempo - var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate)); - theoreticalTempo = mapTempo(theoreticalTempo); - var foundTempo = tempoCounts.some(function (tempoCount) { - if (tempoCount.tempo === theoreticalTempo) - return tempoCount.count += intervalCount.count; - }); - if (!foundTempo) { - if (isNaN(theoreticalTempo)) { - return; - } - tempoCounts.push({ - tempo: Math.round(theoreticalTempo), - count: intervalCount.count + // 3. for processPeaks --> find tempo + function groupNeighborsByTempo(intervalCounts, sampleRate) { + var tempoCounts = []; + intervalCounts.forEach(function (intervalCount) { + try { + // Convert an interval to tempo + var theoreticalTempo = Math.abs( + 60 / (intervalCount.interval / sampleRate) + ); + theoreticalTempo = mapTempo(theoreticalTempo); + var foundTempo = tempoCounts.some(function (tempoCount) { + if (tempoCount.tempo === theoreticalTempo) + return (tempoCount.count += intervalCount.count); }); + if (!foundTempo) { + if (isNaN(theoreticalTempo)) { + return; + } + tempoCounts.push({ + tempo: Math.round(theoreticalTempo), + count: intervalCount.count, + }); + } + } catch (e) { + throw e; } - } catch (e) { - throw e; - } - }); - return tempoCounts; - } - // 4. for processPeaks - get peaks at top tempo - function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { - var peaksAtTopTempo = []; - var peaksArray = Object.keys(peaksObj).sort(); - // TO DO: filter out peaks that have the tempo and return - for (var i = 0; i < peaksArray.length; i++) { - var key = peaksArray[i]; - var peak = peaksObj[key]; - for (var j = 0; j < peak.intervals.length; j++) { - var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate))); - intervalBPM = mapTempo(intervalBPM); - if (Math.abs(intervalBPM - tempo) < bpmVariance) { - // convert sampleIndex to seconds - peaksAtTopTempo.push(peak.sampleIndex / sampleRate); + }); + return tempoCounts; + } + // 4. for processPeaks - get peaks at top tempo + function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { + var peaksAtTopTempo = []; + var peaksArray = Object.keys(peaksObj).sort(); + // TO DO: filter out peaks that have the tempo and return + for (var i = 0; i < peaksArray.length; i++) { + var key = peaksArray[i]; + var peak = peaksObj[key]; + for (var j = 0; j < peak.intervals.length; j++) { + var intervalBPM = Math.round( + Math.abs(60 / (peak.intervals[j] / sampleRate)) + ); + intervalBPM = mapTempo(intervalBPM); + if (Math.abs(intervalBPM - tempo) < bpmVariance) { + // convert sampleIndex to seconds + peaksAtTopTempo.push(peak.sampleIndex / sampleRate); + } } } + // filter out peaks that are very close to each other + peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { + var dif = arr[index + 1] - peakTime; + if (dif > 0.01) { + return true; + } + }); + return peaksAtTopTempo; } - // filter out peaks that are very close to each other - peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { - var dif = arr[index + 1] - peakTime; - if (dif > 0.01) { - return true; + // helper function for processPeaks + function mapTempo(theoreticalTempo) { + // these scenarios create infinite while loop + if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { + return; } - }); - return peaksAtTopTempo; - } - // helper function for processPeaks - function mapTempo(theoreticalTempo) { - // these scenarios create infinite while loop - if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { - return; - } - // Adjust the tempo to fit within the 90-180 BPM range - while (theoreticalTempo < 90) - theoreticalTempo *= 2; - while (theoreticalTempo > 180 && theoreticalTempo > 90) - theoreticalTempo /= 2; - return theoreticalTempo; - } - /*** SCHEDULE EVENTS ***/ - // Cue inspired by JavaScript setTimeout, and the - // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org - var Cue = function (callback, time, id, val) { - this.callback = callback; - this.time = time; - this.id = id; - this.val = val; - }; - /** - * Schedule events to trigger every time a MediaElement - * (audio/video) reaches a playback cue point. - * - * Accepts a callback function, a time (in seconds) at which to trigger - * the callback, and an optional parameter for the callback. - * - * Time will be passed as the first parameter to the callback function, - * and param will be the second parameter. - * - * - * @method addCue - * @param {Number} time Time in seconds, relative to this media - * element's playback. For example, to trigger - * an event every time playback reaches two - * seconds, pass in the number 2. This will be - * passed as the first parameter to - * the callback function. - * @param {Function} callback Name of a function that will be - * called at the given time. The callback will - * receive time and (optionally) param as its - * two parameters. - * @param {Object} [value] An object to be passed as the - * second parameter to the - * callback function. - * @return {Number} id ID of this cue, - * useful for removeCue(id) - * @example - *
- * var mySound; - * function preload() { - * mySound = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * // schedule calls to changeText - * mySound.addCue(0.50, changeText, "hello" ); - * mySound.addCue(1.00, changeText, "p5" ); - * mySound.addCue(1.50, changeText, "what" ); - * mySound.addCue(2.00, changeText, "do" ); - * mySound.addCue(2.50, changeText, "you" ); - * mySound.addCue(3.00, changeText, "want" ); - * mySound.addCue(4.00, changeText, "to" ); - * mySound.addCue(5.00, changeText, "make" ); - * mySound.addCue(6.00, changeText, "?" ); - * } - * - * function changeText(val) { - * background(0); - * text(val, width/2, height/2); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * if (mySound.isPlaying() ) { - * mySound.stop(); - * } else { - * mySound.play(); - * } - * } - * } - *
- */ - p5.SoundFile.prototype.addCue = function (time, callback, val) { - var id = this._cueIDCounter++; - var cue = new Cue(callback, time, id, val); - this._cues.push(cue); - // if (!this.elt.ontimeupdate) { - // this.elt.ontimeupdate = this._onTimeUpdate.bind(this); - // } - return id; - }; - /** - * Remove a callback based on its ID. The ID is returned by the - * addCue method. - * - * @method removeCue - * @param {Number} id ID of the cue, as returned by addCue - */ - p5.SoundFile.prototype.removeCue = function (id) { - var cueLength = this._cues.length; - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; - if (cue.id === id) { - this._cues.splice(i, 1); - break; - } - } - if (this._cues.length === 0) { - } - }; - /** - * Remove all of the callbacks that had originally been scheduled - * via the addCue method. - * - * @method clearCues - */ - p5.SoundFile.prototype.clearCues = function () { - this._cues = []; - }; - // private method that checks for cues to be fired if events - // have been scheduled using addCue(callback, time). - p5.SoundFile.prototype._onTimeUpdate = function (position) { - var playbackTime = position / this.buffer.sampleRate; - var cueLength = this._cues.length; - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; - var callbackTime = cue.time; - var val = cue.val; - if (this._prevTime < callbackTime && callbackTime <= playbackTime) { - // pass the scheduled callbackTime as parameter to the callback - cue.callback(val); - } - } - this._prevTime = playbackTime; - }; - /** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. To upload a file to a server, see - * getBlob - * - * @method save - * @param {String} [fileName] name of the resulting .wav file. - * @example - *
- * var inp, button, mySound; - * var fileName = 'cool'; - * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * function setup() { - * btn = createButton('click to save file'); - * btn.position(0, 0); - * btn.mouseClicked(handleMouseClick); - * } - * - * function handleMouseClick() { - * mySound.save(fileName); - * } - *
- */ - p5.SoundFile.prototype.save = function (fileName) { - const dataView = convertToWav(this.buffer); - p5.prototype.saveSound([dataView], fileName, 'wav'); - }; - /** - * This method is useful for sending a SoundFile to a server. It returns the - * .wav-encoded audio data as a "Blob". - * A Blob is a file-like data object that can be uploaded to a server - * with an http request. We'll - * use the `httpDo` options object to send a POST request with some - * specific options: we encode the request as `multipart/form-data`, - * and attach the blob as one of the form values using `FormData`. - * - * - * @method getBlob - * @returns {Blob} A file-like data object - * @example - *
- * - * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * noCanvas(); - * var soundBlob = mySound.getBlob(); - * - * // Now we can send the blob to a server... - * var serverUrl = 'https://jsonplaceholder.typicode.com/posts'; - * var httpRequestOptions = { - * method: 'POST', - * body: new FormData().append('soundBlob', soundBlob), - * headers: new Headers({ - * 'Content-Type': 'multipart/form-data' - * }) - * }; - * httpDo(serverUrl, httpRequestOptions); - * - * // We can also create an `ObjectURL` pointing to the Blob - * var blobUrl = URL.createObjectURL(soundBlob); - * - * // The `
- */ - p5.SoundFile.prototype.getBlob = function () { - const dataView = convertToWav(this.buffer); - return new Blob([dataView], { type: 'audio/wav' }); - }; - // event handler to keep track of current position - function _onAudioProcess(processEvent) { - var inputBuffer = processEvent.inputBuffer.getChannelData(0); - this._lastPos = inputBuffer[inputBuffer.length - 1] || 0; - // do any callbacks that have been scheduled - this._onTimeUpdate(self._lastPos); - } - // event handler to remove references to the bufferSourceNode when it is done playing - function _clearOnEnd(e) { - const thisBufferSourceNode = e.target; - const soundFile = this; - // delete this.bufferSourceNode from the sources array when it is done playing: - thisBufferSourceNode._playing = false; - thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd); - // call the onended callback - soundFile._onended(soundFile); - soundFile.bufferSourceNodes.forEach(function (n, i) { - if (n._playing === false) { - soundFile.bufferSourceNodes.splice(i); - } - }); - if (soundFile.bufferSourceNodes.length === 0) { - soundFile._playing = false; - } - } -}(errorHandler, master, helpers, helpers); -var amplitude; -'use strict'; -amplitude = function () { - var p5sound = master; - /** - * Amplitude measures volume between 0.0 and 1.0. - * Listens to all p5sound by default, or use setInput() - * to listen to a specific sound source. Accepts an optional - * smoothing value, which defaults to 0. - * - * @class p5.Amplitude - * @constructor - * @param {Number} [smoothing] between 0.0 and .999 to smooth - * amplitude readings (defaults to 0) - * @example - *
- * var sound, amplitude, cnv; - * - * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } - * function setup() { - * cnv = createCanvas(100,100); - * amplitude = new p5.Amplitude(); - * - * // start / stop the sound when canvas is clicked - * cnv.mouseClicked(function() { - * if (sound.isPlaying() ){ - * sound.stop(); - * } else { - * sound.play(); - * } - * }); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * - *
- */ - p5.Amplitude = function (smoothing) { - // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default - this.bufferSize = 2048; - // set audio context - this.audiocontext = p5sound.audiocontext; - this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1); - // for connections - this.input = this.processor; - this.output = this.audiocontext.createGain(); - // smoothing defaults to 0 - this.smoothing = smoothing || 0; - // the variables to return - this.volume = 0; - this.average = 0; - this.stereoVol = [ - 0, - 0 - ]; - this.stereoAvg = [ - 0, - 0 - ]; - this.stereoVolNorm = [ - 0, - 0 - ]; - this.volMax = 0.001; - this.normalize = false; - this.processor.onaudioprocess = this._audioProcess.bind(this); - this.processor.connect(this.output); - this.output.gain.value = 0; - // this may only be necessary because of a Chrome bug - this.output.connect(this.audiocontext.destination); - // connect to p5sound master output by default, unless set by input() - p5sound.meter.connect(this.processor); - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connects to the p5sound instance (master output) by default. - * Optionally, you can pass in a specific source (i.e. a soundfile). - * - * @method setInput - * @param {soundObject|undefined} [snd] set the sound source - * (optional, defaults to - * master output) - * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 - * to smooth amplitude readings - * @example - *
- * function preload(){ - * sound1 = loadSound('assets/beat.mp3'); - * sound2 = loadSound('assets/drum.mp3'); - * } - * function setup(){ - * amplitude = new p5.Amplitude(); - * sound1.play(); - * sound2.play(); - * amplitude.setInput(sound2); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * function mouseClicked(){ - * sound1.stop(); - * sound2.stop(); - * } - *
- */ - p5.Amplitude.prototype.setInput = function (source, smoothing) { - p5sound.meter.disconnect(); - if (smoothing) { - this.smoothing = smoothing; - } - // connect to the master out of p5s instance if no snd is provided - if (source == null) { - console.log('Amplitude input source is not ready! Connecting to master output instead'); - p5sound.meter.connect(this.processor); - } else if (source instanceof p5.Signal) { - source.output.connect(this.processor); - } else if (source) { - source.connect(this.processor); - this.processor.disconnect(); - this.processor.connect(this.output); - } else { - p5sound.meter.connect(this.processor); - } - }; - p5.Amplitude.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else { - this.output.connect(unit); - } - } else { - this.output.connect(this.panner.connect(p5sound.input)); - } - }; - p5.Amplitude.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - // TO DO make this stereo / dependent on # of audio channels - p5.Amplitude.prototype._audioProcess = function (event) { - for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) { - var inputBuffer = event.inputBuffer.getChannelData(channel); - var bufLength = inputBuffer.length; - var total = 0; - var sum = 0; - var x; - for (var i = 0; i < bufLength; i++) { - x = inputBuffer[i]; - if (this.normalize) { - total += Math.max(Math.min(x / this.volMax, 1), -1); - sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1); - } else { - total += x; - sum += x * x; + // Adjust the tempo to fit within the 90-180 BPM range + while (theoreticalTempo < 90) theoreticalTempo *= 2; + while (theoreticalTempo > 180 && theoreticalTempo > 90) + theoreticalTempo /= 2; + return theoreticalTempo; + } + /*** SCHEDULE EVENTS ***/ + // Cue inspired by JavaScript setTimeout, and the + // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org + var Cue = function (callback, time, id, val) { + this.callback = callback; + this.time = time; + this.id = id; + this.val = val; + }; + /** + * Schedule events to trigger every time a MediaElement + * (audio/video) reaches a playback cue point. + * + * Accepts a callback function, a time (in seconds) at which to trigger + * the callback, and an optional parameter for the callback. + * + * Time will be passed as the first parameter to the callback function, + * and param will be the second parameter. + * + * + * @method addCue + * @param {Number} time Time in seconds, relative to this media + * element's playback. For example, to trigger + * an event every time playback reaches two + * seconds, pass in the number 2. This will be + * passed as the first parameter to + * the callback function. + * @param {Function} callback Name of a function that will be + * called at the given time. The callback will + * receive time and (optionally) param as its + * two parameters. + * @param {Object} [value] An object to be passed as the + * second parameter to the + * callback function. + * @return {Number} id ID of this cue, + * useful for removeCue(id) + * @example + *
+ * var mySound; + * function preload() { + * mySound = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * // schedule calls to changeText + * mySound.addCue(0.50, changeText, "hello" ); + * mySound.addCue(1.00, changeText, "p5" ); + * mySound.addCue(1.50, changeText, "what" ); + * mySound.addCue(2.00, changeText, "do" ); + * mySound.addCue(2.50, changeText, "you" ); + * mySound.addCue(3.00, changeText, "want" ); + * mySound.addCue(4.00, changeText, "to" ); + * mySound.addCue(5.00, changeText, "make" ); + * mySound.addCue(6.00, changeText, "?" ); + * } + * + * function changeText(val) { + * background(0); + * text(val, width/2, height/2); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * if (mySound.isPlaying() ) { + * mySound.stop(); + * } else { + * mySound.play(); + * } + * } + * } + *
+ */ + p5.SoundFile.prototype.addCue = function (time, callback, val) { + var id = this._cueIDCounter++; + var cue = new Cue(callback, time, id, val); + this._cues.push(cue); + // if (!this.elt.ontimeupdate) { + // this.elt.ontimeupdate = this._onTimeUpdate.bind(this); + // } + return id; + }; + /** + * Remove a callback based on its ID. The ID is returned by the + * addCue method. + * + * @method removeCue + * @param {Number} id ID of the cue, as returned by addCue + */ + p5.SoundFile.prototype.removeCue = function (id) { + var cueLength = this._cues.length; + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + if (cue.id === id) { + this._cues.splice(i, 1); + break; } } - var average = total / bufLength; - // ... then take the square root of the sum. - var rms = Math.sqrt(sum / bufLength); - this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing); - this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing); - this.volMax = Math.max(this.stereoVol[channel], this.volMax); - } - // add volume from all channels together - var self = this; - var volSum = this.stereoVol.reduce(function (previousValue, currentValue, index) { - self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1] / self.volMax, 1), 0); - self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index] / self.volMax, 1), 0); - return previousValue + currentValue; - }); - // volume is average of channels - this.volume = volSum / this.stereoVol.length; - // normalized value - this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0); - }; - /** - * Returns a single Amplitude reading at the moment it is called. - * For continuous readings, run in the draw loop. - * - * @method getLevel - * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) - * @return {Number} Amplitude as a number between 0.0 and 1.0 - * @example - *
- * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } - * function setup() { - * amplitude = new p5.Amplitude(); - * sound.play(); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * function mouseClicked(){ - * sound.stop(); - * } - *
- */ - p5.Amplitude.prototype.getLevel = function (channel) { - if (typeof channel !== 'undefined') { - if (this.normalize) { - return this.stereoVolNorm[channel]; - } else { - return this.stereoVol[channel]; - } - } else if (this.normalize) { - return this.volNorm; - } else { - return this.volume; - } - }; - /** - * Determines whether the results of Amplitude.process() will be - * Normalized. To normalize, Amplitude finds the difference the - * loudest reading it has processed and the maximum amplitude of - * 1.0. Amplitude adds this difference to all values to produce - * results that will reliably map between 0.0 and 1.0. However, - * if a louder moment occurs, the amount that Normalize adds to - * all the values will change. Accepts an optional boolean parameter - * (true or false). Normalizing is off by default. - * - * @method toggleNormalize - * @param {boolean} [boolean] set normalize to true (1) or false (0) - */ - p5.Amplitude.prototype.toggleNormalize = function (bool) { - if (typeof bool === 'boolean') { - this.normalize = bool; - } else { - this.normalize = !this.normalize; - } - }; - /** - * Smooth Amplitude analysis by averaging with the last analysis - * frame. Off by default. - * - * @method smooth - * @param {Number} set smoothing from 0.0 <= 1 - */ - p5.Amplitude.prototype.smooth = function (s) { - if (s >= 0 && s < 1) { - this.smoothing = s; - } else { - console.log('Error: smoothing must be between 0 and 1'); - } - }; - p5.Amplitude.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.input) { - this.input.disconnect(); - delete this.input; - } - if (this.output) { - this.output.disconnect(); - delete this.output; - } - delete this.processor; - }; -}(master); -var fft; -'use strict'; -fft = function () { - var p5sound = master; - /** - *

FFT (Fast Fourier Transform) is an analysis algorithm that - * isolates individual - * - * audio frequencies within a waveform.

- * - *

Once instantiated, a p5.FFT object can return an array based on - * two types of analyses:
FFT.waveform() computes - * amplitude values along the time domain. The array indices correspond - * to samples across a brief moment in time. Each value represents - * amplitude of the waveform at that sample of time.
- * • FFT.analyze() computes amplitude values along the - * frequency domain. The array indices correspond to frequencies (i.e. - * pitches), from the lowest to the highest that humans can hear. Each - * value represents amplitude at that slice of the frequency spectrum. - * Use with getEnergy() to measure amplitude at specific - * frequencies, or within a range of frequencies.

- * - *

FFT analyzes a very short snapshot of sound called a sample - * buffer. It returns an array of amplitude measurements, referred - * to as bins. The array is 1024 bins long by default. - * You can change the bin array length, but it must be a power of 2 - * between 16 and 1024 in order for the FFT algorithm to function - * correctly. The actual size of the FFT buffer is twice the - * number of bins, so given a standard sample rate, the buffer is - * 2048/44100 seconds long.

- * - * - * @class p5.FFT - * @constructor - * @param {Number} [smoothing] Smooth results of Freq Spectrum. - * 0.0 < smoothing < 1.0. - * Defaults to 0.8. - * @param {Number} [bins] Length of resulting array. - * Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @example - *
- * function preload(){ - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup(){ - * var cnv = createCanvas(100,100); - * cnv.mouseClicked(togglePlay); - * fft = new p5.FFT(); - * sound.amp(0.2); - * } - * - * function draw(){ - * background(0); - * - * var spectrum = fft.analyze(); - * noStroke(); - * fill(0,255,0); // spectrum is green - * for (var i = 0; i< spectrum.length; i++){ - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ) - * } - * - * var waveform = fft.waveform(); - * noFill(); - * beginShape(); - * stroke(255,0,0); // waveform is red - * strokeWeight(1); - * for (var i = 0; i< waveform.length; i++){ - * var x = map(i, 0, waveform.length, 0, width); - * var y = map( waveform[i], -1, 1, 0, height); - * vertex(x,y); - * } - * endShape(); - * - * text('click to play/pause', 4, 10); - * } - * - * // fade sound if mouse is over canvas - * function togglePlay() { - * if (sound.isPlaying()) { - * sound.pause(); - * } else { - * sound.loop(); - * } - * } - *
- */ - p5.FFT = function (smoothing, bins) { - this.input = this.analyser = p5sound.audiocontext.createAnalyser(); - Object.defineProperties(this, { - bins: { - get: function () { - return this.analyser.fftSize / 2; - }, - set: function (b) { - this.analyser.fftSize = b * 2; - }, - configurable: true, - enumerable: true - }, - smoothing: { - get: function () { - return this.analyser.smoothingTimeConstant; - }, - set: function (s) { - this.analyser.smoothingTimeConstant = s; - }, - configurable: true, - enumerable: true - } - }); - // set default smoothing and bins - this.smooth(smoothing); - this.bins = bins || 1024; - // default connections to p5sound fftMeter - p5sound.fftMeter.connect(this.analyser); - this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); - this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); - // predefined frequency ranges, these will be tweakable - this.bass = [ - 20, - 140 - ]; - this.lowMid = [ - 140, - 400 - ]; - this.mid = [ - 400, - 2600 - ]; - this.highMid = [ - 2600, - 5200 - ]; - this.treble = [ - 5200, - 14000 - ]; - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Set the input source for the FFT analysis. If no source is - * provided, FFT will analyze all sound in the sketch. - * - * @method setInput - * @param {Object} [source] p5.sound object (or web audio API source node) - */ - p5.FFT.prototype.setInput = function (source) { - if (!source) { - p5sound.fftMeter.connect(this.analyser); - } else { - if (source.output) { - source.output.connect(this.analyser); - } else if (source.connect) { - source.connect(this.analyser); - } - p5sound.fftMeter.disconnect(); - } - }; - /** - * Returns an array of amplitude values (between -1.0 and +1.0) that represent - * a snapshot of amplitude readings in a single buffer. Length will be - * equal to bins (defaults to 1024). Can be used to draw the waveform - * of a sound. - * - * @method waveform - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {String} [precision] If any value is provided, will return results - * in a Float32 Array which is more precise - * than a regular array. - * @return {Array} Array Array of amplitude values (-1 to 1) - * over time. Array length = bins. - * - */ - p5.FFT.prototype.waveform = function () { - var bins, mode, normalArray; - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - bins = arguments[i]; - this.analyser.fftSize = bins * 2; - } - if (typeof arguments[i] === 'string') { - mode = arguments[i]; + if (this._cues.length === 0) { } - } - // getFloatFrequencyData doesnt work in Safari as of 5/2015 - if (mode && !p5.prototype._isSafari()) { - timeToFloat(this, this.timeDomain); - this.analyser.getFloatTimeDomainData(this.timeDomain); - return this.timeDomain; - } else { - timeToInt(this, this.timeDomain); - this.analyser.getByteTimeDomainData(this.timeDomain); - var normalArray = new Array(); - for (var j = 0; j < this.timeDomain.length; j++) { - var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); - normalArray.push(scaled); - } - return normalArray; - } - }; - /** - * Returns an array of amplitude values (between 0 and 255) - * across the frequency spectrum. Length is equal to FFT bins - * (1024 by default). The array indices correspond to frequencies - * (i.e. pitches), from the lowest to the highest that humans can - * hear. Each value represents amplitude at that slice of the - * frequency spectrum. Must be called prior to using - * getEnergy(). - * - * @method analyze - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {Number} [scale] If "dB," returns decibel - * float measurements between - * -140 and 0 (max). - * Otherwise returns integers from 0-255. - * @return {Array} spectrum Array of energy (amplitude/volume) - * values across the frequency spectrum. - * Lowest energy (silence) = 0, highest - * possible is 255. - * @example - *
- * var osc; - * var fft; - * - * function setup(){ - * createCanvas(100,100); - * osc = new p5.Oscillator(); - * osc.amp(0); - * osc.start(); - * fft = new p5.FFT(); - * } - * - * function draw(){ - * background(0); - * - * var freq = map(mouseX, 0, 800, 20, 15000); - * freq = constrain(freq, 1, 20000); - * osc.freq(freq); - * - * var spectrum = fft.analyze(); - * noStroke(); - * fill(0,255,0); // spectrum is green - * for (var i = 0; i< spectrum.length; i++){ - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ); - * } - * - * stroke(255); - * text('Freq: ' + round(freq)+'Hz', 10, 10); - * - * isMouseOverCanvas(); - * } - * - * // only play sound when mouse is over canvas - * function isMouseOverCanvas() { - * var mX = mouseX, mY = mouseY; - * if (mX > 0 && mX < width && mY < height && mY > 0) { - * osc.amp(0.5, 0.2); - * } else { - * osc.amp(0, 0.2); - * } - * } - *
- * - * - */ - p5.FFT.prototype.analyze = function () { - var mode; - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - this.bins = arguments[i]; - this.analyser.fftSize = this.bins * 2; - } - if (typeof arguments[i] === 'string') { - mode = arguments[i]; + }; + /** + * Remove all of the callbacks that had originally been scheduled + * via the addCue method. + * + * @method clearCues + */ + p5.SoundFile.prototype.clearCues = function () { + this._cues = []; + }; + // private method that checks for cues to be fired if events + // have been scheduled using addCue(callback, time). + p5.SoundFile.prototype._onTimeUpdate = function (position) { + var playbackTime = position / this.buffer.sampleRate; + var cueLength = this._cues.length; + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + var callbackTime = cue.time; + var val = cue.val; + if (this._prevTime < callbackTime && callbackTime <= playbackTime) { + // pass the scheduled callbackTime as parameter to the callback + cue.callback(val); + } } - } - if (mode && mode.toLowerCase() === 'db') { - freqToFloat(this); - this.analyser.getFloatFrequencyData(this.freqDomain); - return this.freqDomain; - } else { - freqToInt(this, this.freqDomain); - this.analyser.getByteFrequencyData(this.freqDomain); - var normalArray = Array.apply([], this.freqDomain); - normalArray.length === this.analyser.fftSize; - normalArray.constructor === Array; - return normalArray; - } - }; - /** - * Returns the amount of energy (volume) at a specific - * - * frequency, or the average amount of energy between two - * frequencies. Accepts Number(s) corresponding - * to frequency (in Hz), or a String corresponding to predefined - * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). - * Returns a range between 0 (no energy/volume at that frequency) and - * 255 (maximum energy). - * NOTE: analyze() must be called prior to getEnergy(). Analyze() - * tells the FFT to analyze frequency data, and getEnergy() uses - * the results determine the value at a specific frequency or - * range of frequencies.

- * - * @method getEnergy - * @param {Number|String} frequency1 Will return a value representing - * energy at this frequency. Alternately, - * the strings "bass", "lowMid" "mid", - * "highMid", and "treble" will return - * predefined frequency ranges. - * @param {Number} [frequency2] If a second frequency is given, - * will return average amount of - * energy that exists between the - * two frequencies. - * @return {Number} Energy Energy (volume/amplitude) from - * 0 and 255. - * - */ - p5.FFT.prototype.getEnergy = function (frequency1, frequency2) { - var nyquist = p5sound.audiocontext.sampleRate / 2; - if (frequency1 === 'bass') { - frequency1 = this.bass[0]; - frequency2 = this.bass[1]; - } else if (frequency1 === 'lowMid') { - frequency1 = this.lowMid[0]; - frequency2 = this.lowMid[1]; - } else if (frequency1 === 'mid') { - frequency1 = this.mid[0]; - frequency2 = this.mid[1]; - } else if (frequency1 === 'highMid') { - frequency1 = this.highMid[0]; - frequency2 = this.highMid[1]; - } else if (frequency1 === 'treble') { - frequency1 = this.treble[0]; - frequency2 = this.treble[1]; - } - if (typeof frequency1 !== 'number') { - throw 'invalid input for getEnergy()'; - } else if (!frequency2) { - // if only one parameter: - var index = Math.round(frequency1 / nyquist * this.freqDomain.length); - return this.freqDomain[index]; - } else if (frequency1 && frequency2) { - // if two parameters: - // if second is higher than first - if (frequency1 > frequency2) { - var swap = frequency2; - frequency2 = frequency1; - frequency1 = swap; - } - var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length); - var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length); - var total = 0; - var numFrequencies = 0; - // add up all of the values for the frequencies - for (var i = lowIndex; i <= highIndex; i++) { - total += this.freqDomain[i]; - numFrequencies += 1; - } - // divide by total number of frequencies - var toReturn = total / numFrequencies; - return toReturn; - } else { - throw 'invalid input for getEnergy()'; - } - }; - // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated... - p5.FFT.prototype.getFreq = function (freq1, freq2) { - console.log('getFreq() is deprecated. Please use getEnergy() instead.'); - var x = this.getEnergy(freq1, freq2); - return x; - }; - /** - * Returns the - * - * spectral centroid of the input signal. - * NOTE: analyze() must be called prior to getCentroid(). Analyze() - * tells the FFT to analyze frequency data, and getCentroid() uses - * the results determine the spectral centroid.

+ this._prevTime = playbackTime; + }; + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. To upload a file to a server, see + * getBlob * - * @method getCentroid - * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz. + * @method save + * @param {String} [fileName] name of the resulting .wav file. + * @example + *
+ * var inp, button, mySound; + * var fileName = 'cool'; + * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * function setup() { + * btn = createButton('click to save file'); + * btn.position(0, 0); + * btn.mouseClicked(handleMouseClick); + * } + * + * function handleMouseClick() { + * mySound.save(fileName); + * } + *
+ */ + p5.SoundFile.prototype.save = function (fileName) { + const dataView = convertToWav(this.buffer); + p5.prototype.saveSound([dataView], fileName, "wav"); + }; + /** + * This method is useful for sending a SoundFile to a server. It returns the + * .wav-encoded audio data as a "Blob". + * A Blob is a file-like data object that can be uploaded to a server + * with an http request. We'll + * use the `httpDo` options object to send a POST request with some + * specific options: we encode the request as `multipart/form-data`, + * and attach the blob as one of the form values using `FormData`. * * + * @method getBlob + * @returns {Blob} A file-like data object * @example *
* + * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } * - *function setup(){ - * cnv = createCanvas(100,100); - * sound = new p5.AudioIn(); - * sound.start(); - * fft = new p5.FFT(); - * sound.connect(fft); - *} - * + * function setup() { + * noCanvas(); + * var soundBlob = mySound.getBlob(); * - *function draw(){ + * // Now we can send the blob to a server... + * var serverUrl = 'https://jsonplaceholder.typicode.com/posts'; + * var httpRequestOptions = { + * method: 'POST', + * body: new FormData().append('soundBlob', soundBlob), + * headers: new Headers({ + * 'Content-Type': 'multipart/form-data' + * }) + * }; + * httpDo(serverUrl, httpRequestOptions); * - * var centroidplot = 0.0; - * var spectralCentroid = 0; + * // We can also create an `ObjectURL` pointing to the Blob + * var blobUrl = URL.createObjectURL(soundBlob); * + * // The `
+ */ + p5.SoundFile.prototype.getBlob = function () { + const dataView = convertToWav(this.buffer); + return new Blob([dataView], { type: "audio/wav" }); + }; + // event handler to keep track of current position + function _onAudioProcess(processEvent) { + var inputBuffer = processEvent.inputBuffer.getChannelData(0); + this._lastPos = inputBuffer[inputBuffer.length - 1] || 0; + // do any callbacks that have been scheduled + this._onTimeUpdate(self._lastPos); + } + // event handler to remove references to the bufferSourceNode when it is done playing + function _clearOnEnd(e) { + const thisBufferSourceNode = e.target; + const soundFile = this; + // delete this.bufferSourceNode from the sources array when it is done playing: + thisBufferSourceNode._playing = false; + thisBufferSourceNode.removeEventListener("ended", soundFile._clearOnEnd); + // call the onended callback + soundFile._onended(soundFile); + soundFile.bufferSourceNodes.forEach(function (n, i) { + if (n._playing === false) { + soundFile.bufferSourceNodes.splice(i); + } + }); + if (soundFile.bufferSourceNodes.length === 0) { + soundFile._playing = false; + } + } + })(errorHandler, master, helpers, helpers); + var amplitude; + ("use strict"); + amplitude = (function () { + var p5sound = master; + /** + * Amplitude measures volume between 0.0 and 1.0. + * Listens to all p5sound by default, or use setInput() + * to listen to a specific sound source. Accepts an optional + * smoothing value, which defaults to 0. * - * // the mean_freq_index calculation is for the display. - * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length); + * @class p5.Amplitude + * @constructor + * @param {Number} [smoothing] between 0.0 and .999 to smooth + * amplitude readings (defaults to 0) + * @example + *
+ * var sound, amplitude, cnv; * - * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); + * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * function setup() { + * cnv = createCanvas(100,100); + * amplitude = new p5.Amplitude(); * + * // start / stop the sound when canvas is clicked + * cnv.mouseClicked(function() { + * if (sound.isPlaying() ){ + * sound.stop(); + * } else { + * sound.play(); + * } + * }); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } * - * stroke(255,0,0); // the line showing where the centroid is will be red + *
+ */ + p5.Amplitude = function (smoothing) { + // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default + this.bufferSize = 2048; + // set audio context + this.audiocontext = p5sound.audiocontext; + this.processor = this.audiocontext.createScriptProcessor( + this.bufferSize, + 2, + 1 + ); + // for connections + this.input = this.processor; + this.output = this.audiocontext.createGain(); + // smoothing defaults to 0 + this.smoothing = smoothing || 0; + // the variables to return + this.volume = 0; + this.average = 0; + this.stereoVol = [0, 0]; + this.stereoAvg = [0, 0]; + this.stereoVolNorm = [0, 0]; + this.volMax = 0.001; + this.normalize = false; + this.processor.onaudioprocess = this._audioProcess.bind(this); + this.processor.connect(this.output); + this.output.gain.value = 0; + // this may only be necessary because of a Chrome bug + this.output.connect(this.audiocontext.destination); + // connect to p5sound master output by default, unless set by input() + p5sound.meter.connect(this.processor); + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connects to the p5sound instance (master output) by default. + * Optionally, you can pass in a specific source (i.e. a soundfile). * - * rect(centroidplot, 0, width / spectrum.length, height) - * noStroke(); - * fill(255,255,255); // text is white - * text("centroid: ", 10, 20); - * text(round(spectralCentroid)+" Hz", 10, 40); - *} - *
+ * @method setInput + * @param {soundObject|undefined} [snd] set the sound source + * (optional, defaults to + * master output) + * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 + * to smooth amplitude readings + * @example + *
+ * function preload(){ + * sound1 = loadSound('assets/beat.mp3'); + * sound2 = loadSound('assets/drum.mp3'); + * } + * function setup(){ + * amplitude = new p5.Amplitude(); + * sound1.play(); + * sound2.play(); + * amplitude.setInput(sound2); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * function mouseClicked(){ + * sound1.stop(); + * sound2.stop(); + * } + *
*/ - p5.FFT.prototype.getCentroid = function () { - var nyquist = p5sound.audiocontext.sampleRate / 2; - var cumulative_sum = 0; - var centroid_normalization = 0; - for (var i = 0; i < this.freqDomain.length; i++) { - cumulative_sum += i * this.freqDomain[i]; - centroid_normalization += this.freqDomain[i]; - } - var mean_freq_index = 0; - if (centroid_normalization !== 0) { - mean_freq_index = cumulative_sum / centroid_normalization; - } - var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length); - return spec_centroid_freq; - }; - /** - * Smooth FFT analysis by averaging with the last analysis frame. - * - * @method smooth - * @param {Number} smoothing 0.0 < smoothing < 1.0. - * Defaults to 0.8. - */ - p5.FFT.prototype.smooth = function (s) { - if (typeof s !== 'undefined') { - this.smoothing = s; - } - return this.smoothing; - }; - p5.FFT.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.analyser) { - this.analyser.disconnect(); - delete this.analyser; - } - }; - /** - * Returns an array of average amplitude values for a given number - * of frequency bands split equally. N defaults to 16. - * NOTE: analyze() must be called prior to linAverages(). Analyze() - * tells the FFT to analyze frequency data, and linAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method linAverages - * @param {Number} N Number of returned frequency groups - * @return {Array} linearAverages Array of average amplitude values for each group - */ - p5.FFT.prototype.linAverages = function (N) { - var N = N || 16; - // This prevents undefined, null or 0 values of N - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var spectrumStep = Math.floor(spectrumLength / N); - var linearAverages = new Array(N); - // Keep a second index for the current average group and place the values accordingly - // with only one loop in the spectrum data - var groupIndex = 0; - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - linearAverages[groupIndex] = linearAverages[groupIndex] !== undefined ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - // Increase the group index when the last element of the group is processed - if (specIndex % spectrumStep === spectrumStep - 1) { - groupIndex++; - } - } - return linearAverages; - }; - /** - * Returns an array of average amplitude values of the spectrum, for a given - * set of - * Octave Bands - * NOTE: analyze() must be called prior to logAverages(). Analyze() - * tells the FFT to analyze frequency data, and logAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method logAverages - * @param {Array} octaveBands Array of Octave Bands objects for grouping - * @return {Array} logAverages Array of average amplitude values for each group - */ - p5.FFT.prototype.logAverages = function (octaveBands) { - var nyquist = p5sound.audiocontext.sampleRate / 2; - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var logAverages = new Array(octaveBands.length); - // Keep a second index for the current average group and place the values accordingly - // With only one loop in the spectrum data - var octaveIndex = 0; - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - var specIndexFrequency = Math.round(specIndex * nyquist / this.freqDomain.length); - // Increase the group index if the current frequency exceeds the limits of the band - if (specIndexFrequency > octaveBands[octaveIndex].hi) { - octaveIndex++; - } - logAverages[octaveIndex] = logAverages[octaveIndex] !== undefined ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - } - return logAverages; - }; - /** - * Calculates and Returns the 1/N - * Octave Bands - * N defaults to 3 and minimum central frequency to 15.625Hz. - * (1/3 Octave Bands ~= 31 Frequency Bands) - * Setting fCtr0 to a central value of a higher octave will ignore the lower bands - * and produce less frequency groups. - * - * @method getOctaveBands - * @param {Number} N Specifies the 1/N type of generated octave bands - * @param {Number} fCtr0 Minimum central frequency for the lowest band - * @return {Array} octaveBands Array of octave band objects with their bounds - */ - p5.FFT.prototype.getOctaveBands = function (N, fCtr0) { - var N = N || 3; - // Default to 1/3 Octave Bands - var fCtr0 = fCtr0 || 15.625; - // Minimum central frequency, defaults to 15.625Hz - var octaveBands = []; - var lastFrequencyBand = { - lo: fCtr0 / Math.pow(2, 1 / (2 * N)), - ctr: fCtr0, - hi: fCtr0 * Math.pow(2, 1 / (2 * N)) - }; - octaveBands.push(lastFrequencyBand); - var nyquist = p5sound.audiocontext.sampleRate / 2; - while (lastFrequencyBand.hi < nyquist) { - var newFrequencyBand = {}; - newFrequencyBand.lo = lastFrequencyBand.hi; - newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); - newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); - octaveBands.push(newFrequencyBand); - lastFrequencyBand = newFrequencyBand; - } - return octaveBands; - }; - // helper methods to convert type from float (dB) to int (0-255) - var freqToFloat = function (fft) { - if (fft.freqDomain instanceof Float32Array === false) { - fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); - } - }; - var freqToInt = function (fft) { - if (fft.freqDomain instanceof Uint8Array === false) { - fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } - }; - var timeToFloat = function (fft) { - if (fft.timeDomain instanceof Float32Array === false) { - fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); - } - }; - var timeToInt = function (fft) { - if (fft.timeDomain instanceof Uint8Array === false) { - fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } - }; -}(master); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_SignalBase; -Tone_signal_SignalBase = function (Tone) { - 'use strict'; - Tone.SignalBase = function () { - }; - Tone.extend(Tone.SignalBase); - Tone.SignalBase.prototype.connect = function (node, outputNumber, inputNumber) { - if (Tone.Signal && Tone.Signal === node.constructor || Tone.Param && Tone.Param === node.constructor || Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) { - node._param.cancelScheduledValues(0); - node._param.value = 0; - node.overridden = true; - } else if (node instanceof AudioParam) { - node.cancelScheduledValues(0); - node.value = 0; - } - Tone.prototype.connect.call(this, node, outputNumber, inputNumber); - return this; - }; - return Tone.SignalBase; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_WaveShaper; -Tone_signal_WaveShaper = function (Tone) { - 'use strict'; - Tone.WaveShaper = function (mapping, bufferLen) { - this._shaper = this.input = this.output = this.context.createWaveShaper(); - this._curve = null; - if (Array.isArray(mapping)) { - this.curve = mapping; - } else if (isFinite(mapping) || this.isUndef(mapping)) { - this._curve = new Float32Array(this.defaultArg(mapping, 1024)); - } else if (this.isFunction(mapping)) { - this._curve = new Float32Array(this.defaultArg(bufferLen, 1024)); - this.setMap(mapping); - } - }; - Tone.extend(Tone.WaveShaper, Tone.SignalBase); - Tone.WaveShaper.prototype.setMap = function (mapping) { - for (var i = 0, len = this._curve.length; i < len; i++) { - var normalized = i / (len - 1) * 2 - 1; - this._curve[i] = mapping(normalized, i); - } - this._shaper.curve = this._curve; - return this; - }; - Object.defineProperty(Tone.WaveShaper.prototype, 'curve', { - get: function () { - return this._shaper.curve; - }, - set: function (mapping) { - this._curve = new Float32Array(mapping); - this._shaper.curve = this._curve; - } - }); - Object.defineProperty(Tone.WaveShaper.prototype, 'oversample', { - get: function () { - return this._shaper.oversample; - }, - set: function (oversampling) { - if ([ - 'none', - '2x', - '4x' - ].indexOf(oversampling) !== -1) { - this._shaper.oversample = oversampling; + p5.Amplitude.prototype.setInput = function (source, smoothing) { + p5sound.meter.disconnect(); + if (smoothing) { + this.smoothing = smoothing; + } + // connect to the master out of p5s instance if no snd is provided + if (source == null) { + console.log( + "Amplitude input source is not ready! Connecting to master output instead" + ); + p5sound.meter.connect(this.processor); + } else if (source instanceof p5.Signal) { + source.output.connect(this.processor); + } else if (source) { + source.connect(this.processor); + this.processor.disconnect(); + this.processor.connect(this.output); } else { - throw new RangeError('Tone.WaveShaper: oversampling must be either \'none\', \'2x\', or \'4x\''); - } - } - }); - Tone.WaveShaper.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._shaper.disconnect(); - this._shaper = null; - this._curve = null; - return this; - }; - return Tone.WaveShaper; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_TimeBase; -Tone_type_TimeBase = function (Tone) { - Tone.TimeBase = function (val, units) { - if (this instanceof Tone.TimeBase) { - this._expr = this._noOp; - if (val instanceof Tone.TimeBase) { - this.copy(val); - } else if (!this.isUndef(units) || this.isNumber(val)) { - units = this.defaultArg(units, this._defaultUnits); - var method = this._primaryExpressions[units].method; - this._expr = method.bind(this, val); - } else if (this.isString(val)) { - this.set(val); - } else if (this.isUndef(val)) { - this._expr = this._defaultExpr(); + p5sound.meter.connect(this.processor); } - } else { - return new Tone.TimeBase(val, units); - } - }; - Tone.extend(Tone.TimeBase); - Tone.TimeBase.prototype.set = function (exprString) { - this._expr = this._parseExprString(exprString); - return this; - }; - Tone.TimeBase.prototype.clone = function () { - var instance = new this.constructor(); - instance.copy(this); - return instance; - }; - Tone.TimeBase.prototype.copy = function (time) { - var val = time._expr(); - return this.set(val); - }; - Tone.TimeBase.prototype._primaryExpressions = { - 'n': { - regexp: /^(\d+)n/i, - method: function (value) { - value = parseInt(value); - if (value === 1) { - return this._beatsToUnits(this._timeSignature()); + }; + p5.Amplitude.prototype.connect = function (unit) { + if (unit) { + if (unit.hasOwnProperty("input")) { + this.output.connect(unit.input); } else { - return this._beatsToUnits(4 / value); + this.output.connect(unit); } + } else { + this.output.connect(this.panner.connect(p5sound.input)); } - }, - 't': { - regexp: /^(\d+)t/i, - method: function (value) { - value = parseInt(value); - return this._beatsToUnits(8 / (parseInt(value) * 3)); - } - }, - 'm': { - regexp: /^(\d+)m/i, - method: function (value) { - return this._beatsToUnits(parseInt(value) * this._timeSignature()); - } - }, - 'i': { - regexp: /^(\d+)i/i, - method: function (value) { - return this._ticksToUnits(parseInt(value)); - } - }, - 'hz': { - regexp: /^(\d+(?:\.\d+)?)hz/i, - method: function (value) { - return this._frequencyToUnits(parseFloat(value)); + }; + p5.Amplitude.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); } - }, - 'tr': { - regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, - method: function (m, q, s) { + }; + // TO DO make this stereo / dependent on # of audio channels + p5.Amplitude.prototype._audioProcess = function (event) { + for ( + var channel = 0; + channel < event.inputBuffer.numberOfChannels; + channel++ + ) { + var inputBuffer = event.inputBuffer.getChannelData(channel); + var bufLength = inputBuffer.length; var total = 0; - if (m && m !== '0') { - total += this._beatsToUnits(this._timeSignature() * parseFloat(m)); - } - if (q && q !== '0') { - total += this._beatsToUnits(parseFloat(q)); - } - if (s && s !== '0') { - total += this._beatsToUnits(parseFloat(s) / 4); + var sum = 0; + var x; + for (var i = 0; i < bufLength; i++) { + x = inputBuffer[i]; + if (this.normalize) { + total += Math.max(Math.min(x / this.volMax, 1), -1); + sum += + Math.max(Math.min(x / this.volMax, 1), -1) * + Math.max(Math.min(x / this.volMax, 1), -1); + } else { + total += x; + sum += x * x; + } } - return total; - } - }, - 's': { - regexp: /^(\d+(?:\.\d+)?s)/, - method: function (value) { - return this._secondsToUnits(parseFloat(value)); + var average = total / bufLength; + // ... then take the square root of the sum. + var rms = Math.sqrt(sum / bufLength); + this.stereoVol[channel] = Math.max( + rms, + this.stereoVol[channel] * this.smoothing + ); + this.stereoAvg[channel] = Math.max( + average, + this.stereoVol[channel] * this.smoothing + ); + this.volMax = Math.max(this.stereoVol[channel], this.volMax); + } + // add volume from all channels together + var self = this; + var volSum = this.stereoVol.reduce(function ( + previousValue, + currentValue, + index + ) { + self.stereoVolNorm[index - 1] = Math.max( + Math.min(self.stereoVol[index - 1] / self.volMax, 1), + 0 + ); + self.stereoVolNorm[index] = Math.max( + Math.min(self.stereoVol[index] / self.volMax, 1), + 0 + ); + return previousValue + currentValue; + }); + // volume is average of channels + this.volume = volSum / this.stereoVol.length; + // normalized value + this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0); + }; + /** + * Returns a single Amplitude reading at the moment it is called. + * For continuous readings, run in the draw loop. + * + * @method getLevel + * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) + * @return {Number} Amplitude as a number between 0.0 and 1.0 + * @example + *
+ * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * function setup() { + * amplitude = new p5.Amplitude(); + * sound.play(); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * function mouseClicked(){ + * sound.stop(); + * } + *
+ */ + p5.Amplitude.prototype.getLevel = function (channel) { + if (typeof channel !== "undefined") { + if (this.normalize) { + return this.stereoVolNorm[channel]; + } else { + return this.stereoVol[channel]; + } + } else if (this.normalize) { + return this.volNorm; + } else { + return this.volume; } - }, - 'samples': { - regexp: /^(\d+)samples/, - method: function (value) { - return parseInt(value) / this.context.sampleRate; + }; + /** + * Determines whether the results of Amplitude.process() will be + * Normalized. To normalize, Amplitude finds the difference the + * loudest reading it has processed and the maximum amplitude of + * 1.0. Amplitude adds this difference to all values to produce + * results that will reliably map between 0.0 and 1.0. However, + * if a louder moment occurs, the amount that Normalize adds to + * all the values will change. Accepts an optional boolean parameter + * (true or false). Normalizing is off by default. + * + * @method toggleNormalize + * @param {boolean} [boolean] set normalize to true (1) or false (0) + */ + p5.Amplitude.prototype.toggleNormalize = function (bool) { + if (typeof bool === "boolean") { + this.normalize = bool; + } else { + this.normalize = !this.normalize; } - }, - 'default': { - regexp: /^(\d+(?:\.\d+)?)/, - method: function (value) { - return this._primaryExpressions[this._defaultUnits].method.call(this, value); + }; + /** + * Smooth Amplitude analysis by averaging with the last analysis + * frame. Off by default. + * + * @method smooth + * @param {Number} set smoothing from 0.0 <= 1 + */ + p5.Amplitude.prototype.smooth = function (s) { + if (s >= 0 && s < 1) { + this.smoothing = s; + } else { + console.log("Error: smoothing must be between 0 and 1"); } - } - }; - Tone.TimeBase.prototype._binaryExpressions = { - '+': { - regexp: /^\+/, - precedence: 2, - method: function (lh, rh) { - return lh() + rh(); - } - }, - '-': { - regexp: /^\-/, - precedence: 2, - method: function (lh, rh) { - return lh() - rh(); - } - }, - '*': { - regexp: /^\*/, - precedence: 1, - method: function (lh, rh) { - return lh() * rh(); - } - }, - '/': { - regexp: /^\//, - precedence: 1, - method: function (lh, rh) { - return lh() / rh(); + }; + p5.Amplitude.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.input) { + this.input.disconnect(); + delete this.input; } - } - }; - Tone.TimeBase.prototype._unaryExpressions = { - 'neg': { - regexp: /^\-/, - method: function (lh) { - return -lh(); + if (this.output) { + this.output.disconnect(); + delete this.output; } - } - }; - Tone.TimeBase.prototype._syntaxGlue = { - '(': { regexp: /^\(/ }, - ')': { regexp: /^\)/ } - }; - Tone.TimeBase.prototype._tokenize = function (expr) { - var position = -1; - var tokens = []; - while (expr.length > 0) { - expr = expr.trim(); - var token = getNextToken(expr, this); - tokens.push(token); - expr = expr.substr(token.value.length); - } - function getNextToken(expr, context) { - var expressions = [ - '_binaryExpressions', - '_unaryExpressions', - '_primaryExpressions', - '_syntaxGlue' - ]; - for (var i = 0; i < expressions.length; i++) { - var group = context[expressions[i]]; - for (var opName in group) { - var op = group[opName]; - var reg = op.regexp; - var match = expr.match(reg); - if (match !== null) { - return { - method: op.method, - precedence: op.precedence, - regexp: op.regexp, - value: match[0] - }; - } + delete this.processor; + }; + })(master); + var fft; + ("use strict"); + fft = (function () { + var p5sound = master; + /** + *

FFT (Fast Fourier Transform) is an analysis algorithm that + * isolates individual + * + * audio frequencies within a waveform.

+ * + *

Once instantiated, a p5.FFT object can return an array based on + * two types of analyses:
FFT.waveform() computes + * amplitude values along the time domain. The array indices correspond + * to samples across a brief moment in time. Each value represents + * amplitude of the waveform at that sample of time.
+ * • FFT.analyze() computes amplitude values along the + * frequency domain. The array indices correspond to frequencies (i.e. + * pitches), from the lowest to the highest that humans can hear. Each + * value represents amplitude at that slice of the frequency spectrum. + * Use with getEnergy() to measure amplitude at specific + * frequencies, or within a range of frequencies.

+ * + *

FFT analyzes a very short snapshot of sound called a sample + * buffer. It returns an array of amplitude measurements, referred + * to as bins. The array is 1024 bins long by default. + * You can change the bin array length, but it must be a power of 2 + * between 16 and 1024 in order for the FFT algorithm to function + * correctly. The actual size of the FFT buffer is twice the + * number of bins, so given a standard sample rate, the buffer is + * 2048/44100 seconds long.

+ * + * + * @class p5.FFT + * @constructor + * @param {Number} [smoothing] Smooth results of Freq Spectrum. + * 0.0 < smoothing < 1.0. + * Defaults to 0.8. + * @param {Number} [bins] Length of resulting array. + * Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @example + *
+ * function preload(){ + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup(){ + * var cnv = createCanvas(100,100); + * cnv.mouseClicked(togglePlay); + * fft = new p5.FFT(); + * sound.amp(0.2); + * } + * + * function draw(){ + * background(0); + * + * var spectrum = fft.analyze(); + * noStroke(); + * fill(0,255,0); // spectrum is green + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ) + * } + * + * var waveform = fft.waveform(); + * noFill(); + * beginShape(); + * stroke(255,0,0); // waveform is red + * strokeWeight(1); + * for (var i = 0; i< waveform.length; i++){ + * var x = map(i, 0, waveform.length, 0, width); + * var y = map( waveform[i], -1, 1, 0, height); + * vertex(x,y); + * } + * endShape(); + * + * text('click to play/pause', 4, 10); + * } + * + * // fade sound if mouse is over canvas + * function togglePlay() { + * if (sound.isPlaying()) { + * sound.pause(); + * } else { + * sound.loop(); + * } + * } + *
+ */ + p5.FFT = function (smoothing, bins) { + this.input = this.analyser = p5sound.audiocontext.createAnalyser(); + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (b) { + this.analyser.fftSize = b * 2; + }, + configurable: true, + enumerable: true, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (s) { + this.analyser.smoothingTimeConstant = s; + }, + configurable: true, + enumerable: true, + }, + }); + // set default smoothing and bins + this.smooth(smoothing); + this.bins = bins || 1024; + // default connections to p5sound fftMeter + p5sound.fftMeter.connect(this.analyser); + this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); + this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); + // predefined frequency ranges, these will be tweakable + this.bass = [20, 140]; + this.lowMid = [140, 400]; + this.mid = [400, 2600]; + this.highMid = [2600, 5200]; + this.treble = [5200, 14000]; + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Set the input source for the FFT analysis. If no source is + * provided, FFT will analyze all sound in the sketch. + * + * @method setInput + * @param {Object} [source] p5.sound object (or web audio API source node) + */ + p5.FFT.prototype.setInput = function (source) { + if (!source) { + p5sound.fftMeter.connect(this.analyser); + } else { + if (source.output) { + source.output.connect(this.analyser); + } else if (source.connect) { + source.connect(this.analyser); } + p5sound.fftMeter.disconnect(); } - throw new SyntaxError('Tone.TimeBase: Unexpected token ' + expr); - } - return { - next: function () { - return tokens[++position]; - }, - peek: function () { - return tokens[position + 1]; - } - }; - }; - Tone.TimeBase.prototype._matchGroup = function (token, group, prec) { - var ret = false; - if (!this.isUndef(token)) { - for (var opName in group) { - var op = group[opName]; - if (op.regexp.test(token.value)) { - if (!this.isUndef(prec)) { - if (op.precedence === prec) { - return op; - } - } else { - return op; - } + }; + /** + * Returns an array of amplitude values (between -1.0 and +1.0) that represent + * a snapshot of amplitude readings in a single buffer. Length will be + * equal to bins (defaults to 1024). Can be used to draw the waveform + * of a sound. + * + * @method waveform + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {String} [precision] If any value is provided, will return results + * in a Float32 Array which is more precise + * than a regular array. + * @return {Array} Array Array of amplitude values (-1 to 1) + * over time. Array length = bins. + * + */ + p5.FFT.prototype.waveform = function () { + var bins, mode, normalArray; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + bins = arguments[i]; + this.analyser.fftSize = bins * 2; + } + if (typeof arguments[i] === "string") { + mode = arguments[i]; } } - } - return ret; - }; - Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) { - if (this.isUndef(precedence)) { - precedence = 2; - } - var expr; - if (precedence < 0) { - expr = this._parseUnary(lexer); - } else { - expr = this._parseBinary(lexer, precedence - 1); - } - var token = lexer.peek(); - while (token && this._matchGroup(token, this._binaryExpressions, precedence)) { - token = lexer.next(); - expr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1)); - token = lexer.peek(); - } - return expr; - }; - Tone.TimeBase.prototype._parseUnary = function (lexer) { - var token, expr; - token = lexer.peek(); - var op = this._matchGroup(token, this._unaryExpressions); - if (op) { - token = lexer.next(); - expr = this._parseUnary(lexer); - return op.method.bind(this, expr); - } - return this._parsePrimary(lexer); - }; - Tone.TimeBase.prototype._parsePrimary = function (lexer) { - var token, expr; - token = lexer.peek(); - if (this.isUndef(token)) { - throw new SyntaxError('Tone.TimeBase: Unexpected end of expression'); - } - if (this._matchGroup(token, this._primaryExpressions)) { - token = lexer.next(); - var matching = token.value.match(token.regexp); - return token.method.bind(this, matching[1], matching[2], matching[3]); - } - if (token && token.value === '(') { - lexer.next(); - expr = this._parseBinary(lexer); - token = lexer.next(); - if (!(token && token.value === ')')) { - throw new SyntaxError('Expected )'); + // getFloatFrequencyData doesnt work in Safari as of 5/2015 + if (mode && !p5.prototype._isSafari()) { + timeToFloat(this, this.timeDomain); + this.analyser.getFloatTimeDomainData(this.timeDomain); + return this.timeDomain; + } else { + timeToInt(this, this.timeDomain); + this.analyser.getByteTimeDomainData(this.timeDomain); + var normalArray = new Array(); + for (var j = 0; j < this.timeDomain.length; j++) { + var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); + normalArray.push(scaled); + } + return normalArray; } - return expr; - } - throw new SyntaxError('Tone.TimeBase: Cannot process token ' + token.value); - }; - Tone.TimeBase.prototype._parseExprString = function (exprString) { - if (!this.isString(exprString)) { - exprString = exprString.toString(); - } - var lexer = this._tokenize(exprString); - var tree = this._parseBinary(lexer); - return tree; - }; - Tone.TimeBase.prototype._noOp = function () { - return 0; - }; - Tone.TimeBase.prototype._defaultExpr = function () { - return this._noOp; - }; - Tone.TimeBase.prototype._defaultUnits = 's'; - Tone.TimeBase.prototype._frequencyToUnits = function (freq) { - return 1 / freq; - }; - Tone.TimeBase.prototype._beatsToUnits = function (beats) { - return 60 / Tone.Transport.bpm.value * beats; - }; - Tone.TimeBase.prototype._secondsToUnits = function (seconds) { - return seconds; - }; - Tone.TimeBase.prototype._ticksToUnits = function (ticks) { - return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ); - }; - Tone.TimeBase.prototype._timeSignature = function () { - return Tone.Transport.timeSignature; - }; - Tone.TimeBase.prototype._pushExpr = function (val, name, units) { - if (!(val instanceof Tone.TimeBase)) { - val = new this.constructor(val, units); - } - this._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr); - return this; - }; - Tone.TimeBase.prototype.add = function (val, units) { - return this._pushExpr(val, '+', units); - }; - Tone.TimeBase.prototype.sub = function (val, units) { - return this._pushExpr(val, '-', units); - }; - Tone.TimeBase.prototype.mult = function (val, units) { - return this._pushExpr(val, '*', units); - }; - Tone.TimeBase.prototype.div = function (val, units) { - return this._pushExpr(val, '/', units); - }; - Tone.TimeBase.prototype.valueOf = function () { - return this._expr(); - }; - Tone.TimeBase.prototype.dispose = function () { - this._expr = null; - }; - return Tone.TimeBase; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Time; -Tone_type_Time = function (Tone) { - Tone.Time = function (val, units) { - if (this instanceof Tone.Time) { - this._plusNow = false; - Tone.TimeBase.call(this, val, units); - } else { - return new Tone.Time(val, units); - } - }; - Tone.extend(Tone.Time, Tone.TimeBase); - Tone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions); - Tone.Time.prototype._unaryExpressions.quantize = { - regexp: /^@/, - method: function (rh) { - return Tone.Transport.nextSubdivision(rh()); - } - }; - Tone.Time.prototype._unaryExpressions.now = { - regexp: /^\+/, - method: function (lh) { - this._plusNow = true; - return lh(); - } - }; - Tone.Time.prototype.quantize = function (subdiv, percent) { - percent = this.defaultArg(percent, 1); - this._expr = function (expr, subdivision, percent) { - expr = expr(); - subdivision = subdivision.toSeconds(); - var multiple = Math.round(expr / subdivision); - var ideal = multiple * subdivision; - var diff = ideal - expr; - return expr + diff * percent; - }.bind(this, this._expr, new this.constructor(subdiv), percent); - return this; - }; - Tone.Time.prototype.addNow = function () { - this._plusNow = true; - return this; - }; - Tone.Time.prototype._defaultExpr = function () { - this._plusNow = true; - return this._noOp; - }; - Tone.Time.prototype.copy = function (time) { - Tone.TimeBase.prototype.copy.call(this, time); - this._plusNow = time._plusNow; - return this; - }; - Tone.Time.prototype.toNotation = function () { - var time = this.toSeconds(); - var testNotations = [ - '1m', - '2n', - '4n', - '8n', - '16n', - '32n', - '64n', - '128n' - ]; - var retNotation = this._toNotationHelper(time, testNotations); - var testTripletNotations = [ - '1m', - '2n', - '2t', - '4n', - '4t', - '8n', - '8t', - '16n', - '16t', - '32n', - '32t', - '64n', - '64t', - '128n' - ]; - var retTripletNotation = this._toNotationHelper(time, testTripletNotations); - if (retTripletNotation.split('+').length < retNotation.split('+').length) { - return retTripletNotation; - } else { - return retNotation; - } - }; - Tone.Time.prototype._toNotationHelper = function (units, testNotations) { - var threshold = this._notationToUnits(testNotations[testNotations.length - 1]); - var retNotation = ''; - for (var i = 0; i < testNotations.length; i++) { - var notationTime = this._notationToUnits(testNotations[i]); - var multiple = units / notationTime; - var floatingPointError = 0.000001; - if (1 - multiple % 1 < floatingPointError) { - multiple += floatingPointError; - } - multiple = Math.floor(multiple); - if (multiple > 0) { - if (multiple === 1) { - retNotation += testNotations[i]; - } else { - retNotation += multiple.toString() + '*' + testNotations[i]; + }; + /** + * Returns an array of amplitude values (between 0 and 255) + * across the frequency spectrum. Length is equal to FFT bins + * (1024 by default). The array indices correspond to frequencies + * (i.e. pitches), from the lowest to the highest that humans can + * hear. Each value represents amplitude at that slice of the + * frequency spectrum. Must be called prior to using + * getEnergy(). + * + * @method analyze + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {Number} [scale] If "dB," returns decibel + * float measurements between + * -140 and 0 (max). + * Otherwise returns integers from 0-255. + * @return {Array} spectrum Array of energy (amplitude/volume) + * values across the frequency spectrum. + * Lowest energy (silence) = 0, highest + * possible is 255. + * @example + *
+ * var osc; + * var fft; + * + * function setup(){ + * createCanvas(100,100); + * osc = new p5.Oscillator(); + * osc.amp(0); + * osc.start(); + * fft = new p5.FFT(); + * } + * + * function draw(){ + * background(0); + * + * var freq = map(mouseX, 0, 800, 20, 15000); + * freq = constrain(freq, 1, 20000); + * osc.freq(freq); + * + * var spectrum = fft.analyze(); + * noStroke(); + * fill(0,255,0); // spectrum is green + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ); + * } + * + * stroke(255); + * text('Freq: ' + round(freq)+'Hz', 10, 10); + * + * isMouseOverCanvas(); + * } + * + * // only play sound when mouse is over canvas + * function isMouseOverCanvas() { + * var mX = mouseX, mY = mouseY; + * if (mX > 0 && mX < width && mY < height && mY > 0) { + * osc.amp(0.5, 0.2); + * } else { + * osc.amp(0, 0.2); + * } + * } + *
+ * + * + */ + p5.FFT.prototype.analyze = function () { + var mode; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + this.bins = arguments[i]; + this.analyser.fftSize = this.bins * 2; } - units -= multiple * notationTime; - if (units < threshold) { - break; - } else { - retNotation += ' + '; + if (typeof arguments[i] === "string") { + mode = arguments[i]; } } - } - if (retNotation === '') { - retNotation = '0'; - } - return retNotation; - }; - Tone.Time.prototype._notationToUnits = function (notation) { - var primaryExprs = this._primaryExpressions; - var notationExprs = [ - primaryExprs.n, - primaryExprs.t, - primaryExprs.m - ]; - for (var i = 0; i < notationExprs.length; i++) { - var expr = notationExprs[i]; - var match = notation.match(expr.regexp); - if (match) { - return expr.method.call(this, match[1]); - } - } - }; - Tone.Time.prototype.toBarsBeatsSixteenths = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.toSeconds() / quarterTime; - var measures = Math.floor(quarters / this._timeSignature()); - var sixteenths = quarters % 1 * 4; - quarters = Math.floor(quarters) % this._timeSignature(); - sixteenths = sixteenths.toString(); - if (sixteenths.length > 3) { - sixteenths = parseFloat(sixteenths).toFixed(3); - } - var progress = [ - measures, - quarters, - sixteenths - ]; - return progress.join(':'); - }; - Tone.Time.prototype.toTicks = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.valueOf() / quarterTime; - return Math.floor(quarters * Tone.Transport.PPQ); - }; - Tone.Time.prototype.toSamples = function () { - return this.toSeconds() * this.context.sampleRate; - }; - Tone.Time.prototype.toFrequency = function () { - return 1 / this.toSeconds(); - }; - Tone.Time.prototype.toSeconds = function () { - return this.valueOf(); - }; - Tone.Time.prototype.toMilliseconds = function () { - return this.toSeconds() * 1000; - }; - Tone.Time.prototype.valueOf = function () { - var val = this._expr(); - return val + (this._plusNow ? this.now() : 0); - }; - return Tone.Time; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Frequency; -Tone_type_Frequency = function (Tone) { - Tone.Frequency = function (val, units) { - if (this instanceof Tone.Frequency) { - Tone.TimeBase.call(this, val, units); - } else { - return new Tone.Frequency(val, units); - } - }; - Tone.extend(Tone.Frequency, Tone.TimeBase); - Tone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions); - Tone.Frequency.prototype._primaryExpressions.midi = { - regexp: /^(\d+(?:\.\d+)?midi)/, - method: function (value) { - return this.midiToFrequency(value); - } - }; - Tone.Frequency.prototype._primaryExpressions.note = { - regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, - method: function (pitch, octave) { - var index = noteToScaleIndex[pitch.toLowerCase()]; - var noteNumber = index + (parseInt(octave) + 1) * 12; - return this.midiToFrequency(noteNumber); - } - }; - Tone.Frequency.prototype._primaryExpressions.tr = { - regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, - method: function (m, q, s) { - var total = 1; - if (m && m !== '0') { - total *= this._beatsToUnits(this._timeSignature() * parseFloat(m)); + if (mode && mode.toLowerCase() === "db") { + freqToFloat(this); + this.analyser.getFloatFrequencyData(this.freqDomain); + return this.freqDomain; + } else { + freqToInt(this, this.freqDomain); + this.analyser.getByteFrequencyData(this.freqDomain); + var normalArray = Array.apply([], this.freqDomain); + normalArray.length === this.analyser.fftSize; + normalArray.constructor === Array; + return normalArray; } - if (q && q !== '0') { - total *= this._beatsToUnits(parseFloat(q)); + }; + /** + * Returns the amount of energy (volume) at a specific + * + * frequency, or the average amount of energy between two + * frequencies. Accepts Number(s) corresponding + * to frequency (in Hz), or a String corresponding to predefined + * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). + * Returns a range between 0 (no energy/volume at that frequency) and + * 255 (maximum energy). + * NOTE: analyze() must be called prior to getEnergy(). Analyze() + * tells the FFT to analyze frequency data, and getEnergy() uses + * the results determine the value at a specific frequency or + * range of frequencies.

+ * + * @method getEnergy + * @param {Number|String} frequency1 Will return a value representing + * energy at this frequency. Alternately, + * the strings "bass", "lowMid" "mid", + * "highMid", and "treble" will return + * predefined frequency ranges. + * @param {Number} [frequency2] If a second frequency is given, + * will return average amount of + * energy that exists between the + * two frequencies. + * @return {Number} Energy Energy (volume/amplitude) from + * 0 and 255. + * + */ + p5.FFT.prototype.getEnergy = function (frequency1, frequency2) { + var nyquist = p5sound.audiocontext.sampleRate / 2; + if (frequency1 === "bass") { + frequency1 = this.bass[0]; + frequency2 = this.bass[1]; + } else if (frequency1 === "lowMid") { + frequency1 = this.lowMid[0]; + frequency2 = this.lowMid[1]; + } else if (frequency1 === "mid") { + frequency1 = this.mid[0]; + frequency2 = this.mid[1]; + } else if (frequency1 === "highMid") { + frequency1 = this.highMid[0]; + frequency2 = this.highMid[1]; + } else if (frequency1 === "treble") { + frequency1 = this.treble[0]; + frequency2 = this.treble[1]; + } + if (typeof frequency1 !== "number") { + throw "invalid input for getEnergy()"; + } else if (!frequency2) { + // if only one parameter: + var index = Math.round((frequency1 / nyquist) * this.freqDomain.length); + return this.freqDomain[index]; + } else if (frequency1 && frequency2) { + // if two parameters: + // if second is higher than first + if (frequency1 > frequency2) { + var swap = frequency2; + frequency2 = frequency1; + frequency1 = swap; + } + var lowIndex = Math.round( + (frequency1 / nyquist) * this.freqDomain.length + ); + var highIndex = Math.round( + (frequency2 / nyquist) * this.freqDomain.length + ); + var total = 0; + var numFrequencies = 0; + // add up all of the values for the frequencies + for (var i = lowIndex; i <= highIndex; i++) { + total += this.freqDomain[i]; + numFrequencies += 1; + } + // divide by total number of frequencies + var toReturn = total / numFrequencies; + return toReturn; + } else { + throw "invalid input for getEnergy()"; } - if (s && s !== '0') { - total *= this._beatsToUnits(parseFloat(s) / 4); + }; + // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated... + p5.FFT.prototype.getFreq = function (freq1, freq2) { + console.log("getFreq() is deprecated. Please use getEnergy() instead."); + var x = this.getEnergy(freq1, freq2); + return x; + }; + /** + * Returns the + * + * spectral centroid of the input signal. + * NOTE: analyze() must be called prior to getCentroid(). Analyze() + * tells the FFT to analyze frequency data, and getCentroid() uses + * the results determine the spectral centroid.

+ * + * @method getCentroid + * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz. + * + * + * @example + *
+ * + * + *function setup(){ + * cnv = createCanvas(100,100); + * sound = new p5.AudioIn(); + * sound.start(); + * fft = new p5.FFT(); + * sound.connect(fft); + *} + * + * + *function draw(){ + * + * var centroidplot = 0.0; + * var spectralCentroid = 0; + * + * + * background(0); + * stroke(0,255,0); + * var spectrum = fft.analyze(); + * fill(0,255,0); // spectrum is green + * + * //draw the spectrum + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(log(i), 0, log(spectrum.length), 0, width); + * var h = map(spectrum[i], 0, 255, 0, height); + * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length)); + * rect(x, height, rectangle_width, -h ) + * } + + * var nyquist = 22050; + * + * // get the centroid + * spectralCentroid = fft.getCentroid(); + * + * // the mean_freq_index calculation is for the display. + * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length); + * + * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); + * + * + * stroke(255,0,0); // the line showing where the centroid is will be red + * + * rect(centroidplot, 0, width / spectrum.length, height) + * noStroke(); + * fill(255,255,255); // text is white + * text("centroid: ", 10, 20); + * text(round(spectralCentroid)+" Hz", 10, 40); + *} + *
+ */ + p5.FFT.prototype.getCentroid = function () { + var nyquist = p5sound.audiocontext.sampleRate / 2; + var cumulative_sum = 0; + var centroid_normalization = 0; + for (var i = 0; i < this.freqDomain.length; i++) { + cumulative_sum += i * this.freqDomain[i]; + centroid_normalization += this.freqDomain[i]; + } + var mean_freq_index = 0; + if (centroid_normalization !== 0) { + mean_freq_index = cumulative_sum / centroid_normalization; + } + var spec_centroid_freq = + mean_freq_index * (nyquist / this.freqDomain.length); + return spec_centroid_freq; + }; + /** + * Smooth FFT analysis by averaging with the last analysis frame. + * + * @method smooth + * @param {Number} smoothing 0.0 < smoothing < 1.0. + * Defaults to 0.8. + */ + p5.FFT.prototype.smooth = function (s) { + if (typeof s !== "undefined") { + this.smoothing = s; } - return total; - } - }; - Tone.Frequency.prototype.transpose = function (interval) { - this._expr = function (expr, interval) { - var val = expr(); - return val * this.intervalToFrequencyRatio(interval); - }.bind(this, this._expr, interval); - return this; - }; - Tone.Frequency.prototype.harmonize = function (intervals) { - this._expr = function (expr, intervals) { - var val = expr(); - var ret = []; - for (var i = 0; i < intervals.length; i++) { - ret[i] = val * this.intervalToFrequencyRatio(intervals[i]); + return this.smoothing; + }; + p5.FFT.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.analyser) { + this.analyser.disconnect(); + delete this.analyser; } - return ret; - }.bind(this, this._expr, intervals); - return this; - }; - Tone.Frequency.prototype.toMidi = function () { - return this.frequencyToMidi(this.valueOf()); - }; - Tone.Frequency.prototype.toNote = function () { - var freq = this.valueOf(); - var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2; - var noteNumber = Math.round(12 * log) + 57; - var octave = Math.floor(noteNumber / 12); - if (octave < 0) { - noteNumber += -12 * octave; - } - var noteName = scaleIndexToNote[noteNumber % 12]; - return noteName + octave.toString(); - }; - Tone.Frequency.prototype.toSeconds = function () { - return 1 / this.valueOf(); - }; - Tone.Frequency.prototype.toFrequency = function () { - return this.valueOf(); - }; - Tone.Frequency.prototype.toTicks = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.valueOf() / quarterTime; - return Math.floor(quarters * Tone.Transport.PPQ); - }; - Tone.Frequency.prototype._frequencyToUnits = function (freq) { - return freq; - }; - Tone.Frequency.prototype._ticksToUnits = function (ticks) { - return 1 / (ticks * 60 / (Tone.Transport.bpm.value * Tone.Transport.PPQ)); - }; - Tone.Frequency.prototype._beatsToUnits = function (beats) { - return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats); - }; - Tone.Frequency.prototype._secondsToUnits = function (seconds) { - return 1 / seconds; - }; - Tone.Frequency.prototype._defaultUnits = 'hz'; - var noteToScaleIndex = { - 'cbb': -2, - 'cb': -1, - 'c': 0, - 'c#': 1, - 'cx': 2, - 'dbb': 0, - 'db': 1, - 'd': 2, - 'd#': 3, - 'dx': 4, - 'ebb': 2, - 'eb': 3, - 'e': 4, - 'e#': 5, - 'ex': 6, - 'fbb': 3, - 'fb': 4, - 'f': 5, - 'f#': 6, - 'fx': 7, - 'gbb': 5, - 'gb': 6, - 'g': 7, - 'g#': 8, - 'gx': 9, - 'abb': 7, - 'ab': 8, - 'a': 9, - 'a#': 10, - 'ax': 11, - 'bbb': 9, - 'bb': 10, - 'b': 11, - 'b#': 12, - 'bx': 13 - }; - var scaleIndexToNote = [ - 'C', - 'C#', - 'D', - 'D#', - 'E', - 'F', - 'F#', - 'G', - 'G#', - 'A', - 'A#', - 'B' - ]; - Tone.Frequency.A4 = 440; - Tone.Frequency.prototype.midiToFrequency = function (midi) { - return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12); - }; - Tone.Frequency.prototype.frequencyToMidi = function (frequency) { - return 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2; - }; - return Tone.Frequency; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_TransportTime; -Tone_type_TransportTime = function (Tone) { - Tone.TransportTime = function (val, units) { - if (this instanceof Tone.TransportTime) { - Tone.Time.call(this, val, units); - } else { - return new Tone.TransportTime(val, units); - } - }; - Tone.extend(Tone.TransportTime, Tone.Time); - Tone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions); - Tone.TransportTime.prototype._unaryExpressions.quantize = { - regexp: /^@/, - method: function (rh) { - var subdivision = this._secondsToTicks(rh()); - var multiple = Math.ceil(Tone.Transport.ticks / subdivision); - return this._ticksToUnits(multiple * subdivision); - } - }; - Tone.TransportTime.prototype._secondsToTicks = function (seconds) { - var quarterTime = this._beatsToUnits(1); - var quarters = seconds / quarterTime; - return Math.round(quarters * Tone.Transport.PPQ); - }; - Tone.TransportTime.prototype.valueOf = function () { - var val = this._secondsToTicks(this._expr()); - return val + (this._plusNow ? Tone.Transport.ticks : 0); - }; - Tone.TransportTime.prototype.toTicks = function () { - return this.valueOf(); - }; - Tone.TransportTime.prototype.toSeconds = function () { - var val = this._expr(); - return val + (this._plusNow ? Tone.Transport.seconds : 0); - }; - Tone.TransportTime.prototype.toFrequency = function () { - return 1 / this.toSeconds(); - }; - return Tone.TransportTime; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Type; -Tone_type_Type = function (Tone) { - Tone.Type = { - Default: 'number', - Time: 'time', - Frequency: 'frequency', - TransportTime: 'transportTime', - Ticks: 'ticks', - NormalRange: 'normalRange', - AudioRange: 'audioRange', - Decibels: 'db', - Interval: 'interval', - BPM: 'bpm', - Positive: 'positive', - Cents: 'cents', - Degrees: 'degrees', - MIDI: 'midi', - BarsBeatsSixteenths: 'barsBeatsSixteenths', - Samples: 'samples', - Hertz: 'hertz', - Note: 'note', - Milliseconds: 'milliseconds', - Seconds: 'seconds', - Notation: 'notation' - }; - Tone.prototype.toSeconds = function (time) { - if (this.isNumber(time)) { - return time; - } else if (this.isUndef(time)) { - return this.now(); - } else if (this.isString(time)) { - return new Tone.Time(time).toSeconds(); - } else if (time instanceof Tone.TimeBase) { - return time.toSeconds(); - } - }; - Tone.prototype.toFrequency = function (freq) { - if (this.isNumber(freq)) { - return freq; - } else if (this.isString(freq) || this.isUndef(freq)) { - return new Tone.Frequency(freq).valueOf(); - } else if (freq instanceof Tone.TimeBase) { - return freq.toFrequency(); - } - }; - Tone.prototype.toTicks = function (time) { - if (this.isNumber(time) || this.isString(time)) { - return new Tone.TransportTime(time).toTicks(); - } else if (this.isUndef(time)) { - return Tone.Transport.ticks; - } else if (time instanceof Tone.TimeBase) { - return time.toTicks(); - } - }; - return Tone; -}(Tone_core_Tone, Tone_type_Time, Tone_type_Frequency, Tone_type_TransportTime); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Param; -Tone_core_Param = function (Tone) { - 'use strict'; - Tone.Param = function () { - var options = this.optionsObject(arguments, [ - 'param', - 'units', - 'convert' - ], Tone.Param.defaults); - this._param = this.input = options.param; - this.units = options.units; - this.convert = options.convert; - this.overridden = false; - this._lfo = null; - if (this.isObject(options.lfo)) { - this.value = options.lfo; - } else if (!this.isUndef(options.value)) { - this.value = options.value; - } - }; - Tone.extend(Tone.Param); - Tone.Param.defaults = { - 'units': Tone.Type.Default, - 'convert': true, - 'param': undefined - }; - Object.defineProperty(Tone.Param.prototype, 'value', { - get: function () { - return this._toUnits(this._param.value); - }, - set: function (value) { - if (this.isObject(value)) { - if (this.isUndef(Tone.LFO)) { - throw new Error('Include \'Tone.LFO\' to use an LFO as a Param value.'); - } - if (this._lfo) { - this._lfo.dispose(); - } - this._lfo = new Tone.LFO(value).start(); - this._lfo.connect(this.input); - } else { - var convertedVal = this._fromUnits(value); - this._param.cancelScheduledValues(0); - this._param.value = convertedVal; + }; + /** + * Returns an array of average amplitude values for a given number + * of frequency bands split equally. N defaults to 16. + * NOTE: analyze() must be called prior to linAverages(). Analyze() + * tells the FFT to analyze frequency data, and linAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method linAverages + * @param {Number} N Number of returned frequency groups + * @return {Array} linearAverages Array of average amplitude values for each group + */ + p5.FFT.prototype.linAverages = function (N) { + var N = N || 16; + // This prevents undefined, null or 0 values of N + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var spectrumStep = Math.floor(spectrumLength / N); + var linearAverages = new Array(N); + // Keep a second index for the current average group and place the values accordingly + // with only one loop in the spectrum data + var groupIndex = 0; + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + linearAverages[groupIndex] = + linearAverages[groupIndex] !== undefined + ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 + : spectrum[specIndex]; + // Increase the group index when the last element of the group is processed + if (specIndex % spectrumStep === spectrumStep - 1) { + groupIndex++; + } } - } - }); - Tone.Param.prototype._fromUnits = function (val) { - if (this.convert || this.isUndef(this.convert)) { - switch (this.units) { - case Tone.Type.Time: - return this.toSeconds(val); - case Tone.Type.Frequency: - return this.toFrequency(val); - case Tone.Type.Decibels: - return this.dbToGain(val); - case Tone.Type.NormalRange: - return Math.min(Math.max(val, 0), 1); - case Tone.Type.AudioRange: - return Math.min(Math.max(val, -1), 1); - case Tone.Type.Positive: - return Math.max(val, 0); - default: - return val; + return linearAverages; + }; + /** + * Returns an array of average amplitude values of the spectrum, for a given + * set of + * Octave Bands + * NOTE: analyze() must be called prior to logAverages(). Analyze() + * tells the FFT to analyze frequency data, and logAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method logAverages + * @param {Array} octaveBands Array of Octave Bands objects for grouping + * @return {Array} logAverages Array of average amplitude values for each group + */ + p5.FFT.prototype.logAverages = function (octaveBands) { + var nyquist = p5sound.audiocontext.sampleRate / 2; + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var logAverages = new Array(octaveBands.length); + // Keep a second index for the current average group and place the values accordingly + // With only one loop in the spectrum data + var octaveIndex = 0; + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + var specIndexFrequency = Math.round( + (specIndex * nyquist) / this.freqDomain.length + ); + // Increase the group index if the current frequency exceeds the limits of the band + if (specIndexFrequency > octaveBands[octaveIndex].hi) { + octaveIndex++; + } + logAverages[octaveIndex] = + logAverages[octaveIndex] !== undefined + ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 + : spectrum[specIndex]; } - } else { - return val; - } - }; - Tone.Param.prototype._toUnits = function (val) { - if (this.convert || this.isUndef(this.convert)) { - switch (this.units) { - case Tone.Type.Decibels: - return this.gainToDb(val); - default: - return val; - } - } else { - return val; - } - }; - Tone.Param.prototype._minOutput = 0.00001; - Tone.Param.prototype.setValueAtTime = function (value, time) { - value = this._fromUnits(value); - time = this.toSeconds(time); - if (time <= this.now() + this.blockTime) { - this._param.value = value; - } else { - this._param.setValueAtTime(value, time); - } - return this; - }; - Tone.Param.prototype.setRampPoint = function (now) { - now = this.defaultArg(now, this.now()); - var currentVal = this._param.value; - if (currentVal === 0) { - currentVal = this._minOutput; - } - this._param.setValueAtTime(currentVal, now); - return this; - }; - Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - this._param.linearRampToValueAtTime(value, this.toSeconds(endTime)); - return this; - }; - Tone.Param.prototype.exponentialRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime)); - return this; - }; - Tone.Param.prototype.exponentialRampToValue = function (value, rampTime, startTime) { - startTime = this.toSeconds(startTime); - this.setRampPoint(startTime); - this.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); - return this; - }; - Tone.Param.prototype.linearRampToValue = function (value, rampTime, startTime) { - startTime = this.toSeconds(startTime); - this.setRampPoint(startTime); - this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); - return this; - }; - Tone.Param.prototype.setTargetAtTime = function (value, startTime, timeConstant) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - timeConstant = Math.max(this._minOutput, timeConstant); - this._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant); - return this; - }; - Tone.Param.prototype.setValueCurveAtTime = function (values, startTime, duration) { - for (var i = 0; i < values.length; i++) { - values[i] = this._fromUnits(values[i]); - } - this._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration)); - return this; - }; - Tone.Param.prototype.cancelScheduledValues = function (startTime) { - this._param.cancelScheduledValues(this.toSeconds(startTime)); - return this; - }; - Tone.Param.prototype.rampTo = function (value, rampTime, startTime) { - rampTime = this.defaultArg(rampTime, 0); - if (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels) { - this.exponentialRampToValue(value, rampTime, startTime); - } else { - this.linearRampToValue(value, rampTime, startTime); - } - return this; - }; - Object.defineProperty(Tone.Param.prototype, 'lfo', { - get: function () { - return this._lfo; - } - }); - Tone.Param.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._param = null; - if (this._lfo) { - this._lfo.dispose(); - this._lfo = null; - } - return this; - }; - return Tone.Param; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Gain; -Tone_core_Gain = function (Tone) { - 'use strict'; - if (window.GainNode && !AudioContext.prototype.createGain) { - AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; - } - Tone.Gain = function () { - var options = this.optionsObject(arguments, [ - 'gain', - 'units' - ], Tone.Gain.defaults); - this.input = this.output = this._gainNode = this.context.createGain(); - this.gain = new Tone.Param({ - 'param': this._gainNode.gain, - 'units': options.units, - 'value': options.gain, - 'convert': options.convert - }); - this._readOnly('gain'); - }; - Tone.extend(Tone.Gain); - Tone.Gain.defaults = { - 'gain': 1, - 'convert': true - }; - Tone.Gain.prototype.dispose = function () { - Tone.Param.prototype.dispose.call(this); - this._gainNode.disconnect(); - this._gainNode = null; - this._writable('gain'); - this.gain.dispose(); - this.gain = null; - }; - Tone.prototype.createInsOuts = function (inputs, outputs) { - if (inputs === 1) { - this.input = new Tone.Gain(); - } else if (inputs > 1) { - this.input = new Array(inputs); - } - if (outputs === 1) { - this.output = new Tone.Gain(); - } else if (outputs > 1) { - this.output = new Array(inputs); - } - }; - return Tone.Gain; -}(Tone_core_Tone, Tone_core_Param); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Signal; -Tone_signal_Signal = function (Tone) { - 'use strict'; - Tone.Signal = function () { - var options = this.optionsObject(arguments, [ - 'value', - 'units' - ], Tone.Signal.defaults); - this.output = this._gain = this.context.createGain(); - options.param = this._gain.gain; - Tone.Param.call(this, options); - this.input = this._param = this._gain.gain; - this.context.getConstant(1).chain(this._gain); - }; - Tone.extend(Tone.Signal, Tone.Param); - Tone.Signal.defaults = { - 'value': 0, - 'units': Tone.Type.Default, - 'convert': true - }; - Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect; - Tone.Signal.prototype.dispose = function () { - Tone.Param.prototype.dispose.call(this); - this._param = null; - this._gain.disconnect(); - this._gain = null; - return this; - }; - return Tone.Signal; -}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_type_Type, Tone_core_Param); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Add; -Tone_signal_Add = function (Tone) { - 'use strict'; - Tone.Add = function (value) { - this.createInsOuts(2, 0); - this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain(); - this._param = this.input[1] = new Tone.Signal(value); - this._param.connect(this._sum); - }; - Tone.extend(Tone.Add, Tone.Signal); - Tone.Add.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._sum.dispose(); - this._sum = null; - this._param.dispose(); - this._param = null; - return this; - }; - return Tone.Add; -}(Tone_core_Tone, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Multiply; -Tone_signal_Multiply = function (Tone) { - 'use strict'; - Tone.Multiply = function (value) { - this.createInsOuts(2, 0); - this._mult = this.input[0] = this.output = new Tone.Gain(); - this._param = this.input[1] = this.output.gain; - this._param.value = this.defaultArg(value, 0); - }; - Tone.extend(Tone.Multiply, Tone.Signal); - Tone.Multiply.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._mult.dispose(); - this._mult = null; - this._param = null; - return this; - }; - return Tone.Multiply; -}(Tone_core_Tone, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Scale; -Tone_signal_Scale = function (Tone) { - 'use strict'; - Tone.Scale = function (outputMin, outputMax) { - this._outputMin = this.defaultArg(outputMin, 0); - this._outputMax = this.defaultArg(outputMax, 1); - this._scale = this.input = new Tone.Multiply(1); - this._add = this.output = new Tone.Add(0); - this._scale.connect(this._add); - this._setRange(); - }; - Tone.extend(Tone.Scale, Tone.SignalBase); - Object.defineProperty(Tone.Scale.prototype, 'min', { - get: function () { - return this._outputMin; - }, - set: function (min) { - this._outputMin = min; - this._setRange(); - } - }); - Object.defineProperty(Tone.Scale.prototype, 'max', { - get: function () { - return this._outputMax; - }, - set: function (max) { - this._outputMax = max; - this._setRange(); - } - }); - Tone.Scale.prototype._setRange = function () { - this._add.value = this._outputMin; - this._scale.value = this._outputMax - this._outputMin; - }; - Tone.Scale.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._add.dispose(); - this._add = null; - this._scale.dispose(); - this._scale = null; - return this; - }; - return Tone.Scale; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Multiply); -var signal; -'use strict'; -signal = function () { - // Signal is built with the Tone.js signal by Yotam Mann - // https://github.com/TONEnoTONE/Tone.js/ - var Signal = Tone_signal_Signal; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - /** - *

p5.Signal is a constant audio-rate signal used by p5.Oscillator - * and p5.Envelope for modulation math.

- * - *

This is necessary because Web Audio is processed on a seprate clock. - * For example, the p5 draw loop runs about 60 times per second. But - * the audio clock must process samples 44100 times per second. If we - * want to add a value to each of those samples, we can't do it in the - * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns - * a Tone.Signal from the Tone.js library by Yotam Mann. - * If you want to work directly with audio signals for modular - * synthesis, check out - * tone.js.

- * - * @class p5.Signal - * @constructor - * @return {Tone.Signal} A Signal object from the Tone.js library - * @example - *
- * function setup() { - * carrier = new p5.Oscillator('sine'); - * carrier.amp(1); // set amplitude - * carrier.freq(220); // set frequency - * carrier.start(); // start oscillating - * - * modulator = new p5.Oscillator('sawtooth'); - * modulator.disconnect(); - * modulator.amp(1); - * modulator.freq(4); - * modulator.start(); - * - * // Modulator's default amplitude range is -1 to 1. - * // Multiply it by -200, so the range is -200 to 200 - * // then add 220 so the range is 20 to 420 - * carrier.freq( modulator.mult(-200).add(220) ); - * } - *
- */ - p5.Signal = function (value) { - var s = new Signal(value); - // p5sound.soundArray.push(s); - return s; - }; - /** - * Fade to value, for smooth transitions - * - * @method fade - * @param {Number} value Value to set this signal - * @param {Number} [secondsFromNow] Length of fade, in seconds from now - */ - Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime; - Mult.prototype.fade = Signal.prototype.fade; - Add.prototype.fade = Signal.prototype.fade; - Scale.prototype.fade = Signal.prototype.fade; - /** - * Connect a p5.sound object or Web Audio node to this - * p5.Signal so that its amplitude values can be scaled. - * - * @method setInput - * @param {Object} input - */ - Signal.prototype.setInput = function (_input) { - _input.connect(this); - }; - Mult.prototype.setInput = Signal.prototype.setInput; - Add.prototype.setInput = Signal.prototype.setInput; - Scale.prototype.setInput = Signal.prototype.setInput; - // signals can add / mult / scale themselves - /** - * Add a constant value to this audio signal, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalAdd. - * - * @method add - * @param {Number} number - * @return {p5.Signal} object - */ - Signal.prototype.add = function (num) { - var add = new Add(num); - // add.setInput(this); - this.connect(add); - return add; - }; - Mult.prototype.add = Signal.prototype.add; - Add.prototype.add = Signal.prototype.add; - Scale.prototype.add = Signal.prototype.add; - /** - * Multiply this signal by a constant value, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalMult. - * - * @method mult - * @param {Number} number to multiply - * @return {p5.Signal} object - */ - Signal.prototype.mult = function (num) { - var mult = new Mult(num); - // mult.setInput(this); - this.connect(mult); - return mult; - }; - Mult.prototype.mult = Signal.prototype.mult; - Add.prototype.mult = Signal.prototype.mult; - Scale.prototype.mult = Signal.prototype.mult; - /** - * Scale this signal value to a given range, - * and return the result as an audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalScale. - * - * @method scale - * @param {Number} number to multiply - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Signal} object - */ - Signal.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - var scale = new Scale(mapOutMin, mapOutMax); - this.connect(scale); - return scale; - }; - Mult.prototype.scale = Signal.prototype.scale; - Add.prototype.scale = Signal.prototype.scale; - Scale.prototype.scale = Signal.prototype.scale; -}(Tone_signal_Signal, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); -var oscillator; -'use strict'; -oscillator = function () { - var p5sound = master; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - /** - *

Creates a signal that oscillates between -1.0 and 1.0. - * By default, the oscillation takes the form of a sinusoidal - * shape ('sine'). Additional types include 'triangle', - * 'sawtooth' and 'square'. The frequency defaults to - * 440 oscillations per second (440Hz, equal to the pitch of an - * 'A' note).

- * - *

Set the type of oscillation with setType(), or by instantiating a - * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. - *

- * - * @class p5.Oscillator - * @constructor - * @param {Number} [freq] frequency defaults to 440Hz - * @param {String} [type] type of oscillator. Options: - * 'sine' (default), 'triangle', - * 'sawtooth', 'square' - * @example - *
- * var osc; - * var playing = false; - * - * function setup() { - * backgroundColor = color(255,0,255); - * textAlign(CENTER); - * - * osc = new p5.Oscillator(); - * osc.setType('sine'); - * osc.freq(240); - * osc.amp(0); - * osc.start(); - * } - * - * function draw() { - * background(backgroundColor) - * text('click to play', width/2, height/2); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { - * if (!playing) { - * // ramp amplitude to 0.5 over 0.05 seconds - * osc.amp(0.5, 0.05); - * playing = true; - * backgroundColor = color(0,255,255); - * } else { - * // ramp amplitude to 0 over 0.5 seconds - * osc.amp(0, 0.5); - * playing = false; - * backgroundColor = color(255,0,255); - * } - * } - * } - *
- */ - p5.Oscillator = function (freq, type) { - if (typeof freq === 'string') { - var f = type; - type = freq; - freq = f; - } - if (typeof type === 'number') { - var f = type; - type = freq; - freq = f; - } - this.started = false; - // components - this.phaseAmount = undefined; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.f = freq || 440; - // frequency - this.oscillator.type = type || 'sine'; - this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime); - // connections - this.output = p5sound.audiocontext.createGain(); - this._freqMods = []; - // modulators connected to this oscillator's frequency - // set default output gain to 0.5 - this.output.gain.value = 0.5; - this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime); - this.oscillator.connect(this.output); - // stereo panning - this.panPosition = 0; - this.connection = p5sound.input; - // connect to p5sound by default - this.panner = new p5.Panner(this.output, this.connection, 1); - //array of math operation signal chaining - this.mathOps = [this.output]; - // add to the soundArray so we can dispose of the osc later - p5sound.soundArray.push(this); - }; - /** - * Start an oscillator. Accepts an optional parameter to - * determine how long (in seconds from now) until the - * oscillator starts. - * - * @method start - * @param {Number} [time] startTime in seconds from now. - * @param {Number} [frequency] frequency in Hz. - */ - p5.Oscillator.prototype.start = function (time, f) { - if (this.started) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - } - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - // set old osc free to be garbage collected (memory) - if (this.oscillator) { - this.oscillator.disconnect(); - delete this.oscillator; + return logAverages; + }; + /** + * Calculates and Returns the 1/N + * Octave Bands + * N defaults to 3 and minimum central frequency to 15.625Hz. + * (1/3 Octave Bands ~= 31 Frequency Bands) + * Setting fCtr0 to a central value of a higher octave will ignore the lower bands + * and produce less frequency groups. + * + * @method getOctaveBands + * @param {Number} N Specifies the 1/N type of generated octave bands + * @param {Number} fCtr0 Minimum central frequency for the lowest band + * @return {Array} octaveBands Array of octave band objects with their bounds + */ + p5.FFT.prototype.getOctaveBands = function (N, fCtr0) { + var N = N || 3; + // Default to 1/3 Octave Bands + var fCtr0 = fCtr0 || 15.625; + // Minimum central frequency, defaults to 15.625Hz + var octaveBands = []; + var lastFrequencyBand = { + lo: fCtr0 / Math.pow(2, 1 / (2 * N)), + ctr: fCtr0, + hi: fCtr0 * Math.pow(2, 1 / (2 * N)), + }; + octaveBands.push(lastFrequencyBand); + var nyquist = p5sound.audiocontext.sampleRate / 2; + while (lastFrequencyBand.hi < nyquist) { + var newFrequencyBand = {}; + newFrequencyBand.lo = lastFrequencyBand.hi; + newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); + newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); + octaveBands.push(newFrequencyBand); + lastFrequencyBand = newFrequencyBand; + } + return octaveBands; + }; + // helper methods to convert type from float (dB) to int (0-255) + var freqToFloat = function (fft) { + if (fft.freqDomain instanceof Float32Array === false) { + fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); } - // var detune = this.oscillator.frequency.value; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.oscillator.frequency.value = Math.abs(freq); - this.oscillator.type = type; - // this.oscillator.detune.value = detune; - this.oscillator.connect(this.output); - time = time || 0; - this.oscillator.start(time + p5sound.audiocontext.currentTime); - this.freqNode = this.oscillator.frequency; - // if other oscillators are already connected to this osc's freq - for (var i in this._freqMods) { - if (typeof this._freqMods[i].connect !== 'undefined') { - this._freqMods[i].connect(this.oscillator.frequency); - } + }; + var freqToInt = function (fft) { + if (fft.freqDomain instanceof Uint8Array === false) { + fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); } - this.started = true; - } - }; - /** - * Stop an oscillator. Accepts an optional parameter - * to determine how long (in seconds from now) until the - * oscillator stops. - * - * @method stop - * @param {Number} secondsFromNow Time, in seconds from now. - */ - p5.Oscillator.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = p5sound.audiocontext.currentTime; - this.oscillator.stop(t + now); - this.started = false; - } - }; - /** - * Set the amplitude between 0 and 1.0. Or, pass in an object - * such as an oscillator to modulate amplitude with an audio signal. - * - * @method amp - * @param {Number|Object} vol between 0 and 1.0 - * or a modulating signal/oscillator - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {AudioParam} gain If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's - * gain/amplitude/volume) - */ - p5.Oscillator.prototype.amp = function (vol, rampTime, tFromNow) { - var self = this; - if (typeof vol === 'number') { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(self.output.gain); - } else { - // return the Gain Node - return this.output.gain; - } - }; - // these are now the same thing - p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp; - p5.Oscillator.prototype.getAmp = function () { - return this.output.gain.value; - }; - /** - * Set frequency of an oscillator to a value. Or, pass in an object - * such as an oscillator to modulate the frequency with an audio signal. - * - * @method freq - * @param {Number|Object} Frequency Frequency in Hz - * or modulating signal/oscillator - * @param {Number} [rampTime] Ramp time (in seconds) - * @param {Number} [timeFromNow] Schedule this event to happen - * at x seconds from now - * @return {AudioParam} Frequency If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's frequency - * @example - *
- * var osc = new p5.Oscillator(300); - * osc.start(); - * osc.freq(40, 10); - *
- */ - p5.Oscillator.prototype.freq = function (val, rampTime, tFromNow) { - if (typeof val === 'number' && !isNaN(val)) { - this.f = val; - var now = p5sound.audiocontext.currentTime; - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var t = now + tFromNow + rampTime; - // var currentFreq = this.oscillator.frequency.value; - // this.oscillator.frequency.cancelScheduledValues(now); - if (rampTime === 0) { - this.oscillator.frequency.setValueAtTime(val, tFromNow + now); - } else { - if (val > 0) { - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - } else { - this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now); - } + }; + var timeToFloat = function (fft) { + if (fft.timeDomain instanceof Float32Array === false) { + fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); } - // reset phase if oscillator has a phase - if (this.phaseAmount) { - this.phase(this.phaseAmount); + }; + var timeToInt = function (fft) { + if (fft.timeDomain instanceof Uint8Array === false) { + fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); } - } else if (val) { - if (val.output) { - val = val.output; + }; + })(master); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_SignalBase; + Tone_signal_SignalBase = (function (Tone) { + "use strict"; + Tone.SignalBase = function () {}; + Tone.extend(Tone.SignalBase); + Tone.SignalBase.prototype.connect = function ( + node, + outputNumber, + inputNumber + ) { + if ( + (Tone.Signal && Tone.Signal === node.constructor) || + (Tone.Param && Tone.Param === node.constructor) || + (Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) + ) { + node._param.cancelScheduledValues(0); + node._param.value = 0; + node.overridden = true; + } else if (node instanceof AudioParam) { + node.cancelScheduledValues(0); + node.value = 0; + } + Tone.prototype.connect.call(this, node, outputNumber, inputNumber); + return this; + }; + return Tone.SignalBase; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_WaveShaper; + Tone_signal_WaveShaper = (function (Tone) { + "use strict"; + Tone.WaveShaper = function (mapping, bufferLen) { + this._shaper = this.input = this.output = this.context.createWaveShaper(); + this._curve = null; + if (Array.isArray(mapping)) { + this.curve = mapping; + } else if (isFinite(mapping) || this.isUndef(mapping)) { + this._curve = new Float32Array(this.defaultArg(mapping, 1024)); + } else if (this.isFunction(mapping)) { + this._curve = new Float32Array(this.defaultArg(bufferLen, 1024)); + this.setMap(mapping); } - val.connect(this.oscillator.frequency); - // keep track of what is modulating this param - // so it can be re-connected if - this._freqMods.push(val); - } else { - // return the Frequency Node - return this.oscillator.frequency; - } - }; - p5.Oscillator.prototype.getFreq = function () { - return this.oscillator.frequency.value; - }; - /** - * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. - * - * @method setType - * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. - */ - p5.Oscillator.prototype.setType = function (type) { - this.oscillator.type = type; - }; - p5.Oscillator.prototype.getType = function () { - return this.oscillator.type; - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.Oscillator.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(p5sound.input); - } else if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); - this.connection = unit.input; - } else { - this.panner.connect(unit); - this.connection = unit; - } - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.Oscillator.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - if (this.panner) { - this.panner.disconnect(); - if (this.output) { - this.output.connect(this.panner); + }; + Tone.extend(Tone.WaveShaper, Tone.SignalBase); + Tone.WaveShaper.prototype.setMap = function (mapping) { + for (var i = 0, len = this._curve.length; i < len; i++) { + var normalized = (i / (len - 1)) * 2 - 1; + this._curve[i] = mapping(normalized, i); } - } - this.oscMods = []; - }; - /** - * Pan between Left (-1) and Right (1) - * - * @method pan - * @param {Number} panning Number between -1 and 1 - * @param {Number} timeFromNow schedule this event to happen - * seconds from now - */ - p5.Oscillator.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); - }; - p5.Oscillator.prototype.getPan = function () { - return this.panPosition; - }; - // get rid of the oscillator - p5.Oscillator.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.oscillator) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - this.disconnect(); - this.panner = null; - this.oscillator = null; - } - // if it is a Pulse - if (this.osc2) { - this.osc2.dispose(); - } - }; - /** - * Set the phase of an oscillator between 0.0 and 1.0. - * In this implementation, phase is a delay time - * based on the oscillator's current frequency. - * - * @method phase - * @param {Number} phase float between 0.0 and 1.0 - */ - p5.Oscillator.prototype.phase = function (p) { - var delayAmt = p5.prototype.map(p, 0, 1, 0, 1 / this.f); - var now = p5sound.audiocontext.currentTime; - this.phaseAmount = p; - if (!this.dNode) { - // create a delay node - this.dNode = p5sound.audiocontext.createDelay(); - // put the delay node in between output and panner - this.oscillator.disconnect(); - this.oscillator.connect(this.dNode); - this.dNode.connect(this.output); - } - // set delay time to match phase: - this.dNode.delayTime.setValueAtTime(delayAmt, now); - }; - // ========================== // - // SIGNAL MATH FOR MODULATION // - // ========================== // - // return sigChain(this, scale, thisChain, nextChain, Scale); - var sigChain = function (o, mathObj, thisChain, nextChain, type) { - var chainSource = o.oscillator; - // if this type of math already exists in the chain, replace it - for (var i in o.mathOps) { - if (o.mathOps[i] instanceof type) { - chainSource.disconnect(); - o.mathOps[i].dispose(); - thisChain = i; - // assume nextChain is output gain node unless... - if (thisChain < o.mathOps.length - 2) { - nextChain = o.mathOps[i + 1]; + this._shaper.curve = this._curve; + return this; + }; + Object.defineProperty(Tone.WaveShaper.prototype, "curve", { + get: function () { + return this._shaper.curve; + }, + set: function (mapping) { + this._curve = new Float32Array(mapping); + this._shaper.curve = this._curve; + }, + }); + Object.defineProperty(Tone.WaveShaper.prototype, "oversample", { + get: function () { + return this._shaper.oversample; + }, + set: function (oversampling) { + if (["none", "2x", "4x"].indexOf(oversampling) !== -1) { + this._shaper.oversample = oversampling; + } else { + throw new RangeError( + "Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'" + ); + } + }, + }); + Tone.WaveShaper.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._shaper.disconnect(); + this._shaper = null; + this._curve = null; + return this; + }; + return Tone.WaveShaper; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_TimeBase; + Tone_type_TimeBase = (function (Tone) { + Tone.TimeBase = function (val, units) { + if (this instanceof Tone.TimeBase) { + this._expr = this._noOp; + if (val instanceof Tone.TimeBase) { + this.copy(val); + } else if (!this.isUndef(units) || this.isNumber(val)) { + units = this.defaultArg(units, this._defaultUnits); + var method = this._primaryExpressions[units].method; + this._expr = method.bind(this, val); + } else if (this.isString(val)) { + this.set(val); + } else if (this.isUndef(val)) { + this._expr = this._defaultExpr(); } + } else { + return new Tone.TimeBase(val, units); } - } - if (thisChain === o.mathOps.length - 1) { - o.mathOps.push(nextChain); - } - // assume source is the oscillator unless i > 0 - if (i > 0) { - chainSource = o.mathOps[i - 1]; - } - chainSource.disconnect(); - chainSource.connect(mathObj); - mathObj.connect(nextChain); - o.mathOps[thisChain] = mathObj; - return o; - }; - /** - * Add a value to the p5.Oscillator's output amplitude, - * and return the oscillator. Calling this method again - * will override the initial add() with a new value. - * - * @method add - * @param {Number} number Constant number to add - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - * - */ - p5.Oscillator.prototype.add = function (num) { - var add = new Add(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, add, thisChain, nextChain, Add); - }; - /** - * Multiply the p5.Oscillator's output amplitude - * by a fixed value (i.e. turn it up!). Calling this method - * again will override the initial mult() with a new value. - * - * @method mult - * @param {Number} number Constant number to multiply - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with multiplied output - */ - p5.Oscillator.prototype.mult = function (num) { - var mult = new Mult(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, mult, thisChain, nextChain, Mult); - }; - /** - * Scale this oscillator's amplitude values to a given - * range, and return the oscillator. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - */ - p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - var scale = new Scale(mapOutMin, mapOutMax); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, scale, thisChain, nextChain, Scale); - }; - // ============================== // - // SinOsc, TriOsc, SqrOsc, SawOsc // - // ============================== // - /** - * Constructor: new p5.SinOsc(). - * This creates a Sine Wave Oscillator and is - * equivalent to new p5.Oscillator('sine') - * or creating a p5.Oscillator and then calling - * its method setType('sine'). - * See p5.Oscillator for methods. - * - * @class p5.SinOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SinOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sine'); - }; - p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.TriOsc(). - * This creates a Triangle Wave Oscillator and is - * equivalent to new p5.Oscillator('triangle') - * or creating a p5.Oscillator and then calling - * its method setType('triangle'). - * See p5.Oscillator for methods. - * - * @class p5.TriOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.TriOsc = function (freq) { - p5.Oscillator.call(this, freq, 'triangle'); - }; - p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.SawOsc(). - * This creates a SawTooth Wave Oscillator and is - * equivalent to new p5.Oscillator('sawtooth') - * or creating a p5.Oscillator and then calling - * its method setType('sawtooth'). - * See p5.Oscillator for methods. - * - * @class p5.SawOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SawOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sawtooth'); - }; - p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.SqrOsc(). - * This creates a Square Wave Oscillator and is - * equivalent to new p5.Oscillator('square') - * or creating a p5.Oscillator and then calling - * its method setType('square'). - * See p5.Oscillator for methods. - * - * @class p5.SqrOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SqrOsc = function (freq) { - p5.Oscillator.call(this, freq, 'square'); - }; - p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype); -}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Timeline; -Tone_core_Timeline = function (Tone) { - 'use strict'; - Tone.Timeline = function () { - var options = this.optionsObject(arguments, ['memory'], Tone.Timeline.defaults); - this._timeline = []; - this._toRemove = []; - this._iterating = false; - this.memory = options.memory; - }; - Tone.extend(Tone.Timeline); - Tone.Timeline.defaults = { 'memory': Infinity }; - Object.defineProperty(Tone.Timeline.prototype, 'length', { - get: function () { - return this._timeline.length; - } - }); - Tone.Timeline.prototype.add = function (event) { - if (this.isUndef(event.time)) { - throw new Error('Tone.Timeline: events must have a time attribute'); - } - if (this._timeline.length) { - var index = this._search(event.time); - this._timeline.splice(index + 1, 0, event); - } else { - this._timeline.push(event); - } - if (this.length > this.memory) { - var diff = this.length - this.memory; - this._timeline.splice(0, diff); - } - return this; - }; - Tone.Timeline.prototype.remove = function (event) { - if (this._iterating) { - this._toRemove.push(event); - } else { - var index = this._timeline.indexOf(event); - if (index !== -1) { - this._timeline.splice(index, 1); + }; + Tone.extend(Tone.TimeBase); + Tone.TimeBase.prototype.set = function (exprString) { + this._expr = this._parseExprString(exprString); + return this; + }; + Tone.TimeBase.prototype.clone = function () { + var instance = new this.constructor(); + instance.copy(this); + return instance; + }; + Tone.TimeBase.prototype.copy = function (time) { + var val = time._expr(); + return this.set(val); + }; + Tone.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (value) { + value = parseInt(value); + if (value === 1) { + return this._beatsToUnits(this._timeSignature()); + } else { + return this._beatsToUnits(4 / value); + } + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (value) { + value = parseInt(value); + return this._beatsToUnits(8 / (parseInt(value) * 3)); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (value) { + return this._beatsToUnits(parseInt(value) * this._timeSignature()); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (value) { + return this._ticksToUnits(parseInt(value)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (value) { + return this._frequencyToUnits(parseFloat(value)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (m, q, s) { + var total = 0; + if (m && m !== "0") { + total += this._beatsToUnits(this._timeSignature() * parseFloat(m)); + } + if (q && q !== "0") { + total += this._beatsToUnits(parseFloat(q)); + } + if (s && s !== "0") { + total += this._beatsToUnits(parseFloat(s) / 4); + } + return total; + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (value) { + return this._secondsToUnits(parseFloat(value)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (value) { + return parseInt(value) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (value) { + return this._primaryExpressions[this._defaultUnits].method.call( + this, + value + ); + }, + }, + }; + Tone.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (lh, rh) { + return lh() + rh(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (lh, rh) { + return lh() - rh(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (lh, rh) { + return lh() * rh(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (lh, rh) { + return lh() / rh(); + }, + }, + }; + Tone.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (lh) { + return -lh(); + }, + }, + }; + Tone.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }; + Tone.TimeBase.prototype._tokenize = function (expr) { + var position = -1; + var tokens = []; + while (expr.length > 0) { + expr = expr.trim(); + var token = getNextToken(expr, this); + tokens.push(token); + expr = expr.substr(token.value.length); + } + function getNextToken(expr, context) { + var expressions = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ]; + for (var i = 0; i < expressions.length; i++) { + var group = context[expressions[i]]; + for (var opName in group) { + var op = group[opName]; + var reg = op.regexp; + var match = expr.match(reg); + if (match !== null) { + return { + method: op.method, + precedence: op.precedence, + regexp: op.regexp, + value: match[0], + }; + } + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + expr); } - } - return this; - }; - Tone.Timeline.prototype.get = function (time) { - var index = this._search(time); - if (index !== -1) { - return this._timeline[index]; - } else { - return null; - } - }; - Tone.Timeline.prototype.peek = function () { - return this._timeline[0]; - }; - Tone.Timeline.prototype.shift = function () { - return this._timeline.shift(); - }; - Tone.Timeline.prototype.getAfter = function (time) { - var index = this._search(time); - if (index + 1 < this._timeline.length) { - return this._timeline[index + 1]; - } else { - return null; - } - }; - Tone.Timeline.prototype.getBefore = function (time) { - var len = this._timeline.length; - if (len > 0 && this._timeline[len - 1].time < time) { - return this._timeline[len - 1]; - } - var index = this._search(time); - if (index - 1 >= 0) { - return this._timeline[index - 1]; - } else { - return null; - } - }; - Tone.Timeline.prototype.cancel = function (after) { - if (this._timeline.length > 1) { - var index = this._search(after); - if (index >= 0) { - if (this._timeline[index].time === after) { - for (var i = index; i >= 0; i--) { - if (this._timeline[i].time === after) { - index = i; + return { + next: function () { + return tokens[++position]; + }, + peek: function () { + return tokens[position + 1]; + }, + }; + }; + Tone.TimeBase.prototype._matchGroup = function (token, group, prec) { + var ret = false; + if (!this.isUndef(token)) { + for (var opName in group) { + var op = group[opName]; + if (op.regexp.test(token.value)) { + if (!this.isUndef(prec)) { + if (op.precedence === prec) { + return op; + } } else { - break; + return op; } } - this._timeline = this._timeline.slice(0, index); - } else { - this._timeline = this._timeline.slice(0, index + 1); } - } else { - this._timeline = []; } - } else if (this._timeline.length === 1) { - if (this._timeline[0].time >= after) { - this._timeline = []; + return ret; + }; + Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) { + if (this.isUndef(precedence)) { + precedence = 2; } - } - return this; - }; - Tone.Timeline.prototype.cancelBefore = function (time) { - if (this._timeline.length) { - var index = this._search(time); - if (index >= 0) { - this._timeline = this._timeline.slice(index + 1); + var expr; + if (precedence < 0) { + expr = this._parseUnary(lexer); + } else { + expr = this._parseBinary(lexer, precedence - 1); } - } - return this; - }; - Tone.Timeline.prototype._search = function (time) { - var beginning = 0; - var len = this._timeline.length; - var end = len; - if (len > 0 && this._timeline[len - 1].time <= time) { - return len - 1; - } - while (beginning < end) { - var midPoint = Math.floor(beginning + (end - beginning) / 2); - var event = this._timeline[midPoint]; - var nextEvent = this._timeline[midPoint + 1]; - if (event.time === time) { - for (var i = midPoint; i < this._timeline.length; i++) { - var testEvent = this._timeline[i]; - if (testEvent.time === time) { - midPoint = i; - } - } - return midPoint; - } else if (event.time < time && nextEvent.time > time) { - return midPoint; - } else if (event.time > time) { - end = midPoint; - } else if (event.time < time) { - beginning = midPoint + 1; + var token = lexer.peek(); + while ( + token && + this._matchGroup(token, this._binaryExpressions, precedence) + ) { + token = lexer.next(); + expr = token.method.bind( + this, + expr, + this._parseBinary(lexer, precedence - 1) + ); + token = lexer.peek(); } - } - return -1; - }; - Tone.Timeline.prototype._iterate = function (callback, lowerBound, upperBound) { - this._iterating = true; - lowerBound = this.defaultArg(lowerBound, 0); - upperBound = this.defaultArg(upperBound, this._timeline.length - 1); - for (var i = lowerBound; i <= upperBound; i++) { - callback(this._timeline[i]); - } - this._iterating = false; - if (this._toRemove.length > 0) { - for (var j = 0; j < this._toRemove.length; j++) { - var index = this._timeline.indexOf(this._toRemove[j]); - if (index !== -1) { - this._timeline.splice(index, 1); - } + return expr; + }; + Tone.TimeBase.prototype._parseUnary = function (lexer) { + var token, expr; + token = lexer.peek(); + var op = this._matchGroup(token, this._unaryExpressions); + if (op) { + token = lexer.next(); + expr = this._parseUnary(lexer); + return op.method.bind(this, expr); } - this._toRemove = []; - } - }; - Tone.Timeline.prototype.forEach = function (callback) { - this._iterate(callback); - return this; - }; - Tone.Timeline.prototype.forEachBefore = function (time, callback) { - var upperBound = this._search(time); - if (upperBound !== -1) { - this._iterate(callback, 0, upperBound); - } - return this; - }; - Tone.Timeline.prototype.forEachAfter = function (time, callback) { - var lowerBound = this._search(time); - this._iterate(callback, lowerBound + 1); - return this; - }; - Tone.Timeline.prototype.forEachFrom = function (time, callback) { - var lowerBound = this._search(time); - while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) { - lowerBound--; - } - this._iterate(callback, lowerBound + 1); - return this; - }; - Tone.Timeline.prototype.forEachAtTime = function (time, callback) { - var upperBound = this._search(time); - if (upperBound !== -1) { - this._iterate(function (event) { - if (event.time === time) { - callback(event); - } - }, 0, upperBound); - } - return this; - }; - Tone.Timeline.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._timeline = null; - this._toRemove = null; - }; - return Tone.Timeline; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_TimelineSignal; -Tone_signal_TimelineSignal = function (Tone) { - 'use strict'; - Tone.TimelineSignal = function () { - var options = this.optionsObject(arguments, [ - 'value', - 'units' - ], Tone.Signal.defaults); - this._events = new Tone.Timeline(10); - Tone.Signal.apply(this, options); - options.param = this._param; - Tone.Param.call(this, options); - this._initial = this._fromUnits(this._param.value); - }; - Tone.extend(Tone.TimelineSignal, Tone.Param); - Tone.TimelineSignal.Type = { - Linear: 'linear', - Exponential: 'exponential', - Target: 'target', - Curve: 'curve', - Set: 'set' - }; - Object.defineProperty(Tone.TimelineSignal.prototype, 'value', { - get: function () { - var now = this.now(); - var val = this.getValueAtTime(now); - return this._toUnits(val); - }, - set: function (value) { - var convertedVal = this._fromUnits(value); - this._initial = convertedVal; - this.cancelScheduledValues(); - this._param.value = convertedVal; - } - }); - Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) { - value = this._fromUnits(value); - startTime = this.toSeconds(startTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Set, - 'value': value, - 'time': startTime - }); - this._param.setValueAtTime(value, startTime); - return this; - }; - Tone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - endTime = this.toSeconds(endTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Linear, - 'value': value, - 'time': endTime - }); - this._param.linearRampToValueAtTime(value, endTime); - return this; - }; - Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) { - endTime = this.toSeconds(endTime); - var beforeEvent = this._searchBefore(endTime); - if (beforeEvent && beforeEvent.value === 0) { - this.setValueAtTime(this._minOutput, beforeEvent.time); - } - value = this._fromUnits(value); - var setValue = Math.max(value, this._minOutput); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Exponential, - 'value': setValue, - 'time': endTime - }); - if (value < this._minOutput) { - this._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime); - this.setValueAtTime(0, endTime); - } else { - this._param.exponentialRampToValueAtTime(value, endTime); - } - return this; - }; - Tone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - timeConstant = Math.max(this._minOutput, timeConstant); - startTime = this.toSeconds(startTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Target, - 'value': value, - 'time': startTime, - 'constant': timeConstant - }); - this._param.setTargetAtTime(value, startTime, timeConstant); - return this; - }; - Tone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) { - scaling = this.defaultArg(scaling, 1); - var floats = new Array(values.length); - for (var i = 0; i < floats.length; i++) { - floats[i] = this._fromUnits(values[i]) * scaling; - } - startTime = this.toSeconds(startTime); - duration = this.toSeconds(duration); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Curve, - 'value': floats, - 'time': startTime, - 'duration': duration - }); - this._param.setValueAtTime(floats[0], startTime); - for (var j = 1; j < floats.length; j++) { - var segmentTime = startTime + j / (floats.length - 1) * duration; - this._param.linearRampToValueAtTime(floats[j], segmentTime); - } - return this; - }; - Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) { - after = this.toSeconds(after); - this._events.cancel(after); - this._param.cancelScheduledValues(after); - return this; - }; - Tone.TimelineSignal.prototype.setRampPoint = function (time) { - time = this.toSeconds(time); - var val = this._toUnits(this.getValueAtTime(time)); - var before = this._searchBefore(time); - if (before && before.time === time) { - this.cancelScheduledValues(time + this.sampleTime); - } else if (before && before.type === Tone.TimelineSignal.Type.Curve && before.time + before.duration > time) { - this.cancelScheduledValues(time); - this.linearRampToValueAtTime(val, time); - } else { - var after = this._searchAfter(time); - if (after) { - this.cancelScheduledValues(time); - if (after.type === Tone.TimelineSignal.Type.Linear) { - this.linearRampToValueAtTime(val, time); - } else if (after.type === Tone.TimelineSignal.Type.Exponential) { - this.exponentialRampToValueAtTime(val, time); + return this._parsePrimary(lexer); + }; + Tone.TimeBase.prototype._parsePrimary = function (lexer) { + var token, expr; + token = lexer.peek(); + if (this.isUndef(token)) { + throw new SyntaxError("Tone.TimeBase: Unexpected end of expression"); + } + if (this._matchGroup(token, this._primaryExpressions)) { + token = lexer.next(); + var matching = token.value.match(token.regexp); + return token.method.bind(this, matching[1], matching[2], matching[3]); + } + if (token && token.value === "(") { + lexer.next(); + expr = this._parseBinary(lexer); + token = lexer.next(); + if (!(token && token.value === ")")) { + throw new SyntaxError("Expected )"); } + return expr; } - this.setValueAtTime(val, time); - } - return this; - }; - Tone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) { - this.setRampPoint(start); - this.linearRampToValueAtTime(value, finish); - return this; - }; - Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) { - this.setRampPoint(start); - this.exponentialRampToValueAtTime(value, finish); - return this; - }; - Tone.TimelineSignal.prototype._searchBefore = function (time) { - return this._events.get(time); - }; - Tone.TimelineSignal.prototype._searchAfter = function (time) { - return this._events.getAfter(time); - }; - Tone.TimelineSignal.prototype.getValueAtTime = function (time) { - time = this.toSeconds(time); - var after = this._searchAfter(time); - var before = this._searchBefore(time); - var value = this._initial; - if (before === null) { - value = this._initial; - } else if (before.type === Tone.TimelineSignal.Type.Target) { - var previous = this._events.getBefore(before.time); - var previouVal; - if (previous === null) { - previouVal = this._initial; + throw new SyntaxError( + "Tone.TimeBase: Cannot process token " + token.value + ); + }; + Tone.TimeBase.prototype._parseExprString = function (exprString) { + if (!this.isString(exprString)) { + exprString = exprString.toString(); + } + var lexer = this._tokenize(exprString); + var tree = this._parseBinary(lexer); + return tree; + }; + Tone.TimeBase.prototype._noOp = function () { + return 0; + }; + Tone.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }; + Tone.TimeBase.prototype._defaultUnits = "s"; + Tone.TimeBase.prototype._frequencyToUnits = function (freq) { + return 1 / freq; + }; + Tone.TimeBase.prototype._beatsToUnits = function (beats) { + return (60 / Tone.Transport.bpm.value) * beats; + }; + Tone.TimeBase.prototype._secondsToUnits = function (seconds) { + return seconds; + }; + Tone.TimeBase.prototype._ticksToUnits = function (ticks) { + return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ); + }; + Tone.TimeBase.prototype._timeSignature = function () { + return Tone.Transport.timeSignature; + }; + Tone.TimeBase.prototype._pushExpr = function (val, name, units) { + if (!(val instanceof Tone.TimeBase)) { + val = new this.constructor(val, units); + } + this._expr = this._binaryExpressions[name].method.bind( + this, + this._expr, + val._expr + ); + return this; + }; + Tone.TimeBase.prototype.add = function (val, units) { + return this._pushExpr(val, "+", units); + }; + Tone.TimeBase.prototype.sub = function (val, units) { + return this._pushExpr(val, "-", units); + }; + Tone.TimeBase.prototype.mult = function (val, units) { + return this._pushExpr(val, "*", units); + }; + Tone.TimeBase.prototype.div = function (val, units) { + return this._pushExpr(val, "/", units); + }; + Tone.TimeBase.prototype.valueOf = function () { + return this._expr(); + }; + Tone.TimeBase.prototype.dispose = function () { + this._expr = null; + }; + return Tone.TimeBase; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Time; + Tone_type_Time = (function (Tone) { + Tone.Time = function (val, units) { + if (this instanceof Tone.Time) { + this._plusNow = false; + Tone.TimeBase.call(this, val, units); } else { - previouVal = previous.value; - } - value = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time); - } else if (before.type === Tone.TimelineSignal.Type.Curve) { - value = this._curveInterpolate(before.time, before.value, before.duration, time); - } else if (after === null) { - value = before.value; - } else if (after.type === Tone.TimelineSignal.Type.Linear) { - value = this._linearInterpolate(before.time, before.value, after.time, after.value, time); - } else if (after.type === Tone.TimelineSignal.Type.Exponential) { - value = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time); - } else { - value = before.value; - } - return value; - }; - Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect; - Tone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) { - return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant); - }; - Tone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) { - return v0 + (v1 - v0) * ((t - t0) / (t1 - t0)); - }; - Tone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) { - v0 = Math.max(this._minOutput, v0); - return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0)); - }; - Tone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) { - var len = curve.length; - if (time >= start + duration) { - return curve[len - 1]; - } else if (time <= start) { - return curve[0]; - } else { - var progress = (time - start) / duration; - var lowerIndex = Math.floor((len - 1) * progress); - var upperIndex = Math.ceil((len - 1) * progress); - var lowerVal = curve[lowerIndex]; - var upperVal = curve[upperIndex]; - if (upperIndex === lowerIndex) { - return lowerVal; + return new Tone.Time(val, units); + } + }; + Tone.extend(Tone.Time, Tone.TimeBase); + Tone.Time.prototype._unaryExpressions = Object.create( + Tone.TimeBase.prototype._unaryExpressions + ); + Tone.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (rh) { + return Tone.Transport.nextSubdivision(rh()); + }, + }; + Tone.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (lh) { + this._plusNow = true; + return lh(); + }, + }; + Tone.Time.prototype.quantize = function (subdiv, percent) { + percent = this.defaultArg(percent, 1); + this._expr = function (expr, subdivision, percent) { + expr = expr(); + subdivision = subdivision.toSeconds(); + var multiple = Math.round(expr / subdivision); + var ideal = multiple * subdivision; + var diff = ideal - expr; + return expr + diff * percent; + }.bind(this, this._expr, new this.constructor(subdiv), percent); + return this; + }; + Tone.Time.prototype.addNow = function () { + this._plusNow = true; + return this; + }; + Tone.Time.prototype._defaultExpr = function () { + this._plusNow = true; + return this._noOp; + }; + Tone.Time.prototype.copy = function (time) { + Tone.TimeBase.prototype.copy.call(this, time); + this._plusNow = time._plusNow; + return this; + }; + Tone.Time.prototype.toNotation = function () { + var time = this.toSeconds(); + var testNotations = ["1m", "2n", "4n", "8n", "16n", "32n", "64n", "128n"]; + var retNotation = this._toNotationHelper(time, testNotations); + var testTripletNotations = [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ]; + var retTripletNotation = this._toNotationHelper( + time, + testTripletNotations + ); + if ( + retTripletNotation.split("+").length < retNotation.split("+").length + ) { + return retTripletNotation; } else { - return this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1)); + return retNotation; } - } - }; - Tone.TimelineSignal.prototype.dispose = function () { - Tone.Signal.prototype.dispose.call(this); - Tone.Param.prototype.dispose.call(this); - this._events.dispose(); - this._events = null; - }; - return Tone.TimelineSignal; -}(Tone_core_Tone, Tone_signal_Signal); -var envelope; -'use strict'; -envelope = function () { - var p5sound = master; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - var TimelineSignal = Tone_signal_TimelineSignal; - /** - *

Envelopes are pre-defined amplitude distribution over time. - * Typically, envelopes are used to control the output volume - * of an object, a series of fades referred to as Attack, Decay, - * Sustain and Release ( - * ADSR - * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can - * control an Oscillator's frequency like this: osc.freq(env).

- *

Use setRange to change the attack/release level. - * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

- *

Use the play method to play the entire envelope, - * the ramp method for a pingable trigger, - * or triggerAttack/ - * triggerRelease to trigger noteOn/noteOff.

- * - * @class p5.Envelope - * @constructor - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope = function (t1, l1, t2, l2, t3, l3) { - /** - * Time until envelope reaches attackLevel - * @property attackTime - */ - this.aTime = t1 || 0.1; - /** - * Level once attack is complete. - * @property attackLevel - */ - this.aLevel = l1 || 1; - /** - * Time until envelope reaches decayLevel. - * @property decayTime - */ - this.dTime = t2 || 0.5; - /** - * Level after decay. The envelope will sustain here until it is released. - * @property decayLevel - */ - this.dLevel = l2 || 0; - /** - * Duration of the release portion of the envelope. - * @property releaseTime - */ - this.rTime = t3 || 0; - /** - * Level at the end of the release. - * @property releaseLevel - */ - this.rLevel = l3 || 0; - this._rampHighPercentage = 0.98; - this._rampLowPercentage = 0.02; - this.output = p5sound.audiocontext.createGain(); - this.control = new TimelineSignal(); - this._init(); - // this makes sure the envelope starts at zero - this.control.connect(this.output); - // connect to the output - this.connection = null; - // store connection - //array of math operation signal chaining - this.mathOps = [this.control]; - //whether envelope should be linear or exponential curve - this.isExponential = false; - // oscillator or buffer source to clear on env complete - // to save resources if/when it is retriggered - this.sourceToClear = null; - // set to true if attack is set, then false on release - this.wasTriggered = false; - // add to the soundArray so we can dispose of the env later - p5sound.soundArray.push(this); - }; - // this init function just smooths the starting value to zero and gives a start point for the timeline - // - it was necessary to remove glitches at the beginning. - p5.Envelope.prototype._init = function () { - var now = p5sound.audiocontext.currentTime; - var t = now; - this.control.setTargetAtTime(0.00001, t, 0.001); - //also, compute the correct time constants - this._setRampAD(this.aTime, this.dTime); - }; - /** - * Reset the envelope with a series of time/value pairs. - * - * @method set - * @param {Number} attackTime Time (in seconds) before level - * reaches attackLevel - * @param {Number} attackLevel Typically an amplitude between - * 0.0 and 1.0 - * @param {Number} decayTime Time - * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, - * decayLevel = sustainLevel) - * @param {Number} releaseTime Release Time (in seconds) - * @param {Number} releaseLevel Amplitude - * @example - *
- * var t1 = 0.1; // attack time in seconds - * var l1 = 0.7; // attack level 0.0 to 1.0 - * var t2 = 0.3; // decay time in seconds - * var l2 = 0.1; // decay level 0.0 to 1.0 - * var t3 = 0.2; // sustain time in seconds - * var l3 = 0.5; // sustain level 0.0 to 1.0 - * // release level defaults to zero - * - * var env; - * var triOsc; - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(t1, l1, t2, l2, t3, l3); - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); // give the env control of the triOsc's amp - * triOsc.start(); - * } - * - * // mouseClick triggers envelope if over canvas - * function mouseClicked() { - * // is mouse over canvas? - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * env.play(triOsc); - * } - * } - *
- * - */ - p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { - this.aTime = t1; - this.aLevel = l1; - this.dTime = t2 || 0; - this.dLevel = l2 || 0; - this.rTime = t3 || 0; - this.rLevel = l3 || 0; - // set time constants for ramp - this._setRampAD(t1, t2); - }; - /** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { - this.aTime = aTime; - this.dTime = dTime || 0; - // lerp - this.sPercent = sPercent || 0; - this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0; - this.rTime = rTime || 0; - // also set time constants for ramp - this._setRampAD(aTime, dTime); - }; - /** - * Set max (attackLevel) and min (releaseLevel) of envelope. - * - * @method setRange - * @param {Number} aLevel attack level (defaults to 1) - * @param {Number} rLevel release level (defaults to 0) - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope.prototype.setRange = function (aLevel, rLevel) { - this.aLevel = aLevel || 1; - this.rLevel = rLevel || 0; - }; - // private (undocumented) method called when ADSR is set to set time constants for ramp - // - // Set the - // time constants for simple exponential ramps. - // The larger the time constant value, the slower the - // transition will be. - // - // method _setRampAD - // param {Number} attackTimeConstant attack time constant - // param {Number} decayTimeConstant decay time constant - // - p5.Envelope.prototype._setRampAD = function (t1, t2) { - this._rampAttackTime = this.checkExpInput(t1); - this._rampDecayTime = this.checkExpInput(t2); - var TCDenominator = 1; - /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) - TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage)); - this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1 / this._rampLowPercentage); - this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); - }; - // private method - p5.Envelope.prototype.setRampPercentages = function (p1, p2) { - //set the percentages that the simple exponential ramps go to - this._rampHighPercentage = this.checkExpInput(p1); - this._rampLowPercentage = this.checkExpInput(p2); - var TCDenominator = 1; - //now re-compute the time constants based on those percentages - /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) - TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage)); - this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1 / this._rampLowPercentage); - this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator); - }; - /** - * Assign a parameter to be controlled by this envelope. - * If a p5.Sound object is given, then the p5.Envelope will control its - * output gain. If multiple inputs are provided, the env will - * control all of them. - * - * @method setInput - * @param {Object} [...inputs] A p5.sound object or - * Web Audio Param. - */ - p5.Envelope.prototype.setInput = function () { - for (var i = 0; i < arguments.length; i++) { - this.connect(arguments[i]); - } - }; - /** - * Set whether the envelope ramp is linear (default) or exponential. - * Exponential ramps can be useful because we perceive amplitude - * and frequency logarithmically. - * - * @method setExp - * @param {Boolean} isExp true is exponential, false is linear - */ - p5.Envelope.prototype.setExp = function (isExp) { - this.isExponential = isExp; - }; - //helper method to protect against zero values being sent to exponential functions - p5.Envelope.prototype.checkExpInput = function (value) { - if (value <= 0) { - value = 1e-8; - } - return value; - }; - /** - * Play tells the envelope to start acting on a given input. - * If the input is a p5.sound object (i.e. AudioIn, Oscillator, - * SoundFile), then Envelope will control its output volume. - * Envelopes can also be used to control any - * Web Audio Audio Param. - * - * @method play - * @param {Object} unit A p5.sound object or - * Web Audio Param. - * @param {Number} [startTime] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * // trigger env on triOsc, 0 seconds from now - * // After decay, sustain for 0.2 seconds before release - * env.play(triOsc, 0, 0.2); - * } - *
- */ - p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) { - var tFromNow = secondsFromNow || 0; - var susTime = susTime || 0; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + }; + Tone.Time.prototype._toNotationHelper = function (units, testNotations) { + var threshold = this._notationToUnits( + testNotations[testNotations.length - 1] + ); + var retNotation = ""; + for (var i = 0; i < testNotations.length; i++) { + var notationTime = this._notationToUnits(testNotations[i]); + var multiple = units / notationTime; + var floatingPointError = 0.000001; + if (1 - (multiple % 1) < floatingPointError) { + multiple += floatingPointError; + } + multiple = Math.floor(multiple); + if (multiple > 0) { + if (multiple === 1) { + retNotation += testNotations[i]; + } else { + retNotation += multiple.toString() + "*" + testNotations[i]; + } + units -= multiple * notationTime; + if (units < threshold) { + break; + } else { + retNotation += " + "; + } + } } - } - this.triggerAttack(unit, tFromNow); - this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime); - }; - /** - * Trigger the Attack, and Decay portion of the Envelope. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. Input can be - * any p5.sound object, or a - * Web Audio Param. - * - * @method triggerAttack - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow time from now (in seconds) - * @example - *
- * - * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.3; - * var susPercent = 0.4; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * background(200); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(envAttack); - * } - * - * function envAttack() { - * console.log('trigger attack'); - * env.triggerAttack(); - * - * background(0,255,0); - * text('attack!', width/2, height/2); - * } - * - * function mouseReleased() { - * env.triggerRelease(); - * - * background(200); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - this.lastAttack = t; - this.wasTriggered = true; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + if (retNotation === "") { + retNotation = "0"; } - } - // get and set value (with linear ramp) to anchor automation - var valToSet = this.control.getValueAtTime(t); - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t); - } else { - this.control.linearRampToValueAtTime(valToSet, t); - } - // after each ramp completes, cancel scheduled values - // (so they can be overridden in case env has been re-triggered) - // then, set current value (with linearRamp to avoid click) - // then, schedule the next automation... - // attack - t += this.aTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.aLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - // decay to decay level (if using ADSR, then decay level == sustain level) - t += this.dTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.dLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - }; - /** - * Trigger the Release of the Envelope. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @method triggerRelease - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow time to trigger the release - * @example - *
- * - * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.3; - * var susPercent = 0.4; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * background(200); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(envAttack); - * } - * - * function envAttack() { - * console.log('trigger attack'); - * env.triggerAttack(); - * - * background(0,255,0); - * text('attack!', width/2, height/2); - * } - * - * function mouseReleased() { - * env.triggerRelease(); - * - * background(200); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) { - // only trigger a release if an attack was triggered - if (!this.wasTriggered) { - // this currently causes a bit of trouble: - // if a later release has been scheduled (via the play function) - // a new earlier release won't interrupt it, because - // this.wasTriggered has already been set to false. - // If we want new earlier releases to override, then we need to - // keep track of the last release time, and if the new release time is - // earlier, then use it. - return; - } - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + return retNotation; + }; + Tone.Time.prototype._notationToUnits = function (notation) { + var primaryExprs = this._primaryExpressions; + var notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m]; + for (var i = 0; i < notationExprs.length; i++) { + var expr = notationExprs[i]; + var match = notation.match(expr.regexp); + if (match) { + return expr.method.call(this, match[1]); + } } - } - // get and set value (with linear or exponential ramp) to anchor automation - var valToSet = this.control.getValueAtTime(t); - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t); - } else { - this.control.linearRampToValueAtTime(valToSet, t); - } - // release - t += this.rTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.rLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - this.wasTriggered = false; - }; - /** - * Exponentially ramp to a value using the first two - * values from setADSR(attackTime, decayTime) - * as - * time constants for simple exponential ramps. - * If the value is higher than current value, it uses attackTime, - * while a decrease uses decayTime. - * - * @method ramp - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow When to trigger the ramp - * @param {Number} v Target value - * @param {Number} [v2] Second target value (optional) - * @example - *
- * var env, osc, amp, cnv; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var attackLevel = 1; - * var decayLevel = 0; - * - * function setup() { - * cnv = createCanvas(100, 100); - * fill(0,255,0); - * noStroke(); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime); - * - * osc = new p5.Oscillator(); - * osc.amp(env); - * osc.start(); - * - * amp = new p5.Amplitude(); - * - * cnv.mousePressed(triggerRamp); - * } - * - * function triggerRamp() { - * env.ramp(osc, 0, attackLevel, decayLevel); - * } - * - * function draw() { - * background(20,20,20); - * text('click me', 10, 20); - * var h = map(amp.getLevel(), 0, 0.4, 0, height);; - * - * rect(0, height, width, -h); - * } - *
- */ - p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - var destination1 = this.checkExpInput(v1); - var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined; - // connect env to unit if not already connected - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + }; + Tone.Time.prototype.toBarsBeatsSixteenths = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.toSeconds() / quarterTime; + var measures = Math.floor(quarters / this._timeSignature()); + var sixteenths = (quarters % 1) * 4; + quarters = Math.floor(quarters) % this._timeSignature(); + sixteenths = sixteenths.toString(); + if (sixteenths.length > 3) { + sixteenths = parseFloat(sixteenths).toFixed(3); + } + var progress = [measures, quarters, sixteenths]; + return progress.join(":"); + }; + Tone.Time.prototype.toTicks = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.valueOf() / quarterTime; + return Math.floor(quarters * Tone.Transport.PPQ); + }; + Tone.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }; + Tone.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }; + Tone.Time.prototype.toSeconds = function () { + return this.valueOf(); + }; + Tone.Time.prototype.toMilliseconds = function () { + return this.toSeconds() * 1000; + }; + Tone.Time.prototype.valueOf = function () { + var val = this._expr(); + return val + (this._plusNow ? this.now() : 0); + }; + return Tone.Time; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Frequency; + Tone_type_Frequency = (function (Tone) { + Tone.Frequency = function (val, units) { + if (this instanceof Tone.Frequency) { + Tone.TimeBase.call(this, val, units); + } else { + return new Tone.Frequency(val, units); } - } - //get current value - var currentVal = this.checkExpInput(this.control.getValueAtTime(t)); - // this.control.cancelScheduledValues(t); - //if it's going up - if (destination1 > currentVal) { - this.control.setTargetAtTime(destination1, t, this._rampAttackTC); - t += this._rampAttackTime; - } else if (destination1 < currentVal) { - this.control.setTargetAtTime(destination1, t, this._rampDecayTC); - t += this._rampDecayTime; - } - // Now the second part of envelope begins - if (destination2 === undefined) - return; - //if it's going up - if (destination2 > destination1) { - this.control.setTargetAtTime(destination2, t, this._rampAttackTC); - } else if (destination2 < destination1) { - this.control.setTargetAtTime(destination2, t, this._rampDecayTC); - } - }; - p5.Envelope.prototype.connect = function (unit) { - this.connection = unit; - // assume we're talking about output gain - // unless given a different audio param - if (unit instanceof p5.Oscillator || unit instanceof p5.SoundFile || unit instanceof p5.AudioIn || unit instanceof p5.Reverb || unit instanceof p5.Noise || unit instanceof p5.Filter || unit instanceof p5.Delay) { - unit = unit.output.gain; - } - if (unit instanceof AudioParam) { - //set the initial value - unit.setValueAtTime(0, p5sound.audiocontext.currentTime); - } - if (unit instanceof p5.Signal) { - unit.setValue(0); - } - this.output.connect(unit); - }; - p5.Envelope.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - // Signal Math - /** - * Add a value to the p5.Oscillator's output amplitude, - * and return the oscillator. Calling this method - * again will override the initial add() with new values. - * - * @method add - * @param {Number} number Constant number to add - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.add = function (num) { - var add = new Add(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, add, thisChain, nextChain, Add); - }; - /** - * Multiply the p5.Envelope's output amplitude - * by a fixed value. Calling this method - * again will override the initial mult() with new values. - * - * @method mult - * @param {Number} number Constant number to multiply - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.mult = function (num) { - var mult = new Mult(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult); - }; - /** - * Scale this envelope's amplitude values to a given - * range, and return the envelope. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { - var scale = new Scale(inMin, inMax, outMin, outMax); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale); - }; - // get rid of the oscillator - p5.Envelope.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.disconnect(); - if (this.control) { - this.control.dispose(); - this.control = null; - } - for (var i = 1; i < this.mathOps.length; i++) { - this.mathOps[i].dispose(); - } - }; - // Different name for backwards compatibility, replicates p5.Envelope class - p5.Env = function (t1, l1, t2, l2, t3, l3) { - console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' + 'Please use the new p5.Envelope instead.'); - p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); - }; - p5.Env.prototype = Object.create(p5.Envelope.prototype); -}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale, Tone_signal_TimelineSignal); -var pulse; -'use strict'; -pulse = function () { - var p5sound = master; - /** - * Creates a Pulse object, an oscillator that implements - * Pulse Width Modulation. - * The pulse is created with two oscillators. - * Accepts a parameter for frequency, and to set the - * width between the pulses. See - * p5.Oscillator for a full list of methods. - * - * @class p5.Pulse - * @extends p5.Oscillator - * @constructor - * @param {Number} [freq] Frequency in oscillations per second (Hz) - * @param {Number} [w] Width between the pulses (0 to 1.0, - * defaults to 0) - * @example - *
- * var pulse; - * function setup() { - * background(0); - * - * // Create and start the pulse wave oscillator - * pulse = new p5.Pulse(); - * pulse.amp(0.5); - * pulse.freq(220); - * pulse.start(); - * } - * - * function draw() { - * var w = map(mouseX, 0, width, 0, 1); - * w = constrain(w, 0, 1); - * pulse.width(w) - * } - *
- */ - p5.Pulse = function (freq, w) { - p5.Oscillator.call(this, freq, 'sawtooth'); - // width of PWM, should be betw 0 to 1.0 - this.w = w || 0; - // create a second oscillator with inverse frequency - this.osc2 = new p5.SawOsc(freq); - // create a delay node - this.dNode = p5sound.audiocontext.createDelay(); - // dc offset - this.dcOffset = createDCOffset(); - this.dcGain = p5sound.audiocontext.createGain(); - this.dcOffset.connect(this.dcGain); - this.dcGain.connect(this.output); - // set delay time based on PWM width - this.f = freq || 440; - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - // disconnect osc2 and connect it to delay, which is connected to output - this.osc2.disconnect(); - this.osc2.panner.disconnect(); - this.osc2.amp(-1); - // inverted amplitude - this.osc2.output.connect(this.dNode); - this.dNode.connect(this.output); - this.output.gain.value = 1; - this.output.connect(this.panner); - }; - p5.Pulse.prototype = Object.create(p5.Oscillator.prototype); - /** - * Set the width of a Pulse object (an oscillator that implements - * Pulse Width Modulation). - * - * @method width - * @param {Number} [width] Width between the pulses (0 to 1.0, - * defaults to 0) - */ - p5.Pulse.prototype.width = function (w) { - if (typeof w === 'number') { - if (w <= 1 && w >= 0) { - this.w = w; - // set delay time based on PWM width - // var mW = map(this.w, 0, 1.0, 0, 1/this.f); - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; + }; + Tone.extend(Tone.Frequency, Tone.TimeBase); + Tone.Frequency.prototype._primaryExpressions = Object.create( + Tone.TimeBase.prototype._primaryExpressions + ); + Tone.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (value) { + return this.midiToFrequency(value); + }, + }; + Tone.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (pitch, octave) { + var index = noteToScaleIndex[pitch.toLowerCase()]; + var noteNumber = index + (parseInt(octave) + 1) * 12; + return this.midiToFrequency(noteNumber); + }, + }; + Tone.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (m, q, s) { + var total = 1; + if (m && m !== "0") { + total *= this._beatsToUnits(this._timeSignature() * parseFloat(m)); + } + if (q && q !== "0") { + total *= this._beatsToUnits(parseFloat(q)); + } + if (s && s !== "0") { + total *= this._beatsToUnits(parseFloat(s) / 4); + } + return total; + }, + }; + Tone.Frequency.prototype.transpose = function (interval) { + this._expr = function (expr, interval) { + var val = expr(); + return val * this.intervalToFrequencyRatio(interval); + }.bind(this, this._expr, interval); + return this; + }; + Tone.Frequency.prototype.harmonize = function (intervals) { + this._expr = function (expr, intervals) { + var val = expr(); + var ret = []; + for (var i = 0; i < intervals.length; i++) { + ret[i] = val * this.intervalToFrequencyRatio(intervals[i]); + } + return ret; + }.bind(this, this._expr, intervals); + return this; + }; + Tone.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }; + Tone.Frequency.prototype.toNote = function () { + var freq = this.valueOf(); + var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2; + var noteNumber = Math.round(12 * log) + 57; + var octave = Math.floor(noteNumber / 12); + if (octave < 0) { + noteNumber += -12 * octave; + } + var noteName = scaleIndexToNote[noteNumber % 12]; + return noteName + octave.toString(); + }; + Tone.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }; + Tone.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }; + Tone.Frequency.prototype.toTicks = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.valueOf() / quarterTime; + return Math.floor(quarters * Tone.Transport.PPQ); + }; + Tone.Frequency.prototype._frequencyToUnits = function (freq) { + return freq; + }; + Tone.Frequency.prototype._ticksToUnits = function (ticks) { + return ( + 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ)) + ); + }; + Tone.Frequency.prototype._beatsToUnits = function (beats) { + return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats); + }; + Tone.Frequency.prototype._secondsToUnits = function (seconds) { + return 1 / seconds; + }; + Tone.Frequency.prototype._defaultUnits = "hz"; + var noteToScaleIndex = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }; + var scaleIndexToNote = [ + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B", + ]; + Tone.Frequency.A4 = 440; + Tone.Frequency.prototype.midiToFrequency = function (midi) { + return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12); + }; + Tone.Frequency.prototype.frequencyToMidi = function (frequency) { + return 69 + (12 * Math.log(frequency / Tone.Frequency.A4)) / Math.LN2; + }; + return Tone.Frequency; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_TransportTime; + Tone_type_TransportTime = (function (Tone) { + Tone.TransportTime = function (val, units) { + if (this instanceof Tone.TransportTime) { + Tone.Time.call(this, val, units); + } else { + return new Tone.TransportTime(val, units); } - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - } else { - w.connect(this.dNode.delayTime); - var sig = new p5.SignalAdd(-0.5); - sig.setInput(w); - sig = sig.mult(-1); - sig = sig.mult(1.7); - sig.connect(this.dcGain.gain); - } - }; - p5.Pulse.prototype.start = function (f, time) { - var now = p5sound.audiocontext.currentTime; - var t = time || 0; - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.oscillator.frequency.setValueAtTime(freq, now); - this.oscillator.type = type; - this.oscillator.connect(this.output); - this.oscillator.start(t + now); - // set up osc2 - this.osc2.oscillator = p5sound.audiocontext.createOscillator(); - this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); - this.osc2.oscillator.type = type; - this.osc2.oscillator.connect(this.osc2.output); - this.osc2.start(t + now); - this.freqNode = [ - this.oscillator.frequency, - this.osc2.oscillator.frequency - ]; - // start dcOffset, too - this.dcOffset = createDCOffset(); - this.dcOffset.connect(this.dcGain); - this.dcOffset.start(t + now); - // if LFO connections depend on these oscillators - if (this.mods !== undefined && this.mods.frequency !== undefined) { - this.mods.frequency.connect(this.freqNode[0]); - this.mods.frequency.connect(this.freqNode[1]); + }; + Tone.extend(Tone.TransportTime, Tone.Time); + Tone.TransportTime.prototype._unaryExpressions = Object.create( + Tone.Time.prototype._unaryExpressions + ); + Tone.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (rh) { + var subdivision = this._secondsToTicks(rh()); + var multiple = Math.ceil(Tone.Transport.ticks / subdivision); + return this._ticksToUnits(multiple * subdivision); + }, + }; + Tone.TransportTime.prototype._secondsToTicks = function (seconds) { + var quarterTime = this._beatsToUnits(1); + var quarters = seconds / quarterTime; + return Math.round(quarters * Tone.Transport.PPQ); + }; + Tone.TransportTime.prototype.valueOf = function () { + var val = this._secondsToTicks(this._expr()); + return val + (this._plusNow ? Tone.Transport.ticks : 0); + }; + Tone.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }; + Tone.TransportTime.prototype.toSeconds = function () { + var val = this._expr(); + return val + (this._plusNow ? Tone.Transport.seconds : 0); + }; + Tone.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }; + return Tone.TransportTime; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Type; + Tone_type_Type = (function (Tone) { + Tone.Type = { + Default: "number", + Time: "time", + Frequency: "frequency", + TransportTime: "transportTime", + Ticks: "ticks", + NormalRange: "normalRange", + AudioRange: "audioRange", + Decibels: "db", + Interval: "interval", + BPM: "bpm", + Positive: "positive", + Cents: "cents", + Degrees: "degrees", + MIDI: "midi", + BarsBeatsSixteenths: "barsBeatsSixteenths", + Samples: "samples", + Hertz: "hertz", + Note: "note", + Milliseconds: "milliseconds", + Seconds: "seconds", + Notation: "notation", + }; + Tone.prototype.toSeconds = function (time) { + if (this.isNumber(time)) { + return time; + } else if (this.isUndef(time)) { + return this.now(); + } else if (this.isString(time)) { + return new Tone.Time(time).toSeconds(); + } else if (time instanceof Tone.TimeBase) { + return time.toSeconds(); } - this.started = true; - this.osc2.started = true; - } - }; - p5.Pulse.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = p5sound.audiocontext.currentTime; - this.oscillator.stop(t + now); - if (this.osc2.oscillator) { - this.osc2.oscillator.stop(t + now); + }; + Tone.prototype.toFrequency = function (freq) { + if (this.isNumber(freq)) { + return freq; + } else if (this.isString(freq) || this.isUndef(freq)) { + return new Tone.Frequency(freq).valueOf(); + } else if (freq instanceof Tone.TimeBase) { + return freq.toFrequency(); } - this.dcOffset.stop(t + now); - this.started = false; - this.osc2.started = false; - } - }; - p5.Pulse.prototype.freq = function (val, rampTime, tFromNow) { - if (typeof val === 'number') { - this.f = val; - var now = p5sound.audiocontext.currentTime; - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var currentFreq = this.oscillator.frequency.value; - this.oscillator.frequency.cancelScheduledValues(now); - this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - this.osc2.oscillator.frequency.cancelScheduledValues(now); - this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.osc2.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - if (this.freqMod) { - this.freqMod.output.disconnect(); - this.freqMod = null; - } - } else if (val.output) { - val.output.disconnect(); - val.output.connect(this.oscillator.frequency); - val.output.connect(this.osc2.oscillator.frequency); - this.freqMod = val; - } - }; - // inspiration: http://webaudiodemos.appspot.com/oscilloscope/ - function createDCOffset() { - var ac = p5sound.audiocontext; - var buffer = ac.createBuffer(1, 2048, ac.sampleRate); - var data = buffer.getChannelData(0); - for (var i = 0; i < 2048; i++) - data[i] = 1; - var bufferSource = ac.createBufferSource(); - bufferSource.buffer = buffer; - bufferSource.loop = true; - return bufferSource; - } -}(master, oscillator); -var noise; -'use strict'; -noise = function () { - var p5sound = master; - /** - * Noise is a type of oscillator that generates a buffer with random values. - * - * @class p5.Noise - * @extends p5.Oscillator - * @constructor - * @param {String} type Type of noise can be 'white' (default), - * 'brown' or 'pink'. - */ - p5.Noise = function (type) { - var assignType; - p5.Oscillator.call(this); - delete this.f; - delete this.freq; - delete this.oscillator; - if (type === 'brown') { - assignType = _brownNoise; - } else if (type === 'pink') { - assignType = _pinkNoise; - } else { - assignType = _whiteNoise; - } - this.buffer = assignType; - }; - p5.Noise.prototype = Object.create(p5.Oscillator.prototype); - // generate noise buffers - var _whiteNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var whiteBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = whiteBuffer.getChannelData(0); - for (var i = 0; i < bufferSize; i++) { - noiseData[i] = Math.random() * 2 - 1; - } - whiteBuffer.type = 'white'; - return whiteBuffer; - }(); - var _pinkNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var pinkBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = pinkBuffer.getChannelData(0); - var b0, b1, b2, b3, b4, b5, b6; - b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0; - for (var i = 0; i < bufferSize; i++) { - var white = Math.random() * 2 - 1; - b0 = 0.99886 * b0 + white * 0.0555179; - b1 = 0.99332 * b1 + white * 0.0750759; - b2 = 0.969 * b2 + white * 0.153852; - b3 = 0.8665 * b3 + white * 0.3104856; - b4 = 0.55 * b4 + white * 0.5329522; - b5 = -0.7616 * b5 - white * 0.016898; - noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362; - noiseData[i] *= 0.11; - // (roughly) compensate for gain - b6 = white * 0.115926; - } - pinkBuffer.type = 'pink'; - return pinkBuffer; - }(); - var _brownNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var brownBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = brownBuffer.getChannelData(0); - var lastOut = 0; - for (var i = 0; i < bufferSize; i++) { - var white = Math.random() * 2 - 1; - noiseData[i] = (lastOut + 0.02 * white) / 1.02; - lastOut = noiseData[i]; - noiseData[i] *= 3.5; - } - brownBuffer.type = 'brown'; - return brownBuffer; - }(); - /** - * Set type of noise to 'white', 'pink' or 'brown'. - * White is the default. - * - * @method setType - * @param {String} [type] 'white', 'pink' or 'brown' - */ - p5.Noise.prototype.setType = function (type) { - switch (type) { - case 'white': - this.buffer = _whiteNoise; - break; - case 'pink': - this.buffer = _pinkNoise; - break; - case 'brown': - this.buffer = _brownNoise; - break; - default: - this.buffer = _whiteNoise; - } - if (this.started) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - this.start(now + 0.01); - } - }; - p5.Noise.prototype.getType = function () { - return this.buffer.type; - }; - p5.Noise.prototype.start = function () { - if (this.started) { - this.stop(); - } - this.noise = p5sound.audiocontext.createBufferSource(); - this.noise.buffer = this.buffer; - this.noise.loop = true; - this.noise.connect(this.output); - var now = p5sound.audiocontext.currentTime; - this.noise.start(now); - this.started = true; - }; - p5.Noise.prototype.stop = function () { - var now = p5sound.audiocontext.currentTime; - if (this.noise) { - this.noise.stop(now); - this.started = false; - } - }; - p5.Noise.prototype.dispose = function () { - var now = p5sound.audiocontext.currentTime; - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.noise) { - this.noise.disconnect(); - this.stop(now); - } - if (this.output) { - this.output.disconnect(); - } - if (this.panner) { - this.panner.disconnect(); - } - this.output = null; - this.panner = null; - this.buffer = null; - this.noise = null; - }; -}(master); -var audioin; -'use strict'; -audioin = function () { - var p5sound = master; - // an array of input sources - p5sound.inputSources = []; - /** - *

Get audio from an input, i.e. your computer's microphone.

- * - *

Turn the mic on/off with the start() and stop() methods. When the mic - * is on, its volume can be measured with getLevel or by connecting an - * FFT object.

- * - *

If you want to hear the AudioIn, use the .connect() method. - * AudioIn does not connect to p5.sound output by default to prevent - * feedback.

- * - *

Note: This uses the getUserMedia/ - * Stream API, which is not supported by certain browsers. Access in Chrome browser - * is limited to localhost and https, but access over http may be limited.

- * - * @class p5.AudioIn - * @constructor - * @param {Function} [errorCallback] A function to call if there is an error - * accessing the AudioIn. For example, - * Safari and iOS devices do not - * currently allow microphone access. - * @example - *
- * var mic; - * function setup(){ - * mic = new p5.AudioIn() - * mic.start(); - * } - * function draw(){ - * background(0); - * micLevel = mic.getLevel(); - * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10); - * } - *
- */ - p5.AudioIn = function (errorCallback) { - // set up audio input - /** - * @property {GainNode} input - */ - this.input = p5sound.audiocontext.createGain(); - /** - * @property {GainNode} output - */ - this.output = p5sound.audiocontext.createGain(); - /** - * @property {MediaStream|null} stream - */ - this.stream = null; - /** - * @property {MediaStreamAudioSourceNode|null} mediaStream - */ - this.mediaStream = null; - /** - * @property {Number|null} currentSource - */ - this.currentSource = null; - /** - * Client must allow browser to access their microphone / audioin source. - * Default: false. Will become true when the client enables acces. - * - * @property {Boolean} enabled - */ - this.enabled = false; - /** - * Input amplitude, connect to it by default but not to master out - * - * @property {p5.Amplitude} amplitude - */ - this.amplitude = new p5.Amplitude(); - this.output.connect(this.amplitude.input); - if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { - errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices'); - } - // add to soundArray so we can dispose on close - p5sound.soundArray.push(this); - }; - /** - * Start processing audio input. This enables the use of other - * AudioIn methods like getLevel(). Note that by default, AudioIn - * is not connected to p5.sound's output. So you won't hear - * anything unless you use the connect() method.
- * - * Certain browsers limit access to the user's microphone. For example, - * Chrome only allows access from localhost and over https. For this reason, - * you may want to include an errorCallback—a function that is called in case - * the browser won't provide mic access. - * - * @method start - * @param {Function} [successCallback] Name of a function to call on - * success. - * @param {Function} [errorCallback] Name of a function to call if - * there was an error. For example, - * some browsers do not support - * getUserMedia. - */ - p5.AudioIn.prototype.start = function (successCallback, errorCallback) { - var self = this; - if (this.stream) { - this.stop(); - } - // set the audio source - var audioSource = p5sound.inputSources[self.currentSource]; - var constraints = { - audio: { - sampleRate: p5sound.audiocontext.sampleRate, - echoCancellation: false + }; + Tone.prototype.toTicks = function (time) { + if (this.isNumber(time) || this.isString(time)) { + return new Tone.TransportTime(time).toTicks(); + } else if (this.isUndef(time)) { + return Tone.Transport.ticks; + } else if (time instanceof Tone.TimeBase) { + return time.toTicks(); } }; - // if developers determine which source to use - if (p5sound.inputSources[this.currentSource]) { - constraints.audio.deviceId = audioSource.deviceId; - } - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - self.stream = stream; - self.enabled = true; - // Wrap a MediaStreamSourceNode around the live input - self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream); - self.mediaStream.connect(self.output); - // only send to the Amplitude reader, so we can see it but not hear it. - self.amplitude.setInput(self.output); - if (successCallback) - successCallback(); - }).catch(function (err) { - if (errorCallback) - errorCallback(err); - else - console.error(err); - }); - }; - /** - * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). - * If re-starting, the user may be prompted for permission access. - * - * @method stop - */ - p5.AudioIn.prototype.stop = function () { - if (this.stream) { - this.stream.getTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.disconnect(); - delete this.mediaStream; - delete this.stream; - } - }; - /** - * Connect to an audio unit. If no parameter is provided, will - * connect to the master output (i.e. your speakers).
- * - * @method connect - * @param {Object} [unit] An object that accepts audio input, - * such as an FFT - */ - p5.AudioIn.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else if (unit.hasOwnProperty('analyser')) { - this.output.connect(unit.analyser); - } else { - this.output.connect(unit); + return Tone; + })( + Tone_core_Tone, + Tone_type_Time, + Tone_type_Frequency, + Tone_type_TransportTime + ); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Param; + Tone_core_Param = (function (Tone) { + "use strict"; + Tone.Param = function () { + var options = this.optionsObject( + arguments, + ["param", "units", "convert"], + Tone.Param.defaults + ); + this._param = this.input = options.param; + this.units = options.units; + this.convert = options.convert; + this.overridden = false; + this._lfo = null; + if (this.isObject(options.lfo)) { + this.value = options.lfo; + } else if (!this.isUndef(options.value)) { + this.value = options.value; } - } else { - this.output.connect(p5sound.input); - } - }; - /** - * Disconnect the AudioIn from all audio units. For example, if - * connect() had been called, disconnect() will stop sending - * signal to your speakers.
- * - * @method disconnect - */ - p5.AudioIn.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - // stay connected to amplitude even if not outputting to p5 - this.output.connect(this.amplitude.input); - } - }; - /** - * Read the Amplitude (volume level) of an AudioIn. The AudioIn - * class contains its own instance of the Amplitude class to help - * make it easy to get a microphone's volume level. Accepts an - * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must - * .start() before using .getLevel().
- * - * @method getLevel - * @param {Number} [smoothing] Smoothing is 0.0 by default. - * Smooths values based on previous values. - * @return {Number} Volume level (between 0.0 and 1.0) - */ - p5.AudioIn.prototype.getLevel = function (smoothing) { - if (smoothing) { - this.amplitude.smoothing = smoothing; - } - return this.amplitude.getLevel(); - }; - /** - * Set amplitude (volume) of a mic input between 0 and 1.0.
- * - * @method amp - * @param {Number} vol between 0 and 1.0 - * @param {Number} [time] ramp time (optional) - */ - p5.AudioIn.prototype.amp = function (vol, t) { - if (t) { - var rampTime = t || 0; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime); - this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime); - this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime); - } else { - this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime); - this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime); - } - }; - /** - * Returns a list of available input sources. This is a wrapper - * for and it returns a Promise. - * - * @method getSources - * @param {Function} [successCallback] This callback function handles the sources when they - * have been enumerated. The callback function - * receives the deviceList array as its only argument - * @param {Function} [errorCallback] This optional callback receives the error - * message as its argument. - * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar - * to the enumerateDevices() method - * @example - *
- * var audiograb; - * - * function setup(){ - * //new audioIn - * audioGrab = new p5.AudioIn(); - * - * audioGrab.getSources(function(deviceList) { - * //print out the array of available sources - * console.log(deviceList); - * //set the source to the first item in the deviceList array - * audioGrab.setSource(0); - * }); - * } - *
- */ - p5.AudioIn.prototype.getSources = function (onSuccess, onError) { - return new Promise(function (resolve, reject) { - window.navigator.mediaDevices.enumerateDevices().then(function (devices) { - p5sound.inputSources = devices.filter(function (device) { - return device.kind === 'audioinput'; - }); - resolve(p5sound.inputSources); - if (onSuccess) { - onSuccess(p5sound.inputSources); - } - }).catch(function (error) { - reject(error); - if (onError) { - onError(error); + }; + Tone.extend(Tone.Param); + Tone.Param.defaults = { + units: Tone.Type.Default, + convert: true, + param: undefined, + }; + Object.defineProperty(Tone.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (value) { + if (this.isObject(value)) { + if (this.isUndef(Tone.LFO)) { + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + } + if (this._lfo) { + this._lfo.dispose(); + } + this._lfo = new Tone.LFO(value).start(); + this._lfo.connect(this.input); } else { - console.error('This browser does not support MediaStreamTrack.getSources()'); + var convertedVal = this._fromUnits(value); + this._param.cancelScheduledValues(0); + this._param.value = convertedVal; } - }); + }, }); - }; - /** - * Set the input source. Accepts a number representing a - * position in the array returned by getSources(). - * This is only available in browsers that support - *
navigator.mediaDevices.enumerateDevices().
- * - * @method setSource - * @param {number} num position of input source in the array - */ - p5.AudioIn.prototype.setSource = function (num) { - if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) { - // set the current source - this.currentSource = num; - console.log('set source to ', p5sound.inputSources[this.currentSource]); - } else { - console.log('unable to set input source'); - } - // restart stream if currently active - if (this.stream && this.stream.active) { - this.start(); - } - }; - // private method - p5.AudioIn.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.stop(); - if (this.output) { - this.output.disconnect(); - } - if (this.amplitude) { - this.amplitude.disconnect(); - } - delete this.amplitude; - delete this.output; - }; -}(master); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Negate; -Tone_signal_Negate = function (Tone) { - 'use strict'; - Tone.Negate = function () { - this._multiply = this.input = this.output = new Tone.Multiply(-1); - }; - Tone.extend(Tone.Negate, Tone.SignalBase); - Tone.Negate.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._multiply.dispose(); - this._multiply = null; - return this; - }; - return Tone.Negate; -}(Tone_core_Tone, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Subtract; -Tone_signal_Subtract = function (Tone) { - 'use strict'; - Tone.Subtract = function (value) { - this.createInsOuts(2, 0); - this._sum = this.input[0] = this.output = new Tone.Gain(); - this._neg = new Tone.Negate(); - this._param = this.input[1] = new Tone.Signal(value); - this._param.chain(this._neg, this._sum); - }; - Tone.extend(Tone.Subtract, Tone.Signal); - Tone.Subtract.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._neg.dispose(); - this._neg = null; - this._sum.disconnect(); - this._sum = null; - this._param.dispose(); - this._param = null; - return this; - }; - return Tone.Subtract; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Negate, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_GreaterThanZero; -Tone_signal_GreaterThanZero = function (Tone) { - 'use strict'; - Tone.GreaterThanZero = function () { - this._thresh = this.output = new Tone.WaveShaper(function (val) { - if (val <= 0) { - return 0; + Tone.Param.prototype._fromUnits = function (val) { + if (this.convert || this.isUndef(this.convert)) { + switch (this.units) { + case Tone.Type.Time: + return this.toSeconds(val); + case Tone.Type.Frequency: + return this.toFrequency(val); + case Tone.Type.Decibels: + return this.dbToGain(val); + case Tone.Type.NormalRange: + return Math.min(Math.max(val, 0), 1); + case Tone.Type.AudioRange: + return Math.min(Math.max(val, -1), 1); + case Tone.Type.Positive: + return Math.max(val, 0); + default: + return val; + } } else { - return 1; - } - }, 127); - this._scale = this.input = new Tone.Multiply(10000); - this._scale.connect(this._thresh); - }; - Tone.extend(Tone.GreaterThanZero, Tone.SignalBase); - Tone.GreaterThanZero.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._scale.dispose(); - this._scale = null; - this._thresh.dispose(); - this._thresh = null; - return this; - }; - return Tone.GreaterThanZero; -}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_GreaterThan; -Tone_signal_GreaterThan = function (Tone) { - 'use strict'; - Tone.GreaterThan = function (value) { - this.createInsOuts(2, 0); - this._param = this.input[0] = new Tone.Subtract(value); - this.input[1] = this._param.input[1]; - this._gtz = this.output = new Tone.GreaterThanZero(); - this._param.connect(this._gtz); - }; - Tone.extend(Tone.GreaterThan, Tone.Signal); - Tone.GreaterThan.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._param.dispose(); - this._param = null; - this._gtz.dispose(); - this._gtz = null; - return this; - }; - return Tone.GreaterThan; -}(Tone_core_Tone, Tone_signal_GreaterThanZero, Tone_signal_Subtract); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Abs; -Tone_signal_Abs = function (Tone) { - 'use strict'; - Tone.Abs = function () { - this._abs = this.input = this.output = new Tone.WaveShaper(function (val) { - if (val === 0) { - return 0; + return val; + } + }; + Tone.Param.prototype._toUnits = function (val) { + if (this.convert || this.isUndef(this.convert)) { + switch (this.units) { + case Tone.Type.Decibels: + return this.gainToDb(val); + default: + return val; + } } else { - return Math.abs(val); - } - }, 127); - }; - Tone.extend(Tone.Abs, Tone.SignalBase); - Tone.Abs.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._abs.dispose(); - this._abs = null; - return this; - }; - return Tone.Abs; -}(Tone_core_Tone, Tone_signal_WaveShaper); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Modulo; -Tone_signal_Modulo = function (Tone) { - 'use strict'; - Tone.Modulo = function (modulus) { - this.createInsOuts(1, 0); - this._shaper = new Tone.WaveShaper(Math.pow(2, 16)); - this._multiply = new Tone.Multiply(); - this._subtract = this.output = new Tone.Subtract(); - this._modSignal = new Tone.Signal(modulus); - this.input.fan(this._shaper, this._subtract); - this._modSignal.connect(this._multiply, 0, 0); - this._shaper.connect(this._multiply, 0, 1); - this._multiply.connect(this._subtract, 0, 1); - this._setWaveShaper(modulus); - }; - Tone.extend(Tone.Modulo, Tone.SignalBase); - Tone.Modulo.prototype._setWaveShaper = function (mod) { - this._shaper.setMap(function (val) { - var multiple = Math.floor((val + 0.0001) / mod); - return multiple; - }); - }; - Object.defineProperty(Tone.Modulo.prototype, 'value', { - get: function () { - return this._modSignal.value; - }, - set: function (mod) { - this._modSignal.value = mod; - this._setWaveShaper(mod); - } - }); - Tone.Modulo.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._shaper.dispose(); - this._shaper = null; - this._multiply.dispose(); - this._multiply = null; - this._subtract.dispose(); - this._subtract = null; - this._modSignal.dispose(); - this._modSignal = null; - return this; - }; - return Tone.Modulo; -}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Pow; -Tone_signal_Pow = function (Tone) { - 'use strict'; - Tone.Pow = function (exp) { - this._exp = this.defaultArg(exp, 1); - this._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192); - }; - Tone.extend(Tone.Pow, Tone.SignalBase); - Object.defineProperty(Tone.Pow.prototype, 'value', { - get: function () { - return this._exp; - }, - set: function (exp) { - this._exp = exp; - this._expScaler.setMap(this._expFunc(this._exp)); - } - }); - Tone.Pow.prototype._expFunc = function (exp) { - return function (val) { - return Math.pow(Math.abs(val), exp); - }; - }; - Tone.Pow.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._expScaler.dispose(); - this._expScaler = null; - return this; - }; - return Tone.Pow; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_AudioToGain; -Tone_signal_AudioToGain = function (Tone) { - 'use strict'; - Tone.AudioToGain = function () { - this._norm = this.input = this.output = new Tone.WaveShaper(function (x) { - return (x + 1) / 2; + return val; + } + }; + Tone.Param.prototype._minOutput = 0.00001; + Tone.Param.prototype.setValueAtTime = function (value, time) { + value = this._fromUnits(value); + time = this.toSeconds(time); + if (time <= this.now() + this.blockTime) { + this._param.value = value; + } else { + this._param.setValueAtTime(value, time); + } + return this; + }; + Tone.Param.prototype.setRampPoint = function (now) { + now = this.defaultArg(now, this.now()); + var currentVal = this._param.value; + if (currentVal === 0) { + currentVal = this._minOutput; + } + this._param.setValueAtTime(currentVal, now); + return this; + }; + Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) { + value = this._fromUnits(value); + this._param.linearRampToValueAtTime(value, this.toSeconds(endTime)); + return this; + }; + Tone.Param.prototype.exponentialRampToValueAtTime = function ( + value, + endTime + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime)); + return this; + }; + Tone.Param.prototype.exponentialRampToValue = function ( + value, + rampTime, + startTime + ) { + startTime = this.toSeconds(startTime); + this.setRampPoint(startTime); + this.exponentialRampToValueAtTime( + value, + startTime + this.toSeconds(rampTime) + ); + return this; + }; + Tone.Param.prototype.linearRampToValue = function ( + value, + rampTime, + startTime + ) { + startTime = this.toSeconds(startTime); + this.setRampPoint(startTime); + this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); + return this; + }; + Tone.Param.prototype.setTargetAtTime = function ( + value, + startTime, + timeConstant + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + timeConstant = Math.max(this._minOutput, timeConstant); + this._param.setTargetAtTime( + value, + this.toSeconds(startTime), + timeConstant + ); + return this; + }; + Tone.Param.prototype.setValueCurveAtTime = function ( + values, + startTime, + duration + ) { + for (var i = 0; i < values.length; i++) { + values[i] = this._fromUnits(values[i]); + } + this._param.setValueCurveAtTime( + values, + this.toSeconds(startTime), + this.toSeconds(duration) + ); + return this; + }; + Tone.Param.prototype.cancelScheduledValues = function (startTime) { + this._param.cancelScheduledValues(this.toSeconds(startTime)); + return this; + }; + Tone.Param.prototype.rampTo = function (value, rampTime, startTime) { + rampTime = this.defaultArg(rampTime, 0); + if ( + this.units === Tone.Type.Frequency || + this.units === Tone.Type.BPM || + this.units === Tone.Type.Decibels + ) { + this.exponentialRampToValue(value, rampTime, startTime); + } else { + this.linearRampToValue(value, rampTime, startTime); + } + return this; + }; + Object.defineProperty(Tone.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, }); - }; - Tone.extend(Tone.AudioToGain, Tone.SignalBase); - Tone.AudioToGain.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._norm.dispose(); - this._norm = null; - return this; - }; - return Tone.AudioToGain; -}(Tone_core_Tone, Tone_signal_WaveShaper); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Expr; -Tone_signal_Expr = function (Tone) { - 'use strict'; - Tone.Expr = function () { - var expr = this._replacements(Array.prototype.slice.call(arguments)); - var inputCount = this._parseInputs(expr); - this._nodes = []; - this.input = new Array(inputCount); - for (var i = 0; i < inputCount; i++) { - this.input[i] = this.context.createGain(); - } - var tree = this._parseTree(expr); - var result; - try { - result = this._eval(tree); - } catch (e) { - this._disposeNodes(); - throw new Error('Tone.Expr: Could evaluate expression: ' + expr); - } - this.output = result; - }; - Tone.extend(Tone.Expr, Tone.SignalBase); - function applyBinary(Constructor, args, self) { - var op = new Constructor(); - self._eval(args[0]).connect(op, 0, 0); - self._eval(args[1]).connect(op, 0, 1); - return op; - } - function applyUnary(Constructor, args, self) { - var op = new Constructor(); - self._eval(args[0]).connect(op, 0, 0); - return op; - } - function getNumber(arg) { - return arg ? parseFloat(arg) : undefined; - } - function literalNumber(arg) { - return arg && arg.args ? parseFloat(arg.args) : undefined; - } - Tone.Expr._Expressions = { - 'value': { - 'signal': { - regexp: /^\d+\.\d+|^\d+/, - method: function (arg) { - var sig = new Tone.Signal(getNumber(arg)); - return sig; - } + Tone.Param.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._param = null; + if (this._lfo) { + this._lfo.dispose(); + this._lfo = null; + } + return this; + }; + return Tone.Param; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Gain; + Tone_core_Gain = (function (Tone) { + "use strict"; + if (window.GainNode && !AudioContext.prototype.createGain) { + AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; + } + Tone.Gain = function () { + var options = this.optionsObject( + arguments, + ["gain", "units"], + Tone.Gain.defaults + ); + this.input = this.output = this._gainNode = this.context.createGain(); + this.gain = new Tone.Param({ + param: this._gainNode.gain, + units: options.units, + value: options.gain, + convert: options.convert, + }); + this._readOnly("gain"); + }; + Tone.extend(Tone.Gain); + Tone.Gain.defaults = { + gain: 1, + convert: true, + }; + Tone.Gain.prototype.dispose = function () { + Tone.Param.prototype.dispose.call(this); + this._gainNode.disconnect(); + this._gainNode = null; + this._writable("gain"); + this.gain.dispose(); + this.gain = null; + }; + Tone.prototype.createInsOuts = function (inputs, outputs) { + if (inputs === 1) { + this.input = new Tone.Gain(); + } else if (inputs > 1) { + this.input = new Array(inputs); + } + if (outputs === 1) { + this.output = new Tone.Gain(); + } else if (outputs > 1) { + this.output = new Array(inputs); + } + }; + return Tone.Gain; + })(Tone_core_Tone, Tone_core_Param); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Signal; + Tone_signal_Signal = (function (Tone) { + "use strict"; + Tone.Signal = function () { + var options = this.optionsObject( + arguments, + ["value", "units"], + Tone.Signal.defaults + ); + this.output = this._gain = this.context.createGain(); + options.param = this._gain.gain; + Tone.Param.call(this, options); + this.input = this._param = this._gain.gain; + this.context.getConstant(1).chain(this._gain); + }; + Tone.extend(Tone.Signal, Tone.Param); + Tone.Signal.defaults = { + value: 0, + units: Tone.Type.Default, + convert: true, + }; + Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect; + Tone.Signal.prototype.dispose = function () { + Tone.Param.prototype.dispose.call(this); + this._param = null; + this._gain.disconnect(); + this._gain = null; + return this; + }; + return Tone.Signal; + })(Tone_core_Tone, Tone_signal_WaveShaper, Tone_type_Type, Tone_core_Param); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Add; + Tone_signal_Add = (function (Tone) { + "use strict"; + Tone.Add = function (value) { + this.createInsOuts(2, 0); + this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain(); + this._param = this.input[1] = new Tone.Signal(value); + this._param.connect(this._sum); + }; + Tone.extend(Tone.Add, Tone.Signal); + Tone.Add.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._sum.dispose(); + this._sum = null; + this._param.dispose(); + this._param = null; + return this; + }; + return Tone.Add; + })(Tone_core_Tone, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Multiply; + Tone_signal_Multiply = (function (Tone) { + "use strict"; + Tone.Multiply = function (value) { + this.createInsOuts(2, 0); + this._mult = this.input[0] = this.output = new Tone.Gain(); + this._param = this.input[1] = this.output.gain; + this._param.value = this.defaultArg(value, 0); + }; + Tone.extend(Tone.Multiply, Tone.Signal); + Tone.Multiply.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._mult.dispose(); + this._mult = null; + this._param = null; + return this; + }; + return Tone.Multiply; + })(Tone_core_Tone, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Scale; + Tone_signal_Scale = (function (Tone) { + "use strict"; + Tone.Scale = function (outputMin, outputMax) { + this._outputMin = this.defaultArg(outputMin, 0); + this._outputMax = this.defaultArg(outputMax, 1); + this._scale = this.input = new Tone.Multiply(1); + this._add = this.output = new Tone.Add(0); + this._scale.connect(this._add); + this._setRange(); + }; + Tone.extend(Tone.Scale, Tone.SignalBase); + Object.defineProperty(Tone.Scale.prototype, "min", { + get: function () { + return this._outputMin; }, - 'input': { - regexp: /^\$\d/, - method: function (arg, self) { - return self.input[getNumber(arg.substr(1))]; - } - } - }, - 'glue': { - '(': { regexp: /^\(/ }, - ')': { regexp: /^\)/ }, - ',': { regexp: /^,/ } - }, - 'func': { - 'abs': { - regexp: /^abs/, - method: applyUnary.bind(this, Tone.Abs) + set: function (min) { + this._outputMin = min; + this._setRange(); }, - 'mod': { - regexp: /^mod/, - method: function (args, self) { - var modulus = literalNumber(args[1]); - var op = new Tone.Modulo(modulus); - self._eval(args[0]).connect(op); - return op; - } + }); + Object.defineProperty(Tone.Scale.prototype, "max", { + get: function () { + return this._outputMax; }, - 'pow': { - regexp: /^pow/, - method: function (args, self) { - var exp = literalNumber(args[1]); - var op = new Tone.Pow(exp); - self._eval(args[0]).connect(op); - return op; - } + set: function (max) { + this._outputMax = max; + this._setRange(); }, - 'a2g': { - regexp: /^a2g/, - method: function (args, self) { - var op = new Tone.AudioToGain(); - self._eval(args[0]).connect(op); - return op; + }); + Tone.Scale.prototype._setRange = function () { + this._add.value = this._outputMin; + this._scale.value = this._outputMax - this._outputMin; + }; + Tone.Scale.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._add.dispose(); + this._add = null; + this._scale.dispose(); + this._scale = null; + return this; + }; + return Tone.Scale; + })(Tone_core_Tone, Tone_signal_Add, Tone_signal_Multiply); + var signal; + ("use strict"); + signal = (function () { + // Signal is built with the Tone.js signal by Yotam Mann + // https://github.com/TONEnoTONE/Tone.js/ + var Signal = Tone_signal_Signal; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + /** + *

p5.Signal is a constant audio-rate signal used by p5.Oscillator + * and p5.Envelope for modulation math.

+ * + *

This is necessary because Web Audio is processed on a seprate clock. + * For example, the p5 draw loop runs about 60 times per second. But + * the audio clock must process samples 44100 times per second. If we + * want to add a value to each of those samples, we can't do it in the + * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns + * a Tone.Signal from the Tone.js library by Yotam Mann. + * If you want to work directly with audio signals for modular + * synthesis, check out + * tone.js.

+ * + * @class p5.Signal + * @constructor + * @return {Tone.Signal} A Signal object from the Tone.js library + * @example + *
+ * function setup() { + * carrier = new p5.Oscillator('sine'); + * carrier.amp(1); // set amplitude + * carrier.freq(220); // set frequency + * carrier.start(); // start oscillating + * + * modulator = new p5.Oscillator('sawtooth'); + * modulator.disconnect(); + * modulator.amp(1); + * modulator.freq(4); + * modulator.start(); + * + * // Modulator's default amplitude range is -1 to 1. + * // Multiply it by -200, so the range is -200 to 200 + * // then add 220 so the range is 20 to 420 + * carrier.freq( modulator.mult(-200).add(220) ); + * } + *
+ */ + p5.Signal = function (value) { + var s = new Signal(value); + // p5sound.soundArray.push(s); + return s; + }; + /** + * Fade to value, for smooth transitions + * + * @method fade + * @param {Number} value Value to set this signal + * @param {Number} [secondsFromNow] Length of fade, in seconds from now + */ + Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime; + Mult.prototype.fade = Signal.prototype.fade; + Add.prototype.fade = Signal.prototype.fade; + Scale.prototype.fade = Signal.prototype.fade; + /** + * Connect a p5.sound object or Web Audio node to this + * p5.Signal so that its amplitude values can be scaled. + * + * @method setInput + * @param {Object} input + */ + Signal.prototype.setInput = function (_input) { + _input.connect(this); + }; + Mult.prototype.setInput = Signal.prototype.setInput; + Add.prototype.setInput = Signal.prototype.setInput; + Scale.prototype.setInput = Signal.prototype.setInput; + // signals can add / mult / scale themselves + /** + * Add a constant value to this audio signal, + * and return the resulting audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalAdd. + * + * @method add + * @param {Number} number + * @return {p5.Signal} object + */ + Signal.prototype.add = function (num) { + var add = new Add(num); + // add.setInput(this); + this.connect(add); + return add; + }; + Mult.prototype.add = Signal.prototype.add; + Add.prototype.add = Signal.prototype.add; + Scale.prototype.add = Signal.prototype.add; + /** + * Multiply this signal by a constant value, + * and return the resulting audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalMult. + * + * @method mult + * @param {Number} number to multiply + * @return {p5.Signal} object + */ + Signal.prototype.mult = function (num) { + var mult = new Mult(num); + // mult.setInput(this); + this.connect(mult); + return mult; + }; + Mult.prototype.mult = Signal.prototype.mult; + Add.prototype.mult = Signal.prototype.mult; + Scale.prototype.mult = Signal.prototype.mult; + /** + * Scale this signal value to a given range, + * and return the result as an audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalScale. + * + * @method scale + * @param {Number} number to multiply + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Signal} object + */ + Signal.prototype.scale = function (inMin, inMax, outMin, outMax) { + var mapOutMin, mapOutMax; + if (arguments.length === 4) { + mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; + mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; + } else { + mapOutMin = arguments[0]; + mapOutMax = arguments[1]; + } + var scale = new Scale(mapOutMin, mapOutMax); + this.connect(scale); + return scale; + }; + Mult.prototype.scale = Signal.prototype.scale; + Add.prototype.scale = Signal.prototype.scale; + Scale.prototype.scale = Signal.prototype.scale; + })( + Tone_signal_Signal, + Tone_signal_Add, + Tone_signal_Multiply, + Tone_signal_Scale + ); + var oscillator; + ("use strict"); + oscillator = (function () { + var p5sound = master; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + /** + *

Creates a signal that oscillates between -1.0 and 1.0. + * By default, the oscillation takes the form of a sinusoidal + * shape ('sine'). Additional types include 'triangle', + * 'sawtooth' and 'square'. The frequency defaults to + * 440 oscillations per second (440Hz, equal to the pitch of an + * 'A' note).

+ * + *

Set the type of oscillation with setType(), or by instantiating a + * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. + *

+ * + * @class p5.Oscillator + * @constructor + * @param {Number} [freq] frequency defaults to 440Hz + * @param {String} [type] type of oscillator. Options: + * 'sine' (default), 'triangle', + * 'sawtooth', 'square' + * @example + *
+ * var osc; + * var playing = false; + * + * function setup() { + * backgroundColor = color(255,0,255); + * textAlign(CENTER); + * + * osc = new p5.Oscillator(); + * osc.setType('sine'); + * osc.freq(240); + * osc.amp(0); + * osc.start(); + * } + * + * function draw() { + * background(backgroundColor) + * text('click to play', width/2, height/2); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { + * if (!playing) { + * // ramp amplitude to 0.5 over 0.05 seconds + * osc.amp(0.5, 0.05); + * playing = true; + * backgroundColor = color(0,255,255); + * } else { + * // ramp amplitude to 0 over 0.5 seconds + * osc.amp(0, 0.5); + * playing = false; + * backgroundColor = color(255,0,255); + * } + * } + * } + *
+ */ + p5.Oscillator = function (freq, type) { + if (typeof freq === "string") { + var f = type; + type = freq; + freq = f; + } + if (typeof type === "number") { + var f = type; + type = freq; + freq = f; + } + this.started = false; + // components + this.phaseAmount = undefined; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.f = freq || 440; + // frequency + this.oscillator.type = type || "sine"; + this.oscillator.frequency.setValueAtTime( + this.f, + p5sound.audiocontext.currentTime + ); + // connections + this.output = p5sound.audiocontext.createGain(); + this._freqMods = []; + // modulators connected to this oscillator's frequency + // set default output gain to 0.5 + this.output.gain.value = 0.5; + this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime); + this.oscillator.connect(this.output); + // stereo panning + this.panPosition = 0; + this.connection = p5sound.input; + // connect to p5sound by default + this.panner = new p5.Panner(this.output, this.connection, 1); + //array of math operation signal chaining + this.mathOps = [this.output]; + // add to the soundArray so we can dispose of the osc later + p5sound.soundArray.push(this); + }; + /** + * Start an oscillator. Accepts an optional parameter to + * determine how long (in seconds from now) until the + * oscillator starts. + * + * @method start + * @param {Number} [time] startTime in seconds from now. + * @param {Number} [frequency] frequency in Hz. + */ + p5.Oscillator.prototype.start = function (time, f) { + if (this.started) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + } + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; + // set old osc free to be garbage collected (memory) + if (this.oscillator) { + this.oscillator.disconnect(); + delete this.oscillator; } + // var detune = this.oscillator.frequency.value; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.oscillator.frequency.value = Math.abs(freq); + this.oscillator.type = type; + // this.oscillator.detune.value = detune; + this.oscillator.connect(this.output); + time = time || 0; + this.oscillator.start(time + p5sound.audiocontext.currentTime); + this.freqNode = this.oscillator.frequency; + // if other oscillators are already connected to this osc's freq + for (var i in this._freqMods) { + if (typeof this._freqMods[i].connect !== "undefined") { + this._freqMods[i].connect(this.oscillator.frequency); + } + } + this.started = true; } - }, - 'binary': { - '+': { - regexp: /^\+/, - precedence: 1, - method: applyBinary.bind(this, Tone.Add) - }, - '-': { - regexp: /^\-/, - precedence: 1, - method: function (args, self) { - if (args.length === 1) { - return applyUnary(Tone.Negate, args, self); + }; + /** + * Stop an oscillator. Accepts an optional parameter + * to determine how long (in seconds from now) until the + * oscillator stops. + * + * @method stop + * @param {Number} secondsFromNow Time, in seconds from now. + */ + p5.Oscillator.prototype.stop = function (time) { + if (this.started) { + var t = time || 0; + var now = p5sound.audiocontext.currentTime; + this.oscillator.stop(t + now); + this.started = false; + } + }; + /** + * Set the amplitude between 0 and 1.0. Or, pass in an object + * such as an oscillator to modulate amplitude with an audio signal. + * + * @method amp + * @param {Number|Object} vol between 0 and 1.0 + * or a modulating signal/oscillator + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {AudioParam} gain If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's + * gain/amplitude/volume) + */ + p5.Oscillator.prototype.amp = function (vol, rampTime, tFromNow) { + var self = this; + if (typeof vol === "number") { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(self.output.gain); + } else { + // return the Gain Node + return this.output.gain; + } + }; + // these are now the same thing + p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp; + p5.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }; + /** + * Set frequency of an oscillator to a value. Or, pass in an object + * such as an oscillator to modulate the frequency with an audio signal. + * + * @method freq + * @param {Number|Object} Frequency Frequency in Hz + * or modulating signal/oscillator + * @param {Number} [rampTime] Ramp time (in seconds) + * @param {Number} [timeFromNow] Schedule this event to happen + * at x seconds from now + * @return {AudioParam} Frequency If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's frequency + * @example + *
+ * var osc = new p5.Oscillator(300); + * osc.start(); + * osc.freq(40, 10); + *
+ */ + p5.Oscillator.prototype.freq = function (val, rampTime, tFromNow) { + if (typeof val === "number" && !isNaN(val)) { + this.f = val; + var now = p5sound.audiocontext.currentTime; + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var t = now + tFromNow + rampTime; + // var currentFreq = this.oscillator.frequency.value; + // this.oscillator.frequency.cancelScheduledValues(now); + if (rampTime === 0) { + this.oscillator.frequency.setValueAtTime(val, tFromNow + now); + } else { + if (val > 0) { + this.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); } else { - return applyBinary(Tone.Subtract, args, self); + this.oscillator.frequency.linearRampToValueAtTime( + val, + tFromNow + rampTime + now + ); } } - }, - '*': { - regexp: /^\*/, - precedence: 0, - method: applyBinary.bind(this, Tone.Multiply) + // reset phase if oscillator has a phase + if (this.phaseAmount) { + this.phase(this.phaseAmount); + } + } else if (val) { + if (val.output) { + val = val.output; + } + val.connect(this.oscillator.frequency); + // keep track of what is modulating this param + // so it can be re-connected if + this._freqMods.push(val); + } else { + // return the Frequency Node + return this.oscillator.frequency; } - }, - 'unary': { - '-': { - regexp: /^\-/, - method: applyUnary.bind(this, Tone.Negate) - }, - '!': { - regexp: /^\!/, - method: applyUnary.bind(this, Tone.NOT) + }; + p5.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }; + /** + * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. + * + * @method setType + * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. + */ + p5.Oscillator.prototype.setType = function (type) { + this.oscillator.type = type; + }; + p5.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.Oscillator.prototype.connect = function (unit) { + if (!unit) { + this.panner.connect(p5sound.input); + } else if (unit.hasOwnProperty("input")) { + this.panner.connect(unit.input); + this.connection = unit.input; + } else { + this.panner.connect(unit); + this.connection = unit; } - } - }; - Tone.Expr.prototype._parseInputs = function (expr) { - var inputArray = expr.match(/\$\d/g); - var inputMax = 0; - if (inputArray !== null) { - for (var i = 0; i < inputArray.length; i++) { - var inputNum = parseInt(inputArray[i].substr(1)) + 1; - inputMax = Math.max(inputMax, inputNum); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.Oscillator.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); } - } - return inputMax; - }; - Tone.Expr.prototype._replacements = function (args) { - var expr = args.shift(); - for (var i = 0; i < args.length; i++) { - expr = expr.replace(/\%/i, args[i]); - } - return expr; - }; - Tone.Expr.prototype._tokenize = function (expr) { - var position = -1; - var tokens = []; - while (expr.length > 0) { - expr = expr.trim(); - var token = getNextToken(expr); - tokens.push(token); - expr = expr.substr(token.value.length); - } - function getNextToken(expr) { - for (var type in Tone.Expr._Expressions) { - var group = Tone.Expr._Expressions[type]; - for (var opName in group) { - var op = group[opName]; - var reg = op.regexp; - var match = expr.match(reg); - if (match !== null) { - return { - type: type, - value: match[0], - method: op.method - }; - } + if (this.panner) { + this.panner.disconnect(); + if (this.output) { + this.output.connect(this.panner); } } - throw new SyntaxError('Tone.Expr: Unexpected token ' + expr); - } - return { - next: function () { - return tokens[++position]; - }, - peek: function () { - return tokens[position + 1]; + this.oscMods = []; + }; + /** + * Pan between Left (-1) and Right (1) + * + * @method pan + * @param {Number} panning Number between -1 and 1 + * @param {Number} timeFromNow schedule this event to happen + * seconds from now + */ + p5.Oscillator.prototype.pan = function (pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + }; + p5.Oscillator.prototype.getPan = function () { + return this.panPosition; + }; + // get rid of the oscillator + p5.Oscillator.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.oscillator) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + this.disconnect(); + this.panner = null; + this.oscillator = null; + } + // if it is a Pulse + if (this.osc2) { + this.osc2.dispose(); } }; - }; - Tone.Expr.prototype._parseTree = function (expr) { - var lexer = this._tokenize(expr); - var isUndef = this.isUndef.bind(this); - function matchSyntax(token, syn) { - return !isUndef(token) && token.type === 'glue' && token.value === syn; - } - function matchGroup(token, groupName, prec) { - var ret = false; - var group = Tone.Expr._Expressions[groupName]; - if (!isUndef(token)) { - for (var opName in group) { - var op = group[opName]; - if (op.regexp.test(token.value)) { - if (!isUndef(prec)) { - if (op.precedence === prec) { - return true; - } - } else { - return true; - } + /** + * Set the phase of an oscillator between 0.0 and 1.0. + * In this implementation, phase is a delay time + * based on the oscillator's current frequency. + * + * @method phase + * @param {Number} phase float between 0.0 and 1.0 + */ + p5.Oscillator.prototype.phase = function (p) { + var delayAmt = p5.prototype.map(p, 0, 1, 0, 1 / this.f); + var now = p5sound.audiocontext.currentTime; + this.phaseAmount = p; + if (!this.dNode) { + // create a delay node + this.dNode = p5sound.audiocontext.createDelay(); + // put the delay node in between output and panner + this.oscillator.disconnect(); + this.oscillator.connect(this.dNode); + this.dNode.connect(this.output); + } + // set delay time to match phase: + this.dNode.delayTime.setValueAtTime(delayAmt, now); + }; + // ========================== // + // SIGNAL MATH FOR MODULATION // + // ========================== // + // return sigChain(this, scale, thisChain, nextChain, Scale); + var sigChain = function (o, mathObj, thisChain, nextChain, type) { + var chainSource = o.oscillator; + // if this type of math already exists in the chain, replace it + for (var i in o.mathOps) { + if (o.mathOps[i] instanceof type) { + chainSource.disconnect(); + o.mathOps[i].dispose(); + thisChain = i; + // assume nextChain is output gain node unless... + if (thisChain < o.mathOps.length - 2) { + nextChain = o.mathOps[i + 1]; } } } - return ret; - } - function parseExpression(precedence) { - if (isUndef(precedence)) { - precedence = 5; + if (thisChain === o.mathOps.length - 1) { + o.mathOps.push(nextChain); } - var expr; - if (precedence < 0) { - expr = parseUnary(); - } else { - expr = parseExpression(precedence - 1); + // assume source is the oscillator unless i > 0 + if (i > 0) { + chainSource = o.mathOps[i - 1]; } - var token = lexer.peek(); - while (matchGroup(token, 'binary', precedence)) { - token = lexer.next(); - expr = { - operator: token.value, - method: token.method, - args: [ - expr, - parseExpression(precedence - 1) - ] - }; - token = lexer.peek(); - } - return expr; - } - function parseUnary() { - var token, expr; - token = lexer.peek(); - if (matchGroup(token, 'unary')) { - token = lexer.next(); - expr = parseUnary(); - return { - operator: token.value, - method: token.method, - args: [expr] - }; + chainSource.disconnect(); + chainSource.connect(mathObj); + mathObj.connect(nextChain); + o.mathOps[thisChain] = mathObj; + return o; + }; + /** + * Add a value to the p5.Oscillator's output amplitude, + * and return the oscillator. Calling this method again + * will override the initial add() with a new value. + * + * @method add + * @param {Number} number Constant number to add + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + * + */ + p5.Oscillator.prototype.add = function (num) { + var add = new Add(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, add, thisChain, nextChain, Add); + }; + /** + * Multiply the p5.Oscillator's output amplitude + * by a fixed value (i.e. turn it up!). Calling this method + * again will override the initial mult() with a new value. + * + * @method mult + * @param {Number} number Constant number to multiply + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with multiplied output + */ + p5.Oscillator.prototype.mult = function (num) { + var mult = new Mult(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, mult, thisChain, nextChain, Mult); + }; + /** + * Scale this oscillator's amplitude values to a given + * range, and return the oscillator. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + */ + p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) { + var mapOutMin, mapOutMax; + if (arguments.length === 4) { + mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; + mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; + } else { + mapOutMin = arguments[0]; + mapOutMax = arguments[1]; } - return parsePrimary(); - } - function parsePrimary() { - var token, expr; - token = lexer.peek(); - if (isUndef(token)) { - throw new SyntaxError('Tone.Expr: Unexpected termination of expression'); + var scale = new Scale(mapOutMin, mapOutMax); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, scale, thisChain, nextChain, Scale); + }; + // ============================== // + // SinOsc, TriOsc, SqrOsc, SawOsc // + // ============================== // + /** + * Constructor: new p5.SinOsc(). + * This creates a Sine Wave Oscillator and is + * equivalent to new p5.Oscillator('sine') + * or creating a p5.Oscillator and then calling + * its method setType('sine'). + * See p5.Oscillator for methods. + * + * @class p5.SinOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SinOsc = function (freq) { + p5.Oscillator.call(this, freq, "sine"); + }; + p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.TriOsc(). + * This creates a Triangle Wave Oscillator and is + * equivalent to new p5.Oscillator('triangle') + * or creating a p5.Oscillator and then calling + * its method setType('triangle'). + * See p5.Oscillator for methods. + * + * @class p5.TriOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.TriOsc = function (freq) { + p5.Oscillator.call(this, freq, "triangle"); + }; + p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.SawOsc(). + * This creates a SawTooth Wave Oscillator and is + * equivalent to new p5.Oscillator('sawtooth') + * or creating a p5.Oscillator and then calling + * its method setType('sawtooth'). + * See p5.Oscillator for methods. + * + * @class p5.SawOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SawOsc = function (freq) { + p5.Oscillator.call(this, freq, "sawtooth"); + }; + p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.SqrOsc(). + * This creates a Square Wave Oscillator and is + * equivalent to new p5.Oscillator('square') + * or creating a p5.Oscillator and then calling + * its method setType('square'). + * See p5.Oscillator for methods. + * + * @class p5.SqrOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SqrOsc = function (freq) { + p5.Oscillator.call(this, freq, "square"); + }; + p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype); + })(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Timeline; + Tone_core_Timeline = (function (Tone) { + "use strict"; + Tone.Timeline = function () { + var options = this.optionsObject( + arguments, + ["memory"], + Tone.Timeline.defaults + ); + this._timeline = []; + this._toRemove = []; + this._iterating = false; + this.memory = options.memory; + }; + Tone.extend(Tone.Timeline); + Tone.Timeline.defaults = { memory: Infinity }; + Object.defineProperty(Tone.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }); + Tone.Timeline.prototype.add = function (event) { + if (this.isUndef(event.time)) { + throw new Error("Tone.Timeline: events must have a time attribute"); } - if (token.type === 'func') { - token = lexer.next(); - return parseFunctionCall(token); + if (this._timeline.length) { + var index = this._search(event.time); + this._timeline.splice(index + 1, 0, event); + } else { + this._timeline.push(event); } - if (token.type === 'value') { - token = lexer.next(); - return { - method: token.method, - args: token.value - }; + if (this.length > this.memory) { + var diff = this.length - this.memory; + this._timeline.splice(0, diff); } - if (matchSyntax(token, '(')) { - lexer.next(); - expr = parseExpression(); - token = lexer.next(); - if (!matchSyntax(token, ')')) { - throw new SyntaxError('Expected )'); + return this; + }; + Tone.Timeline.prototype.remove = function (event) { + if (this._iterating) { + this._toRemove.push(event); + } else { + var index = this._timeline.indexOf(event); + if (index !== -1) { + this._timeline.splice(index, 1); } - return expr; } - throw new SyntaxError('Tone.Expr: Parse error, cannot process token ' + token.value); - } - function parseFunctionCall(func) { - var token, args = []; - token = lexer.next(); - if (!matchSyntax(token, '(')) { - throw new SyntaxError('Tone.Expr: Expected ( in a function call "' + func.value + '"'); + return this; + }; + Tone.Timeline.prototype.get = function (time) { + var index = this._search(time); + if (index !== -1) { + return this._timeline[index]; + } else { + return null; } - token = lexer.peek(); - if (!matchSyntax(token, ')')) { - args = parseArgumentList(); + }; + Tone.Timeline.prototype.peek = function () { + return this._timeline[0]; + }; + Tone.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }; + Tone.Timeline.prototype.getAfter = function (time) { + var index = this._search(time); + if (index + 1 < this._timeline.length) { + return this._timeline[index + 1]; + } else { + return null; } - token = lexer.next(); - if (!matchSyntax(token, ')')) { - throw new SyntaxError('Tone.Expr: Expected ) in a function call "' + func.value + '"'); + }; + Tone.Timeline.prototype.getBefore = function (time) { + var len = this._timeline.length; + if (len > 0 && this._timeline[len - 1].time < time) { + return this._timeline[len - 1]; } - return { - method: func.method, - args: args, - name: name - }; - } - function parseArgumentList() { - var token, expr, args = []; - while (true) { - expr = parseExpression(); - if (isUndef(expr)) { - break; + var index = this._search(time); + if (index - 1 >= 0) { + return this._timeline[index - 1]; + } else { + return null; + } + }; + Tone.Timeline.prototype.cancel = function (after) { + if (this._timeline.length > 1) { + var index = this._search(after); + if (index >= 0) { + if (this._timeline[index].time === after) { + for (var i = index; i >= 0; i--) { + if (this._timeline[i].time === after) { + index = i; + } else { + break; + } + } + this._timeline = this._timeline.slice(0, index); + } else { + this._timeline = this._timeline.slice(0, index + 1); + } + } else { + this._timeline = []; } - args.push(expr); - token = lexer.peek(); - if (!matchSyntax(token, ',')) { - break; + } else if (this._timeline.length === 1) { + if (this._timeline[0].time >= after) { + this._timeline = []; } - lexer.next(); } - return args; - } - return parseExpression(); - }; - Tone.Expr.prototype._eval = function (tree) { - if (!this.isUndef(tree)) { - var node = tree.method(tree.args, this); - this._nodes.push(node); - return node; - } - }; - Tone.Expr.prototype._disposeNodes = function () { - for (var i = 0; i < this._nodes.length; i++) { - var node = this._nodes[i]; - if (this.isFunction(node.dispose)) { - node.dispose(); - } else if (this.isFunction(node.disconnect)) { - node.disconnect(); - } - node = null; - this._nodes[i] = null; - } - this._nodes = null; - }; - Tone.Expr.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._disposeNodes(); - }; - return Tone.Expr; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Subtract, Tone_signal_Multiply, Tone_signal_GreaterThan, Tone_signal_GreaterThanZero, Tone_signal_Abs, Tone_signal_Negate, Tone_signal_Modulo, Tone_signal_Pow); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_EqualPowerGain; -Tone_signal_EqualPowerGain = function (Tone) { - 'use strict'; - Tone.EqualPowerGain = function () { - this._eqPower = this.input = this.output = new Tone.WaveShaper(function (val) { - if (Math.abs(val) < 0.001) { - return 0; + return this; + }; + Tone.Timeline.prototype.cancelBefore = function (time) { + if (this._timeline.length) { + var index = this._search(time); + if (index >= 0) { + this._timeline = this._timeline.slice(index + 1); + } + } + return this; + }; + Tone.Timeline.prototype._search = function (time) { + var beginning = 0; + var len = this._timeline.length; + var end = len; + if (len > 0 && this._timeline[len - 1].time <= time) { + return len - 1; + } + while (beginning < end) { + var midPoint = Math.floor(beginning + (end - beginning) / 2); + var event = this._timeline[midPoint]; + var nextEvent = this._timeline[midPoint + 1]; + if (event.time === time) { + for (var i = midPoint; i < this._timeline.length; i++) { + var testEvent = this._timeline[i]; + if (testEvent.time === time) { + midPoint = i; + } + } + return midPoint; + } else if (event.time < time && nextEvent.time > time) { + return midPoint; + } else if (event.time > time) { + end = midPoint; + } else if (event.time < time) { + beginning = midPoint + 1; + } + } + return -1; + }; + Tone.Timeline.prototype._iterate = function ( + callback, + lowerBound, + upperBound + ) { + this._iterating = true; + lowerBound = this.defaultArg(lowerBound, 0); + upperBound = this.defaultArg(upperBound, this._timeline.length - 1); + for (var i = lowerBound; i <= upperBound; i++) { + callback(this._timeline[i]); + } + this._iterating = false; + if (this._toRemove.length > 0) { + for (var j = 0; j < this._toRemove.length; j++) { + var index = this._timeline.indexOf(this._toRemove[j]); + if (index !== -1) { + this._timeline.splice(index, 1); + } + } + this._toRemove = []; + } + }; + Tone.Timeline.prototype.forEach = function (callback) { + this._iterate(callback); + return this; + }; + Tone.Timeline.prototype.forEachBefore = function (time, callback) { + var upperBound = this._search(time); + if (upperBound !== -1) { + this._iterate(callback, 0, upperBound); + } + return this; + }; + Tone.Timeline.prototype.forEachAfter = function (time, callback) { + var lowerBound = this._search(time); + this._iterate(callback, lowerBound + 1); + return this; + }; + Tone.Timeline.prototype.forEachFrom = function (time, callback) { + var lowerBound = this._search(time); + while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) { + lowerBound--; + } + this._iterate(callback, lowerBound + 1); + return this; + }; + Tone.Timeline.prototype.forEachAtTime = function (time, callback) { + var upperBound = this._search(time); + if (upperBound !== -1) { + this._iterate( + function (event) { + if (event.time === time) { + callback(event); + } + }, + 0, + upperBound + ); + } + return this; + }; + Tone.Timeline.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._timeline = null; + this._toRemove = null; + }; + return Tone.Timeline; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_TimelineSignal; + Tone_signal_TimelineSignal = (function (Tone) { + "use strict"; + Tone.TimelineSignal = function () { + var options = this.optionsObject( + arguments, + ["value", "units"], + Tone.Signal.defaults + ); + this._events = new Tone.Timeline(10); + Tone.Signal.apply(this, options); + options.param = this._param; + Tone.Param.call(this, options); + this._initial = this._fromUnits(this._param.value); + }; + Tone.extend(Tone.TimelineSignal, Tone.Param); + Tone.TimelineSignal.Type = { + Linear: "linear", + Exponential: "exponential", + Target: "target", + Curve: "curve", + Set: "set", + }; + Object.defineProperty(Tone.TimelineSignal.prototype, "value", { + get: function () { + var now = this.now(); + var val = this.getValueAtTime(now); + return this._toUnits(val); + }, + set: function (value) { + var convertedVal = this._fromUnits(value); + this._initial = convertedVal; + this.cancelScheduledValues(); + this._param.value = convertedVal; + }, + }); + Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) { + value = this._fromUnits(value); + startTime = this.toSeconds(startTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Set, + value: value, + time: startTime, + }); + this._param.setValueAtTime(value, startTime); + return this; + }; + Tone.TimelineSignal.prototype.linearRampToValueAtTime = function ( + value, + endTime + ) { + value = this._fromUnits(value); + endTime = this.toSeconds(endTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Linear, + value: value, + time: endTime, + }); + this._param.linearRampToValueAtTime(value, endTime); + return this; + }; + Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function ( + value, + endTime + ) { + endTime = this.toSeconds(endTime); + var beforeEvent = this._searchBefore(endTime); + if (beforeEvent && beforeEvent.value === 0) { + this.setValueAtTime(this._minOutput, beforeEvent.time); + } + value = this._fromUnits(value); + var setValue = Math.max(value, this._minOutput); + this._events.add({ + type: Tone.TimelineSignal.Type.Exponential, + value: setValue, + time: endTime, + }); + if (value < this._minOutput) { + this._param.exponentialRampToValueAtTime( + this._minOutput, + endTime - this.sampleTime + ); + this.setValueAtTime(0, endTime); } else { - return this.equalPowerScale(val); - } - }.bind(this), 4096); - }; - Tone.extend(Tone.EqualPowerGain, Tone.SignalBase); - Tone.EqualPowerGain.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._eqPower.dispose(); - this._eqPower = null; - return this; - }; - return Tone.EqualPowerGain; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_component_CrossFade; -Tone_component_CrossFade = function (Tone) { - 'use strict'; - Tone.CrossFade = function (initialFade) { - this.createInsOuts(2, 1); - this.a = this.input[0] = new Tone.Gain(); - this.b = this.input[1] = new Tone.Gain(); - this.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange); - this._equalPowerA = new Tone.EqualPowerGain(); - this._equalPowerB = new Tone.EqualPowerGain(); - this._invert = new Tone.Expr('1 - $0'); - this.a.connect(this.output); - this.b.connect(this.output); - this.fade.chain(this._equalPowerB, this.b.gain); - this.fade.chain(this._invert, this._equalPowerA, this.a.gain); - this._readOnly('fade'); - }; - Tone.extend(Tone.CrossFade); - Tone.CrossFade.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._writable('fade'); - this._equalPowerA.dispose(); - this._equalPowerA = null; - this._equalPowerB.dispose(); - this._equalPowerB = null; - this.fade.dispose(); - this.fade = null; - this._invert.dispose(); - this._invert = null; - this.a.dispose(); - this.a = null; - this.b.dispose(); - this.b = null; - return this; - }; - return Tone.CrossFade; -}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Expr, Tone_signal_EqualPowerGain); -var effect; -'use strict'; -effect = function () { - var p5sound = master; - var CrossFade = Tone_component_CrossFade; - /** - * Effect is a base class for audio effects in p5.
- * This module handles the nodes and methods that are - * common and useful for current and future effects. - * - * - * This class is extended by p5.Distortion, - * p5.Compressor, - * p5.Delay, - * p5.Filter, - * p5.Reverb. - * - * @class p5.Effect - * @constructor - * - * @param {Object} [ac] Reference to the audio context of the p5 object - * @param {AudioNode} [input] Gain Node effect wrapper - * @param {AudioNode} [output] Gain Node effect wrapper - * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1) - * @param {AudioNode} [wet] Effects that extend this class should connect - * to the wet signal to this gain node, so that dry and wet - * signals are mixed properly. - */ - p5.Effect = function () { - this.ac = p5sound.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); - /** - * The p5.Effect class is built - * using Tone.js CrossFade - * @private - */ - this._drywet = new CrossFade(1); - /** - * In classes that extend - * p5.Effect, connect effect nodes - * to the wet parameter - */ - this.wet = this.ac.createGain(); - this.input.connect(this._drywet.a); - this.wet.connect(this._drywet.b); - this._drywet.connect(this.output); - this.connect(); - //Add to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Set the output volume of the filter. - * - * @method amp - * @param {Number} [vol] amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts until rampTime - * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds - */ - p5.Effect.prototype.amp = function (vol, rampTime, tFromNow) { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + 0.001); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + 0.001); - }; - /** - * Link effects together in a chain - * Example usage: filter.chain(reverb, delay, panner); - * May be used with an open-ended number of arguments - * - * @method chain - * @param {Object} [arguments] Chain together multiple sound objects - */ - p5.Effect.prototype.chain = function () { - if (arguments.length > 0) { - this.connect(arguments[0]); - for (var i = 1; i < arguments.length; i += 1) { - arguments[i - 1].connect(arguments[i]); + this._param.exponentialRampToValueAtTime(value, endTime); } - } - return this; - }; - /** - * Adjust the dry/wet value. - * - * @method drywet - * @param {Number} [fade] The desired drywet value (0 - 1.0) - */ - p5.Effect.prototype.drywet = function (fade) { - if (typeof fade !== 'undefined') { - this._drywet.fade.value = fade; - } - return this._drywet.fade.value; - }; - /** - * Send output to a p5.js-sound, Web Audio Node, or use signal to - * control an AudioParam - * - * @method connect - * @param {Object} unit - */ - p5.Effect.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Effect.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - p5.Effect.prototype.dispose = function () { - // remove refernce form soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.input) { - this.input.disconnect(); - delete this.input; - } - if (this.output) { - this.output.disconnect(); - delete this.output; - } - if (this._drywet) { - this._drywet.disconnect(); - delete this._drywet; - } - if (this.wet) { - this.wet.disconnect(); - delete this.wet; - } - this.ac = undefined; - }; - return p5.Effect; -}(master, Tone_component_CrossFade); -var filter; -'use strict'; -filter = function () { - var p5sound = master; - var Effect = effect; - /** - *

A p5.Filter uses a Web Audio Biquad Filter to filter - * the frequency response of an input source. Subclasses - * include:

- * * p5.LowPass: - * Allows frequencies below the cutoff frequency to pass through, - * and attenuates frequencies above the cutoff.
- * * p5.HighPass: - * The opposite of a lowpass filter.
- * * p5.BandPass: - * Allows a range of frequencies to pass through and attenuates - * the frequencies below and above this frequency range.
- * - * The .res() method controls either width of the - * bandpass, or resonance of the low/highpass cutoff frequency. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Filter - * @extends p5.Effect - * @constructor - * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass' - * @example - *
- * var fft, noise, filter; - * - * function setup() { - * fill(255, 40, 255); - * - * filter = new p5.BandPass(); - * - * noise = new p5.Noise(); - * // disconnect unfiltered noise, - * // and connect to filter - * noise.disconnect(); - * noise.connect(filter); - * noise.start(); - * - * fft = new p5.FFT(); - * } - * - * function draw() { - * background(30); - * - * // set the BandPass frequency based on mouseX - * var freq = map(mouseX, 0, width, 20, 10000); - * filter.freq(freq); - * // give the filter a narrow band (lower res = wider bandpass) - * filter.res(50); - * - * // draw filtered spectrum - * var spectrum = fft.analyze(); - * noStroke(); - * for (var i = 0; i < spectrum.length; i++) { - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width/spectrum.length, h); - * } - * - * isMouseOverCanvas(); - * } - * - * function isMouseOverCanvas() { - * var mX = mouseX, mY = mouseY; - * if (mX > 0 && mX < width && mY < height && mY > 0) { - * noise.amp(0.5, 0.2); - * } else { - * noise.amp(0, 0.2); - * } - * } - *
- */ - //constructor with inheritance - p5.Filter = function (type) { - Effect.call(this); - //add extend Effect by adding a Biquad Filter - /** - * The p5.Filter is built with a - * - * Web Audio BiquadFilter Node. - * - * @property {DelayNode} biquadFilter - */ - this.biquad = this.ac.createBiquadFilter(); - this.input.connect(this.biquad); - this.biquad.connect(this.wet); - if (type) { - this.setType(type); - } - //Properties useful for the toggle method. - this._on = true; - this._untoggledType = this.biquad.type; - }; - p5.Filter.prototype = Object.create(Effect.prototype); - /** - * Filter an audio signal according to a set - * of filter parameters. - * - * @method process - * @param {Object} Signal An object that outputs audio - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance/Width of the filter frequency - * from 0.001 to 1000 - */ - p5.Filter.prototype.process = function (src, freq, res, time) { - src.connect(this.input); - this.set(freq, res, time); - }; - /** - * Set the frequency and the resonance of the filter. - * - * @method set - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance (Q) from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - p5.Filter.prototype.set = function (freq, res, time) { - if (freq) { - this.freq(freq, time); - } - if (res) { - this.res(res, time); - } - }; - /** - * Set the filter frequency, in Hz, from 10 to 22050 (the range of - * human hearing, although in reality most people hear in a narrower - * range). - * - * @method freq - * @param {Number} freq Filter Frequency - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current frequency value - */ - p5.Filter.prototype.freq = function (freq, time) { - var t = time || 0; - if (freq <= 0) { - freq = 1; - } - if (typeof freq === 'number') { - this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t); - } else if (freq) { - freq.connect(this.biquad.frequency); - } - return this.biquad.frequency.value; - }; - /** - * Controls either width of a bandpass frequency, - * or the resonance of a low/highpass cutoff frequency. - * - * @method res - * @param {Number} res Resonance/Width of filter freq - * from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current res value - */ - p5.Filter.prototype.res = function (res, time) { - var t = time || 0; - if (typeof res === 'number') { - this.biquad.Q.value = res; - this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t); - } else if (res) { - res.connect(this.biquad.Q); - } - return this.biquad.Q.value; - }; - /** - * Controls the gain attribute of a Biquad Filter. - * This is distinctly different from .amp() which is inherited from p5.Effect - * .amp() controls the volume via the output gain node - * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. - * - * @method gain - * @param {Number} gain - * @return {Number} Returns the current or updated gain value - */ - p5.Filter.prototype.gain = function (gain, time) { - var t = time || 0; - if (typeof gain === 'number') { - this.biquad.gain.value = gain; - this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t); - } else if (gain) { - gain.connect(this.biquad.gain); - } - return this.biquad.gain.value; - }; - /** - * Toggle function. Switches between the specified type and allpass - * - * @method toggle - * @return {boolean} [Toggle value] - */ - p5.Filter.prototype.toggle = function () { - this._on = !this._on; - if (this._on === true) { - this.biquad.type = this._untoggledType; - } else if (this._on === false) { - this.biquad.type = 'allpass'; - } - return this._on; - }; - /** - * Set the type of a p5.Filter. Possible types include: - * "lowpass" (default), "highpass", "bandpass", - * "lowshelf", "highshelf", "peaking", "notch", - * "allpass". - * - * @method setType - * @param {String} t - */ - p5.Filter.prototype.setType = function (t) { - this.biquad.type = t; - this._untoggledType = this.biquad.type; - }; - p5.Filter.prototype.dispose = function () { - // remove reference from soundArray - Effect.prototype.dispose.apply(this); - if (this.biquad) { - this.biquad.disconnect(); - delete this.biquad; - } - }; - /** - * Constructor: new p5.LowPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('lowpass'). - * See p5.Filter for methods. - * - * @class p5.LowPass - * @constructor - * @extends p5.Filter - */ - p5.LowPass = function () { - p5.Filter.call(this, 'lowpass'); - }; - p5.LowPass.prototype = Object.create(p5.Filter.prototype); - /** - * Constructor: new p5.HighPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('highpass'). - * See p5.Filter for methods. - * - * @class p5.HighPass - * @constructor - * @extends p5.Filter - */ - p5.HighPass = function () { - p5.Filter.call(this, 'highpass'); - }; - p5.HighPass.prototype = Object.create(p5.Filter.prototype); - /** - * Constructor: new p5.BandPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('bandpass'). - * See p5.Filter for methods. - * - * @class p5.BandPass - * @constructor - * @extends p5.Filter - */ - p5.BandPass = function () { - p5.Filter.call(this, 'bandpass'); - }; - p5.BandPass.prototype = Object.create(p5.Filter.prototype); - return p5.Filter; -}(master, effect); -var src_eqFilter; -'use strict'; -src_eqFilter = function () { - var Filter = filter; - var p5sound = master; - /** - * EQFilter extends p5.Filter with constraints - * necessary for the p5.EQ - * - * @private - */ - var EQFilter = function (freq, res) { - Filter.call(this, 'peaking'); - this.disconnect(); - this.set(freq, res); - this.biquad.gain.value = 0; - delete this.input; - delete this.output; - delete this._drywet; - delete this.wet; - }; - EQFilter.prototype = Object.create(Filter.prototype); - EQFilter.prototype.amp = function () { - console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`'); - }; - EQFilter.prototype.drywet = function () { - console.warn('`drywet()` is not available for p5.EQ bands.'); - }; - EQFilter.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - if (this.biquad) { - this.biquad.connect(u.input ? u.input : u); - } else { - this.output.connect(u.input ? u.input : u); - } - }; - EQFilter.prototype.disconnect = function () { - if (this.biquad) { - this.biquad.disconnect(); - } - }; - EQFilter.prototype.dispose = function () { - // remove reference form soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.disconnect(); - delete this.biquad; - }; - return EQFilter; -}(filter, master); -var eq; -'use strict'; -eq = function () { - var Effect = effect; - var EQFilter = src_eqFilter; - /** - * p5.EQ is an audio effect that performs the function of a multiband - * audio equalizer. Equalization is used to adjust the balance of - * frequency compoenents of an audio signal. This process is commonly used - * in sound production and recording to change the waveform before it reaches - * a sound output device. EQ can also be used as an audio effect to create - * interesting distortions by filtering out parts of the spectrum. p5.EQ is - * built using a chain of Web Audio Biquad Filter Nodes and can be - * instantiated with 3 or 8 bands. Bands can be added or removed from - * the EQ by directly modifying p5.EQ.bands (the array that stores filters). - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.EQ - * @constructor - * @extends p5.Effect - * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 - * @return {Object} p5.EQ object - * - * @example - *
- * var eq; - * var band_names; - * var band_index; - * - * var soundFile, play; - * - * function preload() { - * soundFormats('mp3', 'ogg'); - * soundFile = loadSound('assets/beat'); - * } - * - * function setup() { - * eq = new p5.EQ(3); - * soundFile.disconnect(); - * eq.process(soundFile); - * - * band_names = ['lows','mids','highs']; - * band_index = 0; - * play = false; - * textAlign(CENTER); - * } - * - * function draw() { - * background(30); - * noStroke(); - * fill(255); - * text('click to kill',50,25); - * - * fill(255, 40, 255); - * textSize(26); - * text(band_names[band_index],50,55); - * - * fill(255); - * textSize(9); - * text('space = play/pause',50,80); - * } - * - * //If mouse is over canvas, cycle to the next band and kill the frequency - * function mouseClicked() { - * for (var i = 0; i < eq.bands.length; i++) { - * eq.bands[i].gain(0); - * } - * eq.bands[band_index].gain(-40); - * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { - * band_index === 2 ? band_index = 0 : band_index++; - * } - * } - * - * //use space bar to trigger play / pause - * function keyPressed() { - * if (key===' ') { - * play = !play - * play ? soundFile.loop() : soundFile.pause(); - * } - * } - *
- */ - p5.EQ = function (_eqsize) { - Effect.call(this); - //p5.EQ can be of size (3) or (8), defaults to 3 - _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; - var factor; - _eqsize === 3 ? factor = Math.pow(2, 3) : factor = 2; - /** - * The p5.EQ is built with abstracted p5.Filter objects. - * To modify any bands, use methods of the - * p5.Filter API, especially `gain` and `freq`. - * Bands are stored in an array, with indices 0 - 3, or 0 - 7 - * @property {Array} bands - * - */ - this.bands = []; - var freq, res; - for (var i = 0; i < _eqsize; i++) { - if (i === _eqsize - 1) { - freq = 21000; - res = 0.01; - } else if (i === 0) { - freq = 100; - res = 0.1; - } else if (i === 1) { - freq = _eqsize === 3 ? 360 * factor : 360; - res = 1; + return this; + }; + Tone.TimelineSignal.prototype.setTargetAtTime = function ( + value, + startTime, + timeConstant + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + timeConstant = Math.max(this._minOutput, timeConstant); + startTime = this.toSeconds(startTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Target, + value: value, + time: startTime, + constant: timeConstant, + }); + this._param.setTargetAtTime(value, startTime, timeConstant); + return this; + }; + Tone.TimelineSignal.prototype.setValueCurveAtTime = function ( + values, + startTime, + duration, + scaling + ) { + scaling = this.defaultArg(scaling, 1); + var floats = new Array(values.length); + for (var i = 0; i < floats.length; i++) { + floats[i] = this._fromUnits(values[i]) * scaling; + } + startTime = this.toSeconds(startTime); + duration = this.toSeconds(duration); + this._events.add({ + type: Tone.TimelineSignal.Type.Curve, + value: floats, + time: startTime, + duration: duration, + }); + this._param.setValueAtTime(floats[0], startTime); + for (var j = 1; j < floats.length; j++) { + var segmentTime = startTime + (j / (floats.length - 1)) * duration; + this._param.linearRampToValueAtTime(floats[j], segmentTime); + } + return this; + }; + Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) { + after = this.toSeconds(after); + this._events.cancel(after); + this._param.cancelScheduledValues(after); + return this; + }; + Tone.TimelineSignal.prototype.setRampPoint = function (time) { + time = this.toSeconds(time); + var val = this._toUnits(this.getValueAtTime(time)); + var before = this._searchBefore(time); + if (before && before.time === time) { + this.cancelScheduledValues(time + this.sampleTime); + } else if ( + before && + before.type === Tone.TimelineSignal.Type.Curve && + before.time + before.duration > time + ) { + this.cancelScheduledValues(time); + this.linearRampToValueAtTime(val, time); } else { - freq = this.bands[i - 1].freq() * factor; - res = 1; + var after = this._searchAfter(time); + if (after) { + this.cancelScheduledValues(time); + if (after.type === Tone.TimelineSignal.Type.Linear) { + this.linearRampToValueAtTime(val, time); + } else if (after.type === Tone.TimelineSignal.Type.Exponential) { + this.exponentialRampToValueAtTime(val, time); + } + } + this.setValueAtTime(val, time); } - this.bands[i] = this._newBand(freq, res); - if (i > 0) { - this.bands[i - 1].connect(this.bands[i].biquad); + return this; + }; + Tone.TimelineSignal.prototype.linearRampToValueBetween = function ( + value, + start, + finish + ) { + this.setRampPoint(start); + this.linearRampToValueAtTime(value, finish); + return this; + }; + Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function ( + value, + start, + finish + ) { + this.setRampPoint(start); + this.exponentialRampToValueAtTime(value, finish); + return this; + }; + Tone.TimelineSignal.prototype._searchBefore = function (time) { + return this._events.get(time); + }; + Tone.TimelineSignal.prototype._searchAfter = function (time) { + return this._events.getAfter(time); + }; + Tone.TimelineSignal.prototype.getValueAtTime = function (time) { + time = this.toSeconds(time); + var after = this._searchAfter(time); + var before = this._searchBefore(time); + var value = this._initial; + if (before === null) { + value = this._initial; + } else if (before.type === Tone.TimelineSignal.Type.Target) { + var previous = this._events.getBefore(before.time); + var previouVal; + if (previous === null) { + previouVal = this._initial; + } else { + previouVal = previous.value; + } + value = this._exponentialApproach( + before.time, + previouVal, + before.value, + before.constant, + time + ); + } else if (before.type === Tone.TimelineSignal.Type.Curve) { + value = this._curveInterpolate( + before.time, + before.value, + before.duration, + time + ); + } else if (after === null) { + value = before.value; + } else if (after.type === Tone.TimelineSignal.Type.Linear) { + value = this._linearInterpolate( + before.time, + before.value, + after.time, + after.value, + time + ); + } else if (after.type === Tone.TimelineSignal.Type.Exponential) { + value = this._exponentialInterpolate( + before.time, + before.value, + after.time, + after.value, + time + ); } else { - this.input.connect(this.bands[i].biquad); + value = before.value; } - } - this.bands[_eqsize - 1].connect(this.output); - }; - p5.EQ.prototype = Object.create(Effect.prototype); - /** - * Process an input by connecting it to the EQ - * @method process - * @param {Object} src Audio source - */ - p5.EQ.prototype.process = function (src) { - src.connect(this.input); - }; - // /** - // * Set the frequency and gain of each band in the EQ. This method should be - // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. - // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); - // * - // * @method set - // * @param {Number} [freq0] Frequency value for band with index 0 - // * @param {Number} [gain0] Gain value for band with index 0 - // * @param {Number} [freq1] Frequency value for band with index 1 - // * @param {Number} [gain1] Gain value for band with index 1 - // * @param {Number} [freq2] Frequency value for band with index 2 - // * @param {Number} [gain2] Gain value for band with index 2 - // * @param {Number} [freq3] Frequency value for band with index 3 - // * @param {Number} [gain3] Gain value for band with index 3 - // * @param {Number} [freq4] Frequency value for band with index 4 - // * @param {Number} [gain4] Gain value for band with index 4 - // * @param {Number} [freq5] Frequency value for band with index 5 - // * @param {Number} [gain5] Gain value for band with index 5 - // * @param {Number} [freq6] Frequency value for band with index 6 - // * @param {Number} [gain6] Gain value for band with index 6 - // * @param {Number} [freq7] Frequency value for band with index 7 - // * @param {Number} [gain7] Gain value for band with index 7 - // */ - p5.EQ.prototype.set = function () { - if (arguments.length === this.bands.length * 2) { - for (var i = 0; i < arguments.length; i += 2) { - this.bands[i / 2].freq(arguments[i]); - this.bands[i / 2].gain(arguments[i + 1]); + return value; + }; + Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect; + Tone.TimelineSignal.prototype._exponentialApproach = function ( + t0, + v0, + v1, + timeConstant, + t + ) { + return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant); + }; + Tone.TimelineSignal.prototype._linearInterpolate = function ( + t0, + v0, + t1, + v1, + t + ) { + return v0 + (v1 - v0) * ((t - t0) / (t1 - t0)); + }; + Tone.TimelineSignal.prototype._exponentialInterpolate = function ( + t0, + v0, + t1, + v1, + t + ) { + v0 = Math.max(this._minOutput, v0); + return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0)); + }; + Tone.TimelineSignal.prototype._curveInterpolate = function ( + start, + curve, + duration, + time + ) { + var len = curve.length; + if (time >= start + duration) { + return curve[len - 1]; + } else if (time <= start) { + return curve[0]; + } else { + var progress = (time - start) / duration; + var lowerIndex = Math.floor((len - 1) * progress); + var upperIndex = Math.ceil((len - 1) * progress); + var lowerVal = curve[lowerIndex]; + var upperVal = curve[upperIndex]; + if (upperIndex === lowerIndex) { + return lowerVal; + } else { + return this._linearInterpolate( + lowerIndex, + lowerVal, + upperIndex, + upperVal, + progress * (len - 1) + ); + } } - } else { - console.error('Argument mismatch. .set() should be called with ' + this.bands.length * 2 + ' arguments. (one frequency and gain value pair for each band of the eq)'); - } - }; - /** - * Add a new band. Creates a p5.Filter and strips away everything but - * the raw biquad filter. This method returns an abstracted p5.Filter, - * which can be added to p5.EQ.bands, in order to create new EQ bands. - * @private - * @method _newBand - * @param {Number} freq - * @param {Number} res - * @return {Object} Abstracted Filter - */ - p5.EQ.prototype._newBand = function (freq, res) { - return new EQFilter(freq, res); - }; - p5.EQ.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.bands) { - while (this.bands.length > 0) { - delete this.bands.pop().dispose(); - } - delete this.bands; - } - }; - return p5.EQ; -}(effect, src_eqFilter); -var panner3d; -'use strict'; -panner3d = function () { - var p5sound = master; - var Effect = effect; - /** - * Panner3D is based on the - * Web Audio Spatial Panner Node. - * This panner is a spatial processing node that allows audio to be positioned - * and oriented in 3D space. - * - * The position is relative to an - * Audio Context Listener, which can be accessed - * by p5.soundOut.audiocontext.listener - * - * - * @class p5.Panner3D - * @constructor - */ - p5.Panner3D = function () { - Effect.call(this); - /** - * - * Web Audio Spatial Panner Node - * - * Properties include - * - panningModel: "equal power" or "HRTF" - * - distanceModel: "linear", "inverse", or "exponential" - * - * @property {AudioNode} panner - * - */ - this.panner = this.ac.createPanner(); - this.panner.panningModel = 'HRTF'; - this.panner.distanceModel = 'linear'; - this.panner.connect(this.output); - this.input.connect(this.panner); - }; - p5.Panner3D.prototype = Object.create(Effect.prototype); - /** - * Connect an audio sorce - * - * @method process - * @param {Object} src Input source - */ - p5.Panner3D.prototype.process = function (src) { - src.connect(this.input); - }; - /** - * Set the X,Y,Z position of the Panner - * @method set - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ - p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [ - this.panner.positionX.value, - this.panner.positionY.value, - this.panner.positionZ.value - ]; - }; - /** - * Getter and setter methods for position coordinates - * @method positionX - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for position coordinates - * @method positionY - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for position coordinates - * @method positionZ - * @return {Number} updated coordinate value - */ - p5.Panner3D.prototype.positionX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.panner.positionX.value = xVal; - this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.positionX); - } - return this.panner.positionX.value; - }; - p5.Panner3D.prototype.positionY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.panner.positionY.value = yVal; - this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.positionY); - } - return this.panner.positionY.value; - }; - p5.Panner3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.panner.positionZ.value = zVal; - this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.positionZ); - } - return this.panner.positionZ.value; - }; - /** - * Set the X,Y,Z position of the Panner - * @method orient - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ - p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) { - this.orientX(xVal, time); - this.orientY(yVal, time); - this.orientZ(zVal, time); - return [ - this.panner.orientationX.value, - this.panner.orientationY.value, - this.panner.orientationZ.value - ]; - }; - /** - * Getter and setter methods for orient coordinates - * @method orientX - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for orient coordinates - * @method orientY - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for orient coordinates - * @method orientZ - * @return {Number} updated coordinate value - */ - p5.Panner3D.prototype.orientX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.panner.orientationX.value = xVal; - this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.orientationX); - } - return this.panner.orientationX.value; - }; - p5.Panner3D.prototype.orientY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.panner.orientationY.value = yVal; - this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.orientationY); - } - return this.panner.orientationY.value; - }; - p5.Panner3D.prototype.orientZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.panner.orientationZ.value = zVal; - this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.orientationZ); - } - return this.panner.orientationZ.value; - }; - /** - * Set the rolloff factor and max distance - * @method setFalloff - * @param {Number} [maxDistance] - * @param {Number} [rolloffFactor] - */ - p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) { - this.maxDist(maxDistance); - this.rolloff(rolloffFactor); - }; - /** - * Maxium distance between the source and the listener - * @method maxDist - * @param {Number} maxDistance - * @return {Number} updated value - */ - p5.Panner3D.prototype.maxDist = function (maxDistance) { - if (typeof maxDistance === 'number') { - this.panner.maxDistance = maxDistance; - } - return this.panner.maxDistance; - }; - /** - * How quickly the volume is reduced as the source moves away from the listener - * @method rollof - * @param {Number} rolloffFactor - * @return {Number} updated value - */ - p5.Panner3D.prototype.rolloff = function (rolloffFactor) { - if (typeof rolloffFactor === 'number') { - this.panner.rolloffFactor = rolloffFactor; - } - return this.panner.rolloffFactor; - }; - p5.Panner3D.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.panner) { - this.panner.disconnect(); - delete this.panner; - } - }; - return p5.Panner3D; -}(master, effect); -var listener3d; -'use strict'; -listener3d = function () { - var p5sound = master; - var Effect = effect; - // /** - // * listener is a class that can construct both a Spatial Panner - // * and a Spatial Listener. The panner is based on the - // * Web Audio Spatial Panner Node - // * https://www.w3.org/TR/webaudio/#the-listenernode-interface - // * This panner is a spatial processing node that allows audio to be positioned - // * and oriented in 3D space. - // * - // * The Listener modifies the properties of the Audio Context Listener. - // * Both objects types use the same methods. The default is a spatial panner. - // * - // * p5.Panner3D - Constructs a Spatial Panner
- // * p5.Listener3D - Constructs a Spatial Listener
- // * - // * @class listener - // * @constructor - // * @return {Object} p5.Listener3D Object - // * - // * @param {Web Audio Node} listener Web Audio Spatial Panning Node - // * @param {AudioParam} listener.panningModel "equal power" or "HRTF" - // * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential" - // * @param {String} [type] [Specify construction of a spatial panner or listener] - // */ - p5.Listener3D = function (type) { - this.ac = p5sound.audiocontext; - this.listener = this.ac.listener; - }; - // /** - // * Connect an audio sorce - // * @param {Object} src Input source - // */ - p5.Listener3D.prototype.process = function (src) { - src.connect(this.input); - }; - // /** - // * Set the X,Y,Z position of the Panner - // * @param {[Number]} xVal - // * @param {[Number]} yVal - // * @param {[Number]} zVal - // * @param {[Number]} time - // * @return {[Array]} [Updated x, y, z values as an array] - // */ - p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [ - this.listener.positionX.value, - this.listener.positionY.value, - this.listener.positionZ.value - ]; - }; - // /** - // * Getter and setter methods for position coordinates - // * @return {Number} [updated coordinate value] - // */ - p5.Listener3D.prototype.positionX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.positionX.value = xVal; - this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.positionX); - } - return this.listener.positionX.value; - }; - p5.Listener3D.prototype.positionY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.positionY.value = yVal; - this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.positionY); - } - return this.listener.positionY.value; - }; - p5.Listener3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.positionZ.value = zVal; - this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.positionZ); - } - return this.listener.positionZ.value; - }; - // cannot define method when class definition is commented - // /** - // * Overrides the listener orient() method because Listener has slightly - // * different params. In human terms, Forward vectors are the direction the - // * nose is pointing. Up vectors are the direction of the top of the head. - // * - // * @method orient - // * @param {Number} xValF Forward vector X direction - // * @param {Number} yValF Forward vector Y direction - // * @param {Number} zValF Forward vector Z direction - // * @param {Number} xValU Up vector X direction - // * @param {Number} yValU Up vector Y direction - // * @param {Number} zValU Up vector Z direction - // * @param {Number} time - // * @return {Array} All orienation params - // */ - p5.Listener3D.prototype.orient = function (xValF, yValF, zValF, xValU, yValU, zValU, time) { - if (arguments.length === 3 || arguments.length === 4) { - time = arguments[3]; - this.orientForward(xValF, yValF, zValF, time); - } else if (arguments.length === 6 || arguments === 7) { - this.orientForward(xValF, yValF, zValF); - this.orientUp(xValU, yValU, zValU, time); - } - return [ - this.listener.forwardX.value, - this.listener.forwardY.value, - this.listener.forwardZ.value, - this.listener.upX.value, - this.listener.upY.value, - this.listener.upZ.value - ]; - }; - p5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) { - this.forwardX(xValF, time); - this.forwardY(yValF, time); - this.forwardZ(zValF, time); - return [ - this.listener.forwardX, - this.listener.forwardY, - this.listener.forwardZ - ]; - }; - p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) { - this.upX(xValU, time); - this.upY(yValU, time); - this.upZ(zValU, time); - return [ - this.listener.upX, - this.listener.upY, - this.listener.upZ - ]; - }; - // /** - // * Getter and setter methods for orient coordinates - // * @return {Number} [updated coordinate value] - // */ - p5.Listener3D.prototype.forwardX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.forwardX.value = xVal; - this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.forwardX); - } - return this.listener.forwardX.value; - }; - p5.Listener3D.prototype.forwardY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.forwardY.value = yVal; - this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.forwardY); - } - return this.listener.forwardY.value; - }; - p5.Listener3D.prototype.forwardZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.forwardZ.value = zVal; - this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.forwardZ); - } - return this.listener.forwardZ.value; - }; - p5.Listener3D.prototype.upX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.upX.value = xVal; - this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.upX); - } - return this.listener.upX.value; - }; - p5.Listener3D.prototype.upY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.upY.value = yVal; - this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.upY); - } - return this.listener.upY.value; - }; - p5.Listener3D.prototype.upZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.upZ.value = zVal; - this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.upZ); - } - return this.listener.upZ.value; - }; - return p5.Listener3D; -}(master, effect); -var delay; -'use strict'; -delay = function () { - var Filter = filter; - var Effect = effect; - /** - * Delay is an echo effect. It processes an existing sound source, - * and outputs a delayed version of that sound. The p5.Delay can - * produce different effects depending on the delayTime, feedback, - * filter, and type. In the example below, a feedback of 0.5 (the - * defaul value) will produce a looping delay that decreases in - * volume by 50% each repeat. A filter will cut out the high - * frequencies so that the delay does not sound as piercing as the - * original source. - * - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * @class p5.Delay - * @extends p5.Effect - * @constructor - * @example - *
- * var noise, env, delay; - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * noise = new p5.Noise('brown'); - * noise.amp(0); - * noise.start(); - * - * delay = new p5.Delay(); - * - * // delay.process() accepts 4 parameters: - * // source, delayTime, feedback, filter frequency - * // play with these numbers!! - * delay.process(noise, .12, .7, 2300); - * - * // play the noise with an envelope, - * // a series of fades ( time / value pairs ) - * env = new p5.Envelope(.01, 0.2, .2, .1); - * } - * - * // mouseClick triggers envelope - * function mouseClicked() { - * // is mouse over canvas? - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * env.play(noise); - * } - * } - *
- */ - p5.Delay = function () { - Effect.call(this); - this._split = this.ac.createChannelSplitter(2); - this._merge = this.ac.createChannelMerger(2); - this._leftGain = this.ac.createGain(); - this._rightGain = this.ac.createGain(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * - * @property {DelayNode} leftDelay - */ - this.leftDelay = this.ac.createDelay(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * - * @property {DelayNode} rightDelay - */ - this.rightDelay = this.ac.createDelay(); - this._leftFilter = new Filter(); - this._rightFilter = new Filter(); - this._leftFilter.disconnect(); - this._rightFilter.disconnect(); - this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); - this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); - this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); - this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); - // graph routing - this.input.connect(this._split); - this.leftDelay.connect(this._leftGain); - this.rightDelay.connect(this._rightGain); - this._leftGain.connect(this._leftFilter.input); - this._rightGain.connect(this._rightFilter.input); - this._merge.connect(this.wet); - this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); - this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); - // default routing - this.setType(0); - this._maxDelay = this.leftDelay.delayTime.maxValue; - // set initial feedback to 0.5 - this.feedback(0.5); - }; - p5.Delay.prototype = Object.create(Effect.prototype); - /** - * Add delay to an audio signal according to a set - * of delay parameters. - * - * @method process - * @param {Object} Signal An object that outputs audio - * @param {Number} [delayTime] Time (in seconds) of the delay/echo. - * Some browsers limit delayTime to - * 1 second. - * @param {Number} [feedback] sends the delay back through itself - * in a loop that decreases in volume - * each time. - * @param {Number} [lowPass] Cutoff frequency. Only frequencies - * below the lowPass will be part of the - * delay. - */ - p5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) { - var feedback = _feedback || 0; - var delayTime = _delayTime || 0; - if (feedback >= 1) { - throw new Error('Feedback value will force a positive feedback loop.'); - } - if (delayTime >= this._maxDelay) { - throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'); - } - src.connect(this.input); - this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this._leftGain.gain.value = feedback; - this._rightGain.gain.value = feedback; - if (_filter) { - this._leftFilter.freq(_filter); - this._rightFilter.freq(_filter); - } - }; - /** - * Set the delay (echo) time, in seconds. Usually this value will be - * a floating point number between 0.0 and 1.0. - * - * @method delayTime - * @param {Number} delayTime Time (in seconds) of the delay - */ - p5.Delay.prototype.delayTime = function (t) { - // if t is an audio node... - if (typeof t !== 'number') { - t.connect(this.leftDelay.delayTime); - t.connect(this.rightDelay.delayTime); - } else { - this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime); - this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime); - this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime); - this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime); - } - }; - /** - * Feedback occurs when Delay sends its signal back through its input - * in a loop. The feedback amount determines how much signal to send each - * time through the loop. A feedback greater than 1.0 is not desirable because - * it will increase the overall output each time through the loop, - * creating an infinite feedback loop. The default value is 0.5 - * - * @method feedback - * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an - * Oscillator that can be used to - * modulate this param - * @returns {Number} Feedback value - * - */ - p5.Delay.prototype.feedback = function (f) { - // if f is an audio node... - if (f && typeof f !== 'number') { - f.connect(this._leftGain.gain); - f.connect(this._rightGain.gain); - } else if (f >= 1) { - throw new Error('Feedback value will force a positive feedback loop.'); - } else if (typeof f === 'number') { - this._leftGain.gain.value = f; - this._rightGain.gain.value = f; - } - // return value of feedback - return this._leftGain.gain.value; - }; - /** - * Set a lowpass filter frequency for the delay. A lowpass filter - * will cut off any frequencies higher than the filter frequency. - * - * @method filter - * @param {Number|Object} cutoffFreq A lowpass filter will cut off any - * frequencies higher than the filter frequency. - * @param {Number|Object} res Resonance of the filter frequency - * cutoff, or an object (i.e. a p5.Oscillator) - * that can be used to modulate this parameter. - * High numbers (i.e. 15) will produce a resonance, - * low numbers (i.e. .2) will produce a slope. - */ - p5.Delay.prototype.filter = function (freq, q) { - this._leftFilter.set(freq, q); - this._rightFilter.set(freq, q); - }; - /** - * Choose a preset type of delay. 'pingPong' bounces the signal - * from the left to the right channel to produce a stereo effect. - * Any other parameter will revert to the default delay setting. - * - * @method setType - * @param {String|Number} type 'pingPong' (1) or 'default' (0) - */ - p5.Delay.prototype.setType = function (t) { - if (t === 1) { - t = 'pingPong'; - } - this._split.disconnect(); - this._leftFilter.disconnect(); - this._rightFilter.disconnect(); - this._split.connect(this.leftDelay, 0); - this._split.connect(this.rightDelay, 1); - switch (t) { - case 'pingPong': - this._rightFilter.setType(this._leftFilter.biquad.type); - this._leftFilter.output.connect(this._merge, 0, 0); - this._rightFilter.output.connect(this._merge, 0, 1); - this._leftFilter.output.connect(this.rightDelay); - this._rightFilter.output.connect(this.leftDelay); - break; - default: - this._leftFilter.output.connect(this._merge, 0, 0); - this._rightFilter.output.connect(this._merge, 0, 1); - this._leftFilter.output.connect(this.leftDelay); - this._rightFilter.output.connect(this.rightDelay); - } - }; - // DocBlocks for methods inherited from p5.Effect - /** - * Set the output level of the delay effect. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Delay.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - this._split.disconnect(); - this._leftFilter.dispose(); - this._rightFilter.dispose(); - this._merge.disconnect(); - this._leftGain.disconnect(); - this._rightGain.disconnect(); - this.leftDelay.disconnect(); - this.rightDelay.disconnect(); - this._split = undefined; - this._leftFilter = undefined; - this._rightFilter = undefined; - this._merge = undefined; - this._leftGain = undefined; - this._rightGain = undefined; - this.leftDelay = undefined; - this.rightDelay = undefined; - }; -}(filter, effect); -var reverb; -'use strict'; -reverb = function () { - var CustomError = errorHandler; - var Effect = effect; - /** - * Reverb adds depth to a sound through a large number of decaying - * echoes. It creates the perception that sound is occurring in a - * physical space. The p5.Reverb has paramters for Time (how long does the - * reverb last) and decayRate (how much the sound decays with each echo) - * that can be set with the .set() or .process() methods. The p5.Convolver - * extends p5.Reverb allowing you to recreate the sound of actual physical - * spaces through convolution. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Reverb - * @extends p5.Effect - * @constructor - * @example - *
- * var soundFile, reverb; - * function preload() { - * soundFile = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * reverb = new p5.Reverb(); - * soundFile.disconnect(); // so we'll only hear reverb... - * - * // connect soundFile to reverb, process w/ - * // 3 second reverbTime, decayRate of 2% - * reverb.process(soundFile, 3, 2); - * soundFile.play(); - * } - *
- */ - p5.Reverb = function () { - Effect.call(this); - this._initConvolverNode(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - // default params - this._seconds = 3; - this._decay = 2; - this._reverse = false; - this._buildImpulse(); - }; - p5.Reverb.prototype = Object.create(Effect.prototype); - p5.Reverb.prototype._initConvolverNode = function () { - this.convolverNode = this.ac.createConvolver(); - this.input.connect(this.convolverNode); - this.convolverNode.connect(this.wet); - }; - p5.Reverb.prototype._teardownConvolverNode = function () { - if (this.convolverNode) { - this.convolverNode.disconnect(); - delete this.convolverNode; - } - }; - p5.Reverb.prototype._setBuffer = function (audioBuffer) { - this._teardownConvolverNode(); - this._initConvolverNode(); - this.convolverNode.buffer = audioBuffer; - }; - /** - * Connect a source to the reverb, and assign reverb parameters. - * - * @method process - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ - p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) { - src.connect(this.input); - var rebuild = false; - if (seconds) { - this._seconds = seconds; - rebuild = true; - } - if (decayRate) { - this._decay = decayRate; - } - if (reverse) { - this._reverse = reverse; - } - if (rebuild) { - this._buildImpulse(); - } - }; - /** - * Set the reverb settings. Similar to .process(), but without - * assigning a new input. - * - * @method set - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ - p5.Reverb.prototype.set = function (seconds, decayRate, reverse) { - var rebuild = false; - if (seconds) { - this._seconds = seconds; - rebuild = true; - } - if (decayRate) { - this._decay = decayRate; - } - if (reverse) { - this._reverse = reverse; - } - if (rebuild) { - this._buildImpulse(); - } - }; - // DocBlocks for methods inherited from p5.Effect - /** - * Set the output level of the reverb effect. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - /** - * Disconnect all output. - * - * @method disconnect - */ - /** - * Inspired by Simple Reverb by Jordan Santell - * https://github.com/web-audio-components/simple-reverb/blob/master/index.js - * - * Utility function for building an impulse response - * based on the module parameters. - * - * @private - */ - p5.Reverb.prototype._buildImpulse = function () { - var rate = this.ac.sampleRate; - var length = rate * this._seconds; - var decay = this._decay; - var impulse = this.ac.createBuffer(2, length, rate); - var impulseL = impulse.getChannelData(0); - var impulseR = impulse.getChannelData(1); - var n, i; - for (i = 0; i < length; i++) { - n = this._reverse ? length - i : i; - impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - } - this._setBuffer(impulse); - }; - p5.Reverb.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - this._teardownConvolverNode(); - }; - // ======================================================================= - // *** p5.Convolver *** - // ======================================================================= - /** - *

p5.Convolver extends p5.Reverb. It can emulate the sound of real - * physical spaces through a process called - * convolution.

- * - *

Convolution multiplies any audio input by an "impulse response" - * to simulate the dispersion of sound over time. The impulse response is - * generated from an audio file that you provide. One way to - * generate an impulse response is to pop a balloon in a reverberant space - * and record the echo. Convolution can also be used to experiment with - * sound.

- * - *

Use the method createConvolution(path) to instantiate a - * p5.Convolver with a path to your impulse response audio file.

- * - * @class p5.Convolver - * @extends p5.Effect - * @constructor - * @param {String} path path to a sound file - * @param {Function} [callback] function to call when loading succeeds - * @param {Function} [errorCallback] function to call if loading fails. - * This function will receive an error or - * XMLHttpRequest object with information - * about what went wrong. - * @example - *
- * var cVerb, sound; - * function preload() { - * // We have both MP3 and OGG versions of all sound assets - * soundFormats('ogg', 'mp3'); - * - * // Try replacing 'bx-spring' with other soundfiles like - * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' - * cVerb = createConvolver('assets/bx-spring.mp3'); - * - * // Try replacing 'Damscray_DancingTiger' with - * // 'beat', 'doorbell', lucky_dragons_-_power_melody' - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.Convolver = function (path, callback, errorCallback) { - p5.Reverb.call(this); + }; + Tone.TimelineSignal.prototype.dispose = function () { + Tone.Signal.prototype.dispose.call(this); + Tone.Param.prototype.dispose.call(this); + this._events.dispose(); + this._events = null; + }; + return Tone.TimelineSignal; + })(Tone_core_Tone, Tone_signal_Signal); + var envelope; + ("use strict"); + envelope = (function () { + var p5sound = master; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + var TimelineSignal = Tone_signal_TimelineSignal; /** - * Internally, the p5.Convolver uses the a - * - * Web Audio Convolver Node. + *

Envelopes are pre-defined amplitude distribution over time. + * Typically, envelopes are used to control the output volume + * of an object, a series of fades referred to as Attack, Decay, + * Sustain and Release ( + * ADSR + * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can + * control an Oscillator's frequency like this: osc.freq(env).

+ *

Use setRange to change the attack/release level. + * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

+ *

Use the play method to play the entire envelope, + * the ramp method for a pingable trigger, + * or triggerAttack/ + * triggerRelease to trigger noteOn/noteOff.

+ * + * @class p5.Envelope + * @constructor + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); * - * @property {ConvolverNode} convolverNode + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
*/ - this._initConvolverNode(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - if (path) { - this.impulses = []; - this._loadBuffer(path, callback, errorCallback); - } else { - // parameters - this._seconds = 3; - this._decay = 2; - this._reverse = false; - this._buildImpulse(); - } - }; - p5.Convolver.prototype = Object.create(p5.Reverb.prototype); - p5.prototype.registerPreloadMethod('createConvolver', p5.prototype); - /** - * Create a p5.Convolver. Accepts a path to a soundfile - * that will be used to generate an impulse response. - * - * @method createConvolver - * @param {String} path path to a sound file - * @param {Function} [callback] function to call if loading is successful. - * The object will be passed in as the argument - * to the callback function. - * @param {Function} [errorCallback] function to call if loading is not successful. - * A custom error will be passed in as the argument - * to the callback function. - * @return {p5.Convolver} - * @example - *
- * var cVerb, sound; - * function preload() { - * // We have both MP3 and OGG versions of all sound assets - * soundFormats('ogg', 'mp3'); - * - * // Try replacing 'bx-spring' with other soundfiles like - * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' - * cVerb = createConvolver('assets/bx-spring.mp3'); - * - * // Try replacing 'Damscray_DancingTiger' with - * // 'beat', 'doorbell', lucky_dragons_-_power_melody' - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.prototype.createConvolver = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - var self = this; - var cReverb = new p5.Convolver(path, function (buffer) { - if (typeof callback === 'function') { - callback(buffer); - } - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); - } - }, errorCallback); - cReverb.impulses = []; - return cReverb; - }; - /** - * Private method to load a buffer as an Impulse Response, - * assign it to the convolverNode, and add to the Array of .impulses. - * - * @param {String} path - * @param {Function} callback - * @param {Function} errorCallback - * @private - */ - p5.Convolver.prototype._loadBuffer = function (path, callback, errorCallback) { - var path = p5.prototype._checkFileFormats(path); - var self = this; - var errorTrace = new Error().stack; - var ac = p5.prototype.getAudioContext(); - var request = new XMLHttpRequest(); - request.open('GET', path, true); - request.responseType = 'arraybuffer'; - request.onload = function () { - if (request.status === 200) { - // on success loading file: - ac.decodeAudioData(request.response, function (buff) { - var buffer = {}; - var chunks = path.split('/'); - buffer.name = chunks[chunks.length - 1]; - buffer.audioBuffer = buff; - self.impulses.push(buffer); - self._setBuffer(buffer.audioBuffer); - if (callback) { - callback(buffer); - } - }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 - function () { - var err = new CustomError('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; - if (errorCallback) { - err.msg = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }); - } else { - var err = new CustomError('loadConvolver', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - } + p5.Envelope = function (t1, l1, t2, l2, t3, l3) { + /** + * Time until envelope reaches attackLevel + * @property attackTime + */ + this.aTime = t1 || 0.1; + /** + * Level once attack is complete. + * @property attackLevel + */ + this.aLevel = l1 || 1; + /** + * Time until envelope reaches decayLevel. + * @property decayTime + */ + this.dTime = t2 || 0.5; + /** + * Level after decay. The envelope will sustain here until it is released. + * @property decayLevel + */ + this.dLevel = l2 || 0; + /** + * Duration of the release portion of the envelope. + * @property releaseTime + */ + this.rTime = t3 || 0; + /** + * Level at the end of the release. + * @property releaseLevel + */ + this.rLevel = l3 || 0; + this._rampHighPercentage = 0.98; + this._rampLowPercentage = 0.02; + this.output = p5sound.audiocontext.createGain(); + this.control = new TimelineSignal(); + this._init(); + // this makes sure the envelope starts at zero + this.control.connect(this.output); + // connect to the output + this.connection = null; + // store connection + //array of math operation signal chaining + this.mathOps = [this.control]; + //whether envelope should be linear or exponential curve + this.isExponential = false; + // oscillator or buffer source to clear on env complete + // to save resources if/when it is retriggered + this.sourceToClear = null; + // set to true if attack is set, then false on release + this.wasTriggered = false; + // add to the soundArray so we can dispose of the env later + p5sound.soundArray.push(this); }; - // if there is another error, aside from 404... - request.onerror = function () { - var err = new CustomError('loadConvolver', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } + // this init function just smooths the starting value to zero and gives a start point for the timeline + // - it was necessary to remove glitches at the beginning. + p5.Envelope.prototype._init = function () { + var now = p5sound.audiocontext.currentTime; + var t = now; + this.control.setTargetAtTime(0.00001, t, 0.001); + //also, compute the correct time constants + this._setRampAD(this.aTime, this.dTime); }; - request.send(); - }; - p5.Convolver.prototype.set = null; - /** - * Connect a source to the reverb, and assign reverb parameters. - * - * @method process - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - * @example - *
- * var cVerb, sound; - * function preload() { - * soundFormats('ogg', 'mp3'); - * - * cVerb = createConvolver('assets/concrete-tunnel.mp3'); - * - * sound = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with (i.e. connect to) cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.Convolver.prototype.process = function (src) { - src.connect(this.input); - }; - /** - * If you load multiple impulse files using the .addImpulse method, - * they will be stored as Objects in this Array. Toggle between them - * with the toggleImpulse(id) method. - * - * @property {Array} impulses - */ - p5.Convolver.prototype.impulses = []; - /** - * Load and assign a new Impulse Response to the p5.Convolver. - * The impulse is added to the .impulses array. Previous - * impulses can be accessed with the .toggleImpulse(id) - * method. - * - * @method addImpulse - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - p5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - this._loadBuffer(path, callback, errorCallback); - }; - /** - * Similar to .addImpulse, except that the .impulses - * Array is reset to save memory. A new .impulses - * array is created with this impulse as the only item. - * - * @method resetImpulse - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - p5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - this.impulses = []; - this._loadBuffer(path, callback, errorCallback); - }; - /** - * If you have used .addImpulse() to add multiple impulses - * to a p5.Convolver, then you can use this method to toggle between - * the items in the .impulses Array. Accepts a parameter - * to identify which impulse you wish to use, identified either by its - * original filename (String) or by its position in the .impulses - * Array (Number).
- * You can access the objects in the .impulses Array directly. Each - * Object has two attributes: an .audioBuffer (type: - * Web Audio - * AudioBuffer) and a .name, a String that corresponds - * with the original filename. - * - * @method toggleImpulse - * @param {String|Number} id Identify the impulse by its original filename - * (String), or by its position in the - * .impulses Array (Number). - */ - p5.Convolver.prototype.toggleImpulse = function (id) { - if (typeof id === 'number' && id < this.impulses.length) { - this._setBuffer(this.impulses[id].audioBuffer); - } - if (typeof id === 'string') { - for (var i = 0; i < this.impulses.length; i++) { - if (this.impulses[i].name === id) { - this._setBuffer(this.impulses[i].audioBuffer); - break; - } - } - } - }; - p5.Convolver.prototype.dispose = function () { - p5.Reverb.prototype.dispose.apply(this); - // remove all the Impulse Response buffers - for (var i in this.impulses) { - if (this.impulses[i]) { - this.impulses[i] = null; - } - } - }; -}(errorHandler, effect); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_TimelineState; -Tone_core_TimelineState = function (Tone) { - 'use strict'; - Tone.TimelineState = function (initial) { - Tone.Timeline.call(this); - this._initial = initial; - }; - Tone.extend(Tone.TimelineState, Tone.Timeline); - Tone.TimelineState.prototype.getValueAtTime = function (time) { - var event = this.get(time); - if (event !== null) { - return event.state; - } else { - return this._initial; - } - }; - Tone.TimelineState.prototype.setStateAtTime = function (state, time) { - this.add({ - 'state': state, - 'time': time - }); - }; - return Tone.TimelineState; -}(Tone_core_Tone, Tone_core_Timeline); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Clock; -Tone_core_Clock = function (Tone) { - 'use strict'; - Tone.Clock = function () { - Tone.Emitter.call(this); - var options = this.optionsObject(arguments, [ - 'callback', - 'frequency' - ], Tone.Clock.defaults); - this.callback = options.callback; - this._nextTick = 0; - this._lastState = Tone.State.Stopped; - this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency); - this._readOnly('frequency'); - this.ticks = 0; - this._state = new Tone.TimelineState(Tone.State.Stopped); - this._boundLoop = this._loop.bind(this); - this.context.on('tick', this._boundLoop); - }; - Tone.extend(Tone.Clock, Tone.Emitter); - Tone.Clock.defaults = { - 'callback': Tone.noOp, - 'frequency': 1, - 'lookAhead': 'auto' - }; - Object.defineProperty(Tone.Clock.prototype, 'state', { - get: function () { - return this._state.getValueAtTime(this.now()); - } - }); - Tone.Clock.prototype.start = function (time, offset) { - time = this.toSeconds(time); - if (this._state.getValueAtTime(time) !== Tone.State.Started) { - this._state.add({ - 'state': Tone.State.Started, - 'time': time, - 'offset': offset - }); - } - return this; - }; - Tone.Clock.prototype.stop = function (time) { - time = this.toSeconds(time); - this._state.cancel(time); - this._state.setStateAtTime(Tone.State.Stopped, time); - return this; - }; - Tone.Clock.prototype.pause = function (time) { - time = this.toSeconds(time); - if (this._state.getValueAtTime(time) === Tone.State.Started) { - this._state.setStateAtTime(Tone.State.Paused, time); - } - return this; - }; - Tone.Clock.prototype._loop = function () { - var now = this.now(); - var lookAhead = this.context.lookAhead; - var updateInterval = this.context.updateInterval; - var lagCompensation = this.context.lag * 2; - var loopInterval = now + lookAhead + updateInterval + lagCompensation; - while (loopInterval > this._nextTick && this._state) { - var currentState = this._state.getValueAtTime(this._nextTick); - if (currentState !== this._lastState) { - this._lastState = currentState; - var event = this._state.get(this._nextTick); - if (currentState === Tone.State.Started) { - this._nextTick = event.time; - if (!this.isUndef(event.offset)) { - this.ticks = event.offset; - } - this.emit('start', event.time, this.ticks); - } else if (currentState === Tone.State.Stopped) { - this.ticks = 0; - this.emit('stop', event.time); - } else if (currentState === Tone.State.Paused) { - this.emit('pause', event.time); - } - } - var tickTime = this._nextTick; - if (this.frequency) { - this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick); - if (currentState === Tone.State.Started) { - this.callback(tickTime); - this.ticks++; - } - } - } - }; - Tone.Clock.prototype.getStateAtTime = function (time) { - time = this.toSeconds(time); - return this._state.getValueAtTime(time); - }; - Tone.Clock.prototype.dispose = function () { - Tone.Emitter.prototype.dispose.call(this); - this.context.off('tick', this._boundLoop); - this._writable('frequency'); - this.frequency.dispose(); - this.frequency = null; - this._boundLoop = null; - this._nextTick = Infinity; - this.callback = null; - this._state.dispose(); - this._state = null; - }; - return Tone.Clock; -}(Tone_core_Tone, Tone_signal_TimelineSignal, Tone_core_TimelineState, Tone_core_Emitter); -var metro; -'use strict'; -metro = function () { - var p5sound = master; - // requires the Tone.js library's Clock (MIT license, Yotam Mann) - // https://github.com/TONEnoTONE/Tone.js/ - var Clock = Tone_core_Clock; - p5.Metro = function () { - this.clock = new Clock({ 'callback': this.ontick.bind(this) }); - this.syncedParts = []; - this.bpm = 120; - // gets overridden by p5.Part - this._init(); - this.prevTick = 0; - this.tatumTime = 0; - this.tickCallback = function () { - }; - }; - p5.Metro.prototype.ontick = function (tickTime) { - var elapsedTime = tickTime - this.prevTick; - var secondsFromNow = tickTime - p5sound.audiocontext.currentTime; - if (elapsedTime - this.tatumTime <= -0.02) { - return; - } else { - // console.log('ok', this.syncedParts[0].phrases[0].name); - this.prevTick = tickTime; - // for all of the active things on the metro: - var self = this; - this.syncedParts.forEach(function (thisPart) { - if (!thisPart.isPlaying) - return; - thisPart.incrementStep(secondsFromNow); - // each synced source keeps track of its own beat number - thisPart.phrases.forEach(function (thisPhrase) { - var phraseArray = thisPhrase.sequence; - var bNum = self.metroTicks % phraseArray.length; - if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping)) { - thisPhrase.callback(secondsFromNow, phraseArray[bNum]); - } - }); - }); - this.metroTicks += 1; - this.tickCallback(secondsFromNow); - } - }; - p5.Metro.prototype.setBPM = function (bpm, rampTime) { - var beatTime = 60 / (bpm * this.tatums); - var now = p5sound.audiocontext.currentTime; - this.tatumTime = beatTime; - var rampTime = rampTime || 0; - this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); - this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); - this.bpm = bpm; - }; - p5.Metro.prototype.getBPM = function () { - return this.clock.getRate() / this.tatums * 60; - }; - p5.Metro.prototype._init = function () { - this.metroTicks = 0; - }; - // clear existing synced parts, add only this one - p5.Metro.prototype.resetSync = function (part) { - this.syncedParts = [part]; - }; - // push a new synced part to the array - p5.Metro.prototype.pushSync = function (part) { - this.syncedParts.push(part); - }; - p5.Metro.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.clock.start(now + t); - this.setBPM(this.bpm); - }; - p5.Metro.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.clock.stop(now + t); - }; - p5.Metro.prototype.beatLength = function (tatums) { - this.tatums = 1 / tatums / 4; - }; -}(master, Tone_core_Clock); -var looper; -'use strict'; -looper = function () { - var p5sound = master; - var BPM = 120; - /** - * Set the global tempo, in beats per minute, for all - * p5.Parts. This method will impact all active p5.Parts. - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} rampTime Seconds from now - */ - p5.prototype.setBPM = function (bpm, rampTime) { - BPM = bpm; - for (var i in p5sound.parts) { - if (p5sound.parts[i]) { - p5sound.parts[i].setBPM(bpm, rampTime); - } - } - }; - /** - *

A phrase is a pattern of musical events over time, i.e. - * a series of notes and rests.

- * - *

Phrases must be added to a p5.Part for playback, and - * each part can play multiple phrases at the same time. - * For example, one Phrase might be a kick drum, another - * could be a snare, and another could be the bassline.

- * - *

The first parameter is a name so that the phrase can be - * modified or deleted later. The callback is a a function that - * this phrase will call at every step—for example it might be - * called playNote(value){}. The array determines - * which value is passed into the callback at each step of the - * phrase. It can be numbers, an object with multiple numbers, - * or a zero (0) indicates a rest so the callback won't be called).

- * - * @class p5.Phrase - * @constructor - * @param {String} name Name so that you can access the Phrase. - * @param {Function} callback The name of a function that this phrase - * will call. Typically it will play a sound, - * and accept two parameters: a time at which - * to play the sound (in seconds from now), - * and a value from the sequence array. The - * time should be passed into the play() or - * start() method to ensure precision. - * @param {Array} sequence Array of values to pass into the callback - * at each step of the phrase. - * @example - *
- * var mySound, myPhrase, myPart; - * var pattern = [1,0,0,2,0,2,0,0]; - * var msg = 'click to play'; - * - * function preload() { - * mySound = loadSound('assets/beatbox.mp3'); - * } - * - * function setup() { - * noStroke(); - * fill(255); - * textAlign(CENTER); - * masterVolume(0.1); - * - * myPhrase = new p5.Phrase('bbox', makeSound, pattern); - * myPart = new p5.Part(); - * myPart.addPhrase(myPhrase); - * myPart.setBPM(60); - * } - * - * function draw() { - * background(0); - * text(msg, width/2, height/2); - * } - * - * function makeSound(time, playbackRate) { - * mySound.rate(playbackRate); - * mySound.play(time); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * myPart.start(); - * msg = 'playing pattern'; - * } - * } - * - *
- */ - p5.Phrase = function (name, callback, sequence) { - this.phraseStep = 0; - this.name = name; - this.callback = callback; /** - * Array of values to pass into the callback - * at each step of the phrase. Depending on the callback - * function's requirements, these values may be numbers, - * strings, or an object with multiple parameters. - * Zero (0) indicates a rest. + * Reset the envelope with a series of time/value pairs. + * + * @method set + * @param {Number} attackTime Time (in seconds) before level + * reaches attackLevel + * @param {Number} attackLevel Typically an amplitude between + * 0.0 and 1.0 + * @param {Number} decayTime Time + * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, + * decayLevel = sustainLevel) + * @param {Number} releaseTime Release Time (in seconds) + * @param {Number} releaseLevel Amplitude + * @example + *
+ * var t1 = 0.1; // attack time in seconds + * var l1 = 0.7; // attack level 0.0 to 1.0 + * var t2 = 0.3; // decay time in seconds + * var l2 = 0.1; // decay level 0.0 to 1.0 + * var t3 = 0.2; // sustain time in seconds + * var l3 = 0.5; // sustain level 0.0 to 1.0 + * // release level defaults to zero + * + * var env; + * var triOsc; + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(t1, l1, t2, l2, t3, l3); + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); // give the env control of the triOsc's amp + * triOsc.start(); + * } + * + * // mouseClick triggers envelope if over canvas + * function mouseClicked() { + * // is mouse over canvas? + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * env.play(triOsc); + * } + * } + *
* - * @property {Array} sequence */ - this.sequence = sequence; - }; - /** - *

A p5.Part plays back one or more p5.Phrases. Instantiate a part - * with steps and tatums. By default, each step represents a 1/16th note.

- * - *

See p5.Phrase for more about musical timing.

- * - * @class p5.Part - * @constructor - * @param {Number} [steps] Steps in the part - * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note) - * @example - *
- * var box, drum, myPart; - * var boxPat = [1,0,0,2,0,2,0,0]; - * var drumPat = [0,1,1,0,2,0,1,0]; - * var msg = 'click to play'; - * - * function preload() { - * box = loadSound('assets/beatbox.mp3'); - * drum = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * noStroke(); - * fill(255); - * textAlign(CENTER); - * masterVolume(0.1); - * - * var boxPhrase = new p5.Phrase('box', playBox, boxPat); - * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat); - * myPart = new p5.Part(); - * myPart.addPhrase(boxPhrase); - * myPart.addPhrase(drumPhrase); - * myPart.setBPM(60); - * masterVolume(0.1); - * } - * - * function draw() { - * background(0); - * text(msg, width/2, height/2); - * } - * - * function playBox(time, playbackRate) { - * box.rate(playbackRate); - * box.play(time); - * } - * - * function playDrum(time, playbackRate) { - * drum.rate(playbackRate); - * drum.play(time); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * myPart.start(); - * msg = 'playing part'; - * } - * } - *
- */ - p5.Part = function (steps, bLength) { - this.length = steps || 0; - // how many beats - this.partStep = 0; - this.phrases = []; - this.isPlaying = false; - this.noLoop(); - this.tatums = bLength || 0.0625; - // defaults to quarter note - this.metro = new p5.Metro(); - this.metro._init(); - this.metro.beatLength(this.tatums); - this.metro.setBPM(BPM); - p5sound.parts.push(this); - this.callback = function () { - }; - }; - /** - * Set the tempo of this part, in Beats Per Minute. - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} [rampTime] Seconds from now - */ - p5.Part.prototype.setBPM = function (tempo, rampTime) { - this.metro.setBPM(tempo, rampTime); - }; - /** - * Returns the tempo, in Beats Per Minute, of this part. - * - * @method getBPM - * @return {Number} - */ - p5.Part.prototype.getBPM = function () { - return this.metro.getBPM(); - }; - /** - * Start playback of this part. It will play - * through all of its phrases at a speed - * determined by setBPM. - * - * @method start - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.start = function (time) { - if (!this.isPlaying) { - this.isPlaying = true; - this.metro.resetSync(this); - var t = time || 0; - this.metro.start(t); - } - }; - /** - * Loop playback of this part. It will begin - * looping through all of its phrases at a speed - * determined by setBPM. - * - * @method loop - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.loop = function (time) { - this.looping = true; - // rest onended function - this.onended = function () { - this.partStep = 0; + p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { + this.aTime = t1; + this.aLevel = l1; + this.dTime = t2 || 0; + this.dLevel = l2 || 0; + this.rTime = t3 || 0; + this.rLevel = l3 || 0; + // set time constants for ramp + this._setRampAD(t1, t2); }; - var t = time || 0; - this.start(t); - }; - /** - * Tell the part to stop looping. - * - * @method noLoop - */ - p5.Part.prototype.noLoop = function () { - this.looping = false; - // rest onended function - this.onended = function () { - this.stop(); + /** + * Set values like a traditional + * + * ADSR envelope + * . + * + * @method setADSR + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
+ */ + p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { + this.aTime = aTime; + this.dTime = dTime || 0; + // lerp + this.sPercent = sPercent || 0; + this.dLevel = + typeof sPercent !== "undefined" + ? sPercent * (this.aLevel - this.rLevel) + this.rLevel + : 0; + this.rTime = rTime || 0; + // also set time constants for ramp + this._setRampAD(aTime, dTime); }; - }; - /** - * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. - * - * @method stop - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.stop = function (time) { - this.partStep = 0; - this.pause(time); - }; - /** - * Pause the part. Playback will resume - * from the current step. - * - * @method pause - * @param {Number} time seconds from now - */ - p5.Part.prototype.pause = function (time) { - this.isPlaying = false; - var t = time || 0; - this.metro.stop(t); - }; - /** - * Add a p5.Phrase to this Part. - * - * @method addPhrase - * @param {p5.Phrase} phrase reference to a p5.Phrase - */ - p5.Part.prototype.addPhrase = function (name, callback, array) { - var p; - if (arguments.length === 3) { - p = new p5.Phrase(name, callback, array); - } else if (arguments[0] instanceof p5.Phrase) { - p = arguments[0]; - } else { - throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase'; - } - this.phrases.push(p); - // reset the length if phrase is longer than part's existing length - if (p.sequence.length > this.length) { - this.length = p.sequence.length; - } - }; - /** - * Remove a phrase from this part, based on the name it was - * given when it was created. - * - * @method removePhrase - * @param {String} phraseName - */ - p5.Part.prototype.removePhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases.splice(i, 1); + /** + * Set max (attackLevel) and min (releaseLevel) of envelope. + * + * @method setRange + * @param {Number} aLevel attack level (defaults to 1) + * @param {Number} rLevel release level (defaults to 0) + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
+ */ + p5.Envelope.prototype.setRange = function (aLevel, rLevel) { + this.aLevel = aLevel || 1; + this.rLevel = rLevel || 0; + }; + // private (undocumented) method called when ADSR is set to set time constants for ramp + // + // Set the + // time constants for simple exponential ramps. + // The larger the time constant value, the slower the + // transition will be. + // + // method _setRampAD + // param {Number} attackTimeConstant attack time constant + // param {Number} decayTimeConstant decay time constant + // + p5.Envelope.prototype._setRampAD = function (t1, t2) { + this._rampAttackTime = this.checkExpInput(t1); + this._rampDecayTime = this.checkExpInput(t2); + var TCDenominator = 1; + /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) + TCDenominator = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + ); + this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1 / this._rampLowPercentage); + this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); + }; + // private method + p5.Envelope.prototype.setRampPercentages = function (p1, p2) { + //set the percentages that the simple exponential ramps go to + this._rampHighPercentage = this.checkExpInput(p1); + this._rampLowPercentage = this.checkExpInput(p2); + var TCDenominator = 1; + //now re-compute the time constants based on those percentages + /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) + TCDenominator = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + ); + this._rampAttackTC = + this._rampAttackTime / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1 / this._rampLowPercentage); + this._rampDecayTC = + this._rampDecayTime / this.checkExpInput(TCDenominator); + }; + /** + * Assign a parameter to be controlled by this envelope. + * If a p5.Sound object is given, then the p5.Envelope will control its + * output gain. If multiple inputs are provided, the env will + * control all of them. + * + * @method setInput + * @param {Object} [...inputs] A p5.sound object or + * Web Audio Param. + */ + p5.Envelope.prototype.setInput = function () { + for (var i = 0; i < arguments.length; i++) { + this.connect(arguments[i]); } - } - }; - /** - * Get a phrase from this part, based on the name it was - * given when it was created. Now you can modify its array. - * - * @method getPhrase - * @param {String} phraseName - */ - p5.Part.prototype.getPhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - return this.phrases[i]; + }; + /** + * Set whether the envelope ramp is linear (default) or exponential. + * Exponential ramps can be useful because we perceive amplitude + * and frequency logarithmically. + * + * @method setExp + * @param {Boolean} isExp true is exponential, false is linear + */ + p5.Envelope.prototype.setExp = function (isExp) { + this.isExponential = isExp; + }; + //helper method to protect against zero values being sent to exponential functions + p5.Envelope.prototype.checkExpInput = function (value) { + if (value <= 0) { + value = 1e-8; } - } - }; - /** - * Find all sequences with the specified name, and replace their patterns with the specified array. - * - * @method replaceSequence - * @param {String} phraseName - * @param {Array} sequence Array of values to pass into the callback - * at each step of the phrase. - */ - p5.Part.prototype.replaceSequence = function (name, array) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases[i].sequence = array; + return value; + }; + /** + * Play tells the envelope to start acting on a given input. + * If the input is a p5.sound object (i.e. AudioIn, Oscillator, + * SoundFile), then Envelope will control its output volume. + * Envelopes can also be used to control any + * Web Audio Audio Param. + * + * @method play + * @param {Object} unit A p5.sound object or + * Web Audio Param. + * @param {Number} [startTime] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * // trigger env on triOsc, 0 seconds from now + * // After decay, sustain for 0.2 seconds before release + * env.play(triOsc, 0, 0.2); + * } + *
+ */ + p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) { + var tFromNow = secondsFromNow || 0; + var susTime = susTime || 0; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - p5.Part.prototype.incrementStep = function (time) { - if (this.partStep < this.length - 1) { - this.callback(time); - this.partStep += 1; - } else { - if (!this.looping && this.partStep === this.length - 1) { - console.log('done'); - // this.callback(time); - this.onended(); + this.triggerAttack(unit, tFromNow); + this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime); + }; + /** + * Trigger the Attack, and Decay portion of the Envelope. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. Input can be + * any p5.sound object, or a + * Web Audio Param. + * + * @method triggerAttack + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow time from now (in seconds) + * @example + *
+ * + * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.3; + * var susPercent = 0.4; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * background(200); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(envAttack); + * } + * + * function envAttack() { + * console.log('trigger attack'); + * env.triggerAttack(); + * + * background(0,255,0); + * text('attack!', width/2, height/2); + * } + * + * function mouseReleased() { + * env.triggerRelease(); + * + * background(200); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + this.lastAttack = t; + this.wasTriggered = true; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - /** - * Set the function that will be called at every step. This will clear the previous function. - * - * @method onStep - * @param {Function} callback The name of the callback - * you want to fire - * on every beat/tatum. - */ - p5.Part.prototype.onStep = function (callback) { - this.callback = callback; - }; - // =============== - // p5.Score - // =============== - /** - * A Score consists of a series of Parts. The parts will - * be played back in order. For example, you could have an - * A part, a B part, and a C part, and play them back in this order - * new p5.Score(a, a, b, a, c) - * - * @class p5.Score - * @constructor - * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. - */ - p5.Score = function () { - // for all of the arguments - this.parts = []; - this.currentPart = 0; - var thisScore = this; - for (var i in arguments) { - if (arguments[i] && this.parts[i]) { - this.parts[i] = arguments[i]; - this.parts[i].nextPart = this.parts[i + 1]; - this.parts[i].onended = function () { - thisScore.resetPart(i); - playNextPart(thisScore); - }; + // get and set value (with linear ramp) to anchor automation + var valToSet = this.control.getValueAtTime(t); + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(valToSet), + t + ); + } else { + this.control.linearRampToValueAtTime(valToSet, t); + } + // after each ramp completes, cancel scheduled values + // (so they can be overridden in case env has been re-triggered) + // then, set current value (with linearRamp to avoid click) + // then, schedule the next automation... + // attack + t += this.aTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.aLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); + } + // decay to decay level (if using ADSR, then decay level == sustain level) + t += this.dTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.dLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); } - } - this.looping = false; - }; - p5.Score.prototype.onended = function () { - if (this.looping) { - // this.resetParts(); - this.parts[0].start(); - } else { - this.parts[this.parts.length - 1].onended = function () { - this.stop(); - this.resetParts(); - }; - } - this.currentPart = 0; - }; - /** - * Start playback of the score. - * - * @method start - */ - p5.Score.prototype.start = function () { - this.parts[this.currentPart].start(); - this.scoreStep = 0; - }; - /** - * Stop playback of the score. - * - * @method stop - */ - p5.Score.prototype.stop = function () { - this.parts[this.currentPart].stop(); - this.currentPart = 0; - this.scoreStep = 0; - }; - /** - * Pause playback of the score. - * - * @method pause - */ - p5.Score.prototype.pause = function () { - this.parts[this.currentPart].stop(); - }; - /** - * Loop playback of the score. - * - * @method loop - */ - p5.Score.prototype.loop = function () { - this.looping = true; - this.start(); - }; - /** - * Stop looping playback of the score. If it - * is currently playing, this will go into effect - * after the current round of playback completes. - * - * @method noLoop - */ - p5.Score.prototype.noLoop = function () { - this.looping = false; - }; - p5.Score.prototype.resetParts = function () { - var self = this; - this.parts.forEach(function (part) { - self.resetParts[part]; - }); - }; - p5.Score.prototype.resetPart = function (i) { - this.parts[i].stop(); - this.parts[i].partStep = 0; - for (var p in this.parts[i].phrases) { - if (this.parts[i]) { - this.parts[i].phrases[p].phraseStep = 0; + }; + /** + * Trigger the Release of the Envelope. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @method triggerRelease + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow time to trigger the release + * @example + *
+ * + * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.3; + * var susPercent = 0.4; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * background(200); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(envAttack); + * } + * + * function envAttack() { + * console.log('trigger attack'); + * env.triggerAttack(); + * + * background(0,255,0); + * text('attack!', width/2, height/2); + * } + * + * function mouseReleased() { + * env.triggerRelease(); + * + * background(200); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) { + // only trigger a release if an attack was triggered + if (!this.wasTriggered) { + // this currently causes a bit of trouble: + // if a later release has been scheduled (via the play function) + // a new earlier release won't interrupt it, because + // this.wasTriggered has already been set to false. + // If we want new earlier releases to override, then we need to + // keep track of the last release time, and if the new release time is + // earlier, then use it. + return; } - } - }; - /** - * Set the tempo for all parts in the score - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} rampTime Seconds from now - */ - p5.Score.prototype.setBPM = function (bpm, rampTime) { - for (var i in this.parts) { - if (this.parts[i]) { - this.parts[i].setBPM(bpm, rampTime); + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - function playNextPart(aScore) { - aScore.currentPart++; - if (aScore.currentPart >= aScore.parts.length) { - aScore.scoreStep = 0; - aScore.onended(); - } else { - aScore.scoreStep = 0; - aScore.parts[aScore.currentPart - 1].stop(); - aScore.parts[aScore.currentPart].start(); - } - } -}(master); -var soundloop; -'use strict'; -soundloop = function () { - var p5sound = master; - var Clock = Tone_core_Clock; - /** - * SoundLoop - * - * @class p5.SoundLoop - * @constructor - * - * @param {Function} callback this function will be called on each iteration of theloop - * @param {Number|String} [interval] amount of time or beats for each iteration of the loop - * defaults to 1 - * - * @example - *
- * var click; - * var looper1; - * - * function preload() { - * click = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * //the looper's callback is passed the timeFromNow - * //this value should be used as a reference point from - * //which to schedule sounds - * looper1 = new p5.SoundLoop(function(timeFromNow){ - * click.play(timeFromNow); - * background(255 * (looper1.iterations % 2)); - * }, 2); - * - * //stop after 10 iteratios; - * looper1.maxIterations = 10; - * //start the loop - * looper1.start(); - * } - *
- */ - p5.SoundLoop = function (callback, interval) { - this.callback = callback; + // get and set value (with linear or exponential ramp) to anchor automation + var valToSet = this.control.getValueAtTime(t); + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(valToSet), + t + ); + } else { + this.control.linearRampToValueAtTime(valToSet, t); + } + // release + t += this.rTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.rLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); + } + this.wasTriggered = false; + }; /** - * musicalTimeMode uses Tone.Time convention - * true if string, false if number - * @property {Boolean} musicalTimeMode - */ - this.musicalTimeMode = typeof this._interval === 'number' ? false : true; - this._interval = interval || 1; - /** - * musicalTimeMode variables - * modify these only when the interval is specified in musicalTime format as a string - */ - this._timeSignature = 4; - this._bpm = 60; - this.isPlaying = false; - /** - * Set a limit to the number of loops to play. defaults to Infinity - * @property {Number} maxIterations - */ - this.maxIterations = Infinity; - var self = this; - this.clock = new Clock({ - 'callback': function (time) { - var timeFromNow = time - p5sound.audiocontext.currentTime; - /** - * Do not initiate the callback if timeFromNow is < 0 - * This ususually occurs for a few milliseconds when the page - * is not fully loaded - * - * The callback should only be called until maxIterations is reached - */ - if (timeFromNow > 0 && self.iterations <= self.maxIterations) { - self.callback(timeFromNow); + * Exponentially ramp to a value using the first two + * values from setADSR(attackTime, decayTime) + * as + * time constants for simple exponential ramps. + * If the value is higher than current value, it uses attackTime, + * while a decrease uses decayTime. + * + * @method ramp + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow When to trigger the ramp + * @param {Number} v Target value + * @param {Number} [v2] Second target value (optional) + * @example + *
+ * var env, osc, amp, cnv; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var attackLevel = 1; + * var decayLevel = 0; + * + * function setup() { + * cnv = createCanvas(100, 100); + * fill(0,255,0); + * noStroke(); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime); + * + * osc = new p5.Oscillator(); + * osc.amp(env); + * osc.start(); + * + * amp = new p5.Amplitude(); + * + * cnv.mousePressed(triggerRamp); + * } + * + * function triggerRamp() { + * env.ramp(osc, 0, attackLevel, decayLevel); + * } + * + * function draw() { + * background(20,20,20); + * text('click me', 10, 20); + * var h = map(amp.getLevel(), 0, 0.4, 0, height);; + * + * rect(0, height, width, -h); + * } + *
+ */ + p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + var destination1 = this.checkExpInput(v1); + var destination2 = + typeof v2 !== "undefined" ? this.checkExpInput(v2) : undefined; + // connect env to unit if not already connected + if (unit) { + if (this.connection !== unit) { + this.connect(unit); } - }, - 'frequency': this._calcFreq() - }); - }; - /** - * Start the loop - * @method start - * @param {Number} [timeFromNow] schedule a starting time - */ - p5.SoundLoop.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (!this.isPlaying) { - this.clock.start(now + t); - this.isPlaying = true; - } - }; - /** - * Stop the loop - * @method stop - * @param {Number} [timeFromNow] schedule a stopping time - */ - p5.SoundLoop.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.stop(now + t); - this.isPlaying = false; - } - }; - /** - * Pause the loop - * @method pause - * @param {Number} [timeFromNow] schedule a pausing time - */ - p5.SoundLoop.prototype.pause = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.pause(now + t); - this.isPlaying = false; - } - }; - /** - * Synchronize loops. Use this method to start two more more loops in synchronization - * or to start a loop in synchronization with a loop that is already playing - * This method will schedule the implicit loop in sync with the explicit master loop - * i.e. loopToStart.syncedStart(loopToSyncWith) - * - * @method syncedStart - * @param {Object} otherLoop a p5.SoundLoop to sync with - * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds - */ - p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (!otherLoop.isPlaying) { - otherLoop.clock.start(now + t); - otherLoop.isPlaying = true; - this.clock.start(now + t); - this.isPlaying = true; - } else if (otherLoop.isPlaying) { - var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; - this.clock.start(now + time); - this.isPlaying = true; - } - }; - /** - * Updates frequency value, reflected in next callback - * @private - * @method _update - */ - p5.SoundLoop.prototype._update = function () { - this.clock.frequency.value = this._calcFreq(); - }; - /** - * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature - * @private - * @method _calcFreq - * @return {Number} new clock frequency value - */ - p5.SoundLoop.prototype._calcFreq = function () { - //Seconds mode, bpm / timesignature has no effect - if (typeof this._interval === 'number') { - this.musicalTimeMode = false; - return 1 / this._interval; - } else if (typeof this._interval === 'string') { - this.musicalTimeMode = true; - return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4); - } - }; - /** - * Convert notation from musical time format to seconds - * Uses Tone.Time convention - * @private - * @method _convertNotation - * @param {String} value value to be converted - * @return {Number} converted value in seconds - */ - p5.SoundLoop.prototype._convertNotation = function (value) { - var type = value.slice(-1); - value = Number(value.slice(0, -1)); - switch (type) { - case 'm': - return this._measure(value); - case 'n': - return this._note(value); - default: - console.warn('Specified interval is not formatted correctly. See Tone.js ' + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'); - } - }; - /** - * Helper conversion methods of measure and note - * @private - * @method _measure - * @private - * @method _note - */ - p5.SoundLoop.prototype._measure = function (value) { - return value * this._timeSignature; - }; - p5.SoundLoop.prototype._note = function (value) { - return this._timeSignature / value; - }; - /** - * Getters and Setters, setting any paramter will result in a change in the clock's - * frequency, that will be reflected after the next callback - * beats per minute (defaults to 60) - * @property {Number} bpm - */ - Object.defineProperty(p5.SoundLoop.prototype, 'bpm', { - get: function () { - return this._bpm; - }, - set: function (bpm) { - if (!this.musicalTimeMode) { - console.warn('Changing the BPM in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); - } - this._bpm = bpm; - this._update(); - } - }); - /** - * number of quarter notes in a measure (defaults to 4) - * @property {Number} timeSignature - */ - Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', { - get: function () { - return this._timeSignature; - }, - set: function (timeSig) { - if (!this.musicalTimeMode) { - console.warn('Changing the timeSignature in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); - } - this._timeSignature = timeSig; - this._update(); - } - }); - /** - * length of the loops interval - * @property {Number|String} interval - */ - Object.defineProperty(p5.SoundLoop.prototype, 'interval', { - get: function () { - return this._interval; - }, - set: function (interval) { - this.musicalTimeMode = typeof interval === 'Number' ? false : true; - this._interval = interval; - this._update(); - } - }); - /** - * how many times the callback has been called so far - * @property {Number} iterations - * @readonly - */ - Object.defineProperty(p5.SoundLoop.prototype, 'iterations', { - get: function () { - return this.clock.ticks; - } - }); - return p5.SoundLoop; -}(master, Tone_core_Clock); -var compressor; -compressor = function () { - 'use strict'; - var p5sound = master; - var Effect = effect; - var CustomError = errorHandler; - /** - * Compressor is an audio effect class that performs dynamics compression - * on an audio input source. This is a very commonly used technique in music - * and sound production. Compression creates an overall louder, richer, - * and fuller sound by lowering the volume of louds and raising that of softs. - * Compression can be used to avoid clipping (sound distortion due to - * peaks in volume) and is especially useful when many sounds are played - * at once. Compression can be used on indivudal sound sources in addition - * to the master output. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Compressor - * @constructor - * @extends p5.Effect - * - * - */ - p5.Compressor = function () { - Effect.call(this); + } + //get current value + var currentVal = this.checkExpInput(this.control.getValueAtTime(t)); + // this.control.cancelScheduledValues(t); + //if it's going up + if (destination1 > currentVal) { + this.control.setTargetAtTime(destination1, t, this._rampAttackTC); + t += this._rampAttackTime; + } else if (destination1 < currentVal) { + this.control.setTargetAtTime(destination1, t, this._rampDecayTC); + t += this._rampDecayTime; + } + // Now the second part of envelope begins + if (destination2 === undefined) return; + //if it's going up + if (destination2 > destination1) { + this.control.setTargetAtTime(destination2, t, this._rampAttackTC); + } else if (destination2 < destination1) { + this.control.setTargetAtTime(destination2, t, this._rampDecayTC); + } + }; + p5.Envelope.prototype.connect = function (unit) { + this.connection = unit; + // assume we're talking about output gain + // unless given a different audio param + if ( + unit instanceof p5.Oscillator || + unit instanceof p5.SoundFile || + unit instanceof p5.AudioIn || + unit instanceof p5.Reverb || + unit instanceof p5.Noise || + unit instanceof p5.Filter || + unit instanceof p5.Delay + ) { + unit = unit.output.gain; + } + if (unit instanceof AudioParam) { + //set the initial value + unit.setValueAtTime(0, p5sound.audiocontext.currentTime); + } + if (unit instanceof p5.Signal) { + unit.setValue(0); + } + this.output.connect(unit); + }; + p5.Envelope.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + // Signal Math /** - * The p5.Compressor is built with a Web Audio Dynamics Compressor Node - * - * @property {AudioNode} compressor - */ - this.compressor = this.ac.createDynamicsCompressor(); - this.input.connect(this.compressor); - this.compressor.connect(this.wet); - }; - p5.Compressor.prototype = Object.create(Effect.prototype); - /** - * Performs the same function as .connect, but also accepts - * optional parameters to set compressor's audioParams - * @method process - * - * @param {Object} src Sound source to be connected - * - * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [threshold] The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - p5.Compressor.prototype.process = function (src, attack, knee, ratio, threshold, release) { - src.connect(this.input); - this.set(attack, knee, ratio, threshold, release); - }; - /** - * Set the paramters of a compressor. - * @method set - * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} knee A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} ratio The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - p5.Compressor.prototype.set = function (attack, knee, ratio, threshold, release) { - if (typeof attack !== 'undefined') { - this.attack(attack); - } - if (typeof knee !== 'undefined') { - this.knee(knee); - } - if (typeof ratio !== 'undefined') { - this.ratio(ratio); - } - if (typeof threshold !== 'undefined') { - this.threshold(threshold); - } - if (typeof release !== 'undefined') { - this.release(release); - } - }; - /** - * Get current attack or set value w/ time ramp - * - * - * @method attack - * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.attack = function (attack, time) { - var t = time || 0; - if (typeof attack == 'number') { - this.compressor.attack.value = attack; - this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t); - } else if (typeof attack !== 'undefined') { - attack.connect(this.compressor.attack); - } - return this.compressor.attack.value; - }; - /** - * Get current knee or set value w/ time ramp - * - * @method knee - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.knee = function (knee, time) { - var t = time || 0; - if (typeof knee == 'number') { - this.compressor.knee.value = knee; - this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t); - } else if (typeof knee !== 'undefined') { - knee.connect(this.compressor.knee); - } - return this.compressor.knee.value; - }; - /** - * Get current ratio or set value w/ time ramp - * @method ratio - * - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.ratio = function (ratio, time) { - var t = time || 0; - if (typeof ratio == 'number') { - this.compressor.ratio.value = ratio; - this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t); - } else if (typeof ratio !== 'undefined') { - ratio.connect(this.compressor.ratio); - } - return this.compressor.ratio.value; - }; - /** - * Get current threshold or set value w/ time ramp - * @method threshold - * - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.threshold = function (threshold, time) { - var t = time || 0; - if (typeof threshold == 'number') { - this.compressor.threshold.value = threshold; - this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t); - } else if (typeof threshold !== 'undefined') { - threshold.connect(this.compressor.threshold); - } - return this.compressor.threshold.value; - }; - /** - * Get current release or set value w/ time ramp - * @method release - * - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - * - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.release = function (release, time) { - var t = time || 0; - if (typeof release == 'number') { - this.compressor.release.value = release; - this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t); - } else if (typeof number !== 'undefined') { - release.connect(this.compressor.release); - } - return this.compressor.release.value; - }; - /** - * Return the current reduction value - * - * @method reduction - * @return {Number} Value of the amount of gain reduction that is applied to the signal - */ - p5.Compressor.prototype.reduction = function () { - return this.compressor.reduction.value; - }; - p5.Compressor.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.compressor) { - this.compressor.disconnect(); - delete this.compressor; - } - }; - return p5.Compressor; -}(master, effect, errorHandler); -var soundRecorder; -'use strict'; -soundRecorder = function () { - // inspiration: recorder.js, Tone.js & typedarray.org - var p5sound = master; - var convertToWav = helpers.convertToWav; - var ac = p5sound.audiocontext; - /** - *

Record sounds for playback and/or to save as a .wav file. - * The p5.SoundRecorder records all sound output from your sketch, - * or can be assigned a specific source with setInput().

- *

The record() method accepts a p5.SoundFile as a parameter. - * When playback is stopped (either after the given amount of time, - * or with the stop() method), the p5.SoundRecorder will send its - * recording to that p5.SoundFile for playback.

- * - * @class p5.SoundRecorder - * @constructor - * @example - *
- * var mic, recorder, soundFile; - * var state = 0; - * - * function setup() { - * background(200); - * // create an audio in - * mic = new p5.AudioIn(); - * - * // prompts user to enable their browser mic - * mic.start(); - * - * // create a sound recorder - * recorder = new p5.SoundRecorder(); - * - * // connect the mic to the recorder - * recorder.setInput(mic); - * - * // this sound file will be used to - * // playback & save the recording - * soundFile = new p5.SoundFile(); - * - * text('keyPress to record', 20, 20); - * } - * - * function keyPressed() { - * // make sure user enabled the mic - * if (state === 0 && mic.enabled) { - * - * // record to our p5.SoundFile - * recorder.record(soundFile); - * - * background(255,0,0); - * text('Recording!', 20, 20); - * state++; - * } - * else if (state === 1) { - * background(0,255,0); - * - * // stop recorder and - * // send result to soundFile - * recorder.stop(); - * - * text('Stopped', 20, 20); - * state++; - * } - * - * else if (state === 2) { - * soundFile.play(); // play the result! - * save(soundFile, 'mySound.wav'); - * state++; - * } - * } - *
- */ - p5.SoundRecorder = function () { - this.input = ac.createGain(); - this.output = ac.createGain(); - this.recording = false; - this.bufferSize = 1024; - this._channels = 2; - // stereo (default) - this._clear(); - // initialize variables - this._jsNode = ac.createScriptProcessor(this.bufferSize, this._channels, 2); - this._jsNode.onaudioprocess = this._audioprocess.bind(this); - /** - * callback invoked when the recording is over - * @private - * @type Function(Float32Array) + * Add a value to the p5.Oscillator's output amplitude, + * and return the oscillator. Calling this method + * again will override the initial add() with new values. + * + * @method add + * @param {Number} number Constant number to add + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output */ - this._callback = function () { + p5.Envelope.prototype.add = function (num) { + var add = new Add(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, add, thisChain, nextChain, Add); }; - // connections - this._jsNode.connect(p5.soundOut._silentNode); - this.setInput(); - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connect a specific device to the p5.SoundRecorder. - * If no parameter is given, p5.SoundRecorer will record - * all audible p5.sound from your sketch. - * - * @method setInput - * @param {Object} [unit] p5.sound object or a web audio unit - * that outputs sound - */ - p5.SoundRecorder.prototype.setInput = function (unit) { - this.input.disconnect(); - this.input = null; - this.input = ac.createGain(); - this.input.connect(this._jsNode); - this.input.connect(this.output); - if (unit) { - unit.connect(this.input); - } else { - p5.soundOut.output.connect(this.input); - } - }; - /** - * Start recording. To access the recording, provide - * a p5.SoundFile as the first parameter. The p5.SoundRecorder - * will send its recording to that p5.SoundFile for playback once - * recording is complete. Optional parameters include duration - * (in seconds) of the recording, and a callback function that - * will be called once the complete recording has been - * transfered to the p5.SoundFile. - * - * @method record - * @param {p5.SoundFile} soundFile p5.SoundFile - * @param {Number} [duration] Time (in seconds) - * @param {Function} [callback] The name of a function that will be - * called once the recording completes - */ - p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { - this.recording = true; - if (duration) { - this.sampleLimit = Math.round(duration * ac.sampleRate); - } - if (sFile && callback) { - this._callback = function () { - this.buffer = this._getBuffer(); - sFile.setBuffer(this.buffer); - callback(); - }; - } else if (sFile) { - this._callback = function () { - this.buffer = this._getBuffer(); - sFile.setBuffer(this.buffer); - }; - } - }; - /** - * Stop the recording. Once the recording is stopped, - * the results will be sent to the p5.SoundFile that - * was given on .record(), and if a callback function - * was provided on record, that function will be called. - * - * @method stop - */ - p5.SoundRecorder.prototype.stop = function () { - this.recording = false; - this._callback(); - this._clear(); - }; - p5.SoundRecorder.prototype._clear = function () { - this._leftBuffers = []; - this._rightBuffers = []; - this.recordedSamples = 0; - this.sampleLimit = null; - }; - /** - * internal method called on audio process - * - * @private - * @param {AudioProcessorEvent} event - */ - p5.SoundRecorder.prototype._audioprocess = function (event) { - if (this.recording === false) { - return; - } else if (this.recording === true) { - // if we are past the duration, then stop... else: - if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) { - this.stop(); - } else { - // get channel data - var left = event.inputBuffer.getChannelData(0); - var right = event.inputBuffer.getChannelData(1); - // clone the samples - this._leftBuffers.push(new Float32Array(left)); - this._rightBuffers.push(new Float32Array(right)); - this.recordedSamples += this.bufferSize; + /** + * Multiply the p5.Envelope's output amplitude + * by a fixed value. Calling this method + * again will override the initial mult() with new values. + * + * @method mult + * @param {Number} number Constant number to multiply + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output + */ + p5.Envelope.prototype.mult = function (num) { + var mult = new Mult(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult); + }; + /** + * Scale this envelope's amplitude values to a given + * range, and return the envelope. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output + */ + p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { + var scale = new Scale(inMin, inMax, outMin, outMax); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale); + }; + // get rid of the oscillator + p5.Envelope.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.disconnect(); + if (this.control) { + this.control.dispose(); + this.control = null; } - } - }; - p5.SoundRecorder.prototype._getBuffer = function () { - var buffers = []; - buffers.push(this._mergeBuffers(this._leftBuffers)); - buffers.push(this._mergeBuffers(this._rightBuffers)); - return buffers; - }; - p5.SoundRecorder.prototype._mergeBuffers = function (channelBuffer) { - var result = new Float32Array(this.recordedSamples); - var offset = 0; - var lng = channelBuffer.length; - for (var i = 0; i < lng; i++) { - var buffer = channelBuffer[i]; - result.set(buffer, offset); - offset += buffer.length; - } - return result; - }; - p5.SoundRecorder.prototype.dispose = function () { - this._clear(); - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this._callback = function () { - }; - if (this.input) { - this.input.disconnect(); - } - this.input = null; - this._jsNode = null; - }; - /** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. - * For uploading audio to a server, use - * `p5.SoundFile.saveBlob`. - * - * @for p5 - * @method saveSound - * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save - * @param {String} fileName name of the resulting .wav file. - */ - // add to p5.prototype as this is used by the p5 `save()` method. - p5.prototype.saveSound = function (soundFile, fileName) { - const dataView = convertToWav(soundFile.buffer); - p5.prototype.writeFile([dataView], fileName, 'wav'); - }; -}(master, helpers); -var peakdetect; -'use strict'; -peakdetect = function () { - /** - *

PeakDetect works in conjunction with p5.FFT to - * look for onsets in some or all of the frequency spectrum. - *

- *

- * To use p5.PeakDetect, call update in the draw loop - * and pass in a p5.FFT object. - *

- *

- * You can listen for a specific part of the frequency spectrum by - * setting the range between freq1 and freq2. - *

- * - *

threshold is the threshold for detecting a peak, - * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud - * as 1.0.

- * - *

- * The update method is meant to be run in the draw loop, and - * frames determines how many loops must pass before - * another peak can be detected. - * For example, if the frameRate() = 60, you could detect the beat of a - * 120 beat-per-minute song with this equation: - * framesPerPeak = 60 / (estimatedBPM / 60 ); - *

- * - *

- * Based on example contribtued by @b2renger, and a simple beat detection - * explanation by Felix Turner. - *

- * - * @class p5.PeakDetect - * @constructor - * @param {Number} [freq1] lowFrequency - defaults to 20Hz - * @param {Number} [freq2] highFrequency - defaults to 20000 Hz - * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 - * scaled logarithmically where 0.1 is 1/2 the loudness - * of 1.0. Defaults to 0.35. - * @param {Number} [framesPerPeak] Defaults to 20. - * @example - *
- * - * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 10; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * - * // p5.PeakDetect requires a p5.FFT - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * } - * - * function draw() { - * background(0); - * text('click to play/pause', width/2, height/2); - * - * // peakDetect accepts an fft post-analysis - * fft.analyze(); - * peakDetect.update(fft); - * - * if ( peakDetect.isDetected ) { - * ellipseWidth = 50; - * } else { - * ellipseWidth *= 0.95; - * } - * - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // toggle play/stop when canvas is clicked - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * } - * } - *
- */ - p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) { - // framesPerPeak determines how often to look for a beat. - // If a beat is provided, try to look for a beat based on bpm - this.framesPerPeak = _framesPerPeak || 20; - this.framesSinceLastPeak = 0; - this.decayRate = 0.95; - this.threshold = threshold || 0.35; - this.cutoff = 0; - // how much to increase the cutoff - // TO DO: document this / figure out how to make it accessible - this.cutoffMult = 1.5; - this.energy = 0; - this.penergy = 0; - // TO DO: document this property / figure out how to make it accessible - this.currentValue = 0; - /** - * isDetected is set to true when a peak is detected. - * - * @attribute isDetected {Boolean} - * @default false - */ - this.isDetected = false; - this.f1 = freq1 || 40; - this.f2 = freq2 || 20000; - // function to call when a peak is detected - this._onPeak = function () { - }; - }; - /** - * The update method is run in the draw loop. - * - * Accepts an FFT object. You must call .analyze() - * on the FFT object prior to updating the peakDetect - * because it relies on a completed FFT analysis. - * - * @method update - * @param {p5.FFT} fftObject A p5.FFT object - */ - p5.PeakDetect.prototype.update = function (fftObject) { - var nrg = this.energy = fftObject.getEnergy(this.f1, this.f2) / 255; - if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { - // trigger callback - this._onPeak(); - this.isDetected = true; - // debounce - this.cutoff = nrg * this.cutoffMult; - this.framesSinceLastPeak = 0; - } else { - this.isDetected = false; - if (this.framesSinceLastPeak <= this.framesPerPeak) { - this.framesSinceLastPeak++; - } else { - this.cutoff *= this.decayRate; - this.cutoff = Math.max(this.cutoff, this.threshold); + for (var i = 1; i < this.mathOps.length; i++) { + this.mathOps[i].dispose(); } - } - this.currentValue = nrg; - this.penergy = nrg; - }; - /** - * onPeak accepts two arguments: a function to call when - * a peak is detected. The value of the peak, - * between 0.0 and 1.0, is passed to the callback. - * - * @method onPeak - * @param {Function} callback Name of a function that will - * be called when a peak is - * detected. - * @param {Object} [val] Optional value to pass - * into the function when - * a peak is detected. - * @example - *
- * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 0; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * cnv = createCanvas(100,100); - * textAlign(CENTER); - * - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * - * setupSound(); - * - * // when a beat is detected, call triggerBeat() - * peakDetect.onPeak(triggerBeat); - * } - * - * function draw() { - * background(0); - * fill(255); - * text('click to play', width/2, height/2); - * - * fft.analyze(); - * peakDetect.update(fft); - * - * ellipseWidth *= 0.95; - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // this function is called by peakDetect.onPeak - * function triggerBeat() { - * ellipseWidth = 50; - * } - * - * // mouseclick starts/stops sound - * function setupSound() { - * cnv.mouseClicked( function() { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * }); - * } - *
- */ - p5.PeakDetect.prototype.onPeak = function (callback, val) { - var self = this; - self._onPeak = function () { - callback(self.energy, val); - }; - }; -}(); -var gain; -'use strict'; -gain = function () { - var p5sound = master; - /** - * A gain node is usefull to set the relative volume of sound. - * It's typically used to build mixers. - * - * @class p5.Gain - * @constructor - * @example - *
- * - * // load two soundfile and crossfade beetween them - * var sound1,sound2; - * var gain1, gain2, gain3; - * - * function preload(){ - * soundFormats('ogg', 'mp3'); - * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); - * sound2 = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * createCanvas(400,200); - * - * // create a 'master' gain to which we will connect both soundfiles - * gain3 = new p5.Gain(); - * gain3.connect(); - * - * // setup first sound for playing - * sound1.rate(1); - * sound1.loop(); - * sound1.disconnect(); // diconnect from p5 output - * - * gain1 = new p5.Gain(); // setup a gain node - * gain1.setInput(sound1); // connect the first sound to its input - * gain1.connect(gain3); // connect its output to the 'master' - * - * sound2.rate(1); - * sound2.disconnect(); - * sound2.loop(); - * - * gain2 = new p5.Gain(); - * gain2.setInput(sound2); - * gain2.connect(gain3); - * - * } - * - * function draw(){ - * background(180); - * - * // calculate the horizontal distance beetween the mouse and the right of the screen - * var d = dist(mouseX,0,width,0); - * - * // map the horizontal position of the mouse to values useable for volume control of sound1 - * var vol1 = map(mouseX,0,width,0,1); - * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa - * - * gain1.amp(vol1,0.5,0); - * gain2.amp(vol2,0.5,0); - * - * // map the vertical position of the mouse to values useable for 'master volume control' - * var vol3 = map(mouseY,0,height,0,1); - * gain3.amp(vol3,0.5,0); - * } - *
- * - */ - p5.Gain = function () { - this.ac = p5sound.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - this.input.connect(this.output); - // add to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connect a source to the gain node. - * - * @method setInput - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - */ - p5.Gain.prototype.setInput = function (src) { - src.connect(this.input); - }; - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - p5.Gain.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Gain.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Set the output level of the gain node. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - p5.Gain.prototype.amp = function (vol, rampTime, tFromNow) { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - }; - p5.Gain.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.output) { - this.output.disconnect(); + }; + // Different name for backwards compatibility, replicates p5.Envelope class + p5.Env = function (t1, l1, t2, l2, t3, l3) { + console.warn( + "WARNING: p5.Env is now deprecated and may be removed in future versions. " + + "Please use the new p5.Envelope instead." + ); + p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); + }; + p5.Env.prototype = Object.create(p5.Envelope.prototype); + })( + master, + Tone_signal_Add, + Tone_signal_Multiply, + Tone_signal_Scale, + Tone_signal_TimelineSignal + ); + var pulse; + ("use strict"); + pulse = (function () { + var p5sound = master; + /** + * Creates a Pulse object, an oscillator that implements + * Pulse Width Modulation. + * The pulse is created with two oscillators. + * Accepts a parameter for frequency, and to set the + * width between the pulses. See + * p5.Oscillator for a full list of methods. + * + * @class p5.Pulse + * @extends p5.Oscillator + * @constructor + * @param {Number} [freq] Frequency in oscillations per second (Hz) + * @param {Number} [w] Width between the pulses (0 to 1.0, + * defaults to 0) + * @example + *
+ * var pulse; + * function setup() { + * background(0); + * + * // Create and start the pulse wave oscillator + * pulse = new p5.Pulse(); + * pulse.amp(0.5); + * pulse.freq(220); + * pulse.start(); + * } + * + * function draw() { + * var w = map(mouseX, 0, width, 0, 1); + * w = constrain(w, 0, 1); + * pulse.width(w) + * } + *
+ */ + p5.Pulse = function (freq, w) { + p5.Oscillator.call(this, freq, "sawtooth"); + // width of PWM, should be betw 0 to 1.0 + this.w = w || 0; + // create a second oscillator with inverse frequency + this.osc2 = new p5.SawOsc(freq); + // create a delay node + this.dNode = p5sound.audiocontext.createDelay(); + // dc offset + this.dcOffset = createDCOffset(); + this.dcGain = p5sound.audiocontext.createGain(); + this.dcOffset.connect(this.dcGain); + this.dcGain.connect(this.output); + // set delay time based on PWM width + this.f = freq || 440; + var mW = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = mW; + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + // disconnect osc2 and connect it to delay, which is connected to output + this.osc2.disconnect(); + this.osc2.panner.disconnect(); + this.osc2.amp(-1); + // inverted amplitude + this.osc2.output.connect(this.dNode); + this.dNode.connect(this.output); + this.output.gain.value = 1; + this.output.connect(this.panner); + }; + p5.Pulse.prototype = Object.create(p5.Oscillator.prototype); + /** + * Set the width of a Pulse object (an oscillator that implements + * Pulse Width Modulation). + * + * @method width + * @param {Number} [width] Width between the pulses (0 to 1.0, + * defaults to 0) + */ + p5.Pulse.prototype.width = function (w) { + if (typeof w === "number") { + if (w <= 1 && w >= 0) { + this.w = w; + // set delay time based on PWM width + // var mW = map(this.w, 0, 1.0, 0, 1/this.f); + var mW = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = mW; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + w.connect(this.dNode.delayTime); + var sig = new p5.SignalAdd(-0.5); + sig.setInput(w); + sig = sig.mult(-1); + sig = sig.mult(1.7); + sig.connect(this.dcGain.gain); + } + }; + p5.Pulse.prototype.start = function (f, time) { + var now = p5sound.audiocontext.currentTime; + var t = time || 0; + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.oscillator.frequency.setValueAtTime(freq, now); + this.oscillator.type = type; + this.oscillator.connect(this.output); + this.oscillator.start(t + now); + // set up osc2 + this.osc2.oscillator = p5sound.audiocontext.createOscillator(); + this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); + this.osc2.oscillator.type = type; + this.osc2.oscillator.connect(this.osc2.output); + this.osc2.start(t + now); + this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]; + // start dcOffset, too + this.dcOffset = createDCOffset(); + this.dcOffset.connect(this.dcGain); + this.dcOffset.start(t + now); + // if LFO connections depend on these oscillators + if (this.mods !== undefined && this.mods.frequency !== undefined) { + this.mods.frequency.connect(this.freqNode[0]); + this.mods.frequency.connect(this.freqNode[1]); + } + this.started = true; + this.osc2.started = true; + } + }; + p5.Pulse.prototype.stop = function (time) { + if (this.started) { + var t = time || 0; + var now = p5sound.audiocontext.currentTime; + this.oscillator.stop(t + now); + if (this.osc2.oscillator) { + this.osc2.oscillator.stop(t + now); + } + this.dcOffset.stop(t + now); + this.started = false; + this.osc2.started = false; + } + }; + p5.Pulse.prototype.freq = function (val, rampTime, tFromNow) { + if (typeof val === "number") { + this.f = val; + var now = p5sound.audiocontext.currentTime; + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var currentFreq = this.oscillator.frequency.value; + this.oscillator.frequency.cancelScheduledValues(now); + this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); + this.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); + this.osc2.oscillator.frequency.cancelScheduledValues(now); + this.osc2.oscillator.frequency.setValueAtTime( + currentFreq, + now + tFromNow + ); + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); + if (this.freqMod) { + this.freqMod.output.disconnect(); + this.freqMod = null; + } + } else if (val.output) { + val.output.disconnect(); + val.output.connect(this.oscillator.frequency); + val.output.connect(this.osc2.oscillator.frequency); + this.freqMod = val; + } + }; + // inspiration: http://webaudiodemos.appspot.com/oscilloscope/ + function createDCOffset() { + var ac = p5sound.audiocontext; + var buffer = ac.createBuffer(1, 2048, ac.sampleRate); + var data = buffer.getChannelData(0); + for (var i = 0; i < 2048; i++) data[i] = 1; + var bufferSource = ac.createBufferSource(); + bufferSource.buffer = buffer; + bufferSource.loop = true; + return bufferSource; + } + })(master, oscillator); + var noise; + ("use strict"); + noise = (function () { + var p5sound = master; + /** + * Noise is a type of oscillator that generates a buffer with random values. + * + * @class p5.Noise + * @extends p5.Oscillator + * @constructor + * @param {String} type Type of noise can be 'white' (default), + * 'brown' or 'pink'. + */ + p5.Noise = function (type) { + var assignType; + p5.Oscillator.call(this); + delete this.f; + delete this.freq; + delete this.oscillator; + if (type === "brown") { + assignType = _brownNoise; + } else if (type === "pink") { + assignType = _pinkNoise; + } else { + assignType = _whiteNoise; + } + this.buffer = assignType; + }; + p5.Noise.prototype = Object.create(p5.Oscillator.prototype); + // generate noise buffers + var _whiteNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var whiteBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = whiteBuffer.getChannelData(0); + for (var i = 0; i < bufferSize; i++) { + noiseData[i] = Math.random() * 2 - 1; + } + whiteBuffer.type = "white"; + return whiteBuffer; + })(); + var _pinkNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var pinkBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = pinkBuffer.getChannelData(0); + var b0, b1, b2, b3, b4, b5, b6; + b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0; + for (var i = 0; i < bufferSize; i++) { + var white = Math.random() * 2 - 1; + b0 = 0.99886 * b0 + white * 0.0555179; + b1 = 0.99332 * b1 + white * 0.0750759; + b2 = 0.969 * b2 + white * 0.153852; + b3 = 0.8665 * b3 + white * 0.3104856; + b4 = 0.55 * b4 + white * 0.5329522; + b5 = -0.7616 * b5 - white * 0.016898; + noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362; + noiseData[i] *= 0.11; + // (roughly) compensate for gain + b6 = white * 0.115926; + } + pinkBuffer.type = "pink"; + return pinkBuffer; + })(); + var _brownNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var brownBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = brownBuffer.getChannelData(0); + var lastOut = 0; + for (var i = 0; i < bufferSize; i++) { + var white = Math.random() * 2 - 1; + noiseData[i] = (lastOut + 0.02 * white) / 1.02; + lastOut = noiseData[i]; + noiseData[i] *= 3.5; + } + brownBuffer.type = "brown"; + return brownBuffer; + })(); + /** + * Set type of noise to 'white', 'pink' or 'brown'. + * White is the default. + * + * @method setType + * @param {String} [type] 'white', 'pink' or 'brown' + */ + p5.Noise.prototype.setType = function (type) { + switch (type) { + case "white": + this.buffer = _whiteNoise; + break; + case "pink": + this.buffer = _pinkNoise; + break; + case "brown": + this.buffer = _brownNoise; + break; + default: + this.buffer = _whiteNoise; + } + if (this.started) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + this.start(now + 0.01); + } + }; + p5.Noise.prototype.getType = function () { + return this.buffer.type; + }; + p5.Noise.prototype.start = function () { + if (this.started) { + this.stop(); + } + this.noise = p5sound.audiocontext.createBufferSource(); + this.noise.buffer = this.buffer; + this.noise.loop = true; + this.noise.connect(this.output); + var now = p5sound.audiocontext.currentTime; + this.noise.start(now); + this.started = true; + }; + p5.Noise.prototype.stop = function () { + var now = p5sound.audiocontext.currentTime; + if (this.noise) { + this.noise.stop(now); + this.started = false; + } + }; + p5.Noise.prototype.dispose = function () { + var now = p5sound.audiocontext.currentTime; + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.noise) { + this.noise.disconnect(); + this.stop(now); + } + if (this.output) { + this.output.disconnect(); + } + if (this.panner) { + this.panner.disconnect(); + } + this.output = null; + this.panner = null; + this.buffer = null; + this.noise = null; + }; + })(master); + var audioin; + ("use strict"); + audioin = (function () { + var p5sound = master; + // an array of input sources + p5sound.inputSources = []; + /** + *

Get audio from an input, i.e. your computer's microphone.

+ * + *

Turn the mic on/off with the start() and stop() methods. When the mic + * is on, its volume can be measured with getLevel or by connecting an + * FFT object.

+ * + *

If you want to hear the AudioIn, use the .connect() method. + * AudioIn does not connect to p5.sound output by default to prevent + * feedback.

+ * + *

Note: This uses the getUserMedia/ + * Stream API, which is not supported by certain browsers. Access in Chrome browser + * is limited to localhost and https, but access over http may be limited.

+ * + * @class p5.AudioIn + * @constructor + * @param {Function} [errorCallback] A function to call if there is an error + * accessing the AudioIn. For example, + * Safari and iOS devices do not + * currently allow microphone access. + * @example + *
+ * var mic; + * function setup(){ + * mic = new p5.AudioIn() + * mic.start(); + * } + * function draw(){ + * background(0); + * micLevel = mic.getLevel(); + * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10); + * } + *
+ */ + p5.AudioIn = function (errorCallback) { + // set up audio input + /** + * @property {GainNode} input + */ + this.input = p5sound.audiocontext.createGain(); + /** + * @property {GainNode} output + */ + this.output = p5sound.audiocontext.createGain(); + /** + * @property {MediaStream|null} stream + */ + this.stream = null; + /** + * @property {MediaStreamAudioSourceNode|null} mediaStream + */ + this.mediaStream = null; + /** + * @property {Number|null} currentSource + */ + this.currentSource = null; + /** + * Client must allow browser to access their microphone / audioin source. + * Default: false. Will become true when the client enables acces. + * + * @property {Boolean} enabled + */ + this.enabled = false; + /** + * Input amplitude, connect to it by default but not to master out + * + * @property {p5.Amplitude} amplitude + */ + this.amplitude = new p5.Amplitude(); + this.output.connect(this.amplitude.input); + if ( + !window.MediaStreamTrack || + !window.navigator.mediaDevices || + !window.navigator.mediaDevices.getUserMedia + ) { + errorCallback + ? errorCallback() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + ); + } + // add to soundArray so we can dispose on close + p5sound.soundArray.push(this); + }; + /** + * Start processing audio input. This enables the use of other + * AudioIn methods like getLevel(). Note that by default, AudioIn + * is not connected to p5.sound's output. So you won't hear + * anything unless you use the connect() method.
+ * + * Certain browsers limit access to the user's microphone. For example, + * Chrome only allows access from localhost and over https. For this reason, + * you may want to include an errorCallback—a function that is called in case + * the browser won't provide mic access. + * + * @method start + * @param {Function} [successCallback] Name of a function to call on + * success. + * @param {Function} [errorCallback] Name of a function to call if + * there was an error. For example, + * some browsers do not support + * getUserMedia. + */ + p5.AudioIn.prototype.start = function (successCallback, errorCallback) { + var self = this; + if (this.stream) { + this.stop(); + } + // set the audio source + var audioSource = p5sound.inputSources[self.currentSource]; + var constraints = { + audio: { + sampleRate: p5sound.audiocontext.sampleRate, + echoCancellation: false, + }, + }; + // if developers determine which source to use + if (p5sound.inputSources[this.currentSource]) { + constraints.audio.deviceId = audioSource.deviceId; + } + window.navigator.mediaDevices + .getUserMedia(constraints) + .then(function (stream) { + self.stream = stream; + self.enabled = true; + // Wrap a MediaStreamSourceNode around the live input + self.mediaStream = + p5sound.audiocontext.createMediaStreamSource(stream); + self.mediaStream.connect(self.output); + // only send to the Amplitude reader, so we can see it but not hear it. + self.amplitude.setInput(self.output); + if (successCallback) successCallback(); + }) + .catch(function (err) { + if (errorCallback) errorCallback(err); + else console.error(err); + }); + }; + /** + * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). + * If re-starting, the user may be prompted for permission access. + * + * @method stop + */ + p5.AudioIn.prototype.stop = function () { + if (this.stream) { + this.stream.getTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.disconnect(); + delete this.mediaStream; + delete this.stream; + } + }; + /** + * Connect to an audio unit. If no parameter is provided, will + * connect to the master output (i.e. your speakers).
+ * + * @method connect + * @param {Object} [unit] An object that accepts audio input, + * such as an FFT + */ + p5.AudioIn.prototype.connect = function (unit) { + if (unit) { + if (unit.hasOwnProperty("input")) { + this.output.connect(unit.input); + } else if (unit.hasOwnProperty("analyser")) { + this.output.connect(unit.analyser); + } else { + this.output.connect(unit); + } + } else { + this.output.connect(p5sound.input); + } + }; + /** + * Disconnect the AudioIn from all audio units. For example, if + * connect() had been called, disconnect() will stop sending + * signal to your speakers.
+ * + * @method disconnect + */ + p5.AudioIn.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + // stay connected to amplitude even if not outputting to p5 + this.output.connect(this.amplitude.input); + } + }; + /** + * Read the Amplitude (volume level) of an AudioIn. The AudioIn + * class contains its own instance of the Amplitude class to help + * make it easy to get a microphone's volume level. Accepts an + * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must + * .start() before using .getLevel().
+ * + * @method getLevel + * @param {Number} [smoothing] Smoothing is 0.0 by default. + * Smooths values based on previous values. + * @return {Number} Volume level (between 0.0 and 1.0) + */ + p5.AudioIn.prototype.getLevel = function (smoothing) { + if (smoothing) { + this.amplitude.smoothing = smoothing; + } + return this.amplitude.getLevel(); + }; + /** + * Set amplitude (volume) of a mic input between 0 and 1.0.
+ * + * @method amp + * @param {Number} vol between 0 and 1.0 + * @param {Number} [time] ramp time (optional) + */ + p5.AudioIn.prototype.amp = function (vol, t) { + if (t) { + var rampTime = t || 0; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues( + p5sound.audiocontext.currentTime + ); + this.output.gain.setValueAtTime( + currentVol, + p5sound.audiocontext.currentTime + ); + this.output.gain.linearRampToValueAtTime( + vol, + rampTime + p5sound.audiocontext.currentTime + ); + } else { + this.output.gain.cancelScheduledValues( + p5sound.audiocontext.currentTime + ); + this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime); + } + }; + /** + * Returns a list of available input sources. This is a wrapper + * for and it returns a Promise. + * + * @method getSources + * @param {Function} [successCallback] This callback function handles the sources when they + * have been enumerated. The callback function + * receives the deviceList array as its only argument + * @param {Function} [errorCallback] This optional callback receives the error + * message as its argument. + * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar + * to the enumerateDevices() method + * @example + *
+ * var audiograb; + * + * function setup(){ + * //new audioIn + * audioGrab = new p5.AudioIn(); + * + * audioGrab.getSources(function(deviceList) { + * //print out the array of available sources + * console.log(deviceList); + * //set the source to the first item in the deviceList array + * audioGrab.setSource(0); + * }); + * } + *
+ */ + p5.AudioIn.prototype.getSources = function (onSuccess, onError) { + return new Promise(function (resolve, reject) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (devices) { + p5sound.inputSources = devices.filter(function (device) { + return device.kind === "audioinput"; + }); + resolve(p5sound.inputSources); + if (onSuccess) { + onSuccess(p5sound.inputSources); + } + }) + .catch(function (error) { + reject(error); + if (onError) { + onError(error); + } else { + console.error( + "This browser does not support MediaStreamTrack.getSources()" + ); + } + }); + }); + }; + /** + * Set the input source. Accepts a number representing a + * position in the array returned by getSources(). + * This is only available in browsers that support + *
navigator.mediaDevices.enumerateDevices().
+ * + * @method setSource + * @param {number} num position of input source in the array + */ + p5.AudioIn.prototype.setSource = function (num) { + if ( + p5sound.inputSources.length > 0 && + num < p5sound.inputSources.length + ) { + // set the current source + this.currentSource = num; + console.log("set source to ", p5sound.inputSources[this.currentSource]); + } else { + console.log("unable to set input source"); + } + // restart stream if currently active + if (this.stream && this.stream.active) { + this.start(); + } + }; + // private method + p5.AudioIn.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.stop(); + if (this.output) { + this.output.disconnect(); + } + if (this.amplitude) { + this.amplitude.disconnect(); + } + delete this.amplitude; delete this.output; + }; + })(master); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Negate; + Tone_signal_Negate = (function (Tone) { + "use strict"; + Tone.Negate = function () { + this._multiply = this.input = this.output = new Tone.Multiply(-1); + }; + Tone.extend(Tone.Negate, Tone.SignalBase); + Tone.Negate.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._multiply.dispose(); + this._multiply = null; + return this; + }; + return Tone.Negate; + })(Tone_core_Tone, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Subtract; + Tone_signal_Subtract = (function (Tone) { + "use strict"; + Tone.Subtract = function (value) { + this.createInsOuts(2, 0); + this._sum = this.input[0] = this.output = new Tone.Gain(); + this._neg = new Tone.Negate(); + this._param = this.input[1] = new Tone.Signal(value); + this._param.chain(this._neg, this._sum); + }; + Tone.extend(Tone.Subtract, Tone.Signal); + Tone.Subtract.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._neg.dispose(); + this._neg = null; + this._sum.disconnect(); + this._sum = null; + this._param.dispose(); + this._param = null; + return this; + }; + return Tone.Subtract; + })(Tone_core_Tone, Tone_signal_Add, Tone_signal_Negate, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_GreaterThanZero; + Tone_signal_GreaterThanZero = (function (Tone) { + "use strict"; + Tone.GreaterThanZero = function () { + this._thresh = this.output = new Tone.WaveShaper(function (val) { + if (val <= 0) { + return 0; + } else { + return 1; + } + }, 127); + this._scale = this.input = new Tone.Multiply(10000); + this._scale.connect(this._thresh); + }; + Tone.extend(Tone.GreaterThanZero, Tone.SignalBase); + Tone.GreaterThanZero.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._scale.dispose(); + this._scale = null; + this._thresh.dispose(); + this._thresh = null; + return this; + }; + return Tone.GreaterThanZero; + })(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_GreaterThan; + Tone_signal_GreaterThan = (function (Tone) { + "use strict"; + Tone.GreaterThan = function (value) { + this.createInsOuts(2, 0); + this._param = this.input[0] = new Tone.Subtract(value); + this.input[1] = this._param.input[1]; + this._gtz = this.output = new Tone.GreaterThanZero(); + this._param.connect(this._gtz); + }; + Tone.extend(Tone.GreaterThan, Tone.Signal); + Tone.GreaterThan.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._param.dispose(); + this._param = null; + this._gtz.dispose(); + this._gtz = null; + return this; + }; + return Tone.GreaterThan; + })(Tone_core_Tone, Tone_signal_GreaterThanZero, Tone_signal_Subtract); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Abs; + Tone_signal_Abs = (function (Tone) { + "use strict"; + Tone.Abs = function () { + this._abs = + this.input = + this.output = + new Tone.WaveShaper(function (val) { + if (val === 0) { + return 0; + } else { + return Math.abs(val); + } + }, 127); + }; + Tone.extend(Tone.Abs, Tone.SignalBase); + Tone.Abs.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._abs.dispose(); + this._abs = null; + return this; + }; + return Tone.Abs; + })(Tone_core_Tone, Tone_signal_WaveShaper); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Modulo; + Tone_signal_Modulo = (function (Tone) { + "use strict"; + Tone.Modulo = function (modulus) { + this.createInsOuts(1, 0); + this._shaper = new Tone.WaveShaper(Math.pow(2, 16)); + this._multiply = new Tone.Multiply(); + this._subtract = this.output = new Tone.Subtract(); + this._modSignal = new Tone.Signal(modulus); + this.input.fan(this._shaper, this._subtract); + this._modSignal.connect(this._multiply, 0, 0); + this._shaper.connect(this._multiply, 0, 1); + this._multiply.connect(this._subtract, 0, 1); + this._setWaveShaper(modulus); + }; + Tone.extend(Tone.Modulo, Tone.SignalBase); + Tone.Modulo.prototype._setWaveShaper = function (mod) { + this._shaper.setMap(function (val) { + var multiple = Math.floor((val + 0.0001) / mod); + return multiple; + }); + }; + Object.defineProperty(Tone.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (mod) { + this._modSignal.value = mod; + this._setWaveShaper(mod); + }, + }); + Tone.Modulo.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._shaper.dispose(); + this._shaper = null; + this._multiply.dispose(); + this._multiply = null; + this._subtract.dispose(); + this._subtract = null; + this._modSignal.dispose(); + this._modSignal = null; + return this; + }; + return Tone.Modulo; + })(Tone_core_Tone, Tone_signal_WaveShaper, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Pow; + Tone_signal_Pow = (function (Tone) { + "use strict"; + Tone.Pow = function (exp) { + this._exp = this.defaultArg(exp, 1); + this._expScaler = + this.input = + this.output = + new Tone.WaveShaper(this._expFunc(this._exp), 8192); + }; + Tone.extend(Tone.Pow, Tone.SignalBase); + Object.defineProperty(Tone.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (exp) { + this._exp = exp; + this._expScaler.setMap(this._expFunc(this._exp)); + }, + }); + Tone.Pow.prototype._expFunc = function (exp) { + return function (val) { + return Math.pow(Math.abs(val), exp); + }; + }; + Tone.Pow.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._expScaler.dispose(); + this._expScaler = null; + return this; + }; + return Tone.Pow; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_AudioToGain; + Tone_signal_AudioToGain = (function (Tone) { + "use strict"; + Tone.AudioToGain = function () { + this._norm = + this.input = + this.output = + new Tone.WaveShaper(function (x) { + return (x + 1) / 2; + }); + }; + Tone.extend(Tone.AudioToGain, Tone.SignalBase); + Tone.AudioToGain.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._norm.dispose(); + this._norm = null; + return this; + }; + return Tone.AudioToGain; + })(Tone_core_Tone, Tone_signal_WaveShaper); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Expr; + Tone_signal_Expr = (function (Tone) { + "use strict"; + Tone.Expr = function () { + var expr = this._replacements(Array.prototype.slice.call(arguments)); + var inputCount = this._parseInputs(expr); + this._nodes = []; + this.input = new Array(inputCount); + for (var i = 0; i < inputCount; i++) { + this.input[i] = this.context.createGain(); + } + var tree = this._parseTree(expr); + var result; + try { + result = this._eval(tree); + } catch (e) { + this._disposeNodes(); + throw new Error("Tone.Expr: Could evaluate expression: " + expr); + } + this.output = result; + }; + Tone.extend(Tone.Expr, Tone.SignalBase); + function applyBinary(Constructor, args, self) { + var op = new Constructor(); + self._eval(args[0]).connect(op, 0, 0); + self._eval(args[1]).connect(op, 0, 1); + return op; + } + function applyUnary(Constructor, args, self) { + var op = new Constructor(); + self._eval(args[0]).connect(op, 0, 0); + return op; + } + function getNumber(arg) { + return arg ? parseFloat(arg) : undefined; + } + function literalNumber(arg) { + return arg && arg.args ? parseFloat(arg.args) : undefined; + } + Tone.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (arg) { + var sig = new Tone.Signal(getNumber(arg)); + return sig; + }, + }, + input: { + regexp: /^\$\d/, + method: function (arg, self) { + return self.input[getNumber(arg.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { + regexp: /^abs/, + method: applyUnary.bind(this, Tone.Abs), + }, + mod: { + regexp: /^mod/, + method: function (args, self) { + var modulus = literalNumber(args[1]); + var op = new Tone.Modulo(modulus); + self._eval(args[0]).connect(op); + return op; + }, + }, + pow: { + regexp: /^pow/, + method: function (args, self) { + var exp = literalNumber(args[1]); + var op = new Tone.Pow(exp); + self._eval(args[0]).connect(op); + return op; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (args, self) { + var op = new Tone.AudioToGain(); + self._eval(args[0]).connect(op); + return op; + }, + }, + }, + binary: { + "+": { + regexp: /^\+/, + precedence: 1, + method: applyBinary.bind(this, Tone.Add), + }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (args, self) { + if (args.length === 1) { + return applyUnary(Tone.Negate, args, self); + } else { + return applyBinary(Tone.Subtract, args, self); + } + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: applyBinary.bind(this, Tone.Multiply), + }, + }, + unary: { + "-": { + regexp: /^\-/, + method: applyUnary.bind(this, Tone.Negate), + }, + "!": { + regexp: /^\!/, + method: applyUnary.bind(this, Tone.NOT), + }, + }, + }; + Tone.Expr.prototype._parseInputs = function (expr) { + var inputArray = expr.match(/\$\d/g); + var inputMax = 0; + if (inputArray !== null) { + for (var i = 0; i < inputArray.length; i++) { + var inputNum = parseInt(inputArray[i].substr(1)) + 1; + inputMax = Math.max(inputMax, inputNum); + } + } + return inputMax; + }; + Tone.Expr.prototype._replacements = function (args) { + var expr = args.shift(); + for (var i = 0; i < args.length; i++) { + expr = expr.replace(/\%/i, args[i]); + } + return expr; + }; + Tone.Expr.prototype._tokenize = function (expr) { + var position = -1; + var tokens = []; + while (expr.length > 0) { + expr = expr.trim(); + var token = getNextToken(expr); + tokens.push(token); + expr = expr.substr(token.value.length); + } + function getNextToken(expr) { + for (var type in Tone.Expr._Expressions) { + var group = Tone.Expr._Expressions[type]; + for (var opName in group) { + var op = group[opName]; + var reg = op.regexp; + var match = expr.match(reg); + if (match !== null) { + return { + type: type, + value: match[0], + method: op.method, + }; + } + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + expr); + } + return { + next: function () { + return tokens[++position]; + }, + peek: function () { + return tokens[position + 1]; + }, + }; + }; + Tone.Expr.prototype._parseTree = function (expr) { + var lexer = this._tokenize(expr); + var isUndef = this.isUndef.bind(this); + function matchSyntax(token, syn) { + return !isUndef(token) && token.type === "glue" && token.value === syn; + } + function matchGroup(token, groupName, prec) { + var ret = false; + var group = Tone.Expr._Expressions[groupName]; + if (!isUndef(token)) { + for (var opName in group) { + var op = group[opName]; + if (op.regexp.test(token.value)) { + if (!isUndef(prec)) { + if (op.precedence === prec) { + return true; + } + } else { + return true; + } + } + } + } + return ret; + } + function parseExpression(precedence) { + if (isUndef(precedence)) { + precedence = 5; + } + var expr; + if (precedence < 0) { + expr = parseUnary(); + } else { + expr = parseExpression(precedence - 1); + } + var token = lexer.peek(); + while (matchGroup(token, "binary", precedence)) { + token = lexer.next(); + expr = { + operator: token.value, + method: token.method, + args: [expr, parseExpression(precedence - 1)], + }; + token = lexer.peek(); + } + return expr; + } + function parseUnary() { + var token, expr; + token = lexer.peek(); + if (matchGroup(token, "unary")) { + token = lexer.next(); + expr = parseUnary(); + return { + operator: token.value, + method: token.method, + args: [expr], + }; + } + return parsePrimary(); + } + function parsePrimary() { + var token, expr; + token = lexer.peek(); + if (isUndef(token)) { + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + } + if (token.type === "func") { + token = lexer.next(); + return parseFunctionCall(token); + } + if (token.type === "value") { + token = lexer.next(); + return { + method: token.method, + args: token.value, + }; + } + if (matchSyntax(token, "(")) { + lexer.next(); + expr = parseExpression(); + token = lexer.next(); + if (!matchSyntax(token, ")")) { + throw new SyntaxError("Expected )"); + } + return expr; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + token.value + ); + } + function parseFunctionCall(func) { + var token, + args = []; + token = lexer.next(); + if (!matchSyntax(token, "(")) { + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + func.value + '"' + ); + } + token = lexer.peek(); + if (!matchSyntax(token, ")")) { + args = parseArgumentList(); + } + token = lexer.next(); + if (!matchSyntax(token, ")")) { + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + func.value + '"' + ); + } + return { + method: func.method, + args: args, + name: name, + }; + } + function parseArgumentList() { + var token, + expr, + args = []; + while (true) { + expr = parseExpression(); + if (isUndef(expr)) { + break; + } + args.push(expr); + token = lexer.peek(); + if (!matchSyntax(token, ",")) { + break; + } + lexer.next(); + } + return args; + } + return parseExpression(); + }; + Tone.Expr.prototype._eval = function (tree) { + if (!this.isUndef(tree)) { + var node = tree.method(tree.args, this); + this._nodes.push(node); + return node; + } + }; + Tone.Expr.prototype._disposeNodes = function () { + for (var i = 0; i < this._nodes.length; i++) { + var node = this._nodes[i]; + if (this.isFunction(node.dispose)) { + node.dispose(); + } else if (this.isFunction(node.disconnect)) { + node.disconnect(); + } + node = null; + this._nodes[i] = null; + } + this._nodes = null; + }; + Tone.Expr.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._disposeNodes(); + }; + return Tone.Expr; + })( + Tone_core_Tone, + Tone_signal_Add, + Tone_signal_Subtract, + Tone_signal_Multiply, + Tone_signal_GreaterThan, + Tone_signal_GreaterThanZero, + Tone_signal_Abs, + Tone_signal_Negate, + Tone_signal_Modulo, + Tone_signal_Pow + ); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_EqualPowerGain; + Tone_signal_EqualPowerGain = (function (Tone) { + "use strict"; + Tone.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new Tone.WaveShaper( + function (val) { + if (Math.abs(val) < 0.001) { + return 0; + } else { + return this.equalPowerScale(val); + } + }.bind(this), + 4096 + ); + }; + Tone.extend(Tone.EqualPowerGain, Tone.SignalBase); + Tone.EqualPowerGain.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._eqPower.dispose(); + this._eqPower = null; + return this; + }; + return Tone.EqualPowerGain; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_component_CrossFade; + Tone_component_CrossFade = (function (Tone) { + "use strict"; + Tone.CrossFade = function (initialFade) { + this.createInsOuts(2, 1); + this.a = this.input[0] = new Tone.Gain(); + this.b = this.input[1] = new Tone.Gain(); + this.fade = new Tone.Signal( + this.defaultArg(initialFade, 0.5), + Tone.Type.NormalRange + ); + this._equalPowerA = new Tone.EqualPowerGain(); + this._equalPowerB = new Tone.EqualPowerGain(); + this._invert = new Tone.Expr("1 - $0"); + this.a.connect(this.output); + this.b.connect(this.output); + this.fade.chain(this._equalPowerB, this.b.gain); + this.fade.chain(this._invert, this._equalPowerA, this.a.gain); + this._readOnly("fade"); + }; + Tone.extend(Tone.CrossFade); + Tone.CrossFade.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._writable("fade"); + this._equalPowerA.dispose(); + this._equalPowerA = null; + this._equalPowerB.dispose(); + this._equalPowerB = null; + this.fade.dispose(); + this.fade = null; + this._invert.dispose(); + this._invert = null; + this.a.dispose(); + this.a = null; + this.b.dispose(); + this.b = null; + return this; + }; + return Tone.CrossFade; + })( + Tone_core_Tone, + Tone_signal_Signal, + Tone_signal_Expr, + Tone_signal_EqualPowerGain + ); + var effect; + ("use strict"); + effect = (function () { + var p5sound = master; + var CrossFade = Tone_component_CrossFade; + /** + * Effect is a base class for audio effects in p5.
+ * This module handles the nodes and methods that are + * common and useful for current and future effects. + * + * + * This class is extended by p5.Distortion, + * p5.Compressor, + * p5.Delay, + * p5.Filter, + * p5.Reverb. + * + * @class p5.Effect + * @constructor + * + * @param {Object} [ac] Reference to the audio context of the p5 object + * @param {AudioNode} [input] Gain Node effect wrapper + * @param {AudioNode} [output] Gain Node effect wrapper + * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1) + * @param {AudioNode} [wet] Effects that extend this class should connect + * to the wet signal to this gain node, so that dry and wet + * signals are mixed properly. + */ + p5.Effect = function () { + this.ac = p5sound.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); + /** + * The p5.Effect class is built + * using Tone.js CrossFade + * @private + */ + this._drywet = new CrossFade(1); + /** + * In classes that extend + * p5.Effect, connect effect nodes + * to the wet parameter + */ + this.wet = this.ac.createGain(); + this.input.connect(this._drywet.a); + this.wet.connect(this._drywet.b); + this._drywet.connect(this.output); + this.connect(); + //Add to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Set the output volume of the filter. + * + * @method amp + * @param {Number} [vol] amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts until rampTime + * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds + */ + p5.Effect.prototype.amp = function (vol, rampTime, tFromNow) { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime( + currentVol, + now + tFromNow + 0.001 + ); + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + 0.001 + ); + }; + /** + * Link effects together in a chain + * Example usage: filter.chain(reverb, delay, panner); + * May be used with an open-ended number of arguments + * + * @method chain + * @param {Object} [arguments] Chain together multiple sound objects + */ + p5.Effect.prototype.chain = function () { + if (arguments.length > 0) { + this.connect(arguments[0]); + for (var i = 1; i < arguments.length; i += 1) { + arguments[i - 1].connect(arguments[i]); + } + } + return this; + }; + /** + * Adjust the dry/wet value. + * + * @method drywet + * @param {Number} [fade] The desired drywet value (0 - 1.0) + */ + p5.Effect.prototype.drywet = function (fade) { + if (typeof fade !== "undefined") { + this._drywet.fade.value = fade; + } + return this._drywet.fade.value; + }; + /** + * Send output to a p5.js-sound, Web Audio Node, or use signal to + * control an AudioParam + * + * @method connect + * @param {Object} unit + */ + p5.Effect.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Effect.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + p5.Effect.prototype.dispose = function () { + // remove refernce form soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.input) { + this.input.disconnect(); + delete this.input; + } + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this._drywet) { + this._drywet.disconnect(); + delete this._drywet; + } + if (this.wet) { + this.wet.disconnect(); + delete this.wet; + } + this.ac = undefined; + }; + return p5.Effect; + })(master, Tone_component_CrossFade); + var filter; + ("use strict"); + filter = (function () { + var p5sound = master; + var Effect = effect; + /** + *

A p5.Filter uses a Web Audio Biquad Filter to filter + * the frequency response of an input source. Subclasses + * include:

+ * * p5.LowPass: + * Allows frequencies below the cutoff frequency to pass through, + * and attenuates frequencies above the cutoff.
+ * * p5.HighPass: + * The opposite of a lowpass filter.
+ * * p5.BandPass: + * Allows a range of frequencies to pass through and attenuates + * the frequencies below and above this frequency range.
+ * + * The .res() method controls either width of the + * bandpass, or resonance of the low/highpass cutoff frequency. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Filter + * @extends p5.Effect + * @constructor + * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass' + * @example + *
+ * var fft, noise, filter; + * + * function setup() { + * fill(255, 40, 255); + * + * filter = new p5.BandPass(); + * + * noise = new p5.Noise(); + * // disconnect unfiltered noise, + * // and connect to filter + * noise.disconnect(); + * noise.connect(filter); + * noise.start(); + * + * fft = new p5.FFT(); + * } + * + * function draw() { + * background(30); + * + * // set the BandPass frequency based on mouseX + * var freq = map(mouseX, 0, width, 20, 10000); + * filter.freq(freq); + * // give the filter a narrow band (lower res = wider bandpass) + * filter.res(50); + * + * // draw filtered spectrum + * var spectrum = fft.analyze(); + * noStroke(); + * for (var i = 0; i < spectrum.length; i++) { + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width/spectrum.length, h); + * } + * + * isMouseOverCanvas(); + * } + * + * function isMouseOverCanvas() { + * var mX = mouseX, mY = mouseY; + * if (mX > 0 && mX < width && mY < height && mY > 0) { + * noise.amp(0.5, 0.2); + * } else { + * noise.amp(0, 0.2); + * } + * } + *
+ */ + //constructor with inheritance + p5.Filter = function (type) { + Effect.call(this); + //add extend Effect by adding a Biquad Filter + /** + * The p5.Filter is built with a + * + * Web Audio BiquadFilter Node. + * + * @property {DelayNode} biquadFilter + */ + this.biquad = this.ac.createBiquadFilter(); + this.input.connect(this.biquad); + this.biquad.connect(this.wet); + if (type) { + this.setType(type); + } + //Properties useful for the toggle method. + this._on = true; + this._untoggledType = this.biquad.type; + }; + p5.Filter.prototype = Object.create(Effect.prototype); + /** + * Filter an audio signal according to a set + * of filter parameters. + * + * @method process + * @param {Object} Signal An object that outputs audio + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance/Width of the filter frequency + * from 0.001 to 1000 + */ + p5.Filter.prototype.process = function (src, freq, res, time) { + src.connect(this.input); + this.set(freq, res, time); + }; + /** + * Set the frequency and the resonance of the filter. + * + * @method set + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance (Q) from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + p5.Filter.prototype.set = function (freq, res, time) { + if (freq) { + this.freq(freq, time); + } + if (res) { + this.res(res, time); + } + }; + /** + * Set the filter frequency, in Hz, from 10 to 22050 (the range of + * human hearing, although in reality most people hear in a narrower + * range). + * + * @method freq + * @param {Number} freq Filter Frequency + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current frequency value + */ + p5.Filter.prototype.freq = function (freq, time) { + var t = time || 0; + if (freq <= 0) { + freq = 1; + } + if (typeof freq === "number") { + this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.biquad.frequency.exponentialRampToValueAtTime( + freq, + this.ac.currentTime + 0.02 + t + ); + } else if (freq) { + freq.connect(this.biquad.frequency); + } + return this.biquad.frequency.value; + }; + /** + * Controls either width of a bandpass frequency, + * or the resonance of a low/highpass cutoff frequency. + * + * @method res + * @param {Number} res Resonance/Width of filter freq + * from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current res value + */ + p5.Filter.prototype.res = function (res, time) { + var t = time || 0; + if (typeof res === "number") { + this.biquad.Q.value = res; + this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.Q.linearRampToValueAtTime( + res, + this.ac.currentTime + 0.02 + t + ); + } else if (res) { + res.connect(this.biquad.Q); + } + return this.biquad.Q.value; + }; + /** + * Controls the gain attribute of a Biquad Filter. + * This is distinctly different from .amp() which is inherited from p5.Effect + * .amp() controls the volume via the output gain node + * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. + * + * @method gain + * @param {Number} gain + * @return {Number} Returns the current or updated gain value + */ + p5.Filter.prototype.gain = function (gain, time) { + var t = time || 0; + if (typeof gain === "number") { + this.biquad.gain.value = gain; + this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.gain.linearRampToValueAtTime( + gain, + this.ac.currentTime + 0.02 + t + ); + } else if (gain) { + gain.connect(this.biquad.gain); + } + return this.biquad.gain.value; + }; + /** + * Toggle function. Switches between the specified type and allpass + * + * @method toggle + * @return {boolean} [Toggle value] + */ + p5.Filter.prototype.toggle = function () { + this._on = !this._on; + if (this._on === true) { + this.biquad.type = this._untoggledType; + } else if (this._on === false) { + this.biquad.type = "allpass"; + } + return this._on; + }; + /** + * Set the type of a p5.Filter. Possible types include: + * "lowpass" (default), "highpass", "bandpass", + * "lowshelf", "highshelf", "peaking", "notch", + * "allpass". + * + * @method setType + * @param {String} t + */ + p5.Filter.prototype.setType = function (t) { + this.biquad.type = t; + this._untoggledType = this.biquad.type; + }; + p5.Filter.prototype.dispose = function () { + // remove reference from soundArray + Effect.prototype.dispose.apply(this); + if (this.biquad) { + this.biquad.disconnect(); + delete this.biquad; + } + }; + /** + * Constructor: new p5.LowPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('lowpass'). + * See p5.Filter for methods. + * + * @class p5.LowPass + * @constructor + * @extends p5.Filter + */ + p5.LowPass = function () { + p5.Filter.call(this, "lowpass"); + }; + p5.LowPass.prototype = Object.create(p5.Filter.prototype); + /** + * Constructor: new p5.HighPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('highpass'). + * See p5.Filter for methods. + * + * @class p5.HighPass + * @constructor + * @extends p5.Filter + */ + p5.HighPass = function () { + p5.Filter.call(this, "highpass"); + }; + p5.HighPass.prototype = Object.create(p5.Filter.prototype); + /** + * Constructor: new p5.BandPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('bandpass'). + * See p5.Filter for methods. + * + * @class p5.BandPass + * @constructor + * @extends p5.Filter + */ + p5.BandPass = function () { + p5.Filter.call(this, "bandpass"); + }; + p5.BandPass.prototype = Object.create(p5.Filter.prototype); + return p5.Filter; + })(master, effect); + var src_eqFilter; + ("use strict"); + src_eqFilter = (function () { + var Filter = filter; + var p5sound = master; + /** + * EQFilter extends p5.Filter with constraints + * necessary for the p5.EQ + * + * @private + */ + var EQFilter = function (freq, res) { + Filter.call(this, "peaking"); + this.disconnect(); + this.set(freq, res); + this.biquad.gain.value = 0; + delete this.input; + delete this.output; + delete this._drywet; + delete this.wet; + }; + EQFilter.prototype = Object.create(Filter.prototype); + EQFilter.prototype.amp = function () { + console.warn("`amp()` is not available for p5.EQ bands. Use `.gain()`"); + }; + EQFilter.prototype.drywet = function () { + console.warn("`drywet()` is not available for p5.EQ bands."); + }; + EQFilter.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + if (this.biquad) { + this.biquad.connect(u.input ? u.input : u); + } else { + this.output.connect(u.input ? u.input : u); + } + }; + EQFilter.prototype.disconnect = function () { + if (this.biquad) { + this.biquad.disconnect(); + } + }; + EQFilter.prototype.dispose = function () { + // remove reference form soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.disconnect(); + delete this.biquad; + }; + return EQFilter; + })(filter, master); + var eq; + ("use strict"); + eq = (function () { + var Effect = effect; + var EQFilter = src_eqFilter; + /** + * p5.EQ is an audio effect that performs the function of a multiband + * audio equalizer. Equalization is used to adjust the balance of + * frequency compoenents of an audio signal. This process is commonly used + * in sound production and recording to change the waveform before it reaches + * a sound output device. EQ can also be used as an audio effect to create + * interesting distortions by filtering out parts of the spectrum. p5.EQ is + * built using a chain of Web Audio Biquad Filter Nodes and can be + * instantiated with 3 or 8 bands. Bands can be added or removed from + * the EQ by directly modifying p5.EQ.bands (the array that stores filters). + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.EQ + * @constructor + * @extends p5.Effect + * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 + * @return {Object} p5.EQ object + * + * @example + *
+ * var eq; + * var band_names; + * var band_index; + * + * var soundFile, play; + * + * function preload() { + * soundFormats('mp3', 'ogg'); + * soundFile = loadSound('assets/beat'); + * } + * + * function setup() { + * eq = new p5.EQ(3); + * soundFile.disconnect(); + * eq.process(soundFile); + * + * band_names = ['lows','mids','highs']; + * band_index = 0; + * play = false; + * textAlign(CENTER); + * } + * + * function draw() { + * background(30); + * noStroke(); + * fill(255); + * text('click to kill',50,25); + * + * fill(255, 40, 255); + * textSize(26); + * text(band_names[band_index],50,55); + * + * fill(255); + * textSize(9); + * text('space = play/pause',50,80); + * } + * + * //If mouse is over canvas, cycle to the next band and kill the frequency + * function mouseClicked() { + * for (var i = 0; i < eq.bands.length; i++) { + * eq.bands[i].gain(0); + * } + * eq.bands[band_index].gain(-40); + * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { + * band_index === 2 ? band_index = 0 : band_index++; + * } + * } + * + * //use space bar to trigger play / pause + * function keyPressed() { + * if (key===' ') { + * play = !play + * play ? soundFile.loop() : soundFile.pause(); + * } + * } + *
+ */ + p5.EQ = function (_eqsize) { + Effect.call(this); + //p5.EQ can be of size (3) or (8), defaults to 3 + _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; + var factor; + _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2); + /** + * The p5.EQ is built with abstracted p5.Filter objects. + * To modify any bands, use methods of the + * p5.Filter API, especially `gain` and `freq`. + * Bands are stored in an array, with indices 0 - 3, or 0 - 7 + * @property {Array} bands + * + */ + this.bands = []; + var freq, res; + for (var i = 0; i < _eqsize; i++) { + if (i === _eqsize - 1) { + freq = 21000; + res = 0.01; + } else if (i === 0) { + freq = 100; + res = 0.1; + } else if (i === 1) { + freq = _eqsize === 3 ? 360 * factor : 360; + res = 1; + } else { + freq = this.bands[i - 1].freq() * factor; + res = 1; + } + this.bands[i] = this._newBand(freq, res); + if (i > 0) { + this.bands[i - 1].connect(this.bands[i].biquad); + } else { + this.input.connect(this.bands[i].biquad); + } + } + this.bands[_eqsize - 1].connect(this.output); + }; + p5.EQ.prototype = Object.create(Effect.prototype); + /** + * Process an input by connecting it to the EQ + * @method process + * @param {Object} src Audio source + */ + p5.EQ.prototype.process = function (src) { + src.connect(this.input); + }; + // /** + // * Set the frequency and gain of each band in the EQ. This method should be + // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. + // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); + // * + // * @method set + // * @param {Number} [freq0] Frequency value for band with index 0 + // * @param {Number} [gain0] Gain value for band with index 0 + // * @param {Number} [freq1] Frequency value for band with index 1 + // * @param {Number} [gain1] Gain value for band with index 1 + // * @param {Number} [freq2] Frequency value for band with index 2 + // * @param {Number} [gain2] Gain value for band with index 2 + // * @param {Number} [freq3] Frequency value for band with index 3 + // * @param {Number} [gain3] Gain value for band with index 3 + // * @param {Number} [freq4] Frequency value for band with index 4 + // * @param {Number} [gain4] Gain value for band with index 4 + // * @param {Number} [freq5] Frequency value for band with index 5 + // * @param {Number} [gain5] Gain value for band with index 5 + // * @param {Number} [freq6] Frequency value for band with index 6 + // * @param {Number} [gain6] Gain value for band with index 6 + // * @param {Number} [freq7] Frequency value for band with index 7 + // * @param {Number} [gain7] Gain value for band with index 7 + // */ + p5.EQ.prototype.set = function () { + if (arguments.length === this.bands.length * 2) { + for (var i = 0; i < arguments.length; i += 2) { + this.bands[i / 2].freq(arguments[i]); + this.bands[i / 2].gain(arguments[i + 1]); + } + } else { + console.error( + "Argument mismatch. .set() should be called with " + + this.bands.length * 2 + + " arguments. (one frequency and gain value pair for each band of the eq)" + ); + } + }; + /** + * Add a new band. Creates a p5.Filter and strips away everything but + * the raw biquad filter. This method returns an abstracted p5.Filter, + * which can be added to p5.EQ.bands, in order to create new EQ bands. + * @private + * @method _newBand + * @param {Number} freq + * @param {Number} res + * @return {Object} Abstracted Filter + */ + p5.EQ.prototype._newBand = function (freq, res) { + return new EQFilter(freq, res); + }; + p5.EQ.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.bands) { + while (this.bands.length > 0) { + delete this.bands.pop().dispose(); + } + delete this.bands; + } + }; + return p5.EQ; + })(effect, src_eqFilter); + var panner3d; + ("use strict"); + panner3d = (function () { + var p5sound = master; + var Effect = effect; + /** + * Panner3D is based on the + * Web Audio Spatial Panner Node. + * This panner is a spatial processing node that allows audio to be positioned + * and oriented in 3D space. + * + * The position is relative to an + * Audio Context Listener, which can be accessed + * by p5.soundOut.audiocontext.listener + * + * + * @class p5.Panner3D + * @constructor + */ + p5.Panner3D = function () { + Effect.call(this); + /** + * + * Web Audio Spatial Panner Node + * + * Properties include + * - panningModel: "equal power" or "HRTF" + * - distanceModel: "linear", "inverse", or "exponential" + * + * @property {AudioNode} panner + * + */ + this.panner = this.ac.createPanner(); + this.panner.panningModel = "HRTF"; + this.panner.distanceModel = "linear"; + this.panner.connect(this.output); + this.input.connect(this.panner); + }; + p5.Panner3D.prototype = Object.create(Effect.prototype); + /** + * Connect an audio sorce + * + * @method process + * @param {Object} src Input source + */ + p5.Panner3D.prototype.process = function (src) { + src.connect(this.input); + }; + /** + * Set the X,Y,Z position of the Panner + * @method set + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ]; + }; + /** + * Getter and setter methods for position coordinates + * @method positionX + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for position coordinates + * @method positionY + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for position coordinates + * @method positionZ + * @return {Number} updated coordinate value + */ + p5.Panner3D.prototype.positionX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.panner.positionX.value = xVal; + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.panner.positionX); + } + return this.panner.positionX.value; + }; + p5.Panner3D.prototype.positionY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.panner.positionY.value = yVal; + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.panner.positionY); + } + return this.panner.positionY.value; + }; + p5.Panner3D.prototype.positionZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.panner.positionZ.value = zVal; + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.panner.positionZ); + } + return this.panner.positionZ.value; + }; + /** + * Set the X,Y,Z position of the Panner + * @method orient + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) { + this.orientX(xVal, time); + this.orientY(yVal, time); + this.orientZ(zVal, time); + return [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ]; + }; + /** + * Getter and setter methods for orient coordinates + * @method orientX + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for orient coordinates + * @method orientY + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for orient coordinates + * @method orientZ + * @return {Number} updated coordinate value + */ + p5.Panner3D.prototype.orientX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.panner.orientationX.value = xVal; + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.panner.orientationX); + } + return this.panner.orientationX.value; + }; + p5.Panner3D.prototype.orientY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.panner.orientationY.value = yVal; + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.panner.orientationY); + } + return this.panner.orientationY.value; + }; + p5.Panner3D.prototype.orientZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.panner.orientationZ.value = zVal; + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.panner.orientationZ); + } + return this.panner.orientationZ.value; + }; + /** + * Set the rolloff factor and max distance + * @method setFalloff + * @param {Number} [maxDistance] + * @param {Number} [rolloffFactor] + */ + p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) { + this.maxDist(maxDistance); + this.rolloff(rolloffFactor); + }; + /** + * Maxium distance between the source and the listener + * @method maxDist + * @param {Number} maxDistance + * @return {Number} updated value + */ + p5.Panner3D.prototype.maxDist = function (maxDistance) { + if (typeof maxDistance === "number") { + this.panner.maxDistance = maxDistance; + } + return this.panner.maxDistance; + }; + /** + * How quickly the volume is reduced as the source moves away from the listener + * @method rollof + * @param {Number} rolloffFactor + * @return {Number} updated value + */ + p5.Panner3D.prototype.rolloff = function (rolloffFactor) { + if (typeof rolloffFactor === "number") { + this.panner.rolloffFactor = rolloffFactor; + } + return this.panner.rolloffFactor; + }; + p5.Panner3D.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.panner) { + this.panner.disconnect(); + delete this.panner; + } + }; + return p5.Panner3D; + })(master, effect); + var listener3d; + ("use strict"); + listener3d = (function () { + var p5sound = master; + var Effect = effect; + // /** + // * listener is a class that can construct both a Spatial Panner + // * and a Spatial Listener. The panner is based on the + // * Web Audio Spatial Panner Node + // * https://www.w3.org/TR/webaudio/#the-listenernode-interface + // * This panner is a spatial processing node that allows audio to be positioned + // * and oriented in 3D space. + // * + // * The Listener modifies the properties of the Audio Context Listener. + // * Both objects types use the same methods. The default is a spatial panner. + // * + // * p5.Panner3D - Constructs a Spatial Panner
+ // * p5.Listener3D - Constructs a Spatial Listener
+ // * + // * @class listener + // * @constructor + // * @return {Object} p5.Listener3D Object + // * + // * @param {Web Audio Node} listener Web Audio Spatial Panning Node + // * @param {AudioParam} listener.panningModel "equal power" or "HRTF" + // * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential" + // * @param {String} [type] [Specify construction of a spatial panner or listener] + // */ + p5.Listener3D = function (type) { + this.ac = p5sound.audiocontext; + this.listener = this.ac.listener; + }; + // /** + // * Connect an audio sorce + // * @param {Object} src Input source + // */ + p5.Listener3D.prototype.process = function (src) { + src.connect(this.input); + }; + // /** + // * Set the X,Y,Z position of the Panner + // * @param {[Number]} xVal + // * @param {[Number]} yVal + // * @param {[Number]} zVal + // * @param {[Number]} time + // * @return {[Array]} [Updated x, y, z values as an array] + // */ + p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ]; + }; + // /** + // * Getter and setter methods for position coordinates + // * @return {Number} [updated coordinate value] + // */ + p5.Listener3D.prototype.positionX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.positionX.value = xVal; + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.positionX); + } + return this.listener.positionX.value; + }; + p5.Listener3D.prototype.positionY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.positionY.value = yVal; + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.positionY); + } + return this.listener.positionY.value; + }; + p5.Listener3D.prototype.positionZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.positionZ.value = zVal; + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.positionZ); + } + return this.listener.positionZ.value; + }; + // cannot define method when class definition is commented + // /** + // * Overrides the listener orient() method because Listener has slightly + // * different params. In human terms, Forward vectors are the direction the + // * nose is pointing. Up vectors are the direction of the top of the head. + // * + // * @method orient + // * @param {Number} xValF Forward vector X direction + // * @param {Number} yValF Forward vector Y direction + // * @param {Number} zValF Forward vector Z direction + // * @param {Number} xValU Up vector X direction + // * @param {Number} yValU Up vector Y direction + // * @param {Number} zValU Up vector Z direction + // * @param {Number} time + // * @return {Array} All orienation params + // */ + p5.Listener3D.prototype.orient = function ( + xValF, + yValF, + zValF, + xValU, + yValU, + zValU, + time + ) { + if (arguments.length === 3 || arguments.length === 4) { + time = arguments[3]; + this.orientForward(xValF, yValF, zValF, time); + } else if (arguments.length === 6 || arguments === 7) { + this.orientForward(xValF, yValF, zValF); + this.orientUp(xValU, yValU, zValU, time); + } + return [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ]; + }; + p5.Listener3D.prototype.orientForward = function ( + xValF, + yValF, + zValF, + time + ) { + this.forwardX(xValF, time); + this.forwardY(yValF, time); + this.forwardZ(zValF, time); + return [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ]; + }; + p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) { + this.upX(xValU, time); + this.upY(yValU, time); + this.upZ(zValU, time); + return [this.listener.upX, this.listener.upY, this.listener.upZ]; + }; + // /** + // * Getter and setter methods for orient coordinates + // * @return {Number} [updated coordinate value] + // */ + p5.Listener3D.prototype.forwardX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.forwardX.value = xVal; + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.forwardX); + } + return this.listener.forwardX.value; + }; + p5.Listener3D.prototype.forwardY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.forwardY.value = yVal; + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.forwardY); + } + return this.listener.forwardY.value; + }; + p5.Listener3D.prototype.forwardZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.forwardZ.value = zVal; + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.forwardZ); + } + return this.listener.forwardZ.value; + }; + p5.Listener3D.prototype.upX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.upX.value = xVal; + this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.upX); + } + return this.listener.upX.value; + }; + p5.Listener3D.prototype.upY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.upY.value = yVal; + this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.upY); + } + return this.listener.upY.value; + }; + p5.Listener3D.prototype.upZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.upZ.value = zVal; + this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.upZ); + } + return this.listener.upZ.value; + }; + return p5.Listener3D; + })(master, effect); + var delay; + ("use strict"); + delay = (function () { + var Filter = filter; + var Effect = effect; + /** + * Delay is an echo effect. It processes an existing sound source, + * and outputs a delayed version of that sound. The p5.Delay can + * produce different effects depending on the delayTime, feedback, + * filter, and type. In the example below, a feedback of 0.5 (the + * defaul value) will produce a looping delay that decreases in + * volume by 50% each repeat. A filter will cut out the high + * frequencies so that the delay does not sound as piercing as the + * original source. + * + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * @class p5.Delay + * @extends p5.Effect + * @constructor + * @example + *
+ * var noise, env, delay; + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * noise = new p5.Noise('brown'); + * noise.amp(0); + * noise.start(); + * + * delay = new p5.Delay(); + * + * // delay.process() accepts 4 parameters: + * // source, delayTime, feedback, filter frequency + * // play with these numbers!! + * delay.process(noise, .12, .7, 2300); + * + * // play the noise with an envelope, + * // a series of fades ( time / value pairs ) + * env = new p5.Envelope(.01, 0.2, .2, .1); + * } + * + * // mouseClick triggers envelope + * function mouseClicked() { + * // is mouse over canvas? + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * env.play(noise); + * } + * } + *
+ */ + p5.Delay = function () { + Effect.call(this); + this._split = this.ac.createChannelSplitter(2); + this._merge = this.ac.createChannelMerger(2); + this._leftGain = this.ac.createGain(); + this._rightGain = this.ac.createGain(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * + * @property {DelayNode} leftDelay + */ + this.leftDelay = this.ac.createDelay(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * + * @property {DelayNode} rightDelay + */ + this.rightDelay = this.ac.createDelay(); + this._leftFilter = new Filter(); + this._rightFilter = new Filter(); + this._leftFilter.disconnect(); + this._rightFilter.disconnect(); + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ); + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ); + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + // graph routing + this.input.connect(this._split); + this.leftDelay.connect(this._leftGain); + this.rightDelay.connect(this._rightGain); + this._leftGain.connect(this._leftFilter.input); + this._rightGain.connect(this._rightFilter.input); + this._merge.connect(this.wet); + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + // default routing + this.setType(0); + this._maxDelay = this.leftDelay.delayTime.maxValue; + // set initial feedback to 0.5 + this.feedback(0.5); + }; + p5.Delay.prototype = Object.create(Effect.prototype); + /** + * Add delay to an audio signal according to a set + * of delay parameters. + * + * @method process + * @param {Object} Signal An object that outputs audio + * @param {Number} [delayTime] Time (in seconds) of the delay/echo. + * Some browsers limit delayTime to + * 1 second. + * @param {Number} [feedback] sends the delay back through itself + * in a loop that decreases in volume + * each time. + * @param {Number} [lowPass] Cutoff frequency. Only frequencies + * below the lowPass will be part of the + * delay. + */ + p5.Delay.prototype.process = function ( + src, + _delayTime, + _feedback, + _filter + ) { + var feedback = _feedback || 0; + var delayTime = _delayTime || 0; + if (feedback >= 1) { + throw new Error("Feedback value will force a positive feedback loop."); + } + if (delayTime >= this._maxDelay) { + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + } + src.connect(this.input); + this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this._leftGain.gain.value = feedback; + this._rightGain.gain.value = feedback; + if (_filter) { + this._leftFilter.freq(_filter); + this._rightFilter.freq(_filter); + } + }; + /** + * Set the delay (echo) time, in seconds. Usually this value will be + * a floating point number between 0.0 and 1.0. + * + * @method delayTime + * @param {Number} delayTime Time (in seconds) of the delay + */ + p5.Delay.prototype.delayTime = function (t) { + // if t is an audio node... + if (typeof t !== "number") { + t.connect(this.leftDelay.delayTime); + t.connect(this.rightDelay.delayTime); + } else { + this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime); + this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime); + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ); + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ); + } + }; + /** + * Feedback occurs when Delay sends its signal back through its input + * in a loop. The feedback amount determines how much signal to send each + * time through the loop. A feedback greater than 1.0 is not desirable because + * it will increase the overall output each time through the loop, + * creating an infinite feedback loop. The default value is 0.5 + * + * @method feedback + * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an + * Oscillator that can be used to + * modulate this param + * @returns {Number} Feedback value + * + */ + p5.Delay.prototype.feedback = function (f) { + // if f is an audio node... + if (f && typeof f !== "number") { + f.connect(this._leftGain.gain); + f.connect(this._rightGain.gain); + } else if (f >= 1) { + throw new Error("Feedback value will force a positive feedback loop."); + } else if (typeof f === "number") { + this._leftGain.gain.value = f; + this._rightGain.gain.value = f; + } + // return value of feedback + return this._leftGain.gain.value; + }; + /** + * Set a lowpass filter frequency for the delay. A lowpass filter + * will cut off any frequencies higher than the filter frequency. + * + * @method filter + * @param {Number|Object} cutoffFreq A lowpass filter will cut off any + * frequencies higher than the filter frequency. + * @param {Number|Object} res Resonance of the filter frequency + * cutoff, or an object (i.e. a p5.Oscillator) + * that can be used to modulate this parameter. + * High numbers (i.e. 15) will produce a resonance, + * low numbers (i.e. .2) will produce a slope. + */ + p5.Delay.prototype.filter = function (freq, q) { + this._leftFilter.set(freq, q); + this._rightFilter.set(freq, q); + }; + /** + * Choose a preset type of delay. 'pingPong' bounces the signal + * from the left to the right channel to produce a stereo effect. + * Any other parameter will revert to the default delay setting. + * + * @method setType + * @param {String|Number} type 'pingPong' (1) or 'default' (0) + */ + p5.Delay.prototype.setType = function (t) { + if (t === 1) { + t = "pingPong"; + } + this._split.disconnect(); + this._leftFilter.disconnect(); + this._rightFilter.disconnect(); + this._split.connect(this.leftDelay, 0); + this._split.connect(this.rightDelay, 1); + switch (t) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type); + this._leftFilter.output.connect(this._merge, 0, 0); + this._rightFilter.output.connect(this._merge, 0, 1); + this._leftFilter.output.connect(this.rightDelay); + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0); + this._rightFilter.output.connect(this._merge, 0, 1); + this._leftFilter.output.connect(this.leftDelay); + this._rightFilter.output.connect(this.rightDelay); + } + }; + // DocBlocks for methods inherited from p5.Effect + /** + * Set the output level of the delay effect. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Delay.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + this._split.disconnect(); + this._leftFilter.dispose(); + this._rightFilter.dispose(); + this._merge.disconnect(); + this._leftGain.disconnect(); + this._rightGain.disconnect(); + this.leftDelay.disconnect(); + this.rightDelay.disconnect(); + this._split = undefined; + this._leftFilter = undefined; + this._rightFilter = undefined; + this._merge = undefined; + this._leftGain = undefined; + this._rightGain = undefined; + this.leftDelay = undefined; + this.rightDelay = undefined; + }; + })(filter, effect); + var reverb; + ("use strict"); + reverb = (function () { + var CustomError = errorHandler; + var Effect = effect; + /** + * Reverb adds depth to a sound through a large number of decaying + * echoes. It creates the perception that sound is occurring in a + * physical space. The p5.Reverb has paramters for Time (how long does the + * reverb last) and decayRate (how much the sound decays with each echo) + * that can be set with the .set() or .process() methods. The p5.Convolver + * extends p5.Reverb allowing you to recreate the sound of actual physical + * spaces through convolution. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Reverb + * @extends p5.Effect + * @constructor + * @example + *
+ * var soundFile, reverb; + * function preload() { + * soundFile = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * reverb = new p5.Reverb(); + * soundFile.disconnect(); // so we'll only hear reverb... + * + * // connect soundFile to reverb, process w/ + * // 3 second reverbTime, decayRate of 2% + * reverb.process(soundFile, 3, 2); + * soundFile.play(); + * } + *
+ */ + p5.Reverb = function () { + Effect.call(this); + this._initConvolverNode(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + // default params + this._seconds = 3; + this._decay = 2; + this._reverse = false; + this._buildImpulse(); + }; + p5.Reverb.prototype = Object.create(Effect.prototype); + p5.Reverb.prototype._initConvolverNode = function () { + this.convolverNode = this.ac.createConvolver(); + this.input.connect(this.convolverNode); + this.convolverNode.connect(this.wet); + }; + p5.Reverb.prototype._teardownConvolverNode = function () { + if (this.convolverNode) { + this.convolverNode.disconnect(); + delete this.convolverNode; + } + }; + p5.Reverb.prototype._setBuffer = function (audioBuffer) { + this._teardownConvolverNode(); + this._initConvolverNode(); + this.convolverNode.buffer = audioBuffer; + }; + /** + * Connect a source to the reverb, and assign reverb parameters. + * + * @method process + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) { + src.connect(this.input); + var rebuild = false; + if (seconds) { + this._seconds = seconds; + rebuild = true; + } + if (decayRate) { + this._decay = decayRate; + } + if (reverse) { + this._reverse = reverse; + } + if (rebuild) { + this._buildImpulse(); + } + }; + /** + * Set the reverb settings. Similar to .process(), but without + * assigning a new input. + * + * @method set + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + p5.Reverb.prototype.set = function (seconds, decayRate, reverse) { + var rebuild = false; + if (seconds) { + this._seconds = seconds; + rebuild = true; + } + if (decayRate) { + this._decay = decayRate; + } + if (reverse) { + this._reverse = reverse; + } + if (rebuild) { + this._buildImpulse(); + } + }; + // DocBlocks for methods inherited from p5.Effect + /** + * Set the output level of the reverb effect. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + /** + * Disconnect all output. + * + * @method disconnect + */ + /** + * Inspired by Simple Reverb by Jordan Santell + * https://github.com/web-audio-components/simple-reverb/blob/master/index.js + * + * Utility function for building an impulse response + * based on the module parameters. + * + * @private + */ + p5.Reverb.prototype._buildImpulse = function () { + var rate = this.ac.sampleRate; + var length = rate * this._seconds; + var decay = this._decay; + var impulse = this.ac.createBuffer(2, length, rate); + var impulseL = impulse.getChannelData(0); + var impulseR = impulse.getChannelData(1); + var n, i; + for (i = 0; i < length; i++) { + n = this._reverse ? length - i : i; + impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + } + this._setBuffer(impulse); + }; + p5.Reverb.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + this._teardownConvolverNode(); + }; + // ======================================================================= + // *** p5.Convolver *** + // ======================================================================= + /** + *

p5.Convolver extends p5.Reverb. It can emulate the sound of real + * physical spaces through a process called + * convolution.

+ * + *

Convolution multiplies any audio input by an "impulse response" + * to simulate the dispersion of sound over time. The impulse response is + * generated from an audio file that you provide. One way to + * generate an impulse response is to pop a balloon in a reverberant space + * and record the echo. Convolution can also be used to experiment with + * sound.

+ * + *

Use the method createConvolution(path) to instantiate a + * p5.Convolver with a path to your impulse response audio file.

+ * + * @class p5.Convolver + * @extends p5.Effect + * @constructor + * @param {String} path path to a sound file + * @param {Function} [callback] function to call when loading succeeds + * @param {Function} [errorCallback] function to call if loading fails. + * This function will receive an error or + * XMLHttpRequest object with information + * about what went wrong. + * @example + *
+ * var cVerb, sound; + * function preload() { + * // We have both MP3 and OGG versions of all sound assets + * soundFormats('ogg', 'mp3'); + * + * // Try replacing 'bx-spring' with other soundfiles like + * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' + * cVerb = createConvolver('assets/bx-spring.mp3'); + * + * // Try replacing 'Damscray_DancingTiger' with + * // 'beat', 'doorbell', lucky_dragons_-_power_melody' + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.Convolver = function (path, callback, errorCallback) { + p5.Reverb.call(this); + /** + * Internally, the p5.Convolver uses the a + * + * Web Audio Convolver Node. + * + * @property {ConvolverNode} convolverNode + */ + this._initConvolverNode(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + if (path) { + this.impulses = []; + this._loadBuffer(path, callback, errorCallback); + } else { + // parameters + this._seconds = 3; + this._decay = 2; + this._reverse = false; + this._buildImpulse(); + } + }; + p5.Convolver.prototype = Object.create(p5.Reverb.prototype); + p5.prototype.registerPreloadMethod("createConvolver", p5.prototype); + /** + * Create a p5.Convolver. Accepts a path to a soundfile + * that will be used to generate an impulse response. + * + * @method createConvolver + * @param {String} path path to a sound file + * @param {Function} [callback] function to call if loading is successful. + * The object will be passed in as the argument + * to the callback function. + * @param {Function} [errorCallback] function to call if loading is not successful. + * A custom error will be passed in as the argument + * to the callback function. + * @return {p5.Convolver} + * @example + *
+ * var cVerb, sound; + * function preload() { + * // We have both MP3 and OGG versions of all sound assets + * soundFormats('ogg', 'mp3'); + * + * // Try replacing 'bx-spring' with other soundfiles like + * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' + * cVerb = createConvolver('assets/bx-spring.mp3'); + * + * // Try replacing 'Damscray_DancingTiger' with + * // 'beat', 'doorbell', lucky_dragons_-_power_melody' + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.prototype.createConvolver = function (path, callback, errorCallback) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + var self = this; + var cReverb = new p5.Convolver( + path, + function (buffer) { + if (typeof callback === "function") { + callback(buffer); + } + if (typeof self._decrementPreload === "function") { + self._decrementPreload(); + } + }, + errorCallback + ); + cReverb.impulses = []; + return cReverb; + }; + /** + * Private method to load a buffer as an Impulse Response, + * assign it to the convolverNode, and add to the Array of .impulses. + * + * @param {String} path + * @param {Function} callback + * @param {Function} errorCallback + * @private + */ + p5.Convolver.prototype._loadBuffer = function ( + path, + callback, + errorCallback + ) { + var path = p5.prototype._checkFileFormats(path); + var self = this; + var errorTrace = new Error().stack; + var ac = p5.prototype.getAudioContext(); + var request = new XMLHttpRequest(); + request.open("GET", path, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status === 200) { + // on success loading file: + ac.decodeAudioData( + request.response, + function (buff) { + var buffer = {}; + var chunks = path.split("/"); + buffer.name = chunks[chunks.length - 1]; + buffer.audioBuffer = buff; + self.impulses.push(buffer); + self._setBuffer(buffer.audioBuffer); + if (callback) { + callback(buffer); + } + }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 + function () { + var err = new CustomError( + "decodeAudioData", + errorTrace, + self.url + ); + var msg = "AudioContext error at decodeAudioData for " + self.url; + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + ); + } else { + var err = new CustomError("loadConvolver", errorTrace, self.url); + var msg = + "Unable to load " + + self.url + + ". The request status was: " + + request.status + + " (" + + request.statusText + + ")"; + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + }; + // if there is another error, aside from 404... + request.onerror = function () { + var err = new CustomError("loadConvolver", errorTrace, self.url); + var msg = + "There was no response from the server at " + + self.url + + ". Check the url and internet connectivity."; + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + }; + request.send(); + }; + p5.Convolver.prototype.set = null; + /** + * Connect a source to the reverb, and assign reverb parameters. + * + * @method process + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @example + *
+ * var cVerb, sound; + * function preload() { + * soundFormats('ogg', 'mp3'); + * + * cVerb = createConvolver('assets/concrete-tunnel.mp3'); + * + * sound = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with (i.e. connect to) cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.Convolver.prototype.process = function (src) { + src.connect(this.input); + }; + /** + * If you load multiple impulse files using the .addImpulse method, + * they will be stored as Objects in this Array. Toggle between them + * with the toggleImpulse(id) method. + * + * @property {Array} impulses + */ + p5.Convolver.prototype.impulses = []; + /** + * Load and assign a new Impulse Response to the p5.Convolver. + * The impulse is added to the .impulses array. Previous + * impulses can be accessed with the .toggleImpulse(id) + * method. + * + * @method addImpulse + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + p5.Convolver.prototype.addImpulse = function ( + path, + callback, + errorCallback + ) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + this._loadBuffer(path, callback, errorCallback); + }; + /** + * Similar to .addImpulse, except that the .impulses + * Array is reset to save memory. A new .impulses + * array is created with this impulse as the only item. + * + * @method resetImpulse + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + p5.Convolver.prototype.resetImpulse = function ( + path, + callback, + errorCallback + ) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + this.impulses = []; + this._loadBuffer(path, callback, errorCallback); + }; + /** + * If you have used .addImpulse() to add multiple impulses + * to a p5.Convolver, then you can use this method to toggle between + * the items in the .impulses Array. Accepts a parameter + * to identify which impulse you wish to use, identified either by its + * original filename (String) or by its position in the .impulses + * Array (Number).
+ * You can access the objects in the .impulses Array directly. Each + * Object has two attributes: an .audioBuffer (type: + * Web Audio + * AudioBuffer) and a .name, a String that corresponds + * with the original filename. + * + * @method toggleImpulse + * @param {String|Number} id Identify the impulse by its original filename + * (String), or by its position in the + * .impulses Array (Number). + */ + p5.Convolver.prototype.toggleImpulse = function (id) { + if (typeof id === "number" && id < this.impulses.length) { + this._setBuffer(this.impulses[id].audioBuffer); + } + if (typeof id === "string") { + for (var i = 0; i < this.impulses.length; i++) { + if (this.impulses[i].name === id) { + this._setBuffer(this.impulses[i].audioBuffer); + break; + } + } + } + }; + p5.Convolver.prototype.dispose = function () { + p5.Reverb.prototype.dispose.apply(this); + // remove all the Impulse Response buffers + for (var i in this.impulses) { + if (this.impulses[i]) { + this.impulses[i] = null; + } + } + }; + })(errorHandler, effect); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_TimelineState; + Tone_core_TimelineState = (function (Tone) { + "use strict"; + Tone.TimelineState = function (initial) { + Tone.Timeline.call(this); + this._initial = initial; + }; + Tone.extend(Tone.TimelineState, Tone.Timeline); + Tone.TimelineState.prototype.getValueAtTime = function (time) { + var event = this.get(time); + if (event !== null) { + return event.state; + } else { + return this._initial; + } + }; + Tone.TimelineState.prototype.setStateAtTime = function (state, time) { + this.add({ + state: state, + time: time, + }); + }; + return Tone.TimelineState; + })(Tone_core_Tone, Tone_core_Timeline); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Clock; + Tone_core_Clock = (function (Tone) { + "use strict"; + Tone.Clock = function () { + Tone.Emitter.call(this); + var options = this.optionsObject( + arguments, + ["callback", "frequency"], + Tone.Clock.defaults + ); + this.callback = options.callback; + this._nextTick = 0; + this._lastState = Tone.State.Stopped; + this.frequency = new Tone.TimelineSignal( + options.frequency, + Tone.Type.Frequency + ); + this._readOnly("frequency"); + this.ticks = 0; + this._state = new Tone.TimelineState(Tone.State.Stopped); + this._boundLoop = this._loop.bind(this); + this.context.on("tick", this._boundLoop); + }; + Tone.extend(Tone.Clock, Tone.Emitter); + Tone.Clock.defaults = { + callback: Tone.noOp, + frequency: 1, + lookAhead: "auto", + }; + Object.defineProperty(Tone.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }); + Tone.Clock.prototype.start = function (time, offset) { + time = this.toSeconds(time); + if (this._state.getValueAtTime(time) !== Tone.State.Started) { + this._state.add({ + state: Tone.State.Started, + time: time, + offset: offset, + }); + } + return this; + }; + Tone.Clock.prototype.stop = function (time) { + time = this.toSeconds(time); + this._state.cancel(time); + this._state.setStateAtTime(Tone.State.Stopped, time); + return this; + }; + Tone.Clock.prototype.pause = function (time) { + time = this.toSeconds(time); + if (this._state.getValueAtTime(time) === Tone.State.Started) { + this._state.setStateAtTime(Tone.State.Paused, time); + } + return this; + }; + Tone.Clock.prototype._loop = function () { + var now = this.now(); + var lookAhead = this.context.lookAhead; + var updateInterval = this.context.updateInterval; + var lagCompensation = this.context.lag * 2; + var loopInterval = now + lookAhead + updateInterval + lagCompensation; + while (loopInterval > this._nextTick && this._state) { + var currentState = this._state.getValueAtTime(this._nextTick); + if (currentState !== this._lastState) { + this._lastState = currentState; + var event = this._state.get(this._nextTick); + if (currentState === Tone.State.Started) { + this._nextTick = event.time; + if (!this.isUndef(event.offset)) { + this.ticks = event.offset; + } + this.emit("start", event.time, this.ticks); + } else if (currentState === Tone.State.Stopped) { + this.ticks = 0; + this.emit("stop", event.time); + } else if (currentState === Tone.State.Paused) { + this.emit("pause", event.time); + } + } + var tickTime = this._nextTick; + if (this.frequency) { + this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick); + if (currentState === Tone.State.Started) { + this.callback(tickTime); + this.ticks++; + } + } + } + }; + Tone.Clock.prototype.getStateAtTime = function (time) { + time = this.toSeconds(time); + return this._state.getValueAtTime(time); + }; + Tone.Clock.prototype.dispose = function () { + Tone.Emitter.prototype.dispose.call(this); + this.context.off("tick", this._boundLoop); + this._writable("frequency"); + this.frequency.dispose(); + this.frequency = null; + this._boundLoop = null; + this._nextTick = Infinity; + this.callback = null; + this._state.dispose(); + this._state = null; + }; + return Tone.Clock; + })( + Tone_core_Tone, + Tone_signal_TimelineSignal, + Tone_core_TimelineState, + Tone_core_Emitter + ); + var metro; + ("use strict"); + metro = (function () { + var p5sound = master; + // requires the Tone.js library's Clock (MIT license, Yotam Mann) + // https://github.com/TONEnoTONE/Tone.js/ + var Clock = Tone_core_Clock; + p5.Metro = function () { + this.clock = new Clock({ callback: this.ontick.bind(this) }); + this.syncedParts = []; + this.bpm = 120; + // gets overridden by p5.Part + this._init(); + this.prevTick = 0; + this.tatumTime = 0; + this.tickCallback = function () {}; + }; + p5.Metro.prototype.ontick = function (tickTime) { + var elapsedTime = tickTime - this.prevTick; + var secondsFromNow = tickTime - p5sound.audiocontext.currentTime; + if (elapsedTime - this.tatumTime <= -0.02) { + return; + } else { + // console.log('ok', this.syncedParts[0].phrases[0].name); + this.prevTick = tickTime; + // for all of the active things on the metro: + var self = this; + this.syncedParts.forEach(function (thisPart) { + if (!thisPart.isPlaying) return; + thisPart.incrementStep(secondsFromNow); + // each synced source keeps track of its own beat number + thisPart.phrases.forEach(function (thisPhrase) { + var phraseArray = thisPhrase.sequence; + var bNum = self.metroTicks % phraseArray.length; + if ( + phraseArray[bNum] !== 0 && + (self.metroTicks < phraseArray.length || !thisPhrase.looping) + ) { + thisPhrase.callback(secondsFromNow, phraseArray[bNum]); + } + }); + }); + this.metroTicks += 1; + this.tickCallback(secondsFromNow); + } + }; + p5.Metro.prototype.setBPM = function (bpm, rampTime) { + var beatTime = 60 / (bpm * this.tatums); + var now = p5sound.audiocontext.currentTime; + this.tatumTime = beatTime; + var rampTime = rampTime || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); + this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); + this.bpm = bpm; + }; + p5.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }; + p5.Metro.prototype._init = function () { + this.metroTicks = 0; + }; + // clear existing synced parts, add only this one + p5.Metro.prototype.resetSync = function (part) { + this.syncedParts = [part]; + }; + // push a new synced part to the array + p5.Metro.prototype.pushSync = function (part) { + this.syncedParts.push(part); + }; + p5.Metro.prototype.start = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.clock.start(now + t); + this.setBPM(this.bpm); + }; + p5.Metro.prototype.stop = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.clock.stop(now + t); + }; + p5.Metro.prototype.beatLength = function (tatums) { + this.tatums = 1 / tatums / 4; + }; + })(master, Tone_core_Clock); + var looper; + ("use strict"); + looper = (function () { + var p5sound = master; + var BPM = 120; + /** + * Set the global tempo, in beats per minute, for all + * p5.Parts. This method will impact all active p5.Parts. + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} rampTime Seconds from now + */ + p5.prototype.setBPM = function (bpm, rampTime) { + BPM = bpm; + for (var i in p5sound.parts) { + if (p5sound.parts[i]) { + p5sound.parts[i].setBPM(bpm, rampTime); + } + } + }; + /** + *

A phrase is a pattern of musical events over time, i.e. + * a series of notes and rests.

+ * + *

Phrases must be added to a p5.Part for playback, and + * each part can play multiple phrases at the same time. + * For example, one Phrase might be a kick drum, another + * could be a snare, and another could be the bassline.

+ * + *

The first parameter is a name so that the phrase can be + * modified or deleted later. The callback is a a function that + * this phrase will call at every step—for example it might be + * called playNote(value){}. The array determines + * which value is passed into the callback at each step of the + * phrase. It can be numbers, an object with multiple numbers, + * or a zero (0) indicates a rest so the callback won't be called).

+ * + * @class p5.Phrase + * @constructor + * @param {String} name Name so that you can access the Phrase. + * @param {Function} callback The name of a function that this phrase + * will call. Typically it will play a sound, + * and accept two parameters: a time at which + * to play the sound (in seconds from now), + * and a value from the sequence array. The + * time should be passed into the play() or + * start() method to ensure precision. + * @param {Array} sequence Array of values to pass into the callback + * at each step of the phrase. + * @example + *
+ * var mySound, myPhrase, myPart; + * var pattern = [1,0,0,2,0,2,0,0]; + * var msg = 'click to play'; + * + * function preload() { + * mySound = loadSound('assets/beatbox.mp3'); + * } + * + * function setup() { + * noStroke(); + * fill(255); + * textAlign(CENTER); + * masterVolume(0.1); + * + * myPhrase = new p5.Phrase('bbox', makeSound, pattern); + * myPart = new p5.Part(); + * myPart.addPhrase(myPhrase); + * myPart.setBPM(60); + * } + * + * function draw() { + * background(0); + * text(msg, width/2, height/2); + * } + * + * function makeSound(time, playbackRate) { + * mySound.rate(playbackRate); + * mySound.play(time); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * myPart.start(); + * msg = 'playing pattern'; + * } + * } + * + *
+ */ + p5.Phrase = function (name, callback, sequence) { + this.phraseStep = 0; + this.name = name; + this.callback = callback; + /** + * Array of values to pass into the callback + * at each step of the phrase. Depending on the callback + * function's requirements, these values may be numbers, + * strings, or an object with multiple parameters. + * Zero (0) indicates a rest. + * + * @property {Array} sequence + */ + this.sequence = sequence; + }; + /** + *

A p5.Part plays back one or more p5.Phrases. Instantiate a part + * with steps and tatums. By default, each step represents a 1/16th note.

+ * + *

See p5.Phrase for more about musical timing.

+ * + * @class p5.Part + * @constructor + * @param {Number} [steps] Steps in the part + * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note) + * @example + *
+ * var box, drum, myPart; + * var boxPat = [1,0,0,2,0,2,0,0]; + * var drumPat = [0,1,1,0,2,0,1,0]; + * var msg = 'click to play'; + * + * function preload() { + * box = loadSound('assets/beatbox.mp3'); + * drum = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * noStroke(); + * fill(255); + * textAlign(CENTER); + * masterVolume(0.1); + * + * var boxPhrase = new p5.Phrase('box', playBox, boxPat); + * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat); + * myPart = new p5.Part(); + * myPart.addPhrase(boxPhrase); + * myPart.addPhrase(drumPhrase); + * myPart.setBPM(60); + * masterVolume(0.1); + * } + * + * function draw() { + * background(0); + * text(msg, width/2, height/2); + * } + * + * function playBox(time, playbackRate) { + * box.rate(playbackRate); + * box.play(time); + * } + * + * function playDrum(time, playbackRate) { + * drum.rate(playbackRate); + * drum.play(time); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * myPart.start(); + * msg = 'playing part'; + * } + * } + *
+ */ + p5.Part = function (steps, bLength) { + this.length = steps || 0; + // how many beats + this.partStep = 0; + this.phrases = []; + this.isPlaying = false; + this.noLoop(); + this.tatums = bLength || 0.0625; + // defaults to quarter note + this.metro = new p5.Metro(); + this.metro._init(); + this.metro.beatLength(this.tatums); + this.metro.setBPM(BPM); + p5sound.parts.push(this); + this.callback = function () {}; + }; + /** + * Set the tempo of this part, in Beats Per Minute. + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} [rampTime] Seconds from now + */ + p5.Part.prototype.setBPM = function (tempo, rampTime) { + this.metro.setBPM(tempo, rampTime); + }; + /** + * Returns the tempo, in Beats Per Minute, of this part. + * + * @method getBPM + * @return {Number} + */ + p5.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }; + /** + * Start playback of this part. It will play + * through all of its phrases at a speed + * determined by setBPM. + * + * @method start + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.start = function (time) { + if (!this.isPlaying) { + this.isPlaying = true; + this.metro.resetSync(this); + var t = time || 0; + this.metro.start(t); + } + }; + /** + * Loop playback of this part. It will begin + * looping through all of its phrases at a speed + * determined by setBPM. + * + * @method loop + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.loop = function (time) { + this.looping = true; + // rest onended function + this.onended = function () { + this.partStep = 0; + }; + var t = time || 0; + this.start(t); + }; + /** + * Tell the part to stop looping. + * + * @method noLoop + */ + p5.Part.prototype.noLoop = function () { + this.looping = false; + // rest onended function + this.onended = function () { + this.stop(); + }; + }; + /** + * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. + * + * @method stop + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.stop = function (time) { + this.partStep = 0; + this.pause(time); + }; + /** + * Pause the part. Playback will resume + * from the current step. + * + * @method pause + * @param {Number} time seconds from now + */ + p5.Part.prototype.pause = function (time) { + this.isPlaying = false; + var t = time || 0; + this.metro.stop(t); + }; + /** + * Add a p5.Phrase to this Part. + * + * @method addPhrase + * @param {p5.Phrase} phrase reference to a p5.Phrase + */ + p5.Part.prototype.addPhrase = function (name, callback, array) { + var p; + if (arguments.length === 3) { + p = new p5.Phrase(name, callback, array); + } else if (arguments[0] instanceof p5.Phrase) { + p = arguments[0]; + } else { + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + } + this.phrases.push(p); + // reset the length if phrase is longer than part's existing length + if (p.sequence.length > this.length) { + this.length = p.sequence.length; + } + }; + /** + * Remove a phrase from this part, based on the name it was + * given when it was created. + * + * @method removePhrase + * @param {String} phraseName + */ + p5.Part.prototype.removePhrase = function (name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases.splice(i, 1); + } + } + }; + /** + * Get a phrase from this part, based on the name it was + * given when it was created. Now you can modify its array. + * + * @method getPhrase + * @param {String} phraseName + */ + p5.Part.prototype.getPhrase = function (name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + return this.phrases[i]; + } + } + }; + /** + * Find all sequences with the specified name, and replace their patterns with the specified array. + * + * @method replaceSequence + * @param {String} phraseName + * @param {Array} sequence Array of values to pass into the callback + * at each step of the phrase. + */ + p5.Part.prototype.replaceSequence = function (name, array) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases[i].sequence = array; + } + } + }; + p5.Part.prototype.incrementStep = function (time) { + if (this.partStep < this.length - 1) { + this.callback(time); + this.partStep += 1; + } else { + if (!this.looping && this.partStep === this.length - 1) { + console.log("done"); + // this.callback(time); + this.onended(); + } + } + }; + /** + * Set the function that will be called at every step. This will clear the previous function. + * + * @method onStep + * @param {Function} callback The name of the callback + * you want to fire + * on every beat/tatum. + */ + p5.Part.prototype.onStep = function (callback) { + this.callback = callback; + }; + // =============== + // p5.Score + // =============== + /** + * A Score consists of a series of Parts. The parts will + * be played back in order. For example, you could have an + * A part, a B part, and a C part, and play them back in this order + * new p5.Score(a, a, b, a, c) + * + * @class p5.Score + * @constructor + * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. + */ + p5.Score = function () { + // for all of the arguments + this.parts = []; + this.currentPart = 0; + var thisScore = this; + for (var i in arguments) { + if (arguments[i] && this.parts[i]) { + this.parts[i] = arguments[i]; + this.parts[i].nextPart = this.parts[i + 1]; + this.parts[i].onended = function () { + thisScore.resetPart(i); + playNextPart(thisScore); + }; + } + } + this.looping = false; + }; + p5.Score.prototype.onended = function () { + if (this.looping) { + // this.resetParts(); + this.parts[0].start(); + } else { + this.parts[this.parts.length - 1].onended = function () { + this.stop(); + this.resetParts(); + }; + } + this.currentPart = 0; + }; + /** + * Start playback of the score. + * + * @method start + */ + p5.Score.prototype.start = function () { + this.parts[this.currentPart].start(); + this.scoreStep = 0; + }; + /** + * Stop playback of the score. + * + * @method stop + */ + p5.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(); + this.currentPart = 0; + this.scoreStep = 0; + }; + /** + * Pause playback of the score. + * + * @method pause + */ + p5.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }; + /** + * Loop playback of the score. + * + * @method loop + */ + p5.Score.prototype.loop = function () { + this.looping = true; + this.start(); + }; + /** + * Stop looping playback of the score. If it + * is currently playing, this will go into effect + * after the current round of playback completes. + * + * @method noLoop + */ + p5.Score.prototype.noLoop = function () { + this.looping = false; + }; + p5.Score.prototype.resetParts = function () { + var self = this; + this.parts.forEach(function (part) { + self.resetParts[part]; + }); + }; + p5.Score.prototype.resetPart = function (i) { + this.parts[i].stop(); + this.parts[i].partStep = 0; + for (var p in this.parts[i].phrases) { + if (this.parts[i]) { + this.parts[i].phrases[p].phraseStep = 0; + } + } + }; + /** + * Set the tempo for all parts in the score + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} rampTime Seconds from now + */ + p5.Score.prototype.setBPM = function (bpm, rampTime) { + for (var i in this.parts) { + if (this.parts[i]) { + this.parts[i].setBPM(bpm, rampTime); + } + } + }; + function playNextPart(aScore) { + aScore.currentPart++; + if (aScore.currentPart >= aScore.parts.length) { + aScore.scoreStep = 0; + aScore.onended(); + } else { + aScore.scoreStep = 0; + aScore.parts[aScore.currentPart - 1].stop(); + aScore.parts[aScore.currentPart].start(); + } } - if (this.input) { + })(master); + var soundloop; + ("use strict"); + soundloop = (function () { + var p5sound = master; + var Clock = Tone_core_Clock; + /** + * SoundLoop + * + * @class p5.SoundLoop + * @constructor + * + * @param {Function} callback this function will be called on each iteration of theloop + * @param {Number|String} [interval] amount of time or beats for each iteration of the loop + * defaults to 1 + * + * @example + *
+ * var click; + * var looper1; + * + * function preload() { + * click = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * //the looper's callback is passed the timeFromNow + * //this value should be used as a reference point from + * //which to schedule sounds + * looper1 = new p5.SoundLoop(function(timeFromNow){ + * click.play(timeFromNow); + * background(255 * (looper1.iterations % 2)); + * }, 2); + * + * //stop after 10 iteratios; + * looper1.maxIterations = 10; + * //start the loop + * looper1.start(); + * } + *
+ */ + p5.SoundLoop = function (callback, interval) { + this.callback = callback; + /** + * musicalTimeMode uses Tone.Time convention + * true if string, false if number + * @property {Boolean} musicalTimeMode + */ + this.musicalTimeMode = typeof this._interval === "number" ? false : true; + this._interval = interval || 1; + /** + * musicalTimeMode variables + * modify these only when the interval is specified in musicalTime format as a string + */ + this._timeSignature = 4; + this._bpm = 60; + this.isPlaying = false; + /** + * Set a limit to the number of loops to play. defaults to Infinity + * @property {Number} maxIterations + */ + this.maxIterations = Infinity; + var self = this; + this.clock = new Clock({ + callback: function (time) { + var timeFromNow = time - p5sound.audiocontext.currentTime; + /** + * Do not initiate the callback if timeFromNow is < 0 + * This ususually occurs for a few milliseconds when the page + * is not fully loaded + * + * The callback should only be called until maxIterations is reached + */ + if (timeFromNow > 0 && self.iterations <= self.maxIterations) { + self.callback(timeFromNow); + } + }, + frequency: this._calcFreq(), + }); + }; + /** + * Start the loop + * @method start + * @param {Number} [timeFromNow] schedule a starting time + */ + p5.SoundLoop.prototype.start = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (!this.isPlaying) { + this.clock.start(now + t); + this.isPlaying = true; + } + }; + /** + * Stop the loop + * @method stop + * @param {Number} [timeFromNow] schedule a stopping time + */ + p5.SoundLoop.prototype.stop = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.stop(now + t); + this.isPlaying = false; + } + }; + /** + * Pause the loop + * @method pause + * @param {Number} [timeFromNow] schedule a pausing time + */ + p5.SoundLoop.prototype.pause = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.pause(now + t); + this.isPlaying = false; + } + }; + /** + * Synchronize loops. Use this method to start two more more loops in synchronization + * or to start a loop in synchronization with a loop that is already playing + * This method will schedule the implicit loop in sync with the explicit master loop + * i.e. loopToStart.syncedStart(loopToSyncWith) + * + * @method syncedStart + * @param {Object} otherLoop a p5.SoundLoop to sync with + * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds + */ + p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (!otherLoop.isPlaying) { + otherLoop.clock.start(now + t); + otherLoop.isPlaying = true; + this.clock.start(now + t); + this.isPlaying = true; + } else if (otherLoop.isPlaying) { + var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; + this.clock.start(now + time); + this.isPlaying = true; + } + }; + /** + * Updates frequency value, reflected in next callback + * @private + * @method _update + */ + p5.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }; + /** + * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature + * @private + * @method _calcFreq + * @return {Number} new clock frequency value + */ + p5.SoundLoop.prototype._calcFreq = function () { + //Seconds mode, bpm / timesignature has no effect + if (typeof this._interval === "number") { + this.musicalTimeMode = false; + return 1 / this._interval; + } else if (typeof this._interval === "string") { + this.musicalTimeMode = true; + return ( + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4) + ); + } + }; + /** + * Convert notation from musical time format to seconds + * Uses Tone.Time convention + * @private + * @method _convertNotation + * @param {String} value value to be converted + * @return {Number} converted value in seconds + */ + p5.SoundLoop.prototype._convertNotation = function (value) { + var type = value.slice(-1); + value = Number(value.slice(0, -1)); + switch (type) { + case "m": + return this._measure(value); + case "n": + return this._note(value); + default: + console.warn( + "Specified interval is not formatted correctly. See Tone.js " + + "timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time" + ); + } + }; + /** + * Helper conversion methods of measure and note + * @private + * @method _measure + * @private + * @method _note + */ + p5.SoundLoop.prototype._measure = function (value) { + return value * this._timeSignature; + }; + p5.SoundLoop.prototype._note = function (value) { + return this._timeSignature / value; + }; + /** + * Getters and Setters, setting any paramter will result in a change in the clock's + * frequency, that will be reflected after the next callback + * beats per minute (defaults to 60) + * @property {Number} bpm + */ + Object.defineProperty(p5.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (bpm) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the BPM in "seconds" mode has no effect. ' + + "BPM is only relevant in musicalTimeMode " + + "when the interval is specified as a string " + + '("2n", "4n", "1m"...etc)' + ); + } + this._bpm = bpm; + this._update(); + }, + }); + /** + * number of quarter notes in a measure (defaults to 4) + * @property {Number} timeSignature + */ + Object.defineProperty(p5.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (timeSig) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the timeSignature in "seconds" mode has no effect. ' + + "BPM is only relevant in musicalTimeMode " + + "when the interval is specified as a string " + + '("2n", "4n", "1m"...etc)' + ); + } + this._timeSignature = timeSig; + this._update(); + }, + }); + /** + * length of the loops interval + * @property {Number|String} interval + */ + Object.defineProperty(p5.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (interval) { + this.musicalTimeMode = typeof interval === "Number" ? false : true; + this._interval = interval; + this._update(); + }, + }); + /** + * how many times the callback has been called so far + * @property {Number} iterations + * @readonly + */ + Object.defineProperty(p5.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }); + return p5.SoundLoop; + })(master, Tone_core_Clock); + var compressor; + compressor = (function () { + "use strict"; + var p5sound = master; + var Effect = effect; + var CustomError = errorHandler; + /** + * Compressor is an audio effect class that performs dynamics compression + * on an audio input source. This is a very commonly used technique in music + * and sound production. Compression creates an overall louder, richer, + * and fuller sound by lowering the volume of louds and raising that of softs. + * Compression can be used to avoid clipping (sound distortion due to + * peaks in volume) and is especially useful when many sounds are played + * at once. Compression can be used on indivudal sound sources in addition + * to the master output. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Compressor + * @constructor + * @extends p5.Effect + * + * + */ + p5.Compressor = function () { + Effect.call(this); + /** + * The p5.Compressor is built with a Web Audio Dynamics Compressor Node + * + * @property {AudioNode} compressor + */ + this.compressor = this.ac.createDynamicsCompressor(); + this.input.connect(this.compressor); + this.compressor.connect(this.wet); + }; + p5.Compressor.prototype = Object.create(Effect.prototype); + /** + * Performs the same function as .connect, but also accepts + * optional parameters to set compressor's audioParams + * @method process + * + * @param {Object} src Sound source to be connected + * + * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [threshold] The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ + p5.Compressor.prototype.process = function ( + src, + attack, + knee, + ratio, + threshold, + release + ) { + src.connect(this.input); + this.set(attack, knee, ratio, threshold, release); + }; + /** + * Set the paramters of a compressor. + * @method set + * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} knee A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} ratio The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ + p5.Compressor.prototype.set = function ( + attack, + knee, + ratio, + threshold, + release + ) { + if (typeof attack !== "undefined") { + this.attack(attack); + } + if (typeof knee !== "undefined") { + this.knee(knee); + } + if (typeof ratio !== "undefined") { + this.ratio(ratio); + } + if (typeof threshold !== "undefined") { + this.threshold(threshold); + } + if (typeof release !== "undefined") { + this.release(release); + } + }; + /** + * Get current attack or set value w/ time ramp + * + * + * @method attack + * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.attack = function (attack, time) { + var t = time || 0; + if (typeof attack == "number") { + this.compressor.attack.value = attack; + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.attack.linearRampToValueAtTime( + attack, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof attack !== "undefined") { + attack.connect(this.compressor.attack); + } + return this.compressor.attack.value; + }; + /** + * Get current knee or set value w/ time ramp + * + * @method knee + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.knee = function (knee, time) { + var t = time || 0; + if (typeof knee == "number") { + this.compressor.knee.value = knee; + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.knee.linearRampToValueAtTime( + knee, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof knee !== "undefined") { + knee.connect(this.compressor.knee); + } + return this.compressor.knee.value; + }; + /** + * Get current ratio or set value w/ time ramp + * @method ratio + * + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.ratio = function (ratio, time) { + var t = time || 0; + if (typeof ratio == "number") { + this.compressor.ratio.value = ratio; + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.ratio.linearRampToValueAtTime( + ratio, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof ratio !== "undefined") { + ratio.connect(this.compressor.ratio); + } + return this.compressor.ratio.value; + }; + /** + * Get current threshold or set value w/ time ramp + * @method threshold + * + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.threshold = function (threshold, time) { + var t = time || 0; + if (typeof threshold == "number") { + this.compressor.threshold.value = threshold; + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.threshold.linearRampToValueAtTime( + threshold, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof threshold !== "undefined") { + threshold.connect(this.compressor.threshold); + } + return this.compressor.threshold.value; + }; + /** + * Get current release or set value w/ time ramp + * @method release + * + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + * + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.release = function (release, time) { + var t = time || 0; + if (typeof release == "number") { + this.compressor.release.value = release; + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.release.linearRampToValueAtTime( + release, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof number !== "undefined") { + release.connect(this.compressor.release); + } + return this.compressor.release.value; + }; + /** + * Return the current reduction value + * + * @method reduction + * @return {Number} Value of the amount of gain reduction that is applied to the signal + */ + p5.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }; + p5.Compressor.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.compressor) { + this.compressor.disconnect(); + delete this.compressor; + } + }; + return p5.Compressor; + })(master, effect, errorHandler); + var soundRecorder; + ("use strict"); + soundRecorder = (function () { + // inspiration: recorder.js, Tone.js & typedarray.org + var p5sound = master; + var convertToWav = helpers.convertToWav; + var ac = p5sound.audiocontext; + /** + *

Record sounds for playback and/or to save as a .wav file. + * The p5.SoundRecorder records all sound output from your sketch, + * or can be assigned a specific source with setInput().

+ *

The record() method accepts a p5.SoundFile as a parameter. + * When playback is stopped (either after the given amount of time, + * or with the stop() method), the p5.SoundRecorder will send its + * recording to that p5.SoundFile for playback.

+ * + * @class p5.SoundRecorder + * @constructor + * @example + *
+ * var mic, recorder, soundFile; + * var state = 0; + * + * function setup() { + * background(200); + * // create an audio in + * mic = new p5.AudioIn(); + * + * // prompts user to enable their browser mic + * mic.start(); + * + * // create a sound recorder + * recorder = new p5.SoundRecorder(); + * + * // connect the mic to the recorder + * recorder.setInput(mic); + * + * // this sound file will be used to + * // playback & save the recording + * soundFile = new p5.SoundFile(); + * + * text('keyPress to record', 20, 20); + * } + * + * function keyPressed() { + * // make sure user enabled the mic + * if (state === 0 && mic.enabled) { + * + * // record to our p5.SoundFile + * recorder.record(soundFile); + * + * background(255,0,0); + * text('Recording!', 20, 20); + * state++; + * } + * else if (state === 1) { + * background(0,255,0); + * + * // stop recorder and + * // send result to soundFile + * recorder.stop(); + * + * text('Stopped', 20, 20); + * state++; + * } + * + * else if (state === 2) { + * soundFile.play(); // play the result! + * save(soundFile, 'mySound.wav'); + * state++; + * } + * } + *
+ */ + p5.SoundRecorder = function () { + this.input = ac.createGain(); + this.output = ac.createGain(); + this.recording = false; + this.bufferSize = 1024; + this._channels = 2; + // stereo (default) + this._clear(); + // initialize variables + this._jsNode = ac.createScriptProcessor( + this.bufferSize, + this._channels, + 2 + ); + this._jsNode.onaudioprocess = this._audioprocess.bind(this); + /** + * callback invoked when the recording is over + * @private + * @type Function(Float32Array) + */ + this._callback = function () {}; + // connections + this._jsNode.connect(p5.soundOut._silentNode); + this.setInput(); + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connect a specific device to the p5.SoundRecorder. + * If no parameter is given, p5.SoundRecorer will record + * all audible p5.sound from your sketch. + * + * @method setInput + * @param {Object} [unit] p5.sound object or a web audio unit + * that outputs sound + */ + p5.SoundRecorder.prototype.setInput = function (unit) { this.input.disconnect(); - delete this.input; - } - }; -}(master); -var audioVoice; -'use strict'; -audioVoice = function () { - var p5sound = master; - /** - * Base class for monophonic synthesizers. Any extensions of this class - * should follow the API and implement the methods below in order to - * remain compatible with p5.PolySynth(); - * - * @class p5.AudioVoice - * @constructor - */ - p5.AudioVoice = function () { - this.ac = p5sound.audiocontext; - this.output = this.ac.createGain(); - this.connect(); - p5sound.soundArray.push(this); - }; - p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) { - }; - p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) { - }; - p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) { - }; - p5.AudioVoice.prototype.amp = function (vol, rampTime) { - }; - /** - * Connect to p5 objects or Web Audio Nodes - * @method connect - * @param {Object} unit - */ - p5.AudioVoice.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect from soundOut - * @method disconnect - */ - p5.AudioVoice.prototype.disconnect = function () { - this.output.disconnect(); - }; - p5.AudioVoice.prototype.dispose = function () { - if (this.output) { + this.input = null; + this.input = ac.createGain(); + this.input.connect(this._jsNode); + this.input.connect(this.output); + if (unit) { + unit.connect(this.input); + } else { + p5.soundOut.output.connect(this.input); + } + }; + /** + * Start recording. To access the recording, provide + * a p5.SoundFile as the first parameter. The p5.SoundRecorder + * will send its recording to that p5.SoundFile for playback once + * recording is complete. Optional parameters include duration + * (in seconds) of the recording, and a callback function that + * will be called once the complete recording has been + * transfered to the p5.SoundFile. + * + * @method record + * @param {p5.SoundFile} soundFile p5.SoundFile + * @param {Number} [duration] Time (in seconds) + * @param {Function} [callback] The name of a function that will be + * called once the recording completes + */ + p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { + this.recording = true; + if (duration) { + this.sampleLimit = Math.round(duration * ac.sampleRate); + } + if (sFile && callback) { + this._callback = function () { + this.buffer = this._getBuffer(); + sFile.setBuffer(this.buffer); + callback(); + }; + } else if (sFile) { + this._callback = function () { + this.buffer = this._getBuffer(); + sFile.setBuffer(this.buffer); + }; + } + }; + /** + * Stop the recording. Once the recording is stopped, + * the results will be sent to the p5.SoundFile that + * was given on .record(), and if a callback function + * was provided on record, that function will be called. + * + * @method stop + */ + p5.SoundRecorder.prototype.stop = function () { + this.recording = false; + this._callback(); + this._clear(); + }; + p5.SoundRecorder.prototype._clear = function () { + this._leftBuffers = []; + this._rightBuffers = []; + this.recordedSamples = 0; + this.sampleLimit = null; + }; + /** + * internal method called on audio process + * + * @private + * @param {AudioProcessorEvent} event + */ + p5.SoundRecorder.prototype._audioprocess = function (event) { + if (this.recording === false) { + return; + } else if (this.recording === true) { + // if we are past the duration, then stop... else: + if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) { + this.stop(); + } else { + // get channel data + var left = event.inputBuffer.getChannelData(0); + var right = event.inputBuffer.getChannelData(1); + // clone the samples + this._leftBuffers.push(new Float32Array(left)); + this._rightBuffers.push(new Float32Array(right)); + this.recordedSamples += this.bufferSize; + } + } + }; + p5.SoundRecorder.prototype._getBuffer = function () { + var buffers = []; + buffers.push(this._mergeBuffers(this._leftBuffers)); + buffers.push(this._mergeBuffers(this._rightBuffers)); + return buffers; + }; + p5.SoundRecorder.prototype._mergeBuffers = function (channelBuffer) { + var result = new Float32Array(this.recordedSamples); + var offset = 0; + var lng = channelBuffer.length; + for (var i = 0; i < lng; i++) { + var buffer = channelBuffer[i]; + result.set(buffer, offset); + offset += buffer.length; + } + return result; + }; + p5.SoundRecorder.prototype.dispose = function () { + this._clear(); + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this._callback = function () {}; + if (this.input) { + this.input.disconnect(); + } + this.input = null; + this._jsNode = null; + }; + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. + * For uploading audio to a server, use + * `p5.SoundFile.saveBlob`. + * + * @for p5 + * @method saveSound + * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save + * @param {String} fileName name of the resulting .wav file. + */ + // add to p5.prototype as this is used by the p5 `save()` method. + p5.prototype.saveSound = function (soundFile, fileName) { + const dataView = convertToWav(soundFile.buffer); + p5.prototype.writeFile([dataView], fileName, "wav"); + }; + })(master, helpers); + var peakdetect; + ("use strict"); + peakdetect = (function () { + /** + *

PeakDetect works in conjunction with p5.FFT to + * look for onsets in some or all of the frequency spectrum. + *

+ *

+ * To use p5.PeakDetect, call update in the draw loop + * and pass in a p5.FFT object. + *

+ *

+ * You can listen for a specific part of the frequency spectrum by + * setting the range between freq1 and freq2. + *

+ * + *

threshold is the threshold for detecting a peak, + * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud + * as 1.0.

+ * + *

+ * The update method is meant to be run in the draw loop, and + * frames determines how many loops must pass before + * another peak can be detected. + * For example, if the frameRate() = 60, you could detect the beat of a + * 120 beat-per-minute song with this equation: + * framesPerPeak = 60 / (estimatedBPM / 60 ); + *

+ * + *

+ * Based on example contribtued by @b2renger, and a simple beat detection + * explanation by Felix Turner. + *

+ * + * @class p5.PeakDetect + * @constructor + * @param {Number} [freq1] lowFrequency - defaults to 20Hz + * @param {Number} [freq2] highFrequency - defaults to 20000 Hz + * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 + * scaled logarithmically where 0.1 is 1/2 the loudness + * of 1.0. Defaults to 0.35. + * @param {Number} [framesPerPeak] Defaults to 20. + * @example + *
+ * + * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 10; + * + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * + * // p5.PeakDetect requires a p5.FFT + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * } + * + * function draw() { + * background(0); + * text('click to play/pause', width/2, height/2); + * + * // peakDetect accepts an fft post-analysis + * fft.analyze(); + * peakDetect.update(fft); + * + * if ( peakDetect.isDetected ) { + * ellipseWidth = 50; + * } else { + * ellipseWidth *= 0.95; + * } + * + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // toggle play/stop when canvas is clicked + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * } + * } + *
+ */ + p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) { + // framesPerPeak determines how often to look for a beat. + // If a beat is provided, try to look for a beat based on bpm + this.framesPerPeak = _framesPerPeak || 20; + this.framesSinceLastPeak = 0; + this.decayRate = 0.95; + this.threshold = threshold || 0.35; + this.cutoff = 0; + // how much to increase the cutoff + // TO DO: document this / figure out how to make it accessible + this.cutoffMult = 1.5; + this.energy = 0; + this.penergy = 0; + // TO DO: document this property / figure out how to make it accessible + this.currentValue = 0; + /** + * isDetected is set to true when a peak is detected. + * + * @attribute isDetected {Boolean} + * @default false + */ + this.isDetected = false; + this.f1 = freq1 || 40; + this.f2 = freq2 || 20000; + // function to call when a peak is detected + this._onPeak = function () {}; + }; + /** + * The update method is run in the draw loop. + * + * Accepts an FFT object. You must call .analyze() + * on the FFT object prior to updating the peakDetect + * because it relies on a completed FFT analysis. + * + * @method update + * @param {p5.FFT} fftObject A p5.FFT object + */ + p5.PeakDetect.prototype.update = function (fftObject) { + var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255); + if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { + // trigger callback + this._onPeak(); + this.isDetected = true; + // debounce + this.cutoff = nrg * this.cutoffMult; + this.framesSinceLastPeak = 0; + } else { + this.isDetected = false; + if (this.framesSinceLastPeak <= this.framesPerPeak) { + this.framesSinceLastPeak++; + } else { + this.cutoff *= this.decayRate; + this.cutoff = Math.max(this.cutoff, this.threshold); + } + } + this.currentValue = nrg; + this.penergy = nrg; + }; + /** + * onPeak accepts two arguments: a function to call when + * a peak is detected. The value of the peak, + * between 0.0 and 1.0, is passed to the callback. + * + * @method onPeak + * @param {Function} callback Name of a function that will + * be called when a peak is + * detected. + * @param {Object} [val] Optional value to pass + * into the function when + * a peak is detected. + * @example + *
+ * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 0; + * + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * cnv = createCanvas(100,100); + * textAlign(CENTER); + * + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * + * setupSound(); + * + * // when a beat is detected, call triggerBeat() + * peakDetect.onPeak(triggerBeat); + * } + * + * function draw() { + * background(0); + * fill(255); + * text('click to play', width/2, height/2); + * + * fft.analyze(); + * peakDetect.update(fft); + * + * ellipseWidth *= 0.95; + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // this function is called by peakDetect.onPeak + * function triggerBeat() { + * ellipseWidth = 50; + * } + * + * // mouseclick starts/stops sound + * function setupSound() { + * cnv.mouseClicked( function() { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * }); + * } + *
+ */ + p5.PeakDetect.prototype.onPeak = function (callback, val) { + var self = this; + self._onPeak = function () { + callback(self.energy, val); + }; + }; + })(); + var gain; + ("use strict"); + gain = (function () { + var p5sound = master; + /** + * A gain node is usefull to set the relative volume of sound. + * It's typically used to build mixers. + * + * @class p5.Gain + * @constructor + * @example + *
+ * + * // load two soundfile and crossfade beetween them + * var sound1,sound2; + * var gain1, gain2, gain3; + * + * function preload(){ + * soundFormats('ogg', 'mp3'); + * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); + * sound2 = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * createCanvas(400,200); + * + * // create a 'master' gain to which we will connect both soundfiles + * gain3 = new p5.Gain(); + * gain3.connect(); + * + * // setup first sound for playing + * sound1.rate(1); + * sound1.loop(); + * sound1.disconnect(); // diconnect from p5 output + * + * gain1 = new p5.Gain(); // setup a gain node + * gain1.setInput(sound1); // connect the first sound to its input + * gain1.connect(gain3); // connect its output to the 'master' + * + * sound2.rate(1); + * sound2.disconnect(); + * sound2.loop(); + * + * gain2 = new p5.Gain(); + * gain2.setInput(sound2); + * gain2.connect(gain3); + * + * } + * + * function draw(){ + * background(180); + * + * // calculate the horizontal distance beetween the mouse and the right of the screen + * var d = dist(mouseX,0,width,0); + * + * // map the horizontal position of the mouse to values useable for volume control of sound1 + * var vol1 = map(mouseX,0,width,0,1); + * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa + * + * gain1.amp(vol1,0.5,0); + * gain2.amp(vol2,0.5,0); + * + * // map the vertical position of the mouse to values useable for 'master volume control' + * var vol3 = map(mouseY,0,height,0,1); + * gain3.amp(vol3,0.5,0); + * } + *
+ * + */ + p5.Gain = function () { + this.ac = p5sound.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + this.input.connect(this.output); + // add to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connect a source to the gain node. + * + * @method setInput + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + */ + p5.Gain.prototype.setInput = function (src) { + src.connect(this.input); + }; + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + p5.Gain.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Gain.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Set the output level of the gain node. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + p5.Gain.prototype.amp = function (vol, rampTime, tFromNow) { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); + }; + p5.Gain.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this.input) { + this.input.disconnect(); + delete this.input; + } + }; + })(master); + var audioVoice; + ("use strict"); + audioVoice = (function () { + var p5sound = master; + /** + * Base class for monophonic synthesizers. Any extensions of this class + * should follow the API and implement the methods below in order to + * remain compatible with p5.PolySynth(); + * + * @class p5.AudioVoice + * @constructor + */ + p5.AudioVoice = function () { + this.ac = p5sound.audiocontext; + this.output = this.ac.createGain(); + this.connect(); + p5sound.soundArray.push(this); + }; + p5.AudioVoice.prototype.play = function ( + note, + velocity, + secondsFromNow, + sustime + ) {}; + p5.AudioVoice.prototype.triggerAttack = function ( + note, + velocity, + secondsFromNow + ) {}; + p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {}; + p5.AudioVoice.prototype.amp = function (vol, rampTime) {}; + /** + * Connect to p5 objects or Web Audio Nodes + * @method connect + * @param {Object} unit + */ + p5.AudioVoice.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect from soundOut + * @method disconnect + */ + p5.AudioVoice.prototype.disconnect = function () { this.output.disconnect(); - delete this.output; - } - }; - return p5.AudioVoice; -}(master); -var monosynth; -'use strict'; -monosynth = function () { - var p5sound = master; - var AudioVoice = audioVoice; - var noteToFreq = helpers.noteToFreq; - var DEFAULT_SUSTAIN = 0.15; - /** - * A MonoSynth is used as a single voice for sound synthesis. - * This is a class to be used in conjunction with the PolySynth - * class. Custom synthetisers should be built inheriting from - * this class. - * - * @class p5.MonoSynth - * @constructor - * @example - *
- * var monoSynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * monoSynth = new p5.MonoSynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // time from now (in seconds) - * var time = 0; - * // note duration (in seconds) - * var dur = 0.25; - * // velocity (volume, from 0 to 1) - * var v = 0.2; - * - * monoSynth.play("G3", v, time, dur); - * monoSynth.play("C4", v, time += dur, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- **/ - p5.MonoSynth = function () { - AudioVoice.call(this); - this.oscillator = new p5.Oscillator(); - this.env = new p5.Envelope(); - this.env.setRange(1, 0); - this.env.setExp(true); - //set params - this.setADSR(0.02, 0.25, 0.05, 0.35); - // oscillator --> env --> this.output (gain) --> p5.soundOut - this.oscillator.disconnect(); - this.oscillator.connect(this.output); - this.env.disconnect(); - this.env.setInput(this.output.gain); - // reset oscillator gain to 1.0 - this.oscillator.output.gain.value = 1; - this.oscillator.start(); - this.connect(); - p5sound.soundArray.push(this); - }; - p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype); - /** - * Play tells the MonoSynth to start playing a note. This method schedules - * the calling of .triggerAttack and .triggerRelease. - * - * @method play - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var monoSynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * monoSynth = new p5.MonoSynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // time from now (in seconds) - * var time = 0; - * // note duration (in seconds) - * var dur = 1/6; - * // note velocity (volume, from 0 to 1) - * var v = random(); - * - * monoSynth.play("Fb3", v, 0, dur); - * monoSynth.play("Gb3", v, time += dur, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- * - */ - p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) { - this.triggerAttack(note, velocity, ~~secondsFromNow); - this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); - }; - /** - * Trigger the Attack, and Decay portion of the Envelope. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @method triggerAttack - * @example - *
- * var monoSynth = new p5.MonoSynth(); - * - * function mousePressed() { - * monoSynth.triggerAttack("E3"); - * } - * - * function mouseReleased() { - * monoSynth.triggerRelease(); - * } - *
- */ - p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) { - var secondsFromNow = ~~secondsFromNow; - var freq = noteToFreq(note); - var vel = velocity || 0.1; - this.oscillator.freq(freq, 0, secondsFromNow); - this.env.ramp(this.output.gain, secondsFromNow, vel); - }; - /** - * Trigger the release of the Envelope. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @param {Number} secondsFromNow time to trigger the release - * @method triggerRelease - * @example - *
- * var monoSynth = new p5.MonoSynth(); - * - * function mousePressed() { - * monoSynth.triggerAttack("E3"); - * } - * - * function mouseReleased() { - * monoSynth.triggerRelease(); - * } - *
- */ - p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) { - var secondsFromNow = secondsFromNow || 0; - this.env.ramp(this.output.gain, secondsFromNow, 0); - }; - /** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - */ - p5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) { - this.env.setADSR(attack, decay, sustain, release); - }; - /** - * Getters and Setters - * @property {Number} attack - */ - /** - * @property {Number} decay - */ - /** - * @property {Number} sustain - */ - /** - * @property {Number} release - */ - Object.defineProperties(p5.MonoSynth.prototype, { - 'attack': { - get: function () { - return this.env.aTime; + }; + p5.AudioVoice.prototype.dispose = function () { + if (this.output) { + this.output.disconnect(); + delete this.output; + } + }; + return p5.AudioVoice; + })(master); + var monosynth; + ("use strict"); + monosynth = (function () { + var p5sound = master; + var AudioVoice = audioVoice; + var noteToFreq = helpers.noteToFreq; + var DEFAULT_SUSTAIN = 0.15; + /** + * A MonoSynth is used as a single voice for sound synthesis. + * This is a class to be used in conjunction with the PolySynth + * class. Custom synthetisers should be built inheriting from + * this class. + * + * @class p5.MonoSynth + * @constructor + * @example + *
+ * var monoSynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * monoSynth = new p5.MonoSynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // time from now (in seconds) + * var time = 0; + * // note duration (in seconds) + * var dur = 0.25; + * // velocity (volume, from 0 to 1) + * var v = 0.2; + * + * monoSynth.play("G3", v, time, dur); + * monoSynth.play("C4", v, time += dur, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ **/ + p5.MonoSynth = function () { + AudioVoice.call(this); + this.oscillator = new p5.Oscillator(); + this.env = new p5.Envelope(); + this.env.setRange(1, 0); + this.env.setExp(true); + //set params + this.setADSR(0.02, 0.25, 0.05, 0.35); + // oscillator --> env --> this.output (gain) --> p5.soundOut + this.oscillator.disconnect(); + this.oscillator.connect(this.output); + this.env.disconnect(); + this.env.setInput(this.output.gain); + // reset oscillator gain to 1.0 + this.oscillator.output.gain.value = 1; + this.oscillator.start(); + this.connect(); + p5sound.soundArray.push(this); + }; + p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype); + /** + * Play tells the MonoSynth to start playing a note. This method schedules + * the calling of .triggerAttack and .triggerRelease. + * + * @method play + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var monoSynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * monoSynth = new p5.MonoSynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // time from now (in seconds) + * var time = 0; + * // note duration (in seconds) + * var dur = 1/6; + * // note velocity (volume, from 0 to 1) + * var v = random(); + * + * monoSynth.play("Fb3", v, 0, dur); + * monoSynth.play("Gb3", v, time += dur, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ * + */ + p5.MonoSynth.prototype.play = function ( + note, + velocity, + secondsFromNow, + susTime + ) { + this.triggerAttack(note, velocity, ~~secondsFromNow); + this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); + }; + /** + * Trigger the Attack, and Decay portion of the Envelope. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @method triggerAttack + * @example + *
+ * var monoSynth = new p5.MonoSynth(); + * + * function mousePressed() { + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + p5.MonoSynth.prototype.triggerAttack = function ( + note, + velocity, + secondsFromNow + ) { + var secondsFromNow = ~~secondsFromNow; + var freq = noteToFreq(note); + var vel = velocity || 0.1; + this.oscillator.freq(freq, 0, secondsFromNow); + this.env.ramp(this.output.gain, secondsFromNow, vel); + }; + /** + * Trigger the release of the Envelope. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @param {Number} secondsFromNow time to trigger the release + * @method triggerRelease + * @example + *
+ * var monoSynth = new p5.MonoSynth(); + * + * function mousePressed() { + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) { + var secondsFromNow = secondsFromNow || 0; + this.env.ramp(this.output.gain, secondsFromNow, 0); + }; + /** + * Set values like a traditional + * + * ADSR envelope + * . + * + * @method setADSR + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + */ + p5.MonoSynth.prototype.setADSR = function ( + attack, + decay, + sustain, + release + ) { + this.env.setADSR(attack, decay, sustain, release); + }; + /** + * Getters and Setters + * @property {Number} attack + */ + /** + * @property {Number} decay + */ + /** + * @property {Number} sustain + */ + /** + * @property {Number} release + */ + Object.defineProperties(p5.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (attack) { + this.env.setADSR( + attack, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, }, - set: function (attack) { - this.env.setADSR(attack, this.env.dTime, this.env.sPercent, this.env.rTime); - } - }, - 'decay': { - get: function () { - return this.env.dTime; + decay: { + get: function () { + return this.env.dTime; + }, + set: function (decay) { + this.env.setADSR( + this.env.aTime, + decay, + this.env.sPercent, + this.env.rTime + ); + }, }, - set: function (decay) { - this.env.setADSR(this.env.aTime, decay, this.env.sPercent, this.env.rTime); - } - }, - 'sustain': { - get: function () { - return this.env.sPercent; + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (sustain) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + sustain, + this.env.rTime + ); + }, }, - set: function (sustain) { - this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime); - } - }, - 'release': { - get: function () { - return this.env.rTime; + release: { + get: function () { + return this.env.rTime; + }, + set: function (release) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + release + ); + }, }, - set: function (release) { - this.env.setADSR(this.env.aTime, this.env.dTime, this.env.sPercent, release); + }); + /** + * MonoSynth amp + * @method amp + * @param {Number} vol desired volume + * @param {Number} [rampTime] Time to reach new volume + * @return {Number} new volume value + */ + p5.MonoSynth.prototype.amp = function (vol, rampTime) { + var t = rampTime || 0; + if (typeof vol !== "undefined") { + this.oscillator.amp(vol, t); } - } - }); - /** - * MonoSynth amp - * @method amp - * @param {Number} vol desired volume - * @param {Number} [rampTime] Time to reach new volume - * @return {Number} new volume value - */ - p5.MonoSynth.prototype.amp = function (vol, rampTime) { - var t = rampTime || 0; - if (typeof vol !== 'undefined') { - this.oscillator.amp(vol, t); - } - return this.oscillator.amp().value; - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.MonoSynth.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.MonoSynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - */ - p5.MonoSynth.prototype.dispose = function () { - AudioVoice.prototype.dispose.apply(this); - if (this.env) { - this.env.dispose(); - } - if (this.oscillator) { - this.oscillator.dispose(); - } - }; -}(master, audioVoice, helpers); -var polysynth; -'use strict'; -polysynth = function () { - var p5sound = master; - var TimelineSignal = Tone_signal_TimelineSignal; - var noteToFreq = helpers.noteToFreq; - /** - * An AudioVoice is used as a single voice for sound synthesis. - * The PolySynth class holds an array of AudioVoice, and deals - * with voices allocations, with setting notes to be played, and - * parameters to be set. - * - * @class p5.PolySynth - * @constructor - * - * @param {Number} [synthVoice] A monophonic synth voice inheriting - * the AudioVoice class. Defaults to p5.MonoSynth - * @param {Number} [maxVoices] Number of voices, defaults to 8; - * @example - *
- * var polySynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * polySynth = new p5.PolySynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // note duration (in seconds) - * var dur = 1.5; - * - * // time from now (in seconds) - * var time = 0; - * - * // velocity (volume, from 0 to 1) - * var vel = 0.1; - * - * // notes can overlap with each other - * polySynth.play("G2", vel, 0, dur); - * polySynth.play("C3", vel, time += 1/3, dur); - * polySynth.play("G3", vel, time += 1/3, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- **/ - p5.PolySynth = function (audioVoice, maxVoices) { - //audiovoices will contain maxVoices many monophonic synths - this.audiovoices = []; - /** - * An object that holds information about which notes have been played and - * which notes are currently being played. New notes are added as keys - * on the fly. While a note has been attacked, but not released, the value of the - * key is the audiovoice which is generating that note. When notes are released, - * the value of the key becomes undefined. - * @property notes - */ - this.notes = {}; - //indices of the most recently used, and least recently used audiovoice - this._newest = 0; - this._oldest = 0; - /** - * A PolySynth must have at least 1 voice, defaults to 8 - * @property polyvalue - */ - this.maxVoices = maxVoices || 8; - /** - * Monosynth that generates the sound for each note that is triggered. The - * p5.PolySynth defaults to using the p5.MonoSynth as its voice. - * @property AudioVoice - */ - this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; + return this.oscillator.amp().value; + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.MonoSynth.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.MonoSynth.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + */ + p5.MonoSynth.prototype.dispose = function () { + AudioVoice.prototype.dispose.apply(this); + if (this.env) { + this.env.dispose(); + } + if (this.oscillator) { + this.oscillator.dispose(); + } + }; + })(master, audioVoice, helpers); + var polysynth; + ("use strict"); + polysynth = (function () { + var p5sound = master; + var TimelineSignal = Tone_signal_TimelineSignal; + var noteToFreq = helpers.noteToFreq; /** + * An AudioVoice is used as a single voice for sound synthesis. + * The PolySynth class holds an array of AudioVoice, and deals + * with voices allocations, with setting notes to be played, and + * parameters to be set. + * + * @class p5.PolySynth + * @constructor + * + * @param {Number} [synthVoice] A monophonic synth voice inheriting + * the AudioVoice class. Defaults to p5.MonoSynth + * @param {Number} [maxVoices] Number of voices, defaults to 8; + * @example + *
+ * var polySynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * polySynth = new p5.PolySynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // note duration (in seconds) + * var dur = 1.5; + * + * // time from now (in seconds) + * var time = 0; + * + * // velocity (volume, from 0 to 1) + * var vel = 0.1; + * + * // notes can overlap with each other + * polySynth.play("G2", vel, 0, dur); + * polySynth.play("C3", vel, time += 1/3, dur); + * polySynth.play("G3", vel, time += 1/3, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ **/ + p5.PolySynth = function (audioVoice, maxVoices) { + //audiovoices will contain maxVoices many monophonic synths + this.audiovoices = []; + /** + * An object that holds information about which notes have been played and + * which notes are currently being played. New notes are added as keys + * on the fly. While a note has been attacked, but not released, the value of the + * key is the audiovoice which is generating that note. When notes are released, + * the value of the key becomes undefined. + * @property notes + */ + this.notes = {}; + //indices of the most recently used, and least recently used audiovoice + this._newest = 0; + this._oldest = 0; + /** + * A PolySynth must have at least 1 voice, defaults to 8 + * @property polyvalue + */ + this.maxVoices = maxVoices || 8; + /** + * Monosynth that generates the sound for each note that is triggered. The + * p5.PolySynth defaults to using the p5.MonoSynth as its voice. + * @property AudioVoice + */ + this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; + /** * This value must only change as a note is attacked or released. Due to delay * and sustain times, Tone.TimelineSignal is required to schedule the change in value. - * @private + * @private * @property {Tone.TimelineSignal} _voicesInUse */ - this._voicesInUse = new TimelineSignal(0); - this.output = p5sound.audiocontext.createGain(); - this.connect(); - //Construct the appropriate number of audiovoices - this._allocateVoices(); - p5sound.soundArray.push(this); - }; - /** - * Construct the appropriate number of audiovoices - * @private - * @method _allocateVoices - */ - p5.PolySynth.prototype._allocateVoices = function () { - for (var i = 0; i < this.maxVoices; i++) { - this.audiovoices.push(new this.AudioVoice()); - this.audiovoices[i].disconnect(); - this.audiovoices[i].connect(this.output); - } - }; - /** - * Play a note by triggering noteAttack and noteRelease with sustain time - * - * @method play - * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var polySynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * polySynth = new p5.PolySynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // note duration (in seconds) - * var dur = 0.1; - * - * // time from now (in seconds) - * var time = 0; - * - * // velocity (volume, from 0 to 1) - * var vel = 0.1; - * - * polySynth.play("G2", vel, 0, dur); - * polySynth.play("C3", vel, 0, dur); - * polySynth.play("G3", vel, 0, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.PolySynth.prototype.play = function (note, velocity, secondsFromNow, susTime) { - var susTime = susTime || 1; - this.noteAttack(note, velocity, secondsFromNow); - this.noteRelease(note, secondsFromNow + susTime); - }; - /** - * noteADSR sets the envelope for a specific note that has just been triggered. - * Using this method modifies the envelope of whichever audiovoice is being used - * to play the desired note. The envelope should be reset before noteRelease is called - * in order to prevent the modified envelope from being used on other notes. - * - * @method noteADSR - * @param {Number} [note] Midi note on which ADSR should be set. - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow) { - var now = p5sound.audiocontext.currentTime; - var timeFromNow = timeFromNow || 0; - var t = now + timeFromNow; - this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); - }; - /** - * Set the PolySynths global envelope. This method modifies the envelopes of each - * monosynth so that all notes are played with this envelope. - * - * @method setADSR - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - p5.PolySynth.prototype.setADSR = function (a, d, s, r) { - this.audiovoices.forEach(function (voice) { - voice.setADSR(a, d, s, r); - }); - }; - /** - * Trigger the Attack, and Decay portion of a MonoSynth. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @method noteAttack - * @param {Number} [note] midi note on which attack should be triggered. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ - * @param {Number} [secondsFromNow] time from now (in seconds) - * @example - *
- * var polySynth = new p5.PolySynth(); - * var pitches = ["G", "D", "G", "C"]; - * var octaves = [2, 3, 4]; - * - * function mousePressed() { - * // play a chord: multiple notes at the same time - * for (var i = 0; i < 4; i++) { - * var note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } - * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); - * } - *
- */ - p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) { - //this value goes to the audiovoices which handle their own scheduling - var secondsFromNow = ~~secondsFromNow; - //this value is used by this._voicesInUse - var acTime = p5sound.audiocontext.currentTime + secondsFromNow; - //Convert note to frequency if necessary. This is because entries into this.notes - //should be based on frequency for the sake of consistency. - var note = noteToFreq(_note); - var velocity = _velocity || 0.1; - var currentVoice; - //Release the note if it is already playing - if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) { - this.noteRelease(note, 0); - } - //Check to see how many voices are in use at the time the note will start - if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { - currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); - } else { - currentVoice = this._oldest; - var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value); - this.noteRelease(oldestNote); - this._oldest = (this._oldest + 1) % (this.maxVoices - 1); - } - //Overrite the entry in the notes object. A note (frequency value) - //corresponds to the index of the audiovoice that is playing it - this.notes[note] = new TimelineSignal(); - this.notes[note].setValueAtTime(currentVoice, acTime); - //Find the scheduled change in this._voicesInUse that will be previous to this new note - //Add 1 and schedule this value at time 't', when this note will start playing - var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value; - this._voicesInUse.setValueAtTime(previousVal + 1, acTime); - //Then update all scheduled values that follow to increase by 1 - this._updateAfter(acTime, 1); - this._newest = currentVoice; - //The audiovoice handles the actual scheduling of the note - if (typeof velocity === 'number') { - var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2; - velocity = velocity > maxRange ? maxRange : velocity; - } - this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow); - }; - /** - * Private method to ensure accurate values of this._voicesInUse - * Any time a new value is scheduled, it is necessary to increment all subsequent - * scheduledValues after attack, and decrement all subsequent - * scheduledValues after release - * - * @private - * @param {[type]} time [description] - * @param {[type]} value [description] - * @return {[type]} [description] - */ - p5.PolySynth.prototype._updateAfter = function (time, value) { - if (this._voicesInUse._searchAfter(time) === null) { - return; - } else { - this._voicesInUse._searchAfter(time).value += value; - var nextTime = this._voicesInUse._searchAfter(time).time; - this._updateAfter(nextTime, value); - } - }; - /** - * Trigger the Release of an AudioVoice note. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @method noteRelease - * @param {Number} [note] midi note on which attack should be triggered. - * If no value is provided, all notes will be released. - * @param {Number} [secondsFromNow] time to trigger the release - * @example - *
- * var pitches = ["G", "D", "G", "C"]; - * var octaves = [2, 3, 4]; - * var polySynth = new p5.PolySynth(); - * - * function mousePressed() { - * // play a chord: multiple notes at the same time - * for (var i = 0; i < 4; i++) { - * var note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } - * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); - * } - *
- * - */ - p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - // if a note value is not provided, release all voices - if (!_note) { + this._voicesInUse = new TimelineSignal(0); + this.output = p5sound.audiocontext.createGain(); + this.connect(); + //Construct the appropriate number of audiovoices + this._allocateVoices(); + p5sound.soundArray.push(this); + }; + /** + * Construct the appropriate number of audiovoices + * @private + * @method _allocateVoices + */ + p5.PolySynth.prototype._allocateVoices = function () { + for (var i = 0; i < this.maxVoices; i++) { + this.audiovoices.push(new this.AudioVoice()); + this.audiovoices[i].disconnect(); + this.audiovoices[i].connect(this.output); + } + }; + /** + * Play a note by triggering noteAttack and noteRelease with sustain time + * + * @method play + * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var polySynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * polySynth = new p5.PolySynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // note duration (in seconds) + * var dur = 0.1; + * + * // time from now (in seconds) + * var time = 0; + * + * // velocity (volume, from 0 to 1) + * var vel = 0.1; + * + * polySynth.play("G2", vel, 0, dur); + * polySynth.play("C3", vel, 0, dur); + * polySynth.play("G3", vel, 0, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.PolySynth.prototype.play = function ( + note, + velocity, + secondsFromNow, + susTime + ) { + var susTime = susTime || 1; + this.noteAttack(note, velocity, secondsFromNow); + this.noteRelease(note, secondsFromNow + susTime); + }; + /** + * noteADSR sets the envelope for a specific note that has just been triggered. + * Using this method modifies the envelope of whichever audiovoice is being used + * to play the desired note. The envelope should be reset before noteRelease is called + * in order to prevent the modified envelope from being used on other notes. + * + * @method noteADSR + * @param {Number} [note] Midi note on which ADSR should be set. + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow) { + var now = p5sound.audiocontext.currentTime; + var timeFromNow = timeFromNow || 0; + var t = now + timeFromNow; + this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); + }; + /** + * Set the PolySynths global envelope. This method modifies the envelopes of each + * monosynth so that all notes are played with this envelope. + * + * @method setADSR + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + p5.PolySynth.prototype.setADSR = function (a, d, s, r) { this.audiovoices.forEach(function (voice) { - voice.triggerRelease(tFromNow); + voice.setADSR(a, d, s, r); }); - this._voicesInUse.setValueAtTime(0, t); - for (var n in this.notes) { - this.notes[n].dispose(); - delete this.notes[n]; - } - return; - } - //Make sure note is in frequency inorder to query the this.notes object - var note = noteToFreq(_note); - if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { - console.warn('Cannot release a note that is not already playing'); - } else { + }; + /** + * Trigger the Attack, and Decay portion of a MonoSynth. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @method noteAttack + * @param {Number} [note] midi note on which attack should be triggered. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ + * @param {Number} [secondsFromNow] time from now (in seconds) + * @example + *
+ * var polySynth = new p5.PolySynth(); + * var pitches = ["G", "D", "G", "C"]; + * var octaves = [2, 3, 4]; + * + * function mousePressed() { + * // play a chord: multiple notes at the same time + * for (var i = 0; i < 4; i++) { + * var note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ */ + p5.PolySynth.prototype.noteAttack = function ( + _note, + _velocity, + secondsFromNow + ) { + //this value goes to the audiovoices which handle their own scheduling + var secondsFromNow = ~~secondsFromNow; + //this value is used by this._voicesInUse + var acTime = p5sound.audiocontext.currentTime + secondsFromNow; + //Convert note to frequency if necessary. This is because entries into this.notes + //should be based on frequency for the sake of consistency. + var note = noteToFreq(_note); + var velocity = _velocity || 0.1; + var currentVoice; + //Release the note if it is already playing + if ( + this.notes[note] && + this.notes[note].getValueAtTime(acTime) !== null + ) { + this.noteRelease(note, 0); + } + //Check to see how many voices are in use at the time the note will start + if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { + currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); + } else { + currentVoice = this._oldest; + var oldestNote = p5.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(oldestNote); + this._oldest = (this._oldest + 1) % (this.maxVoices - 1); + } + //Overrite the entry in the notes object. A note (frequency value) + //corresponds to the index of the audiovoice that is playing it + this.notes[note] = new TimelineSignal(); + this.notes[note].setValueAtTime(currentVoice, acTime); //Find the scheduled change in this._voicesInUse that will be previous to this new note - //subtract 1 and schedule this value at time 't', when this note will stop playing - var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1); - this._voicesInUse.setValueAtTime(previousVal - 1, t); - //Then update all scheduled values that follow to decrease by 1 but never go below 0 - if (previousVal > 0) { - this._updateAfter(t, -1); - } - this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(tFromNow); - this.notes[note].dispose(); - delete this.notes[note]; - this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); - } - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.PolySynth.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.PolySynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - */ - p5.PolySynth.prototype.dispose = function () { - this.audiovoices.forEach(function (voice) { - voice.dispose(); - }); - if (this.output) { - this.output.disconnect(); - delete this.output; - } - }; -}(master, Tone_signal_TimelineSignal, helpers); -var distortion; -'use strict'; -distortion = function () { - var Effect = effect; - /* - * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) - */ - function makeDistortionCurve(amount) { - var k = typeof amount === 'number' ? amount : 50; - var numSamples = 44100; - var curve = new Float32Array(numSamples); - var deg = Math.PI / 180; - var i = 0; - var x; - for (; i < numSamples; ++i) { - x = i * 2 / numSamples - 1; - curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x)); - } - return curve; - } - /** - * A Distortion effect created with a Waveshaper Node, - * with an approach adapted from - * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Distortion - * @extends p5.Effect - * @constructor - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - * - */ - p5.Distortion = function (amount, oversample) { - Effect.call(this); - if (typeof amount === 'undefined') { - amount = 0.25; - } - if (typeof amount !== 'number') { - throw new Error('amount must be a number'); - } - if (typeof oversample === 'undefined') { - oversample = '2x'; - } - if (typeof oversample !== 'string') { - throw new Error('oversample must be a String'); + //Add 1 and schedule this value at time 't', when this note will start playing + var previousVal = + this._voicesInUse._searchBefore(acTime) === null + ? 0 + : this._voicesInUse._searchBefore(acTime).value; + this._voicesInUse.setValueAtTime(previousVal + 1, acTime); + //Then update all scheduled values that follow to increase by 1 + this._updateAfter(acTime, 1); + this._newest = currentVoice; + //The audiovoice handles the actual scheduling of the note + if (typeof velocity === "number") { + var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2; + velocity = velocity > maxRange ? maxRange : velocity; + } + this.audiovoices[currentVoice].triggerAttack( + note, + velocity, + secondsFromNow + ); + }; + /** + * Private method to ensure accurate values of this._voicesInUse + * Any time a new value is scheduled, it is necessary to increment all subsequent + * scheduledValues after attack, and decrement all subsequent + * scheduledValues after release + * + * @private + * @param {[type]} time [description] + * @param {[type]} value [description] + * @return {[type]} [description] + */ + p5.PolySynth.prototype._updateAfter = function (time, value) { + if (this._voicesInUse._searchAfter(time) === null) { + return; + } else { + this._voicesInUse._searchAfter(time).value += value; + var nextTime = this._voicesInUse._searchAfter(time).time; + this._updateAfter(nextTime, value); + } + }; + /** + * Trigger the Release of an AudioVoice note. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @method noteRelease + * @param {Number} [note] midi note on which attack should be triggered. + * If no value is provided, all notes will be released. + * @param {Number} [secondsFromNow] time to trigger the release + * @example + *
+ * var pitches = ["G", "D", "G", "C"]; + * var octaves = [2, 3, 4]; + * var polySynth = new p5.PolySynth(); + * + * function mousePressed() { + * // play a chord: multiple notes at the same time + * for (var i = 0; i < 4; i++) { + * var note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ * + */ + p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + // if a note value is not provided, release all voices + if (!_note) { + this.audiovoices.forEach(function (voice) { + voice.triggerRelease(tFromNow); + }); + this._voicesInUse.setValueAtTime(0, t); + for (var n in this.notes) { + this.notes[n].dispose(); + delete this.notes[n]; + } + return; + } + //Make sure note is in frequency inorder to query the this.notes object + var note = noteToFreq(_note); + if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { + console.warn("Cannot release a note that is not already playing"); + } else { + //Find the scheduled change in this._voicesInUse that will be previous to this new note + //subtract 1 and schedule this value at time 't', when this note will stop playing + var previousVal = Math.max( + ~~this._voicesInUse.getValueAtTime(t).value, + 1 + ); + this._voicesInUse.setValueAtTime(previousVal - 1, t); + //Then update all scheduled values that follow to decrease by 1 but never go below 0 + if (previousVal > 0) { + this._updateAfter(t, -1); + } + this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease( + tFromNow + ); + this.notes[note].dispose(); + delete this.notes[note]; + this._newest = + this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); + } + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.PolySynth.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.PolySynth.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + */ + p5.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (voice) { + voice.dispose(); + }); + if (this.output) { + this.output.disconnect(); + delete this.output; + } + }; + })(master, Tone_signal_TimelineSignal, helpers); + var distortion; + ("use strict"); + distortion = (function () { + var Effect = effect; + /* + * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) + */ + function makeDistortionCurve(amount) { + var k = typeof amount === "number" ? amount : 50; + var numSamples = 44100; + var curve = new Float32Array(numSamples); + var deg = Math.PI / 180; + var i = 0; + var x; + for (; i < numSamples; ++i) { + x = (i * 2) / numSamples - 1; + curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x)); + } + return curve; } - var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); - /** - * The p5.Distortion is built with a - * - * Web Audio WaveShaper Node. - * - * @property {AudioNode} WaveShaperNode - */ - this.waveShaperNode = this.ac.createWaveShaper(); - this.amount = curveAmount; - this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - this.waveShaperNode.oversample = oversample; - this.input.connect(this.waveShaperNode); - this.waveShaperNode.connect(this.wet); - }; - p5.Distortion.prototype = Object.create(Effect.prototype); - /** - * Process a sound source, optionally specify amount and oversample values. - * - * @method process - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.process = function (src, amount, oversample) { - src.connect(this.input); - this.set(amount, oversample); - }; - /** - * Set the amount and oversample of the waveshaper distortion. - * - * @method set - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.set = function (amount, oversample) { - if (amount) { + /** + * A Distortion effect created with a Waveshaper Node, + * with an approach adapted from + * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Distortion + * @extends p5.Effect + * @constructor + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + * + */ + p5.Distortion = function (amount, oversample) { + Effect.call(this); + if (typeof amount === "undefined") { + amount = 0.25; + } + if (typeof amount !== "number") { + throw new Error("amount must be a number"); + } + if (typeof oversample === "undefined") { + oversample = "2x"; + } + if (typeof oversample !== "string") { + throw new Error("oversample must be a String"); + } var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); + /** + * The p5.Distortion is built with a + * + * Web Audio WaveShaper Node. + * + * @property {AudioNode} WaveShaperNode + */ + this.waveShaperNode = this.ac.createWaveShaper(); this.amount = curveAmount; this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - } - if (oversample) { this.waveShaperNode.oversample = oversample; - } - }; - /** - * Return the distortion amount, typically between 0-1. - * - * @method getAmount - * @return {Number} Unbounded distortion amount. - * Normal values range from 0-1. - */ - p5.Distortion.prototype.getAmount = function () { - return this.amount; - }; - /** - * Return the oversampling. - * - * @method getOversample - * - * @return {String} Oversample can either be 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.getOversample = function () { - return this.waveShaperNode.oversample; - }; - p5.Distortion.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.waveShaperNode) { - this.waveShaperNode.disconnect(); - this.waveShaperNode = null; - } - }; -}(effect); -var src_app; -'use strict'; -src_app = function () { - var p5SOUND = master; - return p5SOUND; -}(shims, audiocontext, master, helpers, errorHandler, panner, soundfile, amplitude, fft, signal, oscillator, envelope, pulse, noise, audioin, filter, eq, panner3d, listener3d, delay, reverb, metro, looper, soundloop, compressor, soundRecorder, peakdetect, gain, monosynth, polysynth, distortion, audioVoice, monosynth, polysynth); -})); \ No newline at end of file + this.input.connect(this.waveShaperNode); + this.waveShaperNode.connect(this.wet); + }; + p5.Distortion.prototype = Object.create(Effect.prototype); + /** + * Process a sound source, optionally specify amount and oversample values. + * + * @method process + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.process = function (src, amount, oversample) { + src.connect(this.input); + this.set(amount, oversample); + }; + /** + * Set the amount and oversample of the waveshaper distortion. + * + * @method set + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.set = function (amount, oversample) { + if (amount) { + var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); + this.amount = curveAmount; + this.waveShaperNode.curve = makeDistortionCurve(curveAmount); + } + if (oversample) { + this.waveShaperNode.oversample = oversample; + } + }; + /** + * Return the distortion amount, typically between 0-1. + * + * @method getAmount + * @return {Number} Unbounded distortion amount. + * Normal values range from 0-1. + */ + p5.Distortion.prototype.getAmount = function () { + return this.amount; + }; + /** + * Return the oversampling. + * + * @method getOversample + * + * @return {String} Oversample can either be 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }; + p5.Distortion.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.waveShaperNode) { + this.waveShaperNode.disconnect(); + this.waveShaperNode = null; + } + }; + })(effect); + var src_app; + ("use strict"); + src_app = (function () { + var p5SOUND = master; + return p5SOUND; + })( + shims, + audiocontext, + master, + helpers, + errorHandler, + panner, + soundfile, + amplitude, + fft, + signal, + oscillator, + envelope, + pulse, + noise, + audioin, + filter, + eq, + panner3d, + listener3d, + delay, + reverb, + metro, + looper, + soundloop, + compressor, + soundRecorder, + peakdetect, + gain, + monosynth, + polysynth, + distortion, + audioVoice, + monosynth, + polysynth + ); +}); diff --git a/week7-runway/GPT2/libraries/p5.sound.js b/week7-runway/GPT2/libraries/p5.sound.js index 33b1304..80b238d 100644 --- a/week7-runway/GPT2/libraries/p5.sound.js +++ b/week7-runway/GPT2/libraries/p5.sound.js @@ -1,4 +1,4 @@ -/*! p5.sound.js v0.3.11 2019-03-14 */ +/*! p5.sound.js vlatest1 2019-03-14 */ /** * p5.sound extends p5 with Web Audio functionality including audio input, @@ -44,7 +44,7 @@ */ /** - * p5.sound + * p5.sound * https://p5js.org/reference/#/libraries/p5.sound * * From the Processing Foundation and contributors @@ -65,20 +65,20 @@ */ (function (root, factory) { - if (typeof define === 'function' && define.amd) - define('p5.sound', ['p5'], function (p5) { (factory(p5));}); - else if (typeof exports === 'object') - factory(require('../p5')); - else - factory(root['p5']); -}(this, function (p5) { - -var shims; -'use strict'; /** - * This module has shims - */ -shims = function () { - /* AudioContext Monkeypatch + if (typeof define === "function" && define.amd) + define("p5.sound", ["p5"], function (p5) { + factory(p5); + }); + else if (typeof exports === "object") factory(require("../p5")); + else factory(root["p5"]); +})(this, function (p5) { + var shims; + ("use strict"); + /** + * This module has shims + */ + shims = (function () { + /* AudioContext Monkeypatch Copyright 2013 Chris Wilson Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -90,100 +90,63 @@ shims = function () { See the License for the specific language governing permissions and limitations under the License. */ - (function () { - function fixSetTarget(param) { - if (!param) - // if NYI, just return - return; - if (!param.setTargetAtTime) - param.setTargetAtTime = param.setTargetValueAtTime; - } - if (window.hasOwnProperty('webkitAudioContext') && !window.hasOwnProperty('AudioContext')) { - window.AudioContext = window.webkitAudioContext; - if (typeof AudioContext.prototype.createGain !== 'function') - AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; - if (typeof AudioContext.prototype.createDelay !== 'function') - AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode; - if (typeof AudioContext.prototype.createScriptProcessor !== 'function') - AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode; - if (typeof AudioContext.prototype.createPeriodicWave !== 'function') - AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable; - AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain; - AudioContext.prototype.createGain = function () { - var node = this.internal_createGain(); - fixSetTarget(node.gain); - return node; - }; - AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay; - AudioContext.prototype.createDelay = function (maxDelayTime) { - var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay(); - fixSetTarget(node.delayTime); - return node; - }; - AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource; - AudioContext.prototype.createBufferSource = function () { - var node = this.internal_createBufferSource(); - if (!node.start) { - node.start = function (when, offset, duration) { - if (offset || duration) - this.noteGrainOn(when || 0, offset, duration); - else - this.noteOn(when || 0); - }; - } else { - node.internal_start = node.start; - node.start = function (when, offset, duration) { - if (typeof duration !== 'undefined') - node.internal_start(when || 0, offset, duration); - else - node.internal_start(when || 0, offset || 0); - }; - } - if (!node.stop) { - node.stop = function (when) { - this.noteOff(when || 0); - }; - } else { - node.internal_stop = node.stop; - node.stop = function (when) { - node.internal_stop(when || 0); - }; - } - fixSetTarget(node.playbackRate); - return node; - }; - AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor; - AudioContext.prototype.createDynamicsCompressor = function () { - var node = this.internal_createDynamicsCompressor(); - fixSetTarget(node.threshold); - fixSetTarget(node.knee); - fixSetTarget(node.ratio); - fixSetTarget(node.reduction); - fixSetTarget(node.attack); - fixSetTarget(node.release); - return node; - }; - AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter; - AudioContext.prototype.createBiquadFilter = function () { - var node = this.internal_createBiquadFilter(); - fixSetTarget(node.frequency); - fixSetTarget(node.detune); - fixSetTarget(node.Q); - fixSetTarget(node.gain); - return node; - }; - if (typeof AudioContext.prototype.createOscillator !== 'function') { - AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator; - AudioContext.prototype.createOscillator = function () { - var node = this.internal_createOscillator(); + (function () { + function fixSetTarget(param) { + if (!param) + // if NYI, just return + return; + if (!param.setTargetAtTime) + param.setTargetAtTime = param.setTargetValueAtTime; + } + if ( + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") + ) { + window.AudioContext = window.webkitAudioContext; + if (typeof AudioContext.prototype.createGain !== "function") + AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode; + if (typeof AudioContext.prototype.createDelay !== "function") + AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode; + if (typeof AudioContext.prototype.createScriptProcessor !== "function") + AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode; + if (typeof AudioContext.prototype.createPeriodicWave !== "function") + AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable; + AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain; + AudioContext.prototype.createGain = function () { + var node = this.internal_createGain(); + fixSetTarget(node.gain); + return node; + }; + AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay; + AudioContext.prototype.createDelay = function (maxDelayTime) { + var node = maxDelayTime + ? this.internal_createDelay(maxDelayTime) + : this.internal_createDelay(); + fixSetTarget(node.delayTime); + return node; + }; + AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource; + AudioContext.prototype.createBufferSource = function () { + var node = this.internal_createBufferSource(); if (!node.start) { - node.start = function (when) { - this.noteOn(when || 0); + node.start = function (when, offset, duration) { + if (offset || duration) + this.noteGrainOn(when || 0, offset, duration); + else this.noteOn(when || 0); }; } else { node.internal_start = node.start; - node.start = function (when) { - node.internal_start(when || 0); + node.start = function (when, offset, duration) { + if (typeof duration !== "undefined") + node.internal_start(when || 0, offset, duration); + else node.internal_start(when || 0, offset || 0); }; } if (!node.stop) { @@ -196,205 +159,267 @@ shims = function () { node.internal_stop(when || 0); }; } - if (!node.setPeriodicWave) - node.setPeriodicWave = node.setWaveTable; + fixSetTarget(node.playbackRate); + return node; + }; + AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor; + AudioContext.prototype.createDynamicsCompressor = function () { + var node = this.internal_createDynamicsCompressor(); + fixSetTarget(node.threshold); + fixSetTarget(node.knee); + fixSetTarget(node.ratio); + fixSetTarget(node.reduction); + fixSetTarget(node.attack); + fixSetTarget(node.release); + return node; + }; + AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter; + AudioContext.prototype.createBiquadFilter = function () { + var node = this.internal_createBiquadFilter(); fixSetTarget(node.frequency); fixSetTarget(node.detune); + fixSetTarget(node.Q); + fixSetTarget(node.gain); return node; }; - } - } - if (window.hasOwnProperty('webkitOfflineAudioContext') && !window.hasOwnProperty('OfflineAudioContext')) { - window.OfflineAudioContext = window.webkitOfflineAudioContext; - } - }(window)); - // <-- end MonkeyPatch. - // Polyfill for AudioIn, also handled by p5.dom createCapture - navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - /** - * Determine which filetypes are supported (inspired by buzz.js) - * The audio element (el) will only be used to test browser support for various audio formats - */ - var el = document.createElement('audio'); - p5.prototype.isSupported = function () { - return !!el.canPlayType; - }; - var isOGGSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"'); - }; - var isMP3Supported = function () { - return !!el.canPlayType && el.canPlayType('audio/mpeg;'); - }; - var isWAVSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"'); - }; - var isAACSupported = function () { - return !!el.canPlayType && (el.canPlayType('audio/x-m4a;') || el.canPlayType('audio/aac;')); - }; - var isAIFSupported = function () { - return !!el.canPlayType && el.canPlayType('audio/x-aiff;'); - }; - p5.prototype.isFileSupported = function (extension) { - switch (extension.toLowerCase()) { - case 'mp3': - return isMP3Supported(); - case 'wav': - return isWAVSupported(); - case 'ogg': - return isOGGSupported(); - case 'aac': - case 'm4a': - case 'mp4': - return isAACSupported(); - case 'aif': - case 'aiff': - return isAIFSupported(); - default: - return false; - } - }; -}(); -var StartAudioContext; -(function (root, factory) { - if (true) { - StartAudioContext = function () { - return factory(); - }(); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(); - } else { - root.StartAudioContext = factory(); - } -}(this, function () { - var TapListener = function (element, context) { - this._dragged = false; - this._element = element; - this._bindedMove = this._moved.bind(this); - this._bindedEnd = this._ended.bind(this, context); - element.addEventListener('touchstart', this._bindedEnd); - element.addEventListener('touchmove', this._bindedMove); - element.addEventListener('touchend', this._bindedEnd); - element.addEventListener('mouseup', this._bindedEnd); - }; - TapListener.prototype._moved = function (e) { - this._dragged = true; - }; - TapListener.prototype._ended = function (context) { - if (!this._dragged) { - startContext(context); - } - this._dragged = false; - }; - TapListener.prototype.dispose = function () { - this._element.removeEventListener('touchstart', this._bindedEnd); - this._element.removeEventListener('touchmove', this._bindedMove); - this._element.removeEventListener('touchend', this._bindedEnd); - this._element.removeEventListener('mouseup', this._bindedEnd); - this._bindedMove = null; - this._bindedEnd = null; - this._element = null; - }; - function startContext(context) { - var buffer = context.createBuffer(1, 1, context.sampleRate); - var source = context.createBufferSource(); - source.buffer = buffer; - source.connect(context.destination); - source.start(0); - if (context.resume) { - context.resume(); - } - } - function isStarted(context) { - return context.state === 'running'; - } - function onStarted(context, callback) { - function checkLoop() { - if (isStarted(context)) { - callback(); - } else { - requestAnimationFrame(checkLoop); - if (context.resume) { - context.resume(); + if (typeof AudioContext.prototype.createOscillator !== "function") { + AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator; + AudioContext.prototype.createOscillator = function () { + var node = this.internal_createOscillator(); + if (!node.start) { + node.start = function (when) { + this.noteOn(when || 0); + }; + } else { + node.internal_start = node.start; + node.start = function (when) { + node.internal_start(when || 0); + }; + } + if (!node.stop) { + node.stop = function (when) { + this.noteOff(when || 0); + }; + } else { + node.internal_stop = node.stop; + node.stop = function (when) { + node.internal_stop(when || 0); + }; + } + if (!node.setPeriodicWave) node.setPeriodicWave = node.setWaveTable; + fixSetTarget(node.frequency); + fixSetTarget(node.detune); + return node; + }; } } - } - if (isStarted(context)) { - callback(); + if ( + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") + ) { + window.OfflineAudioContext = window.webkitOfflineAudioContext; + } + })(window); + // <-- end MonkeyPatch. + // Polyfill for AudioIn, also handled by p5.dom createCapture + navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia; + /** + * Determine which filetypes are supported (inspired by buzz.js) + * The audio element (el) will only be used to test browser support for various audio formats + */ + var el = document.createElement("audio"); + p5.prototype.isSupported = function () { + return !!el.canPlayType; + }; + var isOGGSupported = function () { + return !!el.canPlayType && el.canPlayType('audio/ogg; codecs="vorbis"'); + }; + var isMP3Supported = function () { + return !!el.canPlayType && el.canPlayType("audio/mpeg;"); + }; + var isWAVSupported = function () { + return !!el.canPlayType && el.canPlayType('audio/wav; codecs="1"'); + }; + var isAACSupported = function () { + return ( + !!el.canPlayType && + (el.canPlayType("audio/x-m4a;") || el.canPlayType("audio/aac;")) + ); + }; + var isAIFSupported = function () { + return !!el.canPlayType && el.canPlayType("audio/x-aiff;"); + }; + p5.prototype.isFileSupported = function (extension) { + switch (extension.toLowerCase()) { + case "mp3": + return isMP3Supported(); + case "wav": + return isWAVSupported(); + case "ogg": + return isOGGSupported(); + case "aac": + case "m4a": + case "mp4": + return isAACSupported(); + case "aif": + case "aiff": + return isAIFSupported(); + default: + return false; + } + }; + })(); + var StartAudioContext; + (function (root, factory) { + if (true) { + StartAudioContext = (function () { + return factory(); + })(); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(); } else { - checkLoop(); - } - } - function bindTapListener(element, tapListeners, context) { - if (Array.isArray(element) || NodeList && element instanceof NodeList) { - for (var i = 0; i < element.length; i++) { - bindTapListener(element[i], tapListeners, context); - } - } else if (typeof element === 'string') { - bindTapListener(document.querySelectorAll(element), tapListeners, context); - } else if (element.jquery && typeof element.toArray === 'function') { - bindTapListener(element.toArray(), tapListeners, context); - } else if (Element && element instanceof Element) { - var tap = new TapListener(element, context); - tapListeners.push(tap); - } - } - function StartAudioContext(context, elements, callback) { - var promise = new Promise(function (success) { - onStarted(context, success); - }); - var tapListeners = []; - if (!elements) { - elements = document.body; - } - bindTapListener(elements, tapListeners, context); - promise.then(function () { - for (var i = 0; i < tapListeners.length; i++) { - tapListeners[i].dispose(); + root.StartAudioContext = factory(); + } + })(this, function () { + var TapListener = function (element, context) { + this._dragged = false; + this._element = element; + this._bindedMove = this._moved.bind(this); + this._bindedEnd = this._ended.bind(this, context); + element.addEventListener("touchstart", this._bindedEnd); + element.addEventListener("touchmove", this._bindedMove); + element.addEventListener("touchend", this._bindedEnd); + element.addEventListener("mouseup", this._bindedEnd); + }; + TapListener.prototype._moved = function (e) { + this._dragged = true; + }; + TapListener.prototype._ended = function (context) { + if (!this._dragged) { + startContext(context); + } + this._dragged = false; + }; + TapListener.prototype.dispose = function () { + this._element.removeEventListener("touchstart", this._bindedEnd); + this._element.removeEventListener("touchmove", this._bindedMove); + this._element.removeEventListener("touchend", this._bindedEnd); + this._element.removeEventListener("mouseup", this._bindedEnd); + this._bindedMove = null; + this._bindedEnd = null; + this._element = null; + }; + function startContext(context) { + var buffer = context.createBuffer(1, 1, context.sampleRate); + var source = context.createBufferSource(); + source.buffer = buffer; + source.connect(context.destination); + source.start(0); + if (context.resume) { + context.resume(); + } + } + function isStarted(context) { + return context.state === "running"; + } + function onStarted(context, callback) { + function checkLoop() { + if (isStarted(context)) { + callback(); + } else { + requestAnimationFrame(checkLoop); + if (context.resume) { + context.resume(); + } + } } - tapListeners = null; - if (callback) { + if (isStarted(context)) { callback(); + } else { + checkLoop(); } - }); - return promise; - } - return StartAudioContext; -})); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Tone; -Tone_core_Tone = function () { - 'use strict'; - var Tone = function (inputs, outputs) { - if (this.isUndef(inputs) || inputs === 1) { - this.input = this.context.createGain(); - } else if (inputs > 1) { - this.input = new Array(inputs); } - if (this.isUndef(outputs) || outputs === 1) { - this.output = this.context.createGain(); - } else if (outputs > 1) { - this.output = new Array(inputs); - } - }; - Tone.prototype.set = function (params, value, rampTime) { - if (this.isObject(params)) { - rampTime = value; - } else if (this.isString(params)) { - var tmpObj = {}; - tmpObj[params] = value; - params = tmpObj; + function bindTapListener(element, tapListeners, context) { + if (Array.isArray(element) || (NodeList && element instanceof NodeList)) { + for (var i = 0; i < element.length; i++) { + bindTapListener(element[i], tapListeners, context); + } + } else if (typeof element === "string") { + bindTapListener( + document.querySelectorAll(element), + tapListeners, + context + ); + } else if (element.jquery && typeof element.toArray === "function") { + bindTapListener(element.toArray(), tapListeners, context); + } else if (Element && element instanceof Element) { + var tap = new TapListener(element, context); + tapListeners.push(tap); + } + } + function StartAudioContext(context, elements, callback) { + var promise = new Promise(function (success) { + onStarted(context, success); + }); + var tapListeners = []; + if (!elements) { + elements = document.body; + } + bindTapListener(elements, tapListeners, context); + promise.then(function () { + for (var i = 0; i < tapListeners.length; i++) { + tapListeners[i].dispose(); + } + tapListeners = null; + if (callback) { + callback(); + } + }); + return promise; } - paramLoop: - for (var attr in params) { + return StartAudioContext; + }); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Tone; + Tone_core_Tone = (function () { + "use strict"; + var Tone = function (inputs, outputs) { + if (this.isUndef(inputs) || inputs === 1) { + this.input = this.context.createGain(); + } else if (inputs > 1) { + this.input = new Array(inputs); + } + if (this.isUndef(outputs) || outputs === 1) { + this.output = this.context.createGain(); + } else if (outputs > 1) { + this.output = new Array(inputs); + } + }; + Tone.prototype.set = function (params, value, rampTime) { + if (this.isObject(params)) { + rampTime = value; + } else if (this.isString(params)) { + var tmpObj = {}; + tmpObj[params] = value; + params = tmpObj; + } + paramLoop: for (var attr in params) { value = params[attr]; var parent = this; - if (attr.indexOf('.') !== -1) { - var attrSplit = attr.split('.'); + if (attr.indexOf(".") !== -1) { + var attrSplit = attr.split("."); for (var i = 0; i < attrSplit.length - 1; i++) { parent = parent[attrSplit[i]]; if (parent instanceof Tone) { attrSplit.splice(0, i + 1); - var innerParam = attrSplit.join('.'); + var innerParam = attrSplit.join("."); parent.set(innerParam, value); continue paramLoop; } @@ -405,7 +430,10 @@ Tone_core_Tone = function () { if (this.isUndef(param)) { continue; } - if (Tone.Signal && param instanceof Tone.Signal || Tone.Param && param instanceof Tone.Param) { + if ( + (Tone.Signal && param instanceof Tone.Signal) || + (Tone.Param && param instanceof Tone.Param) + ) { if (param.value !== value) { if (this.isUndef(rampTime)) { param.value = value; @@ -423,1089 +451,1116 @@ Tone_core_Tone = function () { parent[attr] = value; } } - return this; - }; - Tone.prototype.get = function (params) { - if (this.isUndef(params)) { - params = this._collectDefaults(this.constructor); - } else if (this.isString(params)) { - params = [params]; - } - var ret = {}; - for (var i = 0; i < params.length; i++) { - var attr = params[i]; - var parent = this; - var subRet = ret; - if (attr.indexOf('.') !== -1) { - var attrSplit = attr.split('.'); - for (var j = 0; j < attrSplit.length - 1; j++) { - var subAttr = attrSplit[j]; - subRet[subAttr] = subRet[subAttr] || {}; - subRet = subRet[subAttr]; - parent = parent[subAttr]; - } - attr = attrSplit[attrSplit.length - 1]; - } - var param = parent[attr]; - if (this.isObject(params[attr])) { - subRet[attr] = param.get(); - } else if (Tone.Signal && param instanceof Tone.Signal) { - subRet[attr] = param.value; - } else if (Tone.Param && param instanceof Tone.Param) { - subRet[attr] = param.value; - } else if (param instanceof AudioParam) { - subRet[attr] = param.value; - } else if (param instanceof Tone) { - subRet[attr] = param.get(); - } else if (!this.isFunction(param) && !this.isUndef(param)) { - subRet[attr] = param; + return this; + }; + Tone.prototype.get = function (params) { + if (this.isUndef(params)) { + params = this._collectDefaults(this.constructor); + } else if (this.isString(params)) { + params = [params]; } - } - return ret; - }; - Tone.prototype._collectDefaults = function (constr) { - var ret = []; - if (!this.isUndef(constr.defaults)) { - ret = Object.keys(constr.defaults); - } - if (!this.isUndef(constr._super)) { - var superDefs = this._collectDefaults(constr._super); - for (var i = 0; i < superDefs.length; i++) { - if (ret.indexOf(superDefs[i]) === -1) { - ret.push(superDefs[i]); + var ret = {}; + for (var i = 0; i < params.length; i++) { + var attr = params[i]; + var parent = this; + var subRet = ret; + if (attr.indexOf(".") !== -1) { + var attrSplit = attr.split("."); + for (var j = 0; j < attrSplit.length - 1; j++) { + var subAttr = attrSplit[j]; + subRet[subAttr] = subRet[subAttr] || {}; + subRet = subRet[subAttr]; + parent = parent[subAttr]; + } + attr = attrSplit[attrSplit.length - 1]; + } + var param = parent[attr]; + if (this.isObject(params[attr])) { + subRet[attr] = param.get(); + } else if (Tone.Signal && param instanceof Tone.Signal) { + subRet[attr] = param.value; + } else if (Tone.Param && param instanceof Tone.Param) { + subRet[attr] = param.value; + } else if (param instanceof AudioParam) { + subRet[attr] = param.value; + } else if (param instanceof Tone) { + subRet[attr] = param.get(); + } else if (!this.isFunction(param) && !this.isUndef(param)) { + subRet[attr] = param; } } - } - return ret; - }; - Tone.prototype.toString = function () { - for (var className in Tone) { - var isLetter = className[0].match(/^[A-Z]$/); - var sameConstructor = Tone[className] === this.constructor; - if (this.isFunction(Tone[className]) && isLetter && sameConstructor) { - return className; + return ret; + }; + Tone.prototype._collectDefaults = function (constr) { + var ret = []; + if (!this.isUndef(constr.defaults)) { + ret = Object.keys(constr.defaults); + } + if (!this.isUndef(constr._super)) { + var superDefs = this._collectDefaults(constr._super); + for (var i = 0; i < superDefs.length; i++) { + if (ret.indexOf(superDefs[i]) === -1) { + ret.push(superDefs[i]); + } + } } - } - return 'Tone'; - }; - Object.defineProperty(Tone.prototype, 'numberOfInputs', { - get: function () { - if (this.input) { - if (this.isArray(this.input)) { - return this.input.length; - } else { - return 1; + return ret; + }; + Tone.prototype.toString = function () { + for (var className in Tone) { + var isLetter = className[0].match(/^[A-Z]$/); + var sameConstructor = Tone[className] === this.constructor; + if (this.isFunction(Tone[className]) && isLetter && sameConstructor) { + return className; } - } else { - return 0; } - } - }); - Object.defineProperty(Tone.prototype, 'numberOfOutputs', { - get: function () { - if (this.output) { - if (this.isArray(this.output)) { - return this.output.length; + return "Tone"; + }; + Object.defineProperty(Tone.prototype, "numberOfInputs", { + get: function () { + if (this.input) { + if (this.isArray(this.input)) { + return this.input.length; + } else { + return 1; + } } else { - return 1; + return 0; } - } else { - return 0; - } - } - }); - Tone.prototype.dispose = function () { - if (!this.isUndef(this.input)) { - if (this.input instanceof AudioNode) { - this.input.disconnect(); + }, + }); + Object.defineProperty(Tone.prototype, "numberOfOutputs", { + get: function () { + if (this.output) { + if (this.isArray(this.output)) { + return this.output.length; + } else { + return 1; + } + } else { + return 0; + } + }, + }); + Tone.prototype.dispose = function () { + if (!this.isUndef(this.input)) { + if (this.input instanceof AudioNode) { + this.input.disconnect(); + } + this.input = null; } - this.input = null; - } - if (!this.isUndef(this.output)) { - if (this.output instanceof AudioNode) { - this.output.disconnect(); + if (!this.isUndef(this.output)) { + if (this.output instanceof AudioNode) { + this.output.disconnect(); + } + this.output = null; } - this.output = null; - } - return this; - }; - Tone.prototype.connect = function (unit, outputNum, inputNum) { - if (Array.isArray(this.output)) { - outputNum = this.defaultArg(outputNum, 0); - this.output[outputNum].connect(unit, 0, inputNum); - } else { - this.output.connect(unit, outputNum, inputNum); - } - return this; - }; - Tone.prototype.disconnect = function (destination, outputNum, inputNum) { - if (this.isArray(this.output)) { - if (this.isNumber(destination)) { - this.output[destination].disconnect(); - } else { + return this; + }; + Tone.prototype.connect = function (unit, outputNum, inputNum) { + if (Array.isArray(this.output)) { outputNum = this.defaultArg(outputNum, 0); - this.output[outputNum].disconnect(destination, 0, inputNum); - } - } else { - this.output.disconnect.apply(this.output, arguments); - } - }; - Tone.prototype.connectSeries = function () { - if (arguments.length > 1) { - var currentUnit = arguments[0]; - for (var i = 1; i < arguments.length; i++) { - var toUnit = arguments[i]; - currentUnit.connect(toUnit); - currentUnit = toUnit; + this.output[outputNum].connect(unit, 0, inputNum); + } else { + this.output.connect(unit, outputNum, inputNum); } - } - return this; - }; - Tone.prototype.chain = function () { - if (arguments.length > 0) { - var currentUnit = this; - for (var i = 0; i < arguments.length; i++) { - var toUnit = arguments[i]; - currentUnit.connect(toUnit); - currentUnit = toUnit; + return this; + }; + Tone.prototype.disconnect = function (destination, outputNum, inputNum) { + if (this.isArray(this.output)) { + if (this.isNumber(destination)) { + this.output[destination].disconnect(); + } else { + outputNum = this.defaultArg(outputNum, 0); + this.output[outputNum].disconnect(destination, 0, inputNum); + } + } else { + this.output.disconnect.apply(this.output, arguments); } - } - return this; - }; - Tone.prototype.fan = function () { - if (arguments.length > 0) { - for (var i = 0; i < arguments.length; i++) { - this.connect(arguments[i]); + }; + Tone.prototype.connectSeries = function () { + if (arguments.length > 1) { + var currentUnit = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + var toUnit = arguments[i]; + currentUnit.connect(toUnit); + currentUnit = toUnit; + } } - } - return this; - }; - AudioNode.prototype.chain = Tone.prototype.chain; - AudioNode.prototype.fan = Tone.prototype.fan; - Tone.prototype.defaultArg = function (given, fallback) { - if (this.isObject(given) && this.isObject(fallback)) { - var ret = {}; - for (var givenProp in given) { - ret[givenProp] = this.defaultArg(fallback[givenProp], given[givenProp]); + return this; + }; + Tone.prototype.chain = function () { + if (arguments.length > 0) { + var currentUnit = this; + for (var i = 0; i < arguments.length; i++) { + var toUnit = arguments[i]; + currentUnit.connect(toUnit); + currentUnit = toUnit; + } } - for (var fallbackProp in fallback) { - ret[fallbackProp] = this.defaultArg(given[fallbackProp], fallback[fallbackProp]); + return this; + }; + Tone.prototype.fan = function () { + if (arguments.length > 0) { + for (var i = 0; i < arguments.length; i++) { + this.connect(arguments[i]); + } } - return ret; - } else { - return this.isUndef(given) ? fallback : given; - } - }; - Tone.prototype.optionsObject = function (values, keys, defaults) { - var options = {}; - if (values.length === 1 && this.isObject(values[0])) { - options = values[0]; - } else { - for (var i = 0; i < keys.length; i++) { - options[keys[i]] = values[i]; + return this; + }; + AudioNode.prototype.chain = Tone.prototype.chain; + AudioNode.prototype.fan = Tone.prototype.fan; + Tone.prototype.defaultArg = function (given, fallback) { + if (this.isObject(given) && this.isObject(fallback)) { + var ret = {}; + for (var givenProp in given) { + ret[givenProp] = this.defaultArg( + fallback[givenProp], + given[givenProp] + ); + } + for (var fallbackProp in fallback) { + ret[fallbackProp] = this.defaultArg( + given[fallbackProp], + fallback[fallbackProp] + ); + } + return ret; + } else { + return this.isUndef(given) ? fallback : given; } - } - if (!this.isUndef(defaults)) { - return this.defaultArg(options, defaults); - } else { - return options; - } - }; - Tone.prototype.isUndef = function (val) { - return typeof val === 'undefined'; - }; - Tone.prototype.isFunction = function (val) { - return typeof val === 'function'; - }; - Tone.prototype.isNumber = function (arg) { - return typeof arg === 'number'; - }; - Tone.prototype.isObject = function (arg) { - return Object.prototype.toString.call(arg) === '[object Object]' && arg.constructor === Object; - }; - Tone.prototype.isBoolean = function (arg) { - return typeof arg === 'boolean'; - }; - Tone.prototype.isArray = function (arg) { - return Array.isArray(arg); - }; - Tone.prototype.isString = function (arg) { - return typeof arg === 'string'; - }; - Tone.noOp = function () { - }; - Tone.prototype._readOnly = function (property) { - if (Array.isArray(property)) { - for (var i = 0; i < property.length; i++) { - this._readOnly(property[i]); + }; + Tone.prototype.optionsObject = function (values, keys, defaults) { + var options = {}; + if (values.length === 1 && this.isObject(values[0])) { + options = values[0]; + } else { + for (var i = 0; i < keys.length; i++) { + options[keys[i]] = values[i]; + } } - } else { - Object.defineProperty(this, property, { - writable: false, - enumerable: true - }); - } - }; - Tone.prototype._writable = function (property) { - if (Array.isArray(property)) { - for (var i = 0; i < property.length; i++) { - this._writable(property[i]); + if (!this.isUndef(defaults)) { + return this.defaultArg(options, defaults); + } else { + return options; } - } else { - Object.defineProperty(this, property, { writable: true }); - } - }; - Tone.State = { - Started: 'started', - Stopped: 'stopped', - Paused: 'paused' - }; - Tone.prototype.equalPowerScale = function (percent) { - var piFactor = 0.5 * Math.PI; - return Math.sin(percent * piFactor); - }; - Tone.prototype.dbToGain = function (db) { - return Math.pow(2, db / 6); - }; - Tone.prototype.gainToDb = function (gain) { - return 20 * (Math.log(gain) / Math.LN10); - }; - Tone.prototype.intervalToFrequencyRatio = function (interval) { - return Math.pow(2, interval / 12); - }; - Tone.prototype.now = function () { - return Tone.context.now(); - }; - Tone.now = function () { - return Tone.context.now(); - }; - Tone.extend = function (child, parent) { - if (Tone.prototype.isUndef(parent)) { - parent = Tone; - } - function TempConstructor() { - } - TempConstructor.prototype = parent.prototype; - child.prototype = new TempConstructor(); - child.prototype.constructor = child; - child._super = parent; - }; - var audioContext; - Object.defineProperty(Tone, 'context', { - get: function () { - return audioContext; - }, - set: function (context) { - if (Tone.Context && context instanceof Tone.Context) { - audioContext = context; + }; + Tone.prototype.isUndef = function (val) { + return typeof val === "undefined"; + }; + Tone.prototype.isFunction = function (val) { + return typeof val === "function"; + }; + Tone.prototype.isNumber = function (arg) { + return typeof arg === "number"; + }; + Tone.prototype.isObject = function (arg) { + return ( + Object.prototype.toString.call(arg) === "[object Object]" && + arg.constructor === Object + ); + }; + Tone.prototype.isBoolean = function (arg) { + return typeof arg === "boolean"; + }; + Tone.prototype.isArray = function (arg) { + return Array.isArray(arg); + }; + Tone.prototype.isString = function (arg) { + return typeof arg === "string"; + }; + Tone.noOp = function () {}; + Tone.prototype._readOnly = function (property) { + if (Array.isArray(property)) { + for (var i = 0; i < property.length; i++) { + this._readOnly(property[i]); + } } else { - audioContext = new Tone.Context(context); + Object.defineProperty(this, property, { + writable: false, + enumerable: true, + }); } - if (Tone.Context) { - Tone.Context.emit('init', audioContext); + }; + Tone.prototype._writable = function (property) { + if (Array.isArray(property)) { + for (var i = 0; i < property.length; i++) { + this._writable(property[i]); + } + } else { + Object.defineProperty(this, property, { writable: true }); } - } - }); - Object.defineProperty(Tone.prototype, 'context', { - get: function () { - return Tone.context; - } - }); - Tone.setContext = function (ctx) { - Tone.context = ctx; - }; - Object.defineProperty(Tone.prototype, 'blockTime', { - get: function () { - return 128 / this.context.sampleRate; - } - }); - Object.defineProperty(Tone.prototype, 'sampleTime', { - get: function () { - return 1 / this.context.sampleRate; - } - }); - Object.defineProperty(Tone, 'supported', { - get: function () { - var hasAudioContext = window.hasOwnProperty('AudioContext') || window.hasOwnProperty('webkitAudioContext'); - var hasPromises = window.hasOwnProperty('Promise'); - var hasWorkers = window.hasOwnProperty('Worker'); - return hasAudioContext && hasPromises && hasWorkers; - } - }); - Tone.version = 'r10'; - if (!window.TONE_SILENCE_VERSION_LOGGING) { - } - return Tone; -}(); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Emitter; -Tone_core_Emitter = function (Tone) { - 'use strict'; - Tone.Emitter = function () { - this._events = {}; - }; - Tone.extend(Tone.Emitter); - Tone.Emitter.prototype.on = function (event, callback) { - var events = event.split(/\W+/); - for (var i = 0; i < events.length; i++) { - var eventName = events[i]; - if (!this._events.hasOwnProperty(eventName)) { - this._events[eventName] = []; - } - this._events[eventName].push(callback); - } - return this; - }; - Tone.Emitter.prototype.off = function (event, callback) { - var events = event.split(/\W+/); - for (var ev = 0; ev < events.length; ev++) { - event = events[ev]; - if (this._events.hasOwnProperty(event)) { - if (Tone.prototype.isUndef(callback)) { - this._events[event] = []; + }; + Tone.State = { + Started: "started", + Stopped: "stopped", + Paused: "paused", + }; + Tone.prototype.equalPowerScale = function (percent) { + var piFactor = 0.5 * Math.PI; + return Math.sin(percent * piFactor); + }; + Tone.prototype.dbToGain = function (db) { + return Math.pow(2, db / 6); + }; + Tone.prototype.gainToDb = function (gain) { + return 20 * (Math.log(gain) / Math.LN10); + }; + Tone.prototype.intervalToFrequencyRatio = function (interval) { + return Math.pow(2, interval / 12); + }; + Tone.prototype.now = function () { + return Tone.context.now(); + }; + Tone.now = function () { + return Tone.context.now(); + }; + Tone.extend = function (child, parent) { + if (Tone.prototype.isUndef(parent)) { + parent = Tone; + } + function TempConstructor() {} + TempConstructor.prototype = parent.prototype; + child.prototype = new TempConstructor(); + child.prototype.constructor = child; + child._super = parent; + }; + var audioContext; + Object.defineProperty(Tone, "context", { + get: function () { + return audioContext; + }, + set: function (context) { + if (Tone.Context && context instanceof Tone.Context) { + audioContext = context; } else { - var eventList = this._events[event]; - for (var i = 0; i < eventList.length; i++) { - if (eventList[i] === callback) { - eventList.splice(i, 1); + audioContext = new Tone.Context(context); + } + if (Tone.Context) { + Tone.Context.emit("init", audioContext); + } + }, + }); + Object.defineProperty(Tone.prototype, "context", { + get: function () { + return Tone.context; + }, + }); + Tone.setContext = function (ctx) { + Tone.context = ctx; + }; + Object.defineProperty(Tone.prototype, "blockTime", { + get: function () { + return 128 / this.context.sampleRate; + }, + }); + Object.defineProperty(Tone.prototype, "sampleTime", { + get: function () { + return 1 / this.context.sampleRate; + }, + }); + Object.defineProperty(Tone, "supported", { + get: function () { + var hasAudioContext = + window.hasOwnProperty("AudioContext") || + window.hasOwnProperty("webkitAudioContext"); + var hasPromises = window.hasOwnProperty("Promise"); + var hasWorkers = window.hasOwnProperty("Worker"); + return hasAudioContext && hasPromises && hasWorkers; + }, + }); + Tone.version = "r10"; + if (!window.TONE_SILENCE_VERSION_LOGGING) { + } + return Tone; + })(); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Emitter; + Tone_core_Emitter = (function (Tone) { + "use strict"; + Tone.Emitter = function () { + this._events = {}; + }; + Tone.extend(Tone.Emitter); + Tone.Emitter.prototype.on = function (event, callback) { + var events = event.split(/\W+/); + for (var i = 0; i < events.length; i++) { + var eventName = events[i]; + if (!this._events.hasOwnProperty(eventName)) { + this._events[eventName] = []; + } + this._events[eventName].push(callback); + } + return this; + }; + Tone.Emitter.prototype.off = function (event, callback) { + var events = event.split(/\W+/); + for (var ev = 0; ev < events.length; ev++) { + event = events[ev]; + if (this._events.hasOwnProperty(event)) { + if (Tone.prototype.isUndef(callback)) { + this._events[event] = []; + } else { + var eventList = this._events[event]; + for (var i = 0; i < eventList.length; i++) { + if (eventList[i] === callback) { + eventList.splice(i, 1); + } } } } } - } - return this; - }; - Tone.Emitter.prototype.emit = function (event) { - if (this._events) { - var args = Array.apply(null, arguments).slice(1); - if (this._events.hasOwnProperty(event)) { - var eventList = this._events[event]; - for (var i = 0, len = eventList.length; i < len; i++) { - eventList[i].apply(this, args); + return this; + }; + Tone.Emitter.prototype.emit = function (event) { + if (this._events) { + var args = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(event)) { + var eventList = this._events[event]; + for (var i = 0, len = eventList.length; i < len; i++) { + eventList[i].apply(this, args); + } } } + return this; + }; + Tone.Emitter.mixin = function (object) { + var functions = ["on", "off", "emit"]; + object._events = {}; + for (var i = 0; i < functions.length; i++) { + var func = functions[i]; + var emitterFunc = Tone.Emitter.prototype[func]; + object[func] = emitterFunc; + } + }; + Tone.Emitter.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._events = null; + return this; + }; + return Tone.Emitter; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Context; + Tone_core_Context = (function (Tone) { + if ( + !window.hasOwnProperty("AudioContext") && + window.hasOwnProperty("webkitAudioContext") + ) { + window.AudioContext = window.webkitAudioContext; } - return this; - }; - Tone.Emitter.mixin = function (object) { - var functions = [ - 'on', - 'off', - 'emit' - ]; - object._events = {}; - for (var i = 0; i < functions.length; i++) { - var func = functions[i]; - var emitterFunc = Tone.Emitter.prototype[func]; - object[func] = emitterFunc; - } - }; - Tone.Emitter.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._events = null; - return this; - }; - return Tone.Emitter; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Context; -Tone_core_Context = function (Tone) { - if (!window.hasOwnProperty('AudioContext') && window.hasOwnProperty('webkitAudioContext')) { - window.AudioContext = window.webkitAudioContext; - } - Tone.Context = function (context) { - Tone.Emitter.call(this); - if (!context) { - context = new window.AudioContext(); - } - this._context = context; - for (var prop in this._context) { - this._defineProperty(this._context, prop); - } - this._latencyHint = 'interactive'; - this._lookAhead = 0.1; - this._updateInterval = this._lookAhead / 3; - this._computedUpdateInterval = 0; - this._worker = this._createWorker(); - this._constants = {}; - }; - Tone.extend(Tone.Context, Tone.Emitter); - Tone.Emitter.mixin(Tone.Context); - Tone.Context.prototype._defineProperty = function (context, prop) { - if (this.isUndef(this[prop])) { - Object.defineProperty(this, prop, { - get: function () { - if (typeof context[prop] === 'function') { - return context[prop].bind(context); - } else { - return context[prop]; + Tone.Context = function (context) { + Tone.Emitter.call(this); + if (!context) { + context = new window.AudioContext(); + } + this._context = context; + for (var prop in this._context) { + this._defineProperty(this._context, prop); + } + this._latencyHint = "interactive"; + this._lookAhead = 0.1; + this._updateInterval = this._lookAhead / 3; + this._computedUpdateInterval = 0; + this._worker = this._createWorker(); + this._constants = {}; + }; + Tone.extend(Tone.Context, Tone.Emitter); + Tone.Emitter.mixin(Tone.Context); + Tone.Context.prototype._defineProperty = function (context, prop) { + if (this.isUndef(this[prop])) { + Object.defineProperty(this, prop, { + get: function () { + if (typeof context[prop] === "function") { + return context[prop].bind(context); + } else { + return context[prop]; + } + }, + set: function (val) { + context[prop] = val; + }, + }); + } + }; + Tone.Context.prototype.now = function () { + return this._context.currentTime; + }; + Tone.Context.prototype._createWorker = function () { + window.URL = window.URL || window.webkitURL; + var blob = new Blob([ + "var timeoutTime = " + + (this._updateInterval * 1000).toFixed(1) + + ";" + + "self.onmessage = function(msg){" + + "\ttimeoutTime = parseInt(msg.data);" + + "};" + + "function tick(){" + + "\tsetTimeout(tick, timeoutTime);" + + "\tself.postMessage('tick');" + + "}" + + "tick();", + ]); + var blobUrl = URL.createObjectURL(blob); + var worker = new Worker(blobUrl); + worker.addEventListener( + "message", + function () { + this.emit("tick"); + }.bind(this) + ); + worker.addEventListener( + "message", + function () { + var now = this.now(); + if (this.isNumber(this._lastUpdate)) { + var diff = now - this._lastUpdate; + this._computedUpdateInterval = Math.max( + diff, + this._computedUpdateInterval * 0.97 + ); } - }, - set: function (val) { - context[prop] = val; + this._lastUpdate = now; + }.bind(this) + ); + return worker; + }; + Tone.Context.prototype.getConstant = function (val) { + if (this._constants[val]) { + return this._constants[val]; + } else { + var buffer = this._context.createBuffer( + 1, + 128, + this._context.sampleRate + ); + var arr = buffer.getChannelData(0); + for (var i = 0; i < arr.length; i++) { + arr[i] = val; } - }); - } - }; - Tone.Context.prototype.now = function () { - return this._context.currentTime; - }; - Tone.Context.prototype._createWorker = function () { - window.URL = window.URL || window.webkitURL; - var blob = new Blob(['var timeoutTime = ' + (this._updateInterval * 1000).toFixed(1) + ';' + 'self.onmessage = function(msg){' + '\ttimeoutTime = parseInt(msg.data);' + '};' + 'function tick(){' + '\tsetTimeout(tick, timeoutTime);' + '\tself.postMessage(\'tick\');' + '}' + 'tick();']); - var blobUrl = URL.createObjectURL(blob); - var worker = new Worker(blobUrl); - worker.addEventListener('message', function () { - this.emit('tick'); - }.bind(this)); - worker.addEventListener('message', function () { - var now = this.now(); - if (this.isNumber(this._lastUpdate)) { - var diff = now - this._lastUpdate; - this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97); - } - this._lastUpdate = now; - }.bind(this)); - return worker; - }; - Tone.Context.prototype.getConstant = function (val) { - if (this._constants[val]) { - return this._constants[val]; - } else { - var buffer = this._context.createBuffer(1, 128, this._context.sampleRate); - var arr = buffer.getChannelData(0); - for (var i = 0; i < arr.length; i++) { - arr[i] = val; - } - var constant = this._context.createBufferSource(); - constant.channelCount = 1; - constant.channelCountMode = 'explicit'; - constant.buffer = buffer; - constant.loop = true; - constant.start(0); - this._constants[val] = constant; - return constant; - } - }; - Object.defineProperty(Tone.Context.prototype, 'lag', { - get: function () { - var diff = this._computedUpdateInterval - this._updateInterval; - diff = Math.max(diff, 0); - return diff; - } - }); - Object.defineProperty(Tone.Context.prototype, 'lookAhead', { - get: function () { - return this._lookAhead; - }, - set: function (lA) { - this._lookAhead = lA; - } - }); - Object.defineProperty(Tone.Context.prototype, 'updateInterval', { - get: function () { - return this._updateInterval; - }, - set: function (interval) { - this._updateInterval = Math.max(interval, Tone.prototype.blockTime); - this._worker.postMessage(Math.max(interval * 1000, 1)); - } - }); - Object.defineProperty(Tone.Context.prototype, 'latencyHint', { - get: function () { - return this._latencyHint; - }, - set: function (hint) { - var lookAhead = hint; - this._latencyHint = hint; - if (this.isString(hint)) { - switch (hint) { - case 'interactive': - lookAhead = 0.1; - this._context.latencyHint = hint; - break; - case 'playback': - lookAhead = 0.8; - this._context.latencyHint = hint; - break; - case 'balanced': - lookAhead = 0.25; - this._context.latencyHint = hint; - break; - case 'fastest': - lookAhead = 0.01; - break; + var constant = this._context.createBufferSource(); + constant.channelCount = 1; + constant.channelCountMode = "explicit"; + constant.buffer = buffer; + constant.loop = true; + constant.start(0); + this._constants[val] = constant; + return constant; + } + }; + Object.defineProperty(Tone.Context.prototype, "lag", { + get: function () { + var diff = this._computedUpdateInterval - this._updateInterval; + diff = Math.max(diff, 0); + return diff; + }, + }); + Object.defineProperty(Tone.Context.prototype, "lookAhead", { + get: function () { + return this._lookAhead; + }, + set: function (lA) { + this._lookAhead = lA; + }, + }); + Object.defineProperty(Tone.Context.prototype, "updateInterval", { + get: function () { + return this._updateInterval; + }, + set: function (interval) { + this._updateInterval = Math.max(interval, Tone.prototype.blockTime); + this._worker.postMessage(Math.max(interval * 1000, 1)); + }, + }); + Object.defineProperty(Tone.Context.prototype, "latencyHint", { + get: function () { + return this._latencyHint; + }, + set: function (hint) { + var lookAhead = hint; + this._latencyHint = hint; + if (this.isString(hint)) { + switch (hint) { + case "interactive": + lookAhead = 0.1; + this._context.latencyHint = hint; + break; + case "playback": + lookAhead = 0.8; + this._context.latencyHint = hint; + break; + case "balanced": + lookAhead = 0.25; + this._context.latencyHint = hint; + break; + case "fastest": + lookAhead = 0.01; + break; + } + } + this.lookAhead = lookAhead; + this.updateInterval = lookAhead / 3; + }, + }); + function shimConnect() { + var nativeConnect = AudioNode.prototype.connect; + var nativeDisconnect = AudioNode.prototype.disconnect; + function toneConnect(B, outNum, inNum) { + if (B.input) { + if (Array.isArray(B.input)) { + if (Tone.prototype.isUndef(inNum)) { + inNum = 0; + } + this.connect(B.input[inNum]); + } else { + this.connect(B.input, outNum, inNum); + } + } else { + try { + if (B instanceof AudioNode) { + nativeConnect.call(this, B, outNum, inNum); + } else { + nativeConnect.call(this, B, outNum); + } + } catch (e) { + throw new Error("error connecting to node: " + B + "\n" + e); + } } } - this.lookAhead = lookAhead; - this.updateInterval = lookAhead / 3; - } - }); - function shimConnect() { - var nativeConnect = AudioNode.prototype.connect; - var nativeDisconnect = AudioNode.prototype.disconnect; - function toneConnect(B, outNum, inNum) { - if (B.input) { - if (Array.isArray(B.input)) { + function toneDisconnect(B, outNum, inNum) { + if (B && B.input && Array.isArray(B.input)) { if (Tone.prototype.isUndef(inNum)) { inNum = 0; } - this.connect(B.input[inNum]); + this.disconnect(B.input[inNum], outNum, inNum); + } else if (B && B.input) { + this.disconnect(B.input, outNum, inNum); } else { - this.connect(B.input, outNum, inNum); - } - } else { - try { - if (B instanceof AudioNode) { - nativeConnect.call(this, B, outNum, inNum); - } else { - nativeConnect.call(this, B, outNum); + try { + nativeDisconnect.apply(this, arguments); + } catch (e) { + throw new Error("error disconnecting node: " + B + "\n" + e); } - } catch (e) { - throw new Error('error connecting to node: ' + B + '\n' + e); } } - } - function toneDisconnect(B, outNum, inNum) { - if (B && B.input && Array.isArray(B.input)) { - if (Tone.prototype.isUndef(inNum)) { - inNum = 0; - } - this.disconnect(B.input[inNum], outNum, inNum); - } else if (B && B.input) { - this.disconnect(B.input, outNum, inNum); - } else { - try { - nativeDisconnect.apply(this, arguments); - } catch (e) { - throw new Error('error disconnecting node: ' + B + '\n' + e); - } + if (AudioNode.prototype.connect !== toneConnect) { + AudioNode.prototype.connect = toneConnect; + AudioNode.prototype.disconnect = toneDisconnect; } } - if (AudioNode.prototype.connect !== toneConnect) { - AudioNode.prototype.connect = toneConnect; - AudioNode.prototype.disconnect = toneDisconnect; - } - } - if (Tone.supported) { - shimConnect(); - Tone.context = new Tone.Context(); - } else { - console.warn('This browser does not support Tone.js'); - } - return Tone.Context; -}(Tone_core_Tone); -var audiocontext; -'use strict'; -audiocontext = function (StartAudioContext, Context, Tone) { - // Create the Audio Context - const audiocontext = new window.AudioContext(); - Tone.context.dispose(); - Tone.setContext(audiocontext); - /** - *

Returns the Audio Context for this sketch. Useful for users - * who would like to dig deeper into the Web Audio API - * .

- * - *

Some browsers require users to startAudioContext - * with a user gesture, such as touchStarted in the example below.

- * - * @method getAudioContext - * @return {Object} AudioContext for this sketch - * @example - *
- * function draw() { - * background(255); - * textAlign(CENTER); - * - * if (getAudioContext().state !== 'running') { - * text('click to start audio', width/2, height/2); - * } else { - * text('audio is enabled', width/2, height/2); - * } - * } - * - * function touchStarted() { - * if (getAudioContext().state !== 'running') { - * getAudioContext().resume(); - * } - * var synth = new p5.MonoSynth(); - * synth.play('A4', 0.5, 0, 0.2); - * } - * - *
- */ - p5.prototype.getAudioContext = function () { - return audiocontext; - }; - /** - *

It is a good practice to give users control over starting audio playback. - * This practice is enforced by Google Chrome's autoplay policy as of r70 - * (info), iOS Safari, and other browsers. - *

- * - *

- * userStartAudio() starts the Audio Context on a user gesture. It utilizes - * the StartAudioContext library by - * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext. - *

- * - *

Starting the audio context on a user gesture can be as simple as userStartAudio(). - * Optional parameters let you decide on a specific element that will start the audio context, - * and/or call a function once the audio context is started.

- * @param {Element|Array} [element(s)] This argument can be an Element, - * Selector String, NodeList, p5.Element, - * jQuery Element, or an Array of any of those. - * @param {Function} [callback] Callback to invoke when the AudioContext has started - * @return {Promise} Returns a Promise which is resolved when - * the AudioContext state is 'running' - * @method userStartAudio - * @example - *
- * function setup() { - * var myDiv = createDiv('click to start audio'); - * myDiv.position(0, 0); - * - * var mySynth = new p5.MonoSynth(); - * - * // This won't play until the context has started - * mySynth.play('A6'); - * - * // Start the audio context on a click/touch event - * userStartAudio().then(function() { - * myDiv.remove(); - * }); - * } - *
- */ - p5.prototype.userStartAudio = function (elements, callback) { - var elt = elements; - if (elements instanceof p5.Element) { - elt = elements.elt; - } else if (elements instanceof Array && elements[0] instanceof p5.Element) { - elt = elements.map(function (e) { - return e.elt; - }); - } - return StartAudioContext(audiocontext, elt, callback); - }; - return audiocontext; -}(StartAudioContext, Tone_core_Context, Tone_core_Tone); -var master; -'use strict'; -master = function (audiocontext) { - /** - * Master contains AudioContext and the master sound output. - */ - var Master = function () { - this.input = audiocontext.createGain(); - this.output = audiocontext.createGain(); - //put a hard limiter on the output - this.limiter = audiocontext.createDynamicsCompressor(); - this.limiter.threshold.value = -3; - this.limiter.ratio.value = 20; - this.limiter.knee.value = 1; - this.audiocontext = audiocontext; - this.output.disconnect(); - // connect input to limiter - this.input.connect(this.limiter); - // connect limiter to output - this.limiter.connect(this.output); - // meter is just for global Amplitude / FFT analysis - this.meter = audiocontext.createGain(); - this.fftMeter = audiocontext.createGain(); - this.output.connect(this.meter); - this.output.connect(this.fftMeter); - // connect output to destination - this.output.connect(this.audiocontext.destination); - // an array of all sounds in the sketch - this.soundArray = []; - // an array of all musical parts in the sketch - this.parts = []; - // file extensions to search for - this.extensions = []; - }; - // create a single instance of the p5Sound / master output for use within this sketch - var p5sound = new Master(); - /** - * Returns a number representing the master amplitude (volume) for sound - * in this sketch. - * - * @method getMasterVolume - * @return {Number} Master amplitude (volume) for sound in this sketch. - * Should be between 0.0 (silence) and 1.0. - */ - p5.prototype.getMasterVolume = function () { - return p5sound.output.gain.value; - }; - /** - *

Scale the output of all sound in this sketch

- * Scaled between 0.0 (silence) and 1.0 (full volume). - * 1.0 is the maximum amplitude of a digital sound, so multiplying - * by greater than 1.0 may cause digital distortion. To - * fade, provide a rampTime parameter. For more - * complex fades, see the Envelope class. - * - * Alternately, you can pass in a signal source such as an - * oscillator to modulate the amplitude with an audio signal. - * - *

How This Works: When you load the p5.sound module, it - * creates a single instance of p5sound. All sound objects in this - * module output to p5sound before reaching your computer's output. - * So if you change the amplitude of p5sound, it impacts all of the - * sound in this module.

- * - *

If no value is provided, returns a Web Audio API Gain Node

- * - * @method masterVolume - * @param {Number|Object} volume Volume (amplitude) between 0.0 - * and 1.0 or modulating signal/oscillator - * @param {Number} [rampTime] Fade for t seconds - * @param {Number} [timeFromNow] Schedule this event to happen at - * t seconds in the future - */ - p5.prototype.masterVolume = function (vol, rampTime, tFromNow) { - if (typeof vol === 'number') { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = p5sound.output.gain.value; - p5sound.output.gain.cancelScheduledValues(now + tFromNow); - p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - p5sound.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(p5sound.output.gain); + if (Tone.supported) { + shimConnect(); + Tone.context = new Tone.Context(); } else { - // return the Gain Node - return p5sound.output.gain; - } - }; - /** - * `p5.soundOut` is the p5.sound master output. It sends output to - * the destination of this window's web audio context. It contains - * Web Audio API nodes including a dyanmicsCompressor (.limiter), - * and Gain Nodes for .input and .output. - * - * @property {Object} soundOut - */ - p5.prototype.soundOut = p5.soundOut = p5sound; - /** - * a silent connection to the DesinationNode - * which will ensure that anything connected to it - * will not be garbage collected - * - * @private - */ - p5.soundOut._silentNode = p5sound.audiocontext.createGain(); - p5.soundOut._silentNode.gain.value = 0; - p5.soundOut._silentNode.connect(p5sound.audiocontext.destination); - return p5sound; -}(audiocontext); -var helpers; -'use strict'; -helpers = function () { - var p5sound = master; - /** - * @for p5 - */ - /** - * Returns a number representing the sample rate, in samples per second, - * of all sound objects in this audio context. It is determined by the - * sampling rate of your operating system's sound card, and it is not - * currently possile to change. - * It is often 44100, or twice the range of human hearing. - * - * @method sampleRate - * @return {Number} samplerate samples per second - */ - p5.prototype.sampleRate = function () { - return p5sound.audiocontext.sampleRate; - }; - /** - * Returns the closest MIDI note value for - * a given frequency. - * - * @method freqToMidi - * @param {Number} frequency A freqeuncy, for example, the "A" - * above Middle C is 440Hz - * @return {Number} MIDI note value - */ - p5.prototype.freqToMidi = function (f) { - var mathlog2 = Math.log(f / 440) / Math.log(2); - var m = Math.round(12 * mathlog2) + 69; - return m; - }; - /** - * Returns the frequency value of a MIDI note value. - * General MIDI treats notes as integers where middle C - * is 60, C# is 61, D is 62 etc. Useful for generating - * musical frequencies with oscillators. - * - * @method midiToFreq - * @param {Number} midiNote The number of a MIDI note - * @return {Number} Frequency value of the given MIDI note - * @example - *
- * var notes = [60, 64, 67, 72]; - * var i = 0; - * - * function setup() { - * osc = new p5.Oscillator('Triangle'); - * osc.start(); - * frameRate(1); - * } - * - * function draw() { - * var freq = midiToFreq(notes[i]); - * osc.freq(freq); - * i++; - * if (i >= notes.length){ - * i = 0; - * } - * } - *
- */ - var midiToFreq = p5.prototype.midiToFreq = function (m) { - return 440 * Math.pow(2, (m - 69) / 12); - }; - // This method converts ANSI notes specified as a string "C4", "Eb3" to a frequency - var noteToFreq = function (note) { - if (typeof note !== 'string') { - return note; - } - var wholeNotes = { - A: 21, - B: 23, - C: 24, - D: 26, - E: 28, - F: 29, - G: 31 - }; - var value = wholeNotes[note[0].toUpperCase()]; - var octave = ~~note.slice(-1); - value += 12 * (octave - 1); - switch (note[1]) { - case '#': - value += 1; - break; - case 'b': - value -= 1; - break; - default: - break; - } - return midiToFreq(value); - }; - /** - * List the SoundFile formats that you will include. LoadSound - * will search your directory for these extensions, and will pick - * a format that is compatable with the client's web browser. - * Here is a free online file - * converter. - * - * @method soundFormats - * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg' - * @example - *
- * function preload() { - * // set the global sound formats - * soundFormats('mp3', 'ogg'); - * - * // load either beatbox.mp3, or .ogg, depending on browser - * mySound = loadSound('assets/beatbox.mp3'); - * } - * - * function setup() { - * mySound.play(); - * } - *
- */ - p5.prototype.soundFormats = function () { - // reset extensions array - p5sound.extensions = []; - // add extensions - for (var i = 0; i < arguments.length; i++) { - arguments[i] = arguments[i].toLowerCase(); - if ([ - 'mp3', - 'wav', - 'ogg', - 'm4a', - 'aac' - ].indexOf(arguments[i]) > -1) { - p5sound.extensions.push(arguments[i]); + console.warn("This browser does not support Tone.js"); + } + return Tone.Context; + })(Tone_core_Tone); + var audiocontext; + ("use strict"); + audiocontext = (function (StartAudioContext, Context, Tone) { + // Create the Audio Context + const audiocontext = new window.AudioContext(); + Tone.context.dispose(); + Tone.setContext(audiocontext); + /** + *

Returns the Audio Context for this sketch. Useful for users + * who would like to dig deeper into the Web Audio API + * .

+ * + *

Some browsers require users to startAudioContext + * with a user gesture, such as touchStarted in the example below.

+ * + * @method getAudioContext + * @return {Object} AudioContext for this sketch + * @example + *
+ * function draw() { + * background(255); + * textAlign(CENTER); + * + * if (getAudioContext().state !== 'running') { + * text('click to start audio', width/2, height/2); + * } else { + * text('audio is enabled', width/2, height/2); + * } + * } + * + * function touchStarted() { + * if (getAudioContext().state !== 'running') { + * getAudioContext().resume(); + * } + * var synth = new p5.MonoSynth(); + * synth.play('A4', 0.5, 0, 0.2); + * } + * + *
+ */ + p5.prototype.getAudioContext = function () { + return audiocontext; + }; + /** + *

It is a good practice to give users control over starting audio playback. + * This practice is enforced by Google Chrome's autoplay policy as of r70 + * (info), iOS Safari, and other browsers. + *

+ * + *

+ * userStartAudio() starts the Audio Context on a user gesture. It utilizes + * the StartAudioContext library by + * Yotam Mann (MIT Licence, 2016). Read more at https://github.com/tambien/StartAudioContext. + *

+ * + *

Starting the audio context on a user gesture can be as simple as userStartAudio(). + * Optional parameters let you decide on a specific element that will start the audio context, + * and/or call a function once the audio context is started.

+ * @param {Element|Array} [element(s)] This argument can be an Element, + * Selector String, NodeList, p5.Element, + * jQuery Element, or an Array of any of those. + * @param {Function} [callback] Callback to invoke when the AudioContext has started + * @return {Promise} Returns a Promise which is resolved when + * the AudioContext state is 'running' + * @method userStartAudio + * @example + *
+ * function setup() { + * var myDiv = createDiv('click to start audio'); + * myDiv.position(0, 0); + * + * var mySynth = new p5.MonoSynth(); + * + * // This won't play until the context has started + * mySynth.play('A6'); + * + * // Start the audio context on a click/touch event + * userStartAudio().then(function() { + * myDiv.remove(); + * }); + * } + *
+ */ + p5.prototype.userStartAudio = function (elements, callback) { + var elt = elements; + if (elements instanceof p5.Element) { + elt = elements.elt; + } else if ( + elements instanceof Array && + elements[0] instanceof p5.Element + ) { + elt = elements.map(function (e) { + return e.elt; + }); + } + return StartAudioContext(audiocontext, elt, callback); + }; + return audiocontext; + })(StartAudioContext, Tone_core_Context, Tone_core_Tone); + var master; + ("use strict"); + master = (function (audiocontext) { + /** + * Master contains AudioContext and the master sound output. + */ + var Master = function () { + this.input = audiocontext.createGain(); + this.output = audiocontext.createGain(); + //put a hard limiter on the output + this.limiter = audiocontext.createDynamicsCompressor(); + this.limiter.threshold.value = -3; + this.limiter.ratio.value = 20; + this.limiter.knee.value = 1; + this.audiocontext = audiocontext; + this.output.disconnect(); + // connect input to limiter + this.input.connect(this.limiter); + // connect limiter to output + this.limiter.connect(this.output); + // meter is just for global Amplitude / FFT analysis + this.meter = audiocontext.createGain(); + this.fftMeter = audiocontext.createGain(); + this.output.connect(this.meter); + this.output.connect(this.fftMeter); + // connect output to destination + this.output.connect(this.audiocontext.destination); + // an array of all sounds in the sketch + this.soundArray = []; + // an array of all musical parts in the sketch + this.parts = []; + // file extensions to search for + this.extensions = []; + }; + // create a single instance of the p5Sound / master output for use within this sketch + var p5sound = new Master(); + /** + * Returns a number representing the master amplitude (volume) for sound + * in this sketch. + * + * @method getMasterVolume + * @return {Number} Master amplitude (volume) for sound in this sketch. + * Should be between 0.0 (silence) and 1.0. + */ + p5.prototype.getMasterVolume = function () { + return p5sound.output.gain.value; + }; + /** + *

Scale the output of all sound in this sketch

+ * Scaled between 0.0 (silence) and 1.0 (full volume). + * 1.0 is the maximum amplitude of a digital sound, so multiplying + * by greater than 1.0 may cause digital distortion. To + * fade, provide a rampTime parameter. For more + * complex fades, see the Envelope class. + * + * Alternately, you can pass in a signal source such as an + * oscillator to modulate the amplitude with an audio signal. + * + *

How This Works: When you load the p5.sound module, it + * creates a single instance of p5sound. All sound objects in this + * module output to p5sound before reaching your computer's output. + * So if you change the amplitude of p5sound, it impacts all of the + * sound in this module.

+ * + *

If no value is provided, returns a Web Audio API Gain Node

+ * + * @method masterVolume + * @param {Number|Object} volume Volume (amplitude) between 0.0 + * and 1.0 or modulating signal/oscillator + * @param {Number} [rampTime] Fade for t seconds + * @param {Number} [timeFromNow] Schedule this event to happen at + * t seconds in the future + */ + p5.prototype.masterVolume = function (vol, rampTime, tFromNow) { + if (typeof vol === "number") { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = p5sound.output.gain.value; + p5sound.output.gain.cancelScheduledValues(now + tFromNow); + p5sound.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + p5sound.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(p5sound.output.gain); } else { - throw arguments[i] + ' is not a valid sound format!'; + // return the Gain Node + return p5sound.output.gain; } - } - }; - p5.prototype.disposeSound = function () { - for (var i = 0; i < p5sound.soundArray.length; i++) { - p5sound.soundArray[i].dispose(); - } - }; - // register removeSound to dispose of p5sound SoundFiles, Convolvers, - // Oscillators etc when sketch ends - p5.prototype.registerMethod('remove', p5.prototype.disposeSound); - p5.prototype._checkFileFormats = function (paths) { - var path; - // if path is a single string, check to see if extension is provided - if (typeof paths === 'string') { - path = paths; - // see if extension is provided - var extTest = path.split('.').pop(); - // if an extension is provided... - if ([ - 'mp3', - 'wav', - 'ogg', - 'm4a', - 'aac' - ].indexOf(extTest) > -1) { - if (p5.prototype.isFileSupported(extTest)) { - path = path; + }; + /** + * `p5.soundOut` is the p5.sound master output. It sends output to + * the destination of this window's web audio context. It contains + * Web Audio API nodes including a dyanmicsCompressor (.limiter), + * and Gain Nodes for .input and .output. + * + * @property {Object} soundOut + */ + p5.prototype.soundOut = p5.soundOut = p5sound; + /** + * a silent connection to the DesinationNode + * which will ensure that anything connected to it + * will not be garbage collected + * + * @private + */ + p5.soundOut._silentNode = p5sound.audiocontext.createGain(); + p5.soundOut._silentNode.gain.value = 0; + p5.soundOut._silentNode.connect(p5sound.audiocontext.destination); + return p5sound; + })(audiocontext); + var helpers; + ("use strict"); + helpers = (function () { + var p5sound = master; + /** + * @for p5 + */ + /** + * Returns a number representing the sample rate, in samples per second, + * of all sound objects in this audio context. It is determined by the + * sampling rate of your operating system's sound card, and it is not + * currently possile to change. + * It is often 44100, or twice the range of human hearing. + * + * @method sampleRate + * @return {Number} samplerate samples per second + */ + p5.prototype.sampleRate = function () { + return p5sound.audiocontext.sampleRate; + }; + /** + * Returns the closest MIDI note value for + * a given frequency. + * + * @method freqToMidi + * @param {Number} frequency A freqeuncy, for example, the "A" + * above Middle C is 440Hz + * @return {Number} MIDI note value + */ + p5.prototype.freqToMidi = function (f) { + var mathlog2 = Math.log(f / 440) / Math.log(2); + var m = Math.round(12 * mathlog2) + 69; + return m; + }; + /** + * Returns the frequency value of a MIDI note value. + * General MIDI treats notes as integers where middle C + * is 60, C# is 61, D is 62 etc. Useful for generating + * musical frequencies with oscillators. + * + * @method midiToFreq + * @param {Number} midiNote The number of a MIDI note + * @return {Number} Frequency value of the given MIDI note + * @example + *
+ * var notes = [60, 64, 67, 72]; + * var i = 0; + * + * function setup() { + * osc = new p5.Oscillator('Triangle'); + * osc.start(); + * frameRate(1); + * } + * + * function draw() { + * var freq = midiToFreq(notes[i]); + * osc.freq(freq); + * i++; + * if (i >= notes.length){ + * i = 0; + * } + * } + *
+ */ + var midiToFreq = (p5.prototype.midiToFreq = function (m) { + return 440 * Math.pow(2, (m - 69) / 12); + }); + // This method converts ANSI notes specified as a string "C4", "Eb3" to a frequency + var noteToFreq = function (note) { + if (typeof note !== "string") { + return note; + } + var wholeNotes = { + A: 21, + B: 23, + C: 24, + D: 26, + E: 28, + F: 29, + G: 31, + }; + var value = wholeNotes[note[0].toUpperCase()]; + var octave = ~~note.slice(-1); + value += 12 * (octave - 1); + switch (note[1]) { + case "#": + value += 1; + break; + case "b": + value -= 1; + break; + default: + break; + } + return midiToFreq(value); + }; + /** + * List the SoundFile formats that you will include. LoadSound + * will search your directory for these extensions, and will pick + * a format that is compatable with the client's web browser. + * Here is a free online file + * converter. + * + * @method soundFormats + * @param {String} [...formats] i.e. 'mp3', 'wav', 'ogg' + * @example + *
+ * function preload() { + * // set the global sound formats + * soundFormats('mp3', 'ogg'); + * + * // load either beatbox.mp3, or .ogg, depending on browser + * mySound = loadSound('assets/beatbox.mp3'); + * } + * + * function setup() { + * mySound.play(); + * } + *
+ */ + p5.prototype.soundFormats = function () { + // reset extensions array + p5sound.extensions = []; + // add extensions + for (var i = 0; i < arguments.length; i++) { + arguments[i] = arguments[i].toLowerCase(); + if (["mp3", "wav", "ogg", "m4a", "aac"].indexOf(arguments[i]) > -1) { + p5sound.extensions.push(arguments[i]); + } else { + throw arguments[i] + " is not a valid sound format!"; + } + } + }; + p5.prototype.disposeSound = function () { + for (var i = 0; i < p5sound.soundArray.length; i++) { + p5sound.soundArray[i].dispose(); + } + }; + // register removeSound to dispose of p5sound SoundFiles, Convolvers, + // Oscillators etc when sketch ends + p5.prototype.registerMethod("remove", p5.prototype.disposeSound); + p5.prototype._checkFileFormats = function (paths) { + var path; + // if path is a single string, check to see if extension is provided + if (typeof paths === "string") { + path = paths; + // see if extension is provided + var extTest = path.split(".").pop(); + // if an extension is provided... + if (["mp3", "wav", "ogg", "m4a", "aac"].indexOf(extTest) > -1) { + if (p5.prototype.isFileSupported(extTest)) { + path = path; + } else { + var pathSplit = path.split("."); + var pathCore = pathSplit[pathSplit.length - 1]; + for (var i = 0; i < p5sound.extensions.length; i++) { + var extension = p5sound.extensions[i]; + var supported = p5.prototype.isFileSupported(extension); + if (supported) { + pathCore = ""; + if (pathSplit.length === 2) { + pathCore += pathSplit[0]; + } + for (var i = 1; i <= pathSplit.length - 2; i++) { + var p = pathSplit[i]; + pathCore += "." + p; + } + path = pathCore += "."; + path = path += extension; + break; + } + } + } } else { - var pathSplit = path.split('.'); - var pathCore = pathSplit[pathSplit.length - 1]; for (var i = 0; i < p5sound.extensions.length; i++) { var extension = p5sound.extensions[i]; var supported = p5.prototype.isFileSupported(extension); if (supported) { - pathCore = ''; - if (pathSplit.length === 2) { - pathCore += pathSplit[0]; - } - for (var i = 1; i <= pathSplit.length - 2; i++) { - var p = pathSplit[i]; - pathCore += '.' + p; - } - path = pathCore += '.'; - path = path += extension; + path = path + "." + extension; break; } } } - } else { - for (var i = 0; i < p5sound.extensions.length; i++) { - var extension = p5sound.extensions[i]; + } else if (typeof paths === "object") { + for (var i = 0; i < paths.length; i++) { + var extension = paths[i].split(".").pop(); var supported = p5.prototype.isFileSupported(extension); if (supported) { - path = path + '.' + extension; + // console.log('.'+extension + ' is ' + supported + + // ' supported by your browser.'); + path = paths[i]; break; } } } - } else if (typeof paths === 'object') { - for (var i = 0; i < paths.length; i++) { - var extension = paths[i].split('.').pop(); - var supported = p5.prototype.isFileSupported(extension); - if (supported) { - // console.log('.'+extension + ' is ' + supported + - // ' supported by your browser.'); - path = paths[i]; - break; + return path; + }; + /** + * Used by Osc and Envelope to chain signal math + */ + p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { + // if this type of math already exists in the chain, replace it + for (var i in o.mathOps) { + if (o.mathOps[i] instanceof type) { + o.mathOps[i].dispose(); + thisChain = i; + if (thisChain < o.mathOps.length - 1) { + nextChain = o.mathOps[i + 1]; + } } } - } - return path; - }; - /** - * Used by Osc and Envelope to chain signal math - */ - p5.prototype._mathChain = function (o, math, thisChain, nextChain, type) { - // if this type of math already exists in the chain, replace it - for (var i in o.mathOps) { - if (o.mathOps[i] instanceof type) { - o.mathOps[i].dispose(); - thisChain = i; - if (thisChain < o.mathOps.length - 1) { - nextChain = o.mathOps[i + 1]; - } + o.mathOps[thisChain - 1].disconnect(); + o.mathOps[thisChain - 1].connect(math); + math.connect(nextChain); + o.mathOps[thisChain] = math; + return o; + }; + // helper methods to convert audio file as .wav format, + // will use as saving .wav file and saving blob object + // Thank you to Matt Diamond's RecorderJS (MIT License) + // https://github.com/mattdiamond/Recorderjs + function convertToWav(audioBuffer) { + var leftChannel, rightChannel; + leftChannel = audioBuffer.getChannelData(0); + // handle mono files + if (audioBuffer.numberOfChannels > 1) { + rightChannel = audioBuffer.getChannelData(1); + } else { + rightChannel = leftChannel; + } + var interleaved = interleave(leftChannel, rightChannel); + // create the buffer and view to create the .WAV file + var buffer = new window.ArrayBuffer(44 + interleaved.length * 2); + var view = new window.DataView(buffer); + // write the WAV container, + // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf + // RIFF chunk descriptor + writeUTFBytes(view, 0, "RIFF"); + view.setUint32(4, 36 + interleaved.length * 2, true); + writeUTFBytes(view, 8, "WAVE"); + // FMT sub-chunk + writeUTFBytes(view, 12, "fmt "); + view.setUint32(16, 16, true); + view.setUint16(20, 1, true); + // stereo (2 channels) + view.setUint16(22, 2, true); + view.setUint32(24, p5sound.audiocontext.sampleRate, true); + view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true); + view.setUint16(32, 4, true); + view.setUint16(34, 16, true); + // data sub-chunk + writeUTFBytes(view, 36, "data"); + view.setUint32(40, interleaved.length * 2, true); + // write the PCM samples + var lng = interleaved.length; + var index = 44; + var volume = 1; + for (var i = 0; i < lng; i++) { + view.setInt16(index, interleaved[i] * (32767 * volume), true); + index += 2; + } + return view; + } + // helper methods to save waves + function interleave(leftChannel, rightChannel) { + var length = leftChannel.length + rightChannel.length; + var result = new Float32Array(length); + var inputIndex = 0; + for (var index = 0; index < length; ) { + result[index++] = leftChannel[inputIndex]; + result[index++] = rightChannel[inputIndex]; + inputIndex++; + } + return result; + } + function writeUTFBytes(view, offset, string) { + var lng = string.length; + for (var i = 0; i < lng; i++) { + view.setUint8(offset + i, string.charCodeAt(i)); } } - o.mathOps[thisChain - 1].disconnect(); - o.mathOps[thisChain - 1].connect(math); - math.connect(nextChain); - o.mathOps[thisChain] = math; - return o; - }; - // helper methods to convert audio file as .wav format, - // will use as saving .wav file and saving blob object - // Thank you to Matt Diamond's RecorderJS (MIT License) - // https://github.com/mattdiamond/Recorderjs - function convertToWav(audioBuffer) { - var leftChannel, rightChannel; - leftChannel = audioBuffer.getChannelData(0); - // handle mono files - if (audioBuffer.numberOfChannels > 1) { - rightChannel = audioBuffer.getChannelData(1); - } else { - rightChannel = leftChannel; - } - var interleaved = interleave(leftChannel, rightChannel); - // create the buffer and view to create the .WAV file - var buffer = new window.ArrayBuffer(44 + interleaved.length * 2); - var view = new window.DataView(buffer); - // write the WAV container, - // check spec at: https://web.archive.org/web/20171215131933/http://tiny.systems/software/soundProgrammer/WavFormatDocs.pdf - // RIFF chunk descriptor - writeUTFBytes(view, 0, 'RIFF'); - view.setUint32(4, 36 + interleaved.length * 2, true); - writeUTFBytes(view, 8, 'WAVE'); - // FMT sub-chunk - writeUTFBytes(view, 12, 'fmt '); - view.setUint32(16, 16, true); - view.setUint16(20, 1, true); - // stereo (2 channels) - view.setUint16(22, 2, true); - view.setUint32(24, p5sound.audiocontext.sampleRate, true); - view.setUint32(28, p5sound.audiocontext.sampleRate * 4, true); - view.setUint16(32, 4, true); - view.setUint16(34, 16, true); - // data sub-chunk - writeUTFBytes(view, 36, 'data'); - view.setUint32(40, interleaved.length * 2, true); - // write the PCM samples - var lng = interleaved.length; - var index = 44; - var volume = 1; - for (var i = 0; i < lng; i++) { - view.setInt16(index, interleaved[i] * (32767 * volume), true); - index += 2; - } - return view; - } - // helper methods to save waves - function interleave(leftChannel, rightChannel) { - var length = leftChannel.length + rightChannel.length; - var result = new Float32Array(length); - var inputIndex = 0; - for (var index = 0; index < length;) { - result[index++] = leftChannel[inputIndex]; - result[index++] = rightChannel[inputIndex]; - inputIndex++; - } - return result; - } - function writeUTFBytes(view, offset, string) { - var lng = string.length; - for (var i = 0; i < lng; i++) { - view.setUint8(offset + i, string.charCodeAt(i)); - } - } - return { - convertToWav: convertToWav, - midiToFreq: midiToFreq, - noteToFreq: noteToFreq - }; -}(master); -var errorHandler; -'use strict'; -errorHandler = function () { - /* + return { + convertToWav: convertToWav, + midiToFreq: midiToFreq, + noteToFreq: noteToFreq, + }; + })(master); + var errorHandler; + ("use strict"); + errorHandler = (function () { + /* Helper function to generate an error with a custom stack trace that points to the sketch and removes other parts of the stack trace. @@ -1524,11356 +1579,12106 @@ errorHandler = function () { @property {String} failedPath path to the file that failed to load @return {Error} returns a custom Error object */ - var CustomError = function (name, errorTrace, failedPath) { - var err = new Error(); - var tempStack, splitStack; - err.name = name; - err.originalStack = err.stack + errorTrace; - tempStack = err.stack + errorTrace; - err.failedPath = failedPath; - // only print the part of the stack trace that refers to the user code: - var splitStack = tempStack.split('\n'); - splitStack = splitStack.filter(function (ln) { - return !ln.match(/(p5.|native code|globalInit)/g); - }); - err.stack = splitStack.join('\n'); - return err; - }; - return CustomError; -}(); -var panner; -'use strict'; -panner = function () { - var p5sound = master; - var ac = p5sound.audiocontext; - // Stereo panner - // if there is a stereo panner node use it - if (typeof ac.createStereoPanner !== 'undefined') { - p5.Panner = function (input, output) { - this.stereoPanner = this.input = ac.createStereoPanner(); - input.connect(this.stereoPanner); - this.stereoPanner.connect(output); - }; - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = ac.currentTime + time; - this.stereoPanner.pan.linearRampToValueAtTime(val, t); - }; - //not implemented because stereopanner - //node does not require this and will automatically - //convert single channel or multichannel to stereo. - //tested with single and stereo, not with (>2) multichannel - p5.Panner.prototype.inputChannels = function () { - }; - p5.Panner.prototype.connect = function (obj) { - this.stereoPanner.connect(obj); - }; - p5.Panner.prototype.disconnect = function () { - if (this.stereoPanner) { - this.stereoPanner.disconnect(); - } - }; - } else { - // if there is no createStereoPanner object - // such as in safari 7.1.7 at the time of writing this - // use this method to create the effect - p5.Panner = function (input, output, numInputChannels) { - this.input = ac.createGain(); - input.connect(this.input); - this.left = ac.createGain(); - this.right = ac.createGain(); - this.left.channelInterpretation = 'discrete'; - this.right.channelInterpretation = 'discrete'; - // if input is stereo - if (numInputChannels > 1) { - this.splitter = ac.createChannelSplitter(2); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); - } else { - this.input.connect(this.left); - this.input.connect(this.right); - } - this.output = ac.createChannelMerger(2); - this.left.connect(this.output, 0, 1); - this.right.connect(this.output, 0, 0); - this.output.connect(output); - }; - // -1 is left, +1 is right - p5.Panner.prototype.pan = function (val, tFromNow) { - var time = tFromNow || 0; - var t = ac.currentTime + time; - var v = (val + 1) / 2; - var rightVal = Math.cos(v * Math.PI / 2); - var leftVal = Math.sin(v * Math.PI / 2); - this.left.gain.linearRampToValueAtTime(leftVal, t); - this.right.gain.linearRampToValueAtTime(rightVal, t); - }; - p5.Panner.prototype.inputChannels = function (numChannels) { - if (numChannels === 1) { - this.input.disconnect(); - this.input.connect(this.left); - this.input.connect(this.right); - } else if (numChannels === 2) { - if (typeof (this.splitter === 'undefined')) { - this.splitter = ac.createChannelSplitter(2); - } - this.input.disconnect(); - this.input.connect(this.splitter); - this.splitter.connect(this.left, 1); - this.splitter.connect(this.right, 0); - } - }; - p5.Panner.prototype.connect = function (obj) { - this.output.connect(obj); - }; - p5.Panner.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } + var CustomError = function (name, errorTrace, failedPath) { + var err = new Error(); + var tempStack, splitStack; + err.name = name; + err.originalStack = err.stack + errorTrace; + tempStack = err.stack + errorTrace; + err.failedPath = failedPath; + // only print the part of the stack trace that refers to the user code: + var splitStack = tempStack.split("\n"); + splitStack = splitStack.filter(function (ln) { + return !ln.match(/(p5.|native code|globalInit)/g); + }); + err.stack = splitStack.join("\n"); + return err; }; - } -}(master); -var soundfile; -'use strict'; -soundfile = function () { - var CustomError = errorHandler; - var p5sound = master; - var ac = p5sound.audiocontext; - var midiToFreq = helpers.midiToFreq; - var convertToWav = helpers.convertToWav; - /** - *

SoundFile object with a path to a file.

- * - *

The p5.SoundFile may not be available immediately because - * it loads the file information asynchronously.

- * - *

To do something with the sound as soon as it loads - * pass the name of a function as the second parameter.

- * - *

Only one file path is required. However, audio file formats - * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all - * web browsers. If you want to ensure compatability, instead of a single - * file path, you may include an Array of filepaths, and the browser will - * choose a format that works.

- * - * @class p5.SoundFile - * @constructor - * @param {String|Array} path path to a sound file (String). Optionally, - * you may include multiple file formats in - * an array. Alternately, accepts an object - * from the HTML5 File API, or a p5.File. - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if file fails to - * load. This function will receive an error or - * XMLHttpRequest object with information - * about what went wrong. - * @param {Function} [whileLoadingCallback] Name of a function to call while file - * is loading. That function will - * receive progress of the request to - * load the sound file - * (between 0 and 1) as its first - * parameter. This progress - * does not account for the additional - * time needed to decode the audio data. - * - * @example - *
- * - * function preload() { - * soundFormats('mp3', 'ogg'); - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * mySound.setVolume(0.1); - * mySound.play(); - * } - * - *
- */ - p5.SoundFile = function (paths, onload, onerror, whileLoading) { - if (typeof paths !== 'undefined') { - if (typeof paths === 'string' || typeof paths[0] === 'string') { - var path = p5.prototype._checkFileFormats(paths); - this.url = path; - } else if (typeof paths === 'object') { - if (!(window.File && window.FileReader && window.FileList && window.Blob)) { - // The File API isn't supported in this browser - throw 'Unable to load file because the File API is not supported'; - } - } - // if type is a p5.File...get the actual file - if (paths.file) { - paths = paths.file; - } - this.file = paths; - } - // private _onended callback, set by the method: onended(callback) - this._onended = function () { - }; - this._looping = false; - this._playing = false; - this._paused = false; - this._pauseTime = 0; - // cues for scheduling events with addCue() removeCue() - this._cues = []; - this._cueIDCounter = 0; - // position of the most recently played sample - this._lastPos = 0; - this._counterNode = null; - this._scopeNode = null; - // array of sources so that they can all be stopped! - this.bufferSourceNodes = []; - // current source - this.bufferSourceNode = null; - this.buffer = null; - this.playbackRate = 1; - this.input = p5sound.audiocontext.createGain(); - this.output = p5sound.audiocontext.createGain(); - this.reversed = false; - // start and end of playback / loop - this.startTime = 0; - this.endTime = null; - this.pauseTime = 0; - // "restart" would stop playback before retriggering - this.mode = 'sustain'; - // time that playback was started, in millis - this.startMillis = null; - // stereo panning - this.panPosition = 0; - this.panner = new p5.Panner(this.output, p5sound.input, 2); - // it is possible to instantiate a soundfile with no path - if (this.url || this.file) { - this.load(onload, onerror); - } - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - if (typeof whileLoading === 'function') { - this._whileLoading = whileLoading; + return CustomError; + })(); + var panner; + ("use strict"); + panner = (function () { + var p5sound = master; + var ac = p5sound.audiocontext; + // Stereo panner + // if there is a stereo panner node use it + if (typeof ac.createStereoPanner !== "undefined") { + p5.Panner = function (input, output) { + this.stereoPanner = this.input = ac.createStereoPanner(); + input.connect(this.stereoPanner); + this.stereoPanner.connect(output); + }; + p5.Panner.prototype.pan = function (val, tFromNow) { + var time = tFromNow || 0; + var t = ac.currentTime + time; + this.stereoPanner.pan.linearRampToValueAtTime(val, t); + }; + //not implemented because stereopanner + //node does not require this and will automatically + //convert single channel or multichannel to stereo. + //tested with single and stereo, not with (>2) multichannel + p5.Panner.prototype.inputChannels = function () {}; + p5.Panner.prototype.connect = function (obj) { + this.stereoPanner.connect(obj); + }; + p5.Panner.prototype.disconnect = function () { + if (this.stereoPanner) { + this.stereoPanner.disconnect(); + } + }; } else { - this._whileLoading = function () { + // if there is no createStereoPanner object + // such as in safari 7.1.7 at the time of writing this + // use this method to create the effect + p5.Panner = function (input, output, numInputChannels) { + this.input = ac.createGain(); + input.connect(this.input); + this.left = ac.createGain(); + this.right = ac.createGain(); + this.left.channelInterpretation = "discrete"; + this.right.channelInterpretation = "discrete"; + // if input is stereo + if (numInputChannels > 1) { + this.splitter = ac.createChannelSplitter(2); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } else { + this.input.connect(this.left); + this.input.connect(this.right); + } + this.output = ac.createChannelMerger(2); + this.left.connect(this.output, 0, 1); + this.right.connect(this.output, 0, 0); + this.output.connect(output); + }; + // -1 is left, +1 is right + p5.Panner.prototype.pan = function (val, tFromNow) { + var time = tFromNow || 0; + var t = ac.currentTime + time; + var v = (val + 1) / 2; + var rightVal = Math.cos((v * Math.PI) / 2); + var leftVal = Math.sin((v * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(leftVal, t); + this.right.gain.linearRampToValueAtTime(rightVal, t); + }; + p5.Panner.prototype.inputChannels = function (numChannels) { + if (numChannels === 1) { + this.input.disconnect(); + this.input.connect(this.left); + this.input.connect(this.right); + } else if (numChannels === 2) { + if (typeof (this.splitter === "undefined")) { + this.splitter = ac.createChannelSplitter(2); + } + this.input.disconnect(); + this.input.connect(this.splitter); + this.splitter.connect(this.left, 1); + this.splitter.connect(this.right, 0); + } + }; + p5.Panner.prototype.connect = function (obj) { + this.output.connect(obj); + }; + p5.Panner.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } }; } - this._onAudioProcess = _onAudioProcess.bind(this); - this._clearOnEnd = _clearOnEnd.bind(this); - }; - // register preload handling of loadSound - p5.prototype.registerPreloadMethod('loadSound', p5.prototype); - /** - * loadSound() returns a new p5.SoundFile from a specified - * path. If called during preload(), the p5.SoundFile will be ready - * to play in time for setup() and draw(). If called outside of - * preload, the p5.SoundFile will not be ready immediately, so - * loadSound accepts a callback as the second parameter. Using a - * - * local server is recommended when loading external files. - * - * @method loadSound - * @param {String|Array} path Path to the sound file, or an array with - * paths to soundfiles in multiple formats - * i.e. ['sound.ogg', 'sound.mp3']. - * Alternately, accepts an object: either - * from the HTML5 File API, or a p5.File. - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is - * an error loading the file. - * @param {Function} [whileLoading] Name of a function to call while file is loading. - * This function will receive the percentage loaded - * so far, from 0.0 to 1.0. - * @return {SoundFile} Returns a p5.SoundFile - * @example - *
- * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * mySound.setVolume(0.1); - * mySound.play(); - * } - *
- */ - p5.prototype.loadSound = function (path, callback, onerror, whileLoading) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - window.alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - var self = this; - var s = new p5.SoundFile(path, function () { - if (typeof callback === 'function') { - callback.apply(self, arguments); + })(master); + var soundfile; + ("use strict"); + soundfile = (function () { + var CustomError = errorHandler; + var p5sound = master; + var ac = p5sound.audiocontext; + var midiToFreq = helpers.midiToFreq; + var convertToWav = helpers.convertToWav; + /** + *

SoundFile object with a path to a file.

+ * + *

The p5.SoundFile may not be available immediately because + * it loads the file information asynchronously.

+ * + *

To do something with the sound as soon as it loads + * pass the name of a function as the second parameter.

+ * + *

Only one file path is required. However, audio file formats + * (i.e. mp3, ogg, wav and m4a/aac) are not supported by all + * web browsers. If you want to ensure compatability, instead of a single + * file path, you may include an Array of filepaths, and the browser will + * choose a format that works.

+ * + * @class p5.SoundFile + * @constructor + * @param {String|Array} path path to a sound file (String). Optionally, + * you may include multiple file formats in + * an array. Alternately, accepts an object + * from the HTML5 File API, or a p5.File. + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if file fails to + * load. This function will receive an error or + * XMLHttpRequest object with information + * about what went wrong. + * @param {Function} [whileLoadingCallback] Name of a function to call while file + * is loading. That function will + * receive progress of the request to + * load the sound file + * (between 0 and 1) as its first + * parameter. This progress + * does not account for the additional + * time needed to decode the audio data. + * + * @example + *
+ * + * function preload() { + * soundFormats('mp3', 'ogg'); + * mySound = loadSound('assets/doorbell.mp3'); + * } + * + * function setup() { + * mySound.setVolume(0.1); + * mySound.play(); + * } + * + *
+ */ + p5.SoundFile = function (paths, onload, onerror, whileLoading) { + if (typeof paths !== "undefined") { + if (typeof paths === "string" || typeof paths[0] === "string") { + var path = p5.prototype._checkFileFormats(paths); + this.url = path; + } else if (typeof paths === "object") { + if ( + !( + window.File && + window.FileReader && + window.FileList && + window.Blob + ) + ) { + // The File API isn't supported in this browser + throw "Unable to load file because the File API is not supported"; + } + } + // if type is a p5.File...get the actual file + if (paths.file) { + paths = paths.file; + } + this.file = paths; + } + // private _onended callback, set by the method: onended(callback) + this._onended = function () {}; + this._looping = false; + this._playing = false; + this._paused = false; + this._pauseTime = 0; + // cues for scheduling events with addCue() removeCue() + this._cues = []; + this._cueIDCounter = 0; + // position of the most recently played sample + this._lastPos = 0; + this._counterNode = null; + this._scopeNode = null; + // array of sources so that they can all be stopped! + this.bufferSourceNodes = []; + // current source + this.bufferSourceNode = null; + this.buffer = null; + this.playbackRate = 1; + this.input = p5sound.audiocontext.createGain(); + this.output = p5sound.audiocontext.createGain(); + this.reversed = false; + // start and end of playback / loop + this.startTime = 0; + this.endTime = null; + this.pauseTime = 0; + // "restart" would stop playback before retriggering + this.mode = "sustain"; + // time that playback was started, in millis + this.startMillis = null; + // stereo panning + this.panPosition = 0; + this.panner = new p5.Panner(this.output, p5sound.input, 2); + // it is possible to instantiate a soundfile with no path + if (this.url || this.file) { + this.load(onload, onerror); + } + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + if (typeof whileLoading === "function") { + this._whileLoading = whileLoading; + } else { + this._whileLoading = function () {}; } - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); + this._onAudioProcess = _onAudioProcess.bind(this); + this._clearOnEnd = _clearOnEnd.bind(this); + }; + // register preload handling of loadSound + p5.prototype.registerPreloadMethod("loadSound", p5.prototype); + /** + * loadSound() returns a new p5.SoundFile from a specified + * path. If called during preload(), the p5.SoundFile will be ready + * to play in time for setup() and draw(). If called outside of + * preload, the p5.SoundFile will not be ready immediately, so + * loadSound accepts a callback as the second parameter. Using a + * + * local server is recommended when loading external files. + * + * @method loadSound + * @param {String|Array} path Path to the sound file, or an array with + * paths to soundfiles in multiple formats + * i.e. ['sound.ogg', 'sound.mp3']. + * Alternately, accepts an object: either + * from the HTML5 File API, or a p5.File. + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is + * an error loading the file. + * @param {Function} [whileLoading] Name of a function to call while file is loading. + * This function will receive the percentage loaded + * so far, from 0.0 to 1.0. + * @return {SoundFile} Returns a p5.SoundFile + * @example + *
+ * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * + * function setup() { + * mySound.setVolume(0.1); + * mySound.play(); + * } + *
+ */ + p5.prototype.loadSound = function (path, callback, onerror, whileLoading) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); } - }, onerror, whileLoading); - return s; - }; - /** - * This is a helper function that the p5.SoundFile calls to load - * itself. Accepts a callback (the name of another function) - * as an optional parameter. - * - * @private - * @param {Function} [successCallback] Name of a function to call once file loads - * @param {Function} [errorCallback] Name of a function to call if there is an error - */ - p5.SoundFile.prototype.load = function (callback, errorCallback) { - var self = this; - var errorTrace = new Error().stack; - if (this.url !== undefined && this.url !== '') { - var request = new XMLHttpRequest(); - request.addEventListener('progress', function (evt) { - self._updateProgress(evt); - }, false); - request.open('GET', this.url, true); - request.responseType = 'arraybuffer'; - request.onload = function () { - if (request.status === 200) { - // on sucess loading file: - if (!self.panner) - return; - ac.decodeAudioData(request.response, // success decoding buffer: - function (buff) { - if (!self.panner) - return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); - if (callback) { - callback(self); - } - }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 - function () { - if (!self.panner) - return; - var err = new CustomError('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; + var self = this; + var s = new p5.SoundFile( + path, + function () { + if (typeof callback === "function") { + callback.apply(self, arguments); + } + if (typeof self._decrementPreload === "function") { + self._decrementPreload(); + } + }, + onerror, + whileLoading + ); + return s; + }; + /** + * This is a helper function that the p5.SoundFile calls to load + * itself. Accepts a callback (the name of another function) + * as an optional parameter. + * + * @private + * @param {Function} [successCallback] Name of a function to call once file loads + * @param {Function} [errorCallback] Name of a function to call if there is an error + */ + p5.SoundFile.prototype.load = function (callback, errorCallback) { + var self = this; + var errorTrace = new Error().stack; + if (this.url !== undefined && this.url !== "") { + var request = new XMLHttpRequest(); + request.addEventListener( + "progress", + function (evt) { + self._updateProgress(evt); + }, + false + ); + request.open("GET", this.url, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status === 200) { + // on sucess loading file: + if (!self.panner) return; + ac.decodeAudioData( + request.response, // success decoding buffer: + function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); + if (callback) { + callback(self); + } + }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 + function () { + if (!self.panner) return; + var err = new CustomError( + "decodeAudioData", + errorTrace, + self.url + ); + var msg = + "AudioContext error at decodeAudioData for " + self.url; + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + ); + } else { + if (!self.panner) return; + var err = new CustomError("loadSound", errorTrace, self.url); + var msg = + "Unable to load " + + self.url + + ". The request status was: " + + request.status + + " (" + + request.statusText + + ")"; if (errorCallback) { - err.msg = msg; + err.message = msg; errorCallback(err); } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); } - }); - } else { - if (!self.panner) - return; - var err = new CustomError('loadSound', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; + } + }; + // if there is another error, aside from 404... + request.onerror = function () { + var err = new CustomError("loadSound", errorTrace, self.url); + var msg = + "There was no response from the server at " + + self.url + + ". Check the url and internet connectivity."; if (errorCallback) { err.message = msg; errorCallback(err); } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); } - } - }; - // if there is another error, aside from 404... - request.onerror = function () { - var err = new CustomError('loadSound', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }; - request.send(); - } else if (this.file !== undefined) { - var reader = new FileReader(); - reader.onload = function () { - if (!self.panner) - return; - ac.decodeAudioData(reader.result, function (buff) { - if (!self.panner) - return; - self.buffer = buff; - self.panner.inputChannels(buff.numberOfChannels); - if (callback) { - callback(self); + }; + request.send(); + } else if (this.file !== undefined) { + var reader = new FileReader(); + reader.onload = function () { + if (!self.panner) return; + ac.decodeAudioData(reader.result, function (buff) { + if (!self.panner) return; + self.buffer = buff; + self.panner.inputChannels(buff.numberOfChannels); + if (callback) { + callback(self); + } + }); + }; + reader.onerror = function (e) { + if (!self.panner) return; + if (onerror) { + onerror(e); } - }); - }; - reader.onerror = function (e) { - if (!self.panner) - return; - if (onerror) { - onerror(e); - } - }; - reader.readAsArrayBuffer(this.file); - } - }; - // TO DO: use this method to create a loading bar that shows progress during file upload/decode. - p5.SoundFile.prototype._updateProgress = function (evt) { - if (evt.lengthComputable) { - var percentComplete = evt.loaded / evt.total * 0.99; - this._whileLoading(percentComplete, evt); - } else { - // Unable to compute progress information since the total size is unknown - this._whileLoading('size unknown'); - } - }; - /** - * Returns true if the sound file finished loading successfully. - * - * @method isLoaded - * @return {Boolean} - */ - p5.SoundFile.prototype.isLoaded = function () { - if (this.buffer) { - return true; - } else { - return false; - } - }; - /** - * Play the p5.SoundFile - * - * @method play - * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) amplitude (volume) - * of playback - * @param {Number} [cueStart] (optional) cue start time in seconds - * @param {Number} [duration] (optional) duration of playback in seconds - */ - p5.SoundFile.prototype.play = function (startTime, rate, amp, _cueStart, duration) { - if (!this.output) { - console.warn('SoundFile.play() called after dispose'); - return; - } - var self = this; - var now = p5sound.audiocontext.currentTime; - var cueStart, cueEnd; - var time = startTime || 0; - if (time < 0) { - time = 0; - } - time = time + now; - if (typeof rate !== 'undefined') { - this.rate(rate); - } - if (typeof amp !== 'undefined') { - this.setVolume(amp); - } - // TO DO: if already playing, create array of buffers for easy stop() - if (this.buffer) { - // reset the pause time (if it was paused) - this._pauseTime = 0; - // handle restart playmode - if (this.mode === 'restart' && this.buffer && this.bufferSourceNode) { - this.bufferSourceNode.stop(time); - this._counterNode.stop(time); + }; + reader.readAsArrayBuffer(this.file); } - //dont create another instance if already playing - if (this.mode === 'untildone' && this.isPlaying()) { + }; + // TO DO: use this method to create a loading bar that shows progress during file upload/decode. + p5.SoundFile.prototype._updateProgress = function (evt) { + if (evt.lengthComputable) { + var percentComplete = (evt.loaded / evt.total) * 0.99; + this._whileLoading(percentComplete, evt); + } else { + // Unable to compute progress information since the total size is unknown + this._whileLoading("size unknown"); + } + }; + /** + * Returns true if the sound file finished loading successfully. + * + * @method isLoaded + * @return {Boolean} + */ + p5.SoundFile.prototype.isLoaded = function () { + if (this.buffer) { + return true; + } else { + return false; + } + }; + /** + * Play the p5.SoundFile + * + * @method play + * @param {Number} [startTime] (optional) schedule playback to start (in seconds from now). + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) amplitude (volume) + * of playback + * @param {Number} [cueStart] (optional) cue start time in seconds + * @param {Number} [duration] (optional) duration of playback in seconds + */ + p5.SoundFile.prototype.play = function ( + startTime, + rate, + amp, + _cueStart, + duration + ) { + if (!this.output) { + console.warn("SoundFile.play() called after dispose"); return; } - // make a new source and counter. They are automatically assigned playbackRate and buffer - this.bufferSourceNode = this._initSourceNode(); - // garbage collect counterNode and create a new one - delete this._counterNode; - this._counterNode = this._initCounterNode(); - if (_cueStart) { - if (_cueStart >= 0 && _cueStart < this.buffer.duration) { - // this.startTime = cueStart; - cueStart = _cueStart; + var self = this; + var now = p5sound.audiocontext.currentTime; + var cueStart, cueEnd; + var time = startTime || 0; + if (time < 0) { + time = 0; + } + time = time + now; + if (typeof rate !== "undefined") { + this.rate(rate); + } + if (typeof amp !== "undefined") { + this.setVolume(amp); + } + // TO DO: if already playing, create array of buffers for easy stop() + if (this.buffer) { + // reset the pause time (if it was paused) + this._pauseTime = 0; + // handle restart playmode + if (this.mode === "restart" && this.buffer && this.bufferSourceNode) { + this.bufferSourceNode.stop(time); + this._counterNode.stop(time); + } + //dont create another instance if already playing + if (this.mode === "untildone" && this.isPlaying()) { + return; + } + // make a new source and counter. They are automatically assigned playbackRate and buffer + this.bufferSourceNode = this._initSourceNode(); + // garbage collect counterNode and create a new one + delete this._counterNode; + this._counterNode = this._initCounterNode(); + if (_cueStart) { + if (_cueStart >= 0 && _cueStart < this.buffer.duration) { + // this.startTime = cueStart; + cueStart = _cueStart; + } else { + throw "start time out of range"; + } + } else { + cueStart = 0; + } + if (duration) { + // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error + duration = + duration <= this.buffer.duration - cueStart + ? duration + : this.buffer.duration; + } + // if it was paused, play at the pause position + if (this._paused) { + this.bufferSourceNode.start(time, this.pauseTime, duration); + this._counterNode.start(time, this.pauseTime, duration); } else { - throw 'start time out of range'; + this.bufferSourceNode.start(time, cueStart, duration); + this._counterNode.start(time, cueStart, duration); } + this._playing = true; + this._paused = false; + // add source to sources array, which is used in stopAll() + this.bufferSourceNodes.push(this.bufferSourceNode); + this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; + this.bufferSourceNode.addEventListener("ended", this._clearOnEnd); } else { - cueStart = 0; + throw "not ready to play file, buffer has yet to load. Try preload()"; } - if (duration) { - // if duration is greater than buffer.duration, just play entire file anyway rather than throw an error - duration = duration <= this.buffer.duration - cueStart ? duration : this.buffer.duration; + // if looping, will restart at original time + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + if (this._looping === true) { + cueEnd = duration ? duration : cueStart - 1e-15; + this.bufferSourceNode.loopStart = cueStart; + this.bufferSourceNode.loopEnd = cueEnd; + this._counterNode.loopStart = cueStart; + this._counterNode.loopEnd = cueEnd; } - // if it was paused, play at the pause position - if (this._paused) { - this.bufferSourceNode.start(time, this.pauseTime, duration); - this._counterNode.start(time, this.pauseTime, duration); + }; + /** + * p5.SoundFile has two play modes: restart and + * sustain. Play Mode determines what happens to a + * p5.SoundFile if it is triggered while in the middle of playback. + * In sustain mode, playback will continue simultaneous to the + * new playback. In restart mode, play() will stop playback + * and start over. With untilDone, a sound will play only if it's + * not already playing. Sustain is the default mode. + * + * @method playMode + * @param {String} str 'restart' or 'sustain' or 'untilDone' + * @example + *
+ * var mySound; + * function preload(){ + * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * function mouseClicked() { + * mySound.playMode('sustain'); + * mySound.play(); + * } + * function keyPressed() { + * mySound.playMode('restart'); + * mySound.play(); + * } + * + *
+ */ + p5.SoundFile.prototype.playMode = function (str) { + var s = str.toLowerCase(); + // if restart, stop all other sounds from playing + if (s === "restart" && this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + var now = p5sound.audiocontext.currentTime; + this.bufferSourceNodes[i].stop(now); + } + } + // set play mode to effect future playback + if (s === "restart" || s === "sustain" || s === "untildone") { + this.mode = s; } else { - this.bufferSourceNode.start(time, cueStart, duration); - this._counterNode.start(time, cueStart, duration); + throw 'Invalid play mode. Must be either "restart" or "sustain"'; } - this._playing = true; - this._paused = false; - // add source to sources array, which is used in stopAll() - this.bufferSourceNodes.push(this.bufferSourceNode); - this.bufferSourceNode._arrayIndex = this.bufferSourceNodes.length - 1; - this.bufferSourceNode.addEventListener('ended', this._clearOnEnd); - } else { - throw 'not ready to play file, buffer has yet to load. Try preload()'; - } - // if looping, will restart at original time - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; - if (this._looping === true) { - cueEnd = duration ? duration : cueStart - 1e-15; - this.bufferSourceNode.loopStart = cueStart; - this.bufferSourceNode.loopEnd = cueEnd; - this._counterNode.loopStart = cueStart; - this._counterNode.loopEnd = cueEnd; - } - }; - /** - * p5.SoundFile has two play modes: restart and - * sustain. Play Mode determines what happens to a - * p5.SoundFile if it is triggered while in the middle of playback. - * In sustain mode, playback will continue simultaneous to the - * new playback. In restart mode, play() will stop playback - * and start over. With untilDone, a sound will play only if it's - * not already playing. Sustain is the default mode. - * - * @method playMode - * @param {String} str 'restart' or 'sustain' or 'untilDone' - * @example - *
- * var mySound; - * function preload(){ - * mySound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * function mouseClicked() { - * mySound.playMode('sustain'); - * mySound.play(); - * } - * function keyPressed() { - * mySound.playMode('restart'); - * mySound.play(); - * } - * - *
- */ - p5.SoundFile.prototype.playMode = function (str) { - var s = str.toLowerCase(); - // if restart, stop all other sounds from playing - if (s === 'restart' && this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - var now = p5sound.audiocontext.currentTime; - this.bufferSourceNodes[i].stop(now); + }; + /** + * Pauses a file that is currently playing. If the file is not + * playing, then nothing will happen. + * + * After pausing, .play() will resume from the paused + * position. + * If p5.SoundFile had been set to loop before it was paused, + * it will continue to loop after it is unpaused with .play(). + * + * @method pause + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @example + *
+ * var soundFile; + * + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); + * } + * function setup() { + * background(0, 255, 0); + * soundFile.setVolume(0.1); + * soundFile.loop(); + * } + * function keyTyped() { + * if (key == 'p') { + * soundFile.pause(); + * background(255, 0, 0); + * } + * } + * + * function keyReleased() { + * if (key == 'p') { + * soundFile.play(); + * background(0, 255, 0); + * } + * } + * + *
+ */ + p5.SoundFile.prototype.pause = function (startTime) { + var now = p5sound.audiocontext.currentTime; + var time = startTime || 0; + var pTime = time + now; + if (this.isPlaying() && this.buffer && this.bufferSourceNode) { + this.pauseTime = this.currentTime(); + this.bufferSourceNode.stop(pTime); + this._counterNode.stop(pTime); + this._paused = true; + this._playing = false; + this._pauseTime = this.currentTime(); + } else { + this._pauseTime = 0; } - } - // set play mode to effect future playback - if (s === 'restart' || s === 'sustain' || s === 'untildone') { - this.mode = s; - } else { - throw 'Invalid play mode. Must be either "restart" or "sustain"'; - } - }; - /** - * Pauses a file that is currently playing. If the file is not - * playing, then nothing will happen. - * - * After pausing, .play() will resume from the paused - * position. - * If p5.SoundFile had been set to loop before it was paused, - * it will continue to loop after it is unpaused with .play(). - * - * @method pause - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @example - *
- * var soundFile; - * - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/Damscray_-_Dancing_Tiger_02.mp3'); - * } - * function setup() { - * background(0, 255, 0); - * soundFile.setVolume(0.1); - * soundFile.loop(); - * } - * function keyTyped() { - * if (key == 'p') { - * soundFile.pause(); - * background(255, 0, 0); - * } - * } - * - * function keyReleased() { - * if (key == 'p') { - * soundFile.play(); - * background(0, 255, 0); - * } - * } - * - *
- */ - p5.SoundFile.prototype.pause = function (startTime) { - var now = p5sound.audiocontext.currentTime; - var time = startTime || 0; - var pTime = time + now; - if (this.isPlaying() && this.buffer && this.bufferSourceNode) { - this.pauseTime = this.currentTime(); - this.bufferSourceNode.stop(pTime); - this._counterNode.stop(pTime); - this._paused = true; - this._playing = false; - this._pauseTime = this.currentTime(); - } else { - this._pauseTime = 0; - } - }; - /** - * Loop the p5.SoundFile. Accepts optional parameters to set the - * playback rate, playback volume, loopStart, loopEnd. - * - * @method loop - * @param {Number} [startTime] (optional) schedule event to occur - * seconds from now - * @param {Number} [rate] (optional) playback rate - * @param {Number} [amp] (optional) playback volume - * @param {Number} [cueLoopStart] (optional) startTime in seconds - * @param {Number} [duration] (optional) loop duration in seconds - */ - p5.SoundFile.prototype.loop = function (startTime, rate, amp, loopStart, duration) { - this._looping = true; - this.play(startTime, rate, amp, loopStart, duration); - }; - /** - * Set a p5.SoundFile's looping flag to true or false. If the sound - * is currently playing, this change will take effect when it - * reaches the end of the current playback. - * - * @method setLoop - * @param {Boolean} Boolean set looping to true or false - */ - p5.SoundFile.prototype.setLoop = function (bool) { - if (bool === true) { + }; + /** + * Loop the p5.SoundFile. Accepts optional parameters to set the + * playback rate, playback volume, loopStart, loopEnd. + * + * @method loop + * @param {Number} [startTime] (optional) schedule event to occur + * seconds from now + * @param {Number} [rate] (optional) playback rate + * @param {Number} [amp] (optional) playback volume + * @param {Number} [cueLoopStart] (optional) startTime in seconds + * @param {Number} [duration] (optional) loop duration in seconds + */ + p5.SoundFile.prototype.loop = function ( + startTime, + rate, + amp, + loopStart, + duration + ) { this._looping = true; - } else if (bool === false) { - this._looping = false; - } else { - throw 'Error: setLoop accepts either true or false'; - } - if (this.bufferSourceNode) { - this.bufferSourceNode.loop = this._looping; - this._counterNode.loop = this._looping; - } - }; - /** - * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. - * - * @method isLooping - * @return {Boolean} - */ - p5.SoundFile.prototype.isLooping = function () { - if (!this.bufferSourceNode) { + this.play(startTime, rate, amp, loopStart, duration); + }; + /** + * Set a p5.SoundFile's looping flag to true or false. If the sound + * is currently playing, this change will take effect when it + * reaches the end of the current playback. + * + * @method setLoop + * @param {Boolean} Boolean set looping to true or false + */ + p5.SoundFile.prototype.setLoop = function (bool) { + if (bool === true) { + this._looping = true; + } else if (bool === false) { + this._looping = false; + } else { + throw "Error: setLoop accepts either true or false"; + } + if (this.bufferSourceNode) { + this.bufferSourceNode.loop = this._looping; + this._counterNode.loop = this._looping; + } + }; + /** + * Returns 'true' if a p5.SoundFile is currently looping and playing, 'false' if not. + * + * @method isLooping + * @return {Boolean} + */ + p5.SoundFile.prototype.isLooping = function () { + if (!this.bufferSourceNode) { + return false; + } + if (this._looping === true && this.isPlaying() === true) { + return true; + } return false; - } - if (this._looping === true && this.isPlaying() === true) { - return true; - } - return false; - }; - /** - * Returns true if a p5.SoundFile is playing, false if not (i.e. - * paused or stopped). - * - * @method isPlaying - * @return {Boolean} - */ - p5.SoundFile.prototype.isPlaying = function () { - return this._playing; - }; - /** - * Returns true if a p5.SoundFile is paused, false if not (i.e. - * playing or stopped). - * - * @method isPaused - * @return {Boolean} - */ - p5.SoundFile.prototype.isPaused = function () { - return this._paused; - }; - /** - * Stop soundfile playback. - * - * @method stop - * @param {Number} [startTime] (optional) schedule event to occur - * in seconds from now - */ - p5.SoundFile.prototype.stop = function (timeFromNow) { - var time = timeFromNow || 0; - if (this.mode === 'sustain' || this.mode === 'untildone') { - this.stopAll(time); - this._playing = false; - this.pauseTime = 0; - this._paused = false; - } else if (this.buffer && this.bufferSourceNode) { + }; + /** + * Returns true if a p5.SoundFile is playing, false if not (i.e. + * paused or stopped). + * + * @method isPlaying + * @return {Boolean} + */ + p5.SoundFile.prototype.isPlaying = function () { + return this._playing; + }; + /** + * Returns true if a p5.SoundFile is paused, false if not (i.e. + * playing or stopped). + * + * @method isPaused + * @return {Boolean} + */ + p5.SoundFile.prototype.isPaused = function () { + return this._paused; + }; + /** + * Stop soundfile playback. + * + * @method stop + * @param {Number} [startTime] (optional) schedule event to occur + * in seconds from now + */ + p5.SoundFile.prototype.stop = function (timeFromNow) { + var time = timeFromNow || 0; + if (this.mode === "sustain" || this.mode === "untildone") { + this.stopAll(time); + this._playing = false; + this.pauseTime = 0; + this._paused = false; + } else if (this.buffer && this.bufferSourceNode) { + var now = p5sound.audiocontext.currentTime; + var t = time || 0; + this.pauseTime = 0; + this.bufferSourceNode.stop(now + t); + this._counterNode.stop(now + t); + this._playing = false; + this._paused = false; + } + }; + /** + * Stop playback on all of this soundfile's sources. + * @private + */ + p5.SoundFile.prototype.stopAll = function (_time) { var now = p5sound.audiocontext.currentTime; - var t = time || 0; - this.pauseTime = 0; - this.bufferSourceNode.stop(now + t); - this._counterNode.stop(now + t); - this._playing = false; - this._paused = false; - } - }; - /** - * Stop playback on all of this soundfile's sources. - * @private - */ - p5.SoundFile.prototype.stopAll = function (_time) { - var now = p5sound.audiocontext.currentTime; - var time = _time || 0; - if (this.buffer && this.bufferSourceNode) { - for (var i in this.bufferSourceNodes) { - const bufferSourceNode = this.bufferSourceNodes[i]; - if (!!bufferSourceNode) { - try { - bufferSourceNode.stop(now + time); - } catch (e) { + var time = _time || 0; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + const bufferSourceNode = this.bufferSourceNodes[i]; + if (!!bufferSourceNode) { + try { + bufferSourceNode.stop(now + time); + } catch (e) {} } } + this._counterNode.stop(now + time); + this._onended(this); + } + }; + /** + * Multiply the output volume (amplitude) of a sound file + * between 0.0 (silence) and 1.0 (full volume). + * 1.0 is the maximum amplitude of a digital sound, so multiplying + * by greater than 1.0 may cause digital distortion. To + * fade, provide a rampTime parameter. For more + * complex fades, see the Envelope class. + * + * Alternately, you can pass in a signal source such as an + * oscillator to modulate the amplitude with an audio signal. + * + * @method setVolume + * @param {Number|Object} volume Volume (amplitude) between 0.0 + * and 1.0 or modulating signal/oscillator + * @param {Number} [rampTime] Fade for t seconds + * @param {Number} [timeFromNow] Schedule this event to happen at + * t seconds in the future + */ + p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) { + if (typeof vol === "number") { + var rampTime = _rampTime || 0; + var tFromNow = _tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now + tFromNow); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(this.output.gain); + } else { + // return the Gain Node + return this.output.gain; + } + }; + // same as setVolume, to match Processing Sound + p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume; + // these are the same thing + p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume; + p5.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }; + /** + * Set the stereo panning of a p5.sound object to + * a floating point number between -1.0 (left) and 1.0 (right). + * Default is 0.0 (center). + * + * @method pan + * @param {Number} [panValue] Set the stereo panner + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @example + *
+ * + * var ball = {}; + * var soundFile; + * + * function preload() { + * soundFormats('ogg', 'mp3'); + * soundFile = loadSound('assets/beatbox.mp3'); + * } + * + * function draw() { + * background(0); + * ball.x = constrain(mouseX, 0, width); + * ellipse(ball.x, height/2, 20, 20) + * } + * + * function mousePressed(){ + * // map the ball's x location to a panning degree + * // between -1.0 (left) and 1.0 (right) + * var panning = map(ball.x, 0., width,-1.0, 1.0); + * soundFile.pan(panning); + * soundFile.play(); + * } + *
+ */ + p5.SoundFile.prototype.pan = function (pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + }; + /** + * Returns the current stereo pan position (-1.0 to 1.0) + * + * @method getPan + * @return {Number} Returns the stereo pan setting of the Oscillator + * as a number between -1.0 (left) and 1.0 (right). + * 0.0 is center and default. + */ + p5.SoundFile.prototype.getPan = function () { + return this.panPosition; + }; + /** + * Set the playback rate of a sound file. Will change the speed and the pitch. + * Values less than zero will reverse the audio buffer. + * + * @method rate + * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, + * .5 is half-speed, 2.0 is twice as fast. + * Values less than zero play backwards. + * @example + *
+ * var song; + * + * function preload() { + * song = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * song.loop(); + * } + * + * function draw() { + * background(200); + * + * // Set the rate to a range between 0.1 and 4 + * // Changing the rate also alters the pitch + * var speed = map(mouseY, 0.1, height, 0, 2); + * speed = constrain(speed, 0.01, 4); + * song.rate(speed); + * + * // Draw a circle to show what is going on + * stroke(0); + * fill(51, 100); + * ellipse(mouseX, 100, 48, 48); + * } + * + * + *
+ * + */ + p5.SoundFile.prototype.rate = function (playbackRate) { + var reverse = false; + if (typeof playbackRate === "undefined") { + return this.playbackRate; + } + this.playbackRate = playbackRate; + if (playbackRate === 0) { + playbackRate = 1e-13; + } else if (playbackRate < 0 && !this.reversed) { + playbackRate = Math.abs(playbackRate); + reverse = true; + } else if (playbackRate > 0 && this.reversed) { + reverse = true; + } + if (this.bufferSourceNode) { + var now = p5sound.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(now); + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(playbackRate), + now + ); + this._counterNode.playbackRate.cancelScheduledValues(now); + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(playbackRate), + now + ); + } + if (reverse) { + this.reverseBuffer(); } - this._counterNode.stop(now + time); - this._onended(this); - } - }; - /** - * Multiply the output volume (amplitude) of a sound file - * between 0.0 (silence) and 1.0 (full volume). - * 1.0 is the maximum amplitude of a digital sound, so multiplying - * by greater than 1.0 may cause digital distortion. To - * fade, provide a rampTime parameter. For more - * complex fades, see the Envelope class. - * - * Alternately, you can pass in a signal source such as an - * oscillator to modulate the amplitude with an audio signal. - * - * @method setVolume - * @param {Number|Object} volume Volume (amplitude) between 0.0 - * and 1.0 or modulating signal/oscillator - * @param {Number} [rampTime] Fade for t seconds - * @param {Number} [timeFromNow] Schedule this event to happen at - * t seconds in the future - */ - p5.SoundFile.prototype.setVolume = function (vol, _rampTime, _tFromNow) { - if (typeof vol === 'number') { - var rampTime = _rampTime || 0; - var tFromNow = _tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now + tFromNow); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(this.output.gain); - } else { - // return the Gain Node - return this.output.gain; - } - }; - // same as setVolume, to match Processing Sound - p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume; - // these are the same thing - p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume; - p5.SoundFile.prototype.getVolume = function () { - return this.output.gain.value; - }; - /** - * Set the stereo panning of a p5.sound object to - * a floating point number between -1.0 (left) and 1.0 (right). - * Default is 0.0 (center). - * - * @method pan - * @param {Number} [panValue] Set the stereo panner - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @example - *
- * - * var ball = {}; - * var soundFile; - * - * function preload() { - * soundFormats('ogg', 'mp3'); - * soundFile = loadSound('assets/beatbox.mp3'); - * } - * - * function draw() { - * background(0); - * ball.x = constrain(mouseX, 0, width); - * ellipse(ball.x, height/2, 20, 20) - * } - * - * function mousePressed(){ - * // map the ball's x location to a panning degree - * // between -1.0 (left) and 1.0 (right) - * var panning = map(ball.x, 0., width,-1.0, 1.0); - * soundFile.pan(panning); - * soundFile.play(); - * } - *
- */ - p5.SoundFile.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); - }; - /** - * Returns the current stereo pan position (-1.0 to 1.0) - * - * @method getPan - * @return {Number} Returns the stereo pan setting of the Oscillator - * as a number between -1.0 (left) and 1.0 (right). - * 0.0 is center and default. - */ - p5.SoundFile.prototype.getPan = function () { - return this.panPosition; - }; - /** - * Set the playback rate of a sound file. Will change the speed and the pitch. - * Values less than zero will reverse the audio buffer. - * - * @method rate - * @param {Number} [playbackRate] Set the playback rate. 1.0 is normal, - * .5 is half-speed, 2.0 is twice as fast. - * Values less than zero play backwards. - * @example - *
- * var song; - * - * function preload() { - * song = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * song.loop(); - * } - * - * function draw() { - * background(200); - * - * // Set the rate to a range between 0.1 and 4 - * // Changing the rate also alters the pitch - * var speed = map(mouseY, 0.1, height, 0, 2); - * speed = constrain(speed, 0.01, 4); - * song.rate(speed); - * - * // Draw a circle to show what is going on - * stroke(0); - * fill(51, 100); - * ellipse(mouseX, 100, 48, 48); - * } - * - * - *
- * - */ - p5.SoundFile.prototype.rate = function (playbackRate) { - var reverse = false; - if (typeof playbackRate === 'undefined') { return this.playbackRate; - } - this.playbackRate = playbackRate; - if (playbackRate === 0) { - playbackRate = 1e-13; - } else if (playbackRate < 0 && !this.reversed) { - playbackRate = Math.abs(playbackRate); - reverse = true; - } else if (playbackRate > 0 && this.reversed) { - reverse = true; - } - if (this.bufferSourceNode) { - var now = p5sound.audiocontext.currentTime; - this.bufferSourceNode.playbackRate.cancelScheduledValues(now); - this.bufferSourceNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - this._counterNode.playbackRate.cancelScheduledValues(now); - this._counterNode.playbackRate.linearRampToValueAtTime(Math.abs(playbackRate), now); - } - if (reverse) { - this.reverseBuffer(); - } - return this.playbackRate; - }; - // TO DO: document this - p5.SoundFile.prototype.setPitch = function (num) { - var newPlaybackRate = midiToFreq(num) / midiToFreq(60); - this.rate(newPlaybackRate); - }; - p5.SoundFile.prototype.getPlaybackRate = function () { - return this.playbackRate; - }; - /** - * Returns the duration of a sound file in seconds. - * - * @method duration - * @return {Number} The duration of the soundFile in seconds. - */ - p5.SoundFile.prototype.duration = function () { - // Return Duration - if (this.buffer) { - return this.buffer.duration; - } else { - return 0; - } - }; - /** - * Return the current position of the p5.SoundFile playhead, in seconds. - * Time is relative to the normal buffer direction, so if `reverseBuffer` - * has been called, currentTime will count backwards. - * - * @method currentTime - * @return {Number} currentTime of the soundFile in seconds. - */ - p5.SoundFile.prototype.currentTime = function () { - return this.reversed ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate : this._lastPos / ac.sampleRate; - }; - /** - * Move the playhead of the song to a position, in seconds. Start timing - * and playback duration. If none are given, will reset the file to play - * entire duration from start to finish. - * - * @method jump - * @param {Number} cueTime cueTime of the soundFile in seconds. - * @param {Number} duration duration in seconds. - */ - p5.SoundFile.prototype.jump = function (cueTime, duration) { - if (cueTime < 0 || cueTime > this.buffer.duration) { - throw 'jump time out of range'; - } - if (duration > this.buffer.duration - cueTime) { - throw 'end time out of range'; - } - var cTime = cueTime || 0; - var dur = duration || undefined; - if (this.isPlaying()) { - this.stop(0); - } - this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); - }; - /** - * Return the number of channels in a sound file. - * For example, Mono = 1, Stereo = 2. - * - * @method channels - * @return {Number} [channels] - */ - p5.SoundFile.prototype.channels = function () { - return this.buffer.numberOfChannels; - }; - /** - * Return the sample rate of the sound file. - * - * @method sampleRate - * @return {Number} [sampleRate] - */ - p5.SoundFile.prototype.sampleRate = function () { - return this.buffer.sampleRate; - }; - /** - * Return the number of samples in a sound file. - * Equal to sampleRate * duration. - * - * @method frames - * @return {Number} [sampleCount] - */ - p5.SoundFile.prototype.frames = function () { - return this.buffer.length; - }; - /** - * Returns an array of amplitude peaks in a p5.SoundFile that can be - * used to draw a static waveform. Scans through the p5.SoundFile's - * audio buffer to find the greatest amplitudes. Accepts one - * parameter, 'length', which determines size of the array. - * Larger arrays result in more precise waveform visualizations. - * - * Inspired by Wavesurfer.js. - * - * @method getPeaks - * @params {Number} [length] length is the size of the returned array. - * Larger length results in more precision. - * Defaults to 5*width of the browser window. - * @returns {Float32Array} Array of peaks. - */ - p5.SoundFile.prototype.getPeaks = function (length) { - if (this.buffer) { - // set length to window's width if no length is provided - if (!length) { - length = window.width * 5; + }; + // TO DO: document this + p5.SoundFile.prototype.setPitch = function (num) { + var newPlaybackRate = midiToFreq(num) / midiToFreq(60); + this.rate(newPlaybackRate); + }; + p5.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }; + /** + * Returns the duration of a sound file in seconds. + * + * @method duration + * @return {Number} The duration of the soundFile in seconds. + */ + p5.SoundFile.prototype.duration = function () { + // Return Duration + if (this.buffer) { + return this.buffer.duration; + } else { + return 0; + } + }; + /** + * Return the current position of the p5.SoundFile playhead, in seconds. + * Time is relative to the normal buffer direction, so if `reverseBuffer` + * has been called, currentTime will count backwards. + * + * @method currentTime + * @return {Number} currentTime of the soundFile in seconds. + */ + p5.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / ac.sampleRate + : this._lastPos / ac.sampleRate; + }; + /** + * Move the playhead of the song to a position, in seconds. Start timing + * and playback duration. If none are given, will reset the file to play + * entire duration from start to finish. + * + * @method jump + * @param {Number} cueTime cueTime of the soundFile in seconds. + * @param {Number} duration duration in seconds. + */ + p5.SoundFile.prototype.jump = function (cueTime, duration) { + if (cueTime < 0 || cueTime > this.buffer.duration) { + throw "jump time out of range"; + } + if (duration > this.buffer.duration - cueTime) { + throw "end time out of range"; } + var cTime = cueTime || 0; + var dur = duration || undefined; + if (this.isPlaying()) { + this.stop(0); + } + this.play(0, this.playbackRate, this.output.gain.value, cTime, dur); + }; + /** + * Return the number of channels in a sound file. + * For example, Mono = 1, Stereo = 2. + * + * @method channels + * @return {Number} [channels] + */ + p5.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }; + /** + * Return the sample rate of the sound file. + * + * @method sampleRate + * @return {Number} [sampleRate] + */ + p5.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }; + /** + * Return the number of samples in a sound file. + * Equal to sampleRate * duration. + * + * @method frames + * @return {Number} [sampleCount] + */ + p5.SoundFile.prototype.frames = function () { + return this.buffer.length; + }; + /** + * Returns an array of amplitude peaks in a p5.SoundFile that can be + * used to draw a static waveform. Scans through the p5.SoundFile's + * audio buffer to find the greatest amplitudes. Accepts one + * parameter, 'length', which determines size of the array. + * Larger arrays result in more precise waveform visualizations. + * + * Inspired by Wavesurfer.js. + * + * @method getPeaks + * @params {Number} [length] length is the size of the returned array. + * Larger length results in more precision. + * Defaults to 5*width of the browser window. + * @returns {Float32Array} Array of peaks. + */ + p5.SoundFile.prototype.getPeaks = function (length) { if (this.buffer) { - var buffer = this.buffer; - var sampleSize = buffer.length / length; - var sampleStep = ~~(sampleSize / 10) || 1; - var channels = buffer.numberOfChannels; - var peaks = new Float32Array(Math.round(length)); - for (var c = 0; c < channels; c++) { - var chan = buffer.getChannelData(c); - for (var i = 0; i < length; i++) { - var start = ~~(i * sampleSize); - var end = ~~(start + sampleSize); - var max = 0; - for (var j = start; j < end; j += sampleStep) { - var value = chan[j]; - if (value > max) { - max = value; - } else if (-value > max) { - max = value; + // set length to window's width if no length is provided + if (!length) { + length = window.width * 5; + } + if (this.buffer) { + var buffer = this.buffer; + var sampleSize = buffer.length / length; + var sampleStep = ~~(sampleSize / 10) || 1; + var channels = buffer.numberOfChannels; + var peaks = new Float32Array(Math.round(length)); + for (var c = 0; c < channels; c++) { + var chan = buffer.getChannelData(c); + for (var i = 0; i < length; i++) { + var start = ~~(i * sampleSize); + var end = ~~(start + sampleSize); + var max = 0; + for (var j = start; j < end; j += sampleStep) { + var value = chan[j]; + if (value > max) { + max = value; + } else if (-value > max) { + max = value; + } + } + if (c === 0 || Math.abs(max) > peaks[i]) { + peaks[i] = max; } - } - if (c === 0 || Math.abs(max) > peaks[i]) { - peaks[i] = max; } } + return peaks; } - return peaks; + } else { + throw "Cannot load peaks yet, buffer is not loaded"; } - } else { - throw 'Cannot load peaks yet, buffer is not loaded'; - } - }; - /** - * Reverses the p5.SoundFile's buffer source. - * Playback must be handled separately (see example). - * - * @method reverseBuffer - * @example - *
- * var drum; - * - * function preload() { - * drum = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * drum.reverseBuffer(); - * drum.play(); - * } - * - * - *
- */ - p5.SoundFile.prototype.reverseBuffer = function () { - if (this.buffer) { - var currentPos = this._lastPos / ac.sampleRate; - var curVol = this.getVolume(); - this.setVolume(0, 0.001); - const numChannels = this.buffer.numberOfChannels; - for (var i = 0; i < numChannels; i++) { - this.buffer.getChannelData(i).reverse(); - } - // set reversed flag - this.reversed = !this.reversed; - if (currentPos) { - this.jump(this.duration() - currentPos); - } - this.setVolume(curVol, 0.001); - } else { - throw 'SoundFile is not done loading'; - } - }; - /** - * Schedule an event to be called when the soundfile - * reaches the end of a buffer. If the soundfile is - * playing through once, this will be called when it - * ends. If it is looping, it will be called when - * stop is called. - * - * @method onended - * @param {Function} callback function to call when the - * soundfile has ended. - */ - p5.SoundFile.prototype.onended = function (callback) { - this._onended = callback; - return this; - }; - p5.SoundFile.prototype.add = function () { - }; - p5.SoundFile.prototype.dispose = function () { - var now = p5sound.audiocontext.currentTime; - // remove reference to soundfile - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.stop(now); - if (this.buffer && this.bufferSourceNode) { - for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { - if (this.bufferSourceNodes[i] !== null) { - this.bufferSourceNodes[i].disconnect(); + }; + /** + * Reverses the p5.SoundFile's buffer source. + * Playback must be handled separately (see example). + * + * @method reverseBuffer + * @example + *
+ * var drum; + * + * function preload() { + * drum = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * drum.reverseBuffer(); + * drum.play(); + * } + * + * + *
+ */ + p5.SoundFile.prototype.reverseBuffer = function () { + if (this.buffer) { + var currentPos = this._lastPos / ac.sampleRate; + var curVol = this.getVolume(); + this.setVolume(0, 0.001); + const numChannels = this.buffer.numberOfChannels; + for (var i = 0; i < numChannels; i++) { + this.buffer.getChannelData(i).reverse(); + } + // set reversed flag + this.reversed = !this.reversed; + if (currentPos) { + this.jump(this.duration() - currentPos); + } + this.setVolume(curVol, 0.001); + } else { + throw "SoundFile is not done loading"; + } + }; + /** + * Schedule an event to be called when the soundfile + * reaches the end of a buffer. If the soundfile is + * playing through once, this will be called when it + * ends. If it is looping, it will be called when + * stop is called. + * + * @method onended + * @param {Function} callback function to call when the + * soundfile has ended. + */ + p5.SoundFile.prototype.onended = function (callback) { + this._onended = callback; + return this; + }; + p5.SoundFile.prototype.add = function () {}; + p5.SoundFile.prototype.dispose = function () { + var now = p5sound.audiocontext.currentTime; + // remove reference to soundfile + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.stop(now); + if (this.buffer && this.bufferSourceNode) { + for (var i = 0; i < this.bufferSourceNodes.length - 1; i++) { + if (this.bufferSourceNodes[i] !== null) { + this.bufferSourceNodes[i].disconnect(); + try { + this.bufferSourceNodes[i].stop(now); + } catch (e) { + console.warning("no buffer source node to dispose"); + } + this.bufferSourceNodes[i] = null; + } + } + if (this.isPlaying()) { try { - this.bufferSourceNodes[i].stop(now); + this._counterNode.stop(now); } catch (e) { - console.warning('no buffer source node to dispose'); + console.log(e); } - this.bufferSourceNodes[i] = null; + this._counterNode = null; } } - if (this.isPlaying()) { - try { - this._counterNode.stop(now); - } catch (e) { - console.log(e); - } - this._counterNode = null; + if (this.output) { + this.output.disconnect(); + this.output = null; } - } - if (this.output) { - this.output.disconnect(); - this.output = null; - } - if (this.panner) { - this.panner.disconnect(); - this.panner = null; - } - }; - /** - * Connects the output of a p5sound object to input of another - * p5.sound object. For example, you may connect a p5.SoundFile to an - * FFT or an Effect. If no parameter is given, it will connect to - * the master output. Most p5sound objects connect to the master - * output when they are created. - * - * @method connect - * @param {Object} [object] Audio object that accepts an input - */ - p5.SoundFile.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(p5sound.input); - } else { - if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); + if (this.panner) { + this.panner.disconnect(); + this.panner = null; + } + }; + /** + * Connects the output of a p5sound object to input of another + * p5.sound object. For example, you may connect a p5.SoundFile to an + * FFT or an Effect. If no parameter is given, it will connect to + * the master output. Most p5sound objects connect to the master + * output when they are created. + * + * @method connect + * @param {Object} [object] Audio object that accepts an input + */ + p5.SoundFile.prototype.connect = function (unit) { + if (!unit) { + this.panner.connect(p5sound.input); } else { - this.panner.connect(unit); + if (unit.hasOwnProperty("input")) { + this.panner.connect(unit.input); + } else { + this.panner.connect(unit); + } } - } - }; - /** - * Disconnects the output of this p5sound object. - * - * @method disconnect - */ - p5.SoundFile.prototype.disconnect = function () { - if (this.panner) { - this.panner.disconnect(); - } - }; - /** - */ - p5.SoundFile.prototype.getLevel = function () { - console.warn('p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead'); - }; - /** - * Reset the source for this SoundFile to a - * new path (URL). - * - * @method setPath - * @param {String} path path to audio file - * @param {Function} callback Callback - */ - p5.SoundFile.prototype.setPath = function (p, callback) { - var path = p5.prototype._checkFileFormats(p); - this.url = path; - this.load(callback); - }; - /** - * Replace the current Audio Buffer with a new Buffer. - * - * @method setBuffer - * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays - * will create a stereo source. 1 will create - * a mono source. - */ - p5.SoundFile.prototype.setBuffer = function (buf) { - var numChannels = buf.length; - var size = buf[0].length; - var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate); - if (!(buf[0] instanceof Float32Array)) { - buf[0] = new Float32Array(buf[0]); - } - for (var channelNum = 0; channelNum < numChannels; channelNum++) { - var channel = newBuffer.getChannelData(channelNum); - channel.set(buf[channelNum]); - } - this.buffer = newBuffer; - // set numbers of channels on input to the panner - this.panner.inputChannels(numChannels); - }; - ////////////////////////////////////////////////// - // script processor node with an empty buffer to help - // keep a sample-accurate position in playback buffer. - // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV - // Copyright [2015] [Sonoport (Asia) Pte. Ltd.], - // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0 - //////////////////////////////////////////////////////////////////////////////////// - var _createCounterBuffer = function (buffer) { - const len = buffer.length; - const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate); - const arrayBuffer = audioBuf.getChannelData(0); - for (var index = 0; index < len; index++) { - arrayBuffer[index] = index; - } - return audioBuf; - }; - // initialize counterNode, set its initial buffer and playbackRate - p5.SoundFile.prototype._initCounterNode = function () { - var self = this; - var now = ac.currentTime; - var cNode = ac.createBufferSource(); - // dispose of scope node if it already exists - if (self._scopeNode) { - self._scopeNode.disconnect(); - self._scopeNode.removeEventListener('audioprocess', self._onAudioProcess); - delete self._scopeNode; - } - self._scopeNode = ac.createScriptProcessor(256, 1, 1); - // create counter buffer of the same length as self.buffer - cNode.buffer = _createCounterBuffer(self.buffer); - cNode.playbackRate.setValueAtTime(self.playbackRate, now); - cNode.connect(self._scopeNode); - self._scopeNode.connect(p5.soundOut._silentNode); - self._scopeNode.addEventListener('audioprocess', self._onAudioProcess); - return cNode; - }; - // initialize sourceNode, set its initial buffer and playbackRate - p5.SoundFile.prototype._initSourceNode = function () { - var bufferSourceNode = ac.createBufferSource(); - bufferSourceNode.buffer = this.buffer; - bufferSourceNode.playbackRate.value = this.playbackRate; - bufferSourceNode.connect(this.output); - return bufferSourceNode; - }; - /** - * processPeaks returns an array of timestamps where it thinks there is a beat. - * - * This is an asynchronous function that processes the soundfile in an offline audio context, - * and sends the results to your callback function. - * - * The process involves running the soundfile through a lowpass filter, and finding all of the - * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, - * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. - * - * @method processPeaks - * @param {Function} callback a function to call once this data is returned - * @param {Number} [initThreshold] initial threshold defaults to 0.9 - * @param {Number} [minThreshold] minimum threshold defaults to 0.22 - * @param {Number} [minPeaks] minimum number of peaks defaults to 200 - * @return {Array} Array of timestamped peaks - */ - p5.SoundFile.prototype.processPeaks = function (callback, _initThreshold, _minThreshold, _minPeaks) { - var bufLen = this.buffer.length; - var sampleRate = this.buffer.sampleRate; - var buffer = this.buffer; - var allPeaks = []; - var initialThreshold = _initThreshold || 0.9, threshold = initialThreshold, minThreshold = _minThreshold || 0.22, minPeaks = _minPeaks || 200; - // Create offline context - var offlineContext = new window.OfflineAudioContext(1, bufLen, sampleRate); - // create buffer source - var source = offlineContext.createBufferSource(); - source.buffer = buffer; - // Create filter. TO DO: allow custom setting of filter - var filter = offlineContext.createBiquadFilter(); - filter.type = 'lowpass'; - source.connect(filter); - filter.connect(offlineContext.destination); - // start playing at time:0 - source.start(0); - offlineContext.startRendering(); - // Render the song - // act on the result - offlineContext.oncomplete = function (e) { - if (!self.panner) - return; - var filteredBuffer = e.renderedBuffer; - var bufferData = filteredBuffer.getChannelData(0); - // step 1: - // create Peak instances, add them to array, with strength and sampleIndex - do { - allPeaks = getPeaksAtThreshold(bufferData, threshold); - threshold -= 0.005; - } while (Object.keys(allPeaks).length < minPeaks && threshold >= minThreshold); - // step 2: - // find intervals for each peak in the sampleIndex, add tempos array - var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); - // step 3: find top tempos - var groups = groupNeighborsByTempo(intervalCounts, filteredBuffer.sampleRate); - // sort top intervals - var topTempos = groups.sort(function (intA, intB) { - return intB.count - intA.count; - }).splice(0, 5); - // set this SoundFile's tempo to the top tempo ?? - this.tempo = topTempos[0].tempo; - // step 4: - // new array of peaks at top tempo within a bpmVariance - var bpmVariance = 5; - var tempoPeaks = getPeaksAtTopTempo(allPeaks, topTempos[0].tempo, filteredBuffer.sampleRate, bpmVariance); - callback(tempoPeaks); - }; - }; - // process peaks - var Peak = function (amp, i) { - this.sampleIndex = i; - this.amplitude = amp; - this.tempos = []; - this.intervals = []; - }; - // 1. for processPeaks() Function to identify peaks above a threshold - // returns an array of peak indexes as frames (samples) of the original soundfile - function getPeaksAtThreshold(data, threshold) { - var peaksObj = {}; - var length = data.length; - for (var i = 0; i < length; i++) { - if (data[i] > threshold) { - var amp = data[i]; - var peak = new Peak(amp, i); - peaksObj[i] = peak; - // Skip forward ~ 1/8s to get past this peak. - i += 6000; - } - i++; - } - return peaksObj; - } - // 2. for processPeaks() - function countIntervalsBetweenNearbyPeaks(peaksObj) { - var intervalCounts = []; - var peaksArray = Object.keys(peaksObj).sort(); - for (var index = 0; index < peaksArray.length; index++) { - // find intervals in comparison to nearby peaks - for (var i = 0; i < 10; i++) { - var startPeak = peaksObj[peaksArray[index]]; - var endPeak = peaksObj[peaksArray[index + i]]; - if (startPeak && endPeak) { - var startPos = startPeak.sampleIndex; - var endPos = endPeak.sampleIndex; - var interval = endPos - startPos; - // add a sample interval to the startPeak in the allPeaks array - if (interval > 0) { - startPeak.intervals.push(interval); - } - // tally the intervals and return interval counts - var foundInterval = intervalCounts.some(function (intervalCount) { - if (intervalCount.interval === interval) { - intervalCount.count++; - return intervalCount; + }; + /** + * Disconnects the output of this p5sound object. + * + * @method disconnect + */ + p5.SoundFile.prototype.disconnect = function () { + if (this.panner) { + this.panner.disconnect(); + } + }; + /** + */ + p5.SoundFile.prototype.getLevel = function () { + console.warn( + "p5.SoundFile.getLevel has been removed from the library. Use p5.Amplitude instead" + ); + }; + /** + * Reset the source for this SoundFile to a + * new path (URL). + * + * @method setPath + * @param {String} path path to audio file + * @param {Function} callback Callback + */ + p5.SoundFile.prototype.setPath = function (p, callback) { + var path = p5.prototype._checkFileFormats(p); + this.url = path; + this.load(callback); + }; + /** + * Replace the current Audio Buffer with a new Buffer. + * + * @method setBuffer + * @param {Array} buf Array of Float32 Array(s). 2 Float32 Arrays + * will create a stereo source. 1 will create + * a mono source. + */ + p5.SoundFile.prototype.setBuffer = function (buf) { + var numChannels = buf.length; + var size = buf[0].length; + var newBuffer = ac.createBuffer(numChannels, size, ac.sampleRate); + if (!(buf[0] instanceof Float32Array)) { + buf[0] = new Float32Array(buf[0]); + } + for (var channelNum = 0; channelNum < numChannels; channelNum++) { + var channel = newBuffer.getChannelData(channelNum); + channel.set(buf[channelNum]); + } + this.buffer = newBuffer; + // set numbers of channels on input to the panner + this.panner.inputChannels(numChannels); + }; + ////////////////////////////////////////////////// + // script processor node with an empty buffer to help + // keep a sample-accurate position in playback buffer. + // Inspired by Chinmay Pendharkar's technique for Sonoport --> http://bit.ly/1HwdCsV + // Copyright [2015] [Sonoport (Asia) Pte. Ltd.], + // Licensed under the Apache License http://apache.org/licenses/LICENSE-2.0 + //////////////////////////////////////////////////////////////////////////////////// + var _createCounterBuffer = function (buffer) { + const len = buffer.length; + const audioBuf = ac.createBuffer(1, buffer.length, ac.sampleRate); + const arrayBuffer = audioBuf.getChannelData(0); + for (var index = 0; index < len; index++) { + arrayBuffer[index] = index; + } + return audioBuf; + }; + // initialize counterNode, set its initial buffer and playbackRate + p5.SoundFile.prototype._initCounterNode = function () { + var self = this; + var now = ac.currentTime; + var cNode = ac.createBufferSource(); + // dispose of scope node if it already exists + if (self._scopeNode) { + self._scopeNode.disconnect(); + self._scopeNode.removeEventListener( + "audioprocess", + self._onAudioProcess + ); + delete self._scopeNode; + } + self._scopeNode = ac.createScriptProcessor(256, 1, 1); + // create counter buffer of the same length as self.buffer + cNode.buffer = _createCounterBuffer(self.buffer); + cNode.playbackRate.setValueAtTime(self.playbackRate, now); + cNode.connect(self._scopeNode); + self._scopeNode.connect(p5.soundOut._silentNode); + self._scopeNode.addEventListener("audioprocess", self._onAudioProcess); + return cNode; + }; + // initialize sourceNode, set its initial buffer and playbackRate + p5.SoundFile.prototype._initSourceNode = function () { + var bufferSourceNode = ac.createBufferSource(); + bufferSourceNode.buffer = this.buffer; + bufferSourceNode.playbackRate.value = this.playbackRate; + bufferSourceNode.connect(this.output); + return bufferSourceNode; + }; + /** + * processPeaks returns an array of timestamps where it thinks there is a beat. + * + * This is an asynchronous function that processes the soundfile in an offline audio context, + * and sends the results to your callback function. + * + * The process involves running the soundfile through a lowpass filter, and finding all of the + * peaks above the initial threshold. If the total number of peaks are below the minimum number of peaks, + * it decreases the threshold and re-runs the analysis until either minPeaks or minThreshold are reached. + * + * @method processPeaks + * @param {Function} callback a function to call once this data is returned + * @param {Number} [initThreshold] initial threshold defaults to 0.9 + * @param {Number} [minThreshold] minimum threshold defaults to 0.22 + * @param {Number} [minPeaks] minimum number of peaks defaults to 200 + * @return {Array} Array of timestamped peaks + */ + p5.SoundFile.prototype.processPeaks = function ( + callback, + _initThreshold, + _minThreshold, + _minPeaks + ) { + var bufLen = this.buffer.length; + var sampleRate = this.buffer.sampleRate; + var buffer = this.buffer; + var allPeaks = []; + var initialThreshold = _initThreshold || 0.9, + threshold = initialThreshold, + minThreshold = _minThreshold || 0.22, + minPeaks = _minPeaks || 200; + // Create offline context + var offlineContext = new window.OfflineAudioContext( + 1, + bufLen, + sampleRate + ); + // create buffer source + var source = offlineContext.createBufferSource(); + source.buffer = buffer; + // Create filter. TO DO: allow custom setting of filter + var filter = offlineContext.createBiquadFilter(); + filter.type = "lowpass"; + source.connect(filter); + filter.connect(offlineContext.destination); + // start playing at time:0 + source.start(0); + offlineContext.startRendering(); + // Render the song + // act on the result + offlineContext.oncomplete = function (e) { + if (!self.panner) return; + var filteredBuffer = e.renderedBuffer; + var bufferData = filteredBuffer.getChannelData(0); + // step 1: + // create Peak instances, add them to array, with strength and sampleIndex + do { + allPeaks = getPeaksAtThreshold(bufferData, threshold); + threshold -= 0.005; + } while ( + Object.keys(allPeaks).length < minPeaks && + threshold >= minThreshold + ); + // step 2: + // find intervals for each peak in the sampleIndex, add tempos array + var intervalCounts = countIntervalsBetweenNearbyPeaks(allPeaks); + // step 3: find top tempos + var groups = groupNeighborsByTempo( + intervalCounts, + filteredBuffer.sampleRate + ); + // sort top intervals + var topTempos = groups + .sort(function (intA, intB) { + return intB.count - intA.count; + }) + .splice(0, 5); + // set this SoundFile's tempo to the top tempo ?? + this.tempo = topTempos[0].tempo; + // step 4: + // new array of peaks at top tempo within a bpmVariance + var bpmVariance = 5; + var tempoPeaks = getPeaksAtTopTempo( + allPeaks, + topTempos[0].tempo, + filteredBuffer.sampleRate, + bpmVariance + ); + callback(tempoPeaks); + }; + }; + // process peaks + var Peak = function (amp, i) { + this.sampleIndex = i; + this.amplitude = amp; + this.tempos = []; + this.intervals = []; + }; + // 1. for processPeaks() Function to identify peaks above a threshold + // returns an array of peak indexes as frames (samples) of the original soundfile + function getPeaksAtThreshold(data, threshold) { + var peaksObj = {}; + var length = data.length; + for (var i = 0; i < length; i++) { + if (data[i] > threshold) { + var amp = data[i]; + var peak = new Peak(amp, i); + peaksObj[i] = peak; + // Skip forward ~ 1/8s to get past this peak. + i += 6000; + } + i++; + } + return peaksObj; + } + // 2. for processPeaks() + function countIntervalsBetweenNearbyPeaks(peaksObj) { + var intervalCounts = []; + var peaksArray = Object.keys(peaksObj).sort(); + for (var index = 0; index < peaksArray.length; index++) { + // find intervals in comparison to nearby peaks + for (var i = 0; i < 10; i++) { + var startPeak = peaksObj[peaksArray[index]]; + var endPeak = peaksObj[peaksArray[index + i]]; + if (startPeak && endPeak) { + var startPos = startPeak.sampleIndex; + var endPos = endPeak.sampleIndex; + var interval = endPos - startPos; + // add a sample interval to the startPeak in the allPeaks array + if (interval > 0) { + startPeak.intervals.push(interval); } - }); - // store with JSON like formatting - if (!foundInterval) { - intervalCounts.push({ - interval: interval, - count: 1 + // tally the intervals and return interval counts + var foundInterval = intervalCounts.some(function (intervalCount) { + if (intervalCount.interval === interval) { + intervalCount.count++; + return intervalCount; + } }); + // store with JSON like formatting + if (!foundInterval) { + intervalCounts.push({ + interval: interval, + count: 1, + }); + } } } } + return intervalCounts; } - return intervalCounts; - } - // 3. for processPeaks --> find tempo - function groupNeighborsByTempo(intervalCounts, sampleRate) { - var tempoCounts = []; - intervalCounts.forEach(function (intervalCount) { - try { - // Convert an interval to tempo - var theoreticalTempo = Math.abs(60 / (intervalCount.interval / sampleRate)); - theoreticalTempo = mapTempo(theoreticalTempo); - var foundTempo = tempoCounts.some(function (tempoCount) { - if (tempoCount.tempo === theoreticalTempo) - return tempoCount.count += intervalCount.count; - }); - if (!foundTempo) { - if (isNaN(theoreticalTempo)) { - return; - } - tempoCounts.push({ - tempo: Math.round(theoreticalTempo), - count: intervalCount.count + // 3. for processPeaks --> find tempo + function groupNeighborsByTempo(intervalCounts, sampleRate) { + var tempoCounts = []; + intervalCounts.forEach(function (intervalCount) { + try { + // Convert an interval to tempo + var theoreticalTempo = Math.abs( + 60 / (intervalCount.interval / sampleRate) + ); + theoreticalTempo = mapTempo(theoreticalTempo); + var foundTempo = tempoCounts.some(function (tempoCount) { + if (tempoCount.tempo === theoreticalTempo) + return (tempoCount.count += intervalCount.count); }); + if (!foundTempo) { + if (isNaN(theoreticalTempo)) { + return; + } + tempoCounts.push({ + tempo: Math.round(theoreticalTempo), + count: intervalCount.count, + }); + } + } catch (e) { + throw e; } - } catch (e) { - throw e; - } - }); - return tempoCounts; - } - // 4. for processPeaks - get peaks at top tempo - function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { - var peaksAtTopTempo = []; - var peaksArray = Object.keys(peaksObj).sort(); - // TO DO: filter out peaks that have the tempo and return - for (var i = 0; i < peaksArray.length; i++) { - var key = peaksArray[i]; - var peak = peaksObj[key]; - for (var j = 0; j < peak.intervals.length; j++) { - var intervalBPM = Math.round(Math.abs(60 / (peak.intervals[j] / sampleRate))); - intervalBPM = mapTempo(intervalBPM); - if (Math.abs(intervalBPM - tempo) < bpmVariance) { - // convert sampleIndex to seconds - peaksAtTopTempo.push(peak.sampleIndex / sampleRate); + }); + return tempoCounts; + } + // 4. for processPeaks - get peaks at top tempo + function getPeaksAtTopTempo(peaksObj, tempo, sampleRate, bpmVariance) { + var peaksAtTopTempo = []; + var peaksArray = Object.keys(peaksObj).sort(); + // TO DO: filter out peaks that have the tempo and return + for (var i = 0; i < peaksArray.length; i++) { + var key = peaksArray[i]; + var peak = peaksObj[key]; + for (var j = 0; j < peak.intervals.length; j++) { + var intervalBPM = Math.round( + Math.abs(60 / (peak.intervals[j] / sampleRate)) + ); + intervalBPM = mapTempo(intervalBPM); + if (Math.abs(intervalBPM - tempo) < bpmVariance) { + // convert sampleIndex to seconds + peaksAtTopTempo.push(peak.sampleIndex / sampleRate); + } } } + // filter out peaks that are very close to each other + peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { + var dif = arr[index + 1] - peakTime; + if (dif > 0.01) { + return true; + } + }); + return peaksAtTopTempo; } - // filter out peaks that are very close to each other - peaksAtTopTempo = peaksAtTopTempo.filter(function (peakTime, index, arr) { - var dif = arr[index + 1] - peakTime; - if (dif > 0.01) { - return true; + // helper function for processPeaks + function mapTempo(theoreticalTempo) { + // these scenarios create infinite while loop + if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { + return; } - }); - return peaksAtTopTempo; - } - // helper function for processPeaks - function mapTempo(theoreticalTempo) { - // these scenarios create infinite while loop - if (!isFinite(theoreticalTempo) || theoreticalTempo === 0) { - return; - } - // Adjust the tempo to fit within the 90-180 BPM range - while (theoreticalTempo < 90) - theoreticalTempo *= 2; - while (theoreticalTempo > 180 && theoreticalTempo > 90) - theoreticalTempo /= 2; - return theoreticalTempo; - } - /*** SCHEDULE EVENTS ***/ - // Cue inspired by JavaScript setTimeout, and the - // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org - var Cue = function (callback, time, id, val) { - this.callback = callback; - this.time = time; - this.id = id; - this.val = val; - }; - /** - * Schedule events to trigger every time a MediaElement - * (audio/video) reaches a playback cue point. - * - * Accepts a callback function, a time (in seconds) at which to trigger - * the callback, and an optional parameter for the callback. - * - * Time will be passed as the first parameter to the callback function, - * and param will be the second parameter. - * - * - * @method addCue - * @param {Number} time Time in seconds, relative to this media - * element's playback. For example, to trigger - * an event every time playback reaches two - * seconds, pass in the number 2. This will be - * passed as the first parameter to - * the callback function. - * @param {Function} callback Name of a function that will be - * called at the given time. The callback will - * receive time and (optionally) param as its - * two parameters. - * @param {Object} [value] An object to be passed as the - * second parameter to the - * callback function. - * @return {Number} id ID of this cue, - * useful for removeCue(id) - * @example - *
- * var mySound; - * function preload() { - * mySound = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * // schedule calls to changeText - * mySound.addCue(0.50, changeText, "hello" ); - * mySound.addCue(1.00, changeText, "p5" ); - * mySound.addCue(1.50, changeText, "what" ); - * mySound.addCue(2.00, changeText, "do" ); - * mySound.addCue(2.50, changeText, "you" ); - * mySound.addCue(3.00, changeText, "want" ); - * mySound.addCue(4.00, changeText, "to" ); - * mySound.addCue(5.00, changeText, "make" ); - * mySound.addCue(6.00, changeText, "?" ); - * } - * - * function changeText(val) { - * background(0); - * text(val, width/2, height/2); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * if (mySound.isPlaying() ) { - * mySound.stop(); - * } else { - * mySound.play(); - * } - * } - * } - *
- */ - p5.SoundFile.prototype.addCue = function (time, callback, val) { - var id = this._cueIDCounter++; - var cue = new Cue(callback, time, id, val); - this._cues.push(cue); - // if (!this.elt.ontimeupdate) { - // this.elt.ontimeupdate = this._onTimeUpdate.bind(this); - // } - return id; - }; - /** - * Remove a callback based on its ID. The ID is returned by the - * addCue method. - * - * @method removeCue - * @param {Number} id ID of the cue, as returned by addCue - */ - p5.SoundFile.prototype.removeCue = function (id) { - var cueLength = this._cues.length; - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; - if (cue.id === id) { - this._cues.splice(i, 1); - break; - } - } - if (this._cues.length === 0) { - } - }; - /** - * Remove all of the callbacks that had originally been scheduled - * via the addCue method. - * - * @method clearCues - */ - p5.SoundFile.prototype.clearCues = function () { - this._cues = []; - }; - // private method that checks for cues to be fired if events - // have been scheduled using addCue(callback, time). - p5.SoundFile.prototype._onTimeUpdate = function (position) { - var playbackTime = position / this.buffer.sampleRate; - var cueLength = this._cues.length; - for (var i = 0; i < cueLength; i++) { - var cue = this._cues[i]; - var callbackTime = cue.time; - var val = cue.val; - if (this._prevTime < callbackTime && callbackTime <= playbackTime) { - // pass the scheduled callbackTime as parameter to the callback - cue.callback(val); - } - } - this._prevTime = playbackTime; - }; - /** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. To upload a file to a server, see - * getBlob - * - * @method save - * @param {String} [fileName] name of the resulting .wav file. - * @example - *
- * var inp, button, mySound; - * var fileName = 'cool'; - * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * function setup() { - * btn = createButton('click to save file'); - * btn.position(0, 0); - * btn.mouseClicked(handleMouseClick); - * } - * - * function handleMouseClick() { - * mySound.save(fileName); - * } - *
- */ - p5.SoundFile.prototype.save = function (fileName) { - const dataView = convertToWav(this.buffer); - p5.prototype.saveSound([dataView], fileName, 'wav'); - }; - /** - * This method is useful for sending a SoundFile to a server. It returns the - * .wav-encoded audio data as a "Blob". - * A Blob is a file-like data object that can be uploaded to a server - * with an http request. We'll - * use the `httpDo` options object to send a POST request with some - * specific options: we encode the request as `multipart/form-data`, - * and attach the blob as one of the form values using `FormData`. - * - * - * @method getBlob - * @returns {Blob} A file-like data object - * @example - *
- * - * function preload() { - * mySound = loadSound('assets/doorbell.mp3'); - * } - * - * function setup() { - * noCanvas(); - * var soundBlob = mySound.getBlob(); - * - * // Now we can send the blob to a server... - * var serverUrl = 'https://jsonplaceholder.typicode.com/posts'; - * var httpRequestOptions = { - * method: 'POST', - * body: new FormData().append('soundBlob', soundBlob), - * headers: new Headers({ - * 'Content-Type': 'multipart/form-data' - * }) - * }; - * httpDo(serverUrl, httpRequestOptions); - * - * // We can also create an `ObjectURL` pointing to the Blob - * var blobUrl = URL.createObjectURL(soundBlob); - * - * // The `
- */ - p5.SoundFile.prototype.getBlob = function () { - const dataView = convertToWav(this.buffer); - return new Blob([dataView], { type: 'audio/wav' }); - }; - // event handler to keep track of current position - function _onAudioProcess(processEvent) { - var inputBuffer = processEvent.inputBuffer.getChannelData(0); - this._lastPos = inputBuffer[inputBuffer.length - 1] || 0; - // do any callbacks that have been scheduled - this._onTimeUpdate(self._lastPos); - } - // event handler to remove references to the bufferSourceNode when it is done playing - function _clearOnEnd(e) { - const thisBufferSourceNode = e.target; - const soundFile = this; - // delete this.bufferSourceNode from the sources array when it is done playing: - thisBufferSourceNode._playing = false; - thisBufferSourceNode.removeEventListener('ended', soundFile._clearOnEnd); - // call the onended callback - soundFile._onended(soundFile); - soundFile.bufferSourceNodes.forEach(function (n, i) { - if (n._playing === false) { - soundFile.bufferSourceNodes.splice(i); - } - }); - if (soundFile.bufferSourceNodes.length === 0) { - soundFile._playing = false; - } - } -}(errorHandler, master, helpers, helpers); -var amplitude; -'use strict'; -amplitude = function () { - var p5sound = master; - /** - * Amplitude measures volume between 0.0 and 1.0. - * Listens to all p5sound by default, or use setInput() - * to listen to a specific sound source. Accepts an optional - * smoothing value, which defaults to 0. - * - * @class p5.Amplitude - * @constructor - * @param {Number} [smoothing] between 0.0 and .999 to smooth - * amplitude readings (defaults to 0) - * @example - *
- * var sound, amplitude, cnv; - * - * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } - * function setup() { - * cnv = createCanvas(100,100); - * amplitude = new p5.Amplitude(); - * - * // start / stop the sound when canvas is clicked - * cnv.mouseClicked(function() { - * if (sound.isPlaying() ){ - * sound.stop(); - * } else { - * sound.play(); - * } - * }); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * - *
- */ - p5.Amplitude = function (smoothing) { - // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default - this.bufferSize = 2048; - // set audio context - this.audiocontext = p5sound.audiocontext; - this.processor = this.audiocontext.createScriptProcessor(this.bufferSize, 2, 1); - // for connections - this.input = this.processor; - this.output = this.audiocontext.createGain(); - // smoothing defaults to 0 - this.smoothing = smoothing || 0; - // the variables to return - this.volume = 0; - this.average = 0; - this.stereoVol = [ - 0, - 0 - ]; - this.stereoAvg = [ - 0, - 0 - ]; - this.stereoVolNorm = [ - 0, - 0 - ]; - this.volMax = 0.001; - this.normalize = false; - this.processor.onaudioprocess = this._audioProcess.bind(this); - this.processor.connect(this.output); - this.output.gain.value = 0; - // this may only be necessary because of a Chrome bug - this.output.connect(this.audiocontext.destination); - // connect to p5sound master output by default, unless set by input() - p5sound.meter.connect(this.processor); - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connects to the p5sound instance (master output) by default. - * Optionally, you can pass in a specific source (i.e. a soundfile). - * - * @method setInput - * @param {soundObject|undefined} [snd] set the sound source - * (optional, defaults to - * master output) - * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 - * to smooth amplitude readings - * @example - *
- * function preload(){ - * sound1 = loadSound('assets/beat.mp3'); - * sound2 = loadSound('assets/drum.mp3'); - * } - * function setup(){ - * amplitude = new p5.Amplitude(); - * sound1.play(); - * sound2.play(); - * amplitude.setInput(sound2); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * function mouseClicked(){ - * sound1.stop(); - * sound2.stop(); - * } - *
- */ - p5.Amplitude.prototype.setInput = function (source, smoothing) { - p5sound.meter.disconnect(); - if (smoothing) { - this.smoothing = smoothing; - } - // connect to the master out of p5s instance if no snd is provided - if (source == null) { - console.log('Amplitude input source is not ready! Connecting to master output instead'); - p5sound.meter.connect(this.processor); - } else if (source instanceof p5.Signal) { - source.output.connect(this.processor); - } else if (source) { - source.connect(this.processor); - this.processor.disconnect(); - this.processor.connect(this.output); - } else { - p5sound.meter.connect(this.processor); - } - }; - p5.Amplitude.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else { - this.output.connect(unit); - } - } else { - this.output.connect(this.panner.connect(p5sound.input)); - } - }; - p5.Amplitude.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - // TO DO make this stereo / dependent on # of audio channels - p5.Amplitude.prototype._audioProcess = function (event) { - for (var channel = 0; channel < event.inputBuffer.numberOfChannels; channel++) { - var inputBuffer = event.inputBuffer.getChannelData(channel); - var bufLength = inputBuffer.length; - var total = 0; - var sum = 0; - var x; - for (var i = 0; i < bufLength; i++) { - x = inputBuffer[i]; - if (this.normalize) { - total += Math.max(Math.min(x / this.volMax, 1), -1); - sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1); - } else { - total += x; - sum += x * x; + // Adjust the tempo to fit within the 90-180 BPM range + while (theoreticalTempo < 90) theoreticalTempo *= 2; + while (theoreticalTempo > 180 && theoreticalTempo > 90) + theoreticalTempo /= 2; + return theoreticalTempo; + } + /*** SCHEDULE EVENTS ***/ + // Cue inspired by JavaScript setTimeout, and the + // Tone.js Transport Timeline Event, MIT License Yotam Mann 2015 tonejs.org + var Cue = function (callback, time, id, val) { + this.callback = callback; + this.time = time; + this.id = id; + this.val = val; + }; + /** + * Schedule events to trigger every time a MediaElement + * (audio/video) reaches a playback cue point. + * + * Accepts a callback function, a time (in seconds) at which to trigger + * the callback, and an optional parameter for the callback. + * + * Time will be passed as the first parameter to the callback function, + * and param will be the second parameter. + * + * + * @method addCue + * @param {Number} time Time in seconds, relative to this media + * element's playback. For example, to trigger + * an event every time playback reaches two + * seconds, pass in the number 2. This will be + * passed as the first parameter to + * the callback function. + * @param {Function} callback Name of a function that will be + * called at the given time. The callback will + * receive time and (optionally) param as its + * two parameters. + * @param {Object} [value] An object to be passed as the + * second parameter to the + * callback function. + * @return {Number} id ID of this cue, + * useful for removeCue(id) + * @example + *
+ * var mySound; + * function preload() { + * mySound = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * // schedule calls to changeText + * mySound.addCue(0.50, changeText, "hello" ); + * mySound.addCue(1.00, changeText, "p5" ); + * mySound.addCue(1.50, changeText, "what" ); + * mySound.addCue(2.00, changeText, "do" ); + * mySound.addCue(2.50, changeText, "you" ); + * mySound.addCue(3.00, changeText, "want" ); + * mySound.addCue(4.00, changeText, "to" ); + * mySound.addCue(5.00, changeText, "make" ); + * mySound.addCue(6.00, changeText, "?" ); + * } + * + * function changeText(val) { + * background(0); + * text(val, width/2, height/2); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * if (mySound.isPlaying() ) { + * mySound.stop(); + * } else { + * mySound.play(); + * } + * } + * } + *
+ */ + p5.SoundFile.prototype.addCue = function (time, callback, val) { + var id = this._cueIDCounter++; + var cue = new Cue(callback, time, id, val); + this._cues.push(cue); + // if (!this.elt.ontimeupdate) { + // this.elt.ontimeupdate = this._onTimeUpdate.bind(this); + // } + return id; + }; + /** + * Remove a callback based on its ID. The ID is returned by the + * addCue method. + * + * @method removeCue + * @param {Number} id ID of the cue, as returned by addCue + */ + p5.SoundFile.prototype.removeCue = function (id) { + var cueLength = this._cues.length; + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + if (cue.id === id) { + this._cues.splice(i, 1); + break; } } - var average = total / bufLength; - // ... then take the square root of the sum. - var rms = Math.sqrt(sum / bufLength); - this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * this.smoothing); - this.stereoAvg[channel] = Math.max(average, this.stereoVol[channel] * this.smoothing); - this.volMax = Math.max(this.stereoVol[channel], this.volMax); - } - // add volume from all channels together - var self = this; - var volSum = this.stereoVol.reduce(function (previousValue, currentValue, index) { - self.stereoVolNorm[index - 1] = Math.max(Math.min(self.stereoVol[index - 1] / self.volMax, 1), 0); - self.stereoVolNorm[index] = Math.max(Math.min(self.stereoVol[index] / self.volMax, 1), 0); - return previousValue + currentValue; - }); - // volume is average of channels - this.volume = volSum / this.stereoVol.length; - // normalized value - this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0); - }; - /** - * Returns a single Amplitude reading at the moment it is called. - * For continuous readings, run in the draw loop. - * - * @method getLevel - * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) - * @return {Number} Amplitude as a number between 0.0 and 1.0 - * @example - *
- * function preload(){ - * sound = loadSound('assets/beat.mp3'); - * } - * function setup() { - * amplitude = new p5.Amplitude(); - * sound.play(); - * } - * function draw() { - * background(0); - * fill(255); - * var level = amplitude.getLevel(); - * var size = map(level, 0, 1, 0, 200); - * ellipse(width/2, height/2, size, size); - * } - * function mouseClicked(){ - * sound.stop(); - * } - *
- */ - p5.Amplitude.prototype.getLevel = function (channel) { - if (typeof channel !== 'undefined') { - if (this.normalize) { - return this.stereoVolNorm[channel]; - } else { - return this.stereoVol[channel]; - } - } else if (this.normalize) { - return this.volNorm; - } else { - return this.volume; - } - }; - /** - * Determines whether the results of Amplitude.process() will be - * Normalized. To normalize, Amplitude finds the difference the - * loudest reading it has processed and the maximum amplitude of - * 1.0. Amplitude adds this difference to all values to produce - * results that will reliably map between 0.0 and 1.0. However, - * if a louder moment occurs, the amount that Normalize adds to - * all the values will change. Accepts an optional boolean parameter - * (true or false). Normalizing is off by default. - * - * @method toggleNormalize - * @param {boolean} [boolean] set normalize to true (1) or false (0) - */ - p5.Amplitude.prototype.toggleNormalize = function (bool) { - if (typeof bool === 'boolean') { - this.normalize = bool; - } else { - this.normalize = !this.normalize; - } - }; - /** - * Smooth Amplitude analysis by averaging with the last analysis - * frame. Off by default. - * - * @method smooth - * @param {Number} set smoothing from 0.0 <= 1 - */ - p5.Amplitude.prototype.smooth = function (s) { - if (s >= 0 && s < 1) { - this.smoothing = s; - } else { - console.log('Error: smoothing must be between 0 and 1'); - } - }; - p5.Amplitude.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.input) { - this.input.disconnect(); - delete this.input; - } - if (this.output) { - this.output.disconnect(); - delete this.output; - } - delete this.processor; - }; -}(master); -var fft; -'use strict'; -fft = function () { - var p5sound = master; - /** - *

FFT (Fast Fourier Transform) is an analysis algorithm that - * isolates individual - * - * audio frequencies within a waveform.

- * - *

Once instantiated, a p5.FFT object can return an array based on - * two types of analyses:
FFT.waveform() computes - * amplitude values along the time domain. The array indices correspond - * to samples across a brief moment in time. Each value represents - * amplitude of the waveform at that sample of time.
- * • FFT.analyze() computes amplitude values along the - * frequency domain. The array indices correspond to frequencies (i.e. - * pitches), from the lowest to the highest that humans can hear. Each - * value represents amplitude at that slice of the frequency spectrum. - * Use with getEnergy() to measure amplitude at specific - * frequencies, or within a range of frequencies.

- * - *

FFT analyzes a very short snapshot of sound called a sample - * buffer. It returns an array of amplitude measurements, referred - * to as bins. The array is 1024 bins long by default. - * You can change the bin array length, but it must be a power of 2 - * between 16 and 1024 in order for the FFT algorithm to function - * correctly. The actual size of the FFT buffer is twice the - * number of bins, so given a standard sample rate, the buffer is - * 2048/44100 seconds long.

- * - * - * @class p5.FFT - * @constructor - * @param {Number} [smoothing] Smooth results of Freq Spectrum. - * 0.0 < smoothing < 1.0. - * Defaults to 0.8. - * @param {Number} [bins] Length of resulting array. - * Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @example - *
- * function preload(){ - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup(){ - * var cnv = createCanvas(100,100); - * cnv.mouseClicked(togglePlay); - * fft = new p5.FFT(); - * sound.amp(0.2); - * } - * - * function draw(){ - * background(0); - * - * var spectrum = fft.analyze(); - * noStroke(); - * fill(0,255,0); // spectrum is green - * for (var i = 0; i< spectrum.length; i++){ - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ) - * } - * - * var waveform = fft.waveform(); - * noFill(); - * beginShape(); - * stroke(255,0,0); // waveform is red - * strokeWeight(1); - * for (var i = 0; i< waveform.length; i++){ - * var x = map(i, 0, waveform.length, 0, width); - * var y = map( waveform[i], -1, 1, 0, height); - * vertex(x,y); - * } - * endShape(); - * - * text('click to play/pause', 4, 10); - * } - * - * // fade sound if mouse is over canvas - * function togglePlay() { - * if (sound.isPlaying()) { - * sound.pause(); - * } else { - * sound.loop(); - * } - * } - *
- */ - p5.FFT = function (smoothing, bins) { - this.input = this.analyser = p5sound.audiocontext.createAnalyser(); - Object.defineProperties(this, { - bins: { - get: function () { - return this.analyser.fftSize / 2; - }, - set: function (b) { - this.analyser.fftSize = b * 2; - }, - configurable: true, - enumerable: true - }, - smoothing: { - get: function () { - return this.analyser.smoothingTimeConstant; - }, - set: function (s) { - this.analyser.smoothingTimeConstant = s; - }, - configurable: true, - enumerable: true - } - }); - // set default smoothing and bins - this.smooth(smoothing); - this.bins = bins || 1024; - // default connections to p5sound fftMeter - p5sound.fftMeter.connect(this.analyser); - this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); - this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); - // predefined frequency ranges, these will be tweakable - this.bass = [ - 20, - 140 - ]; - this.lowMid = [ - 140, - 400 - ]; - this.mid = [ - 400, - 2600 - ]; - this.highMid = [ - 2600, - 5200 - ]; - this.treble = [ - 5200, - 14000 - ]; - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Set the input source for the FFT analysis. If no source is - * provided, FFT will analyze all sound in the sketch. - * - * @method setInput - * @param {Object} [source] p5.sound object (or web audio API source node) - */ - p5.FFT.prototype.setInput = function (source) { - if (!source) { - p5sound.fftMeter.connect(this.analyser); - } else { - if (source.output) { - source.output.connect(this.analyser); - } else if (source.connect) { - source.connect(this.analyser); - } - p5sound.fftMeter.disconnect(); - } - }; - /** - * Returns an array of amplitude values (between -1.0 and +1.0) that represent - * a snapshot of amplitude readings in a single buffer. Length will be - * equal to bins (defaults to 1024). Can be used to draw the waveform - * of a sound. - * - * @method waveform - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {String} [precision] If any value is provided, will return results - * in a Float32 Array which is more precise - * than a regular array. - * @return {Array} Array Array of amplitude values (-1 to 1) - * over time. Array length = bins. - * - */ - p5.FFT.prototype.waveform = function () { - var bins, mode, normalArray; - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - bins = arguments[i]; - this.analyser.fftSize = bins * 2; - } - if (typeof arguments[i] === 'string') { - mode = arguments[i]; + if (this._cues.length === 0) { } - } - // getFloatFrequencyData doesnt work in Safari as of 5/2015 - if (mode && !p5.prototype._isSafari()) { - timeToFloat(this, this.timeDomain); - this.analyser.getFloatTimeDomainData(this.timeDomain); - return this.timeDomain; - } else { - timeToInt(this, this.timeDomain); - this.analyser.getByteTimeDomainData(this.timeDomain); - var normalArray = new Array(); - for (var j = 0; j < this.timeDomain.length; j++) { - var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); - normalArray.push(scaled); - } - return normalArray; - } - }; - /** - * Returns an array of amplitude values (between 0 and 255) - * across the frequency spectrum. Length is equal to FFT bins - * (1024 by default). The array indices correspond to frequencies - * (i.e. pitches), from the lowest to the highest that humans can - * hear. Each value represents amplitude at that slice of the - * frequency spectrum. Must be called prior to using - * getEnergy(). - * - * @method analyze - * @param {Number} [bins] Must be a power of two between - * 16 and 1024. Defaults to 1024. - * @param {Number} [scale] If "dB," returns decibel - * float measurements between - * -140 and 0 (max). - * Otherwise returns integers from 0-255. - * @return {Array} spectrum Array of energy (amplitude/volume) - * values across the frequency spectrum. - * Lowest energy (silence) = 0, highest - * possible is 255. - * @example - *
- * var osc; - * var fft; - * - * function setup(){ - * createCanvas(100,100); - * osc = new p5.Oscillator(); - * osc.amp(0); - * osc.start(); - * fft = new p5.FFT(); - * } - * - * function draw(){ - * background(0); - * - * var freq = map(mouseX, 0, 800, 20, 15000); - * freq = constrain(freq, 1, 20000); - * osc.freq(freq); - * - * var spectrum = fft.analyze(); - * noStroke(); - * fill(0,255,0); // spectrum is green - * for (var i = 0; i< spectrum.length; i++){ - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width / spectrum.length, h ); - * } - * - * stroke(255); - * text('Freq: ' + round(freq)+'Hz', 10, 10); - * - * isMouseOverCanvas(); - * } - * - * // only play sound when mouse is over canvas - * function isMouseOverCanvas() { - * var mX = mouseX, mY = mouseY; - * if (mX > 0 && mX < width && mY < height && mY > 0) { - * osc.amp(0.5, 0.2); - * } else { - * osc.amp(0, 0.2); - * } - * } - *
- * - * - */ - p5.FFT.prototype.analyze = function () { - var mode; - for (var i = 0; i < arguments.length; i++) { - if (typeof arguments[i] === 'number') { - this.bins = arguments[i]; - this.analyser.fftSize = this.bins * 2; - } - if (typeof arguments[i] === 'string') { - mode = arguments[i]; + }; + /** + * Remove all of the callbacks that had originally been scheduled + * via the addCue method. + * + * @method clearCues + */ + p5.SoundFile.prototype.clearCues = function () { + this._cues = []; + }; + // private method that checks for cues to be fired if events + // have been scheduled using addCue(callback, time). + p5.SoundFile.prototype._onTimeUpdate = function (position) { + var playbackTime = position / this.buffer.sampleRate; + var cueLength = this._cues.length; + for (var i = 0; i < cueLength; i++) { + var cue = this._cues[i]; + var callbackTime = cue.time; + var val = cue.val; + if (this._prevTime < callbackTime && callbackTime <= playbackTime) { + // pass the scheduled callbackTime as parameter to the callback + cue.callback(val); + } } - } - if (mode && mode.toLowerCase() === 'db') { - freqToFloat(this); - this.analyser.getFloatFrequencyData(this.freqDomain); - return this.freqDomain; - } else { - freqToInt(this, this.freqDomain); - this.analyser.getByteFrequencyData(this.freqDomain); - var normalArray = Array.apply([], this.freqDomain); - normalArray.length === this.analyser.fftSize; - normalArray.constructor === Array; - return normalArray; - } - }; - /** - * Returns the amount of energy (volume) at a specific - * - * frequency, or the average amount of energy between two - * frequencies. Accepts Number(s) corresponding - * to frequency (in Hz), or a String corresponding to predefined - * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). - * Returns a range between 0 (no energy/volume at that frequency) and - * 255 (maximum energy). - * NOTE: analyze() must be called prior to getEnergy(). Analyze() - * tells the FFT to analyze frequency data, and getEnergy() uses - * the results determine the value at a specific frequency or - * range of frequencies.

- * - * @method getEnergy - * @param {Number|String} frequency1 Will return a value representing - * energy at this frequency. Alternately, - * the strings "bass", "lowMid" "mid", - * "highMid", and "treble" will return - * predefined frequency ranges. - * @param {Number} [frequency2] If a second frequency is given, - * will return average amount of - * energy that exists between the - * two frequencies. - * @return {Number} Energy Energy (volume/amplitude) from - * 0 and 255. - * - */ - p5.FFT.prototype.getEnergy = function (frequency1, frequency2) { - var nyquist = p5sound.audiocontext.sampleRate / 2; - if (frequency1 === 'bass') { - frequency1 = this.bass[0]; - frequency2 = this.bass[1]; - } else if (frequency1 === 'lowMid') { - frequency1 = this.lowMid[0]; - frequency2 = this.lowMid[1]; - } else if (frequency1 === 'mid') { - frequency1 = this.mid[0]; - frequency2 = this.mid[1]; - } else if (frequency1 === 'highMid') { - frequency1 = this.highMid[0]; - frequency2 = this.highMid[1]; - } else if (frequency1 === 'treble') { - frequency1 = this.treble[0]; - frequency2 = this.treble[1]; - } - if (typeof frequency1 !== 'number') { - throw 'invalid input for getEnergy()'; - } else if (!frequency2) { - // if only one parameter: - var index = Math.round(frequency1 / nyquist * this.freqDomain.length); - return this.freqDomain[index]; - } else if (frequency1 && frequency2) { - // if two parameters: - // if second is higher than first - if (frequency1 > frequency2) { - var swap = frequency2; - frequency2 = frequency1; - frequency1 = swap; - } - var lowIndex = Math.round(frequency1 / nyquist * this.freqDomain.length); - var highIndex = Math.round(frequency2 / nyquist * this.freqDomain.length); - var total = 0; - var numFrequencies = 0; - // add up all of the values for the frequencies - for (var i = lowIndex; i <= highIndex; i++) { - total += this.freqDomain[i]; - numFrequencies += 1; - } - // divide by total number of frequencies - var toReturn = total / numFrequencies; - return toReturn; - } else { - throw 'invalid input for getEnergy()'; - } - }; - // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated... - p5.FFT.prototype.getFreq = function (freq1, freq2) { - console.log('getFreq() is deprecated. Please use getEnergy() instead.'); - var x = this.getEnergy(freq1, freq2); - return x; - }; - /** - * Returns the - * - * spectral centroid of the input signal. - * NOTE: analyze() must be called prior to getCentroid(). Analyze() - * tells the FFT to analyze frequency data, and getCentroid() uses - * the results determine the spectral centroid.

+ this._prevTime = playbackTime; + }; + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. To upload a file to a server, see + * getBlob * - * @method getCentroid - * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz. + * @method save + * @param {String} [fileName] name of the resulting .wav file. + * @example + *
+ * var inp, button, mySound; + * var fileName = 'cool'; + * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } + * function setup() { + * btn = createButton('click to save file'); + * btn.position(0, 0); + * btn.mouseClicked(handleMouseClick); + * } + * + * function handleMouseClick() { + * mySound.save(fileName); + * } + *
+ */ + p5.SoundFile.prototype.save = function (fileName) { + const dataView = convertToWav(this.buffer); + p5.prototype.saveSound([dataView], fileName, "wav"); + }; + /** + * This method is useful for sending a SoundFile to a server. It returns the + * .wav-encoded audio data as a "Blob". + * A Blob is a file-like data object that can be uploaded to a server + * with an http request. We'll + * use the `httpDo` options object to send a POST request with some + * specific options: we encode the request as `multipart/form-data`, + * and attach the blob as one of the form values using `FormData`. * * + * @method getBlob + * @returns {Blob} A file-like data object * @example *
* + * function preload() { + * mySound = loadSound('assets/doorbell.mp3'); + * } * - *function setup(){ - * cnv = createCanvas(100,100); - * sound = new p5.AudioIn(); - * sound.start(); - * fft = new p5.FFT(); - * sound.connect(fft); - *} - * + * function setup() { + * noCanvas(); + * var soundBlob = mySound.getBlob(); * - *function draw(){ + * // Now we can send the blob to a server... + * var serverUrl = 'https://jsonplaceholder.typicode.com/posts'; + * var httpRequestOptions = { + * method: 'POST', + * body: new FormData().append('soundBlob', soundBlob), + * headers: new Headers({ + * 'Content-Type': 'multipart/form-data' + * }) + * }; + * httpDo(serverUrl, httpRequestOptions); * - * var centroidplot = 0.0; - * var spectralCentroid = 0; + * // We can also create an `ObjectURL` pointing to the Blob + * var blobUrl = URL.createObjectURL(soundBlob); * + * // The `
+ */ + p5.SoundFile.prototype.getBlob = function () { + const dataView = convertToWav(this.buffer); + return new Blob([dataView], { type: "audio/wav" }); + }; + // event handler to keep track of current position + function _onAudioProcess(processEvent) { + var inputBuffer = processEvent.inputBuffer.getChannelData(0); + this._lastPos = inputBuffer[inputBuffer.length - 1] || 0; + // do any callbacks that have been scheduled + this._onTimeUpdate(self._lastPos); + } + // event handler to remove references to the bufferSourceNode when it is done playing + function _clearOnEnd(e) { + const thisBufferSourceNode = e.target; + const soundFile = this; + // delete this.bufferSourceNode from the sources array when it is done playing: + thisBufferSourceNode._playing = false; + thisBufferSourceNode.removeEventListener("ended", soundFile._clearOnEnd); + // call the onended callback + soundFile._onended(soundFile); + soundFile.bufferSourceNodes.forEach(function (n, i) { + if (n._playing === false) { + soundFile.bufferSourceNodes.splice(i); + } + }); + if (soundFile.bufferSourceNodes.length === 0) { + soundFile._playing = false; + } + } + })(errorHandler, master, helpers, helpers); + var amplitude; + ("use strict"); + amplitude = (function () { + var p5sound = master; + /** + * Amplitude measures volume between 0.0 and 1.0. + * Listens to all p5sound by default, or use setInput() + * to listen to a specific sound source. Accepts an optional + * smoothing value, which defaults to 0. * - * // the mean_freq_index calculation is for the display. - * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length); + * @class p5.Amplitude + * @constructor + * @param {Number} [smoothing] between 0.0 and .999 to smooth + * amplitude readings (defaults to 0) + * @example + *
+ * var sound, amplitude, cnv; * - * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); + * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * function setup() { + * cnv = createCanvas(100,100); + * amplitude = new p5.Amplitude(); * + * // start / stop the sound when canvas is clicked + * cnv.mouseClicked(function() { + * if (sound.isPlaying() ){ + * sound.stop(); + * } else { + * sound.play(); + * } + * }); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } * - * stroke(255,0,0); // the line showing where the centroid is will be red + *
+ */ + p5.Amplitude = function (smoothing) { + // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default + this.bufferSize = 2048; + // set audio context + this.audiocontext = p5sound.audiocontext; + this.processor = this.audiocontext.createScriptProcessor( + this.bufferSize, + 2, + 1 + ); + // for connections + this.input = this.processor; + this.output = this.audiocontext.createGain(); + // smoothing defaults to 0 + this.smoothing = smoothing || 0; + // the variables to return + this.volume = 0; + this.average = 0; + this.stereoVol = [0, 0]; + this.stereoAvg = [0, 0]; + this.stereoVolNorm = [0, 0]; + this.volMax = 0.001; + this.normalize = false; + this.processor.onaudioprocess = this._audioProcess.bind(this); + this.processor.connect(this.output); + this.output.gain.value = 0; + // this may only be necessary because of a Chrome bug + this.output.connect(this.audiocontext.destination); + // connect to p5sound master output by default, unless set by input() + p5sound.meter.connect(this.processor); + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connects to the p5sound instance (master output) by default. + * Optionally, you can pass in a specific source (i.e. a soundfile). * - * rect(centroidplot, 0, width / spectrum.length, height) - * noStroke(); - * fill(255,255,255); // text is white - * text("centroid: ", 10, 20); - * text(round(spectralCentroid)+" Hz", 10, 40); - *} - *
+ * @method setInput + * @param {soundObject|undefined} [snd] set the sound source + * (optional, defaults to + * master output) + * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0 + * to smooth amplitude readings + * @example + *
+ * function preload(){ + * sound1 = loadSound('assets/beat.mp3'); + * sound2 = loadSound('assets/drum.mp3'); + * } + * function setup(){ + * amplitude = new p5.Amplitude(); + * sound1.play(); + * sound2.play(); + * amplitude.setInput(sound2); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * function mouseClicked(){ + * sound1.stop(); + * sound2.stop(); + * } + *
*/ - p5.FFT.prototype.getCentroid = function () { - var nyquist = p5sound.audiocontext.sampleRate / 2; - var cumulative_sum = 0; - var centroid_normalization = 0; - for (var i = 0; i < this.freqDomain.length; i++) { - cumulative_sum += i * this.freqDomain[i]; - centroid_normalization += this.freqDomain[i]; - } - var mean_freq_index = 0; - if (centroid_normalization !== 0) { - mean_freq_index = cumulative_sum / centroid_normalization; - } - var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length); - return spec_centroid_freq; - }; - /** - * Smooth FFT analysis by averaging with the last analysis frame. - * - * @method smooth - * @param {Number} smoothing 0.0 < smoothing < 1.0. - * Defaults to 0.8. - */ - p5.FFT.prototype.smooth = function (s) { - if (typeof s !== 'undefined') { - this.smoothing = s; - } - return this.smoothing; - }; - p5.FFT.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.analyser) { - this.analyser.disconnect(); - delete this.analyser; - } - }; - /** - * Returns an array of average amplitude values for a given number - * of frequency bands split equally. N defaults to 16. - * NOTE: analyze() must be called prior to linAverages(). Analyze() - * tells the FFT to analyze frequency data, and linAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method linAverages - * @param {Number} N Number of returned frequency groups - * @return {Array} linearAverages Array of average amplitude values for each group - */ - p5.FFT.prototype.linAverages = function (N) { - var N = N || 16; - // This prevents undefined, null or 0 values of N - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var spectrumStep = Math.floor(spectrumLength / N); - var linearAverages = new Array(N); - // Keep a second index for the current average group and place the values accordingly - // with only one loop in the spectrum data - var groupIndex = 0; - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - linearAverages[groupIndex] = linearAverages[groupIndex] !== undefined ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - // Increase the group index when the last element of the group is processed - if (specIndex % spectrumStep === spectrumStep - 1) { - groupIndex++; - } - } - return linearAverages; - }; - /** - * Returns an array of average amplitude values of the spectrum, for a given - * set of - * Octave Bands - * NOTE: analyze() must be called prior to logAverages(). Analyze() - * tells the FFT to analyze frequency data, and logAverages() uses - * the results to group them into a smaller set of averages.

- * - * @method logAverages - * @param {Array} octaveBands Array of Octave Bands objects for grouping - * @return {Array} logAverages Array of average amplitude values for each group - */ - p5.FFT.prototype.logAverages = function (octaveBands) { - var nyquist = p5sound.audiocontext.sampleRate / 2; - var spectrum = this.freqDomain; - var spectrumLength = spectrum.length; - var logAverages = new Array(octaveBands.length); - // Keep a second index for the current average group and place the values accordingly - // With only one loop in the spectrum data - var octaveIndex = 0; - for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { - var specIndexFrequency = Math.round(specIndex * nyquist / this.freqDomain.length); - // Increase the group index if the current frequency exceeds the limits of the band - if (specIndexFrequency > octaveBands[octaveIndex].hi) { - octaveIndex++; - } - logAverages[octaveIndex] = logAverages[octaveIndex] !== undefined ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 : spectrum[specIndex]; - } - return logAverages; - }; - /** - * Calculates and Returns the 1/N - * Octave Bands - * N defaults to 3 and minimum central frequency to 15.625Hz. - * (1/3 Octave Bands ~= 31 Frequency Bands) - * Setting fCtr0 to a central value of a higher octave will ignore the lower bands - * and produce less frequency groups. - * - * @method getOctaveBands - * @param {Number} N Specifies the 1/N type of generated octave bands - * @param {Number} fCtr0 Minimum central frequency for the lowest band - * @return {Array} octaveBands Array of octave band objects with their bounds - */ - p5.FFT.prototype.getOctaveBands = function (N, fCtr0) { - var N = N || 3; - // Default to 1/3 Octave Bands - var fCtr0 = fCtr0 || 15.625; - // Minimum central frequency, defaults to 15.625Hz - var octaveBands = []; - var lastFrequencyBand = { - lo: fCtr0 / Math.pow(2, 1 / (2 * N)), - ctr: fCtr0, - hi: fCtr0 * Math.pow(2, 1 / (2 * N)) - }; - octaveBands.push(lastFrequencyBand); - var nyquist = p5sound.audiocontext.sampleRate / 2; - while (lastFrequencyBand.hi < nyquist) { - var newFrequencyBand = {}; - newFrequencyBand.lo = lastFrequencyBand.hi; - newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); - newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); - octaveBands.push(newFrequencyBand); - lastFrequencyBand = newFrequencyBand; - } - return octaveBands; - }; - // helper methods to convert type from float (dB) to int (0-255) - var freqToFloat = function (fft) { - if (fft.freqDomain instanceof Float32Array === false) { - fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); - } - }; - var freqToInt = function (fft) { - if (fft.freqDomain instanceof Uint8Array === false) { - fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } - }; - var timeToFloat = function (fft) { - if (fft.timeDomain instanceof Float32Array === false) { - fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); - } - }; - var timeToInt = function (fft) { - if (fft.timeDomain instanceof Uint8Array === false) { - fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); - } - }; -}(master); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_SignalBase; -Tone_signal_SignalBase = function (Tone) { - 'use strict'; - Tone.SignalBase = function () { - }; - Tone.extend(Tone.SignalBase); - Tone.SignalBase.prototype.connect = function (node, outputNumber, inputNumber) { - if (Tone.Signal && Tone.Signal === node.constructor || Tone.Param && Tone.Param === node.constructor || Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) { - node._param.cancelScheduledValues(0); - node._param.value = 0; - node.overridden = true; - } else if (node instanceof AudioParam) { - node.cancelScheduledValues(0); - node.value = 0; - } - Tone.prototype.connect.call(this, node, outputNumber, inputNumber); - return this; - }; - return Tone.SignalBase; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_WaveShaper; -Tone_signal_WaveShaper = function (Tone) { - 'use strict'; - Tone.WaveShaper = function (mapping, bufferLen) { - this._shaper = this.input = this.output = this.context.createWaveShaper(); - this._curve = null; - if (Array.isArray(mapping)) { - this.curve = mapping; - } else if (isFinite(mapping) || this.isUndef(mapping)) { - this._curve = new Float32Array(this.defaultArg(mapping, 1024)); - } else if (this.isFunction(mapping)) { - this._curve = new Float32Array(this.defaultArg(bufferLen, 1024)); - this.setMap(mapping); - } - }; - Tone.extend(Tone.WaveShaper, Tone.SignalBase); - Tone.WaveShaper.prototype.setMap = function (mapping) { - for (var i = 0, len = this._curve.length; i < len; i++) { - var normalized = i / (len - 1) * 2 - 1; - this._curve[i] = mapping(normalized, i); - } - this._shaper.curve = this._curve; - return this; - }; - Object.defineProperty(Tone.WaveShaper.prototype, 'curve', { - get: function () { - return this._shaper.curve; - }, - set: function (mapping) { - this._curve = new Float32Array(mapping); - this._shaper.curve = this._curve; - } - }); - Object.defineProperty(Tone.WaveShaper.prototype, 'oversample', { - get: function () { - return this._shaper.oversample; - }, - set: function (oversampling) { - if ([ - 'none', - '2x', - '4x' - ].indexOf(oversampling) !== -1) { - this._shaper.oversample = oversampling; + p5.Amplitude.prototype.setInput = function (source, smoothing) { + p5sound.meter.disconnect(); + if (smoothing) { + this.smoothing = smoothing; + } + // connect to the master out of p5s instance if no snd is provided + if (source == null) { + console.log( + "Amplitude input source is not ready! Connecting to master output instead" + ); + p5sound.meter.connect(this.processor); + } else if (source instanceof p5.Signal) { + source.output.connect(this.processor); + } else if (source) { + source.connect(this.processor); + this.processor.disconnect(); + this.processor.connect(this.output); } else { - throw new RangeError('Tone.WaveShaper: oversampling must be either \'none\', \'2x\', or \'4x\''); - } - } - }); - Tone.WaveShaper.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._shaper.disconnect(); - this._shaper = null; - this._curve = null; - return this; - }; - return Tone.WaveShaper; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_TimeBase; -Tone_type_TimeBase = function (Tone) { - Tone.TimeBase = function (val, units) { - if (this instanceof Tone.TimeBase) { - this._expr = this._noOp; - if (val instanceof Tone.TimeBase) { - this.copy(val); - } else if (!this.isUndef(units) || this.isNumber(val)) { - units = this.defaultArg(units, this._defaultUnits); - var method = this._primaryExpressions[units].method; - this._expr = method.bind(this, val); - } else if (this.isString(val)) { - this.set(val); - } else if (this.isUndef(val)) { - this._expr = this._defaultExpr(); + p5sound.meter.connect(this.processor); } - } else { - return new Tone.TimeBase(val, units); - } - }; - Tone.extend(Tone.TimeBase); - Tone.TimeBase.prototype.set = function (exprString) { - this._expr = this._parseExprString(exprString); - return this; - }; - Tone.TimeBase.prototype.clone = function () { - var instance = new this.constructor(); - instance.copy(this); - return instance; - }; - Tone.TimeBase.prototype.copy = function (time) { - var val = time._expr(); - return this.set(val); - }; - Tone.TimeBase.prototype._primaryExpressions = { - 'n': { - regexp: /^(\d+)n/i, - method: function (value) { - value = parseInt(value); - if (value === 1) { - return this._beatsToUnits(this._timeSignature()); + }; + p5.Amplitude.prototype.connect = function (unit) { + if (unit) { + if (unit.hasOwnProperty("input")) { + this.output.connect(unit.input); } else { - return this._beatsToUnits(4 / value); + this.output.connect(unit); } + } else { + this.output.connect(this.panner.connect(p5sound.input)); } - }, - 't': { - regexp: /^(\d+)t/i, - method: function (value) { - value = parseInt(value); - return this._beatsToUnits(8 / (parseInt(value) * 3)); - } - }, - 'm': { - regexp: /^(\d+)m/i, - method: function (value) { - return this._beatsToUnits(parseInt(value) * this._timeSignature()); - } - }, - 'i': { - regexp: /^(\d+)i/i, - method: function (value) { - return this._ticksToUnits(parseInt(value)); - } - }, - 'hz': { - regexp: /^(\d+(?:\.\d+)?)hz/i, - method: function (value) { - return this._frequencyToUnits(parseFloat(value)); + }; + p5.Amplitude.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); } - }, - 'tr': { - regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, - method: function (m, q, s) { + }; + // TO DO make this stereo / dependent on # of audio channels + p5.Amplitude.prototype._audioProcess = function (event) { + for ( + var channel = 0; + channel < event.inputBuffer.numberOfChannels; + channel++ + ) { + var inputBuffer = event.inputBuffer.getChannelData(channel); + var bufLength = inputBuffer.length; var total = 0; - if (m && m !== '0') { - total += this._beatsToUnits(this._timeSignature() * parseFloat(m)); - } - if (q && q !== '0') { - total += this._beatsToUnits(parseFloat(q)); - } - if (s && s !== '0') { - total += this._beatsToUnits(parseFloat(s) / 4); + var sum = 0; + var x; + for (var i = 0; i < bufLength; i++) { + x = inputBuffer[i]; + if (this.normalize) { + total += Math.max(Math.min(x / this.volMax, 1), -1); + sum += + Math.max(Math.min(x / this.volMax, 1), -1) * + Math.max(Math.min(x / this.volMax, 1), -1); + } else { + total += x; + sum += x * x; + } } - return total; - } - }, - 's': { - regexp: /^(\d+(?:\.\d+)?s)/, - method: function (value) { - return this._secondsToUnits(parseFloat(value)); + var average = total / bufLength; + // ... then take the square root of the sum. + var rms = Math.sqrt(sum / bufLength); + this.stereoVol[channel] = Math.max( + rms, + this.stereoVol[channel] * this.smoothing + ); + this.stereoAvg[channel] = Math.max( + average, + this.stereoVol[channel] * this.smoothing + ); + this.volMax = Math.max(this.stereoVol[channel], this.volMax); + } + // add volume from all channels together + var self = this; + var volSum = this.stereoVol.reduce(function ( + previousValue, + currentValue, + index + ) { + self.stereoVolNorm[index - 1] = Math.max( + Math.min(self.stereoVol[index - 1] / self.volMax, 1), + 0 + ); + self.stereoVolNorm[index] = Math.max( + Math.min(self.stereoVol[index] / self.volMax, 1), + 0 + ); + return previousValue + currentValue; + }); + // volume is average of channels + this.volume = volSum / this.stereoVol.length; + // normalized value + this.volNorm = Math.max(Math.min(this.volume / this.volMax, 1), 0); + }; + /** + * Returns a single Amplitude reading at the moment it is called. + * For continuous readings, run in the draw loop. + * + * @method getLevel + * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right) + * @return {Number} Amplitude as a number between 0.0 and 1.0 + * @example + *
+ * function preload(){ + * sound = loadSound('assets/beat.mp3'); + * } + * function setup() { + * amplitude = new p5.Amplitude(); + * sound.play(); + * } + * function draw() { + * background(0); + * fill(255); + * var level = amplitude.getLevel(); + * var size = map(level, 0, 1, 0, 200); + * ellipse(width/2, height/2, size, size); + * } + * function mouseClicked(){ + * sound.stop(); + * } + *
+ */ + p5.Amplitude.prototype.getLevel = function (channel) { + if (typeof channel !== "undefined") { + if (this.normalize) { + return this.stereoVolNorm[channel]; + } else { + return this.stereoVol[channel]; + } + } else if (this.normalize) { + return this.volNorm; + } else { + return this.volume; } - }, - 'samples': { - regexp: /^(\d+)samples/, - method: function (value) { - return parseInt(value) / this.context.sampleRate; + }; + /** + * Determines whether the results of Amplitude.process() will be + * Normalized. To normalize, Amplitude finds the difference the + * loudest reading it has processed and the maximum amplitude of + * 1.0. Amplitude adds this difference to all values to produce + * results that will reliably map between 0.0 and 1.0. However, + * if a louder moment occurs, the amount that Normalize adds to + * all the values will change. Accepts an optional boolean parameter + * (true or false). Normalizing is off by default. + * + * @method toggleNormalize + * @param {boolean} [boolean] set normalize to true (1) or false (0) + */ + p5.Amplitude.prototype.toggleNormalize = function (bool) { + if (typeof bool === "boolean") { + this.normalize = bool; + } else { + this.normalize = !this.normalize; } - }, - 'default': { - regexp: /^(\d+(?:\.\d+)?)/, - method: function (value) { - return this._primaryExpressions[this._defaultUnits].method.call(this, value); + }; + /** + * Smooth Amplitude analysis by averaging with the last analysis + * frame. Off by default. + * + * @method smooth + * @param {Number} set smoothing from 0.0 <= 1 + */ + p5.Amplitude.prototype.smooth = function (s) { + if (s >= 0 && s < 1) { + this.smoothing = s; + } else { + console.log("Error: smoothing must be between 0 and 1"); } - } - }; - Tone.TimeBase.prototype._binaryExpressions = { - '+': { - regexp: /^\+/, - precedence: 2, - method: function (lh, rh) { - return lh() + rh(); - } - }, - '-': { - regexp: /^\-/, - precedence: 2, - method: function (lh, rh) { - return lh() - rh(); - } - }, - '*': { - regexp: /^\*/, - precedence: 1, - method: function (lh, rh) { - return lh() * rh(); - } - }, - '/': { - regexp: /^\//, - precedence: 1, - method: function (lh, rh) { - return lh() / rh(); + }; + p5.Amplitude.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.input) { + this.input.disconnect(); + delete this.input; } - } - }; - Tone.TimeBase.prototype._unaryExpressions = { - 'neg': { - regexp: /^\-/, - method: function (lh) { - return -lh(); + if (this.output) { + this.output.disconnect(); + delete this.output; } - } - }; - Tone.TimeBase.prototype._syntaxGlue = { - '(': { regexp: /^\(/ }, - ')': { regexp: /^\)/ } - }; - Tone.TimeBase.prototype._tokenize = function (expr) { - var position = -1; - var tokens = []; - while (expr.length > 0) { - expr = expr.trim(); - var token = getNextToken(expr, this); - tokens.push(token); - expr = expr.substr(token.value.length); - } - function getNextToken(expr, context) { - var expressions = [ - '_binaryExpressions', - '_unaryExpressions', - '_primaryExpressions', - '_syntaxGlue' - ]; - for (var i = 0; i < expressions.length; i++) { - var group = context[expressions[i]]; - for (var opName in group) { - var op = group[opName]; - var reg = op.regexp; - var match = expr.match(reg); - if (match !== null) { - return { - method: op.method, - precedence: op.precedence, - regexp: op.regexp, - value: match[0] - }; - } + delete this.processor; + }; + })(master); + var fft; + ("use strict"); + fft = (function () { + var p5sound = master; + /** + *

FFT (Fast Fourier Transform) is an analysis algorithm that + * isolates individual + * + * audio frequencies within a waveform.

+ * + *

Once instantiated, a p5.FFT object can return an array based on + * two types of analyses:
FFT.waveform() computes + * amplitude values along the time domain. The array indices correspond + * to samples across a brief moment in time. Each value represents + * amplitude of the waveform at that sample of time.
+ * • FFT.analyze() computes amplitude values along the + * frequency domain. The array indices correspond to frequencies (i.e. + * pitches), from the lowest to the highest that humans can hear. Each + * value represents amplitude at that slice of the frequency spectrum. + * Use with getEnergy() to measure amplitude at specific + * frequencies, or within a range of frequencies.

+ * + *

FFT analyzes a very short snapshot of sound called a sample + * buffer. It returns an array of amplitude measurements, referred + * to as bins. The array is 1024 bins long by default. + * You can change the bin array length, but it must be a power of 2 + * between 16 and 1024 in order for the FFT algorithm to function + * correctly. The actual size of the FFT buffer is twice the + * number of bins, so given a standard sample rate, the buffer is + * 2048/44100 seconds long.

+ * + * + * @class p5.FFT + * @constructor + * @param {Number} [smoothing] Smooth results of Freq Spectrum. + * 0.0 < smoothing < 1.0. + * Defaults to 0.8. + * @param {Number} [bins] Length of resulting array. + * Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @example + *
+ * function preload(){ + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup(){ + * var cnv = createCanvas(100,100); + * cnv.mouseClicked(togglePlay); + * fft = new p5.FFT(); + * sound.amp(0.2); + * } + * + * function draw(){ + * background(0); + * + * var spectrum = fft.analyze(); + * noStroke(); + * fill(0,255,0); // spectrum is green + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ) + * } + * + * var waveform = fft.waveform(); + * noFill(); + * beginShape(); + * stroke(255,0,0); // waveform is red + * strokeWeight(1); + * for (var i = 0; i< waveform.length; i++){ + * var x = map(i, 0, waveform.length, 0, width); + * var y = map( waveform[i], -1, 1, 0, height); + * vertex(x,y); + * } + * endShape(); + * + * text('click to play/pause', 4, 10); + * } + * + * // fade sound if mouse is over canvas + * function togglePlay() { + * if (sound.isPlaying()) { + * sound.pause(); + * } else { + * sound.loop(); + * } + * } + *
+ */ + p5.FFT = function (smoothing, bins) { + this.input = this.analyser = p5sound.audiocontext.createAnalyser(); + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (b) { + this.analyser.fftSize = b * 2; + }, + configurable: true, + enumerable: true, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (s) { + this.analyser.smoothingTimeConstant = s; + }, + configurable: true, + enumerable: true, + }, + }); + // set default smoothing and bins + this.smooth(smoothing); + this.bins = bins || 1024; + // default connections to p5sound fftMeter + p5sound.fftMeter.connect(this.analyser); + this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount); + this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount); + // predefined frequency ranges, these will be tweakable + this.bass = [20, 140]; + this.lowMid = [140, 400]; + this.mid = [400, 2600]; + this.highMid = [2600, 5200]; + this.treble = [5200, 14000]; + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Set the input source for the FFT analysis. If no source is + * provided, FFT will analyze all sound in the sketch. + * + * @method setInput + * @param {Object} [source] p5.sound object (or web audio API source node) + */ + p5.FFT.prototype.setInput = function (source) { + if (!source) { + p5sound.fftMeter.connect(this.analyser); + } else { + if (source.output) { + source.output.connect(this.analyser); + } else if (source.connect) { + source.connect(this.analyser); } + p5sound.fftMeter.disconnect(); } - throw new SyntaxError('Tone.TimeBase: Unexpected token ' + expr); - } - return { - next: function () { - return tokens[++position]; - }, - peek: function () { - return tokens[position + 1]; - } - }; - }; - Tone.TimeBase.prototype._matchGroup = function (token, group, prec) { - var ret = false; - if (!this.isUndef(token)) { - for (var opName in group) { - var op = group[opName]; - if (op.regexp.test(token.value)) { - if (!this.isUndef(prec)) { - if (op.precedence === prec) { - return op; - } - } else { - return op; - } + }; + /** + * Returns an array of amplitude values (between -1.0 and +1.0) that represent + * a snapshot of amplitude readings in a single buffer. Length will be + * equal to bins (defaults to 1024). Can be used to draw the waveform + * of a sound. + * + * @method waveform + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {String} [precision] If any value is provided, will return results + * in a Float32 Array which is more precise + * than a regular array. + * @return {Array} Array Array of amplitude values (-1 to 1) + * over time. Array length = bins. + * + */ + p5.FFT.prototype.waveform = function () { + var bins, mode, normalArray; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + bins = arguments[i]; + this.analyser.fftSize = bins * 2; + } + if (typeof arguments[i] === "string") { + mode = arguments[i]; } } - } - return ret; - }; - Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) { - if (this.isUndef(precedence)) { - precedence = 2; - } - var expr; - if (precedence < 0) { - expr = this._parseUnary(lexer); - } else { - expr = this._parseBinary(lexer, precedence - 1); - } - var token = lexer.peek(); - while (token && this._matchGroup(token, this._binaryExpressions, precedence)) { - token = lexer.next(); - expr = token.method.bind(this, expr, this._parseBinary(lexer, precedence - 1)); - token = lexer.peek(); - } - return expr; - }; - Tone.TimeBase.prototype._parseUnary = function (lexer) { - var token, expr; - token = lexer.peek(); - var op = this._matchGroup(token, this._unaryExpressions); - if (op) { - token = lexer.next(); - expr = this._parseUnary(lexer); - return op.method.bind(this, expr); - } - return this._parsePrimary(lexer); - }; - Tone.TimeBase.prototype._parsePrimary = function (lexer) { - var token, expr; - token = lexer.peek(); - if (this.isUndef(token)) { - throw new SyntaxError('Tone.TimeBase: Unexpected end of expression'); - } - if (this._matchGroup(token, this._primaryExpressions)) { - token = lexer.next(); - var matching = token.value.match(token.regexp); - return token.method.bind(this, matching[1], matching[2], matching[3]); - } - if (token && token.value === '(') { - lexer.next(); - expr = this._parseBinary(lexer); - token = lexer.next(); - if (!(token && token.value === ')')) { - throw new SyntaxError('Expected )'); + // getFloatFrequencyData doesnt work in Safari as of 5/2015 + if (mode && !p5.prototype._isSafari()) { + timeToFloat(this, this.timeDomain); + this.analyser.getFloatTimeDomainData(this.timeDomain); + return this.timeDomain; + } else { + timeToInt(this, this.timeDomain); + this.analyser.getByteTimeDomainData(this.timeDomain); + var normalArray = new Array(); + for (var j = 0; j < this.timeDomain.length; j++) { + var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1); + normalArray.push(scaled); + } + return normalArray; } - return expr; - } - throw new SyntaxError('Tone.TimeBase: Cannot process token ' + token.value); - }; - Tone.TimeBase.prototype._parseExprString = function (exprString) { - if (!this.isString(exprString)) { - exprString = exprString.toString(); - } - var lexer = this._tokenize(exprString); - var tree = this._parseBinary(lexer); - return tree; - }; - Tone.TimeBase.prototype._noOp = function () { - return 0; - }; - Tone.TimeBase.prototype._defaultExpr = function () { - return this._noOp; - }; - Tone.TimeBase.prototype._defaultUnits = 's'; - Tone.TimeBase.prototype._frequencyToUnits = function (freq) { - return 1 / freq; - }; - Tone.TimeBase.prototype._beatsToUnits = function (beats) { - return 60 / Tone.Transport.bpm.value * beats; - }; - Tone.TimeBase.prototype._secondsToUnits = function (seconds) { - return seconds; - }; - Tone.TimeBase.prototype._ticksToUnits = function (ticks) { - return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ); - }; - Tone.TimeBase.prototype._timeSignature = function () { - return Tone.Transport.timeSignature; - }; - Tone.TimeBase.prototype._pushExpr = function (val, name, units) { - if (!(val instanceof Tone.TimeBase)) { - val = new this.constructor(val, units); - } - this._expr = this._binaryExpressions[name].method.bind(this, this._expr, val._expr); - return this; - }; - Tone.TimeBase.prototype.add = function (val, units) { - return this._pushExpr(val, '+', units); - }; - Tone.TimeBase.prototype.sub = function (val, units) { - return this._pushExpr(val, '-', units); - }; - Tone.TimeBase.prototype.mult = function (val, units) { - return this._pushExpr(val, '*', units); - }; - Tone.TimeBase.prototype.div = function (val, units) { - return this._pushExpr(val, '/', units); - }; - Tone.TimeBase.prototype.valueOf = function () { - return this._expr(); - }; - Tone.TimeBase.prototype.dispose = function () { - this._expr = null; - }; - return Tone.TimeBase; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Time; -Tone_type_Time = function (Tone) { - Tone.Time = function (val, units) { - if (this instanceof Tone.Time) { - this._plusNow = false; - Tone.TimeBase.call(this, val, units); - } else { - return new Tone.Time(val, units); - } - }; - Tone.extend(Tone.Time, Tone.TimeBase); - Tone.Time.prototype._unaryExpressions = Object.create(Tone.TimeBase.prototype._unaryExpressions); - Tone.Time.prototype._unaryExpressions.quantize = { - regexp: /^@/, - method: function (rh) { - return Tone.Transport.nextSubdivision(rh()); - } - }; - Tone.Time.prototype._unaryExpressions.now = { - regexp: /^\+/, - method: function (lh) { - this._plusNow = true; - return lh(); - } - }; - Tone.Time.prototype.quantize = function (subdiv, percent) { - percent = this.defaultArg(percent, 1); - this._expr = function (expr, subdivision, percent) { - expr = expr(); - subdivision = subdivision.toSeconds(); - var multiple = Math.round(expr / subdivision); - var ideal = multiple * subdivision; - var diff = ideal - expr; - return expr + diff * percent; - }.bind(this, this._expr, new this.constructor(subdiv), percent); - return this; - }; - Tone.Time.prototype.addNow = function () { - this._plusNow = true; - return this; - }; - Tone.Time.prototype._defaultExpr = function () { - this._plusNow = true; - return this._noOp; - }; - Tone.Time.prototype.copy = function (time) { - Tone.TimeBase.prototype.copy.call(this, time); - this._plusNow = time._plusNow; - return this; - }; - Tone.Time.prototype.toNotation = function () { - var time = this.toSeconds(); - var testNotations = [ - '1m', - '2n', - '4n', - '8n', - '16n', - '32n', - '64n', - '128n' - ]; - var retNotation = this._toNotationHelper(time, testNotations); - var testTripletNotations = [ - '1m', - '2n', - '2t', - '4n', - '4t', - '8n', - '8t', - '16n', - '16t', - '32n', - '32t', - '64n', - '64t', - '128n' - ]; - var retTripletNotation = this._toNotationHelper(time, testTripletNotations); - if (retTripletNotation.split('+').length < retNotation.split('+').length) { - return retTripletNotation; - } else { - return retNotation; - } - }; - Tone.Time.prototype._toNotationHelper = function (units, testNotations) { - var threshold = this._notationToUnits(testNotations[testNotations.length - 1]); - var retNotation = ''; - for (var i = 0; i < testNotations.length; i++) { - var notationTime = this._notationToUnits(testNotations[i]); - var multiple = units / notationTime; - var floatingPointError = 0.000001; - if (1 - multiple % 1 < floatingPointError) { - multiple += floatingPointError; - } - multiple = Math.floor(multiple); - if (multiple > 0) { - if (multiple === 1) { - retNotation += testNotations[i]; - } else { - retNotation += multiple.toString() + '*' + testNotations[i]; + }; + /** + * Returns an array of amplitude values (between 0 and 255) + * across the frequency spectrum. Length is equal to FFT bins + * (1024 by default). The array indices correspond to frequencies + * (i.e. pitches), from the lowest to the highest that humans can + * hear. Each value represents amplitude at that slice of the + * frequency spectrum. Must be called prior to using + * getEnergy(). + * + * @method analyze + * @param {Number} [bins] Must be a power of two between + * 16 and 1024. Defaults to 1024. + * @param {Number} [scale] If "dB," returns decibel + * float measurements between + * -140 and 0 (max). + * Otherwise returns integers from 0-255. + * @return {Array} spectrum Array of energy (amplitude/volume) + * values across the frequency spectrum. + * Lowest energy (silence) = 0, highest + * possible is 255. + * @example + *
+ * var osc; + * var fft; + * + * function setup(){ + * createCanvas(100,100); + * osc = new p5.Oscillator(); + * osc.amp(0); + * osc.start(); + * fft = new p5.FFT(); + * } + * + * function draw(){ + * background(0); + * + * var freq = map(mouseX, 0, 800, 20, 15000); + * freq = constrain(freq, 1, 20000); + * osc.freq(freq); + * + * var spectrum = fft.analyze(); + * noStroke(); + * fill(0,255,0); // spectrum is green + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width / spectrum.length, h ); + * } + * + * stroke(255); + * text('Freq: ' + round(freq)+'Hz', 10, 10); + * + * isMouseOverCanvas(); + * } + * + * // only play sound when mouse is over canvas + * function isMouseOverCanvas() { + * var mX = mouseX, mY = mouseY; + * if (mX > 0 && mX < width && mY < height && mY > 0) { + * osc.amp(0.5, 0.2); + * } else { + * osc.amp(0, 0.2); + * } + * } + *
+ * + * + */ + p5.FFT.prototype.analyze = function () { + var mode; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + this.bins = arguments[i]; + this.analyser.fftSize = this.bins * 2; } - units -= multiple * notationTime; - if (units < threshold) { - break; - } else { - retNotation += ' + '; + if (typeof arguments[i] === "string") { + mode = arguments[i]; } } - } - if (retNotation === '') { - retNotation = '0'; - } - return retNotation; - }; - Tone.Time.prototype._notationToUnits = function (notation) { - var primaryExprs = this._primaryExpressions; - var notationExprs = [ - primaryExprs.n, - primaryExprs.t, - primaryExprs.m - ]; - for (var i = 0; i < notationExprs.length; i++) { - var expr = notationExprs[i]; - var match = notation.match(expr.regexp); - if (match) { - return expr.method.call(this, match[1]); - } - } - }; - Tone.Time.prototype.toBarsBeatsSixteenths = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.toSeconds() / quarterTime; - var measures = Math.floor(quarters / this._timeSignature()); - var sixteenths = quarters % 1 * 4; - quarters = Math.floor(quarters) % this._timeSignature(); - sixteenths = sixteenths.toString(); - if (sixteenths.length > 3) { - sixteenths = parseFloat(sixteenths).toFixed(3); - } - var progress = [ - measures, - quarters, - sixteenths - ]; - return progress.join(':'); - }; - Tone.Time.prototype.toTicks = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.valueOf() / quarterTime; - return Math.floor(quarters * Tone.Transport.PPQ); - }; - Tone.Time.prototype.toSamples = function () { - return this.toSeconds() * this.context.sampleRate; - }; - Tone.Time.prototype.toFrequency = function () { - return 1 / this.toSeconds(); - }; - Tone.Time.prototype.toSeconds = function () { - return this.valueOf(); - }; - Tone.Time.prototype.toMilliseconds = function () { - return this.toSeconds() * 1000; - }; - Tone.Time.prototype.valueOf = function () { - var val = this._expr(); - return val + (this._plusNow ? this.now() : 0); - }; - return Tone.Time; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Frequency; -Tone_type_Frequency = function (Tone) { - Tone.Frequency = function (val, units) { - if (this instanceof Tone.Frequency) { - Tone.TimeBase.call(this, val, units); - } else { - return new Tone.Frequency(val, units); - } - }; - Tone.extend(Tone.Frequency, Tone.TimeBase); - Tone.Frequency.prototype._primaryExpressions = Object.create(Tone.TimeBase.prototype._primaryExpressions); - Tone.Frequency.prototype._primaryExpressions.midi = { - regexp: /^(\d+(?:\.\d+)?midi)/, - method: function (value) { - return this.midiToFrequency(value); - } - }; - Tone.Frequency.prototype._primaryExpressions.note = { - regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, - method: function (pitch, octave) { - var index = noteToScaleIndex[pitch.toLowerCase()]; - var noteNumber = index + (parseInt(octave) + 1) * 12; - return this.midiToFrequency(noteNumber); - } - }; - Tone.Frequency.prototype._primaryExpressions.tr = { - regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, - method: function (m, q, s) { - var total = 1; - if (m && m !== '0') { - total *= this._beatsToUnits(this._timeSignature() * parseFloat(m)); + if (mode && mode.toLowerCase() === "db") { + freqToFloat(this); + this.analyser.getFloatFrequencyData(this.freqDomain); + return this.freqDomain; + } else { + freqToInt(this, this.freqDomain); + this.analyser.getByteFrequencyData(this.freqDomain); + var normalArray = Array.apply([], this.freqDomain); + normalArray.length === this.analyser.fftSize; + normalArray.constructor === Array; + return normalArray; } - if (q && q !== '0') { - total *= this._beatsToUnits(parseFloat(q)); + }; + /** + * Returns the amount of energy (volume) at a specific + * + * frequency, or the average amount of energy between two + * frequencies. Accepts Number(s) corresponding + * to frequency (in Hz), or a String corresponding to predefined + * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble"). + * Returns a range between 0 (no energy/volume at that frequency) and + * 255 (maximum energy). + * NOTE: analyze() must be called prior to getEnergy(). Analyze() + * tells the FFT to analyze frequency data, and getEnergy() uses + * the results determine the value at a specific frequency or + * range of frequencies.

+ * + * @method getEnergy + * @param {Number|String} frequency1 Will return a value representing + * energy at this frequency. Alternately, + * the strings "bass", "lowMid" "mid", + * "highMid", and "treble" will return + * predefined frequency ranges. + * @param {Number} [frequency2] If a second frequency is given, + * will return average amount of + * energy that exists between the + * two frequencies. + * @return {Number} Energy Energy (volume/amplitude) from + * 0 and 255. + * + */ + p5.FFT.prototype.getEnergy = function (frequency1, frequency2) { + var nyquist = p5sound.audiocontext.sampleRate / 2; + if (frequency1 === "bass") { + frequency1 = this.bass[0]; + frequency2 = this.bass[1]; + } else if (frequency1 === "lowMid") { + frequency1 = this.lowMid[0]; + frequency2 = this.lowMid[1]; + } else if (frequency1 === "mid") { + frequency1 = this.mid[0]; + frequency2 = this.mid[1]; + } else if (frequency1 === "highMid") { + frequency1 = this.highMid[0]; + frequency2 = this.highMid[1]; + } else if (frequency1 === "treble") { + frequency1 = this.treble[0]; + frequency2 = this.treble[1]; + } + if (typeof frequency1 !== "number") { + throw "invalid input for getEnergy()"; + } else if (!frequency2) { + // if only one parameter: + var index = Math.round((frequency1 / nyquist) * this.freqDomain.length); + return this.freqDomain[index]; + } else if (frequency1 && frequency2) { + // if two parameters: + // if second is higher than first + if (frequency1 > frequency2) { + var swap = frequency2; + frequency2 = frequency1; + frequency1 = swap; + } + var lowIndex = Math.round( + (frequency1 / nyquist) * this.freqDomain.length + ); + var highIndex = Math.round( + (frequency2 / nyquist) * this.freqDomain.length + ); + var total = 0; + var numFrequencies = 0; + // add up all of the values for the frequencies + for (var i = lowIndex; i <= highIndex; i++) { + total += this.freqDomain[i]; + numFrequencies += 1; + } + // divide by total number of frequencies + var toReturn = total / numFrequencies; + return toReturn; + } else { + throw "invalid input for getEnergy()"; } - if (s && s !== '0') { - total *= this._beatsToUnits(parseFloat(s) / 4); + }; + // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated... + p5.FFT.prototype.getFreq = function (freq1, freq2) { + console.log("getFreq() is deprecated. Please use getEnergy() instead."); + var x = this.getEnergy(freq1, freq2); + return x; + }; + /** + * Returns the + * + * spectral centroid of the input signal. + * NOTE: analyze() must be called prior to getCentroid(). Analyze() + * tells the FFT to analyze frequency data, and getCentroid() uses + * the results determine the spectral centroid.

+ * + * @method getCentroid + * @return {Number} Spectral Centroid Frequency Frequency of the spectral centroid in Hz. + * + * + * @example + *
+ * + * + *function setup(){ + * cnv = createCanvas(100,100); + * sound = new p5.AudioIn(); + * sound.start(); + * fft = new p5.FFT(); + * sound.connect(fft); + *} + * + * + *function draw(){ + * + * var centroidplot = 0.0; + * var spectralCentroid = 0; + * + * + * background(0); + * stroke(0,255,0); + * var spectrum = fft.analyze(); + * fill(0,255,0); // spectrum is green + * + * //draw the spectrum + * for (var i = 0; i< spectrum.length; i++){ + * var x = map(log(i), 0, log(spectrum.length), 0, width); + * var h = map(spectrum[i], 0, 255, 0, height); + * var rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length)); + * rect(x, height, rectangle_width, -h ) + * } + + * var nyquist = 22050; + * + * // get the centroid + * spectralCentroid = fft.getCentroid(); + * + * // the mean_freq_index calculation is for the display. + * var mean_freq_index = spectralCentroid/(nyquist/spectrum.length); + * + * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width); + * + * + * stroke(255,0,0); // the line showing where the centroid is will be red + * + * rect(centroidplot, 0, width / spectrum.length, height) + * noStroke(); + * fill(255,255,255); // text is white + * text("centroid: ", 10, 20); + * text(round(spectralCentroid)+" Hz", 10, 40); + *} + *
+ */ + p5.FFT.prototype.getCentroid = function () { + var nyquist = p5sound.audiocontext.sampleRate / 2; + var cumulative_sum = 0; + var centroid_normalization = 0; + for (var i = 0; i < this.freqDomain.length; i++) { + cumulative_sum += i * this.freqDomain[i]; + centroid_normalization += this.freqDomain[i]; + } + var mean_freq_index = 0; + if (centroid_normalization !== 0) { + mean_freq_index = cumulative_sum / centroid_normalization; + } + var spec_centroid_freq = + mean_freq_index * (nyquist / this.freqDomain.length); + return spec_centroid_freq; + }; + /** + * Smooth FFT analysis by averaging with the last analysis frame. + * + * @method smooth + * @param {Number} smoothing 0.0 < smoothing < 1.0. + * Defaults to 0.8. + */ + p5.FFT.prototype.smooth = function (s) { + if (typeof s !== "undefined") { + this.smoothing = s; } - return total; - } - }; - Tone.Frequency.prototype.transpose = function (interval) { - this._expr = function (expr, interval) { - var val = expr(); - return val * this.intervalToFrequencyRatio(interval); - }.bind(this, this._expr, interval); - return this; - }; - Tone.Frequency.prototype.harmonize = function (intervals) { - this._expr = function (expr, intervals) { - var val = expr(); - var ret = []; - for (var i = 0; i < intervals.length; i++) { - ret[i] = val * this.intervalToFrequencyRatio(intervals[i]); + return this.smoothing; + }; + p5.FFT.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.analyser) { + this.analyser.disconnect(); + delete this.analyser; } - return ret; - }.bind(this, this._expr, intervals); - return this; - }; - Tone.Frequency.prototype.toMidi = function () { - return this.frequencyToMidi(this.valueOf()); - }; - Tone.Frequency.prototype.toNote = function () { - var freq = this.valueOf(); - var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2; - var noteNumber = Math.round(12 * log) + 57; - var octave = Math.floor(noteNumber / 12); - if (octave < 0) { - noteNumber += -12 * octave; - } - var noteName = scaleIndexToNote[noteNumber % 12]; - return noteName + octave.toString(); - }; - Tone.Frequency.prototype.toSeconds = function () { - return 1 / this.valueOf(); - }; - Tone.Frequency.prototype.toFrequency = function () { - return this.valueOf(); - }; - Tone.Frequency.prototype.toTicks = function () { - var quarterTime = this._beatsToUnits(1); - var quarters = this.valueOf() / quarterTime; - return Math.floor(quarters * Tone.Transport.PPQ); - }; - Tone.Frequency.prototype._frequencyToUnits = function (freq) { - return freq; - }; - Tone.Frequency.prototype._ticksToUnits = function (ticks) { - return 1 / (ticks * 60 / (Tone.Transport.bpm.value * Tone.Transport.PPQ)); - }; - Tone.Frequency.prototype._beatsToUnits = function (beats) { - return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats); - }; - Tone.Frequency.prototype._secondsToUnits = function (seconds) { - return 1 / seconds; - }; - Tone.Frequency.prototype._defaultUnits = 'hz'; - var noteToScaleIndex = { - 'cbb': -2, - 'cb': -1, - 'c': 0, - 'c#': 1, - 'cx': 2, - 'dbb': 0, - 'db': 1, - 'd': 2, - 'd#': 3, - 'dx': 4, - 'ebb': 2, - 'eb': 3, - 'e': 4, - 'e#': 5, - 'ex': 6, - 'fbb': 3, - 'fb': 4, - 'f': 5, - 'f#': 6, - 'fx': 7, - 'gbb': 5, - 'gb': 6, - 'g': 7, - 'g#': 8, - 'gx': 9, - 'abb': 7, - 'ab': 8, - 'a': 9, - 'a#': 10, - 'ax': 11, - 'bbb': 9, - 'bb': 10, - 'b': 11, - 'b#': 12, - 'bx': 13 - }; - var scaleIndexToNote = [ - 'C', - 'C#', - 'D', - 'D#', - 'E', - 'F', - 'F#', - 'G', - 'G#', - 'A', - 'A#', - 'B' - ]; - Tone.Frequency.A4 = 440; - Tone.Frequency.prototype.midiToFrequency = function (midi) { - return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12); - }; - Tone.Frequency.prototype.frequencyToMidi = function (frequency) { - return 69 + 12 * Math.log(frequency / Tone.Frequency.A4) / Math.LN2; - }; - return Tone.Frequency; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_TransportTime; -Tone_type_TransportTime = function (Tone) { - Tone.TransportTime = function (val, units) { - if (this instanceof Tone.TransportTime) { - Tone.Time.call(this, val, units); - } else { - return new Tone.TransportTime(val, units); - } - }; - Tone.extend(Tone.TransportTime, Tone.Time); - Tone.TransportTime.prototype._unaryExpressions = Object.create(Tone.Time.prototype._unaryExpressions); - Tone.TransportTime.prototype._unaryExpressions.quantize = { - regexp: /^@/, - method: function (rh) { - var subdivision = this._secondsToTicks(rh()); - var multiple = Math.ceil(Tone.Transport.ticks / subdivision); - return this._ticksToUnits(multiple * subdivision); - } - }; - Tone.TransportTime.prototype._secondsToTicks = function (seconds) { - var quarterTime = this._beatsToUnits(1); - var quarters = seconds / quarterTime; - return Math.round(quarters * Tone.Transport.PPQ); - }; - Tone.TransportTime.prototype.valueOf = function () { - var val = this._secondsToTicks(this._expr()); - return val + (this._plusNow ? Tone.Transport.ticks : 0); - }; - Tone.TransportTime.prototype.toTicks = function () { - return this.valueOf(); - }; - Tone.TransportTime.prototype.toSeconds = function () { - var val = this._expr(); - return val + (this._plusNow ? Tone.Transport.seconds : 0); - }; - Tone.TransportTime.prototype.toFrequency = function () { - return 1 / this.toSeconds(); - }; - return Tone.TransportTime; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_type_Type; -Tone_type_Type = function (Tone) { - Tone.Type = { - Default: 'number', - Time: 'time', - Frequency: 'frequency', - TransportTime: 'transportTime', - Ticks: 'ticks', - NormalRange: 'normalRange', - AudioRange: 'audioRange', - Decibels: 'db', - Interval: 'interval', - BPM: 'bpm', - Positive: 'positive', - Cents: 'cents', - Degrees: 'degrees', - MIDI: 'midi', - BarsBeatsSixteenths: 'barsBeatsSixteenths', - Samples: 'samples', - Hertz: 'hertz', - Note: 'note', - Milliseconds: 'milliseconds', - Seconds: 'seconds', - Notation: 'notation' - }; - Tone.prototype.toSeconds = function (time) { - if (this.isNumber(time)) { - return time; - } else if (this.isUndef(time)) { - return this.now(); - } else if (this.isString(time)) { - return new Tone.Time(time).toSeconds(); - } else if (time instanceof Tone.TimeBase) { - return time.toSeconds(); - } - }; - Tone.prototype.toFrequency = function (freq) { - if (this.isNumber(freq)) { - return freq; - } else if (this.isString(freq) || this.isUndef(freq)) { - return new Tone.Frequency(freq).valueOf(); - } else if (freq instanceof Tone.TimeBase) { - return freq.toFrequency(); - } - }; - Tone.prototype.toTicks = function (time) { - if (this.isNumber(time) || this.isString(time)) { - return new Tone.TransportTime(time).toTicks(); - } else if (this.isUndef(time)) { - return Tone.Transport.ticks; - } else if (time instanceof Tone.TimeBase) { - return time.toTicks(); - } - }; - return Tone; -}(Tone_core_Tone, Tone_type_Time, Tone_type_Frequency, Tone_type_TransportTime); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Param; -Tone_core_Param = function (Tone) { - 'use strict'; - Tone.Param = function () { - var options = this.optionsObject(arguments, [ - 'param', - 'units', - 'convert' - ], Tone.Param.defaults); - this._param = this.input = options.param; - this.units = options.units; - this.convert = options.convert; - this.overridden = false; - this._lfo = null; - if (this.isObject(options.lfo)) { - this.value = options.lfo; - } else if (!this.isUndef(options.value)) { - this.value = options.value; - } - }; - Tone.extend(Tone.Param); - Tone.Param.defaults = { - 'units': Tone.Type.Default, - 'convert': true, - 'param': undefined - }; - Object.defineProperty(Tone.Param.prototype, 'value', { - get: function () { - return this._toUnits(this._param.value); - }, - set: function (value) { - if (this.isObject(value)) { - if (this.isUndef(Tone.LFO)) { - throw new Error('Include \'Tone.LFO\' to use an LFO as a Param value.'); - } - if (this._lfo) { - this._lfo.dispose(); - } - this._lfo = new Tone.LFO(value).start(); - this._lfo.connect(this.input); - } else { - var convertedVal = this._fromUnits(value); - this._param.cancelScheduledValues(0); - this._param.value = convertedVal; + }; + /** + * Returns an array of average amplitude values for a given number + * of frequency bands split equally. N defaults to 16. + * NOTE: analyze() must be called prior to linAverages(). Analyze() + * tells the FFT to analyze frequency data, and linAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method linAverages + * @param {Number} N Number of returned frequency groups + * @return {Array} linearAverages Array of average amplitude values for each group + */ + p5.FFT.prototype.linAverages = function (N) { + var N = N || 16; + // This prevents undefined, null or 0 values of N + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var spectrumStep = Math.floor(spectrumLength / N); + var linearAverages = new Array(N); + // Keep a second index for the current average group and place the values accordingly + // with only one loop in the spectrum data + var groupIndex = 0; + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + linearAverages[groupIndex] = + linearAverages[groupIndex] !== undefined + ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2 + : spectrum[specIndex]; + // Increase the group index when the last element of the group is processed + if (specIndex % spectrumStep === spectrumStep - 1) { + groupIndex++; + } } - } - }); - Tone.Param.prototype._fromUnits = function (val) { - if (this.convert || this.isUndef(this.convert)) { - switch (this.units) { - case Tone.Type.Time: - return this.toSeconds(val); - case Tone.Type.Frequency: - return this.toFrequency(val); - case Tone.Type.Decibels: - return this.dbToGain(val); - case Tone.Type.NormalRange: - return Math.min(Math.max(val, 0), 1); - case Tone.Type.AudioRange: - return Math.min(Math.max(val, -1), 1); - case Tone.Type.Positive: - return Math.max(val, 0); - default: - return val; + return linearAverages; + }; + /** + * Returns an array of average amplitude values of the spectrum, for a given + * set of + * Octave Bands + * NOTE: analyze() must be called prior to logAverages(). Analyze() + * tells the FFT to analyze frequency data, and logAverages() uses + * the results to group them into a smaller set of averages.

+ * + * @method logAverages + * @param {Array} octaveBands Array of Octave Bands objects for grouping + * @return {Array} logAverages Array of average amplitude values for each group + */ + p5.FFT.prototype.logAverages = function (octaveBands) { + var nyquist = p5sound.audiocontext.sampleRate / 2; + var spectrum = this.freqDomain; + var spectrumLength = spectrum.length; + var logAverages = new Array(octaveBands.length); + // Keep a second index for the current average group and place the values accordingly + // With only one loop in the spectrum data + var octaveIndex = 0; + for (var specIndex = 0; specIndex < spectrumLength; specIndex++) { + var specIndexFrequency = Math.round( + (specIndex * nyquist) / this.freqDomain.length + ); + // Increase the group index if the current frequency exceeds the limits of the band + if (specIndexFrequency > octaveBands[octaveIndex].hi) { + octaveIndex++; + } + logAverages[octaveIndex] = + logAverages[octaveIndex] !== undefined + ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2 + : spectrum[specIndex]; } - } else { - return val; - } - }; - Tone.Param.prototype._toUnits = function (val) { - if (this.convert || this.isUndef(this.convert)) { - switch (this.units) { - case Tone.Type.Decibels: - return this.gainToDb(val); - default: - return val; - } - } else { - return val; - } - }; - Tone.Param.prototype._minOutput = 0.00001; - Tone.Param.prototype.setValueAtTime = function (value, time) { - value = this._fromUnits(value); - time = this.toSeconds(time); - if (time <= this.now() + this.blockTime) { - this._param.value = value; - } else { - this._param.setValueAtTime(value, time); - } - return this; - }; - Tone.Param.prototype.setRampPoint = function (now) { - now = this.defaultArg(now, this.now()); - var currentVal = this._param.value; - if (currentVal === 0) { - currentVal = this._minOutput; - } - this._param.setValueAtTime(currentVal, now); - return this; - }; - Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - this._param.linearRampToValueAtTime(value, this.toSeconds(endTime)); - return this; - }; - Tone.Param.prototype.exponentialRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime)); - return this; - }; - Tone.Param.prototype.exponentialRampToValue = function (value, rampTime, startTime) { - startTime = this.toSeconds(startTime); - this.setRampPoint(startTime); - this.exponentialRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); - return this; - }; - Tone.Param.prototype.linearRampToValue = function (value, rampTime, startTime) { - startTime = this.toSeconds(startTime); - this.setRampPoint(startTime); - this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); - return this; - }; - Tone.Param.prototype.setTargetAtTime = function (value, startTime, timeConstant) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - timeConstant = Math.max(this._minOutput, timeConstant); - this._param.setTargetAtTime(value, this.toSeconds(startTime), timeConstant); - return this; - }; - Tone.Param.prototype.setValueCurveAtTime = function (values, startTime, duration) { - for (var i = 0; i < values.length; i++) { - values[i] = this._fromUnits(values[i]); - } - this._param.setValueCurveAtTime(values, this.toSeconds(startTime), this.toSeconds(duration)); - return this; - }; - Tone.Param.prototype.cancelScheduledValues = function (startTime) { - this._param.cancelScheduledValues(this.toSeconds(startTime)); - return this; - }; - Tone.Param.prototype.rampTo = function (value, rampTime, startTime) { - rampTime = this.defaultArg(rampTime, 0); - if (this.units === Tone.Type.Frequency || this.units === Tone.Type.BPM || this.units === Tone.Type.Decibels) { - this.exponentialRampToValue(value, rampTime, startTime); - } else { - this.linearRampToValue(value, rampTime, startTime); - } - return this; - }; - Object.defineProperty(Tone.Param.prototype, 'lfo', { - get: function () { - return this._lfo; - } - }); - Tone.Param.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._param = null; - if (this._lfo) { - this._lfo.dispose(); - this._lfo = null; - } - return this; - }; - return Tone.Param; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Gain; -Tone_core_Gain = function (Tone) { - 'use strict'; - if (window.GainNode && !AudioContext.prototype.createGain) { - AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; - } - Tone.Gain = function () { - var options = this.optionsObject(arguments, [ - 'gain', - 'units' - ], Tone.Gain.defaults); - this.input = this.output = this._gainNode = this.context.createGain(); - this.gain = new Tone.Param({ - 'param': this._gainNode.gain, - 'units': options.units, - 'value': options.gain, - 'convert': options.convert - }); - this._readOnly('gain'); - }; - Tone.extend(Tone.Gain); - Tone.Gain.defaults = { - 'gain': 1, - 'convert': true - }; - Tone.Gain.prototype.dispose = function () { - Tone.Param.prototype.dispose.call(this); - this._gainNode.disconnect(); - this._gainNode = null; - this._writable('gain'); - this.gain.dispose(); - this.gain = null; - }; - Tone.prototype.createInsOuts = function (inputs, outputs) { - if (inputs === 1) { - this.input = new Tone.Gain(); - } else if (inputs > 1) { - this.input = new Array(inputs); - } - if (outputs === 1) { - this.output = new Tone.Gain(); - } else if (outputs > 1) { - this.output = new Array(inputs); - } - }; - return Tone.Gain; -}(Tone_core_Tone, Tone_core_Param); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Signal; -Tone_signal_Signal = function (Tone) { - 'use strict'; - Tone.Signal = function () { - var options = this.optionsObject(arguments, [ - 'value', - 'units' - ], Tone.Signal.defaults); - this.output = this._gain = this.context.createGain(); - options.param = this._gain.gain; - Tone.Param.call(this, options); - this.input = this._param = this._gain.gain; - this.context.getConstant(1).chain(this._gain); - }; - Tone.extend(Tone.Signal, Tone.Param); - Tone.Signal.defaults = { - 'value': 0, - 'units': Tone.Type.Default, - 'convert': true - }; - Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect; - Tone.Signal.prototype.dispose = function () { - Tone.Param.prototype.dispose.call(this); - this._param = null; - this._gain.disconnect(); - this._gain = null; - return this; - }; - return Tone.Signal; -}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_type_Type, Tone_core_Param); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Add; -Tone_signal_Add = function (Tone) { - 'use strict'; - Tone.Add = function (value) { - this.createInsOuts(2, 0); - this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain(); - this._param = this.input[1] = new Tone.Signal(value); - this._param.connect(this._sum); - }; - Tone.extend(Tone.Add, Tone.Signal); - Tone.Add.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._sum.dispose(); - this._sum = null; - this._param.dispose(); - this._param = null; - return this; - }; - return Tone.Add; -}(Tone_core_Tone, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Multiply; -Tone_signal_Multiply = function (Tone) { - 'use strict'; - Tone.Multiply = function (value) { - this.createInsOuts(2, 0); - this._mult = this.input[0] = this.output = new Tone.Gain(); - this._param = this.input[1] = this.output.gain; - this._param.value = this.defaultArg(value, 0); - }; - Tone.extend(Tone.Multiply, Tone.Signal); - Tone.Multiply.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._mult.dispose(); - this._mult = null; - this._param = null; - return this; - }; - return Tone.Multiply; -}(Tone_core_Tone, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Scale; -Tone_signal_Scale = function (Tone) { - 'use strict'; - Tone.Scale = function (outputMin, outputMax) { - this._outputMin = this.defaultArg(outputMin, 0); - this._outputMax = this.defaultArg(outputMax, 1); - this._scale = this.input = new Tone.Multiply(1); - this._add = this.output = new Tone.Add(0); - this._scale.connect(this._add); - this._setRange(); - }; - Tone.extend(Tone.Scale, Tone.SignalBase); - Object.defineProperty(Tone.Scale.prototype, 'min', { - get: function () { - return this._outputMin; - }, - set: function (min) { - this._outputMin = min; - this._setRange(); - } - }); - Object.defineProperty(Tone.Scale.prototype, 'max', { - get: function () { - return this._outputMax; - }, - set: function (max) { - this._outputMax = max; - this._setRange(); - } - }); - Tone.Scale.prototype._setRange = function () { - this._add.value = this._outputMin; - this._scale.value = this._outputMax - this._outputMin; - }; - Tone.Scale.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._add.dispose(); - this._add = null; - this._scale.dispose(); - this._scale = null; - return this; - }; - return Tone.Scale; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Multiply); -var signal; -'use strict'; -signal = function () { - // Signal is built with the Tone.js signal by Yotam Mann - // https://github.com/TONEnoTONE/Tone.js/ - var Signal = Tone_signal_Signal; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - /** - *

p5.Signal is a constant audio-rate signal used by p5.Oscillator - * and p5.Envelope for modulation math.

- * - *

This is necessary because Web Audio is processed on a seprate clock. - * For example, the p5 draw loop runs about 60 times per second. But - * the audio clock must process samples 44100 times per second. If we - * want to add a value to each of those samples, we can't do it in the - * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns - * a Tone.Signal from the Tone.js library by Yotam Mann. - * If you want to work directly with audio signals for modular - * synthesis, check out - * tone.js.

- * - * @class p5.Signal - * @constructor - * @return {Tone.Signal} A Signal object from the Tone.js library - * @example - *
- * function setup() { - * carrier = new p5.Oscillator('sine'); - * carrier.amp(1); // set amplitude - * carrier.freq(220); // set frequency - * carrier.start(); // start oscillating - * - * modulator = new p5.Oscillator('sawtooth'); - * modulator.disconnect(); - * modulator.amp(1); - * modulator.freq(4); - * modulator.start(); - * - * // Modulator's default amplitude range is -1 to 1. - * // Multiply it by -200, so the range is -200 to 200 - * // then add 220 so the range is 20 to 420 - * carrier.freq( modulator.mult(-200).add(220) ); - * } - *
- */ - p5.Signal = function (value) { - var s = new Signal(value); - // p5sound.soundArray.push(s); - return s; - }; - /** - * Fade to value, for smooth transitions - * - * @method fade - * @param {Number} value Value to set this signal - * @param {Number} [secondsFromNow] Length of fade, in seconds from now - */ - Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime; - Mult.prototype.fade = Signal.prototype.fade; - Add.prototype.fade = Signal.prototype.fade; - Scale.prototype.fade = Signal.prototype.fade; - /** - * Connect a p5.sound object or Web Audio node to this - * p5.Signal so that its amplitude values can be scaled. - * - * @method setInput - * @param {Object} input - */ - Signal.prototype.setInput = function (_input) { - _input.connect(this); - }; - Mult.prototype.setInput = Signal.prototype.setInput; - Add.prototype.setInput = Signal.prototype.setInput; - Scale.prototype.setInput = Signal.prototype.setInput; - // signals can add / mult / scale themselves - /** - * Add a constant value to this audio signal, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalAdd. - * - * @method add - * @param {Number} number - * @return {p5.Signal} object - */ - Signal.prototype.add = function (num) { - var add = new Add(num); - // add.setInput(this); - this.connect(add); - return add; - }; - Mult.prototype.add = Signal.prototype.add; - Add.prototype.add = Signal.prototype.add; - Scale.prototype.add = Signal.prototype.add; - /** - * Multiply this signal by a constant value, - * and return the resulting audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalMult. - * - * @method mult - * @param {Number} number to multiply - * @return {p5.Signal} object - */ - Signal.prototype.mult = function (num) { - var mult = new Mult(num); - // mult.setInput(this); - this.connect(mult); - return mult; - }; - Mult.prototype.mult = Signal.prototype.mult; - Add.prototype.mult = Signal.prototype.mult; - Scale.prototype.mult = Signal.prototype.mult; - /** - * Scale this signal value to a given range, - * and return the result as an audio signal. Does - * not change the value of the original signal, - * instead it returns a new p5.SignalScale. - * - * @method scale - * @param {Number} number to multiply - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Signal} object - */ - Signal.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - var scale = new Scale(mapOutMin, mapOutMax); - this.connect(scale); - return scale; - }; - Mult.prototype.scale = Signal.prototype.scale; - Add.prototype.scale = Signal.prototype.scale; - Scale.prototype.scale = Signal.prototype.scale; -}(Tone_signal_Signal, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); -var oscillator; -'use strict'; -oscillator = function () { - var p5sound = master; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - /** - *

Creates a signal that oscillates between -1.0 and 1.0. - * By default, the oscillation takes the form of a sinusoidal - * shape ('sine'). Additional types include 'triangle', - * 'sawtooth' and 'square'. The frequency defaults to - * 440 oscillations per second (440Hz, equal to the pitch of an - * 'A' note).

- * - *

Set the type of oscillation with setType(), or by instantiating a - * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. - *

- * - * @class p5.Oscillator - * @constructor - * @param {Number} [freq] frequency defaults to 440Hz - * @param {String} [type] type of oscillator. Options: - * 'sine' (default), 'triangle', - * 'sawtooth', 'square' - * @example - *
- * var osc; - * var playing = false; - * - * function setup() { - * backgroundColor = color(255,0,255); - * textAlign(CENTER); - * - * osc = new p5.Oscillator(); - * osc.setType('sine'); - * osc.freq(240); - * osc.amp(0); - * osc.start(); - * } - * - * function draw() { - * background(backgroundColor) - * text('click to play', width/2, height/2); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { - * if (!playing) { - * // ramp amplitude to 0.5 over 0.05 seconds - * osc.amp(0.5, 0.05); - * playing = true; - * backgroundColor = color(0,255,255); - * } else { - * // ramp amplitude to 0 over 0.5 seconds - * osc.amp(0, 0.5); - * playing = false; - * backgroundColor = color(255,0,255); - * } - * } - * } - *
- */ - p5.Oscillator = function (freq, type) { - if (typeof freq === 'string') { - var f = type; - type = freq; - freq = f; - } - if (typeof type === 'number') { - var f = type; - type = freq; - freq = f; - } - this.started = false; - // components - this.phaseAmount = undefined; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.f = freq || 440; - // frequency - this.oscillator.type = type || 'sine'; - this.oscillator.frequency.setValueAtTime(this.f, p5sound.audiocontext.currentTime); - // connections - this.output = p5sound.audiocontext.createGain(); - this._freqMods = []; - // modulators connected to this oscillator's frequency - // set default output gain to 0.5 - this.output.gain.value = 0.5; - this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime); - this.oscillator.connect(this.output); - // stereo panning - this.panPosition = 0; - this.connection = p5sound.input; - // connect to p5sound by default - this.panner = new p5.Panner(this.output, this.connection, 1); - //array of math operation signal chaining - this.mathOps = [this.output]; - // add to the soundArray so we can dispose of the osc later - p5sound.soundArray.push(this); - }; - /** - * Start an oscillator. Accepts an optional parameter to - * determine how long (in seconds from now) until the - * oscillator starts. - * - * @method start - * @param {Number} [time] startTime in seconds from now. - * @param {Number} [frequency] frequency in Hz. - */ - p5.Oscillator.prototype.start = function (time, f) { - if (this.started) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - } - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - // set old osc free to be garbage collected (memory) - if (this.oscillator) { - this.oscillator.disconnect(); - delete this.oscillator; + return logAverages; + }; + /** + * Calculates and Returns the 1/N + * Octave Bands + * N defaults to 3 and minimum central frequency to 15.625Hz. + * (1/3 Octave Bands ~= 31 Frequency Bands) + * Setting fCtr0 to a central value of a higher octave will ignore the lower bands + * and produce less frequency groups. + * + * @method getOctaveBands + * @param {Number} N Specifies the 1/N type of generated octave bands + * @param {Number} fCtr0 Minimum central frequency for the lowest band + * @return {Array} octaveBands Array of octave band objects with their bounds + */ + p5.FFT.prototype.getOctaveBands = function (N, fCtr0) { + var N = N || 3; + // Default to 1/3 Octave Bands + var fCtr0 = fCtr0 || 15.625; + // Minimum central frequency, defaults to 15.625Hz + var octaveBands = []; + var lastFrequencyBand = { + lo: fCtr0 / Math.pow(2, 1 / (2 * N)), + ctr: fCtr0, + hi: fCtr0 * Math.pow(2, 1 / (2 * N)), + }; + octaveBands.push(lastFrequencyBand); + var nyquist = p5sound.audiocontext.sampleRate / 2; + while (lastFrequencyBand.hi < nyquist) { + var newFrequencyBand = {}; + newFrequencyBand.lo = lastFrequencyBand.hi; + newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N); + newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N)); + octaveBands.push(newFrequencyBand); + lastFrequencyBand = newFrequencyBand; + } + return octaveBands; + }; + // helper methods to convert type from float (dB) to int (0-255) + var freqToFloat = function (fft) { + if (fft.freqDomain instanceof Float32Array === false) { + fft.freqDomain = new Float32Array(fft.analyser.frequencyBinCount); } - // var detune = this.oscillator.frequency.value; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.oscillator.frequency.value = Math.abs(freq); - this.oscillator.type = type; - // this.oscillator.detune.value = detune; - this.oscillator.connect(this.output); - time = time || 0; - this.oscillator.start(time + p5sound.audiocontext.currentTime); - this.freqNode = this.oscillator.frequency; - // if other oscillators are already connected to this osc's freq - for (var i in this._freqMods) { - if (typeof this._freqMods[i].connect !== 'undefined') { - this._freqMods[i].connect(this.oscillator.frequency); - } + }; + var freqToInt = function (fft) { + if (fft.freqDomain instanceof Uint8Array === false) { + fft.freqDomain = new Uint8Array(fft.analyser.frequencyBinCount); } - this.started = true; - } - }; - /** - * Stop an oscillator. Accepts an optional parameter - * to determine how long (in seconds from now) until the - * oscillator stops. - * - * @method stop - * @param {Number} secondsFromNow Time, in seconds from now. - */ - p5.Oscillator.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = p5sound.audiocontext.currentTime; - this.oscillator.stop(t + now); - this.started = false; - } - }; - /** - * Set the amplitude between 0 and 1.0. Or, pass in an object - * such as an oscillator to modulate amplitude with an audio signal. - * - * @method amp - * @param {Number|Object} vol between 0 and 1.0 - * or a modulating signal/oscillator - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {AudioParam} gain If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's - * gain/amplitude/volume) - */ - p5.Oscillator.prototype.amp = function (vol, rampTime, tFromNow) { - var self = this; - if (typeof vol === 'number') { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - } else if (vol) { - vol.connect(self.output.gain); - } else { - // return the Gain Node - return this.output.gain; - } - }; - // these are now the same thing - p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp; - p5.Oscillator.prototype.getAmp = function () { - return this.output.gain.value; - }; - /** - * Set frequency of an oscillator to a value. Or, pass in an object - * such as an oscillator to modulate the frequency with an audio signal. - * - * @method freq - * @param {Number|Object} Frequency Frequency in Hz - * or modulating signal/oscillator - * @param {Number} [rampTime] Ramp time (in seconds) - * @param {Number} [timeFromNow] Schedule this event to happen - * at x seconds from now - * @return {AudioParam} Frequency If no value is provided, - * returns the Web Audio API - * AudioParam that controls - * this oscillator's frequency - * @example - *
- * var osc = new p5.Oscillator(300); - * osc.start(); - * osc.freq(40, 10); - *
- */ - p5.Oscillator.prototype.freq = function (val, rampTime, tFromNow) { - if (typeof val === 'number' && !isNaN(val)) { - this.f = val; - var now = p5sound.audiocontext.currentTime; - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var t = now + tFromNow + rampTime; - // var currentFreq = this.oscillator.frequency.value; - // this.oscillator.frequency.cancelScheduledValues(now); - if (rampTime === 0) { - this.oscillator.frequency.setValueAtTime(val, tFromNow + now); - } else { - if (val > 0) { - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - } else { - this.oscillator.frequency.linearRampToValueAtTime(val, tFromNow + rampTime + now); - } + }; + var timeToFloat = function (fft) { + if (fft.timeDomain instanceof Float32Array === false) { + fft.timeDomain = new Float32Array(fft.analyser.frequencyBinCount); } - // reset phase if oscillator has a phase - if (this.phaseAmount) { - this.phase(this.phaseAmount); + }; + var timeToInt = function (fft) { + if (fft.timeDomain instanceof Uint8Array === false) { + fft.timeDomain = new Uint8Array(fft.analyser.frequencyBinCount); } - } else if (val) { - if (val.output) { - val = val.output; + }; + })(master); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_SignalBase; + Tone_signal_SignalBase = (function (Tone) { + "use strict"; + Tone.SignalBase = function () {}; + Tone.extend(Tone.SignalBase); + Tone.SignalBase.prototype.connect = function ( + node, + outputNumber, + inputNumber + ) { + if ( + (Tone.Signal && Tone.Signal === node.constructor) || + (Tone.Param && Tone.Param === node.constructor) || + (Tone.TimelineSignal && Tone.TimelineSignal === node.constructor) + ) { + node._param.cancelScheduledValues(0); + node._param.value = 0; + node.overridden = true; + } else if (node instanceof AudioParam) { + node.cancelScheduledValues(0); + node.value = 0; + } + Tone.prototype.connect.call(this, node, outputNumber, inputNumber); + return this; + }; + return Tone.SignalBase; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_WaveShaper; + Tone_signal_WaveShaper = (function (Tone) { + "use strict"; + Tone.WaveShaper = function (mapping, bufferLen) { + this._shaper = this.input = this.output = this.context.createWaveShaper(); + this._curve = null; + if (Array.isArray(mapping)) { + this.curve = mapping; + } else if (isFinite(mapping) || this.isUndef(mapping)) { + this._curve = new Float32Array(this.defaultArg(mapping, 1024)); + } else if (this.isFunction(mapping)) { + this._curve = new Float32Array(this.defaultArg(bufferLen, 1024)); + this.setMap(mapping); } - val.connect(this.oscillator.frequency); - // keep track of what is modulating this param - // so it can be re-connected if - this._freqMods.push(val); - } else { - // return the Frequency Node - return this.oscillator.frequency; - } - }; - p5.Oscillator.prototype.getFreq = function () { - return this.oscillator.frequency.value; - }; - /** - * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. - * - * @method setType - * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. - */ - p5.Oscillator.prototype.setType = function (type) { - this.oscillator.type = type; - }; - p5.Oscillator.prototype.getType = function () { - return this.oscillator.type; - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.Oscillator.prototype.connect = function (unit) { - if (!unit) { - this.panner.connect(p5sound.input); - } else if (unit.hasOwnProperty('input')) { - this.panner.connect(unit.input); - this.connection = unit.input; - } else { - this.panner.connect(unit); - this.connection = unit; - } - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.Oscillator.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - if (this.panner) { - this.panner.disconnect(); - if (this.output) { - this.output.connect(this.panner); + }; + Tone.extend(Tone.WaveShaper, Tone.SignalBase); + Tone.WaveShaper.prototype.setMap = function (mapping) { + for (var i = 0, len = this._curve.length; i < len; i++) { + var normalized = (i / (len - 1)) * 2 - 1; + this._curve[i] = mapping(normalized, i); } - } - this.oscMods = []; - }; - /** - * Pan between Left (-1) and Right (1) - * - * @method pan - * @param {Number} panning Number between -1 and 1 - * @param {Number} timeFromNow schedule this event to happen - * seconds from now - */ - p5.Oscillator.prototype.pan = function (pval, tFromNow) { - this.panPosition = pval; - this.panner.pan(pval, tFromNow); - }; - p5.Oscillator.prototype.getPan = function () { - return this.panPosition; - }; - // get rid of the oscillator - p5.Oscillator.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.oscillator) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - this.disconnect(); - this.panner = null; - this.oscillator = null; - } - // if it is a Pulse - if (this.osc2) { - this.osc2.dispose(); - } - }; - /** - * Set the phase of an oscillator between 0.0 and 1.0. - * In this implementation, phase is a delay time - * based on the oscillator's current frequency. - * - * @method phase - * @param {Number} phase float between 0.0 and 1.0 - */ - p5.Oscillator.prototype.phase = function (p) { - var delayAmt = p5.prototype.map(p, 0, 1, 0, 1 / this.f); - var now = p5sound.audiocontext.currentTime; - this.phaseAmount = p; - if (!this.dNode) { - // create a delay node - this.dNode = p5sound.audiocontext.createDelay(); - // put the delay node in between output and panner - this.oscillator.disconnect(); - this.oscillator.connect(this.dNode); - this.dNode.connect(this.output); - } - // set delay time to match phase: - this.dNode.delayTime.setValueAtTime(delayAmt, now); - }; - // ========================== // - // SIGNAL MATH FOR MODULATION // - // ========================== // - // return sigChain(this, scale, thisChain, nextChain, Scale); - var sigChain = function (o, mathObj, thisChain, nextChain, type) { - var chainSource = o.oscillator; - // if this type of math already exists in the chain, replace it - for (var i in o.mathOps) { - if (o.mathOps[i] instanceof type) { - chainSource.disconnect(); - o.mathOps[i].dispose(); - thisChain = i; - // assume nextChain is output gain node unless... - if (thisChain < o.mathOps.length - 2) { - nextChain = o.mathOps[i + 1]; + this._shaper.curve = this._curve; + return this; + }; + Object.defineProperty(Tone.WaveShaper.prototype, "curve", { + get: function () { + return this._shaper.curve; + }, + set: function (mapping) { + this._curve = new Float32Array(mapping); + this._shaper.curve = this._curve; + }, + }); + Object.defineProperty(Tone.WaveShaper.prototype, "oversample", { + get: function () { + return this._shaper.oversample; + }, + set: function (oversampling) { + if (["none", "2x", "4x"].indexOf(oversampling) !== -1) { + this._shaper.oversample = oversampling; + } else { + throw new RangeError( + "Tone.WaveShaper: oversampling must be either 'none', '2x', or '4x'" + ); + } + }, + }); + Tone.WaveShaper.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._shaper.disconnect(); + this._shaper = null; + this._curve = null; + return this; + }; + return Tone.WaveShaper; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_TimeBase; + Tone_type_TimeBase = (function (Tone) { + Tone.TimeBase = function (val, units) { + if (this instanceof Tone.TimeBase) { + this._expr = this._noOp; + if (val instanceof Tone.TimeBase) { + this.copy(val); + } else if (!this.isUndef(units) || this.isNumber(val)) { + units = this.defaultArg(units, this._defaultUnits); + var method = this._primaryExpressions[units].method; + this._expr = method.bind(this, val); + } else if (this.isString(val)) { + this.set(val); + } else if (this.isUndef(val)) { + this._expr = this._defaultExpr(); } + } else { + return new Tone.TimeBase(val, units); } - } - if (thisChain === o.mathOps.length - 1) { - o.mathOps.push(nextChain); - } - // assume source is the oscillator unless i > 0 - if (i > 0) { - chainSource = o.mathOps[i - 1]; - } - chainSource.disconnect(); - chainSource.connect(mathObj); - mathObj.connect(nextChain); - o.mathOps[thisChain] = mathObj; - return o; - }; - /** - * Add a value to the p5.Oscillator's output amplitude, - * and return the oscillator. Calling this method again - * will override the initial add() with a new value. - * - * @method add - * @param {Number} number Constant number to add - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - * - */ - p5.Oscillator.prototype.add = function (num) { - var add = new Add(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, add, thisChain, nextChain, Add); - }; - /** - * Multiply the p5.Oscillator's output amplitude - * by a fixed value (i.e. turn it up!). Calling this method - * again will override the initial mult() with a new value. - * - * @method mult - * @param {Number} number Constant number to multiply - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with multiplied output - */ - p5.Oscillator.prototype.mult = function (num) { - var mult = new Mult(num); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, mult, thisChain, nextChain, Mult); - }; - /** - * Scale this oscillator's amplitude values to a given - * range, and return the oscillator. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Oscillator} Oscillator Returns this oscillator - * with scaled output - */ - p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) { - var mapOutMin, mapOutMax; - if (arguments.length === 4) { - mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; - mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; - } else { - mapOutMin = arguments[0]; - mapOutMax = arguments[1]; - } - var scale = new Scale(mapOutMin, mapOutMax); - var thisChain = this.mathOps.length - 1; - var nextChain = this.output; - return sigChain(this, scale, thisChain, nextChain, Scale); - }; - // ============================== // - // SinOsc, TriOsc, SqrOsc, SawOsc // - // ============================== // - /** - * Constructor: new p5.SinOsc(). - * This creates a Sine Wave Oscillator and is - * equivalent to new p5.Oscillator('sine') - * or creating a p5.Oscillator and then calling - * its method setType('sine'). - * See p5.Oscillator for methods. - * - * @class p5.SinOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SinOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sine'); - }; - p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.TriOsc(). - * This creates a Triangle Wave Oscillator and is - * equivalent to new p5.Oscillator('triangle') - * or creating a p5.Oscillator and then calling - * its method setType('triangle'). - * See p5.Oscillator for methods. - * - * @class p5.TriOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.TriOsc = function (freq) { - p5.Oscillator.call(this, freq, 'triangle'); - }; - p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.SawOsc(). - * This creates a SawTooth Wave Oscillator and is - * equivalent to new p5.Oscillator('sawtooth') - * or creating a p5.Oscillator and then calling - * its method setType('sawtooth'). - * See p5.Oscillator for methods. - * - * @class p5.SawOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SawOsc = function (freq) { - p5.Oscillator.call(this, freq, 'sawtooth'); - }; - p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype); - /** - * Constructor: new p5.SqrOsc(). - * This creates a Square Wave Oscillator and is - * equivalent to new p5.Oscillator('square') - * or creating a p5.Oscillator and then calling - * its method setType('square'). - * See p5.Oscillator for methods. - * - * @class p5.SqrOsc - * @constructor - * @extends p5.Oscillator - * @param {Number} [freq] Set the frequency - */ - p5.SqrOsc = function (freq) { - p5.Oscillator.call(this, freq, 'square'); - }; - p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype); -}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Timeline; -Tone_core_Timeline = function (Tone) { - 'use strict'; - Tone.Timeline = function () { - var options = this.optionsObject(arguments, ['memory'], Tone.Timeline.defaults); - this._timeline = []; - this._toRemove = []; - this._iterating = false; - this.memory = options.memory; - }; - Tone.extend(Tone.Timeline); - Tone.Timeline.defaults = { 'memory': Infinity }; - Object.defineProperty(Tone.Timeline.prototype, 'length', { - get: function () { - return this._timeline.length; - } - }); - Tone.Timeline.prototype.add = function (event) { - if (this.isUndef(event.time)) { - throw new Error('Tone.Timeline: events must have a time attribute'); - } - if (this._timeline.length) { - var index = this._search(event.time); - this._timeline.splice(index + 1, 0, event); - } else { - this._timeline.push(event); - } - if (this.length > this.memory) { - var diff = this.length - this.memory; - this._timeline.splice(0, diff); - } - return this; - }; - Tone.Timeline.prototype.remove = function (event) { - if (this._iterating) { - this._toRemove.push(event); - } else { - var index = this._timeline.indexOf(event); - if (index !== -1) { - this._timeline.splice(index, 1); + }; + Tone.extend(Tone.TimeBase); + Tone.TimeBase.prototype.set = function (exprString) { + this._expr = this._parseExprString(exprString); + return this; + }; + Tone.TimeBase.prototype.clone = function () { + var instance = new this.constructor(); + instance.copy(this); + return instance; + }; + Tone.TimeBase.prototype.copy = function (time) { + var val = time._expr(); + return this.set(val); + }; + Tone.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (value) { + value = parseInt(value); + if (value === 1) { + return this._beatsToUnits(this._timeSignature()); + } else { + return this._beatsToUnits(4 / value); + } + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (value) { + value = parseInt(value); + return this._beatsToUnits(8 / (parseInt(value) * 3)); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (value) { + return this._beatsToUnits(parseInt(value) * this._timeSignature()); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (value) { + return this._ticksToUnits(parseInt(value)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (value) { + return this._frequencyToUnits(parseFloat(value)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (m, q, s) { + var total = 0; + if (m && m !== "0") { + total += this._beatsToUnits(this._timeSignature() * parseFloat(m)); + } + if (q && q !== "0") { + total += this._beatsToUnits(parseFloat(q)); + } + if (s && s !== "0") { + total += this._beatsToUnits(parseFloat(s) / 4); + } + return total; + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (value) { + return this._secondsToUnits(parseFloat(value)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (value) { + return parseInt(value) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (value) { + return this._primaryExpressions[this._defaultUnits].method.call( + this, + value + ); + }, + }, + }; + Tone.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (lh, rh) { + return lh() + rh(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (lh, rh) { + return lh() - rh(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (lh, rh) { + return lh() * rh(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (lh, rh) { + return lh() / rh(); + }, + }, + }; + Tone.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (lh) { + return -lh(); + }, + }, + }; + Tone.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }; + Tone.TimeBase.prototype._tokenize = function (expr) { + var position = -1; + var tokens = []; + while (expr.length > 0) { + expr = expr.trim(); + var token = getNextToken(expr, this); + tokens.push(token); + expr = expr.substr(token.value.length); + } + function getNextToken(expr, context) { + var expressions = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ]; + for (var i = 0; i < expressions.length; i++) { + var group = context[expressions[i]]; + for (var opName in group) { + var op = group[opName]; + var reg = op.regexp; + var match = expr.match(reg); + if (match !== null) { + return { + method: op.method, + precedence: op.precedence, + regexp: op.regexp, + value: match[0], + }; + } + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + expr); } - } - return this; - }; - Tone.Timeline.prototype.get = function (time) { - var index = this._search(time); - if (index !== -1) { - return this._timeline[index]; - } else { - return null; - } - }; - Tone.Timeline.prototype.peek = function () { - return this._timeline[0]; - }; - Tone.Timeline.prototype.shift = function () { - return this._timeline.shift(); - }; - Tone.Timeline.prototype.getAfter = function (time) { - var index = this._search(time); - if (index + 1 < this._timeline.length) { - return this._timeline[index + 1]; - } else { - return null; - } - }; - Tone.Timeline.prototype.getBefore = function (time) { - var len = this._timeline.length; - if (len > 0 && this._timeline[len - 1].time < time) { - return this._timeline[len - 1]; - } - var index = this._search(time); - if (index - 1 >= 0) { - return this._timeline[index - 1]; - } else { - return null; - } - }; - Tone.Timeline.prototype.cancel = function (after) { - if (this._timeline.length > 1) { - var index = this._search(after); - if (index >= 0) { - if (this._timeline[index].time === after) { - for (var i = index; i >= 0; i--) { - if (this._timeline[i].time === after) { - index = i; + return { + next: function () { + return tokens[++position]; + }, + peek: function () { + return tokens[position + 1]; + }, + }; + }; + Tone.TimeBase.prototype._matchGroup = function (token, group, prec) { + var ret = false; + if (!this.isUndef(token)) { + for (var opName in group) { + var op = group[opName]; + if (op.regexp.test(token.value)) { + if (!this.isUndef(prec)) { + if (op.precedence === prec) { + return op; + } } else { - break; + return op; } } - this._timeline = this._timeline.slice(0, index); - } else { - this._timeline = this._timeline.slice(0, index + 1); } - } else { - this._timeline = []; } - } else if (this._timeline.length === 1) { - if (this._timeline[0].time >= after) { - this._timeline = []; + return ret; + }; + Tone.TimeBase.prototype._parseBinary = function (lexer, precedence) { + if (this.isUndef(precedence)) { + precedence = 2; } - } - return this; - }; - Tone.Timeline.prototype.cancelBefore = function (time) { - if (this._timeline.length) { - var index = this._search(time); - if (index >= 0) { - this._timeline = this._timeline.slice(index + 1); + var expr; + if (precedence < 0) { + expr = this._parseUnary(lexer); + } else { + expr = this._parseBinary(lexer, precedence - 1); } - } - return this; - }; - Tone.Timeline.prototype._search = function (time) { - var beginning = 0; - var len = this._timeline.length; - var end = len; - if (len > 0 && this._timeline[len - 1].time <= time) { - return len - 1; - } - while (beginning < end) { - var midPoint = Math.floor(beginning + (end - beginning) / 2); - var event = this._timeline[midPoint]; - var nextEvent = this._timeline[midPoint + 1]; - if (event.time === time) { - for (var i = midPoint; i < this._timeline.length; i++) { - var testEvent = this._timeline[i]; - if (testEvent.time === time) { - midPoint = i; - } - } - return midPoint; - } else if (event.time < time && nextEvent.time > time) { - return midPoint; - } else if (event.time > time) { - end = midPoint; - } else if (event.time < time) { - beginning = midPoint + 1; + var token = lexer.peek(); + while ( + token && + this._matchGroup(token, this._binaryExpressions, precedence) + ) { + token = lexer.next(); + expr = token.method.bind( + this, + expr, + this._parseBinary(lexer, precedence - 1) + ); + token = lexer.peek(); } - } - return -1; - }; - Tone.Timeline.prototype._iterate = function (callback, lowerBound, upperBound) { - this._iterating = true; - lowerBound = this.defaultArg(lowerBound, 0); - upperBound = this.defaultArg(upperBound, this._timeline.length - 1); - for (var i = lowerBound; i <= upperBound; i++) { - callback(this._timeline[i]); - } - this._iterating = false; - if (this._toRemove.length > 0) { - for (var j = 0; j < this._toRemove.length; j++) { - var index = this._timeline.indexOf(this._toRemove[j]); - if (index !== -1) { - this._timeline.splice(index, 1); - } + return expr; + }; + Tone.TimeBase.prototype._parseUnary = function (lexer) { + var token, expr; + token = lexer.peek(); + var op = this._matchGroup(token, this._unaryExpressions); + if (op) { + token = lexer.next(); + expr = this._parseUnary(lexer); + return op.method.bind(this, expr); } - this._toRemove = []; - } - }; - Tone.Timeline.prototype.forEach = function (callback) { - this._iterate(callback); - return this; - }; - Tone.Timeline.prototype.forEachBefore = function (time, callback) { - var upperBound = this._search(time); - if (upperBound !== -1) { - this._iterate(callback, 0, upperBound); - } - return this; - }; - Tone.Timeline.prototype.forEachAfter = function (time, callback) { - var lowerBound = this._search(time); - this._iterate(callback, lowerBound + 1); - return this; - }; - Tone.Timeline.prototype.forEachFrom = function (time, callback) { - var lowerBound = this._search(time); - while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) { - lowerBound--; - } - this._iterate(callback, lowerBound + 1); - return this; - }; - Tone.Timeline.prototype.forEachAtTime = function (time, callback) { - var upperBound = this._search(time); - if (upperBound !== -1) { - this._iterate(function (event) { - if (event.time === time) { - callback(event); - } - }, 0, upperBound); - } - return this; - }; - Tone.Timeline.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._timeline = null; - this._toRemove = null; - }; - return Tone.Timeline; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_TimelineSignal; -Tone_signal_TimelineSignal = function (Tone) { - 'use strict'; - Tone.TimelineSignal = function () { - var options = this.optionsObject(arguments, [ - 'value', - 'units' - ], Tone.Signal.defaults); - this._events = new Tone.Timeline(10); - Tone.Signal.apply(this, options); - options.param = this._param; - Tone.Param.call(this, options); - this._initial = this._fromUnits(this._param.value); - }; - Tone.extend(Tone.TimelineSignal, Tone.Param); - Tone.TimelineSignal.Type = { - Linear: 'linear', - Exponential: 'exponential', - Target: 'target', - Curve: 'curve', - Set: 'set' - }; - Object.defineProperty(Tone.TimelineSignal.prototype, 'value', { - get: function () { - var now = this.now(); - var val = this.getValueAtTime(now); - return this._toUnits(val); - }, - set: function (value) { - var convertedVal = this._fromUnits(value); - this._initial = convertedVal; - this.cancelScheduledValues(); - this._param.value = convertedVal; - } - }); - Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) { - value = this._fromUnits(value); - startTime = this.toSeconds(startTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Set, - 'value': value, - 'time': startTime - }); - this._param.setValueAtTime(value, startTime); - return this; - }; - Tone.TimelineSignal.prototype.linearRampToValueAtTime = function (value, endTime) { - value = this._fromUnits(value); - endTime = this.toSeconds(endTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Linear, - 'value': value, - 'time': endTime - }); - this._param.linearRampToValueAtTime(value, endTime); - return this; - }; - Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function (value, endTime) { - endTime = this.toSeconds(endTime); - var beforeEvent = this._searchBefore(endTime); - if (beforeEvent && beforeEvent.value === 0) { - this.setValueAtTime(this._minOutput, beforeEvent.time); - } - value = this._fromUnits(value); - var setValue = Math.max(value, this._minOutput); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Exponential, - 'value': setValue, - 'time': endTime - }); - if (value < this._minOutput) { - this._param.exponentialRampToValueAtTime(this._minOutput, endTime - this.sampleTime); - this.setValueAtTime(0, endTime); - } else { - this._param.exponentialRampToValueAtTime(value, endTime); - } - return this; - }; - Tone.TimelineSignal.prototype.setTargetAtTime = function (value, startTime, timeConstant) { - value = this._fromUnits(value); - value = Math.max(this._minOutput, value); - timeConstant = Math.max(this._minOutput, timeConstant); - startTime = this.toSeconds(startTime); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Target, - 'value': value, - 'time': startTime, - 'constant': timeConstant - }); - this._param.setTargetAtTime(value, startTime, timeConstant); - return this; - }; - Tone.TimelineSignal.prototype.setValueCurveAtTime = function (values, startTime, duration, scaling) { - scaling = this.defaultArg(scaling, 1); - var floats = new Array(values.length); - for (var i = 0; i < floats.length; i++) { - floats[i] = this._fromUnits(values[i]) * scaling; - } - startTime = this.toSeconds(startTime); - duration = this.toSeconds(duration); - this._events.add({ - 'type': Tone.TimelineSignal.Type.Curve, - 'value': floats, - 'time': startTime, - 'duration': duration - }); - this._param.setValueAtTime(floats[0], startTime); - for (var j = 1; j < floats.length; j++) { - var segmentTime = startTime + j / (floats.length - 1) * duration; - this._param.linearRampToValueAtTime(floats[j], segmentTime); - } - return this; - }; - Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) { - after = this.toSeconds(after); - this._events.cancel(after); - this._param.cancelScheduledValues(after); - return this; - }; - Tone.TimelineSignal.prototype.setRampPoint = function (time) { - time = this.toSeconds(time); - var val = this._toUnits(this.getValueAtTime(time)); - var before = this._searchBefore(time); - if (before && before.time === time) { - this.cancelScheduledValues(time + this.sampleTime); - } else if (before && before.type === Tone.TimelineSignal.Type.Curve && before.time + before.duration > time) { - this.cancelScheduledValues(time); - this.linearRampToValueAtTime(val, time); - } else { - var after = this._searchAfter(time); - if (after) { - this.cancelScheduledValues(time); - if (after.type === Tone.TimelineSignal.Type.Linear) { - this.linearRampToValueAtTime(val, time); - } else if (after.type === Tone.TimelineSignal.Type.Exponential) { - this.exponentialRampToValueAtTime(val, time); + return this._parsePrimary(lexer); + }; + Tone.TimeBase.prototype._parsePrimary = function (lexer) { + var token, expr; + token = lexer.peek(); + if (this.isUndef(token)) { + throw new SyntaxError("Tone.TimeBase: Unexpected end of expression"); + } + if (this._matchGroup(token, this._primaryExpressions)) { + token = lexer.next(); + var matching = token.value.match(token.regexp); + return token.method.bind(this, matching[1], matching[2], matching[3]); + } + if (token && token.value === "(") { + lexer.next(); + expr = this._parseBinary(lexer); + token = lexer.next(); + if (!(token && token.value === ")")) { + throw new SyntaxError("Expected )"); } + return expr; } - this.setValueAtTime(val, time); - } - return this; - }; - Tone.TimelineSignal.prototype.linearRampToValueBetween = function (value, start, finish) { - this.setRampPoint(start); - this.linearRampToValueAtTime(value, finish); - return this; - }; - Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function (value, start, finish) { - this.setRampPoint(start); - this.exponentialRampToValueAtTime(value, finish); - return this; - }; - Tone.TimelineSignal.prototype._searchBefore = function (time) { - return this._events.get(time); - }; - Tone.TimelineSignal.prototype._searchAfter = function (time) { - return this._events.getAfter(time); - }; - Tone.TimelineSignal.prototype.getValueAtTime = function (time) { - time = this.toSeconds(time); - var after = this._searchAfter(time); - var before = this._searchBefore(time); - var value = this._initial; - if (before === null) { - value = this._initial; - } else if (before.type === Tone.TimelineSignal.Type.Target) { - var previous = this._events.getBefore(before.time); - var previouVal; - if (previous === null) { - previouVal = this._initial; + throw new SyntaxError( + "Tone.TimeBase: Cannot process token " + token.value + ); + }; + Tone.TimeBase.prototype._parseExprString = function (exprString) { + if (!this.isString(exprString)) { + exprString = exprString.toString(); + } + var lexer = this._tokenize(exprString); + var tree = this._parseBinary(lexer); + return tree; + }; + Tone.TimeBase.prototype._noOp = function () { + return 0; + }; + Tone.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }; + Tone.TimeBase.prototype._defaultUnits = "s"; + Tone.TimeBase.prototype._frequencyToUnits = function (freq) { + return 1 / freq; + }; + Tone.TimeBase.prototype._beatsToUnits = function (beats) { + return (60 / Tone.Transport.bpm.value) * beats; + }; + Tone.TimeBase.prototype._secondsToUnits = function (seconds) { + return seconds; + }; + Tone.TimeBase.prototype._ticksToUnits = function (ticks) { + return ticks * (this._beatsToUnits(1) / Tone.Transport.PPQ); + }; + Tone.TimeBase.prototype._timeSignature = function () { + return Tone.Transport.timeSignature; + }; + Tone.TimeBase.prototype._pushExpr = function (val, name, units) { + if (!(val instanceof Tone.TimeBase)) { + val = new this.constructor(val, units); + } + this._expr = this._binaryExpressions[name].method.bind( + this, + this._expr, + val._expr + ); + return this; + }; + Tone.TimeBase.prototype.add = function (val, units) { + return this._pushExpr(val, "+", units); + }; + Tone.TimeBase.prototype.sub = function (val, units) { + return this._pushExpr(val, "-", units); + }; + Tone.TimeBase.prototype.mult = function (val, units) { + return this._pushExpr(val, "*", units); + }; + Tone.TimeBase.prototype.div = function (val, units) { + return this._pushExpr(val, "/", units); + }; + Tone.TimeBase.prototype.valueOf = function () { + return this._expr(); + }; + Tone.TimeBase.prototype.dispose = function () { + this._expr = null; + }; + return Tone.TimeBase; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Time; + Tone_type_Time = (function (Tone) { + Tone.Time = function (val, units) { + if (this instanceof Tone.Time) { + this._plusNow = false; + Tone.TimeBase.call(this, val, units); } else { - previouVal = previous.value; - } - value = this._exponentialApproach(before.time, previouVal, before.value, before.constant, time); - } else if (before.type === Tone.TimelineSignal.Type.Curve) { - value = this._curveInterpolate(before.time, before.value, before.duration, time); - } else if (after === null) { - value = before.value; - } else if (after.type === Tone.TimelineSignal.Type.Linear) { - value = this._linearInterpolate(before.time, before.value, after.time, after.value, time); - } else if (after.type === Tone.TimelineSignal.Type.Exponential) { - value = this._exponentialInterpolate(before.time, before.value, after.time, after.value, time); - } else { - value = before.value; - } - return value; - }; - Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect; - Tone.TimelineSignal.prototype._exponentialApproach = function (t0, v0, v1, timeConstant, t) { - return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant); - }; - Tone.TimelineSignal.prototype._linearInterpolate = function (t0, v0, t1, v1, t) { - return v0 + (v1 - v0) * ((t - t0) / (t1 - t0)); - }; - Tone.TimelineSignal.prototype._exponentialInterpolate = function (t0, v0, t1, v1, t) { - v0 = Math.max(this._minOutput, v0); - return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0)); - }; - Tone.TimelineSignal.prototype._curveInterpolate = function (start, curve, duration, time) { - var len = curve.length; - if (time >= start + duration) { - return curve[len - 1]; - } else if (time <= start) { - return curve[0]; - } else { - var progress = (time - start) / duration; - var lowerIndex = Math.floor((len - 1) * progress); - var upperIndex = Math.ceil((len - 1) * progress); - var lowerVal = curve[lowerIndex]; - var upperVal = curve[upperIndex]; - if (upperIndex === lowerIndex) { - return lowerVal; + return new Tone.Time(val, units); + } + }; + Tone.extend(Tone.Time, Tone.TimeBase); + Tone.Time.prototype._unaryExpressions = Object.create( + Tone.TimeBase.prototype._unaryExpressions + ); + Tone.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (rh) { + return Tone.Transport.nextSubdivision(rh()); + }, + }; + Tone.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (lh) { + this._plusNow = true; + return lh(); + }, + }; + Tone.Time.prototype.quantize = function (subdiv, percent) { + percent = this.defaultArg(percent, 1); + this._expr = function (expr, subdivision, percent) { + expr = expr(); + subdivision = subdivision.toSeconds(); + var multiple = Math.round(expr / subdivision); + var ideal = multiple * subdivision; + var diff = ideal - expr; + return expr + diff * percent; + }.bind(this, this._expr, new this.constructor(subdiv), percent); + return this; + }; + Tone.Time.prototype.addNow = function () { + this._plusNow = true; + return this; + }; + Tone.Time.prototype._defaultExpr = function () { + this._plusNow = true; + return this._noOp; + }; + Tone.Time.prototype.copy = function (time) { + Tone.TimeBase.prototype.copy.call(this, time); + this._plusNow = time._plusNow; + return this; + }; + Tone.Time.prototype.toNotation = function () { + var time = this.toSeconds(); + var testNotations = ["1m", "2n", "4n", "8n", "16n", "32n", "64n", "128n"]; + var retNotation = this._toNotationHelper(time, testNotations); + var testTripletNotations = [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ]; + var retTripletNotation = this._toNotationHelper( + time, + testTripletNotations + ); + if ( + retTripletNotation.split("+").length < retNotation.split("+").length + ) { + return retTripletNotation; } else { - return this._linearInterpolate(lowerIndex, lowerVal, upperIndex, upperVal, progress * (len - 1)); + return retNotation; } - } - }; - Tone.TimelineSignal.prototype.dispose = function () { - Tone.Signal.prototype.dispose.call(this); - Tone.Param.prototype.dispose.call(this); - this._events.dispose(); - this._events = null; - }; - return Tone.TimelineSignal; -}(Tone_core_Tone, Tone_signal_Signal); -var envelope; -'use strict'; -envelope = function () { - var p5sound = master; - var Add = Tone_signal_Add; - var Mult = Tone_signal_Multiply; - var Scale = Tone_signal_Scale; - var TimelineSignal = Tone_signal_TimelineSignal; - /** - *

Envelopes are pre-defined amplitude distribution over time. - * Typically, envelopes are used to control the output volume - * of an object, a series of fades referred to as Attack, Decay, - * Sustain and Release ( - * ADSR - * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can - * control an Oscillator's frequency like this: osc.freq(env).

- *

Use setRange to change the attack/release level. - * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

- *

Use the play method to play the entire envelope, - * the ramp method for a pingable trigger, - * or triggerAttack/ - * triggerRelease to trigger noteOn/noteOff.

- * - * @class p5.Envelope - * @constructor - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope = function (t1, l1, t2, l2, t3, l3) { - /** - * Time until envelope reaches attackLevel - * @property attackTime - */ - this.aTime = t1 || 0.1; - /** - * Level once attack is complete. - * @property attackLevel - */ - this.aLevel = l1 || 1; - /** - * Time until envelope reaches decayLevel. - * @property decayTime - */ - this.dTime = t2 || 0.5; - /** - * Level after decay. The envelope will sustain here until it is released. - * @property decayLevel - */ - this.dLevel = l2 || 0; - /** - * Duration of the release portion of the envelope. - * @property releaseTime - */ - this.rTime = t3 || 0; - /** - * Level at the end of the release. - * @property releaseLevel - */ - this.rLevel = l3 || 0; - this._rampHighPercentage = 0.98; - this._rampLowPercentage = 0.02; - this.output = p5sound.audiocontext.createGain(); - this.control = new TimelineSignal(); - this._init(); - // this makes sure the envelope starts at zero - this.control.connect(this.output); - // connect to the output - this.connection = null; - // store connection - //array of math operation signal chaining - this.mathOps = [this.control]; - //whether envelope should be linear or exponential curve - this.isExponential = false; - // oscillator or buffer source to clear on env complete - // to save resources if/when it is retriggered - this.sourceToClear = null; - // set to true if attack is set, then false on release - this.wasTriggered = false; - // add to the soundArray so we can dispose of the env later - p5sound.soundArray.push(this); - }; - // this init function just smooths the starting value to zero and gives a start point for the timeline - // - it was necessary to remove glitches at the beginning. - p5.Envelope.prototype._init = function () { - var now = p5sound.audiocontext.currentTime; - var t = now; - this.control.setTargetAtTime(0.00001, t, 0.001); - //also, compute the correct time constants - this._setRampAD(this.aTime, this.dTime); - }; - /** - * Reset the envelope with a series of time/value pairs. - * - * @method set - * @param {Number} attackTime Time (in seconds) before level - * reaches attackLevel - * @param {Number} attackLevel Typically an amplitude between - * 0.0 and 1.0 - * @param {Number} decayTime Time - * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, - * decayLevel = sustainLevel) - * @param {Number} releaseTime Release Time (in seconds) - * @param {Number} releaseLevel Amplitude - * @example - *
- * var t1 = 0.1; // attack time in seconds - * var l1 = 0.7; // attack level 0.0 to 1.0 - * var t2 = 0.3; // decay time in seconds - * var l2 = 0.1; // decay level 0.0 to 1.0 - * var t3 = 0.2; // sustain time in seconds - * var l3 = 0.5; // sustain level 0.0 to 1.0 - * // release level defaults to zero - * - * var env; - * var triOsc; - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(t1, l1, t2, l2, t3, l3); - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); // give the env control of the triOsc's amp - * triOsc.start(); - * } - * - * // mouseClick triggers envelope if over canvas - * function mouseClicked() { - * // is mouse over canvas? - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * env.play(triOsc); - * } - * } - *
- * - */ - p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { - this.aTime = t1; - this.aLevel = l1; - this.dTime = t2 || 0; - this.dLevel = l2 || 0; - this.rTime = t3 || 0; - this.rLevel = l3 || 0; - // set time constants for ramp - this._setRampAD(t1, t2); - }; - /** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { - this.aTime = aTime; - this.dTime = dTime || 0; - // lerp - this.sPercent = sPercent || 0; - this.dLevel = typeof sPercent !== 'undefined' ? sPercent * (this.aLevel - this.rLevel) + this.rLevel : 0; - this.rTime = rTime || 0; - // also set time constants for ramp - this._setRampAD(aTime, dTime); - }; - /** - * Set max (attackLevel) and min (releaseLevel) of envelope. - * - * @method setRange - * @param {Number} aLevel attack level (defaults to 1) - * @param {Number} rLevel release level (defaults to 0) - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * env.play(); - * } - *
- */ - p5.Envelope.prototype.setRange = function (aLevel, rLevel) { - this.aLevel = aLevel || 1; - this.rLevel = rLevel || 0; - }; - // private (undocumented) method called when ADSR is set to set time constants for ramp - // - // Set the - // time constants for simple exponential ramps. - // The larger the time constant value, the slower the - // transition will be. - // - // method _setRampAD - // param {Number} attackTimeConstant attack time constant - // param {Number} decayTimeConstant decay time constant - // - p5.Envelope.prototype._setRampAD = function (t1, t2) { - this._rampAttackTime = this.checkExpInput(t1); - this._rampDecayTime = this.checkExpInput(t2); - var TCDenominator = 1; - /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) - TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage)); - this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1 / this._rampLowPercentage); - this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); - }; - // private method - p5.Envelope.prototype.setRampPercentages = function (p1, p2) { - //set the percentages that the simple exponential ramps go to - this._rampHighPercentage = this.checkExpInput(p1); - this._rampLowPercentage = this.checkExpInput(p2); - var TCDenominator = 1; - //now re-compute the time constants based on those percentages - /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) - TCDenominator = Math.log(1 / this.checkExpInput(1 - this._rampHighPercentage)); - this._rampAttackTC = this._rampAttackTime / this.checkExpInput(TCDenominator); - TCDenominator = Math.log(1 / this._rampLowPercentage); - this._rampDecayTC = this._rampDecayTime / this.checkExpInput(TCDenominator); - }; - /** - * Assign a parameter to be controlled by this envelope. - * If a p5.Sound object is given, then the p5.Envelope will control its - * output gain. If multiple inputs are provided, the env will - * control all of them. - * - * @method setInput - * @param {Object} [...inputs] A p5.sound object or - * Web Audio Param. - */ - p5.Envelope.prototype.setInput = function () { - for (var i = 0; i < arguments.length; i++) { - this.connect(arguments[i]); - } - }; - /** - * Set whether the envelope ramp is linear (default) or exponential. - * Exponential ramps can be useful because we perceive amplitude - * and frequency logarithmically. - * - * @method setExp - * @param {Boolean} isExp true is exponential, false is linear - */ - p5.Envelope.prototype.setExp = function (isExp) { - this.isExponential = isExp; - }; - //helper method to protect against zero values being sent to exponential functions - p5.Envelope.prototype.checkExpInput = function (value) { - if (value <= 0) { - value = 1e-8; - } - return value; - }; - /** - * Play tells the envelope to start acting on a given input. - * If the input is a p5.sound object (i.e. AudioIn, Oscillator, - * SoundFile), then Envelope will control its output volume. - * Envelopes can also be used to control any - * Web Audio Audio Param. - * - * @method play - * @param {Object} unit A p5.sound object or - * Web Audio Param. - * @param {Number} [startTime] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var susPercent = 0.2; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(playEnv); - * } - * - * function playEnv() { - * // trigger env on triOsc, 0 seconds from now - * // After decay, sustain for 0.2 seconds before release - * env.play(triOsc, 0, 0.2); - * } - *
- */ - p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) { - var tFromNow = secondsFromNow || 0; - var susTime = susTime || 0; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + }; + Tone.Time.prototype._toNotationHelper = function (units, testNotations) { + var threshold = this._notationToUnits( + testNotations[testNotations.length - 1] + ); + var retNotation = ""; + for (var i = 0; i < testNotations.length; i++) { + var notationTime = this._notationToUnits(testNotations[i]); + var multiple = units / notationTime; + var floatingPointError = 0.000001; + if (1 - (multiple % 1) < floatingPointError) { + multiple += floatingPointError; + } + multiple = Math.floor(multiple); + if (multiple > 0) { + if (multiple === 1) { + retNotation += testNotations[i]; + } else { + retNotation += multiple.toString() + "*" + testNotations[i]; + } + units -= multiple * notationTime; + if (units < threshold) { + break; + } else { + retNotation += " + "; + } + } } - } - this.triggerAttack(unit, tFromNow); - this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime); - }; - /** - * Trigger the Attack, and Decay portion of the Envelope. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. Input can be - * any p5.sound object, or a - * Web Audio Param. - * - * @method triggerAttack - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow time from now (in seconds) - * @example - *
- * - * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.3; - * var susPercent = 0.4; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * background(200); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(envAttack); - * } - * - * function envAttack() { - * console.log('trigger attack'); - * env.triggerAttack(); - * - * background(0,255,0); - * text('attack!', width/2, height/2); - * } - * - * function mouseReleased() { - * env.triggerRelease(); - * - * background(200); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - this.lastAttack = t; - this.wasTriggered = true; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + if (retNotation === "") { + retNotation = "0"; } - } - // get and set value (with linear ramp) to anchor automation - var valToSet = this.control.getValueAtTime(t); - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t); - } else { - this.control.linearRampToValueAtTime(valToSet, t); - } - // after each ramp completes, cancel scheduled values - // (so they can be overridden in case env has been re-triggered) - // then, set current value (with linearRamp to avoid click) - // then, schedule the next automation... - // attack - t += this.aTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.aLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.aLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - // decay to decay level (if using ADSR, then decay level == sustain level) - t += this.dTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.dLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.dLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - }; - /** - * Trigger the Release of the Envelope. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @method triggerRelease - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow time to trigger the release - * @example - *
- * - * var attackLevel = 1.0; - * var releaseLevel = 0; - * - * var attackTime = 0.001; - * var decayTime = 0.3; - * var susPercent = 0.4; - * var releaseTime = 0.5; - * - * var env, triOsc; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * background(200); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime, susPercent, releaseTime); - * env.setRange(attackLevel, releaseLevel); - * - * triOsc = new p5.Oscillator('triangle'); - * triOsc.amp(env); - * triOsc.start(); - * triOsc.freq(220); - * - * cnv.mousePressed(envAttack); - * } - * - * function envAttack() { - * console.log('trigger attack'); - * env.triggerAttack(); - * - * background(0,255,0); - * text('attack!', width/2, height/2); - * } - * - * function mouseReleased() { - * env.triggerRelease(); - * - * background(200); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) { - // only trigger a release if an attack was triggered - if (!this.wasTriggered) { - // this currently causes a bit of trouble: - // if a later release has been scheduled (via the play function) - // a new earlier release won't interrupt it, because - // this.wasTriggered has already been set to false. - // If we want new earlier releases to override, then we need to - // keep track of the last release time, and if the new release time is - // earlier, then use it. - return; - } - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + return retNotation; + }; + Tone.Time.prototype._notationToUnits = function (notation) { + var primaryExprs = this._primaryExpressions; + var notationExprs = [primaryExprs.n, primaryExprs.t, primaryExprs.m]; + for (var i = 0; i < notationExprs.length; i++) { + var expr = notationExprs[i]; + var match = notation.match(expr.regexp); + if (match) { + return expr.method.call(this, match[1]); + } } - } - // get and set value (with linear or exponential ramp) to anchor automation - var valToSet = this.control.getValueAtTime(t); - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(valToSet), t); - } else { - this.control.linearRampToValueAtTime(valToSet, t); - } - // release - t += this.rTime; - if (this.isExponential === true) { - this.control.exponentialRampToValueAtTime(this.checkExpInput(this.rLevel), t); - valToSet = this.checkExpInput(this.control.getValueAtTime(t)); - this.control.cancelScheduledValues(t); - this.control.exponentialRampToValueAtTime(valToSet, t); - } else { - this.control.linearRampToValueAtTime(this.rLevel, t); - valToSet = this.control.getValueAtTime(t); - this.control.cancelScheduledValues(t); - this.control.linearRampToValueAtTime(valToSet, t); - } - this.wasTriggered = false; - }; - /** - * Exponentially ramp to a value using the first two - * values from setADSR(attackTime, decayTime) - * as - * time constants for simple exponential ramps. - * If the value is higher than current value, it uses attackTime, - * while a decrease uses decayTime. - * - * @method ramp - * @param {Object} unit p5.sound Object or Web Audio Param - * @param {Number} secondsFromNow When to trigger the ramp - * @param {Number} v Target value - * @param {Number} [v2] Second target value (optional) - * @example - *
- * var env, osc, amp, cnv; - * - * var attackTime = 0.001; - * var decayTime = 0.2; - * var attackLevel = 1; - * var decayLevel = 0; - * - * function setup() { - * cnv = createCanvas(100, 100); - * fill(0,255,0); - * noStroke(); - * - * env = new p5.Envelope(); - * env.setADSR(attackTime, decayTime); - * - * osc = new p5.Oscillator(); - * osc.amp(env); - * osc.start(); - * - * amp = new p5.Amplitude(); - * - * cnv.mousePressed(triggerRamp); - * } - * - * function triggerRamp() { - * env.ramp(osc, 0, attackLevel, decayLevel); - * } - * - * function draw() { - * background(20,20,20); - * text('click me', 10, 20); - * var h = map(amp.getLevel(), 0, 0.4, 0, height);; - * - * rect(0, height, width, -h); - * } - *
- */ - p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - var destination1 = this.checkExpInput(v1); - var destination2 = typeof v2 !== 'undefined' ? this.checkExpInput(v2) : undefined; - // connect env to unit if not already connected - if (unit) { - if (this.connection !== unit) { - this.connect(unit); + }; + Tone.Time.prototype.toBarsBeatsSixteenths = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.toSeconds() / quarterTime; + var measures = Math.floor(quarters / this._timeSignature()); + var sixteenths = (quarters % 1) * 4; + quarters = Math.floor(quarters) % this._timeSignature(); + sixteenths = sixteenths.toString(); + if (sixteenths.length > 3) { + sixteenths = parseFloat(sixteenths).toFixed(3); + } + var progress = [measures, quarters, sixteenths]; + return progress.join(":"); + }; + Tone.Time.prototype.toTicks = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.valueOf() / quarterTime; + return Math.floor(quarters * Tone.Transport.PPQ); + }; + Tone.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }; + Tone.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }; + Tone.Time.prototype.toSeconds = function () { + return this.valueOf(); + }; + Tone.Time.prototype.toMilliseconds = function () { + return this.toSeconds() * 1000; + }; + Tone.Time.prototype.valueOf = function () { + var val = this._expr(); + return val + (this._plusNow ? this.now() : 0); + }; + return Tone.Time; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Frequency; + Tone_type_Frequency = (function (Tone) { + Tone.Frequency = function (val, units) { + if (this instanceof Tone.Frequency) { + Tone.TimeBase.call(this, val, units); + } else { + return new Tone.Frequency(val, units); } - } - //get current value - var currentVal = this.checkExpInput(this.control.getValueAtTime(t)); - // this.control.cancelScheduledValues(t); - //if it's going up - if (destination1 > currentVal) { - this.control.setTargetAtTime(destination1, t, this._rampAttackTC); - t += this._rampAttackTime; - } else if (destination1 < currentVal) { - this.control.setTargetAtTime(destination1, t, this._rampDecayTC); - t += this._rampDecayTime; - } - // Now the second part of envelope begins - if (destination2 === undefined) - return; - //if it's going up - if (destination2 > destination1) { - this.control.setTargetAtTime(destination2, t, this._rampAttackTC); - } else if (destination2 < destination1) { - this.control.setTargetAtTime(destination2, t, this._rampDecayTC); - } - }; - p5.Envelope.prototype.connect = function (unit) { - this.connection = unit; - // assume we're talking about output gain - // unless given a different audio param - if (unit instanceof p5.Oscillator || unit instanceof p5.SoundFile || unit instanceof p5.AudioIn || unit instanceof p5.Reverb || unit instanceof p5.Noise || unit instanceof p5.Filter || unit instanceof p5.Delay) { - unit = unit.output.gain; - } - if (unit instanceof AudioParam) { - //set the initial value - unit.setValueAtTime(0, p5sound.audiocontext.currentTime); - } - if (unit instanceof p5.Signal) { - unit.setValue(0); - } - this.output.connect(unit); - }; - p5.Envelope.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - // Signal Math - /** - * Add a value to the p5.Oscillator's output amplitude, - * and return the oscillator. Calling this method - * again will override the initial add() with new values. - * - * @method add - * @param {Number} number Constant number to add - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.add = function (num) { - var add = new Add(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, add, thisChain, nextChain, Add); - }; - /** - * Multiply the p5.Envelope's output amplitude - * by a fixed value. Calling this method - * again will override the initial mult() with new values. - * - * @method mult - * @param {Number} number Constant number to multiply - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.mult = function (num) { - var mult = new Mult(num); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult); - }; - /** - * Scale this envelope's amplitude values to a given - * range, and return the envelope. Calling this method - * again will override the initial scale() with new values. - * - * @method scale - * @param {Number} inMin input range minumum - * @param {Number} inMax input range maximum - * @param {Number} outMin input range minumum - * @param {Number} outMax input range maximum - * @return {p5.Envelope} Envelope Returns this envelope - * with scaled output - */ - p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { - var scale = new Scale(inMin, inMax, outMin, outMax); - var thisChain = this.mathOps.length; - var nextChain = this.output; - return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale); - }; - // get rid of the oscillator - p5.Envelope.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.disconnect(); - if (this.control) { - this.control.dispose(); - this.control = null; - } - for (var i = 1; i < this.mathOps.length; i++) { - this.mathOps[i].dispose(); - } - }; - // Different name for backwards compatibility, replicates p5.Envelope class - p5.Env = function (t1, l1, t2, l2, t3, l3) { - console.warn('WARNING: p5.Env is now deprecated and may be removed in future versions. ' + 'Please use the new p5.Envelope instead.'); - p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); - }; - p5.Env.prototype = Object.create(p5.Envelope.prototype); -}(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale, Tone_signal_TimelineSignal); -var pulse; -'use strict'; -pulse = function () { - var p5sound = master; - /** - * Creates a Pulse object, an oscillator that implements - * Pulse Width Modulation. - * The pulse is created with two oscillators. - * Accepts a parameter for frequency, and to set the - * width between the pulses. See - * p5.Oscillator for a full list of methods. - * - * @class p5.Pulse - * @extends p5.Oscillator - * @constructor - * @param {Number} [freq] Frequency in oscillations per second (Hz) - * @param {Number} [w] Width between the pulses (0 to 1.0, - * defaults to 0) - * @example - *
- * var pulse; - * function setup() { - * background(0); - * - * // Create and start the pulse wave oscillator - * pulse = new p5.Pulse(); - * pulse.amp(0.5); - * pulse.freq(220); - * pulse.start(); - * } - * - * function draw() { - * var w = map(mouseX, 0, width, 0, 1); - * w = constrain(w, 0, 1); - * pulse.width(w) - * } - *
- */ - p5.Pulse = function (freq, w) { - p5.Oscillator.call(this, freq, 'sawtooth'); - // width of PWM, should be betw 0 to 1.0 - this.w = w || 0; - // create a second oscillator with inverse frequency - this.osc2 = new p5.SawOsc(freq); - // create a delay node - this.dNode = p5sound.audiocontext.createDelay(); - // dc offset - this.dcOffset = createDCOffset(); - this.dcGain = p5sound.audiocontext.createGain(); - this.dcOffset.connect(this.dcGain); - this.dcGain.connect(this.output); - // set delay time based on PWM width - this.f = freq || 440; - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - // disconnect osc2 and connect it to delay, which is connected to output - this.osc2.disconnect(); - this.osc2.panner.disconnect(); - this.osc2.amp(-1); - // inverted amplitude - this.osc2.output.connect(this.dNode); - this.dNode.connect(this.output); - this.output.gain.value = 1; - this.output.connect(this.panner); - }; - p5.Pulse.prototype = Object.create(p5.Oscillator.prototype); - /** - * Set the width of a Pulse object (an oscillator that implements - * Pulse Width Modulation). - * - * @method width - * @param {Number} [width] Width between the pulses (0 to 1.0, - * defaults to 0) - */ - p5.Pulse.prototype.width = function (w) { - if (typeof w === 'number') { - if (w <= 1 && w >= 0) { - this.w = w; - // set delay time based on PWM width - // var mW = map(this.w, 0, 1.0, 0, 1/this.f); - var mW = this.w / this.oscillator.frequency.value; - this.dNode.delayTime.value = mW; + }; + Tone.extend(Tone.Frequency, Tone.TimeBase); + Tone.Frequency.prototype._primaryExpressions = Object.create( + Tone.TimeBase.prototype._primaryExpressions + ); + Tone.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (value) { + return this.midiToFrequency(value); + }, + }; + Tone.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (pitch, octave) { + var index = noteToScaleIndex[pitch.toLowerCase()]; + var noteNumber = index + (parseInt(octave) + 1) * 12; + return this.midiToFrequency(noteNumber); + }, + }; + Tone.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (m, q, s) { + var total = 1; + if (m && m !== "0") { + total *= this._beatsToUnits(this._timeSignature() * parseFloat(m)); + } + if (q && q !== "0") { + total *= this._beatsToUnits(parseFloat(q)); + } + if (s && s !== "0") { + total *= this._beatsToUnits(parseFloat(s) / 4); + } + return total; + }, + }; + Tone.Frequency.prototype.transpose = function (interval) { + this._expr = function (expr, interval) { + var val = expr(); + return val * this.intervalToFrequencyRatio(interval); + }.bind(this, this._expr, interval); + return this; + }; + Tone.Frequency.prototype.harmonize = function (intervals) { + this._expr = function (expr, intervals) { + var val = expr(); + var ret = []; + for (var i = 0; i < intervals.length; i++) { + ret[i] = val * this.intervalToFrequencyRatio(intervals[i]); + } + return ret; + }.bind(this, this._expr, intervals); + return this; + }; + Tone.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }; + Tone.Frequency.prototype.toNote = function () { + var freq = this.valueOf(); + var log = Math.log(freq / Tone.Frequency.A4) / Math.LN2; + var noteNumber = Math.round(12 * log) + 57; + var octave = Math.floor(noteNumber / 12); + if (octave < 0) { + noteNumber += -12 * octave; + } + var noteName = scaleIndexToNote[noteNumber % 12]; + return noteName + octave.toString(); + }; + Tone.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }; + Tone.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }; + Tone.Frequency.prototype.toTicks = function () { + var quarterTime = this._beatsToUnits(1); + var quarters = this.valueOf() / quarterTime; + return Math.floor(quarters * Tone.Transport.PPQ); + }; + Tone.Frequency.prototype._frequencyToUnits = function (freq) { + return freq; + }; + Tone.Frequency.prototype._ticksToUnits = function (ticks) { + return ( + 1 / ((ticks * 60) / (Tone.Transport.bpm.value * Tone.Transport.PPQ)) + ); + }; + Tone.Frequency.prototype._beatsToUnits = function (beats) { + return 1 / Tone.TimeBase.prototype._beatsToUnits.call(this, beats); + }; + Tone.Frequency.prototype._secondsToUnits = function (seconds) { + return 1 / seconds; + }; + Tone.Frequency.prototype._defaultUnits = "hz"; + var noteToScaleIndex = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }; + var scaleIndexToNote = [ + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B", + ]; + Tone.Frequency.A4 = 440; + Tone.Frequency.prototype.midiToFrequency = function (midi) { + return Tone.Frequency.A4 * Math.pow(2, (midi - 69) / 12); + }; + Tone.Frequency.prototype.frequencyToMidi = function (frequency) { + return 69 + (12 * Math.log(frequency / Tone.Frequency.A4)) / Math.LN2; + }; + return Tone.Frequency; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_TransportTime; + Tone_type_TransportTime = (function (Tone) { + Tone.TransportTime = function (val, units) { + if (this instanceof Tone.TransportTime) { + Tone.Time.call(this, val, units); + } else { + return new Tone.TransportTime(val, units); } - this.dcGain.gain.value = 1.7 * (0.5 - this.w); - } else { - w.connect(this.dNode.delayTime); - var sig = new p5.SignalAdd(-0.5); - sig.setInput(w); - sig = sig.mult(-1); - sig = sig.mult(1.7); - sig.connect(this.dcGain.gain); - } - }; - p5.Pulse.prototype.start = function (f, time) { - var now = p5sound.audiocontext.currentTime; - var t = time || 0; - if (!this.started) { - var freq = f || this.f; - var type = this.oscillator.type; - this.oscillator = p5sound.audiocontext.createOscillator(); - this.oscillator.frequency.setValueAtTime(freq, now); - this.oscillator.type = type; - this.oscillator.connect(this.output); - this.oscillator.start(t + now); - // set up osc2 - this.osc2.oscillator = p5sound.audiocontext.createOscillator(); - this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); - this.osc2.oscillator.type = type; - this.osc2.oscillator.connect(this.osc2.output); - this.osc2.start(t + now); - this.freqNode = [ - this.oscillator.frequency, - this.osc2.oscillator.frequency - ]; - // start dcOffset, too - this.dcOffset = createDCOffset(); - this.dcOffset.connect(this.dcGain); - this.dcOffset.start(t + now); - // if LFO connections depend on these oscillators - if (this.mods !== undefined && this.mods.frequency !== undefined) { - this.mods.frequency.connect(this.freqNode[0]); - this.mods.frequency.connect(this.freqNode[1]); + }; + Tone.extend(Tone.TransportTime, Tone.Time); + Tone.TransportTime.prototype._unaryExpressions = Object.create( + Tone.Time.prototype._unaryExpressions + ); + Tone.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (rh) { + var subdivision = this._secondsToTicks(rh()); + var multiple = Math.ceil(Tone.Transport.ticks / subdivision); + return this._ticksToUnits(multiple * subdivision); + }, + }; + Tone.TransportTime.prototype._secondsToTicks = function (seconds) { + var quarterTime = this._beatsToUnits(1); + var quarters = seconds / quarterTime; + return Math.round(quarters * Tone.Transport.PPQ); + }; + Tone.TransportTime.prototype.valueOf = function () { + var val = this._secondsToTicks(this._expr()); + return val + (this._plusNow ? Tone.Transport.ticks : 0); + }; + Tone.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }; + Tone.TransportTime.prototype.toSeconds = function () { + var val = this._expr(); + return val + (this._plusNow ? Tone.Transport.seconds : 0); + }; + Tone.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }; + return Tone.TransportTime; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_type_Type; + Tone_type_Type = (function (Tone) { + Tone.Type = { + Default: "number", + Time: "time", + Frequency: "frequency", + TransportTime: "transportTime", + Ticks: "ticks", + NormalRange: "normalRange", + AudioRange: "audioRange", + Decibels: "db", + Interval: "interval", + BPM: "bpm", + Positive: "positive", + Cents: "cents", + Degrees: "degrees", + MIDI: "midi", + BarsBeatsSixteenths: "barsBeatsSixteenths", + Samples: "samples", + Hertz: "hertz", + Note: "note", + Milliseconds: "milliseconds", + Seconds: "seconds", + Notation: "notation", + }; + Tone.prototype.toSeconds = function (time) { + if (this.isNumber(time)) { + return time; + } else if (this.isUndef(time)) { + return this.now(); + } else if (this.isString(time)) { + return new Tone.Time(time).toSeconds(); + } else if (time instanceof Tone.TimeBase) { + return time.toSeconds(); } - this.started = true; - this.osc2.started = true; - } - }; - p5.Pulse.prototype.stop = function (time) { - if (this.started) { - var t = time || 0; - var now = p5sound.audiocontext.currentTime; - this.oscillator.stop(t + now); - if (this.osc2.oscillator) { - this.osc2.oscillator.stop(t + now); + }; + Tone.prototype.toFrequency = function (freq) { + if (this.isNumber(freq)) { + return freq; + } else if (this.isString(freq) || this.isUndef(freq)) { + return new Tone.Frequency(freq).valueOf(); + } else if (freq instanceof Tone.TimeBase) { + return freq.toFrequency(); } - this.dcOffset.stop(t + now); - this.started = false; - this.osc2.started = false; - } - }; - p5.Pulse.prototype.freq = function (val, rampTime, tFromNow) { - if (typeof val === 'number') { - this.f = val; - var now = p5sound.audiocontext.currentTime; - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var currentFreq = this.oscillator.frequency.value; - this.oscillator.frequency.cancelScheduledValues(now); - this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - this.osc2.oscillator.frequency.cancelScheduledValues(now); - this.osc2.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); - this.osc2.oscillator.frequency.exponentialRampToValueAtTime(val, tFromNow + rampTime + now); - if (this.freqMod) { - this.freqMod.output.disconnect(); - this.freqMod = null; - } - } else if (val.output) { - val.output.disconnect(); - val.output.connect(this.oscillator.frequency); - val.output.connect(this.osc2.oscillator.frequency); - this.freqMod = val; - } - }; - // inspiration: http://webaudiodemos.appspot.com/oscilloscope/ - function createDCOffset() { - var ac = p5sound.audiocontext; - var buffer = ac.createBuffer(1, 2048, ac.sampleRate); - var data = buffer.getChannelData(0); - for (var i = 0; i < 2048; i++) - data[i] = 1; - var bufferSource = ac.createBufferSource(); - bufferSource.buffer = buffer; - bufferSource.loop = true; - return bufferSource; - } -}(master, oscillator); -var noise; -'use strict'; -noise = function () { - var p5sound = master; - /** - * Noise is a type of oscillator that generates a buffer with random values. - * - * @class p5.Noise - * @extends p5.Oscillator - * @constructor - * @param {String} type Type of noise can be 'white' (default), - * 'brown' or 'pink'. - */ - p5.Noise = function (type) { - var assignType; - p5.Oscillator.call(this); - delete this.f; - delete this.freq; - delete this.oscillator; - if (type === 'brown') { - assignType = _brownNoise; - } else if (type === 'pink') { - assignType = _pinkNoise; - } else { - assignType = _whiteNoise; - } - this.buffer = assignType; - }; - p5.Noise.prototype = Object.create(p5.Oscillator.prototype); - // generate noise buffers - var _whiteNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var whiteBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = whiteBuffer.getChannelData(0); - for (var i = 0; i < bufferSize; i++) { - noiseData[i] = Math.random() * 2 - 1; - } - whiteBuffer.type = 'white'; - return whiteBuffer; - }(); - var _pinkNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var pinkBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = pinkBuffer.getChannelData(0); - var b0, b1, b2, b3, b4, b5, b6; - b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0; - for (var i = 0; i < bufferSize; i++) { - var white = Math.random() * 2 - 1; - b0 = 0.99886 * b0 + white * 0.0555179; - b1 = 0.99332 * b1 + white * 0.0750759; - b2 = 0.969 * b2 + white * 0.153852; - b3 = 0.8665 * b3 + white * 0.3104856; - b4 = 0.55 * b4 + white * 0.5329522; - b5 = -0.7616 * b5 - white * 0.016898; - noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362; - noiseData[i] *= 0.11; - // (roughly) compensate for gain - b6 = white * 0.115926; - } - pinkBuffer.type = 'pink'; - return pinkBuffer; - }(); - var _brownNoise = function () { - var bufferSize = 2 * p5sound.audiocontext.sampleRate; - var brownBuffer = p5sound.audiocontext.createBuffer(1, bufferSize, p5sound.audiocontext.sampleRate); - var noiseData = brownBuffer.getChannelData(0); - var lastOut = 0; - for (var i = 0; i < bufferSize; i++) { - var white = Math.random() * 2 - 1; - noiseData[i] = (lastOut + 0.02 * white) / 1.02; - lastOut = noiseData[i]; - noiseData[i] *= 3.5; - } - brownBuffer.type = 'brown'; - return brownBuffer; - }(); - /** - * Set type of noise to 'white', 'pink' or 'brown'. - * White is the default. - * - * @method setType - * @param {String} [type] 'white', 'pink' or 'brown' - */ - p5.Noise.prototype.setType = function (type) { - switch (type) { - case 'white': - this.buffer = _whiteNoise; - break; - case 'pink': - this.buffer = _pinkNoise; - break; - case 'brown': - this.buffer = _brownNoise; - break; - default: - this.buffer = _whiteNoise; - } - if (this.started) { - var now = p5sound.audiocontext.currentTime; - this.stop(now); - this.start(now + 0.01); - } - }; - p5.Noise.prototype.getType = function () { - return this.buffer.type; - }; - p5.Noise.prototype.start = function () { - if (this.started) { - this.stop(); - } - this.noise = p5sound.audiocontext.createBufferSource(); - this.noise.buffer = this.buffer; - this.noise.loop = true; - this.noise.connect(this.output); - var now = p5sound.audiocontext.currentTime; - this.noise.start(now); - this.started = true; - }; - p5.Noise.prototype.stop = function () { - var now = p5sound.audiocontext.currentTime; - if (this.noise) { - this.noise.stop(now); - this.started = false; - } - }; - p5.Noise.prototype.dispose = function () { - var now = p5sound.audiocontext.currentTime; - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.noise) { - this.noise.disconnect(); - this.stop(now); - } - if (this.output) { - this.output.disconnect(); - } - if (this.panner) { - this.panner.disconnect(); - } - this.output = null; - this.panner = null; - this.buffer = null; - this.noise = null; - }; -}(master); -var audioin; -'use strict'; -audioin = function () { - var p5sound = master; - // an array of input sources - p5sound.inputSources = []; - /** - *

Get audio from an input, i.e. your computer's microphone.

- * - *

Turn the mic on/off with the start() and stop() methods. When the mic - * is on, its volume can be measured with getLevel or by connecting an - * FFT object.

- * - *

If you want to hear the AudioIn, use the .connect() method. - * AudioIn does not connect to p5.sound output by default to prevent - * feedback.

- * - *

Note: This uses the getUserMedia/ - * Stream API, which is not supported by certain browsers. Access in Chrome browser - * is limited to localhost and https, but access over http may be limited.

- * - * @class p5.AudioIn - * @constructor - * @param {Function} [errorCallback] A function to call if there is an error - * accessing the AudioIn. For example, - * Safari and iOS devices do not - * currently allow microphone access. - * @example - *
- * var mic; - * function setup(){ - * mic = new p5.AudioIn() - * mic.start(); - * } - * function draw(){ - * background(0); - * micLevel = mic.getLevel(); - * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10); - * } - *
- */ - p5.AudioIn = function (errorCallback) { - // set up audio input - /** - * @property {GainNode} input - */ - this.input = p5sound.audiocontext.createGain(); - /** - * @property {GainNode} output - */ - this.output = p5sound.audiocontext.createGain(); - /** - * @property {MediaStream|null} stream - */ - this.stream = null; - /** - * @property {MediaStreamAudioSourceNode|null} mediaStream - */ - this.mediaStream = null; - /** - * @property {Number|null} currentSource - */ - this.currentSource = null; - /** - * Client must allow browser to access their microphone / audioin source. - * Default: false. Will become true when the client enables acces. - * - * @property {Boolean} enabled - */ - this.enabled = false; - /** - * Input amplitude, connect to it by default but not to master out - * - * @property {p5.Amplitude} amplitude - */ - this.amplitude = new p5.Amplitude(); - this.output.connect(this.amplitude.input); - if (!window.MediaStreamTrack || !window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { - errorCallback ? errorCallback() : window.alert('This browser does not support MediaStreamTrack and mediaDevices'); - } - // add to soundArray so we can dispose on close - p5sound.soundArray.push(this); - }; - /** - * Start processing audio input. This enables the use of other - * AudioIn methods like getLevel(). Note that by default, AudioIn - * is not connected to p5.sound's output. So you won't hear - * anything unless you use the connect() method.
- * - * Certain browsers limit access to the user's microphone. For example, - * Chrome only allows access from localhost and over https. For this reason, - * you may want to include an errorCallback—a function that is called in case - * the browser won't provide mic access. - * - * @method start - * @param {Function} [successCallback] Name of a function to call on - * success. - * @param {Function} [errorCallback] Name of a function to call if - * there was an error. For example, - * some browsers do not support - * getUserMedia. - */ - p5.AudioIn.prototype.start = function (successCallback, errorCallback) { - var self = this; - if (this.stream) { - this.stop(); - } - // set the audio source - var audioSource = p5sound.inputSources[self.currentSource]; - var constraints = { - audio: { - sampleRate: p5sound.audiocontext.sampleRate, - echoCancellation: false + }; + Tone.prototype.toTicks = function (time) { + if (this.isNumber(time) || this.isString(time)) { + return new Tone.TransportTime(time).toTicks(); + } else if (this.isUndef(time)) { + return Tone.Transport.ticks; + } else if (time instanceof Tone.TimeBase) { + return time.toTicks(); } }; - // if developers determine which source to use - if (p5sound.inputSources[this.currentSource]) { - constraints.audio.deviceId = audioSource.deviceId; - } - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - self.stream = stream; - self.enabled = true; - // Wrap a MediaStreamSourceNode around the live input - self.mediaStream = p5sound.audiocontext.createMediaStreamSource(stream); - self.mediaStream.connect(self.output); - // only send to the Amplitude reader, so we can see it but not hear it. - self.amplitude.setInput(self.output); - if (successCallback) - successCallback(); - }).catch(function (err) { - if (errorCallback) - errorCallback(err); - else - console.error(err); - }); - }; - /** - * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). - * If re-starting, the user may be prompted for permission access. - * - * @method stop - */ - p5.AudioIn.prototype.stop = function () { - if (this.stream) { - this.stream.getTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.disconnect(); - delete this.mediaStream; - delete this.stream; - } - }; - /** - * Connect to an audio unit. If no parameter is provided, will - * connect to the master output (i.e. your speakers).
- * - * @method connect - * @param {Object} [unit] An object that accepts audio input, - * such as an FFT - */ - p5.AudioIn.prototype.connect = function (unit) { - if (unit) { - if (unit.hasOwnProperty('input')) { - this.output.connect(unit.input); - } else if (unit.hasOwnProperty('analyser')) { - this.output.connect(unit.analyser); - } else { - this.output.connect(unit); + return Tone; + })( + Tone_core_Tone, + Tone_type_Time, + Tone_type_Frequency, + Tone_type_TransportTime + ); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Param; + Tone_core_Param = (function (Tone) { + "use strict"; + Tone.Param = function () { + var options = this.optionsObject( + arguments, + ["param", "units", "convert"], + Tone.Param.defaults + ); + this._param = this.input = options.param; + this.units = options.units; + this.convert = options.convert; + this.overridden = false; + this._lfo = null; + if (this.isObject(options.lfo)) { + this.value = options.lfo; + } else if (!this.isUndef(options.value)) { + this.value = options.value; } - } else { - this.output.connect(p5sound.input); - } - }; - /** - * Disconnect the AudioIn from all audio units. For example, if - * connect() had been called, disconnect() will stop sending - * signal to your speakers.
- * - * @method disconnect - */ - p5.AudioIn.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - // stay connected to amplitude even if not outputting to p5 - this.output.connect(this.amplitude.input); - } - }; - /** - * Read the Amplitude (volume level) of an AudioIn. The AudioIn - * class contains its own instance of the Amplitude class to help - * make it easy to get a microphone's volume level. Accepts an - * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must - * .start() before using .getLevel().
- * - * @method getLevel - * @param {Number} [smoothing] Smoothing is 0.0 by default. - * Smooths values based on previous values. - * @return {Number} Volume level (between 0.0 and 1.0) - */ - p5.AudioIn.prototype.getLevel = function (smoothing) { - if (smoothing) { - this.amplitude.smoothing = smoothing; - } - return this.amplitude.getLevel(); - }; - /** - * Set amplitude (volume) of a mic input between 0 and 1.0.
- * - * @method amp - * @param {Number} vol between 0 and 1.0 - * @param {Number} [time] ramp time (optional) - */ - p5.AudioIn.prototype.amp = function (vol, t) { - if (t) { - var rampTime = t || 0; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime); - this.output.gain.setValueAtTime(currentVol, p5sound.audiocontext.currentTime); - this.output.gain.linearRampToValueAtTime(vol, rampTime + p5sound.audiocontext.currentTime); - } else { - this.output.gain.cancelScheduledValues(p5sound.audiocontext.currentTime); - this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime); - } - }; - /** - * Returns a list of available input sources. This is a wrapper - * for and it returns a Promise. - * - * @method getSources - * @param {Function} [successCallback] This callback function handles the sources when they - * have been enumerated. The callback function - * receives the deviceList array as its only argument - * @param {Function} [errorCallback] This optional callback receives the error - * message as its argument. - * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar - * to the enumerateDevices() method - * @example - *
- * var audiograb; - * - * function setup(){ - * //new audioIn - * audioGrab = new p5.AudioIn(); - * - * audioGrab.getSources(function(deviceList) { - * //print out the array of available sources - * console.log(deviceList); - * //set the source to the first item in the deviceList array - * audioGrab.setSource(0); - * }); - * } - *
- */ - p5.AudioIn.prototype.getSources = function (onSuccess, onError) { - return new Promise(function (resolve, reject) { - window.navigator.mediaDevices.enumerateDevices().then(function (devices) { - p5sound.inputSources = devices.filter(function (device) { - return device.kind === 'audioinput'; - }); - resolve(p5sound.inputSources); - if (onSuccess) { - onSuccess(p5sound.inputSources); - } - }).catch(function (error) { - reject(error); - if (onError) { - onError(error); + }; + Tone.extend(Tone.Param); + Tone.Param.defaults = { + units: Tone.Type.Default, + convert: true, + param: undefined, + }; + Object.defineProperty(Tone.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (value) { + if (this.isObject(value)) { + if (this.isUndef(Tone.LFO)) { + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + } + if (this._lfo) { + this._lfo.dispose(); + } + this._lfo = new Tone.LFO(value).start(); + this._lfo.connect(this.input); } else { - console.error('This browser does not support MediaStreamTrack.getSources()'); + var convertedVal = this._fromUnits(value); + this._param.cancelScheduledValues(0); + this._param.value = convertedVal; } - }); + }, }); - }; - /** - * Set the input source. Accepts a number representing a - * position in the array returned by getSources(). - * This is only available in browsers that support - *
navigator.mediaDevices.enumerateDevices().
- * - * @method setSource - * @param {number} num position of input source in the array - */ - p5.AudioIn.prototype.setSource = function (num) { - if (p5sound.inputSources.length > 0 && num < p5sound.inputSources.length) { - // set the current source - this.currentSource = num; - console.log('set source to ', p5sound.inputSources[this.currentSource]); - } else { - console.log('unable to set input source'); - } - // restart stream if currently active - if (this.stream && this.stream.active) { - this.start(); - } - }; - // private method - p5.AudioIn.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.stop(); - if (this.output) { - this.output.disconnect(); - } - if (this.amplitude) { - this.amplitude.disconnect(); - } - delete this.amplitude; - delete this.output; - }; -}(master); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Negate; -Tone_signal_Negate = function (Tone) { - 'use strict'; - Tone.Negate = function () { - this._multiply = this.input = this.output = new Tone.Multiply(-1); - }; - Tone.extend(Tone.Negate, Tone.SignalBase); - Tone.Negate.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._multiply.dispose(); - this._multiply = null; - return this; - }; - return Tone.Negate; -}(Tone_core_Tone, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Subtract; -Tone_signal_Subtract = function (Tone) { - 'use strict'; - Tone.Subtract = function (value) { - this.createInsOuts(2, 0); - this._sum = this.input[0] = this.output = new Tone.Gain(); - this._neg = new Tone.Negate(); - this._param = this.input[1] = new Tone.Signal(value); - this._param.chain(this._neg, this._sum); - }; - Tone.extend(Tone.Subtract, Tone.Signal); - Tone.Subtract.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._neg.dispose(); - this._neg = null; - this._sum.disconnect(); - this._sum = null; - this._param.dispose(); - this._param = null; - return this; - }; - return Tone.Subtract; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Negate, Tone_signal_Signal); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_GreaterThanZero; -Tone_signal_GreaterThanZero = function (Tone) { - 'use strict'; - Tone.GreaterThanZero = function () { - this._thresh = this.output = new Tone.WaveShaper(function (val) { - if (val <= 0) { - return 0; + Tone.Param.prototype._fromUnits = function (val) { + if (this.convert || this.isUndef(this.convert)) { + switch (this.units) { + case Tone.Type.Time: + return this.toSeconds(val); + case Tone.Type.Frequency: + return this.toFrequency(val); + case Tone.Type.Decibels: + return this.dbToGain(val); + case Tone.Type.NormalRange: + return Math.min(Math.max(val, 0), 1); + case Tone.Type.AudioRange: + return Math.min(Math.max(val, -1), 1); + case Tone.Type.Positive: + return Math.max(val, 0); + default: + return val; + } } else { - return 1; - } - }, 127); - this._scale = this.input = new Tone.Multiply(10000); - this._scale.connect(this._thresh); - }; - Tone.extend(Tone.GreaterThanZero, Tone.SignalBase); - Tone.GreaterThanZero.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._scale.dispose(); - this._scale = null; - this._thresh.dispose(); - this._thresh = null; - return this; - }; - return Tone.GreaterThanZero; -}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_GreaterThan; -Tone_signal_GreaterThan = function (Tone) { - 'use strict'; - Tone.GreaterThan = function (value) { - this.createInsOuts(2, 0); - this._param = this.input[0] = new Tone.Subtract(value); - this.input[1] = this._param.input[1]; - this._gtz = this.output = new Tone.GreaterThanZero(); - this._param.connect(this._gtz); - }; - Tone.extend(Tone.GreaterThan, Tone.Signal); - Tone.GreaterThan.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._param.dispose(); - this._param = null; - this._gtz.dispose(); - this._gtz = null; - return this; - }; - return Tone.GreaterThan; -}(Tone_core_Tone, Tone_signal_GreaterThanZero, Tone_signal_Subtract); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Abs; -Tone_signal_Abs = function (Tone) { - 'use strict'; - Tone.Abs = function () { - this._abs = this.input = this.output = new Tone.WaveShaper(function (val) { - if (val === 0) { - return 0; + return val; + } + }; + Tone.Param.prototype._toUnits = function (val) { + if (this.convert || this.isUndef(this.convert)) { + switch (this.units) { + case Tone.Type.Decibels: + return this.gainToDb(val); + default: + return val; + } } else { - return Math.abs(val); - } - }, 127); - }; - Tone.extend(Tone.Abs, Tone.SignalBase); - Tone.Abs.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._abs.dispose(); - this._abs = null; - return this; - }; - return Tone.Abs; -}(Tone_core_Tone, Tone_signal_WaveShaper); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Modulo; -Tone_signal_Modulo = function (Tone) { - 'use strict'; - Tone.Modulo = function (modulus) { - this.createInsOuts(1, 0); - this._shaper = new Tone.WaveShaper(Math.pow(2, 16)); - this._multiply = new Tone.Multiply(); - this._subtract = this.output = new Tone.Subtract(); - this._modSignal = new Tone.Signal(modulus); - this.input.fan(this._shaper, this._subtract); - this._modSignal.connect(this._multiply, 0, 0); - this._shaper.connect(this._multiply, 0, 1); - this._multiply.connect(this._subtract, 0, 1); - this._setWaveShaper(modulus); - }; - Tone.extend(Tone.Modulo, Tone.SignalBase); - Tone.Modulo.prototype._setWaveShaper = function (mod) { - this._shaper.setMap(function (val) { - var multiple = Math.floor((val + 0.0001) / mod); - return multiple; - }); - }; - Object.defineProperty(Tone.Modulo.prototype, 'value', { - get: function () { - return this._modSignal.value; - }, - set: function (mod) { - this._modSignal.value = mod; - this._setWaveShaper(mod); - } - }); - Tone.Modulo.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._shaper.dispose(); - this._shaper = null; - this._multiply.dispose(); - this._multiply = null; - this._subtract.dispose(); - this._subtract = null; - this._modSignal.dispose(); - this._modSignal = null; - return this; - }; - return Tone.Modulo; -}(Tone_core_Tone, Tone_signal_WaveShaper, Tone_signal_Multiply); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Pow; -Tone_signal_Pow = function (Tone) { - 'use strict'; - Tone.Pow = function (exp) { - this._exp = this.defaultArg(exp, 1); - this._expScaler = this.input = this.output = new Tone.WaveShaper(this._expFunc(this._exp), 8192); - }; - Tone.extend(Tone.Pow, Tone.SignalBase); - Object.defineProperty(Tone.Pow.prototype, 'value', { - get: function () { - return this._exp; - }, - set: function (exp) { - this._exp = exp; - this._expScaler.setMap(this._expFunc(this._exp)); - } - }); - Tone.Pow.prototype._expFunc = function (exp) { - return function (val) { - return Math.pow(Math.abs(val), exp); - }; - }; - Tone.Pow.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._expScaler.dispose(); - this._expScaler = null; - return this; - }; - return Tone.Pow; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_AudioToGain; -Tone_signal_AudioToGain = function (Tone) { - 'use strict'; - Tone.AudioToGain = function () { - this._norm = this.input = this.output = new Tone.WaveShaper(function (x) { - return (x + 1) / 2; + return val; + } + }; + Tone.Param.prototype._minOutput = 0.00001; + Tone.Param.prototype.setValueAtTime = function (value, time) { + value = this._fromUnits(value); + time = this.toSeconds(time); + if (time <= this.now() + this.blockTime) { + this._param.value = value; + } else { + this._param.setValueAtTime(value, time); + } + return this; + }; + Tone.Param.prototype.setRampPoint = function (now) { + now = this.defaultArg(now, this.now()); + var currentVal = this._param.value; + if (currentVal === 0) { + currentVal = this._minOutput; + } + this._param.setValueAtTime(currentVal, now); + return this; + }; + Tone.Param.prototype.linearRampToValueAtTime = function (value, endTime) { + value = this._fromUnits(value); + this._param.linearRampToValueAtTime(value, this.toSeconds(endTime)); + return this; + }; + Tone.Param.prototype.exponentialRampToValueAtTime = function ( + value, + endTime + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + this._param.exponentialRampToValueAtTime(value, this.toSeconds(endTime)); + return this; + }; + Tone.Param.prototype.exponentialRampToValue = function ( + value, + rampTime, + startTime + ) { + startTime = this.toSeconds(startTime); + this.setRampPoint(startTime); + this.exponentialRampToValueAtTime( + value, + startTime + this.toSeconds(rampTime) + ); + return this; + }; + Tone.Param.prototype.linearRampToValue = function ( + value, + rampTime, + startTime + ) { + startTime = this.toSeconds(startTime); + this.setRampPoint(startTime); + this.linearRampToValueAtTime(value, startTime + this.toSeconds(rampTime)); + return this; + }; + Tone.Param.prototype.setTargetAtTime = function ( + value, + startTime, + timeConstant + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + timeConstant = Math.max(this._minOutput, timeConstant); + this._param.setTargetAtTime( + value, + this.toSeconds(startTime), + timeConstant + ); + return this; + }; + Tone.Param.prototype.setValueCurveAtTime = function ( + values, + startTime, + duration + ) { + for (var i = 0; i < values.length; i++) { + values[i] = this._fromUnits(values[i]); + } + this._param.setValueCurveAtTime( + values, + this.toSeconds(startTime), + this.toSeconds(duration) + ); + return this; + }; + Tone.Param.prototype.cancelScheduledValues = function (startTime) { + this._param.cancelScheduledValues(this.toSeconds(startTime)); + return this; + }; + Tone.Param.prototype.rampTo = function (value, rampTime, startTime) { + rampTime = this.defaultArg(rampTime, 0); + if ( + this.units === Tone.Type.Frequency || + this.units === Tone.Type.BPM || + this.units === Tone.Type.Decibels + ) { + this.exponentialRampToValue(value, rampTime, startTime); + } else { + this.linearRampToValue(value, rampTime, startTime); + } + return this; + }; + Object.defineProperty(Tone.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, }); - }; - Tone.extend(Tone.AudioToGain, Tone.SignalBase); - Tone.AudioToGain.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._norm.dispose(); - this._norm = null; - return this; - }; - return Tone.AudioToGain; -}(Tone_core_Tone, Tone_signal_WaveShaper); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_Expr; -Tone_signal_Expr = function (Tone) { - 'use strict'; - Tone.Expr = function () { - var expr = this._replacements(Array.prototype.slice.call(arguments)); - var inputCount = this._parseInputs(expr); - this._nodes = []; - this.input = new Array(inputCount); - for (var i = 0; i < inputCount; i++) { - this.input[i] = this.context.createGain(); - } - var tree = this._parseTree(expr); - var result; - try { - result = this._eval(tree); - } catch (e) { - this._disposeNodes(); - throw new Error('Tone.Expr: Could evaluate expression: ' + expr); - } - this.output = result; - }; - Tone.extend(Tone.Expr, Tone.SignalBase); - function applyBinary(Constructor, args, self) { - var op = new Constructor(); - self._eval(args[0]).connect(op, 0, 0); - self._eval(args[1]).connect(op, 0, 1); - return op; - } - function applyUnary(Constructor, args, self) { - var op = new Constructor(); - self._eval(args[0]).connect(op, 0, 0); - return op; - } - function getNumber(arg) { - return arg ? parseFloat(arg) : undefined; - } - function literalNumber(arg) { - return arg && arg.args ? parseFloat(arg.args) : undefined; - } - Tone.Expr._Expressions = { - 'value': { - 'signal': { - regexp: /^\d+\.\d+|^\d+/, - method: function (arg) { - var sig = new Tone.Signal(getNumber(arg)); - return sig; - } + Tone.Param.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._param = null; + if (this._lfo) { + this._lfo.dispose(); + this._lfo = null; + } + return this; + }; + return Tone.Param; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Gain; + Tone_core_Gain = (function (Tone) { + "use strict"; + if (window.GainNode && !AudioContext.prototype.createGain) { + AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; + } + Tone.Gain = function () { + var options = this.optionsObject( + arguments, + ["gain", "units"], + Tone.Gain.defaults + ); + this.input = this.output = this._gainNode = this.context.createGain(); + this.gain = new Tone.Param({ + param: this._gainNode.gain, + units: options.units, + value: options.gain, + convert: options.convert, + }); + this._readOnly("gain"); + }; + Tone.extend(Tone.Gain); + Tone.Gain.defaults = { + gain: 1, + convert: true, + }; + Tone.Gain.prototype.dispose = function () { + Tone.Param.prototype.dispose.call(this); + this._gainNode.disconnect(); + this._gainNode = null; + this._writable("gain"); + this.gain.dispose(); + this.gain = null; + }; + Tone.prototype.createInsOuts = function (inputs, outputs) { + if (inputs === 1) { + this.input = new Tone.Gain(); + } else if (inputs > 1) { + this.input = new Array(inputs); + } + if (outputs === 1) { + this.output = new Tone.Gain(); + } else if (outputs > 1) { + this.output = new Array(inputs); + } + }; + return Tone.Gain; + })(Tone_core_Tone, Tone_core_Param); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Signal; + Tone_signal_Signal = (function (Tone) { + "use strict"; + Tone.Signal = function () { + var options = this.optionsObject( + arguments, + ["value", "units"], + Tone.Signal.defaults + ); + this.output = this._gain = this.context.createGain(); + options.param = this._gain.gain; + Tone.Param.call(this, options); + this.input = this._param = this._gain.gain; + this.context.getConstant(1).chain(this._gain); + }; + Tone.extend(Tone.Signal, Tone.Param); + Tone.Signal.defaults = { + value: 0, + units: Tone.Type.Default, + convert: true, + }; + Tone.Signal.prototype.connect = Tone.SignalBase.prototype.connect; + Tone.Signal.prototype.dispose = function () { + Tone.Param.prototype.dispose.call(this); + this._param = null; + this._gain.disconnect(); + this._gain = null; + return this; + }; + return Tone.Signal; + })(Tone_core_Tone, Tone_signal_WaveShaper, Tone_type_Type, Tone_core_Param); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Add; + Tone_signal_Add = (function (Tone) { + "use strict"; + Tone.Add = function (value) { + this.createInsOuts(2, 0); + this._sum = this.input[0] = this.input[1] = this.output = new Tone.Gain(); + this._param = this.input[1] = new Tone.Signal(value); + this._param.connect(this._sum); + }; + Tone.extend(Tone.Add, Tone.Signal); + Tone.Add.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._sum.dispose(); + this._sum = null; + this._param.dispose(); + this._param = null; + return this; + }; + return Tone.Add; + })(Tone_core_Tone, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Multiply; + Tone_signal_Multiply = (function (Tone) { + "use strict"; + Tone.Multiply = function (value) { + this.createInsOuts(2, 0); + this._mult = this.input[0] = this.output = new Tone.Gain(); + this._param = this.input[1] = this.output.gain; + this._param.value = this.defaultArg(value, 0); + }; + Tone.extend(Tone.Multiply, Tone.Signal); + Tone.Multiply.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._mult.dispose(); + this._mult = null; + this._param = null; + return this; + }; + return Tone.Multiply; + })(Tone_core_Tone, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Scale; + Tone_signal_Scale = (function (Tone) { + "use strict"; + Tone.Scale = function (outputMin, outputMax) { + this._outputMin = this.defaultArg(outputMin, 0); + this._outputMax = this.defaultArg(outputMax, 1); + this._scale = this.input = new Tone.Multiply(1); + this._add = this.output = new Tone.Add(0); + this._scale.connect(this._add); + this._setRange(); + }; + Tone.extend(Tone.Scale, Tone.SignalBase); + Object.defineProperty(Tone.Scale.prototype, "min", { + get: function () { + return this._outputMin; }, - 'input': { - regexp: /^\$\d/, - method: function (arg, self) { - return self.input[getNumber(arg.substr(1))]; - } - } - }, - 'glue': { - '(': { regexp: /^\(/ }, - ')': { regexp: /^\)/ }, - ',': { regexp: /^,/ } - }, - 'func': { - 'abs': { - regexp: /^abs/, - method: applyUnary.bind(this, Tone.Abs) + set: function (min) { + this._outputMin = min; + this._setRange(); }, - 'mod': { - regexp: /^mod/, - method: function (args, self) { - var modulus = literalNumber(args[1]); - var op = new Tone.Modulo(modulus); - self._eval(args[0]).connect(op); - return op; - } + }); + Object.defineProperty(Tone.Scale.prototype, "max", { + get: function () { + return this._outputMax; }, - 'pow': { - regexp: /^pow/, - method: function (args, self) { - var exp = literalNumber(args[1]); - var op = new Tone.Pow(exp); - self._eval(args[0]).connect(op); - return op; - } + set: function (max) { + this._outputMax = max; + this._setRange(); }, - 'a2g': { - regexp: /^a2g/, - method: function (args, self) { - var op = new Tone.AudioToGain(); - self._eval(args[0]).connect(op); - return op; + }); + Tone.Scale.prototype._setRange = function () { + this._add.value = this._outputMin; + this._scale.value = this._outputMax - this._outputMin; + }; + Tone.Scale.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._add.dispose(); + this._add = null; + this._scale.dispose(); + this._scale = null; + return this; + }; + return Tone.Scale; + })(Tone_core_Tone, Tone_signal_Add, Tone_signal_Multiply); + var signal; + ("use strict"); + signal = (function () { + // Signal is built with the Tone.js signal by Yotam Mann + // https://github.com/TONEnoTONE/Tone.js/ + var Signal = Tone_signal_Signal; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + /** + *

p5.Signal is a constant audio-rate signal used by p5.Oscillator + * and p5.Envelope for modulation math.

+ * + *

This is necessary because Web Audio is processed on a seprate clock. + * For example, the p5 draw loop runs about 60 times per second. But + * the audio clock must process samples 44100 times per second. If we + * want to add a value to each of those samples, we can't do it in the + * draw loop, but we can do it by adding a constant-rate audio signal.This class mostly functions behind the scenes in p5.sound, and returns + * a Tone.Signal from the Tone.js library by Yotam Mann. + * If you want to work directly with audio signals for modular + * synthesis, check out + * tone.js.

+ * + * @class p5.Signal + * @constructor + * @return {Tone.Signal} A Signal object from the Tone.js library + * @example + *
+ * function setup() { + * carrier = new p5.Oscillator('sine'); + * carrier.amp(1); // set amplitude + * carrier.freq(220); // set frequency + * carrier.start(); // start oscillating + * + * modulator = new p5.Oscillator('sawtooth'); + * modulator.disconnect(); + * modulator.amp(1); + * modulator.freq(4); + * modulator.start(); + * + * // Modulator's default amplitude range is -1 to 1. + * // Multiply it by -200, so the range is -200 to 200 + * // then add 220 so the range is 20 to 420 + * carrier.freq( modulator.mult(-200).add(220) ); + * } + *
+ */ + p5.Signal = function (value) { + var s = new Signal(value); + // p5sound.soundArray.push(s); + return s; + }; + /** + * Fade to value, for smooth transitions + * + * @method fade + * @param {Number} value Value to set this signal + * @param {Number} [secondsFromNow] Length of fade, in seconds from now + */ + Signal.prototype.fade = Signal.prototype.linearRampToValueAtTime; + Mult.prototype.fade = Signal.prototype.fade; + Add.prototype.fade = Signal.prototype.fade; + Scale.prototype.fade = Signal.prototype.fade; + /** + * Connect a p5.sound object or Web Audio node to this + * p5.Signal so that its amplitude values can be scaled. + * + * @method setInput + * @param {Object} input + */ + Signal.prototype.setInput = function (_input) { + _input.connect(this); + }; + Mult.prototype.setInput = Signal.prototype.setInput; + Add.prototype.setInput = Signal.prototype.setInput; + Scale.prototype.setInput = Signal.prototype.setInput; + // signals can add / mult / scale themselves + /** + * Add a constant value to this audio signal, + * and return the resulting audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalAdd. + * + * @method add + * @param {Number} number + * @return {p5.Signal} object + */ + Signal.prototype.add = function (num) { + var add = new Add(num); + // add.setInput(this); + this.connect(add); + return add; + }; + Mult.prototype.add = Signal.prototype.add; + Add.prototype.add = Signal.prototype.add; + Scale.prototype.add = Signal.prototype.add; + /** + * Multiply this signal by a constant value, + * and return the resulting audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalMult. + * + * @method mult + * @param {Number} number to multiply + * @return {p5.Signal} object + */ + Signal.prototype.mult = function (num) { + var mult = new Mult(num); + // mult.setInput(this); + this.connect(mult); + return mult; + }; + Mult.prototype.mult = Signal.prototype.mult; + Add.prototype.mult = Signal.prototype.mult; + Scale.prototype.mult = Signal.prototype.mult; + /** + * Scale this signal value to a given range, + * and return the result as an audio signal. Does + * not change the value of the original signal, + * instead it returns a new p5.SignalScale. + * + * @method scale + * @param {Number} number to multiply + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Signal} object + */ + Signal.prototype.scale = function (inMin, inMax, outMin, outMax) { + var mapOutMin, mapOutMax; + if (arguments.length === 4) { + mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; + mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; + } else { + mapOutMin = arguments[0]; + mapOutMax = arguments[1]; + } + var scale = new Scale(mapOutMin, mapOutMax); + this.connect(scale); + return scale; + }; + Mult.prototype.scale = Signal.prototype.scale; + Add.prototype.scale = Signal.prototype.scale; + Scale.prototype.scale = Signal.prototype.scale; + })( + Tone_signal_Signal, + Tone_signal_Add, + Tone_signal_Multiply, + Tone_signal_Scale + ); + var oscillator; + ("use strict"); + oscillator = (function () { + var p5sound = master; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + /** + *

Creates a signal that oscillates between -1.0 and 1.0. + * By default, the oscillation takes the form of a sinusoidal + * shape ('sine'). Additional types include 'triangle', + * 'sawtooth' and 'square'. The frequency defaults to + * 440 oscillations per second (440Hz, equal to the pitch of an + * 'A' note).

+ * + *

Set the type of oscillation with setType(), or by instantiating a + * specific oscillator: p5.SinOsc, p5.TriOsc, p5.SqrOsc, or p5.SawOsc. + *

+ * + * @class p5.Oscillator + * @constructor + * @param {Number} [freq] frequency defaults to 440Hz + * @param {String} [type] type of oscillator. Options: + * 'sine' (default), 'triangle', + * 'sawtooth', 'square' + * @example + *
+ * var osc; + * var playing = false; + * + * function setup() { + * backgroundColor = color(255,0,255); + * textAlign(CENTER); + * + * osc = new p5.Oscillator(); + * osc.setType('sine'); + * osc.freq(240); + * osc.amp(0); + * osc.start(); + * } + * + * function draw() { + * background(backgroundColor) + * text('click to play', width/2, height/2); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { + * if (!playing) { + * // ramp amplitude to 0.5 over 0.05 seconds + * osc.amp(0.5, 0.05); + * playing = true; + * backgroundColor = color(0,255,255); + * } else { + * // ramp amplitude to 0 over 0.5 seconds + * osc.amp(0, 0.5); + * playing = false; + * backgroundColor = color(255,0,255); + * } + * } + * } + *
+ */ + p5.Oscillator = function (freq, type) { + if (typeof freq === "string") { + var f = type; + type = freq; + freq = f; + } + if (typeof type === "number") { + var f = type; + type = freq; + freq = f; + } + this.started = false; + // components + this.phaseAmount = undefined; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.f = freq || 440; + // frequency + this.oscillator.type = type || "sine"; + this.oscillator.frequency.setValueAtTime( + this.f, + p5sound.audiocontext.currentTime + ); + // connections + this.output = p5sound.audiocontext.createGain(); + this._freqMods = []; + // modulators connected to this oscillator's frequency + // set default output gain to 0.5 + this.output.gain.value = 0.5; + this.output.gain.setValueAtTime(0.5, p5sound.audiocontext.currentTime); + this.oscillator.connect(this.output); + // stereo panning + this.panPosition = 0; + this.connection = p5sound.input; + // connect to p5sound by default + this.panner = new p5.Panner(this.output, this.connection, 1); + //array of math operation signal chaining + this.mathOps = [this.output]; + // add to the soundArray so we can dispose of the osc later + p5sound.soundArray.push(this); + }; + /** + * Start an oscillator. Accepts an optional parameter to + * determine how long (in seconds from now) until the + * oscillator starts. + * + * @method start + * @param {Number} [time] startTime in seconds from now. + * @param {Number} [frequency] frequency in Hz. + */ + p5.Oscillator.prototype.start = function (time, f) { + if (this.started) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + } + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; + // set old osc free to be garbage collected (memory) + if (this.oscillator) { + this.oscillator.disconnect(); + delete this.oscillator; } + // var detune = this.oscillator.frequency.value; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.oscillator.frequency.value = Math.abs(freq); + this.oscillator.type = type; + // this.oscillator.detune.value = detune; + this.oscillator.connect(this.output); + time = time || 0; + this.oscillator.start(time + p5sound.audiocontext.currentTime); + this.freqNode = this.oscillator.frequency; + // if other oscillators are already connected to this osc's freq + for (var i in this._freqMods) { + if (typeof this._freqMods[i].connect !== "undefined") { + this._freqMods[i].connect(this.oscillator.frequency); + } + } + this.started = true; } - }, - 'binary': { - '+': { - regexp: /^\+/, - precedence: 1, - method: applyBinary.bind(this, Tone.Add) - }, - '-': { - regexp: /^\-/, - precedence: 1, - method: function (args, self) { - if (args.length === 1) { - return applyUnary(Tone.Negate, args, self); + }; + /** + * Stop an oscillator. Accepts an optional parameter + * to determine how long (in seconds from now) until the + * oscillator stops. + * + * @method stop + * @param {Number} secondsFromNow Time, in seconds from now. + */ + p5.Oscillator.prototype.stop = function (time) { + if (this.started) { + var t = time || 0; + var now = p5sound.audiocontext.currentTime; + this.oscillator.stop(t + now); + this.started = false; + } + }; + /** + * Set the amplitude between 0 and 1.0. Or, pass in an object + * such as an oscillator to modulate amplitude with an audio signal. + * + * @method amp + * @param {Number|Object} vol between 0 and 1.0 + * or a modulating signal/oscillator + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {AudioParam} gain If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's + * gain/amplitude/volume) + */ + p5.Oscillator.prototype.amp = function (vol, rampTime, tFromNow) { + var self = this; + if (typeof vol === "number") { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + ); + } else if (vol) { + vol.connect(self.output.gain); + } else { + // return the Gain Node + return this.output.gain; + } + }; + // these are now the same thing + p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp; + p5.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }; + /** + * Set frequency of an oscillator to a value. Or, pass in an object + * such as an oscillator to modulate the frequency with an audio signal. + * + * @method freq + * @param {Number|Object} Frequency Frequency in Hz + * or modulating signal/oscillator + * @param {Number} [rampTime] Ramp time (in seconds) + * @param {Number} [timeFromNow] Schedule this event to happen + * at x seconds from now + * @return {AudioParam} Frequency If no value is provided, + * returns the Web Audio API + * AudioParam that controls + * this oscillator's frequency + * @example + *
+ * var osc = new p5.Oscillator(300); + * osc.start(); + * osc.freq(40, 10); + *
+ */ + p5.Oscillator.prototype.freq = function (val, rampTime, tFromNow) { + if (typeof val === "number" && !isNaN(val)) { + this.f = val; + var now = p5sound.audiocontext.currentTime; + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var t = now + tFromNow + rampTime; + // var currentFreq = this.oscillator.frequency.value; + // this.oscillator.frequency.cancelScheduledValues(now); + if (rampTime === 0) { + this.oscillator.frequency.setValueAtTime(val, tFromNow + now); + } else { + if (val > 0) { + this.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); } else { - return applyBinary(Tone.Subtract, args, self); + this.oscillator.frequency.linearRampToValueAtTime( + val, + tFromNow + rampTime + now + ); } } - }, - '*': { - regexp: /^\*/, - precedence: 0, - method: applyBinary.bind(this, Tone.Multiply) + // reset phase if oscillator has a phase + if (this.phaseAmount) { + this.phase(this.phaseAmount); + } + } else if (val) { + if (val.output) { + val = val.output; + } + val.connect(this.oscillator.frequency); + // keep track of what is modulating this param + // so it can be re-connected if + this._freqMods.push(val); + } else { + // return the Frequency Node + return this.oscillator.frequency; } - }, - 'unary': { - '-': { - regexp: /^\-/, - method: applyUnary.bind(this, Tone.Negate) - }, - '!': { - regexp: /^\!/, - method: applyUnary.bind(this, Tone.NOT) + }; + p5.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }; + /** + * Set type to 'sine', 'triangle', 'sawtooth' or 'square'. + * + * @method setType + * @param {String} type 'sine', 'triangle', 'sawtooth' or 'square'. + */ + p5.Oscillator.prototype.setType = function (type) { + this.oscillator.type = type; + }; + p5.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.Oscillator.prototype.connect = function (unit) { + if (!unit) { + this.panner.connect(p5sound.input); + } else if (unit.hasOwnProperty("input")) { + this.panner.connect(unit.input); + this.connection = unit.input; + } else { + this.panner.connect(unit); + this.connection = unit; } - } - }; - Tone.Expr.prototype._parseInputs = function (expr) { - var inputArray = expr.match(/\$\d/g); - var inputMax = 0; - if (inputArray !== null) { - for (var i = 0; i < inputArray.length; i++) { - var inputNum = parseInt(inputArray[i].substr(1)) + 1; - inputMax = Math.max(inputMax, inputNum); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.Oscillator.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); } - } - return inputMax; - }; - Tone.Expr.prototype._replacements = function (args) { - var expr = args.shift(); - for (var i = 0; i < args.length; i++) { - expr = expr.replace(/\%/i, args[i]); - } - return expr; - }; - Tone.Expr.prototype._tokenize = function (expr) { - var position = -1; - var tokens = []; - while (expr.length > 0) { - expr = expr.trim(); - var token = getNextToken(expr); - tokens.push(token); - expr = expr.substr(token.value.length); - } - function getNextToken(expr) { - for (var type in Tone.Expr._Expressions) { - var group = Tone.Expr._Expressions[type]; - for (var opName in group) { - var op = group[opName]; - var reg = op.regexp; - var match = expr.match(reg); - if (match !== null) { - return { - type: type, - value: match[0], - method: op.method - }; - } + if (this.panner) { + this.panner.disconnect(); + if (this.output) { + this.output.connect(this.panner); } } - throw new SyntaxError('Tone.Expr: Unexpected token ' + expr); - } - return { - next: function () { - return tokens[++position]; - }, - peek: function () { - return tokens[position + 1]; + this.oscMods = []; + }; + /** + * Pan between Left (-1) and Right (1) + * + * @method pan + * @param {Number} panning Number between -1 and 1 + * @param {Number} timeFromNow schedule this event to happen + * seconds from now + */ + p5.Oscillator.prototype.pan = function (pval, tFromNow) { + this.panPosition = pval; + this.panner.pan(pval, tFromNow); + }; + p5.Oscillator.prototype.getPan = function () { + return this.panPosition; + }; + // get rid of the oscillator + p5.Oscillator.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.oscillator) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + this.disconnect(); + this.panner = null; + this.oscillator = null; + } + // if it is a Pulse + if (this.osc2) { + this.osc2.dispose(); } }; - }; - Tone.Expr.prototype._parseTree = function (expr) { - var lexer = this._tokenize(expr); - var isUndef = this.isUndef.bind(this); - function matchSyntax(token, syn) { - return !isUndef(token) && token.type === 'glue' && token.value === syn; - } - function matchGroup(token, groupName, prec) { - var ret = false; - var group = Tone.Expr._Expressions[groupName]; - if (!isUndef(token)) { - for (var opName in group) { - var op = group[opName]; - if (op.regexp.test(token.value)) { - if (!isUndef(prec)) { - if (op.precedence === prec) { - return true; - } - } else { - return true; - } + /** + * Set the phase of an oscillator between 0.0 and 1.0. + * In this implementation, phase is a delay time + * based on the oscillator's current frequency. + * + * @method phase + * @param {Number} phase float between 0.0 and 1.0 + */ + p5.Oscillator.prototype.phase = function (p) { + var delayAmt = p5.prototype.map(p, 0, 1, 0, 1 / this.f); + var now = p5sound.audiocontext.currentTime; + this.phaseAmount = p; + if (!this.dNode) { + // create a delay node + this.dNode = p5sound.audiocontext.createDelay(); + // put the delay node in between output and panner + this.oscillator.disconnect(); + this.oscillator.connect(this.dNode); + this.dNode.connect(this.output); + } + // set delay time to match phase: + this.dNode.delayTime.setValueAtTime(delayAmt, now); + }; + // ========================== // + // SIGNAL MATH FOR MODULATION // + // ========================== // + // return sigChain(this, scale, thisChain, nextChain, Scale); + var sigChain = function (o, mathObj, thisChain, nextChain, type) { + var chainSource = o.oscillator; + // if this type of math already exists in the chain, replace it + for (var i in o.mathOps) { + if (o.mathOps[i] instanceof type) { + chainSource.disconnect(); + o.mathOps[i].dispose(); + thisChain = i; + // assume nextChain is output gain node unless... + if (thisChain < o.mathOps.length - 2) { + nextChain = o.mathOps[i + 1]; } } } - return ret; - } - function parseExpression(precedence) { - if (isUndef(precedence)) { - precedence = 5; + if (thisChain === o.mathOps.length - 1) { + o.mathOps.push(nextChain); } - var expr; - if (precedence < 0) { - expr = parseUnary(); - } else { - expr = parseExpression(precedence - 1); + // assume source is the oscillator unless i > 0 + if (i > 0) { + chainSource = o.mathOps[i - 1]; } - var token = lexer.peek(); - while (matchGroup(token, 'binary', precedence)) { - token = lexer.next(); - expr = { - operator: token.value, - method: token.method, - args: [ - expr, - parseExpression(precedence - 1) - ] - }; - token = lexer.peek(); - } - return expr; - } - function parseUnary() { - var token, expr; - token = lexer.peek(); - if (matchGroup(token, 'unary')) { - token = lexer.next(); - expr = parseUnary(); - return { - operator: token.value, - method: token.method, - args: [expr] - }; + chainSource.disconnect(); + chainSource.connect(mathObj); + mathObj.connect(nextChain); + o.mathOps[thisChain] = mathObj; + return o; + }; + /** + * Add a value to the p5.Oscillator's output amplitude, + * and return the oscillator. Calling this method again + * will override the initial add() with a new value. + * + * @method add + * @param {Number} number Constant number to add + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + * + */ + p5.Oscillator.prototype.add = function (num) { + var add = new Add(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, add, thisChain, nextChain, Add); + }; + /** + * Multiply the p5.Oscillator's output amplitude + * by a fixed value (i.e. turn it up!). Calling this method + * again will override the initial mult() with a new value. + * + * @method mult + * @param {Number} number Constant number to multiply + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with multiplied output + */ + p5.Oscillator.prototype.mult = function (num) { + var mult = new Mult(num); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, mult, thisChain, nextChain, Mult); + }; + /** + * Scale this oscillator's amplitude values to a given + * range, and return the oscillator. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Oscillator} Oscillator Returns this oscillator + * with scaled output + */ + p5.Oscillator.prototype.scale = function (inMin, inMax, outMin, outMax) { + var mapOutMin, mapOutMax; + if (arguments.length === 4) { + mapOutMin = p5.prototype.map(outMin, inMin, inMax, 0, 1) - 0.5; + mapOutMax = p5.prototype.map(outMax, inMin, inMax, 0, 1) - 0.5; + } else { + mapOutMin = arguments[0]; + mapOutMax = arguments[1]; } - return parsePrimary(); - } - function parsePrimary() { - var token, expr; - token = lexer.peek(); - if (isUndef(token)) { - throw new SyntaxError('Tone.Expr: Unexpected termination of expression'); + var scale = new Scale(mapOutMin, mapOutMax); + var thisChain = this.mathOps.length - 1; + var nextChain = this.output; + return sigChain(this, scale, thisChain, nextChain, Scale); + }; + // ============================== // + // SinOsc, TriOsc, SqrOsc, SawOsc // + // ============================== // + /** + * Constructor: new p5.SinOsc(). + * This creates a Sine Wave Oscillator and is + * equivalent to new p5.Oscillator('sine') + * or creating a p5.Oscillator and then calling + * its method setType('sine'). + * See p5.Oscillator for methods. + * + * @class p5.SinOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SinOsc = function (freq) { + p5.Oscillator.call(this, freq, "sine"); + }; + p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.TriOsc(). + * This creates a Triangle Wave Oscillator and is + * equivalent to new p5.Oscillator('triangle') + * or creating a p5.Oscillator and then calling + * its method setType('triangle'). + * See p5.Oscillator for methods. + * + * @class p5.TriOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.TriOsc = function (freq) { + p5.Oscillator.call(this, freq, "triangle"); + }; + p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.SawOsc(). + * This creates a SawTooth Wave Oscillator and is + * equivalent to new p5.Oscillator('sawtooth') + * or creating a p5.Oscillator and then calling + * its method setType('sawtooth'). + * See p5.Oscillator for methods. + * + * @class p5.SawOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SawOsc = function (freq) { + p5.Oscillator.call(this, freq, "sawtooth"); + }; + p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype); + /** + * Constructor: new p5.SqrOsc(). + * This creates a Square Wave Oscillator and is + * equivalent to new p5.Oscillator('square') + * or creating a p5.Oscillator and then calling + * its method setType('square'). + * See p5.Oscillator for methods. + * + * @class p5.SqrOsc + * @constructor + * @extends p5.Oscillator + * @param {Number} [freq] Set the frequency + */ + p5.SqrOsc = function (freq) { + p5.Oscillator.call(this, freq, "square"); + }; + p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype); + })(master, Tone_signal_Add, Tone_signal_Multiply, Tone_signal_Scale); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Timeline; + Tone_core_Timeline = (function (Tone) { + "use strict"; + Tone.Timeline = function () { + var options = this.optionsObject( + arguments, + ["memory"], + Tone.Timeline.defaults + ); + this._timeline = []; + this._toRemove = []; + this._iterating = false; + this.memory = options.memory; + }; + Tone.extend(Tone.Timeline); + Tone.Timeline.defaults = { memory: Infinity }; + Object.defineProperty(Tone.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }); + Tone.Timeline.prototype.add = function (event) { + if (this.isUndef(event.time)) { + throw new Error("Tone.Timeline: events must have a time attribute"); } - if (token.type === 'func') { - token = lexer.next(); - return parseFunctionCall(token); + if (this._timeline.length) { + var index = this._search(event.time); + this._timeline.splice(index + 1, 0, event); + } else { + this._timeline.push(event); } - if (token.type === 'value') { - token = lexer.next(); - return { - method: token.method, - args: token.value - }; + if (this.length > this.memory) { + var diff = this.length - this.memory; + this._timeline.splice(0, diff); } - if (matchSyntax(token, '(')) { - lexer.next(); - expr = parseExpression(); - token = lexer.next(); - if (!matchSyntax(token, ')')) { - throw new SyntaxError('Expected )'); + return this; + }; + Tone.Timeline.prototype.remove = function (event) { + if (this._iterating) { + this._toRemove.push(event); + } else { + var index = this._timeline.indexOf(event); + if (index !== -1) { + this._timeline.splice(index, 1); } - return expr; } - throw new SyntaxError('Tone.Expr: Parse error, cannot process token ' + token.value); - } - function parseFunctionCall(func) { - var token, args = []; - token = lexer.next(); - if (!matchSyntax(token, '(')) { - throw new SyntaxError('Tone.Expr: Expected ( in a function call "' + func.value + '"'); + return this; + }; + Tone.Timeline.prototype.get = function (time) { + var index = this._search(time); + if (index !== -1) { + return this._timeline[index]; + } else { + return null; } - token = lexer.peek(); - if (!matchSyntax(token, ')')) { - args = parseArgumentList(); + }; + Tone.Timeline.prototype.peek = function () { + return this._timeline[0]; + }; + Tone.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }; + Tone.Timeline.prototype.getAfter = function (time) { + var index = this._search(time); + if (index + 1 < this._timeline.length) { + return this._timeline[index + 1]; + } else { + return null; } - token = lexer.next(); - if (!matchSyntax(token, ')')) { - throw new SyntaxError('Tone.Expr: Expected ) in a function call "' + func.value + '"'); + }; + Tone.Timeline.prototype.getBefore = function (time) { + var len = this._timeline.length; + if (len > 0 && this._timeline[len - 1].time < time) { + return this._timeline[len - 1]; } - return { - method: func.method, - args: args, - name: name - }; - } - function parseArgumentList() { - var token, expr, args = []; - while (true) { - expr = parseExpression(); - if (isUndef(expr)) { - break; + var index = this._search(time); + if (index - 1 >= 0) { + return this._timeline[index - 1]; + } else { + return null; + } + }; + Tone.Timeline.prototype.cancel = function (after) { + if (this._timeline.length > 1) { + var index = this._search(after); + if (index >= 0) { + if (this._timeline[index].time === after) { + for (var i = index; i >= 0; i--) { + if (this._timeline[i].time === after) { + index = i; + } else { + break; + } + } + this._timeline = this._timeline.slice(0, index); + } else { + this._timeline = this._timeline.slice(0, index + 1); + } + } else { + this._timeline = []; } - args.push(expr); - token = lexer.peek(); - if (!matchSyntax(token, ',')) { - break; + } else if (this._timeline.length === 1) { + if (this._timeline[0].time >= after) { + this._timeline = []; } - lexer.next(); } - return args; - } - return parseExpression(); - }; - Tone.Expr.prototype._eval = function (tree) { - if (!this.isUndef(tree)) { - var node = tree.method(tree.args, this); - this._nodes.push(node); - return node; - } - }; - Tone.Expr.prototype._disposeNodes = function () { - for (var i = 0; i < this._nodes.length; i++) { - var node = this._nodes[i]; - if (this.isFunction(node.dispose)) { - node.dispose(); - } else if (this.isFunction(node.disconnect)) { - node.disconnect(); - } - node = null; - this._nodes[i] = null; - } - this._nodes = null; - }; - Tone.Expr.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._disposeNodes(); - }; - return Tone.Expr; -}(Tone_core_Tone, Tone_signal_Add, Tone_signal_Subtract, Tone_signal_Multiply, Tone_signal_GreaterThan, Tone_signal_GreaterThanZero, Tone_signal_Abs, Tone_signal_Negate, Tone_signal_Modulo, Tone_signal_Pow); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_signal_EqualPowerGain; -Tone_signal_EqualPowerGain = function (Tone) { - 'use strict'; - Tone.EqualPowerGain = function () { - this._eqPower = this.input = this.output = new Tone.WaveShaper(function (val) { - if (Math.abs(val) < 0.001) { - return 0; + return this; + }; + Tone.Timeline.prototype.cancelBefore = function (time) { + if (this._timeline.length) { + var index = this._search(time); + if (index >= 0) { + this._timeline = this._timeline.slice(index + 1); + } + } + return this; + }; + Tone.Timeline.prototype._search = function (time) { + var beginning = 0; + var len = this._timeline.length; + var end = len; + if (len > 0 && this._timeline[len - 1].time <= time) { + return len - 1; + } + while (beginning < end) { + var midPoint = Math.floor(beginning + (end - beginning) / 2); + var event = this._timeline[midPoint]; + var nextEvent = this._timeline[midPoint + 1]; + if (event.time === time) { + for (var i = midPoint; i < this._timeline.length; i++) { + var testEvent = this._timeline[i]; + if (testEvent.time === time) { + midPoint = i; + } + } + return midPoint; + } else if (event.time < time && nextEvent.time > time) { + return midPoint; + } else if (event.time > time) { + end = midPoint; + } else if (event.time < time) { + beginning = midPoint + 1; + } + } + return -1; + }; + Tone.Timeline.prototype._iterate = function ( + callback, + lowerBound, + upperBound + ) { + this._iterating = true; + lowerBound = this.defaultArg(lowerBound, 0); + upperBound = this.defaultArg(upperBound, this._timeline.length - 1); + for (var i = lowerBound; i <= upperBound; i++) { + callback(this._timeline[i]); + } + this._iterating = false; + if (this._toRemove.length > 0) { + for (var j = 0; j < this._toRemove.length; j++) { + var index = this._timeline.indexOf(this._toRemove[j]); + if (index !== -1) { + this._timeline.splice(index, 1); + } + } + this._toRemove = []; + } + }; + Tone.Timeline.prototype.forEach = function (callback) { + this._iterate(callback); + return this; + }; + Tone.Timeline.prototype.forEachBefore = function (time, callback) { + var upperBound = this._search(time); + if (upperBound !== -1) { + this._iterate(callback, 0, upperBound); + } + return this; + }; + Tone.Timeline.prototype.forEachAfter = function (time, callback) { + var lowerBound = this._search(time); + this._iterate(callback, lowerBound + 1); + return this; + }; + Tone.Timeline.prototype.forEachFrom = function (time, callback) { + var lowerBound = this._search(time); + while (lowerBound >= 0 && this._timeline[lowerBound].time >= time) { + lowerBound--; + } + this._iterate(callback, lowerBound + 1); + return this; + }; + Tone.Timeline.prototype.forEachAtTime = function (time, callback) { + var upperBound = this._search(time); + if (upperBound !== -1) { + this._iterate( + function (event) { + if (event.time === time) { + callback(event); + } + }, + 0, + upperBound + ); + } + return this; + }; + Tone.Timeline.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._timeline = null; + this._toRemove = null; + }; + return Tone.Timeline; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_TimelineSignal; + Tone_signal_TimelineSignal = (function (Tone) { + "use strict"; + Tone.TimelineSignal = function () { + var options = this.optionsObject( + arguments, + ["value", "units"], + Tone.Signal.defaults + ); + this._events = new Tone.Timeline(10); + Tone.Signal.apply(this, options); + options.param = this._param; + Tone.Param.call(this, options); + this._initial = this._fromUnits(this._param.value); + }; + Tone.extend(Tone.TimelineSignal, Tone.Param); + Tone.TimelineSignal.Type = { + Linear: "linear", + Exponential: "exponential", + Target: "target", + Curve: "curve", + Set: "set", + }; + Object.defineProperty(Tone.TimelineSignal.prototype, "value", { + get: function () { + var now = this.now(); + var val = this.getValueAtTime(now); + return this._toUnits(val); + }, + set: function (value) { + var convertedVal = this._fromUnits(value); + this._initial = convertedVal; + this.cancelScheduledValues(); + this._param.value = convertedVal; + }, + }); + Tone.TimelineSignal.prototype.setValueAtTime = function (value, startTime) { + value = this._fromUnits(value); + startTime = this.toSeconds(startTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Set, + value: value, + time: startTime, + }); + this._param.setValueAtTime(value, startTime); + return this; + }; + Tone.TimelineSignal.prototype.linearRampToValueAtTime = function ( + value, + endTime + ) { + value = this._fromUnits(value); + endTime = this.toSeconds(endTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Linear, + value: value, + time: endTime, + }); + this._param.linearRampToValueAtTime(value, endTime); + return this; + }; + Tone.TimelineSignal.prototype.exponentialRampToValueAtTime = function ( + value, + endTime + ) { + endTime = this.toSeconds(endTime); + var beforeEvent = this._searchBefore(endTime); + if (beforeEvent && beforeEvent.value === 0) { + this.setValueAtTime(this._minOutput, beforeEvent.time); + } + value = this._fromUnits(value); + var setValue = Math.max(value, this._minOutput); + this._events.add({ + type: Tone.TimelineSignal.Type.Exponential, + value: setValue, + time: endTime, + }); + if (value < this._minOutput) { + this._param.exponentialRampToValueAtTime( + this._minOutput, + endTime - this.sampleTime + ); + this.setValueAtTime(0, endTime); } else { - return this.equalPowerScale(val); - } - }.bind(this), 4096); - }; - Tone.extend(Tone.EqualPowerGain, Tone.SignalBase); - Tone.EqualPowerGain.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._eqPower.dispose(); - this._eqPower = null; - return this; - }; - return Tone.EqualPowerGain; -}(Tone_core_Tone); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_component_CrossFade; -Tone_component_CrossFade = function (Tone) { - 'use strict'; - Tone.CrossFade = function (initialFade) { - this.createInsOuts(2, 1); - this.a = this.input[0] = new Tone.Gain(); - this.b = this.input[1] = new Tone.Gain(); - this.fade = new Tone.Signal(this.defaultArg(initialFade, 0.5), Tone.Type.NormalRange); - this._equalPowerA = new Tone.EqualPowerGain(); - this._equalPowerB = new Tone.EqualPowerGain(); - this._invert = new Tone.Expr('1 - $0'); - this.a.connect(this.output); - this.b.connect(this.output); - this.fade.chain(this._equalPowerB, this.b.gain); - this.fade.chain(this._invert, this._equalPowerA, this.a.gain); - this._readOnly('fade'); - }; - Tone.extend(Tone.CrossFade); - Tone.CrossFade.prototype.dispose = function () { - Tone.prototype.dispose.call(this); - this._writable('fade'); - this._equalPowerA.dispose(); - this._equalPowerA = null; - this._equalPowerB.dispose(); - this._equalPowerB = null; - this.fade.dispose(); - this.fade = null; - this._invert.dispose(); - this._invert = null; - this.a.dispose(); - this.a = null; - this.b.dispose(); - this.b = null; - return this; - }; - return Tone.CrossFade; -}(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Expr, Tone_signal_EqualPowerGain); -var effect; -'use strict'; -effect = function () { - var p5sound = master; - var CrossFade = Tone_component_CrossFade; - /** - * Effect is a base class for audio effects in p5.
- * This module handles the nodes and methods that are - * common and useful for current and future effects. - * - * - * This class is extended by p5.Distortion, - * p5.Compressor, - * p5.Delay, - * p5.Filter, - * p5.Reverb. - * - * @class p5.Effect - * @constructor - * - * @param {Object} [ac] Reference to the audio context of the p5 object - * @param {AudioNode} [input] Gain Node effect wrapper - * @param {AudioNode} [output] Gain Node effect wrapper - * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1) - * @param {AudioNode} [wet] Effects that extend this class should connect - * to the wet signal to this gain node, so that dry and wet - * signals are mixed properly. - */ - p5.Effect = function () { - this.ac = p5sound.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); - /** - * The p5.Effect class is built - * using Tone.js CrossFade - * @private - */ - this._drywet = new CrossFade(1); - /** - * In classes that extend - * p5.Effect, connect effect nodes - * to the wet parameter - */ - this.wet = this.ac.createGain(); - this.input.connect(this._drywet.a); - this.wet.connect(this._drywet.b); - this._drywet.connect(this.output); - this.connect(); - //Add to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Set the output volume of the filter. - * - * @method amp - * @param {Number} [vol] amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts until rampTime - * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds - */ - p5.Effect.prototype.amp = function (vol, rampTime, tFromNow) { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + 0.001); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + 0.001); - }; - /** - * Link effects together in a chain - * Example usage: filter.chain(reverb, delay, panner); - * May be used with an open-ended number of arguments - * - * @method chain - * @param {Object} [arguments] Chain together multiple sound objects - */ - p5.Effect.prototype.chain = function () { - if (arguments.length > 0) { - this.connect(arguments[0]); - for (var i = 1; i < arguments.length; i += 1) { - arguments[i - 1].connect(arguments[i]); + this._param.exponentialRampToValueAtTime(value, endTime); } - } - return this; - }; - /** - * Adjust the dry/wet value. - * - * @method drywet - * @param {Number} [fade] The desired drywet value (0 - 1.0) - */ - p5.Effect.prototype.drywet = function (fade) { - if (typeof fade !== 'undefined') { - this._drywet.fade.value = fade; - } - return this._drywet.fade.value; - }; - /** - * Send output to a p5.js-sound, Web Audio Node, or use signal to - * control an AudioParam - * - * @method connect - * @param {Object} unit - */ - p5.Effect.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Effect.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - p5.Effect.prototype.dispose = function () { - // remove refernce form soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.input) { - this.input.disconnect(); - delete this.input; - } - if (this.output) { - this.output.disconnect(); - delete this.output; - } - if (this._drywet) { - this._drywet.disconnect(); - delete this._drywet; - } - if (this.wet) { - this.wet.disconnect(); - delete this.wet; - } - this.ac = undefined; - }; - return p5.Effect; -}(master, Tone_component_CrossFade); -var filter; -'use strict'; -filter = function () { - var p5sound = master; - var Effect = effect; - /** - *

A p5.Filter uses a Web Audio Biquad Filter to filter - * the frequency response of an input source. Subclasses - * include:

- * * p5.LowPass: - * Allows frequencies below the cutoff frequency to pass through, - * and attenuates frequencies above the cutoff.
- * * p5.HighPass: - * The opposite of a lowpass filter.
- * * p5.BandPass: - * Allows a range of frequencies to pass through and attenuates - * the frequencies below and above this frequency range.
- * - * The .res() method controls either width of the - * bandpass, or resonance of the low/highpass cutoff frequency. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Filter - * @extends p5.Effect - * @constructor - * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass' - * @example - *
- * var fft, noise, filter; - * - * function setup() { - * fill(255, 40, 255); - * - * filter = new p5.BandPass(); - * - * noise = new p5.Noise(); - * // disconnect unfiltered noise, - * // and connect to filter - * noise.disconnect(); - * noise.connect(filter); - * noise.start(); - * - * fft = new p5.FFT(); - * } - * - * function draw() { - * background(30); - * - * // set the BandPass frequency based on mouseX - * var freq = map(mouseX, 0, width, 20, 10000); - * filter.freq(freq); - * // give the filter a narrow band (lower res = wider bandpass) - * filter.res(50); - * - * // draw filtered spectrum - * var spectrum = fft.analyze(); - * noStroke(); - * for (var i = 0; i < spectrum.length; i++) { - * var x = map(i, 0, spectrum.length, 0, width); - * var h = -height + map(spectrum[i], 0, 255, height, 0); - * rect(x, height, width/spectrum.length, h); - * } - * - * isMouseOverCanvas(); - * } - * - * function isMouseOverCanvas() { - * var mX = mouseX, mY = mouseY; - * if (mX > 0 && mX < width && mY < height && mY > 0) { - * noise.amp(0.5, 0.2); - * } else { - * noise.amp(0, 0.2); - * } - * } - *
- */ - //constructor with inheritance - p5.Filter = function (type) { - Effect.call(this); - //add extend Effect by adding a Biquad Filter - /** - * The p5.Filter is built with a - * - * Web Audio BiquadFilter Node. - * - * @property {DelayNode} biquadFilter - */ - this.biquad = this.ac.createBiquadFilter(); - this.input.connect(this.biquad); - this.biquad.connect(this.wet); - if (type) { - this.setType(type); - } - //Properties useful for the toggle method. - this._on = true; - this._untoggledType = this.biquad.type; - }; - p5.Filter.prototype = Object.create(Effect.prototype); - /** - * Filter an audio signal according to a set - * of filter parameters. - * - * @method process - * @param {Object} Signal An object that outputs audio - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance/Width of the filter frequency - * from 0.001 to 1000 - */ - p5.Filter.prototype.process = function (src, freq, res, time) { - src.connect(this.input); - this.set(freq, res, time); - }; - /** - * Set the frequency and the resonance of the filter. - * - * @method set - * @param {Number} [freq] Frequency in Hz, from 10 to 22050 - * @param {Number} [res] Resonance (Q) from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - p5.Filter.prototype.set = function (freq, res, time) { - if (freq) { - this.freq(freq, time); - } - if (res) { - this.res(res, time); - } - }; - /** - * Set the filter frequency, in Hz, from 10 to 22050 (the range of - * human hearing, although in reality most people hear in a narrower - * range). - * - * @method freq - * @param {Number} freq Filter Frequency - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current frequency value - */ - p5.Filter.prototype.freq = function (freq, time) { - var t = time || 0; - if (freq <= 0) { - freq = 1; - } - if (typeof freq === 'number') { - this.biquad.frequency.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.frequency.exponentialRampToValueAtTime(freq, this.ac.currentTime + 0.02 + t); - } else if (freq) { - freq.connect(this.biquad.frequency); - } - return this.biquad.frequency.value; - }; - /** - * Controls either width of a bandpass frequency, - * or the resonance of a low/highpass cutoff frequency. - * - * @method res - * @param {Number} res Resonance/Width of filter freq - * from 0.001 to 1000 - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - * @return {Number} value Returns the current res value - */ - p5.Filter.prototype.res = function (res, time) { - var t = time || 0; - if (typeof res === 'number') { - this.biquad.Q.value = res; - this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.Q.linearRampToValueAtTime(res, this.ac.currentTime + 0.02 + t); - } else if (res) { - res.connect(this.biquad.Q); - } - return this.biquad.Q.value; - }; - /** - * Controls the gain attribute of a Biquad Filter. - * This is distinctly different from .amp() which is inherited from p5.Effect - * .amp() controls the volume via the output gain node - * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. - * - * @method gain - * @param {Number} gain - * @return {Number} Returns the current or updated gain value - */ - p5.Filter.prototype.gain = function (gain, time) { - var t = time || 0; - if (typeof gain === 'number') { - this.biquad.gain.value = gain; - this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.biquad.gain.linearRampToValueAtTime(gain, this.ac.currentTime + 0.02 + t); - } else if (gain) { - gain.connect(this.biquad.gain); - } - return this.biquad.gain.value; - }; - /** - * Toggle function. Switches between the specified type and allpass - * - * @method toggle - * @return {boolean} [Toggle value] - */ - p5.Filter.prototype.toggle = function () { - this._on = !this._on; - if (this._on === true) { - this.biquad.type = this._untoggledType; - } else if (this._on === false) { - this.biquad.type = 'allpass'; - } - return this._on; - }; - /** - * Set the type of a p5.Filter. Possible types include: - * "lowpass" (default), "highpass", "bandpass", - * "lowshelf", "highshelf", "peaking", "notch", - * "allpass". - * - * @method setType - * @param {String} t - */ - p5.Filter.prototype.setType = function (t) { - this.biquad.type = t; - this._untoggledType = this.biquad.type; - }; - p5.Filter.prototype.dispose = function () { - // remove reference from soundArray - Effect.prototype.dispose.apply(this); - if (this.biquad) { - this.biquad.disconnect(); - delete this.biquad; - } - }; - /** - * Constructor: new p5.LowPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('lowpass'). - * See p5.Filter for methods. - * - * @class p5.LowPass - * @constructor - * @extends p5.Filter - */ - p5.LowPass = function () { - p5.Filter.call(this, 'lowpass'); - }; - p5.LowPass.prototype = Object.create(p5.Filter.prototype); - /** - * Constructor: new p5.HighPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('highpass'). - * See p5.Filter for methods. - * - * @class p5.HighPass - * @constructor - * @extends p5.Filter - */ - p5.HighPass = function () { - p5.Filter.call(this, 'highpass'); - }; - p5.HighPass.prototype = Object.create(p5.Filter.prototype); - /** - * Constructor: new p5.BandPass() Filter. - * This is the same as creating a p5.Filter and then calling - * its method setType('bandpass'). - * See p5.Filter for methods. - * - * @class p5.BandPass - * @constructor - * @extends p5.Filter - */ - p5.BandPass = function () { - p5.Filter.call(this, 'bandpass'); - }; - p5.BandPass.prototype = Object.create(p5.Filter.prototype); - return p5.Filter; -}(master, effect); -var src_eqFilter; -'use strict'; -src_eqFilter = function () { - var Filter = filter; - var p5sound = master; - /** - * EQFilter extends p5.Filter with constraints - * necessary for the p5.EQ - * - * @private - */ - var EQFilter = function (freq, res) { - Filter.call(this, 'peaking'); - this.disconnect(); - this.set(freq, res); - this.biquad.gain.value = 0; - delete this.input; - delete this.output; - delete this._drywet; - delete this.wet; - }; - EQFilter.prototype = Object.create(Filter.prototype); - EQFilter.prototype.amp = function () { - console.warn('`amp()` is not available for p5.EQ bands. Use `.gain()`'); - }; - EQFilter.prototype.drywet = function () { - console.warn('`drywet()` is not available for p5.EQ bands.'); - }; - EQFilter.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - if (this.biquad) { - this.biquad.connect(u.input ? u.input : u); - } else { - this.output.connect(u.input ? u.input : u); - } - }; - EQFilter.prototype.disconnect = function () { - if (this.biquad) { - this.biquad.disconnect(); - } - }; - EQFilter.prototype.dispose = function () { - // remove reference form soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this.disconnect(); - delete this.biquad; - }; - return EQFilter; -}(filter, master); -var eq; -'use strict'; -eq = function () { - var Effect = effect; - var EQFilter = src_eqFilter; - /** - * p5.EQ is an audio effect that performs the function of a multiband - * audio equalizer. Equalization is used to adjust the balance of - * frequency compoenents of an audio signal. This process is commonly used - * in sound production and recording to change the waveform before it reaches - * a sound output device. EQ can also be used as an audio effect to create - * interesting distortions by filtering out parts of the spectrum. p5.EQ is - * built using a chain of Web Audio Biquad Filter Nodes and can be - * instantiated with 3 or 8 bands. Bands can be added or removed from - * the EQ by directly modifying p5.EQ.bands (the array that stores filters). - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.EQ - * @constructor - * @extends p5.Effect - * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 - * @return {Object} p5.EQ object - * - * @example - *
- * var eq; - * var band_names; - * var band_index; - * - * var soundFile, play; - * - * function preload() { - * soundFormats('mp3', 'ogg'); - * soundFile = loadSound('assets/beat'); - * } - * - * function setup() { - * eq = new p5.EQ(3); - * soundFile.disconnect(); - * eq.process(soundFile); - * - * band_names = ['lows','mids','highs']; - * band_index = 0; - * play = false; - * textAlign(CENTER); - * } - * - * function draw() { - * background(30); - * noStroke(); - * fill(255); - * text('click to kill',50,25); - * - * fill(255, 40, 255); - * textSize(26); - * text(band_names[band_index],50,55); - * - * fill(255); - * textSize(9); - * text('space = play/pause',50,80); - * } - * - * //If mouse is over canvas, cycle to the next band and kill the frequency - * function mouseClicked() { - * for (var i = 0; i < eq.bands.length; i++) { - * eq.bands[i].gain(0); - * } - * eq.bands[band_index].gain(-40); - * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { - * band_index === 2 ? band_index = 0 : band_index++; - * } - * } - * - * //use space bar to trigger play / pause - * function keyPressed() { - * if (key===' ') { - * play = !play - * play ? soundFile.loop() : soundFile.pause(); - * } - * } - *
- */ - p5.EQ = function (_eqsize) { - Effect.call(this); - //p5.EQ can be of size (3) or (8), defaults to 3 - _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; - var factor; - _eqsize === 3 ? factor = Math.pow(2, 3) : factor = 2; - /** - * The p5.EQ is built with abstracted p5.Filter objects. - * To modify any bands, use methods of the - * p5.Filter API, especially `gain` and `freq`. - * Bands are stored in an array, with indices 0 - 3, or 0 - 7 - * @property {Array} bands - * - */ - this.bands = []; - var freq, res; - for (var i = 0; i < _eqsize; i++) { - if (i === _eqsize - 1) { - freq = 21000; - res = 0.01; - } else if (i === 0) { - freq = 100; - res = 0.1; - } else if (i === 1) { - freq = _eqsize === 3 ? 360 * factor : 360; - res = 1; + return this; + }; + Tone.TimelineSignal.prototype.setTargetAtTime = function ( + value, + startTime, + timeConstant + ) { + value = this._fromUnits(value); + value = Math.max(this._minOutput, value); + timeConstant = Math.max(this._minOutput, timeConstant); + startTime = this.toSeconds(startTime); + this._events.add({ + type: Tone.TimelineSignal.Type.Target, + value: value, + time: startTime, + constant: timeConstant, + }); + this._param.setTargetAtTime(value, startTime, timeConstant); + return this; + }; + Tone.TimelineSignal.prototype.setValueCurveAtTime = function ( + values, + startTime, + duration, + scaling + ) { + scaling = this.defaultArg(scaling, 1); + var floats = new Array(values.length); + for (var i = 0; i < floats.length; i++) { + floats[i] = this._fromUnits(values[i]) * scaling; + } + startTime = this.toSeconds(startTime); + duration = this.toSeconds(duration); + this._events.add({ + type: Tone.TimelineSignal.Type.Curve, + value: floats, + time: startTime, + duration: duration, + }); + this._param.setValueAtTime(floats[0], startTime); + for (var j = 1; j < floats.length; j++) { + var segmentTime = startTime + (j / (floats.length - 1)) * duration; + this._param.linearRampToValueAtTime(floats[j], segmentTime); + } + return this; + }; + Tone.TimelineSignal.prototype.cancelScheduledValues = function (after) { + after = this.toSeconds(after); + this._events.cancel(after); + this._param.cancelScheduledValues(after); + return this; + }; + Tone.TimelineSignal.prototype.setRampPoint = function (time) { + time = this.toSeconds(time); + var val = this._toUnits(this.getValueAtTime(time)); + var before = this._searchBefore(time); + if (before && before.time === time) { + this.cancelScheduledValues(time + this.sampleTime); + } else if ( + before && + before.type === Tone.TimelineSignal.Type.Curve && + before.time + before.duration > time + ) { + this.cancelScheduledValues(time); + this.linearRampToValueAtTime(val, time); } else { - freq = this.bands[i - 1].freq() * factor; - res = 1; + var after = this._searchAfter(time); + if (after) { + this.cancelScheduledValues(time); + if (after.type === Tone.TimelineSignal.Type.Linear) { + this.linearRampToValueAtTime(val, time); + } else if (after.type === Tone.TimelineSignal.Type.Exponential) { + this.exponentialRampToValueAtTime(val, time); + } + } + this.setValueAtTime(val, time); } - this.bands[i] = this._newBand(freq, res); - if (i > 0) { - this.bands[i - 1].connect(this.bands[i].biquad); + return this; + }; + Tone.TimelineSignal.prototype.linearRampToValueBetween = function ( + value, + start, + finish + ) { + this.setRampPoint(start); + this.linearRampToValueAtTime(value, finish); + return this; + }; + Tone.TimelineSignal.prototype.exponentialRampToValueBetween = function ( + value, + start, + finish + ) { + this.setRampPoint(start); + this.exponentialRampToValueAtTime(value, finish); + return this; + }; + Tone.TimelineSignal.prototype._searchBefore = function (time) { + return this._events.get(time); + }; + Tone.TimelineSignal.prototype._searchAfter = function (time) { + return this._events.getAfter(time); + }; + Tone.TimelineSignal.prototype.getValueAtTime = function (time) { + time = this.toSeconds(time); + var after = this._searchAfter(time); + var before = this._searchBefore(time); + var value = this._initial; + if (before === null) { + value = this._initial; + } else if (before.type === Tone.TimelineSignal.Type.Target) { + var previous = this._events.getBefore(before.time); + var previouVal; + if (previous === null) { + previouVal = this._initial; + } else { + previouVal = previous.value; + } + value = this._exponentialApproach( + before.time, + previouVal, + before.value, + before.constant, + time + ); + } else if (before.type === Tone.TimelineSignal.Type.Curve) { + value = this._curveInterpolate( + before.time, + before.value, + before.duration, + time + ); + } else if (after === null) { + value = before.value; + } else if (after.type === Tone.TimelineSignal.Type.Linear) { + value = this._linearInterpolate( + before.time, + before.value, + after.time, + after.value, + time + ); + } else if (after.type === Tone.TimelineSignal.Type.Exponential) { + value = this._exponentialInterpolate( + before.time, + before.value, + after.time, + after.value, + time + ); } else { - this.input.connect(this.bands[i].biquad); + value = before.value; } - } - this.bands[_eqsize - 1].connect(this.output); - }; - p5.EQ.prototype = Object.create(Effect.prototype); - /** - * Process an input by connecting it to the EQ - * @method process - * @param {Object} src Audio source - */ - p5.EQ.prototype.process = function (src) { - src.connect(this.input); - }; - // /** - // * Set the frequency and gain of each band in the EQ. This method should be - // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. - // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); - // * - // * @method set - // * @param {Number} [freq0] Frequency value for band with index 0 - // * @param {Number} [gain0] Gain value for band with index 0 - // * @param {Number} [freq1] Frequency value for band with index 1 - // * @param {Number} [gain1] Gain value for band with index 1 - // * @param {Number} [freq2] Frequency value for band with index 2 - // * @param {Number} [gain2] Gain value for band with index 2 - // * @param {Number} [freq3] Frequency value for band with index 3 - // * @param {Number} [gain3] Gain value for band with index 3 - // * @param {Number} [freq4] Frequency value for band with index 4 - // * @param {Number} [gain4] Gain value for band with index 4 - // * @param {Number} [freq5] Frequency value for band with index 5 - // * @param {Number} [gain5] Gain value for band with index 5 - // * @param {Number} [freq6] Frequency value for band with index 6 - // * @param {Number} [gain6] Gain value for band with index 6 - // * @param {Number} [freq7] Frequency value for band with index 7 - // * @param {Number} [gain7] Gain value for band with index 7 - // */ - p5.EQ.prototype.set = function () { - if (arguments.length === this.bands.length * 2) { - for (var i = 0; i < arguments.length; i += 2) { - this.bands[i / 2].freq(arguments[i]); - this.bands[i / 2].gain(arguments[i + 1]); + return value; + }; + Tone.TimelineSignal.prototype.connect = Tone.SignalBase.prototype.connect; + Tone.TimelineSignal.prototype._exponentialApproach = function ( + t0, + v0, + v1, + timeConstant, + t + ) { + return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant); + }; + Tone.TimelineSignal.prototype._linearInterpolate = function ( + t0, + v0, + t1, + v1, + t + ) { + return v0 + (v1 - v0) * ((t - t0) / (t1 - t0)); + }; + Tone.TimelineSignal.prototype._exponentialInterpolate = function ( + t0, + v0, + t1, + v1, + t + ) { + v0 = Math.max(this._minOutput, v0); + return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0)); + }; + Tone.TimelineSignal.prototype._curveInterpolate = function ( + start, + curve, + duration, + time + ) { + var len = curve.length; + if (time >= start + duration) { + return curve[len - 1]; + } else if (time <= start) { + return curve[0]; + } else { + var progress = (time - start) / duration; + var lowerIndex = Math.floor((len - 1) * progress); + var upperIndex = Math.ceil((len - 1) * progress); + var lowerVal = curve[lowerIndex]; + var upperVal = curve[upperIndex]; + if (upperIndex === lowerIndex) { + return lowerVal; + } else { + return this._linearInterpolate( + lowerIndex, + lowerVal, + upperIndex, + upperVal, + progress * (len - 1) + ); + } } - } else { - console.error('Argument mismatch. .set() should be called with ' + this.bands.length * 2 + ' arguments. (one frequency and gain value pair for each band of the eq)'); - } - }; - /** - * Add a new band. Creates a p5.Filter and strips away everything but - * the raw biquad filter. This method returns an abstracted p5.Filter, - * which can be added to p5.EQ.bands, in order to create new EQ bands. - * @private - * @method _newBand - * @param {Number} freq - * @param {Number} res - * @return {Object} Abstracted Filter - */ - p5.EQ.prototype._newBand = function (freq, res) { - return new EQFilter(freq, res); - }; - p5.EQ.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.bands) { - while (this.bands.length > 0) { - delete this.bands.pop().dispose(); - } - delete this.bands; - } - }; - return p5.EQ; -}(effect, src_eqFilter); -var panner3d; -'use strict'; -panner3d = function () { - var p5sound = master; - var Effect = effect; - /** - * Panner3D is based on the - * Web Audio Spatial Panner Node. - * This panner is a spatial processing node that allows audio to be positioned - * and oriented in 3D space. - * - * The position is relative to an - * Audio Context Listener, which can be accessed - * by p5.soundOut.audiocontext.listener - * - * - * @class p5.Panner3D - * @constructor - */ - p5.Panner3D = function () { - Effect.call(this); - /** - * - * Web Audio Spatial Panner Node - * - * Properties include - * - panningModel: "equal power" or "HRTF" - * - distanceModel: "linear", "inverse", or "exponential" - * - * @property {AudioNode} panner - * - */ - this.panner = this.ac.createPanner(); - this.panner.panningModel = 'HRTF'; - this.panner.distanceModel = 'linear'; - this.panner.connect(this.output); - this.input.connect(this.panner); - }; - p5.Panner3D.prototype = Object.create(Effect.prototype); - /** - * Connect an audio sorce - * - * @method process - * @param {Object} src Input source - */ - p5.Panner3D.prototype.process = function (src) { - src.connect(this.input); - }; - /** - * Set the X,Y,Z position of the Panner - * @method set - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ - p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [ - this.panner.positionX.value, - this.panner.positionY.value, - this.panner.positionZ.value - ]; - }; - /** - * Getter and setter methods for position coordinates - * @method positionX - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for position coordinates - * @method positionY - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for position coordinates - * @method positionZ - * @return {Number} updated coordinate value - */ - p5.Panner3D.prototype.positionX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.panner.positionX.value = xVal; - this.panner.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.positionX); - } - return this.panner.positionX.value; - }; - p5.Panner3D.prototype.positionY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.panner.positionY.value = yVal; - this.panner.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.positionY); - } - return this.panner.positionY.value; - }; - p5.Panner3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.panner.positionZ.value = zVal; - this.panner.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.positionZ); - } - return this.panner.positionZ.value; - }; - /** - * Set the X,Y,Z position of the Panner - * @method orient - * @param {Number} xVal - * @param {Number} yVal - * @param {Number} zVal - * @param {Number} time - * @return {Array} Updated x, y, z values as an array - */ - p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) { - this.orientX(xVal, time); - this.orientY(yVal, time); - this.orientZ(zVal, time); - return [ - this.panner.orientationX.value, - this.panner.orientationY.value, - this.panner.orientationZ.value - ]; - }; - /** - * Getter and setter methods for orient coordinates - * @method orientX - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for orient coordinates - * @method orientY - * @return {Number} updated coordinate value - */ - /** - * Getter and setter methods for orient coordinates - * @method orientZ - * @return {Number} updated coordinate value - */ - p5.Panner3D.prototype.orientX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.panner.orientationX.value = xVal; - this.panner.orientationX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.panner.orientationX); - } - return this.panner.orientationX.value; - }; - p5.Panner3D.prototype.orientY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.panner.orientationY.value = yVal; - this.panner.orientationY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.panner.orientationY); - } - return this.panner.orientationY.value; - }; - p5.Panner3D.prototype.orientZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.panner.orientationZ.value = zVal; - this.panner.orientationZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.panner.orientationZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.panner.orientationZ); - } - return this.panner.orientationZ.value; - }; - /** - * Set the rolloff factor and max distance - * @method setFalloff - * @param {Number} [maxDistance] - * @param {Number} [rolloffFactor] - */ - p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) { - this.maxDist(maxDistance); - this.rolloff(rolloffFactor); - }; - /** - * Maxium distance between the source and the listener - * @method maxDist - * @param {Number} maxDistance - * @return {Number} updated value - */ - p5.Panner3D.prototype.maxDist = function (maxDistance) { - if (typeof maxDistance === 'number') { - this.panner.maxDistance = maxDistance; - } - return this.panner.maxDistance; - }; - /** - * How quickly the volume is reduced as the source moves away from the listener - * @method rollof - * @param {Number} rolloffFactor - * @return {Number} updated value - */ - p5.Panner3D.prototype.rolloff = function (rolloffFactor) { - if (typeof rolloffFactor === 'number') { - this.panner.rolloffFactor = rolloffFactor; - } - return this.panner.rolloffFactor; - }; - p5.Panner3D.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.panner) { - this.panner.disconnect(); - delete this.panner; - } - }; - return p5.Panner3D; -}(master, effect); -var listener3d; -'use strict'; -listener3d = function () { - var p5sound = master; - var Effect = effect; - // /** - // * listener is a class that can construct both a Spatial Panner - // * and a Spatial Listener. The panner is based on the - // * Web Audio Spatial Panner Node - // * https://www.w3.org/TR/webaudio/#the-listenernode-interface - // * This panner is a spatial processing node that allows audio to be positioned - // * and oriented in 3D space. - // * - // * The Listener modifies the properties of the Audio Context Listener. - // * Both objects types use the same methods. The default is a spatial panner. - // * - // * p5.Panner3D - Constructs a Spatial Panner
- // * p5.Listener3D - Constructs a Spatial Listener
- // * - // * @class listener - // * @constructor - // * @return {Object} p5.Listener3D Object - // * - // * @param {Web Audio Node} listener Web Audio Spatial Panning Node - // * @param {AudioParam} listener.panningModel "equal power" or "HRTF" - // * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential" - // * @param {String} [type] [Specify construction of a spatial panner or listener] - // */ - p5.Listener3D = function (type) { - this.ac = p5sound.audiocontext; - this.listener = this.ac.listener; - }; - // /** - // * Connect an audio sorce - // * @param {Object} src Input source - // */ - p5.Listener3D.prototype.process = function (src) { - src.connect(this.input); - }; - // /** - // * Set the X,Y,Z position of the Panner - // * @param {[Number]} xVal - // * @param {[Number]} yVal - // * @param {[Number]} zVal - // * @param {[Number]} time - // * @return {[Array]} [Updated x, y, z values as an array] - // */ - p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) { - this.positionX(xVal, time); - this.positionY(yVal, time); - this.positionZ(zVal, time); - return [ - this.listener.positionX.value, - this.listener.positionY.value, - this.listener.positionZ.value - ]; - }; - // /** - // * Getter and setter methods for position coordinates - // * @return {Number} [updated coordinate value] - // */ - p5.Listener3D.prototype.positionX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.positionX.value = xVal; - this.listener.positionX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.positionX); - } - return this.listener.positionX.value; - }; - p5.Listener3D.prototype.positionY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.positionY.value = yVal; - this.listener.positionY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.positionY); - } - return this.listener.positionY.value; - }; - p5.Listener3D.prototype.positionZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.positionZ.value = zVal; - this.listener.positionZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.positionZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.positionZ); - } - return this.listener.positionZ.value; - }; - // cannot define method when class definition is commented - // /** - // * Overrides the listener orient() method because Listener has slightly - // * different params. In human terms, Forward vectors are the direction the - // * nose is pointing. Up vectors are the direction of the top of the head. - // * - // * @method orient - // * @param {Number} xValF Forward vector X direction - // * @param {Number} yValF Forward vector Y direction - // * @param {Number} zValF Forward vector Z direction - // * @param {Number} xValU Up vector X direction - // * @param {Number} yValU Up vector Y direction - // * @param {Number} zValU Up vector Z direction - // * @param {Number} time - // * @return {Array} All orienation params - // */ - p5.Listener3D.prototype.orient = function (xValF, yValF, zValF, xValU, yValU, zValU, time) { - if (arguments.length === 3 || arguments.length === 4) { - time = arguments[3]; - this.orientForward(xValF, yValF, zValF, time); - } else if (arguments.length === 6 || arguments === 7) { - this.orientForward(xValF, yValF, zValF); - this.orientUp(xValU, yValU, zValU, time); - } - return [ - this.listener.forwardX.value, - this.listener.forwardY.value, - this.listener.forwardZ.value, - this.listener.upX.value, - this.listener.upY.value, - this.listener.upZ.value - ]; - }; - p5.Listener3D.prototype.orientForward = function (xValF, yValF, zValF, time) { - this.forwardX(xValF, time); - this.forwardY(yValF, time); - this.forwardZ(zValF, time); - return [ - this.listener.forwardX, - this.listener.forwardY, - this.listener.forwardZ - ]; - }; - p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) { - this.upX(xValU, time); - this.upY(yValU, time); - this.upZ(zValU, time); - return [ - this.listener.upX, - this.listener.upY, - this.listener.upZ - ]; - }; - // /** - // * Getter and setter methods for orient coordinates - // * @return {Number} [updated coordinate value] - // */ - p5.Listener3D.prototype.forwardX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.forwardX.value = xVal; - this.listener.forwardX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.forwardX); - } - return this.listener.forwardX.value; - }; - p5.Listener3D.prototype.forwardY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.forwardY.value = yVal; - this.listener.forwardY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.forwardY); - } - return this.listener.forwardY.value; - }; - p5.Listener3D.prototype.forwardZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.forwardZ.value = zVal; - this.listener.forwardZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.forwardZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.forwardZ); - } - return this.listener.forwardZ.value; - }; - p5.Listener3D.prototype.upX = function (xVal, time) { - var t = time || 0; - if (typeof xVal === 'number') { - this.listener.upX.value = xVal; - this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upX.linearRampToValueAtTime(xVal, this.ac.currentTime + 0.02 + t); - } else if (xVal) { - xVal.connect(this.listener.upX); - } - return this.listener.upX.value; - }; - p5.Listener3D.prototype.upY = function (yVal, time) { - var t = time || 0; - if (typeof yVal === 'number') { - this.listener.upY.value = yVal; - this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upY.linearRampToValueAtTime(yVal, this.ac.currentTime + 0.02 + t); - } else if (yVal) { - yVal.connect(this.listener.upY); - } - return this.listener.upY.value; - }; - p5.Listener3D.prototype.upZ = function (zVal, time) { - var t = time || 0; - if (typeof zVal === 'number') { - this.listener.upZ.value = zVal; - this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.listener.upZ.linearRampToValueAtTime(zVal, this.ac.currentTime + 0.02 + t); - } else if (zVal) { - zVal.connect(this.listener.upZ); - } - return this.listener.upZ.value; - }; - return p5.Listener3D; -}(master, effect); -var delay; -'use strict'; -delay = function () { - var Filter = filter; - var Effect = effect; - /** - * Delay is an echo effect. It processes an existing sound source, - * and outputs a delayed version of that sound. The p5.Delay can - * produce different effects depending on the delayTime, feedback, - * filter, and type. In the example below, a feedback of 0.5 (the - * defaul value) will produce a looping delay that decreases in - * volume by 50% each repeat. A filter will cut out the high - * frequencies so that the delay does not sound as piercing as the - * original source. - * - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * @class p5.Delay - * @extends p5.Effect - * @constructor - * @example - *
- * var noise, env, delay; - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * - * noise = new p5.Noise('brown'); - * noise.amp(0); - * noise.start(); - * - * delay = new p5.Delay(); - * - * // delay.process() accepts 4 parameters: - * // source, delayTime, feedback, filter frequency - * // play with these numbers!! - * delay.process(noise, .12, .7, 2300); - * - * // play the noise with an envelope, - * // a series of fades ( time / value pairs ) - * env = new p5.Envelope(.01, 0.2, .2, .1); - * } - * - * // mouseClick triggers envelope - * function mouseClicked() { - * // is mouse over canvas? - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * env.play(noise); - * } - * } - *
- */ - p5.Delay = function () { - Effect.call(this); - this._split = this.ac.createChannelSplitter(2); - this._merge = this.ac.createChannelMerger(2); - this._leftGain = this.ac.createGain(); - this._rightGain = this.ac.createGain(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * - * @property {DelayNode} leftDelay - */ - this.leftDelay = this.ac.createDelay(); - /** - * The p5.Delay is built with two - * - * Web Audio Delay Nodes, one for each stereo channel. - * - * @property {DelayNode} rightDelay - */ - this.rightDelay = this.ac.createDelay(); - this._leftFilter = new Filter(); - this._rightFilter = new Filter(); - this._leftFilter.disconnect(); - this._rightFilter.disconnect(); - this._leftFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); - this._rightFilter.biquad.frequency.setValueAtTime(1200, this.ac.currentTime); - this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); - this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); - // graph routing - this.input.connect(this._split); - this.leftDelay.connect(this._leftGain); - this.rightDelay.connect(this._rightGain); - this._leftGain.connect(this._leftFilter.input); - this._rightGain.connect(this._rightFilter.input); - this._merge.connect(this.wet); - this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); - this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); - // default routing - this.setType(0); - this._maxDelay = this.leftDelay.delayTime.maxValue; - // set initial feedback to 0.5 - this.feedback(0.5); - }; - p5.Delay.prototype = Object.create(Effect.prototype); - /** - * Add delay to an audio signal according to a set - * of delay parameters. - * - * @method process - * @param {Object} Signal An object that outputs audio - * @param {Number} [delayTime] Time (in seconds) of the delay/echo. - * Some browsers limit delayTime to - * 1 second. - * @param {Number} [feedback] sends the delay back through itself - * in a loop that decreases in volume - * each time. - * @param {Number} [lowPass] Cutoff frequency. Only frequencies - * below the lowPass will be part of the - * delay. - */ - p5.Delay.prototype.process = function (src, _delayTime, _feedback, _filter) { - var feedback = _feedback || 0; - var delayTime = _delayTime || 0; - if (feedback >= 1) { - throw new Error('Feedback value will force a positive feedback loop.'); - } - if (delayTime >= this._maxDelay) { - throw new Error('Delay Time exceeds maximum delay time of ' + this._maxDelay + ' second.'); - } - src.connect(this.input); - this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); - this._leftGain.gain.value = feedback; - this._rightGain.gain.value = feedback; - if (_filter) { - this._leftFilter.freq(_filter); - this._rightFilter.freq(_filter); - } - }; - /** - * Set the delay (echo) time, in seconds. Usually this value will be - * a floating point number between 0.0 and 1.0. - * - * @method delayTime - * @param {Number} delayTime Time (in seconds) of the delay - */ - p5.Delay.prototype.delayTime = function (t) { - // if t is an audio node... - if (typeof t !== 'number') { - t.connect(this.leftDelay.delayTime); - t.connect(this.rightDelay.delayTime); - } else { - this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime); - this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime); - this.leftDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime); - this.rightDelay.delayTime.linearRampToValueAtTime(t, this.ac.currentTime); - } - }; - /** - * Feedback occurs when Delay sends its signal back through its input - * in a loop. The feedback amount determines how much signal to send each - * time through the loop. A feedback greater than 1.0 is not desirable because - * it will increase the overall output each time through the loop, - * creating an infinite feedback loop. The default value is 0.5 - * - * @method feedback - * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an - * Oscillator that can be used to - * modulate this param - * @returns {Number} Feedback value - * - */ - p5.Delay.prototype.feedback = function (f) { - // if f is an audio node... - if (f && typeof f !== 'number') { - f.connect(this._leftGain.gain); - f.connect(this._rightGain.gain); - } else if (f >= 1) { - throw new Error('Feedback value will force a positive feedback loop.'); - } else if (typeof f === 'number') { - this._leftGain.gain.value = f; - this._rightGain.gain.value = f; - } - // return value of feedback - return this._leftGain.gain.value; - }; - /** - * Set a lowpass filter frequency for the delay. A lowpass filter - * will cut off any frequencies higher than the filter frequency. - * - * @method filter - * @param {Number|Object} cutoffFreq A lowpass filter will cut off any - * frequencies higher than the filter frequency. - * @param {Number|Object} res Resonance of the filter frequency - * cutoff, or an object (i.e. a p5.Oscillator) - * that can be used to modulate this parameter. - * High numbers (i.e. 15) will produce a resonance, - * low numbers (i.e. .2) will produce a slope. - */ - p5.Delay.prototype.filter = function (freq, q) { - this._leftFilter.set(freq, q); - this._rightFilter.set(freq, q); - }; - /** - * Choose a preset type of delay. 'pingPong' bounces the signal - * from the left to the right channel to produce a stereo effect. - * Any other parameter will revert to the default delay setting. - * - * @method setType - * @param {String|Number} type 'pingPong' (1) or 'default' (0) - */ - p5.Delay.prototype.setType = function (t) { - if (t === 1) { - t = 'pingPong'; - } - this._split.disconnect(); - this._leftFilter.disconnect(); - this._rightFilter.disconnect(); - this._split.connect(this.leftDelay, 0); - this._split.connect(this.rightDelay, 1); - switch (t) { - case 'pingPong': - this._rightFilter.setType(this._leftFilter.biquad.type); - this._leftFilter.output.connect(this._merge, 0, 0); - this._rightFilter.output.connect(this._merge, 0, 1); - this._leftFilter.output.connect(this.rightDelay); - this._rightFilter.output.connect(this.leftDelay); - break; - default: - this._leftFilter.output.connect(this._merge, 0, 0); - this._rightFilter.output.connect(this._merge, 0, 1); - this._leftFilter.output.connect(this.leftDelay); - this._rightFilter.output.connect(this.rightDelay); - } - }; - // DocBlocks for methods inherited from p5.Effect - /** - * Set the output level of the delay effect. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Delay.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - this._split.disconnect(); - this._leftFilter.dispose(); - this._rightFilter.dispose(); - this._merge.disconnect(); - this._leftGain.disconnect(); - this._rightGain.disconnect(); - this.leftDelay.disconnect(); - this.rightDelay.disconnect(); - this._split = undefined; - this._leftFilter = undefined; - this._rightFilter = undefined; - this._merge = undefined; - this._leftGain = undefined; - this._rightGain = undefined; - this.leftDelay = undefined; - this.rightDelay = undefined; - }; -}(filter, effect); -var reverb; -'use strict'; -reverb = function () { - var CustomError = errorHandler; - var Effect = effect; - /** - * Reverb adds depth to a sound through a large number of decaying - * echoes. It creates the perception that sound is occurring in a - * physical space. The p5.Reverb has paramters for Time (how long does the - * reverb last) and decayRate (how much the sound decays with each echo) - * that can be set with the .set() or .process() methods. The p5.Convolver - * extends p5.Reverb allowing you to recreate the sound of actual physical - * spaces through convolution. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Reverb - * @extends p5.Effect - * @constructor - * @example - *
- * var soundFile, reverb; - * function preload() { - * soundFile = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * reverb = new p5.Reverb(); - * soundFile.disconnect(); // so we'll only hear reverb... - * - * // connect soundFile to reverb, process w/ - * // 3 second reverbTime, decayRate of 2% - * reverb.process(soundFile, 3, 2); - * soundFile.play(); - * } - *
- */ - p5.Reverb = function () { - Effect.call(this); - this._initConvolverNode(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - // default params - this._seconds = 3; - this._decay = 2; - this._reverse = false; - this._buildImpulse(); - }; - p5.Reverb.prototype = Object.create(Effect.prototype); - p5.Reverb.prototype._initConvolverNode = function () { - this.convolverNode = this.ac.createConvolver(); - this.input.connect(this.convolverNode); - this.convolverNode.connect(this.wet); - }; - p5.Reverb.prototype._teardownConvolverNode = function () { - if (this.convolverNode) { - this.convolverNode.disconnect(); - delete this.convolverNode; - } - }; - p5.Reverb.prototype._setBuffer = function (audioBuffer) { - this._teardownConvolverNode(); - this._initConvolverNode(); - this.convolverNode.buffer = audioBuffer; - }; - /** - * Connect a source to the reverb, and assign reverb parameters. - * - * @method process - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ - p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) { - src.connect(this.input); - var rebuild = false; - if (seconds) { - this._seconds = seconds; - rebuild = true; - } - if (decayRate) { - this._decay = decayRate; - } - if (reverse) { - this._reverse = reverse; - } - if (rebuild) { - this._buildImpulse(); - } - }; - /** - * Set the reverb settings. Similar to .process(), but without - * assigning a new input. - * - * @method set - * @param {Number} [seconds] Duration of the reverb, in seconds. - * Min: 0, Max: 10. Defaults to 3. - * @param {Number} [decayRate] Percentage of decay with each echo. - * Min: 0, Max: 100. Defaults to 2. - * @param {Boolean} [reverse] Play the reverb backwards or forwards. - */ - p5.Reverb.prototype.set = function (seconds, decayRate, reverse) { - var rebuild = false; - if (seconds) { - this._seconds = seconds; - rebuild = true; - } - if (decayRate) { - this._decay = decayRate; - } - if (reverse) { - this._reverse = reverse; - } - if (rebuild) { - this._buildImpulse(); - } - }; - // DocBlocks for methods inherited from p5.Effect - /** - * Set the output level of the reverb effect. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - /** - * Disconnect all output. - * - * @method disconnect - */ - /** - * Inspired by Simple Reverb by Jordan Santell - * https://github.com/web-audio-components/simple-reverb/blob/master/index.js - * - * Utility function for building an impulse response - * based on the module parameters. - * - * @private - */ - p5.Reverb.prototype._buildImpulse = function () { - var rate = this.ac.sampleRate; - var length = rate * this._seconds; - var decay = this._decay; - var impulse = this.ac.createBuffer(2, length, rate); - var impulseL = impulse.getChannelData(0); - var impulseR = impulse.getChannelData(1); - var n, i; - for (i = 0; i < length; i++) { - n = this._reverse ? length - i : i; - impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); - } - this._setBuffer(impulse); - }; - p5.Reverb.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - this._teardownConvolverNode(); - }; - // ======================================================================= - // *** p5.Convolver *** - // ======================================================================= - /** - *

p5.Convolver extends p5.Reverb. It can emulate the sound of real - * physical spaces through a process called - * convolution.

- * - *

Convolution multiplies any audio input by an "impulse response" - * to simulate the dispersion of sound over time. The impulse response is - * generated from an audio file that you provide. One way to - * generate an impulse response is to pop a balloon in a reverberant space - * and record the echo. Convolution can also be used to experiment with - * sound.

- * - *

Use the method createConvolution(path) to instantiate a - * p5.Convolver with a path to your impulse response audio file.

- * - * @class p5.Convolver - * @extends p5.Effect - * @constructor - * @param {String} path path to a sound file - * @param {Function} [callback] function to call when loading succeeds - * @param {Function} [errorCallback] function to call if loading fails. - * This function will receive an error or - * XMLHttpRequest object with information - * about what went wrong. - * @example - *
- * var cVerb, sound; - * function preload() { - * // We have both MP3 and OGG versions of all sound assets - * soundFormats('ogg', 'mp3'); - * - * // Try replacing 'bx-spring' with other soundfiles like - * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' - * cVerb = createConvolver('assets/bx-spring.mp3'); - * - * // Try replacing 'Damscray_DancingTiger' with - * // 'beat', 'doorbell', lucky_dragons_-_power_melody' - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.Convolver = function (path, callback, errorCallback) { - p5.Reverb.call(this); + }; + Tone.TimelineSignal.prototype.dispose = function () { + Tone.Signal.prototype.dispose.call(this); + Tone.Param.prototype.dispose.call(this); + this._events.dispose(); + this._events = null; + }; + return Tone.TimelineSignal; + })(Tone_core_Tone, Tone_signal_Signal); + var envelope; + ("use strict"); + envelope = (function () { + var p5sound = master; + var Add = Tone_signal_Add; + var Mult = Tone_signal_Multiply; + var Scale = Tone_signal_Scale; + var TimelineSignal = Tone_signal_TimelineSignal; /** - * Internally, the p5.Convolver uses the a - * - * Web Audio Convolver Node. + *

Envelopes are pre-defined amplitude distribution over time. + * Typically, envelopes are used to control the output volume + * of an object, a series of fades referred to as Attack, Decay, + * Sustain and Release ( + * ADSR + * ). Envelopes can also control other Web Audio Parameters—for example, a p5.Envelope can + * control an Oscillator's frequency like this: osc.freq(env).

+ *

Use setRange to change the attack/release level. + * Use setADSR to change attackTime, decayTime, sustainPercent and releaseTime.

+ *

Use the play method to play the entire envelope, + * the ramp method for a pingable trigger, + * or triggerAttack/ + * triggerRelease to trigger noteOn/noteOff.

+ * + * @class p5.Envelope + * @constructor + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); * - * @property {ConvolverNode} convolverNode + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
*/ - this._initConvolverNode(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - if (path) { - this.impulses = []; - this._loadBuffer(path, callback, errorCallback); - } else { - // parameters - this._seconds = 3; - this._decay = 2; - this._reverse = false; - this._buildImpulse(); - } - }; - p5.Convolver.prototype = Object.create(p5.Reverb.prototype); - p5.prototype.registerPreloadMethod('createConvolver', p5.prototype); - /** - * Create a p5.Convolver. Accepts a path to a soundfile - * that will be used to generate an impulse response. - * - * @method createConvolver - * @param {String} path path to a sound file - * @param {Function} [callback] function to call if loading is successful. - * The object will be passed in as the argument - * to the callback function. - * @param {Function} [errorCallback] function to call if loading is not successful. - * A custom error will be passed in as the argument - * to the callback function. - * @return {p5.Convolver} - * @example - *
- * var cVerb, sound; - * function preload() { - * // We have both MP3 and OGG versions of all sound assets - * soundFormats('ogg', 'mp3'); - * - * // Try replacing 'bx-spring' with other soundfiles like - * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' - * cVerb = createConvolver('assets/bx-spring.mp3'); - * - * // Try replacing 'Damscray_DancingTiger' with - * // 'beat', 'doorbell', lucky_dragons_-_power_melody' - * sound = loadSound('assets/Damscray_DancingTiger.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.prototype.createConvolver = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - var self = this; - var cReverb = new p5.Convolver(path, function (buffer) { - if (typeof callback === 'function') { - callback(buffer); - } - if (typeof self._decrementPreload === 'function') { - self._decrementPreload(); - } - }, errorCallback); - cReverb.impulses = []; - return cReverb; - }; - /** - * Private method to load a buffer as an Impulse Response, - * assign it to the convolverNode, and add to the Array of .impulses. - * - * @param {String} path - * @param {Function} callback - * @param {Function} errorCallback - * @private - */ - p5.Convolver.prototype._loadBuffer = function (path, callback, errorCallback) { - var path = p5.prototype._checkFileFormats(path); - var self = this; - var errorTrace = new Error().stack; - var ac = p5.prototype.getAudioContext(); - var request = new XMLHttpRequest(); - request.open('GET', path, true); - request.responseType = 'arraybuffer'; - request.onload = function () { - if (request.status === 200) { - // on success loading file: - ac.decodeAudioData(request.response, function (buff) { - var buffer = {}; - var chunks = path.split('/'); - buffer.name = chunks[chunks.length - 1]; - buffer.audioBuffer = buff; - self.impulses.push(buffer); - self._setBuffer(buffer.audioBuffer); - if (callback) { - callback(buffer); - } - }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 - function () { - var err = new CustomError('decodeAudioData', errorTrace, self.url); - var msg = 'AudioContext error at decodeAudioData for ' + self.url; - if (errorCallback) { - err.msg = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - }); - } else { - var err = new CustomError('loadConvolver', errorTrace, self.url); - var msg = 'Unable to load ' + self.url + '. The request status was: ' + request.status + ' (' + request.statusText + ')'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } - } + p5.Envelope = function (t1, l1, t2, l2, t3, l3) { + /** + * Time until envelope reaches attackLevel + * @property attackTime + */ + this.aTime = t1 || 0.1; + /** + * Level once attack is complete. + * @property attackLevel + */ + this.aLevel = l1 || 1; + /** + * Time until envelope reaches decayLevel. + * @property decayTime + */ + this.dTime = t2 || 0.5; + /** + * Level after decay. The envelope will sustain here until it is released. + * @property decayLevel + */ + this.dLevel = l2 || 0; + /** + * Duration of the release portion of the envelope. + * @property releaseTime + */ + this.rTime = t3 || 0; + /** + * Level at the end of the release. + * @property releaseLevel + */ + this.rLevel = l3 || 0; + this._rampHighPercentage = 0.98; + this._rampLowPercentage = 0.02; + this.output = p5sound.audiocontext.createGain(); + this.control = new TimelineSignal(); + this._init(); + // this makes sure the envelope starts at zero + this.control.connect(this.output); + // connect to the output + this.connection = null; + // store connection + //array of math operation signal chaining + this.mathOps = [this.control]; + //whether envelope should be linear or exponential curve + this.isExponential = false; + // oscillator or buffer source to clear on env complete + // to save resources if/when it is retriggered + this.sourceToClear = null; + // set to true if attack is set, then false on release + this.wasTriggered = false; + // add to the soundArray so we can dispose of the env later + p5sound.soundArray.push(this); }; - // if there is another error, aside from 404... - request.onerror = function () { - var err = new CustomError('loadConvolver', errorTrace, self.url); - var msg = 'There was no response from the server at ' + self.url + '. Check the url and internet connectivity.'; - if (errorCallback) { - err.message = msg; - errorCallback(err); - } else { - console.error(msg + '\n The error stack trace includes: \n' + err.stack); - } + // this init function just smooths the starting value to zero and gives a start point for the timeline + // - it was necessary to remove glitches at the beginning. + p5.Envelope.prototype._init = function () { + var now = p5sound.audiocontext.currentTime; + var t = now; + this.control.setTargetAtTime(0.00001, t, 0.001); + //also, compute the correct time constants + this._setRampAD(this.aTime, this.dTime); }; - request.send(); - }; - p5.Convolver.prototype.set = null; - /** - * Connect a source to the reverb, and assign reverb parameters. - * - * @method process - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - * @example - *
- * var cVerb, sound; - * function preload() { - * soundFormats('ogg', 'mp3'); - * - * cVerb = createConvolver('assets/concrete-tunnel.mp3'); - * - * sound = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * // disconnect from master output... - * sound.disconnect(); - * - * // ...and process with (i.e. connect to) cVerb - * // so that we only hear the convolution - * cVerb.process(sound); - * - * sound.play(); - * } - *
- */ - p5.Convolver.prototype.process = function (src) { - src.connect(this.input); - }; - /** - * If you load multiple impulse files using the .addImpulse method, - * they will be stored as Objects in this Array. Toggle between them - * with the toggleImpulse(id) method. - * - * @property {Array} impulses - */ - p5.Convolver.prototype.impulses = []; - /** - * Load and assign a new Impulse Response to the p5.Convolver. - * The impulse is added to the .impulses array. Previous - * impulses can be accessed with the .toggleImpulse(id) - * method. - * - * @method addImpulse - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - p5.Convolver.prototype.addImpulse = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - this._loadBuffer(path, callback, errorCallback); - }; - /** - * Similar to .addImpulse, except that the .impulses - * Array is reset to save memory. A new .impulses - * array is created with this impulse as the only item. - * - * @method resetImpulse - * @param {String} path path to a sound file - * @param {Function} callback function (optional) - * @param {Function} errorCallback function (optional) - */ - p5.Convolver.prototype.resetImpulse = function (path, callback, errorCallback) { - // if loading locally without a server - if (window.location.origin.indexOf('file://') > -1 && window.cordova === 'undefined') { - alert('This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS'); - } - this.impulses = []; - this._loadBuffer(path, callback, errorCallback); - }; - /** - * If you have used .addImpulse() to add multiple impulses - * to a p5.Convolver, then you can use this method to toggle between - * the items in the .impulses Array. Accepts a parameter - * to identify which impulse you wish to use, identified either by its - * original filename (String) or by its position in the .impulses - * Array (Number).
- * You can access the objects in the .impulses Array directly. Each - * Object has two attributes: an .audioBuffer (type: - * Web Audio - * AudioBuffer) and a .name, a String that corresponds - * with the original filename. - * - * @method toggleImpulse - * @param {String|Number} id Identify the impulse by its original filename - * (String), or by its position in the - * .impulses Array (Number). - */ - p5.Convolver.prototype.toggleImpulse = function (id) { - if (typeof id === 'number' && id < this.impulses.length) { - this._setBuffer(this.impulses[id].audioBuffer); - } - if (typeof id === 'string') { - for (var i = 0; i < this.impulses.length; i++) { - if (this.impulses[i].name === id) { - this._setBuffer(this.impulses[i].audioBuffer); - break; - } - } - } - }; - p5.Convolver.prototype.dispose = function () { - p5.Reverb.prototype.dispose.apply(this); - // remove all the Impulse Response buffers - for (var i in this.impulses) { - if (this.impulses[i]) { - this.impulses[i] = null; - } - } - }; -}(errorHandler, effect); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_TimelineState; -Tone_core_TimelineState = function (Tone) { - 'use strict'; - Tone.TimelineState = function (initial) { - Tone.Timeline.call(this); - this._initial = initial; - }; - Tone.extend(Tone.TimelineState, Tone.Timeline); - Tone.TimelineState.prototype.getValueAtTime = function (time) { - var event = this.get(time); - if (event !== null) { - return event.state; - } else { - return this._initial; - } - }; - Tone.TimelineState.prototype.setStateAtTime = function (state, time) { - this.add({ - 'state': state, - 'time': time - }); - }; - return Tone.TimelineState; -}(Tone_core_Tone, Tone_core_Timeline); -/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ -var Tone_core_Clock; -Tone_core_Clock = function (Tone) { - 'use strict'; - Tone.Clock = function () { - Tone.Emitter.call(this); - var options = this.optionsObject(arguments, [ - 'callback', - 'frequency' - ], Tone.Clock.defaults); - this.callback = options.callback; - this._nextTick = 0; - this._lastState = Tone.State.Stopped; - this.frequency = new Tone.TimelineSignal(options.frequency, Tone.Type.Frequency); - this._readOnly('frequency'); - this.ticks = 0; - this._state = new Tone.TimelineState(Tone.State.Stopped); - this._boundLoop = this._loop.bind(this); - this.context.on('tick', this._boundLoop); - }; - Tone.extend(Tone.Clock, Tone.Emitter); - Tone.Clock.defaults = { - 'callback': Tone.noOp, - 'frequency': 1, - 'lookAhead': 'auto' - }; - Object.defineProperty(Tone.Clock.prototype, 'state', { - get: function () { - return this._state.getValueAtTime(this.now()); - } - }); - Tone.Clock.prototype.start = function (time, offset) { - time = this.toSeconds(time); - if (this._state.getValueAtTime(time) !== Tone.State.Started) { - this._state.add({ - 'state': Tone.State.Started, - 'time': time, - 'offset': offset - }); - } - return this; - }; - Tone.Clock.prototype.stop = function (time) { - time = this.toSeconds(time); - this._state.cancel(time); - this._state.setStateAtTime(Tone.State.Stopped, time); - return this; - }; - Tone.Clock.prototype.pause = function (time) { - time = this.toSeconds(time); - if (this._state.getValueAtTime(time) === Tone.State.Started) { - this._state.setStateAtTime(Tone.State.Paused, time); - } - return this; - }; - Tone.Clock.prototype._loop = function () { - var now = this.now(); - var lookAhead = this.context.lookAhead; - var updateInterval = this.context.updateInterval; - var lagCompensation = this.context.lag * 2; - var loopInterval = now + lookAhead + updateInterval + lagCompensation; - while (loopInterval > this._nextTick && this._state) { - var currentState = this._state.getValueAtTime(this._nextTick); - if (currentState !== this._lastState) { - this._lastState = currentState; - var event = this._state.get(this._nextTick); - if (currentState === Tone.State.Started) { - this._nextTick = event.time; - if (!this.isUndef(event.offset)) { - this.ticks = event.offset; - } - this.emit('start', event.time, this.ticks); - } else if (currentState === Tone.State.Stopped) { - this.ticks = 0; - this.emit('stop', event.time); - } else if (currentState === Tone.State.Paused) { - this.emit('pause', event.time); - } - } - var tickTime = this._nextTick; - if (this.frequency) { - this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick); - if (currentState === Tone.State.Started) { - this.callback(tickTime); - this.ticks++; - } - } - } - }; - Tone.Clock.prototype.getStateAtTime = function (time) { - time = this.toSeconds(time); - return this._state.getValueAtTime(time); - }; - Tone.Clock.prototype.dispose = function () { - Tone.Emitter.prototype.dispose.call(this); - this.context.off('tick', this._boundLoop); - this._writable('frequency'); - this.frequency.dispose(); - this.frequency = null; - this._boundLoop = null; - this._nextTick = Infinity; - this.callback = null; - this._state.dispose(); - this._state = null; - }; - return Tone.Clock; -}(Tone_core_Tone, Tone_signal_TimelineSignal, Tone_core_TimelineState, Tone_core_Emitter); -var metro; -'use strict'; -metro = function () { - var p5sound = master; - // requires the Tone.js library's Clock (MIT license, Yotam Mann) - // https://github.com/TONEnoTONE/Tone.js/ - var Clock = Tone_core_Clock; - p5.Metro = function () { - this.clock = new Clock({ 'callback': this.ontick.bind(this) }); - this.syncedParts = []; - this.bpm = 120; - // gets overridden by p5.Part - this._init(); - this.prevTick = 0; - this.tatumTime = 0; - this.tickCallback = function () { - }; - }; - p5.Metro.prototype.ontick = function (tickTime) { - var elapsedTime = tickTime - this.prevTick; - var secondsFromNow = tickTime - p5sound.audiocontext.currentTime; - if (elapsedTime - this.tatumTime <= -0.02) { - return; - } else { - // console.log('ok', this.syncedParts[0].phrases[0].name); - this.prevTick = tickTime; - // for all of the active things on the metro: - var self = this; - this.syncedParts.forEach(function (thisPart) { - if (!thisPart.isPlaying) - return; - thisPart.incrementStep(secondsFromNow); - // each synced source keeps track of its own beat number - thisPart.phrases.forEach(function (thisPhrase) { - var phraseArray = thisPhrase.sequence; - var bNum = self.metroTicks % phraseArray.length; - if (phraseArray[bNum] !== 0 && (self.metroTicks < phraseArray.length || !thisPhrase.looping)) { - thisPhrase.callback(secondsFromNow, phraseArray[bNum]); - } - }); - }); - this.metroTicks += 1; - this.tickCallback(secondsFromNow); - } - }; - p5.Metro.prototype.setBPM = function (bpm, rampTime) { - var beatTime = 60 / (bpm * this.tatums); - var now = p5sound.audiocontext.currentTime; - this.tatumTime = beatTime; - var rampTime = rampTime || 0; - this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); - this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); - this.bpm = bpm; - }; - p5.Metro.prototype.getBPM = function () { - return this.clock.getRate() / this.tatums * 60; - }; - p5.Metro.prototype._init = function () { - this.metroTicks = 0; - }; - // clear existing synced parts, add only this one - p5.Metro.prototype.resetSync = function (part) { - this.syncedParts = [part]; - }; - // push a new synced part to the array - p5.Metro.prototype.pushSync = function (part) { - this.syncedParts.push(part); - }; - p5.Metro.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.clock.start(now + t); - this.setBPM(this.bpm); - }; - p5.Metro.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - this.clock.stop(now + t); - }; - p5.Metro.prototype.beatLength = function (tatums) { - this.tatums = 1 / tatums / 4; - }; -}(master, Tone_core_Clock); -var looper; -'use strict'; -looper = function () { - var p5sound = master; - var BPM = 120; - /** - * Set the global tempo, in beats per minute, for all - * p5.Parts. This method will impact all active p5.Parts. - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} rampTime Seconds from now - */ - p5.prototype.setBPM = function (bpm, rampTime) { - BPM = bpm; - for (var i in p5sound.parts) { - if (p5sound.parts[i]) { - p5sound.parts[i].setBPM(bpm, rampTime); - } - } - }; - /** - *

A phrase is a pattern of musical events over time, i.e. - * a series of notes and rests.

- * - *

Phrases must be added to a p5.Part for playback, and - * each part can play multiple phrases at the same time. - * For example, one Phrase might be a kick drum, another - * could be a snare, and another could be the bassline.

- * - *

The first parameter is a name so that the phrase can be - * modified or deleted later. The callback is a a function that - * this phrase will call at every step—for example it might be - * called playNote(value){}. The array determines - * which value is passed into the callback at each step of the - * phrase. It can be numbers, an object with multiple numbers, - * or a zero (0) indicates a rest so the callback won't be called).

- * - * @class p5.Phrase - * @constructor - * @param {String} name Name so that you can access the Phrase. - * @param {Function} callback The name of a function that this phrase - * will call. Typically it will play a sound, - * and accept two parameters: a time at which - * to play the sound (in seconds from now), - * and a value from the sequence array. The - * time should be passed into the play() or - * start() method to ensure precision. - * @param {Array} sequence Array of values to pass into the callback - * at each step of the phrase. - * @example - *
- * var mySound, myPhrase, myPart; - * var pattern = [1,0,0,2,0,2,0,0]; - * var msg = 'click to play'; - * - * function preload() { - * mySound = loadSound('assets/beatbox.mp3'); - * } - * - * function setup() { - * noStroke(); - * fill(255); - * textAlign(CENTER); - * masterVolume(0.1); - * - * myPhrase = new p5.Phrase('bbox', makeSound, pattern); - * myPart = new p5.Part(); - * myPart.addPhrase(myPhrase); - * myPart.setBPM(60); - * } - * - * function draw() { - * background(0); - * text(msg, width/2, height/2); - * } - * - * function makeSound(time, playbackRate) { - * mySound.rate(playbackRate); - * mySound.play(time); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * myPart.start(); - * msg = 'playing pattern'; - * } - * } - * - *
- */ - p5.Phrase = function (name, callback, sequence) { - this.phraseStep = 0; - this.name = name; - this.callback = callback; /** - * Array of values to pass into the callback - * at each step of the phrase. Depending on the callback - * function's requirements, these values may be numbers, - * strings, or an object with multiple parameters. - * Zero (0) indicates a rest. + * Reset the envelope with a series of time/value pairs. + * + * @method set + * @param {Number} attackTime Time (in seconds) before level + * reaches attackLevel + * @param {Number} attackLevel Typically an amplitude between + * 0.0 and 1.0 + * @param {Number} decayTime Time + * @param {Number} decayLevel Amplitude (In a standard ADSR envelope, + * decayLevel = sustainLevel) + * @param {Number} releaseTime Release Time (in seconds) + * @param {Number} releaseLevel Amplitude + * @example + *
+ * var t1 = 0.1; // attack time in seconds + * var l1 = 0.7; // attack level 0.0 to 1.0 + * var t2 = 0.3; // decay time in seconds + * var l2 = 0.1; // decay level 0.0 to 1.0 + * var t3 = 0.2; // sustain time in seconds + * var l3 = 0.5; // sustain level 0.0 to 1.0 + * // release level defaults to zero + * + * var env; + * var triOsc; + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(t1, l1, t2, l2, t3, l3); + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); // give the env control of the triOsc's amp + * triOsc.start(); + * } + * + * // mouseClick triggers envelope if over canvas + * function mouseClicked() { + * // is mouse over canvas? + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * env.play(triOsc); + * } + * } + *
* - * @property {Array} sequence */ - this.sequence = sequence; - }; - /** - *

A p5.Part plays back one or more p5.Phrases. Instantiate a part - * with steps and tatums. By default, each step represents a 1/16th note.

- * - *

See p5.Phrase for more about musical timing.

- * - * @class p5.Part - * @constructor - * @param {Number} [steps] Steps in the part - * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note) - * @example - *
- * var box, drum, myPart; - * var boxPat = [1,0,0,2,0,2,0,0]; - * var drumPat = [0,1,1,0,2,0,1,0]; - * var msg = 'click to play'; - * - * function preload() { - * box = loadSound('assets/beatbox.mp3'); - * drum = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * noStroke(); - * fill(255); - * textAlign(CENTER); - * masterVolume(0.1); - * - * var boxPhrase = new p5.Phrase('box', playBox, boxPat); - * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat); - * myPart = new p5.Part(); - * myPart.addPhrase(boxPhrase); - * myPart.addPhrase(drumPhrase); - * myPart.setBPM(60); - * masterVolume(0.1); - * } - * - * function draw() { - * background(0); - * text(msg, width/2, height/2); - * } - * - * function playBox(time, playbackRate) { - * box.rate(playbackRate); - * box.play(time); - * } - * - * function playDrum(time, playbackRate) { - * drum.rate(playbackRate); - * drum.play(time); - * } - * - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * myPart.start(); - * msg = 'playing part'; - * } - * } - *
- */ - p5.Part = function (steps, bLength) { - this.length = steps || 0; - // how many beats - this.partStep = 0; - this.phrases = []; - this.isPlaying = false; - this.noLoop(); - this.tatums = bLength || 0.0625; - // defaults to quarter note - this.metro = new p5.Metro(); - this.metro._init(); - this.metro.beatLength(this.tatums); - this.metro.setBPM(BPM); - p5sound.parts.push(this); - this.callback = function () { - }; - }; - /** - * Set the tempo of this part, in Beats Per Minute. - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} [rampTime] Seconds from now - */ - p5.Part.prototype.setBPM = function (tempo, rampTime) { - this.metro.setBPM(tempo, rampTime); - }; - /** - * Returns the tempo, in Beats Per Minute, of this part. - * - * @method getBPM - * @return {Number} - */ - p5.Part.prototype.getBPM = function () { - return this.metro.getBPM(); - }; - /** - * Start playback of this part. It will play - * through all of its phrases at a speed - * determined by setBPM. - * - * @method start - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.start = function (time) { - if (!this.isPlaying) { - this.isPlaying = true; - this.metro.resetSync(this); - var t = time || 0; - this.metro.start(t); - } - }; - /** - * Loop playback of this part. It will begin - * looping through all of its phrases at a speed - * determined by setBPM. - * - * @method loop - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.loop = function (time) { - this.looping = true; - // rest onended function - this.onended = function () { - this.partStep = 0; + p5.Envelope.prototype.set = function (t1, l1, t2, l2, t3, l3) { + this.aTime = t1; + this.aLevel = l1; + this.dTime = t2 || 0; + this.dLevel = l2 || 0; + this.rTime = t3 || 0; + this.rLevel = l3 || 0; + // set time constants for ramp + this._setRampAD(t1, t2); }; - var t = time || 0; - this.start(t); - }; - /** - * Tell the part to stop looping. - * - * @method noLoop - */ - p5.Part.prototype.noLoop = function () { - this.looping = false; - // rest onended function - this.onended = function () { - this.stop(); + /** + * Set values like a traditional + * + * ADSR envelope + * . + * + * @method setADSR + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
+ */ + p5.Envelope.prototype.setADSR = function (aTime, dTime, sPercent, rTime) { + this.aTime = aTime; + this.dTime = dTime || 0; + // lerp + this.sPercent = sPercent || 0; + this.dLevel = + typeof sPercent !== "undefined" + ? sPercent * (this.aLevel - this.rLevel) + this.rLevel + : 0; + this.rTime = rTime || 0; + // also set time constants for ramp + this._setRampAD(aTime, dTime); }; - }; - /** - * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. - * - * @method stop - * @param {Number} [time] seconds from now - */ - p5.Part.prototype.stop = function (time) { - this.partStep = 0; - this.pause(time); - }; - /** - * Pause the part. Playback will resume - * from the current step. - * - * @method pause - * @param {Number} time seconds from now - */ - p5.Part.prototype.pause = function (time) { - this.isPlaying = false; - var t = time || 0; - this.metro.stop(t); - }; - /** - * Add a p5.Phrase to this Part. - * - * @method addPhrase - * @param {p5.Phrase} phrase reference to a p5.Phrase - */ - p5.Part.prototype.addPhrase = function (name, callback, array) { - var p; - if (arguments.length === 3) { - p = new p5.Phrase(name, callback, array); - } else if (arguments[0] instanceof p5.Phrase) { - p = arguments[0]; - } else { - throw 'invalid input. addPhrase accepts name, callback, array or a p5.Phrase'; - } - this.phrases.push(p); - // reset the length if phrase is longer than part's existing length - if (p.sequence.length > this.length) { - this.length = p.sequence.length; - } - }; - /** - * Remove a phrase from this part, based on the name it was - * given when it was created. - * - * @method removePhrase - * @param {String} phraseName - */ - p5.Part.prototype.removePhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases.splice(i, 1); + /** + * Set max (attackLevel) and min (releaseLevel) of envelope. + * + * @method setRange + * @param {Number} aLevel attack level (defaults to 1) + * @param {Number} rLevel release level (defaults to 0) + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * env.play(); + * } + *
+ */ + p5.Envelope.prototype.setRange = function (aLevel, rLevel) { + this.aLevel = aLevel || 1; + this.rLevel = rLevel || 0; + }; + // private (undocumented) method called when ADSR is set to set time constants for ramp + // + // Set the + // time constants for simple exponential ramps. + // The larger the time constant value, the slower the + // transition will be. + // + // method _setRampAD + // param {Number} attackTimeConstant attack time constant + // param {Number} decayTimeConstant decay time constant + // + p5.Envelope.prototype._setRampAD = function (t1, t2) { + this._rampAttackTime = this.checkExpInput(t1); + this._rampDecayTime = this.checkExpInput(t2); + var TCDenominator = 1; + /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) + TCDenominator = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + ); + this._rampAttackTC = t1 / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1 / this._rampLowPercentage); + this._rampDecayTC = t2 / this.checkExpInput(TCDenominator); + }; + // private method + p5.Envelope.prototype.setRampPercentages = function (p1, p2) { + //set the percentages that the simple exponential ramps go to + this._rampHighPercentage = this.checkExpInput(p1); + this._rampLowPercentage = this.checkExpInput(p2); + var TCDenominator = 1; + //now re-compute the time constants based on those percentages + /// Aatish Bhatia's calculation for time constant for rise(to adjust 1/1-e calculation to any percentage) + TCDenominator = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + ); + this._rampAttackTC = + this._rampAttackTime / this.checkExpInput(TCDenominator); + TCDenominator = Math.log(1 / this._rampLowPercentage); + this._rampDecayTC = + this._rampDecayTime / this.checkExpInput(TCDenominator); + }; + /** + * Assign a parameter to be controlled by this envelope. + * If a p5.Sound object is given, then the p5.Envelope will control its + * output gain. If multiple inputs are provided, the env will + * control all of them. + * + * @method setInput + * @param {Object} [...inputs] A p5.sound object or + * Web Audio Param. + */ + p5.Envelope.prototype.setInput = function () { + for (var i = 0; i < arguments.length; i++) { + this.connect(arguments[i]); } - } - }; - /** - * Get a phrase from this part, based on the name it was - * given when it was created. Now you can modify its array. - * - * @method getPhrase - * @param {String} phraseName - */ - p5.Part.prototype.getPhrase = function (name) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - return this.phrases[i]; + }; + /** + * Set whether the envelope ramp is linear (default) or exponential. + * Exponential ramps can be useful because we perceive amplitude + * and frequency logarithmically. + * + * @method setExp + * @param {Boolean} isExp true is exponential, false is linear + */ + p5.Envelope.prototype.setExp = function (isExp) { + this.isExponential = isExp; + }; + //helper method to protect against zero values being sent to exponential functions + p5.Envelope.prototype.checkExpInput = function (value) { + if (value <= 0) { + value = 1e-8; } - } - }; - /** - * Find all sequences with the specified name, and replace their patterns with the specified array. - * - * @method replaceSequence - * @param {String} phraseName - * @param {Array} sequence Array of values to pass into the callback - * at each step of the phrase. - */ - p5.Part.prototype.replaceSequence = function (name, array) { - for (var i in this.phrases) { - if (this.phrases[i].name === name) { - this.phrases[i].sequence = array; + return value; + }; + /** + * Play tells the envelope to start acting on a given input. + * If the input is a p5.sound object (i.e. AudioIn, Oscillator, + * SoundFile), then Envelope will control its output volume. + * Envelopes can also be used to control any + * Web Audio Audio Param. + * + * @method play + * @param {Object} unit A p5.sound object or + * Web Audio Param. + * @param {Number} [startTime] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var susPercent = 0.2; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(playEnv); + * } + * + * function playEnv() { + * // trigger env on triOsc, 0 seconds from now + * // After decay, sustain for 0.2 seconds before release + * env.play(triOsc, 0, 0.2); + * } + *
+ */ + p5.Envelope.prototype.play = function (unit, secondsFromNow, susTime) { + var tFromNow = secondsFromNow || 0; + var susTime = susTime || 0; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - p5.Part.prototype.incrementStep = function (time) { - if (this.partStep < this.length - 1) { - this.callback(time); - this.partStep += 1; - } else { - if (!this.looping && this.partStep === this.length - 1) { - console.log('done'); - // this.callback(time); - this.onended(); + this.triggerAttack(unit, tFromNow); + this.triggerRelease(unit, tFromNow + this.aTime + this.dTime + susTime); + }; + /** + * Trigger the Attack, and Decay portion of the Envelope. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. Input can be + * any p5.sound object, or a + * Web Audio Param. + * + * @method triggerAttack + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow time from now (in seconds) + * @example + *
+ * + * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.3; + * var susPercent = 0.4; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * background(200); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(envAttack); + * } + * + * function envAttack() { + * console.log('trigger attack'); + * env.triggerAttack(); + * + * background(0,255,0); + * text('attack!', width/2, height/2); + * } + * + * function mouseReleased() { + * env.triggerRelease(); + * + * background(200); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.Envelope.prototype.triggerAttack = function (unit, secondsFromNow) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + this.lastAttack = t; + this.wasTriggered = true; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - /** - * Set the function that will be called at every step. This will clear the previous function. - * - * @method onStep - * @param {Function} callback The name of the callback - * you want to fire - * on every beat/tatum. - */ - p5.Part.prototype.onStep = function (callback) { - this.callback = callback; - }; - // =============== - // p5.Score - // =============== - /** - * A Score consists of a series of Parts. The parts will - * be played back in order. For example, you could have an - * A part, a B part, and a C part, and play them back in this order - * new p5.Score(a, a, b, a, c) - * - * @class p5.Score - * @constructor - * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. - */ - p5.Score = function () { - // for all of the arguments - this.parts = []; - this.currentPart = 0; - var thisScore = this; - for (var i in arguments) { - if (arguments[i] && this.parts[i]) { - this.parts[i] = arguments[i]; - this.parts[i].nextPart = this.parts[i + 1]; - this.parts[i].onended = function () { - thisScore.resetPart(i); - playNextPart(thisScore); - }; + // get and set value (with linear ramp) to anchor automation + var valToSet = this.control.getValueAtTime(t); + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(valToSet), + t + ); + } else { + this.control.linearRampToValueAtTime(valToSet, t); + } + // after each ramp completes, cancel scheduled values + // (so they can be overridden in case env has been re-triggered) + // then, set current value (with linearRamp to avoid click) + // then, schedule the next automation... + // attack + t += this.aTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.aLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); + } + // decay to decay level (if using ADSR, then decay level == sustain level) + t += this.dTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.dLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); } - } - this.looping = false; - }; - p5.Score.prototype.onended = function () { - if (this.looping) { - // this.resetParts(); - this.parts[0].start(); - } else { - this.parts[this.parts.length - 1].onended = function () { - this.stop(); - this.resetParts(); - }; - } - this.currentPart = 0; - }; - /** - * Start playback of the score. - * - * @method start - */ - p5.Score.prototype.start = function () { - this.parts[this.currentPart].start(); - this.scoreStep = 0; - }; - /** - * Stop playback of the score. - * - * @method stop - */ - p5.Score.prototype.stop = function () { - this.parts[this.currentPart].stop(); - this.currentPart = 0; - this.scoreStep = 0; - }; - /** - * Pause playback of the score. - * - * @method pause - */ - p5.Score.prototype.pause = function () { - this.parts[this.currentPart].stop(); - }; - /** - * Loop playback of the score. - * - * @method loop - */ - p5.Score.prototype.loop = function () { - this.looping = true; - this.start(); - }; - /** - * Stop looping playback of the score. If it - * is currently playing, this will go into effect - * after the current round of playback completes. - * - * @method noLoop - */ - p5.Score.prototype.noLoop = function () { - this.looping = false; - }; - p5.Score.prototype.resetParts = function () { - var self = this; - this.parts.forEach(function (part) { - self.resetParts[part]; - }); - }; - p5.Score.prototype.resetPart = function (i) { - this.parts[i].stop(); - this.parts[i].partStep = 0; - for (var p in this.parts[i].phrases) { - if (this.parts[i]) { - this.parts[i].phrases[p].phraseStep = 0; + }; + /** + * Trigger the Release of the Envelope. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @method triggerRelease + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow time to trigger the release + * @example + *
+ * + * var attackLevel = 1.0; + * var releaseLevel = 0; + * + * var attackTime = 0.001; + * var decayTime = 0.3; + * var susPercent = 0.4; + * var releaseTime = 0.5; + * + * var env, triOsc; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * background(200); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime, susPercent, releaseTime); + * env.setRange(attackLevel, releaseLevel); + * + * triOsc = new p5.Oscillator('triangle'); + * triOsc.amp(env); + * triOsc.start(); + * triOsc.freq(220); + * + * cnv.mousePressed(envAttack); + * } + * + * function envAttack() { + * console.log('trigger attack'); + * env.triggerAttack(); + * + * background(0,255,0); + * text('attack!', width/2, height/2); + * } + * + * function mouseReleased() { + * env.triggerRelease(); + * + * background(200); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.Envelope.prototype.triggerRelease = function (unit, secondsFromNow) { + // only trigger a release if an attack was triggered + if (!this.wasTriggered) { + // this currently causes a bit of trouble: + // if a later release has been scheduled (via the play function) + // a new earlier release won't interrupt it, because + // this.wasTriggered has already been set to false. + // If we want new earlier releases to override, then we need to + // keep track of the last release time, and if the new release time is + // earlier, then use it. + return; } - } - }; - /** - * Set the tempo for all parts in the score - * - * @method setBPM - * @param {Number} BPM Beats Per Minute - * @param {Number} rampTime Seconds from now - */ - p5.Score.prototype.setBPM = function (bpm, rampTime) { - for (var i in this.parts) { - if (this.parts[i]) { - this.parts[i].setBPM(bpm, rampTime); + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + if (unit) { + if (this.connection !== unit) { + this.connect(unit); + } } - } - }; - function playNextPart(aScore) { - aScore.currentPart++; - if (aScore.currentPart >= aScore.parts.length) { - aScore.scoreStep = 0; - aScore.onended(); - } else { - aScore.scoreStep = 0; - aScore.parts[aScore.currentPart - 1].stop(); - aScore.parts[aScore.currentPart].start(); - } - } -}(master); -var soundloop; -'use strict'; -soundloop = function () { - var p5sound = master; - var Clock = Tone_core_Clock; - /** - * SoundLoop - * - * @class p5.SoundLoop - * @constructor - * - * @param {Function} callback this function will be called on each iteration of theloop - * @param {Number|String} [interval] amount of time or beats for each iteration of the loop - * defaults to 1 - * - * @example - *
- * var click; - * var looper1; - * - * function preload() { - * click = loadSound('assets/drum.mp3'); - * } - * - * function setup() { - * //the looper's callback is passed the timeFromNow - * //this value should be used as a reference point from - * //which to schedule sounds - * looper1 = new p5.SoundLoop(function(timeFromNow){ - * click.play(timeFromNow); - * background(255 * (looper1.iterations % 2)); - * }, 2); - * - * //stop after 10 iteratios; - * looper1.maxIterations = 10; - * //start the loop - * looper1.start(); - * } - *
- */ - p5.SoundLoop = function (callback, interval) { - this.callback = callback; + // get and set value (with linear or exponential ramp) to anchor automation + var valToSet = this.control.getValueAtTime(t); + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(valToSet), + t + ); + } else { + this.control.linearRampToValueAtTime(valToSet, t); + } + // release + t += this.rTime; + if (this.isExponential === true) { + this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + t + ); + valToSet = this.checkExpInput(this.control.getValueAtTime(t)); + this.control.cancelScheduledValues(t); + this.control.exponentialRampToValueAtTime(valToSet, t); + } else { + this.control.linearRampToValueAtTime(this.rLevel, t); + valToSet = this.control.getValueAtTime(t); + this.control.cancelScheduledValues(t); + this.control.linearRampToValueAtTime(valToSet, t); + } + this.wasTriggered = false; + }; /** - * musicalTimeMode uses Tone.Time convention - * true if string, false if number - * @property {Boolean} musicalTimeMode - */ - this.musicalTimeMode = typeof this._interval === 'number' ? false : true; - this._interval = interval || 1; - /** - * musicalTimeMode variables - * modify these only when the interval is specified in musicalTime format as a string - */ - this._timeSignature = 4; - this._bpm = 60; - this.isPlaying = false; - /** - * Set a limit to the number of loops to play. defaults to Infinity - * @property {Number} maxIterations - */ - this.maxIterations = Infinity; - var self = this; - this.clock = new Clock({ - 'callback': function (time) { - var timeFromNow = time - p5sound.audiocontext.currentTime; - /** - * Do not initiate the callback if timeFromNow is < 0 - * This ususually occurs for a few milliseconds when the page - * is not fully loaded - * - * The callback should only be called until maxIterations is reached - */ - if (timeFromNow > 0 && self.iterations <= self.maxIterations) { - self.callback(timeFromNow); + * Exponentially ramp to a value using the first two + * values from setADSR(attackTime, decayTime) + * as + * time constants for simple exponential ramps. + * If the value is higher than current value, it uses attackTime, + * while a decrease uses decayTime. + * + * @method ramp + * @param {Object} unit p5.sound Object or Web Audio Param + * @param {Number} secondsFromNow When to trigger the ramp + * @param {Number} v Target value + * @param {Number} [v2] Second target value (optional) + * @example + *
+ * var env, osc, amp, cnv; + * + * var attackTime = 0.001; + * var decayTime = 0.2; + * var attackLevel = 1; + * var decayLevel = 0; + * + * function setup() { + * cnv = createCanvas(100, 100); + * fill(0,255,0); + * noStroke(); + * + * env = new p5.Envelope(); + * env.setADSR(attackTime, decayTime); + * + * osc = new p5.Oscillator(); + * osc.amp(env); + * osc.start(); + * + * amp = new p5.Amplitude(); + * + * cnv.mousePressed(triggerRamp); + * } + * + * function triggerRamp() { + * env.ramp(osc, 0, attackLevel, decayLevel); + * } + * + * function draw() { + * background(20,20,20); + * text('click me', 10, 20); + * var h = map(amp.getLevel(), 0, 0.4, 0, height);; + * + * rect(0, height, width, -h); + * } + *
+ */ + p5.Envelope.prototype.ramp = function (unit, secondsFromNow, v1, v2) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + var destination1 = this.checkExpInput(v1); + var destination2 = + typeof v2 !== "undefined" ? this.checkExpInput(v2) : undefined; + // connect env to unit if not already connected + if (unit) { + if (this.connection !== unit) { + this.connect(unit); } - }, - 'frequency': this._calcFreq() - }); - }; - /** - * Start the loop - * @method start - * @param {Number} [timeFromNow] schedule a starting time - */ - p5.SoundLoop.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (!this.isPlaying) { - this.clock.start(now + t); - this.isPlaying = true; - } - }; - /** - * Stop the loop - * @method stop - * @param {Number} [timeFromNow] schedule a stopping time - */ - p5.SoundLoop.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.stop(now + t); - this.isPlaying = false; - } - }; - /** - * Pause the loop - * @method pause - * @param {Number} [timeFromNow] schedule a pausing time - */ - p5.SoundLoop.prototype.pause = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.pause(now + t); - this.isPlaying = false; - } - }; - /** - * Synchronize loops. Use this method to start two more more loops in synchronization - * or to start a loop in synchronization with a loop that is already playing - * This method will schedule the implicit loop in sync with the explicit master loop - * i.e. loopToStart.syncedStart(loopToSyncWith) - * - * @method syncedStart - * @param {Object} otherLoop a p5.SoundLoop to sync with - * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds - */ - p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (!otherLoop.isPlaying) { - otherLoop.clock.start(now + t); - otherLoop.isPlaying = true; - this.clock.start(now + t); - this.isPlaying = true; - } else if (otherLoop.isPlaying) { - var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; - this.clock.start(now + time); - this.isPlaying = true; - } - }; - /** - * Updates frequency value, reflected in next callback - * @private - * @method _update - */ - p5.SoundLoop.prototype._update = function () { - this.clock.frequency.value = this._calcFreq(); - }; - /** - * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature - * @private - * @method _calcFreq - * @return {Number} new clock frequency value - */ - p5.SoundLoop.prototype._calcFreq = function () { - //Seconds mode, bpm / timesignature has no effect - if (typeof this._interval === 'number') { - this.musicalTimeMode = false; - return 1 / this._interval; - } else if (typeof this._interval === 'string') { - this.musicalTimeMode = true; - return this._bpm / 60 / this._convertNotation(this._interval) * (this._timeSignature / 4); - } - }; - /** - * Convert notation from musical time format to seconds - * Uses Tone.Time convention - * @private - * @method _convertNotation - * @param {String} value value to be converted - * @return {Number} converted value in seconds - */ - p5.SoundLoop.prototype._convertNotation = function (value) { - var type = value.slice(-1); - value = Number(value.slice(0, -1)); - switch (type) { - case 'm': - return this._measure(value); - case 'n': - return this._note(value); - default: - console.warn('Specified interval is not formatted correctly. See Tone.js ' + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time'); - } - }; - /** - * Helper conversion methods of measure and note - * @private - * @method _measure - * @private - * @method _note - */ - p5.SoundLoop.prototype._measure = function (value) { - return value * this._timeSignature; - }; - p5.SoundLoop.prototype._note = function (value) { - return this._timeSignature / value; - }; - /** - * Getters and Setters, setting any paramter will result in a change in the clock's - * frequency, that will be reflected after the next callback - * beats per minute (defaults to 60) - * @property {Number} bpm - */ - Object.defineProperty(p5.SoundLoop.prototype, 'bpm', { - get: function () { - return this._bpm; - }, - set: function (bpm) { - if (!this.musicalTimeMode) { - console.warn('Changing the BPM in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); - } - this._bpm = bpm; - this._update(); - } - }); - /** - * number of quarter notes in a measure (defaults to 4) - * @property {Number} timeSignature - */ - Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', { - get: function () { - return this._timeSignature; - }, - set: function (timeSig) { - if (!this.musicalTimeMode) { - console.warn('Changing the timeSignature in "seconds" mode has no effect. ' + 'BPM is only relevant in musicalTimeMode ' + 'when the interval is specified as a string ' + '("2n", "4n", "1m"...etc)'); - } - this._timeSignature = timeSig; - this._update(); - } - }); - /** - * length of the loops interval - * @property {Number|String} interval - */ - Object.defineProperty(p5.SoundLoop.prototype, 'interval', { - get: function () { - return this._interval; - }, - set: function (interval) { - this.musicalTimeMode = typeof interval === 'Number' ? false : true; - this._interval = interval; - this._update(); - } - }); - /** - * how many times the callback has been called so far - * @property {Number} iterations - * @readonly - */ - Object.defineProperty(p5.SoundLoop.prototype, 'iterations', { - get: function () { - return this.clock.ticks; - } - }); - return p5.SoundLoop; -}(master, Tone_core_Clock); -var compressor; -compressor = function () { - 'use strict'; - var p5sound = master; - var Effect = effect; - var CustomError = errorHandler; - /** - * Compressor is an audio effect class that performs dynamics compression - * on an audio input source. This is a very commonly used technique in music - * and sound production. Compression creates an overall louder, richer, - * and fuller sound by lowering the volume of louds and raising that of softs. - * Compression can be used to avoid clipping (sound distortion due to - * peaks in volume) and is especially useful when many sounds are played - * at once. Compression can be used on indivudal sound sources in addition - * to the master output. - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Compressor - * @constructor - * @extends p5.Effect - * - * - */ - p5.Compressor = function () { - Effect.call(this); + } + //get current value + var currentVal = this.checkExpInput(this.control.getValueAtTime(t)); + // this.control.cancelScheduledValues(t); + //if it's going up + if (destination1 > currentVal) { + this.control.setTargetAtTime(destination1, t, this._rampAttackTC); + t += this._rampAttackTime; + } else if (destination1 < currentVal) { + this.control.setTargetAtTime(destination1, t, this._rampDecayTC); + t += this._rampDecayTime; + } + // Now the second part of envelope begins + if (destination2 === undefined) return; + //if it's going up + if (destination2 > destination1) { + this.control.setTargetAtTime(destination2, t, this._rampAttackTC); + } else if (destination2 < destination1) { + this.control.setTargetAtTime(destination2, t, this._rampDecayTC); + } + }; + p5.Envelope.prototype.connect = function (unit) { + this.connection = unit; + // assume we're talking about output gain + // unless given a different audio param + if ( + unit instanceof p5.Oscillator || + unit instanceof p5.SoundFile || + unit instanceof p5.AudioIn || + unit instanceof p5.Reverb || + unit instanceof p5.Noise || + unit instanceof p5.Filter || + unit instanceof p5.Delay + ) { + unit = unit.output.gain; + } + if (unit instanceof AudioParam) { + //set the initial value + unit.setValueAtTime(0, p5sound.audiocontext.currentTime); + } + if (unit instanceof p5.Signal) { + unit.setValue(0); + } + this.output.connect(unit); + }; + p5.Envelope.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + // Signal Math /** - * The p5.Compressor is built with a Web Audio Dynamics Compressor Node - * - * @property {AudioNode} compressor - */ - this.compressor = this.ac.createDynamicsCompressor(); - this.input.connect(this.compressor); - this.compressor.connect(this.wet); - }; - p5.Compressor.prototype = Object.create(Effect.prototype); - /** - * Performs the same function as .connect, but also accepts - * optional parameters to set compressor's audioParams - * @method process - * - * @param {Object} src Sound source to be connected - * - * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [threshold] The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - p5.Compressor.prototype.process = function (src, attack, knee, ratio, threshold, release) { - src.connect(this.input); - this.set(attack, knee, ratio, threshold, release); - }; - /** - * Set the paramters of a compressor. - * @method set - * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} knee A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} ratio The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - */ - p5.Compressor.prototype.set = function (attack, knee, ratio, threshold, release) { - if (typeof attack !== 'undefined') { - this.attack(attack); - } - if (typeof knee !== 'undefined') { - this.knee(knee); - } - if (typeof ratio !== 'undefined') { - this.ratio(ratio); - } - if (typeof threshold !== 'undefined') { - this.threshold(threshold); - } - if (typeof release !== 'undefined') { - this.release(release); - } - }; - /** - * Get current attack or set value w/ time ramp - * - * - * @method attack - * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, - * default = .003, range 0 - 1 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.attack = function (attack, time) { - var t = time || 0; - if (typeof attack == 'number') { - this.compressor.attack.value = attack; - this.compressor.attack.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.attack.linearRampToValueAtTime(attack, this.ac.currentTime + 0.02 + t); - } else if (typeof attack !== 'undefined') { - attack.connect(this.compressor.attack); - } - return this.compressor.attack.value; - }; - /** - * Get current knee or set value w/ time ramp - * - * @method knee - * @param {Number} [knee] A decibel value representing the range above the - * threshold where the curve smoothly transitions to the "ratio" portion. - * default = 30, range 0 - 40 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.knee = function (knee, time) { - var t = time || 0; - if (typeof knee == 'number') { - this.compressor.knee.value = knee; - this.compressor.knee.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.knee.linearRampToValueAtTime(knee, this.ac.currentTime + 0.02 + t); - } else if (typeof knee !== 'undefined') { - knee.connect(this.compressor.knee); - } - return this.compressor.knee.value; - }; - /** - * Get current ratio or set value w/ time ramp - * @method ratio - * - * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output - * default = 12, range 1 - 20 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.ratio = function (ratio, time) { - var t = time || 0; - if (typeof ratio == 'number') { - this.compressor.ratio.value = ratio; - this.compressor.ratio.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.ratio.linearRampToValueAtTime(ratio, this.ac.currentTime + 0.02 + t); - } else if (typeof ratio !== 'undefined') { - ratio.connect(this.compressor.ratio); - } - return this.compressor.ratio.value; - }; - /** - * Get current threshold or set value w/ time ramp - * @method threshold - * - * @param {Number} threshold The decibel value above which the compression will start taking effect - * default = -24, range -100 - 0 - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.threshold = function (threshold, time) { - var t = time || 0; - if (typeof threshold == 'number') { - this.compressor.threshold.value = threshold; - this.compressor.threshold.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.threshold.linearRampToValueAtTime(threshold, this.ac.currentTime + 0.02 + t); - } else if (typeof threshold !== 'undefined') { - threshold.connect(this.compressor.threshold); - } - return this.compressor.threshold.value; - }; - /** - * Get current release or set value w/ time ramp - * @method release - * - * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB - * default = .25, range 0 - 1 - * - * @param {Number} [time] Assign time value to schedule the change in value - */ - p5.Compressor.prototype.release = function (release, time) { - var t = time || 0; - if (typeof release == 'number') { - this.compressor.release.value = release; - this.compressor.release.cancelScheduledValues(this.ac.currentTime + 0.01 + t); - this.compressor.release.linearRampToValueAtTime(release, this.ac.currentTime + 0.02 + t); - } else if (typeof number !== 'undefined') { - release.connect(this.compressor.release); - } - return this.compressor.release.value; - }; - /** - * Return the current reduction value - * - * @method reduction - * @return {Number} Value of the amount of gain reduction that is applied to the signal - */ - p5.Compressor.prototype.reduction = function () { - return this.compressor.reduction.value; - }; - p5.Compressor.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.compressor) { - this.compressor.disconnect(); - delete this.compressor; - } - }; - return p5.Compressor; -}(master, effect, errorHandler); -var soundRecorder; -'use strict'; -soundRecorder = function () { - // inspiration: recorder.js, Tone.js & typedarray.org - var p5sound = master; - var convertToWav = helpers.convertToWav; - var ac = p5sound.audiocontext; - /** - *

Record sounds for playback and/or to save as a .wav file. - * The p5.SoundRecorder records all sound output from your sketch, - * or can be assigned a specific source with setInput().

- *

The record() method accepts a p5.SoundFile as a parameter. - * When playback is stopped (either after the given amount of time, - * or with the stop() method), the p5.SoundRecorder will send its - * recording to that p5.SoundFile for playback.

- * - * @class p5.SoundRecorder - * @constructor - * @example - *
- * var mic, recorder, soundFile; - * var state = 0; - * - * function setup() { - * background(200); - * // create an audio in - * mic = new p5.AudioIn(); - * - * // prompts user to enable their browser mic - * mic.start(); - * - * // create a sound recorder - * recorder = new p5.SoundRecorder(); - * - * // connect the mic to the recorder - * recorder.setInput(mic); - * - * // this sound file will be used to - * // playback & save the recording - * soundFile = new p5.SoundFile(); - * - * text('keyPress to record', 20, 20); - * } - * - * function keyPressed() { - * // make sure user enabled the mic - * if (state === 0 && mic.enabled) { - * - * // record to our p5.SoundFile - * recorder.record(soundFile); - * - * background(255,0,0); - * text('Recording!', 20, 20); - * state++; - * } - * else if (state === 1) { - * background(0,255,0); - * - * // stop recorder and - * // send result to soundFile - * recorder.stop(); - * - * text('Stopped', 20, 20); - * state++; - * } - * - * else if (state === 2) { - * soundFile.play(); // play the result! - * save(soundFile, 'mySound.wav'); - * state++; - * } - * } - *
- */ - p5.SoundRecorder = function () { - this.input = ac.createGain(); - this.output = ac.createGain(); - this.recording = false; - this.bufferSize = 1024; - this._channels = 2; - // stereo (default) - this._clear(); - // initialize variables - this._jsNode = ac.createScriptProcessor(this.bufferSize, this._channels, 2); - this._jsNode.onaudioprocess = this._audioprocess.bind(this); - /** - * callback invoked when the recording is over - * @private - * @type Function(Float32Array) + * Add a value to the p5.Oscillator's output amplitude, + * and return the oscillator. Calling this method + * again will override the initial add() with new values. + * + * @method add + * @param {Number} number Constant number to add + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output */ - this._callback = function () { + p5.Envelope.prototype.add = function (num) { + var add = new Add(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, add, thisChain, nextChain, Add); }; - // connections - this._jsNode.connect(p5.soundOut._silentNode); - this.setInput(); - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connect a specific device to the p5.SoundRecorder. - * If no parameter is given, p5.SoundRecorer will record - * all audible p5.sound from your sketch. - * - * @method setInput - * @param {Object} [unit] p5.sound object or a web audio unit - * that outputs sound - */ - p5.SoundRecorder.prototype.setInput = function (unit) { - this.input.disconnect(); - this.input = null; - this.input = ac.createGain(); - this.input.connect(this._jsNode); - this.input.connect(this.output); - if (unit) { - unit.connect(this.input); - } else { - p5.soundOut.output.connect(this.input); - } - }; - /** - * Start recording. To access the recording, provide - * a p5.SoundFile as the first parameter. The p5.SoundRecorder - * will send its recording to that p5.SoundFile for playback once - * recording is complete. Optional parameters include duration - * (in seconds) of the recording, and a callback function that - * will be called once the complete recording has been - * transfered to the p5.SoundFile. - * - * @method record - * @param {p5.SoundFile} soundFile p5.SoundFile - * @param {Number} [duration] Time (in seconds) - * @param {Function} [callback] The name of a function that will be - * called once the recording completes - */ - p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { - this.recording = true; - if (duration) { - this.sampleLimit = Math.round(duration * ac.sampleRate); - } - if (sFile && callback) { - this._callback = function () { - this.buffer = this._getBuffer(); - sFile.setBuffer(this.buffer); - callback(); - }; - } else if (sFile) { - this._callback = function () { - this.buffer = this._getBuffer(); - sFile.setBuffer(this.buffer); - }; - } - }; - /** - * Stop the recording. Once the recording is stopped, - * the results will be sent to the p5.SoundFile that - * was given on .record(), and if a callback function - * was provided on record, that function will be called. - * - * @method stop - */ - p5.SoundRecorder.prototype.stop = function () { - this.recording = false; - this._callback(); - this._clear(); - }; - p5.SoundRecorder.prototype._clear = function () { - this._leftBuffers = []; - this._rightBuffers = []; - this.recordedSamples = 0; - this.sampleLimit = null; - }; - /** - * internal method called on audio process - * - * @private - * @param {AudioProcessorEvent} event - */ - p5.SoundRecorder.prototype._audioprocess = function (event) { - if (this.recording === false) { - return; - } else if (this.recording === true) { - // if we are past the duration, then stop... else: - if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) { - this.stop(); - } else { - // get channel data - var left = event.inputBuffer.getChannelData(0); - var right = event.inputBuffer.getChannelData(1); - // clone the samples - this._leftBuffers.push(new Float32Array(left)); - this._rightBuffers.push(new Float32Array(right)); - this.recordedSamples += this.bufferSize; + /** + * Multiply the p5.Envelope's output amplitude + * by a fixed value. Calling this method + * again will override the initial mult() with new values. + * + * @method mult + * @param {Number} number Constant number to multiply + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output + */ + p5.Envelope.prototype.mult = function (num) { + var mult = new Mult(num); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, mult, thisChain, nextChain, Mult); + }; + /** + * Scale this envelope's amplitude values to a given + * range, and return the envelope. Calling this method + * again will override the initial scale() with new values. + * + * @method scale + * @param {Number} inMin input range minumum + * @param {Number} inMax input range maximum + * @param {Number} outMin input range minumum + * @param {Number} outMax input range maximum + * @return {p5.Envelope} Envelope Returns this envelope + * with scaled output + */ + p5.Envelope.prototype.scale = function (inMin, inMax, outMin, outMax) { + var scale = new Scale(inMin, inMax, outMin, outMax); + var thisChain = this.mathOps.length; + var nextChain = this.output; + return p5.prototype._mathChain(this, scale, thisChain, nextChain, Scale); + }; + // get rid of the oscillator + p5.Envelope.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.disconnect(); + if (this.control) { + this.control.dispose(); + this.control = null; } - } - }; - p5.SoundRecorder.prototype._getBuffer = function () { - var buffers = []; - buffers.push(this._mergeBuffers(this._leftBuffers)); - buffers.push(this._mergeBuffers(this._rightBuffers)); - return buffers; - }; - p5.SoundRecorder.prototype._mergeBuffers = function (channelBuffer) { - var result = new Float32Array(this.recordedSamples); - var offset = 0; - var lng = channelBuffer.length; - for (var i = 0; i < lng; i++) { - var buffer = channelBuffer[i]; - result.set(buffer, offset); - offset += buffer.length; - } - return result; - }; - p5.SoundRecorder.prototype.dispose = function () { - this._clear(); - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - this._callback = function () { - }; - if (this.input) { - this.input.disconnect(); - } - this.input = null; - this._jsNode = null; - }; - /** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. - * For uploading audio to a server, use - * `p5.SoundFile.saveBlob`. - * - * @for p5 - * @method saveSound - * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save - * @param {String} fileName name of the resulting .wav file. - */ - // add to p5.prototype as this is used by the p5 `save()` method. - p5.prototype.saveSound = function (soundFile, fileName) { - const dataView = convertToWav(soundFile.buffer); - p5.prototype.writeFile([dataView], fileName, 'wav'); - }; -}(master, helpers); -var peakdetect; -'use strict'; -peakdetect = function () { - /** - *

PeakDetect works in conjunction with p5.FFT to - * look for onsets in some or all of the frequency spectrum. - *

- *

- * To use p5.PeakDetect, call update in the draw loop - * and pass in a p5.FFT object. - *

- *

- * You can listen for a specific part of the frequency spectrum by - * setting the range between freq1 and freq2. - *

- * - *

threshold is the threshold for detecting a peak, - * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud - * as 1.0.

- * - *

- * The update method is meant to be run in the draw loop, and - * frames determines how many loops must pass before - * another peak can be detected. - * For example, if the frameRate() = 60, you could detect the beat of a - * 120 beat-per-minute song with this equation: - * framesPerPeak = 60 / (estimatedBPM / 60 ); - *

- * - *

- * Based on example contribtued by @b2renger, and a simple beat detection - * explanation by Felix Turner. - *

- * - * @class p5.PeakDetect - * @constructor - * @param {Number} [freq1] lowFrequency - defaults to 20Hz - * @param {Number} [freq2] highFrequency - defaults to 20000 Hz - * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 - * scaled logarithmically where 0.1 is 1/2 the loudness - * of 1.0. Defaults to 0.35. - * @param {Number} [framesPerPeak] Defaults to 20. - * @example - *
- * - * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 10; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * background(0); - * noStroke(); - * fill(255); - * textAlign(CENTER); - * - * // p5.PeakDetect requires a p5.FFT - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * } - * - * function draw() { - * background(0); - * text('click to play/pause', width/2, height/2); - * - * // peakDetect accepts an fft post-analysis - * fft.analyze(); - * peakDetect.update(fft); - * - * if ( peakDetect.isDetected ) { - * ellipseWidth = 50; - * } else { - * ellipseWidth *= 0.95; - * } - * - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // toggle play/stop when canvas is clicked - * function mouseClicked() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * } - * } - *
- */ - p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) { - // framesPerPeak determines how often to look for a beat. - // If a beat is provided, try to look for a beat based on bpm - this.framesPerPeak = _framesPerPeak || 20; - this.framesSinceLastPeak = 0; - this.decayRate = 0.95; - this.threshold = threshold || 0.35; - this.cutoff = 0; - // how much to increase the cutoff - // TO DO: document this / figure out how to make it accessible - this.cutoffMult = 1.5; - this.energy = 0; - this.penergy = 0; - // TO DO: document this property / figure out how to make it accessible - this.currentValue = 0; - /** - * isDetected is set to true when a peak is detected. - * - * @attribute isDetected {Boolean} - * @default false - */ - this.isDetected = false; - this.f1 = freq1 || 40; - this.f2 = freq2 || 20000; - // function to call when a peak is detected - this._onPeak = function () { - }; - }; - /** - * The update method is run in the draw loop. - * - * Accepts an FFT object. You must call .analyze() - * on the FFT object prior to updating the peakDetect - * because it relies on a completed FFT analysis. - * - * @method update - * @param {p5.FFT} fftObject A p5.FFT object - */ - p5.PeakDetect.prototype.update = function (fftObject) { - var nrg = this.energy = fftObject.getEnergy(this.f1, this.f2) / 255; - if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { - // trigger callback - this._onPeak(); - this.isDetected = true; - // debounce - this.cutoff = nrg * this.cutoffMult; - this.framesSinceLastPeak = 0; - } else { - this.isDetected = false; - if (this.framesSinceLastPeak <= this.framesPerPeak) { - this.framesSinceLastPeak++; - } else { - this.cutoff *= this.decayRate; - this.cutoff = Math.max(this.cutoff, this.threshold); + for (var i = 1; i < this.mathOps.length; i++) { + this.mathOps[i].dispose(); } - } - this.currentValue = nrg; - this.penergy = nrg; - }; - /** - * onPeak accepts two arguments: a function to call when - * a peak is detected. The value of the peak, - * between 0.0 and 1.0, is passed to the callback. - * - * @method onPeak - * @param {Function} callback Name of a function that will - * be called when a peak is - * detected. - * @param {Object} [val] Optional value to pass - * into the function when - * a peak is detected. - * @example - *
- * var cnv, soundFile, fft, peakDetect; - * var ellipseWidth = 0; - * - * function preload() { - * soundFile = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * cnv = createCanvas(100,100); - * textAlign(CENTER); - * - * fft = new p5.FFT(); - * peakDetect = new p5.PeakDetect(); - * - * setupSound(); - * - * // when a beat is detected, call triggerBeat() - * peakDetect.onPeak(triggerBeat); - * } - * - * function draw() { - * background(0); - * fill(255); - * text('click to play', width/2, height/2); - * - * fft.analyze(); - * peakDetect.update(fft); - * - * ellipseWidth *= 0.95; - * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); - * } - * - * // this function is called by peakDetect.onPeak - * function triggerBeat() { - * ellipseWidth = 50; - * } - * - * // mouseclick starts/stops sound - * function setupSound() { - * cnv.mouseClicked( function() { - * if (soundFile.isPlaying() ) { - * soundFile.stop(); - * } else { - * soundFile.play(); - * } - * }); - * } - *
- */ - p5.PeakDetect.prototype.onPeak = function (callback, val) { - var self = this; - self._onPeak = function () { - callback(self.energy, val); - }; - }; -}(); -var gain; -'use strict'; -gain = function () { - var p5sound = master; - /** - * A gain node is usefull to set the relative volume of sound. - * It's typically used to build mixers. - * - * @class p5.Gain - * @constructor - * @example - *
- * - * // load two soundfile and crossfade beetween them - * var sound1,sound2; - * var gain1, gain2, gain3; - * - * function preload(){ - * soundFormats('ogg', 'mp3'); - * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); - * sound2 = loadSound('assets/beat.mp3'); - * } - * - * function setup() { - * createCanvas(400,200); - * - * // create a 'master' gain to which we will connect both soundfiles - * gain3 = new p5.Gain(); - * gain3.connect(); - * - * // setup first sound for playing - * sound1.rate(1); - * sound1.loop(); - * sound1.disconnect(); // diconnect from p5 output - * - * gain1 = new p5.Gain(); // setup a gain node - * gain1.setInput(sound1); // connect the first sound to its input - * gain1.connect(gain3); // connect its output to the 'master' - * - * sound2.rate(1); - * sound2.disconnect(); - * sound2.loop(); - * - * gain2 = new p5.Gain(); - * gain2.setInput(sound2); - * gain2.connect(gain3); - * - * } - * - * function draw(){ - * background(180); - * - * // calculate the horizontal distance beetween the mouse and the right of the screen - * var d = dist(mouseX,0,width,0); - * - * // map the horizontal position of the mouse to values useable for volume control of sound1 - * var vol1 = map(mouseX,0,width,0,1); - * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa - * - * gain1.amp(vol1,0.5,0); - * gain2.amp(vol2,0.5,0); - * - * // map the vertical position of the mouse to values useable for 'master volume control' - * var vol3 = map(mouseY,0,height,0,1); - * gain3.amp(vol3,0.5,0); - * } - *
- * - */ - p5.Gain = function () { - this.ac = p5sound.audiocontext; - this.input = this.ac.createGain(); - this.output = this.ac.createGain(); - // otherwise, Safari distorts - this.input.gain.value = 0.5; - this.input.connect(this.output); - // add to the soundArray - p5sound.soundArray.push(this); - }; - /** - * Connect a source to the gain node. - * - * @method setInput - * @param {Object} src p5.sound / Web Audio object with a sound - * output. - */ - p5.Gain.prototype.setInput = function (src) { - src.connect(this.input); - }; - /** - * Send output to a p5.sound or web audio object - * - * @method connect - * @param {Object} unit - */ - p5.Gain.prototype.connect = function (unit) { - var u = unit || p5.soundOut.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all output. - * - * @method disconnect - */ - p5.Gain.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Set the output level of the gain node. - * - * @method amp - * @param {Number} volume amplitude between 0 and 1.0 - * @param {Number} [rampTime] create a fade that lasts rampTime - * @param {Number} [timeFromNow] schedule this event to happen - * seconds from now - */ - p5.Gain.prototype.amp = function (vol, rampTime, tFromNow) { - var rampTime = rampTime || 0; - var tFromNow = tFromNow || 0; - var now = p5sound.audiocontext.currentTime; - var currentVol = this.output.gain.value; - this.output.gain.cancelScheduledValues(now); - this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); - this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); - }; - p5.Gain.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); - if (this.output) { - this.output.disconnect(); + }; + // Different name for backwards compatibility, replicates p5.Envelope class + p5.Env = function (t1, l1, t2, l2, t3, l3) { + console.warn( + "WARNING: p5.Env is now deprecated and may be removed in future versions. " + + "Please use the new p5.Envelope instead." + ); + p5.Envelope.call(this, t1, l1, t2, l2, t3, l3); + }; + p5.Env.prototype = Object.create(p5.Envelope.prototype); + })( + master, + Tone_signal_Add, + Tone_signal_Multiply, + Tone_signal_Scale, + Tone_signal_TimelineSignal + ); + var pulse; + ("use strict"); + pulse = (function () { + var p5sound = master; + /** + * Creates a Pulse object, an oscillator that implements + * Pulse Width Modulation. + * The pulse is created with two oscillators. + * Accepts a parameter for frequency, and to set the + * width between the pulses. See + * p5.Oscillator for a full list of methods. + * + * @class p5.Pulse + * @extends p5.Oscillator + * @constructor + * @param {Number} [freq] Frequency in oscillations per second (Hz) + * @param {Number} [w] Width between the pulses (0 to 1.0, + * defaults to 0) + * @example + *
+ * var pulse; + * function setup() { + * background(0); + * + * // Create and start the pulse wave oscillator + * pulse = new p5.Pulse(); + * pulse.amp(0.5); + * pulse.freq(220); + * pulse.start(); + * } + * + * function draw() { + * var w = map(mouseX, 0, width, 0, 1); + * w = constrain(w, 0, 1); + * pulse.width(w) + * } + *
+ */ + p5.Pulse = function (freq, w) { + p5.Oscillator.call(this, freq, "sawtooth"); + // width of PWM, should be betw 0 to 1.0 + this.w = w || 0; + // create a second oscillator with inverse frequency + this.osc2 = new p5.SawOsc(freq); + // create a delay node + this.dNode = p5sound.audiocontext.createDelay(); + // dc offset + this.dcOffset = createDCOffset(); + this.dcGain = p5sound.audiocontext.createGain(); + this.dcOffset.connect(this.dcGain); + this.dcGain.connect(this.output); + // set delay time based on PWM width + this.f = freq || 440; + var mW = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = mW; + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + // disconnect osc2 and connect it to delay, which is connected to output + this.osc2.disconnect(); + this.osc2.panner.disconnect(); + this.osc2.amp(-1); + // inverted amplitude + this.osc2.output.connect(this.dNode); + this.dNode.connect(this.output); + this.output.gain.value = 1; + this.output.connect(this.panner); + }; + p5.Pulse.prototype = Object.create(p5.Oscillator.prototype); + /** + * Set the width of a Pulse object (an oscillator that implements + * Pulse Width Modulation). + * + * @method width + * @param {Number} [width] Width between the pulses (0 to 1.0, + * defaults to 0) + */ + p5.Pulse.prototype.width = function (w) { + if (typeof w === "number") { + if (w <= 1 && w >= 0) { + this.w = w; + // set delay time based on PWM width + // var mW = map(this.w, 0, 1.0, 0, 1/this.f); + var mW = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = mW; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + w.connect(this.dNode.delayTime); + var sig = new p5.SignalAdd(-0.5); + sig.setInput(w); + sig = sig.mult(-1); + sig = sig.mult(1.7); + sig.connect(this.dcGain.gain); + } + }; + p5.Pulse.prototype.start = function (f, time) { + var now = p5sound.audiocontext.currentTime; + var t = time || 0; + if (!this.started) { + var freq = f || this.f; + var type = this.oscillator.type; + this.oscillator = p5sound.audiocontext.createOscillator(); + this.oscillator.frequency.setValueAtTime(freq, now); + this.oscillator.type = type; + this.oscillator.connect(this.output); + this.oscillator.start(t + now); + // set up osc2 + this.osc2.oscillator = p5sound.audiocontext.createOscillator(); + this.osc2.oscillator.frequency.setValueAtTime(freq, t + now); + this.osc2.oscillator.type = type; + this.osc2.oscillator.connect(this.osc2.output); + this.osc2.start(t + now); + this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]; + // start dcOffset, too + this.dcOffset = createDCOffset(); + this.dcOffset.connect(this.dcGain); + this.dcOffset.start(t + now); + // if LFO connections depend on these oscillators + if (this.mods !== undefined && this.mods.frequency !== undefined) { + this.mods.frequency.connect(this.freqNode[0]); + this.mods.frequency.connect(this.freqNode[1]); + } + this.started = true; + this.osc2.started = true; + } + }; + p5.Pulse.prototype.stop = function (time) { + if (this.started) { + var t = time || 0; + var now = p5sound.audiocontext.currentTime; + this.oscillator.stop(t + now); + if (this.osc2.oscillator) { + this.osc2.oscillator.stop(t + now); + } + this.dcOffset.stop(t + now); + this.started = false; + this.osc2.started = false; + } + }; + p5.Pulse.prototype.freq = function (val, rampTime, tFromNow) { + if (typeof val === "number") { + this.f = val; + var now = p5sound.audiocontext.currentTime; + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var currentFreq = this.oscillator.frequency.value; + this.oscillator.frequency.cancelScheduledValues(now); + this.oscillator.frequency.setValueAtTime(currentFreq, now + tFromNow); + this.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); + this.osc2.oscillator.frequency.cancelScheduledValues(now); + this.osc2.oscillator.frequency.setValueAtTime( + currentFreq, + now + tFromNow + ); + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + val, + tFromNow + rampTime + now + ); + if (this.freqMod) { + this.freqMod.output.disconnect(); + this.freqMod = null; + } + } else if (val.output) { + val.output.disconnect(); + val.output.connect(this.oscillator.frequency); + val.output.connect(this.osc2.oscillator.frequency); + this.freqMod = val; + } + }; + // inspiration: http://webaudiodemos.appspot.com/oscilloscope/ + function createDCOffset() { + var ac = p5sound.audiocontext; + var buffer = ac.createBuffer(1, 2048, ac.sampleRate); + var data = buffer.getChannelData(0); + for (var i = 0; i < 2048; i++) data[i] = 1; + var bufferSource = ac.createBufferSource(); + bufferSource.buffer = buffer; + bufferSource.loop = true; + return bufferSource; + } + })(master, oscillator); + var noise; + ("use strict"); + noise = (function () { + var p5sound = master; + /** + * Noise is a type of oscillator that generates a buffer with random values. + * + * @class p5.Noise + * @extends p5.Oscillator + * @constructor + * @param {String} type Type of noise can be 'white' (default), + * 'brown' or 'pink'. + */ + p5.Noise = function (type) { + var assignType; + p5.Oscillator.call(this); + delete this.f; + delete this.freq; + delete this.oscillator; + if (type === "brown") { + assignType = _brownNoise; + } else if (type === "pink") { + assignType = _pinkNoise; + } else { + assignType = _whiteNoise; + } + this.buffer = assignType; + }; + p5.Noise.prototype = Object.create(p5.Oscillator.prototype); + // generate noise buffers + var _whiteNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var whiteBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = whiteBuffer.getChannelData(0); + for (var i = 0; i < bufferSize; i++) { + noiseData[i] = Math.random() * 2 - 1; + } + whiteBuffer.type = "white"; + return whiteBuffer; + })(); + var _pinkNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var pinkBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = pinkBuffer.getChannelData(0); + var b0, b1, b2, b3, b4, b5, b6; + b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0; + for (var i = 0; i < bufferSize; i++) { + var white = Math.random() * 2 - 1; + b0 = 0.99886 * b0 + white * 0.0555179; + b1 = 0.99332 * b1 + white * 0.0750759; + b2 = 0.969 * b2 + white * 0.153852; + b3 = 0.8665 * b3 + white * 0.3104856; + b4 = 0.55 * b4 + white * 0.5329522; + b5 = -0.7616 * b5 - white * 0.016898; + noiseData[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362; + noiseData[i] *= 0.11; + // (roughly) compensate for gain + b6 = white * 0.115926; + } + pinkBuffer.type = "pink"; + return pinkBuffer; + })(); + var _brownNoise = (function () { + var bufferSize = 2 * p5sound.audiocontext.sampleRate; + var brownBuffer = p5sound.audiocontext.createBuffer( + 1, + bufferSize, + p5sound.audiocontext.sampleRate + ); + var noiseData = brownBuffer.getChannelData(0); + var lastOut = 0; + for (var i = 0; i < bufferSize; i++) { + var white = Math.random() * 2 - 1; + noiseData[i] = (lastOut + 0.02 * white) / 1.02; + lastOut = noiseData[i]; + noiseData[i] *= 3.5; + } + brownBuffer.type = "brown"; + return brownBuffer; + })(); + /** + * Set type of noise to 'white', 'pink' or 'brown'. + * White is the default. + * + * @method setType + * @param {String} [type] 'white', 'pink' or 'brown' + */ + p5.Noise.prototype.setType = function (type) { + switch (type) { + case "white": + this.buffer = _whiteNoise; + break; + case "pink": + this.buffer = _pinkNoise; + break; + case "brown": + this.buffer = _brownNoise; + break; + default: + this.buffer = _whiteNoise; + } + if (this.started) { + var now = p5sound.audiocontext.currentTime; + this.stop(now); + this.start(now + 0.01); + } + }; + p5.Noise.prototype.getType = function () { + return this.buffer.type; + }; + p5.Noise.prototype.start = function () { + if (this.started) { + this.stop(); + } + this.noise = p5sound.audiocontext.createBufferSource(); + this.noise.buffer = this.buffer; + this.noise.loop = true; + this.noise.connect(this.output); + var now = p5sound.audiocontext.currentTime; + this.noise.start(now); + this.started = true; + }; + p5.Noise.prototype.stop = function () { + var now = p5sound.audiocontext.currentTime; + if (this.noise) { + this.noise.stop(now); + this.started = false; + } + }; + p5.Noise.prototype.dispose = function () { + var now = p5sound.audiocontext.currentTime; + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.noise) { + this.noise.disconnect(); + this.stop(now); + } + if (this.output) { + this.output.disconnect(); + } + if (this.panner) { + this.panner.disconnect(); + } + this.output = null; + this.panner = null; + this.buffer = null; + this.noise = null; + }; + })(master); + var audioin; + ("use strict"); + audioin = (function () { + var p5sound = master; + // an array of input sources + p5sound.inputSources = []; + /** + *

Get audio from an input, i.e. your computer's microphone.

+ * + *

Turn the mic on/off with the start() and stop() methods. When the mic + * is on, its volume can be measured with getLevel or by connecting an + * FFT object.

+ * + *

If you want to hear the AudioIn, use the .connect() method. + * AudioIn does not connect to p5.sound output by default to prevent + * feedback.

+ * + *

Note: This uses the getUserMedia/ + * Stream API, which is not supported by certain browsers. Access in Chrome browser + * is limited to localhost and https, but access over http may be limited.

+ * + * @class p5.AudioIn + * @constructor + * @param {Function} [errorCallback] A function to call if there is an error + * accessing the AudioIn. For example, + * Safari and iOS devices do not + * currently allow microphone access. + * @example + *
+ * var mic; + * function setup(){ + * mic = new p5.AudioIn() + * mic.start(); + * } + * function draw(){ + * background(0); + * micLevel = mic.getLevel(); + * ellipse(width/2, constrain(height-micLevel*height*5, 0, height), 10, 10); + * } + *
+ */ + p5.AudioIn = function (errorCallback) { + // set up audio input + /** + * @property {GainNode} input + */ + this.input = p5sound.audiocontext.createGain(); + /** + * @property {GainNode} output + */ + this.output = p5sound.audiocontext.createGain(); + /** + * @property {MediaStream|null} stream + */ + this.stream = null; + /** + * @property {MediaStreamAudioSourceNode|null} mediaStream + */ + this.mediaStream = null; + /** + * @property {Number|null} currentSource + */ + this.currentSource = null; + /** + * Client must allow browser to access their microphone / audioin source. + * Default: false. Will become true when the client enables acces. + * + * @property {Boolean} enabled + */ + this.enabled = false; + /** + * Input amplitude, connect to it by default but not to master out + * + * @property {p5.Amplitude} amplitude + */ + this.amplitude = new p5.Amplitude(); + this.output.connect(this.amplitude.input); + if ( + !window.MediaStreamTrack || + !window.navigator.mediaDevices || + !window.navigator.mediaDevices.getUserMedia + ) { + errorCallback + ? errorCallback() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + ); + } + // add to soundArray so we can dispose on close + p5sound.soundArray.push(this); + }; + /** + * Start processing audio input. This enables the use of other + * AudioIn methods like getLevel(). Note that by default, AudioIn + * is not connected to p5.sound's output. So you won't hear + * anything unless you use the connect() method.
+ * + * Certain browsers limit access to the user's microphone. For example, + * Chrome only allows access from localhost and over https. For this reason, + * you may want to include an errorCallback—a function that is called in case + * the browser won't provide mic access. + * + * @method start + * @param {Function} [successCallback] Name of a function to call on + * success. + * @param {Function} [errorCallback] Name of a function to call if + * there was an error. For example, + * some browsers do not support + * getUserMedia. + */ + p5.AudioIn.prototype.start = function (successCallback, errorCallback) { + var self = this; + if (this.stream) { + this.stop(); + } + // set the audio source + var audioSource = p5sound.inputSources[self.currentSource]; + var constraints = { + audio: { + sampleRate: p5sound.audiocontext.sampleRate, + echoCancellation: false, + }, + }; + // if developers determine which source to use + if (p5sound.inputSources[this.currentSource]) { + constraints.audio.deviceId = audioSource.deviceId; + } + window.navigator.mediaDevices + .getUserMedia(constraints) + .then(function (stream) { + self.stream = stream; + self.enabled = true; + // Wrap a MediaStreamSourceNode around the live input + self.mediaStream = + p5sound.audiocontext.createMediaStreamSource(stream); + self.mediaStream.connect(self.output); + // only send to the Amplitude reader, so we can see it but not hear it. + self.amplitude.setInput(self.output); + if (successCallback) successCallback(); + }) + .catch(function (err) { + if (errorCallback) errorCallback(err); + else console.error(err); + }); + }; + /** + * Turn the AudioIn off. If the AudioIn is stopped, it cannot getLevel(). + * If re-starting, the user may be prompted for permission access. + * + * @method stop + */ + p5.AudioIn.prototype.stop = function () { + if (this.stream) { + this.stream.getTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.disconnect(); + delete this.mediaStream; + delete this.stream; + } + }; + /** + * Connect to an audio unit. If no parameter is provided, will + * connect to the master output (i.e. your speakers).
+ * + * @method connect + * @param {Object} [unit] An object that accepts audio input, + * such as an FFT + */ + p5.AudioIn.prototype.connect = function (unit) { + if (unit) { + if (unit.hasOwnProperty("input")) { + this.output.connect(unit.input); + } else if (unit.hasOwnProperty("analyser")) { + this.output.connect(unit.analyser); + } else { + this.output.connect(unit); + } + } else { + this.output.connect(p5sound.input); + } + }; + /** + * Disconnect the AudioIn from all audio units. For example, if + * connect() had been called, disconnect() will stop sending + * signal to your speakers.
+ * + * @method disconnect + */ + p5.AudioIn.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + // stay connected to amplitude even if not outputting to p5 + this.output.connect(this.amplitude.input); + } + }; + /** + * Read the Amplitude (volume level) of an AudioIn. The AudioIn + * class contains its own instance of the Amplitude class to help + * make it easy to get a microphone's volume level. Accepts an + * optional smoothing value (0.0 < 1.0). NOTE: AudioIn must + * .start() before using .getLevel().
+ * + * @method getLevel + * @param {Number} [smoothing] Smoothing is 0.0 by default. + * Smooths values based on previous values. + * @return {Number} Volume level (between 0.0 and 1.0) + */ + p5.AudioIn.prototype.getLevel = function (smoothing) { + if (smoothing) { + this.amplitude.smoothing = smoothing; + } + return this.amplitude.getLevel(); + }; + /** + * Set amplitude (volume) of a mic input between 0 and 1.0.
+ * + * @method amp + * @param {Number} vol between 0 and 1.0 + * @param {Number} [time] ramp time (optional) + */ + p5.AudioIn.prototype.amp = function (vol, t) { + if (t) { + var rampTime = t || 0; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues( + p5sound.audiocontext.currentTime + ); + this.output.gain.setValueAtTime( + currentVol, + p5sound.audiocontext.currentTime + ); + this.output.gain.linearRampToValueAtTime( + vol, + rampTime + p5sound.audiocontext.currentTime + ); + } else { + this.output.gain.cancelScheduledValues( + p5sound.audiocontext.currentTime + ); + this.output.gain.setValueAtTime(vol, p5sound.audiocontext.currentTime); + } + }; + /** + * Returns a list of available input sources. This is a wrapper + * for and it returns a Promise. + * + * @method getSources + * @param {Function} [successCallback] This callback function handles the sources when they + * have been enumerated. The callback function + * receives the deviceList array as its only argument + * @param {Function} [errorCallback] This optional callback receives the error + * message as its argument. + * @returns {Promise} Returns a Promise that can be used in place of the callbacks, similar + * to the enumerateDevices() method + * @example + *
+ * var audiograb; + * + * function setup(){ + * //new audioIn + * audioGrab = new p5.AudioIn(); + * + * audioGrab.getSources(function(deviceList) { + * //print out the array of available sources + * console.log(deviceList); + * //set the source to the first item in the deviceList array + * audioGrab.setSource(0); + * }); + * } + *
+ */ + p5.AudioIn.prototype.getSources = function (onSuccess, onError) { + return new Promise(function (resolve, reject) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (devices) { + p5sound.inputSources = devices.filter(function (device) { + return device.kind === "audioinput"; + }); + resolve(p5sound.inputSources); + if (onSuccess) { + onSuccess(p5sound.inputSources); + } + }) + .catch(function (error) { + reject(error); + if (onError) { + onError(error); + } else { + console.error( + "This browser does not support MediaStreamTrack.getSources()" + ); + } + }); + }); + }; + /** + * Set the input source. Accepts a number representing a + * position in the array returned by getSources(). + * This is only available in browsers that support + *
navigator.mediaDevices.enumerateDevices().
+ * + * @method setSource + * @param {number} num position of input source in the array + */ + p5.AudioIn.prototype.setSource = function (num) { + if ( + p5sound.inputSources.length > 0 && + num < p5sound.inputSources.length + ) { + // set the current source + this.currentSource = num; + console.log("set source to ", p5sound.inputSources[this.currentSource]); + } else { + console.log("unable to set input source"); + } + // restart stream if currently active + if (this.stream && this.stream.active) { + this.start(); + } + }; + // private method + p5.AudioIn.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.stop(); + if (this.output) { + this.output.disconnect(); + } + if (this.amplitude) { + this.amplitude.disconnect(); + } + delete this.amplitude; delete this.output; + }; + })(master); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Negate; + Tone_signal_Negate = (function (Tone) { + "use strict"; + Tone.Negate = function () { + this._multiply = this.input = this.output = new Tone.Multiply(-1); + }; + Tone.extend(Tone.Negate, Tone.SignalBase); + Tone.Negate.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._multiply.dispose(); + this._multiply = null; + return this; + }; + return Tone.Negate; + })(Tone_core_Tone, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Subtract; + Tone_signal_Subtract = (function (Tone) { + "use strict"; + Tone.Subtract = function (value) { + this.createInsOuts(2, 0); + this._sum = this.input[0] = this.output = new Tone.Gain(); + this._neg = new Tone.Negate(); + this._param = this.input[1] = new Tone.Signal(value); + this._param.chain(this._neg, this._sum); + }; + Tone.extend(Tone.Subtract, Tone.Signal); + Tone.Subtract.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._neg.dispose(); + this._neg = null; + this._sum.disconnect(); + this._sum = null; + this._param.dispose(); + this._param = null; + return this; + }; + return Tone.Subtract; + })(Tone_core_Tone, Tone_signal_Add, Tone_signal_Negate, Tone_signal_Signal); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_GreaterThanZero; + Tone_signal_GreaterThanZero = (function (Tone) { + "use strict"; + Tone.GreaterThanZero = function () { + this._thresh = this.output = new Tone.WaveShaper(function (val) { + if (val <= 0) { + return 0; + } else { + return 1; + } + }, 127); + this._scale = this.input = new Tone.Multiply(10000); + this._scale.connect(this._thresh); + }; + Tone.extend(Tone.GreaterThanZero, Tone.SignalBase); + Tone.GreaterThanZero.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._scale.dispose(); + this._scale = null; + this._thresh.dispose(); + this._thresh = null; + return this; + }; + return Tone.GreaterThanZero; + })(Tone_core_Tone, Tone_signal_Signal, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_GreaterThan; + Tone_signal_GreaterThan = (function (Tone) { + "use strict"; + Tone.GreaterThan = function (value) { + this.createInsOuts(2, 0); + this._param = this.input[0] = new Tone.Subtract(value); + this.input[1] = this._param.input[1]; + this._gtz = this.output = new Tone.GreaterThanZero(); + this._param.connect(this._gtz); + }; + Tone.extend(Tone.GreaterThan, Tone.Signal); + Tone.GreaterThan.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._param.dispose(); + this._param = null; + this._gtz.dispose(); + this._gtz = null; + return this; + }; + return Tone.GreaterThan; + })(Tone_core_Tone, Tone_signal_GreaterThanZero, Tone_signal_Subtract); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Abs; + Tone_signal_Abs = (function (Tone) { + "use strict"; + Tone.Abs = function () { + this._abs = + this.input = + this.output = + new Tone.WaveShaper(function (val) { + if (val === 0) { + return 0; + } else { + return Math.abs(val); + } + }, 127); + }; + Tone.extend(Tone.Abs, Tone.SignalBase); + Tone.Abs.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._abs.dispose(); + this._abs = null; + return this; + }; + return Tone.Abs; + })(Tone_core_Tone, Tone_signal_WaveShaper); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Modulo; + Tone_signal_Modulo = (function (Tone) { + "use strict"; + Tone.Modulo = function (modulus) { + this.createInsOuts(1, 0); + this._shaper = new Tone.WaveShaper(Math.pow(2, 16)); + this._multiply = new Tone.Multiply(); + this._subtract = this.output = new Tone.Subtract(); + this._modSignal = new Tone.Signal(modulus); + this.input.fan(this._shaper, this._subtract); + this._modSignal.connect(this._multiply, 0, 0); + this._shaper.connect(this._multiply, 0, 1); + this._multiply.connect(this._subtract, 0, 1); + this._setWaveShaper(modulus); + }; + Tone.extend(Tone.Modulo, Tone.SignalBase); + Tone.Modulo.prototype._setWaveShaper = function (mod) { + this._shaper.setMap(function (val) { + var multiple = Math.floor((val + 0.0001) / mod); + return multiple; + }); + }; + Object.defineProperty(Tone.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (mod) { + this._modSignal.value = mod; + this._setWaveShaper(mod); + }, + }); + Tone.Modulo.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._shaper.dispose(); + this._shaper = null; + this._multiply.dispose(); + this._multiply = null; + this._subtract.dispose(); + this._subtract = null; + this._modSignal.dispose(); + this._modSignal = null; + return this; + }; + return Tone.Modulo; + })(Tone_core_Tone, Tone_signal_WaveShaper, Tone_signal_Multiply); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Pow; + Tone_signal_Pow = (function (Tone) { + "use strict"; + Tone.Pow = function (exp) { + this._exp = this.defaultArg(exp, 1); + this._expScaler = + this.input = + this.output = + new Tone.WaveShaper(this._expFunc(this._exp), 8192); + }; + Tone.extend(Tone.Pow, Tone.SignalBase); + Object.defineProperty(Tone.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (exp) { + this._exp = exp; + this._expScaler.setMap(this._expFunc(this._exp)); + }, + }); + Tone.Pow.prototype._expFunc = function (exp) { + return function (val) { + return Math.pow(Math.abs(val), exp); + }; + }; + Tone.Pow.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._expScaler.dispose(); + this._expScaler = null; + return this; + }; + return Tone.Pow; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_AudioToGain; + Tone_signal_AudioToGain = (function (Tone) { + "use strict"; + Tone.AudioToGain = function () { + this._norm = + this.input = + this.output = + new Tone.WaveShaper(function (x) { + return (x + 1) / 2; + }); + }; + Tone.extend(Tone.AudioToGain, Tone.SignalBase); + Tone.AudioToGain.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._norm.dispose(); + this._norm = null; + return this; + }; + return Tone.AudioToGain; + })(Tone_core_Tone, Tone_signal_WaveShaper); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_Expr; + Tone_signal_Expr = (function (Tone) { + "use strict"; + Tone.Expr = function () { + var expr = this._replacements(Array.prototype.slice.call(arguments)); + var inputCount = this._parseInputs(expr); + this._nodes = []; + this.input = new Array(inputCount); + for (var i = 0; i < inputCount; i++) { + this.input[i] = this.context.createGain(); + } + var tree = this._parseTree(expr); + var result; + try { + result = this._eval(tree); + } catch (e) { + this._disposeNodes(); + throw new Error("Tone.Expr: Could evaluate expression: " + expr); + } + this.output = result; + }; + Tone.extend(Tone.Expr, Tone.SignalBase); + function applyBinary(Constructor, args, self) { + var op = new Constructor(); + self._eval(args[0]).connect(op, 0, 0); + self._eval(args[1]).connect(op, 0, 1); + return op; + } + function applyUnary(Constructor, args, self) { + var op = new Constructor(); + self._eval(args[0]).connect(op, 0, 0); + return op; + } + function getNumber(arg) { + return arg ? parseFloat(arg) : undefined; + } + function literalNumber(arg) { + return arg && arg.args ? parseFloat(arg.args) : undefined; + } + Tone.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (arg) { + var sig = new Tone.Signal(getNumber(arg)); + return sig; + }, + }, + input: { + regexp: /^\$\d/, + method: function (arg, self) { + return self.input[getNumber(arg.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { + regexp: /^abs/, + method: applyUnary.bind(this, Tone.Abs), + }, + mod: { + regexp: /^mod/, + method: function (args, self) { + var modulus = literalNumber(args[1]); + var op = new Tone.Modulo(modulus); + self._eval(args[0]).connect(op); + return op; + }, + }, + pow: { + regexp: /^pow/, + method: function (args, self) { + var exp = literalNumber(args[1]); + var op = new Tone.Pow(exp); + self._eval(args[0]).connect(op); + return op; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (args, self) { + var op = new Tone.AudioToGain(); + self._eval(args[0]).connect(op); + return op; + }, + }, + }, + binary: { + "+": { + regexp: /^\+/, + precedence: 1, + method: applyBinary.bind(this, Tone.Add), + }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (args, self) { + if (args.length === 1) { + return applyUnary(Tone.Negate, args, self); + } else { + return applyBinary(Tone.Subtract, args, self); + } + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: applyBinary.bind(this, Tone.Multiply), + }, + }, + unary: { + "-": { + regexp: /^\-/, + method: applyUnary.bind(this, Tone.Negate), + }, + "!": { + regexp: /^\!/, + method: applyUnary.bind(this, Tone.NOT), + }, + }, + }; + Tone.Expr.prototype._parseInputs = function (expr) { + var inputArray = expr.match(/\$\d/g); + var inputMax = 0; + if (inputArray !== null) { + for (var i = 0; i < inputArray.length; i++) { + var inputNum = parseInt(inputArray[i].substr(1)) + 1; + inputMax = Math.max(inputMax, inputNum); + } + } + return inputMax; + }; + Tone.Expr.prototype._replacements = function (args) { + var expr = args.shift(); + for (var i = 0; i < args.length; i++) { + expr = expr.replace(/\%/i, args[i]); + } + return expr; + }; + Tone.Expr.prototype._tokenize = function (expr) { + var position = -1; + var tokens = []; + while (expr.length > 0) { + expr = expr.trim(); + var token = getNextToken(expr); + tokens.push(token); + expr = expr.substr(token.value.length); + } + function getNextToken(expr) { + for (var type in Tone.Expr._Expressions) { + var group = Tone.Expr._Expressions[type]; + for (var opName in group) { + var op = group[opName]; + var reg = op.regexp; + var match = expr.match(reg); + if (match !== null) { + return { + type: type, + value: match[0], + method: op.method, + }; + } + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + expr); + } + return { + next: function () { + return tokens[++position]; + }, + peek: function () { + return tokens[position + 1]; + }, + }; + }; + Tone.Expr.prototype._parseTree = function (expr) { + var lexer = this._tokenize(expr); + var isUndef = this.isUndef.bind(this); + function matchSyntax(token, syn) { + return !isUndef(token) && token.type === "glue" && token.value === syn; + } + function matchGroup(token, groupName, prec) { + var ret = false; + var group = Tone.Expr._Expressions[groupName]; + if (!isUndef(token)) { + for (var opName in group) { + var op = group[opName]; + if (op.regexp.test(token.value)) { + if (!isUndef(prec)) { + if (op.precedence === prec) { + return true; + } + } else { + return true; + } + } + } + } + return ret; + } + function parseExpression(precedence) { + if (isUndef(precedence)) { + precedence = 5; + } + var expr; + if (precedence < 0) { + expr = parseUnary(); + } else { + expr = parseExpression(precedence - 1); + } + var token = lexer.peek(); + while (matchGroup(token, "binary", precedence)) { + token = lexer.next(); + expr = { + operator: token.value, + method: token.method, + args: [expr, parseExpression(precedence - 1)], + }; + token = lexer.peek(); + } + return expr; + } + function parseUnary() { + var token, expr; + token = lexer.peek(); + if (matchGroup(token, "unary")) { + token = lexer.next(); + expr = parseUnary(); + return { + operator: token.value, + method: token.method, + args: [expr], + }; + } + return parsePrimary(); + } + function parsePrimary() { + var token, expr; + token = lexer.peek(); + if (isUndef(token)) { + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + } + if (token.type === "func") { + token = lexer.next(); + return parseFunctionCall(token); + } + if (token.type === "value") { + token = lexer.next(); + return { + method: token.method, + args: token.value, + }; + } + if (matchSyntax(token, "(")) { + lexer.next(); + expr = parseExpression(); + token = lexer.next(); + if (!matchSyntax(token, ")")) { + throw new SyntaxError("Expected )"); + } + return expr; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + token.value + ); + } + function parseFunctionCall(func) { + var token, + args = []; + token = lexer.next(); + if (!matchSyntax(token, "(")) { + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + func.value + '"' + ); + } + token = lexer.peek(); + if (!matchSyntax(token, ")")) { + args = parseArgumentList(); + } + token = lexer.next(); + if (!matchSyntax(token, ")")) { + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + func.value + '"' + ); + } + return { + method: func.method, + args: args, + name: name, + }; + } + function parseArgumentList() { + var token, + expr, + args = []; + while (true) { + expr = parseExpression(); + if (isUndef(expr)) { + break; + } + args.push(expr); + token = lexer.peek(); + if (!matchSyntax(token, ",")) { + break; + } + lexer.next(); + } + return args; + } + return parseExpression(); + }; + Tone.Expr.prototype._eval = function (tree) { + if (!this.isUndef(tree)) { + var node = tree.method(tree.args, this); + this._nodes.push(node); + return node; + } + }; + Tone.Expr.prototype._disposeNodes = function () { + for (var i = 0; i < this._nodes.length; i++) { + var node = this._nodes[i]; + if (this.isFunction(node.dispose)) { + node.dispose(); + } else if (this.isFunction(node.disconnect)) { + node.disconnect(); + } + node = null; + this._nodes[i] = null; + } + this._nodes = null; + }; + Tone.Expr.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._disposeNodes(); + }; + return Tone.Expr; + })( + Tone_core_Tone, + Tone_signal_Add, + Tone_signal_Subtract, + Tone_signal_Multiply, + Tone_signal_GreaterThan, + Tone_signal_GreaterThanZero, + Tone_signal_Abs, + Tone_signal_Negate, + Tone_signal_Modulo, + Tone_signal_Pow + ); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_signal_EqualPowerGain; + Tone_signal_EqualPowerGain = (function (Tone) { + "use strict"; + Tone.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new Tone.WaveShaper( + function (val) { + if (Math.abs(val) < 0.001) { + return 0; + } else { + return this.equalPowerScale(val); + } + }.bind(this), + 4096 + ); + }; + Tone.extend(Tone.EqualPowerGain, Tone.SignalBase); + Tone.EqualPowerGain.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._eqPower.dispose(); + this._eqPower = null; + return this; + }; + return Tone.EqualPowerGain; + })(Tone_core_Tone); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_component_CrossFade; + Tone_component_CrossFade = (function (Tone) { + "use strict"; + Tone.CrossFade = function (initialFade) { + this.createInsOuts(2, 1); + this.a = this.input[0] = new Tone.Gain(); + this.b = this.input[1] = new Tone.Gain(); + this.fade = new Tone.Signal( + this.defaultArg(initialFade, 0.5), + Tone.Type.NormalRange + ); + this._equalPowerA = new Tone.EqualPowerGain(); + this._equalPowerB = new Tone.EqualPowerGain(); + this._invert = new Tone.Expr("1 - $0"); + this.a.connect(this.output); + this.b.connect(this.output); + this.fade.chain(this._equalPowerB, this.b.gain); + this.fade.chain(this._invert, this._equalPowerA, this.a.gain); + this._readOnly("fade"); + }; + Tone.extend(Tone.CrossFade); + Tone.CrossFade.prototype.dispose = function () { + Tone.prototype.dispose.call(this); + this._writable("fade"); + this._equalPowerA.dispose(); + this._equalPowerA = null; + this._equalPowerB.dispose(); + this._equalPowerB = null; + this.fade.dispose(); + this.fade = null; + this._invert.dispose(); + this._invert = null; + this.a.dispose(); + this.a = null; + this.b.dispose(); + this.b = null; + return this; + }; + return Tone.CrossFade; + })( + Tone_core_Tone, + Tone_signal_Signal, + Tone_signal_Expr, + Tone_signal_EqualPowerGain + ); + var effect; + ("use strict"); + effect = (function () { + var p5sound = master; + var CrossFade = Tone_component_CrossFade; + /** + * Effect is a base class for audio effects in p5.
+ * This module handles the nodes and methods that are + * common and useful for current and future effects. + * + * + * This class is extended by p5.Distortion, + * p5.Compressor, + * p5.Delay, + * p5.Filter, + * p5.Reverb. + * + * @class p5.Effect + * @constructor + * + * @param {Object} [ac] Reference to the audio context of the p5 object + * @param {AudioNode} [input] Gain Node effect wrapper + * @param {AudioNode} [output] Gain Node effect wrapper + * @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1) + * @param {AudioNode} [wet] Effects that extend this class should connect + * to the wet signal to this gain node, so that dry and wet + * signals are mixed properly. + */ + p5.Effect = function () { + this.ac = p5sound.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); + /** + * The p5.Effect class is built + * using Tone.js CrossFade + * @private + */ + this._drywet = new CrossFade(1); + /** + * In classes that extend + * p5.Effect, connect effect nodes + * to the wet parameter + */ + this.wet = this.ac.createGain(); + this.input.connect(this._drywet.a); + this.wet.connect(this._drywet.b); + this._drywet.connect(this.output); + this.connect(); + //Add to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Set the output volume of the filter. + * + * @method amp + * @param {Number} [vol] amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts until rampTime + * @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds + */ + p5.Effect.prototype.amp = function (vol, rampTime, tFromNow) { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime( + currentVol, + now + tFromNow + 0.001 + ); + this.output.gain.linearRampToValueAtTime( + vol, + now + tFromNow + rampTime + 0.001 + ); + }; + /** + * Link effects together in a chain + * Example usage: filter.chain(reverb, delay, panner); + * May be used with an open-ended number of arguments + * + * @method chain + * @param {Object} [arguments] Chain together multiple sound objects + */ + p5.Effect.prototype.chain = function () { + if (arguments.length > 0) { + this.connect(arguments[0]); + for (var i = 1; i < arguments.length; i += 1) { + arguments[i - 1].connect(arguments[i]); + } + } + return this; + }; + /** + * Adjust the dry/wet value. + * + * @method drywet + * @param {Number} [fade] The desired drywet value (0 - 1.0) + */ + p5.Effect.prototype.drywet = function (fade) { + if (typeof fade !== "undefined") { + this._drywet.fade.value = fade; + } + return this._drywet.fade.value; + }; + /** + * Send output to a p5.js-sound, Web Audio Node, or use signal to + * control an AudioParam + * + * @method connect + * @param {Object} unit + */ + p5.Effect.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Effect.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + p5.Effect.prototype.dispose = function () { + // remove refernce form soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.input) { + this.input.disconnect(); + delete this.input; + } + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this._drywet) { + this._drywet.disconnect(); + delete this._drywet; + } + if (this.wet) { + this.wet.disconnect(); + delete this.wet; + } + this.ac = undefined; + }; + return p5.Effect; + })(master, Tone_component_CrossFade); + var filter; + ("use strict"); + filter = (function () { + var p5sound = master; + var Effect = effect; + /** + *

A p5.Filter uses a Web Audio Biquad Filter to filter + * the frequency response of an input source. Subclasses + * include:

+ * * p5.LowPass: + * Allows frequencies below the cutoff frequency to pass through, + * and attenuates frequencies above the cutoff.
+ * * p5.HighPass: + * The opposite of a lowpass filter.
+ * * p5.BandPass: + * Allows a range of frequencies to pass through and attenuates + * the frequencies below and above this frequency range.
+ * + * The .res() method controls either width of the + * bandpass, or resonance of the low/highpass cutoff frequency. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Filter + * @extends p5.Effect + * @constructor + * @param {String} [type] 'lowpass' (default), 'highpass', 'bandpass' + * @example + *
+ * var fft, noise, filter; + * + * function setup() { + * fill(255, 40, 255); + * + * filter = new p5.BandPass(); + * + * noise = new p5.Noise(); + * // disconnect unfiltered noise, + * // and connect to filter + * noise.disconnect(); + * noise.connect(filter); + * noise.start(); + * + * fft = new p5.FFT(); + * } + * + * function draw() { + * background(30); + * + * // set the BandPass frequency based on mouseX + * var freq = map(mouseX, 0, width, 20, 10000); + * filter.freq(freq); + * // give the filter a narrow band (lower res = wider bandpass) + * filter.res(50); + * + * // draw filtered spectrum + * var spectrum = fft.analyze(); + * noStroke(); + * for (var i = 0; i < spectrum.length; i++) { + * var x = map(i, 0, spectrum.length, 0, width); + * var h = -height + map(spectrum[i], 0, 255, height, 0); + * rect(x, height, width/spectrum.length, h); + * } + * + * isMouseOverCanvas(); + * } + * + * function isMouseOverCanvas() { + * var mX = mouseX, mY = mouseY; + * if (mX > 0 && mX < width && mY < height && mY > 0) { + * noise.amp(0.5, 0.2); + * } else { + * noise.amp(0, 0.2); + * } + * } + *
+ */ + //constructor with inheritance + p5.Filter = function (type) { + Effect.call(this); + //add extend Effect by adding a Biquad Filter + /** + * The p5.Filter is built with a + * + * Web Audio BiquadFilter Node. + * + * @property {DelayNode} biquadFilter + */ + this.biquad = this.ac.createBiquadFilter(); + this.input.connect(this.biquad); + this.biquad.connect(this.wet); + if (type) { + this.setType(type); + } + //Properties useful for the toggle method. + this._on = true; + this._untoggledType = this.biquad.type; + }; + p5.Filter.prototype = Object.create(Effect.prototype); + /** + * Filter an audio signal according to a set + * of filter parameters. + * + * @method process + * @param {Object} Signal An object that outputs audio + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance/Width of the filter frequency + * from 0.001 to 1000 + */ + p5.Filter.prototype.process = function (src, freq, res, time) { + src.connect(this.input); + this.set(freq, res, time); + }; + /** + * Set the frequency and the resonance of the filter. + * + * @method set + * @param {Number} [freq] Frequency in Hz, from 10 to 22050 + * @param {Number} [res] Resonance (Q) from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + p5.Filter.prototype.set = function (freq, res, time) { + if (freq) { + this.freq(freq, time); + } + if (res) { + this.res(res, time); + } + }; + /** + * Set the filter frequency, in Hz, from 10 to 22050 (the range of + * human hearing, although in reality most people hear in a narrower + * range). + * + * @method freq + * @param {Number} freq Filter Frequency + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current frequency value + */ + p5.Filter.prototype.freq = function (freq, time) { + var t = time || 0; + if (freq <= 0) { + freq = 1; + } + if (typeof freq === "number") { + this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.biquad.frequency.exponentialRampToValueAtTime( + freq, + this.ac.currentTime + 0.02 + t + ); + } else if (freq) { + freq.connect(this.biquad.frequency); + } + return this.biquad.frequency.value; + }; + /** + * Controls either width of a bandpass frequency, + * or the resonance of a low/highpass cutoff frequency. + * + * @method res + * @param {Number} res Resonance/Width of filter freq + * from 0.001 to 1000 + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + * @return {Number} value Returns the current res value + */ + p5.Filter.prototype.res = function (res, time) { + var t = time || 0; + if (typeof res === "number") { + this.biquad.Q.value = res; + this.biquad.Q.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.Q.linearRampToValueAtTime( + res, + this.ac.currentTime + 0.02 + t + ); + } else if (res) { + res.connect(this.biquad.Q); + } + return this.biquad.Q.value; + }; + /** + * Controls the gain attribute of a Biquad Filter. + * This is distinctly different from .amp() which is inherited from p5.Effect + * .amp() controls the volume via the output gain node + * p5.Filter.gain() controls the gain parameter of a Biquad Filter node. + * + * @method gain + * @param {Number} gain + * @return {Number} Returns the current or updated gain value + */ + p5.Filter.prototype.gain = function (gain, time) { + var t = time || 0; + if (typeof gain === "number") { + this.biquad.gain.value = gain; + this.biquad.gain.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.biquad.gain.linearRampToValueAtTime( + gain, + this.ac.currentTime + 0.02 + t + ); + } else if (gain) { + gain.connect(this.biquad.gain); + } + return this.biquad.gain.value; + }; + /** + * Toggle function. Switches between the specified type and allpass + * + * @method toggle + * @return {boolean} [Toggle value] + */ + p5.Filter.prototype.toggle = function () { + this._on = !this._on; + if (this._on === true) { + this.biquad.type = this._untoggledType; + } else if (this._on === false) { + this.biquad.type = "allpass"; + } + return this._on; + }; + /** + * Set the type of a p5.Filter. Possible types include: + * "lowpass" (default), "highpass", "bandpass", + * "lowshelf", "highshelf", "peaking", "notch", + * "allpass". + * + * @method setType + * @param {String} t + */ + p5.Filter.prototype.setType = function (t) { + this.biquad.type = t; + this._untoggledType = this.biquad.type; + }; + p5.Filter.prototype.dispose = function () { + // remove reference from soundArray + Effect.prototype.dispose.apply(this); + if (this.biquad) { + this.biquad.disconnect(); + delete this.biquad; + } + }; + /** + * Constructor: new p5.LowPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('lowpass'). + * See p5.Filter for methods. + * + * @class p5.LowPass + * @constructor + * @extends p5.Filter + */ + p5.LowPass = function () { + p5.Filter.call(this, "lowpass"); + }; + p5.LowPass.prototype = Object.create(p5.Filter.prototype); + /** + * Constructor: new p5.HighPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('highpass'). + * See p5.Filter for methods. + * + * @class p5.HighPass + * @constructor + * @extends p5.Filter + */ + p5.HighPass = function () { + p5.Filter.call(this, "highpass"); + }; + p5.HighPass.prototype = Object.create(p5.Filter.prototype); + /** + * Constructor: new p5.BandPass() Filter. + * This is the same as creating a p5.Filter and then calling + * its method setType('bandpass'). + * See p5.Filter for methods. + * + * @class p5.BandPass + * @constructor + * @extends p5.Filter + */ + p5.BandPass = function () { + p5.Filter.call(this, "bandpass"); + }; + p5.BandPass.prototype = Object.create(p5.Filter.prototype); + return p5.Filter; + })(master, effect); + var src_eqFilter; + ("use strict"); + src_eqFilter = (function () { + var Filter = filter; + var p5sound = master; + /** + * EQFilter extends p5.Filter with constraints + * necessary for the p5.EQ + * + * @private + */ + var EQFilter = function (freq, res) { + Filter.call(this, "peaking"); + this.disconnect(); + this.set(freq, res); + this.biquad.gain.value = 0; + delete this.input; + delete this.output; + delete this._drywet; + delete this.wet; + }; + EQFilter.prototype = Object.create(Filter.prototype); + EQFilter.prototype.amp = function () { + console.warn("`amp()` is not available for p5.EQ bands. Use `.gain()`"); + }; + EQFilter.prototype.drywet = function () { + console.warn("`drywet()` is not available for p5.EQ bands."); + }; + EQFilter.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + if (this.biquad) { + this.biquad.connect(u.input ? u.input : u); + } else { + this.output.connect(u.input ? u.input : u); + } + }; + EQFilter.prototype.disconnect = function () { + if (this.biquad) { + this.biquad.disconnect(); + } + }; + EQFilter.prototype.dispose = function () { + // remove reference form soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this.disconnect(); + delete this.biquad; + }; + return EQFilter; + })(filter, master); + var eq; + ("use strict"); + eq = (function () { + var Effect = effect; + var EQFilter = src_eqFilter; + /** + * p5.EQ is an audio effect that performs the function of a multiband + * audio equalizer. Equalization is used to adjust the balance of + * frequency compoenents of an audio signal. This process is commonly used + * in sound production and recording to change the waveform before it reaches + * a sound output device. EQ can also be used as an audio effect to create + * interesting distortions by filtering out parts of the spectrum. p5.EQ is + * built using a chain of Web Audio Biquad Filter Nodes and can be + * instantiated with 3 or 8 bands. Bands can be added or removed from + * the EQ by directly modifying p5.EQ.bands (the array that stores filters). + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.EQ + * @constructor + * @extends p5.Effect + * @param {Number} [_eqsize] Constructor will accept 3 or 8, defaults to 3 + * @return {Object} p5.EQ object + * + * @example + *
+ * var eq; + * var band_names; + * var band_index; + * + * var soundFile, play; + * + * function preload() { + * soundFormats('mp3', 'ogg'); + * soundFile = loadSound('assets/beat'); + * } + * + * function setup() { + * eq = new p5.EQ(3); + * soundFile.disconnect(); + * eq.process(soundFile); + * + * band_names = ['lows','mids','highs']; + * band_index = 0; + * play = false; + * textAlign(CENTER); + * } + * + * function draw() { + * background(30); + * noStroke(); + * fill(255); + * text('click to kill',50,25); + * + * fill(255, 40, 255); + * textSize(26); + * text(band_names[band_index],50,55); + * + * fill(255); + * textSize(9); + * text('space = play/pause',50,80); + * } + * + * //If mouse is over canvas, cycle to the next band and kill the frequency + * function mouseClicked() { + * for (var i = 0; i < eq.bands.length; i++) { + * eq.bands[i].gain(0); + * } + * eq.bands[band_index].gain(-40); + * if (mouseX > 0 && mouseX < width && mouseY < height && mouseY > 0) { + * band_index === 2 ? band_index = 0 : band_index++; + * } + * } + * + * //use space bar to trigger play / pause + * function keyPressed() { + * if (key===' ') { + * play = !play + * play ? soundFile.loop() : soundFile.pause(); + * } + * } + *
+ */ + p5.EQ = function (_eqsize) { + Effect.call(this); + //p5.EQ can be of size (3) or (8), defaults to 3 + _eqsize = _eqsize === 3 || _eqsize === 8 ? _eqsize : 3; + var factor; + _eqsize === 3 ? (factor = Math.pow(2, 3)) : (factor = 2); + /** + * The p5.EQ is built with abstracted p5.Filter objects. + * To modify any bands, use methods of the + * p5.Filter API, especially `gain` and `freq`. + * Bands are stored in an array, with indices 0 - 3, or 0 - 7 + * @property {Array} bands + * + */ + this.bands = []; + var freq, res; + for (var i = 0; i < _eqsize; i++) { + if (i === _eqsize - 1) { + freq = 21000; + res = 0.01; + } else if (i === 0) { + freq = 100; + res = 0.1; + } else if (i === 1) { + freq = _eqsize === 3 ? 360 * factor : 360; + res = 1; + } else { + freq = this.bands[i - 1].freq() * factor; + res = 1; + } + this.bands[i] = this._newBand(freq, res); + if (i > 0) { + this.bands[i - 1].connect(this.bands[i].biquad); + } else { + this.input.connect(this.bands[i].biquad); + } + } + this.bands[_eqsize - 1].connect(this.output); + }; + p5.EQ.prototype = Object.create(Effect.prototype); + /** + * Process an input by connecting it to the EQ + * @method process + * @param {Object} src Audio source + */ + p5.EQ.prototype.process = function (src) { + src.connect(this.input); + }; + // /** + // * Set the frequency and gain of each band in the EQ. This method should be + // * called with 3 or 8 frequency and gain pairs, depending on the size of the EQ. + // * ex. eq.set(freq0, gain0, freq1, gain1, freq2, gain2); + // * + // * @method set + // * @param {Number} [freq0] Frequency value for band with index 0 + // * @param {Number} [gain0] Gain value for band with index 0 + // * @param {Number} [freq1] Frequency value for band with index 1 + // * @param {Number} [gain1] Gain value for band with index 1 + // * @param {Number} [freq2] Frequency value for band with index 2 + // * @param {Number} [gain2] Gain value for band with index 2 + // * @param {Number} [freq3] Frequency value for band with index 3 + // * @param {Number} [gain3] Gain value for band with index 3 + // * @param {Number} [freq4] Frequency value for band with index 4 + // * @param {Number} [gain4] Gain value for band with index 4 + // * @param {Number} [freq5] Frequency value for band with index 5 + // * @param {Number} [gain5] Gain value for band with index 5 + // * @param {Number} [freq6] Frequency value for band with index 6 + // * @param {Number} [gain6] Gain value for band with index 6 + // * @param {Number} [freq7] Frequency value for band with index 7 + // * @param {Number} [gain7] Gain value for band with index 7 + // */ + p5.EQ.prototype.set = function () { + if (arguments.length === this.bands.length * 2) { + for (var i = 0; i < arguments.length; i += 2) { + this.bands[i / 2].freq(arguments[i]); + this.bands[i / 2].gain(arguments[i + 1]); + } + } else { + console.error( + "Argument mismatch. .set() should be called with " + + this.bands.length * 2 + + " arguments. (one frequency and gain value pair for each band of the eq)" + ); + } + }; + /** + * Add a new band. Creates a p5.Filter and strips away everything but + * the raw biquad filter. This method returns an abstracted p5.Filter, + * which can be added to p5.EQ.bands, in order to create new EQ bands. + * @private + * @method _newBand + * @param {Number} freq + * @param {Number} res + * @return {Object} Abstracted Filter + */ + p5.EQ.prototype._newBand = function (freq, res) { + return new EQFilter(freq, res); + }; + p5.EQ.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.bands) { + while (this.bands.length > 0) { + delete this.bands.pop().dispose(); + } + delete this.bands; + } + }; + return p5.EQ; + })(effect, src_eqFilter); + var panner3d; + ("use strict"); + panner3d = (function () { + var p5sound = master; + var Effect = effect; + /** + * Panner3D is based on the + * Web Audio Spatial Panner Node. + * This panner is a spatial processing node that allows audio to be positioned + * and oriented in 3D space. + * + * The position is relative to an + * Audio Context Listener, which can be accessed + * by p5.soundOut.audiocontext.listener + * + * + * @class p5.Panner3D + * @constructor + */ + p5.Panner3D = function () { + Effect.call(this); + /** + * + * Web Audio Spatial Panner Node + * + * Properties include + * - panningModel: "equal power" or "HRTF" + * - distanceModel: "linear", "inverse", or "exponential" + * + * @property {AudioNode} panner + * + */ + this.panner = this.ac.createPanner(); + this.panner.panningModel = "HRTF"; + this.panner.distanceModel = "linear"; + this.panner.connect(this.output); + this.input.connect(this.panner); + }; + p5.Panner3D.prototype = Object.create(Effect.prototype); + /** + * Connect an audio sorce + * + * @method process + * @param {Object} src Input source + */ + p5.Panner3D.prototype.process = function (src) { + src.connect(this.input); + }; + /** + * Set the X,Y,Z position of the Panner + * @method set + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + p5.Panner3D.prototype.set = function (xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ]; + }; + /** + * Getter and setter methods for position coordinates + * @method positionX + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for position coordinates + * @method positionY + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for position coordinates + * @method positionZ + * @return {Number} updated coordinate value + */ + p5.Panner3D.prototype.positionX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.panner.positionX.value = xVal; + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.panner.positionX); + } + return this.panner.positionX.value; + }; + p5.Panner3D.prototype.positionY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.panner.positionY.value = yVal; + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.panner.positionY); + } + return this.panner.positionY.value; + }; + p5.Panner3D.prototype.positionZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.panner.positionZ.value = zVal; + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.positionZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.panner.positionZ); + } + return this.panner.positionZ.value; + }; + /** + * Set the X,Y,Z position of the Panner + * @method orient + * @param {Number} xVal + * @param {Number} yVal + * @param {Number} zVal + * @param {Number} time + * @return {Array} Updated x, y, z values as an array + */ + p5.Panner3D.prototype.orient = function (xVal, yVal, zVal, time) { + this.orientX(xVal, time); + this.orientY(yVal, time); + this.orientZ(zVal, time); + return [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ]; + }; + /** + * Getter and setter methods for orient coordinates + * @method orientX + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for orient coordinates + * @method orientY + * @return {Number} updated coordinate value + */ + /** + * Getter and setter methods for orient coordinates + * @method orientZ + * @return {Number} updated coordinate value + */ + p5.Panner3D.prototype.orientX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.panner.orientationX.value = xVal; + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.panner.orientationX); + } + return this.panner.orientationX.value; + }; + p5.Panner3D.prototype.orientY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.panner.orientationY.value = yVal; + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.panner.orientationY); + } + return this.panner.orientationY.value; + }; + p5.Panner3D.prototype.orientZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.panner.orientationZ.value = zVal; + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.panner.orientationZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.panner.orientationZ); + } + return this.panner.orientationZ.value; + }; + /** + * Set the rolloff factor and max distance + * @method setFalloff + * @param {Number} [maxDistance] + * @param {Number} [rolloffFactor] + */ + p5.Panner3D.prototype.setFalloff = function (maxDistance, rolloffFactor) { + this.maxDist(maxDistance); + this.rolloff(rolloffFactor); + }; + /** + * Maxium distance between the source and the listener + * @method maxDist + * @param {Number} maxDistance + * @return {Number} updated value + */ + p5.Panner3D.prototype.maxDist = function (maxDistance) { + if (typeof maxDistance === "number") { + this.panner.maxDistance = maxDistance; + } + return this.panner.maxDistance; + }; + /** + * How quickly the volume is reduced as the source moves away from the listener + * @method rollof + * @param {Number} rolloffFactor + * @return {Number} updated value + */ + p5.Panner3D.prototype.rolloff = function (rolloffFactor) { + if (typeof rolloffFactor === "number") { + this.panner.rolloffFactor = rolloffFactor; + } + return this.panner.rolloffFactor; + }; + p5.Panner3D.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.panner) { + this.panner.disconnect(); + delete this.panner; + } + }; + return p5.Panner3D; + })(master, effect); + var listener3d; + ("use strict"); + listener3d = (function () { + var p5sound = master; + var Effect = effect; + // /** + // * listener is a class that can construct both a Spatial Panner + // * and a Spatial Listener. The panner is based on the + // * Web Audio Spatial Panner Node + // * https://www.w3.org/TR/webaudio/#the-listenernode-interface + // * This panner is a spatial processing node that allows audio to be positioned + // * and oriented in 3D space. + // * + // * The Listener modifies the properties of the Audio Context Listener. + // * Both objects types use the same methods. The default is a spatial panner. + // * + // * p5.Panner3D - Constructs a Spatial Panner
+ // * p5.Listener3D - Constructs a Spatial Listener
+ // * + // * @class listener + // * @constructor + // * @return {Object} p5.Listener3D Object + // * + // * @param {Web Audio Node} listener Web Audio Spatial Panning Node + // * @param {AudioParam} listener.panningModel "equal power" or "HRTF" + // * @param {AudioParam} listener.distanceModel "linear", "inverse", or "exponential" + // * @param {String} [type] [Specify construction of a spatial panner or listener] + // */ + p5.Listener3D = function (type) { + this.ac = p5sound.audiocontext; + this.listener = this.ac.listener; + }; + // /** + // * Connect an audio sorce + // * @param {Object} src Input source + // */ + p5.Listener3D.prototype.process = function (src) { + src.connect(this.input); + }; + // /** + // * Set the X,Y,Z position of the Panner + // * @param {[Number]} xVal + // * @param {[Number]} yVal + // * @param {[Number]} zVal + // * @param {[Number]} time + // * @return {[Array]} [Updated x, y, z values as an array] + // */ + p5.Listener3D.prototype.position = function (xVal, yVal, zVal, time) { + this.positionX(xVal, time); + this.positionY(yVal, time); + this.positionZ(zVal, time); + return [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ]; + }; + // /** + // * Getter and setter methods for position coordinates + // * @return {Number} [updated coordinate value] + // */ + p5.Listener3D.prototype.positionX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.positionX.value = xVal; + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.positionX); + } + return this.listener.positionX.value; + }; + p5.Listener3D.prototype.positionY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.positionY.value = yVal; + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.positionY); + } + return this.listener.positionY.value; + }; + p5.Listener3D.prototype.positionZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.positionZ.value = zVal; + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.positionZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.positionZ); + } + return this.listener.positionZ.value; + }; + // cannot define method when class definition is commented + // /** + // * Overrides the listener orient() method because Listener has slightly + // * different params. In human terms, Forward vectors are the direction the + // * nose is pointing. Up vectors are the direction of the top of the head. + // * + // * @method orient + // * @param {Number} xValF Forward vector X direction + // * @param {Number} yValF Forward vector Y direction + // * @param {Number} zValF Forward vector Z direction + // * @param {Number} xValU Up vector X direction + // * @param {Number} yValU Up vector Y direction + // * @param {Number} zValU Up vector Z direction + // * @param {Number} time + // * @return {Array} All orienation params + // */ + p5.Listener3D.prototype.orient = function ( + xValF, + yValF, + zValF, + xValU, + yValU, + zValU, + time + ) { + if (arguments.length === 3 || arguments.length === 4) { + time = arguments[3]; + this.orientForward(xValF, yValF, zValF, time); + } else if (arguments.length === 6 || arguments === 7) { + this.orientForward(xValF, yValF, zValF); + this.orientUp(xValU, yValU, zValU, time); + } + return [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ]; + }; + p5.Listener3D.prototype.orientForward = function ( + xValF, + yValF, + zValF, + time + ) { + this.forwardX(xValF, time); + this.forwardY(yValF, time); + this.forwardZ(zValF, time); + return [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ]; + }; + p5.Listener3D.prototype.orientUp = function (xValU, yValU, zValU, time) { + this.upX(xValU, time); + this.upY(yValU, time); + this.upZ(zValU, time); + return [this.listener.upX, this.listener.upY, this.listener.upZ]; + }; + // /** + // * Getter and setter methods for orient coordinates + // * @return {Number} [updated coordinate value] + // */ + p5.Listener3D.prototype.forwardX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.forwardX.value = xVal; + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.forwardX); + } + return this.listener.forwardX.value; + }; + p5.Listener3D.prototype.forwardY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.forwardY.value = yVal; + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.forwardY); + } + return this.listener.forwardY.value; + }; + p5.Listener3D.prototype.forwardZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.forwardZ.value = zVal; + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.listener.forwardZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.forwardZ); + } + return this.listener.forwardZ.value; + }; + p5.Listener3D.prototype.upX = function (xVal, time) { + var t = time || 0; + if (typeof xVal === "number") { + this.listener.upX.value = xVal; + this.listener.upX.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upX.linearRampToValueAtTime( + xVal, + this.ac.currentTime + 0.02 + t + ); + } else if (xVal) { + xVal.connect(this.listener.upX); + } + return this.listener.upX.value; + }; + p5.Listener3D.prototype.upY = function (yVal, time) { + var t = time || 0; + if (typeof yVal === "number") { + this.listener.upY.value = yVal; + this.listener.upY.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upY.linearRampToValueAtTime( + yVal, + this.ac.currentTime + 0.02 + t + ); + } else if (yVal) { + yVal.connect(this.listener.upY); + } + return this.listener.upY.value; + }; + p5.Listener3D.prototype.upZ = function (zVal, time) { + var t = time || 0; + if (typeof zVal === "number") { + this.listener.upZ.value = zVal; + this.listener.upZ.cancelScheduledValues(this.ac.currentTime + 0.01 + t); + this.listener.upZ.linearRampToValueAtTime( + zVal, + this.ac.currentTime + 0.02 + t + ); + } else if (zVal) { + zVal.connect(this.listener.upZ); + } + return this.listener.upZ.value; + }; + return p5.Listener3D; + })(master, effect); + var delay; + ("use strict"); + delay = (function () { + var Filter = filter; + var Effect = effect; + /** + * Delay is an echo effect. It processes an existing sound source, + * and outputs a delayed version of that sound. The p5.Delay can + * produce different effects depending on the delayTime, feedback, + * filter, and type. In the example below, a feedback of 0.5 (the + * defaul value) will produce a looping delay that decreases in + * volume by 50% each repeat. A filter will cut out the high + * frequencies so that the delay does not sound as piercing as the + * original source. + * + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * @class p5.Delay + * @extends p5.Effect + * @constructor + * @example + *
+ * var noise, env, delay; + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * + * noise = new p5.Noise('brown'); + * noise.amp(0); + * noise.start(); + * + * delay = new p5.Delay(); + * + * // delay.process() accepts 4 parameters: + * // source, delayTime, feedback, filter frequency + * // play with these numbers!! + * delay.process(noise, .12, .7, 2300); + * + * // play the noise with an envelope, + * // a series of fades ( time / value pairs ) + * env = new p5.Envelope(.01, 0.2, .2, .1); + * } + * + * // mouseClick triggers envelope + * function mouseClicked() { + * // is mouse over canvas? + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * env.play(noise); + * } + * } + *
+ */ + p5.Delay = function () { + Effect.call(this); + this._split = this.ac.createChannelSplitter(2); + this._merge = this.ac.createChannelMerger(2); + this._leftGain = this.ac.createGain(); + this._rightGain = this.ac.createGain(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * + * @property {DelayNode} leftDelay + */ + this.leftDelay = this.ac.createDelay(); + /** + * The p5.Delay is built with two + * + * Web Audio Delay Nodes, one for each stereo channel. + * + * @property {DelayNode} rightDelay + */ + this.rightDelay = this.ac.createDelay(); + this._leftFilter = new Filter(); + this._rightFilter = new Filter(); + this._leftFilter.disconnect(); + this._rightFilter.disconnect(); + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ); + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ); + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime); + // graph routing + this.input.connect(this._split); + this.leftDelay.connect(this._leftGain); + this.rightDelay.connect(this._rightGain); + this._leftGain.connect(this._leftFilter.input); + this._rightGain.connect(this._rightFilter.input); + this._merge.connect(this.wet); + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + this._rightFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime); + // default routing + this.setType(0); + this._maxDelay = this.leftDelay.delayTime.maxValue; + // set initial feedback to 0.5 + this.feedback(0.5); + }; + p5.Delay.prototype = Object.create(Effect.prototype); + /** + * Add delay to an audio signal according to a set + * of delay parameters. + * + * @method process + * @param {Object} Signal An object that outputs audio + * @param {Number} [delayTime] Time (in seconds) of the delay/echo. + * Some browsers limit delayTime to + * 1 second. + * @param {Number} [feedback] sends the delay back through itself + * in a loop that decreases in volume + * each time. + * @param {Number} [lowPass] Cutoff frequency. Only frequencies + * below the lowPass will be part of the + * delay. + */ + p5.Delay.prototype.process = function ( + src, + _delayTime, + _feedback, + _filter + ) { + var feedback = _feedback || 0; + var delayTime = _delayTime || 0; + if (feedback >= 1) { + throw new Error("Feedback value will force a positive feedback loop."); + } + if (delayTime >= this._maxDelay) { + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + } + src.connect(this.input); + this.leftDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this.rightDelay.delayTime.setValueAtTime(delayTime, this.ac.currentTime); + this._leftGain.gain.value = feedback; + this._rightGain.gain.value = feedback; + if (_filter) { + this._leftFilter.freq(_filter); + this._rightFilter.freq(_filter); + } + }; + /** + * Set the delay (echo) time, in seconds. Usually this value will be + * a floating point number between 0.0 and 1.0. + * + * @method delayTime + * @param {Number} delayTime Time (in seconds) of the delay + */ + p5.Delay.prototype.delayTime = function (t) { + // if t is an audio node... + if (typeof t !== "number") { + t.connect(this.leftDelay.delayTime); + t.connect(this.rightDelay.delayTime); + } else { + this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime); + this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime); + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ); + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ); + } + }; + /** + * Feedback occurs when Delay sends its signal back through its input + * in a loop. The feedback amount determines how much signal to send each + * time through the loop. A feedback greater than 1.0 is not desirable because + * it will increase the overall output each time through the loop, + * creating an infinite feedback loop. The default value is 0.5 + * + * @method feedback + * @param {Number|Object} feedback 0.0 to 1.0, or an object such as an + * Oscillator that can be used to + * modulate this param + * @returns {Number} Feedback value + * + */ + p5.Delay.prototype.feedback = function (f) { + // if f is an audio node... + if (f && typeof f !== "number") { + f.connect(this._leftGain.gain); + f.connect(this._rightGain.gain); + } else if (f >= 1) { + throw new Error("Feedback value will force a positive feedback loop."); + } else if (typeof f === "number") { + this._leftGain.gain.value = f; + this._rightGain.gain.value = f; + } + // return value of feedback + return this._leftGain.gain.value; + }; + /** + * Set a lowpass filter frequency for the delay. A lowpass filter + * will cut off any frequencies higher than the filter frequency. + * + * @method filter + * @param {Number|Object} cutoffFreq A lowpass filter will cut off any + * frequencies higher than the filter frequency. + * @param {Number|Object} res Resonance of the filter frequency + * cutoff, or an object (i.e. a p5.Oscillator) + * that can be used to modulate this parameter. + * High numbers (i.e. 15) will produce a resonance, + * low numbers (i.e. .2) will produce a slope. + */ + p5.Delay.prototype.filter = function (freq, q) { + this._leftFilter.set(freq, q); + this._rightFilter.set(freq, q); + }; + /** + * Choose a preset type of delay. 'pingPong' bounces the signal + * from the left to the right channel to produce a stereo effect. + * Any other parameter will revert to the default delay setting. + * + * @method setType + * @param {String|Number} type 'pingPong' (1) or 'default' (0) + */ + p5.Delay.prototype.setType = function (t) { + if (t === 1) { + t = "pingPong"; + } + this._split.disconnect(); + this._leftFilter.disconnect(); + this._rightFilter.disconnect(); + this._split.connect(this.leftDelay, 0); + this._split.connect(this.rightDelay, 1); + switch (t) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type); + this._leftFilter.output.connect(this._merge, 0, 0); + this._rightFilter.output.connect(this._merge, 0, 1); + this._leftFilter.output.connect(this.rightDelay); + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0); + this._rightFilter.output.connect(this._merge, 0, 1); + this._leftFilter.output.connect(this.leftDelay); + this._rightFilter.output.connect(this.rightDelay); + } + }; + // DocBlocks for methods inherited from p5.Effect + /** + * Set the output level of the delay effect. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Delay.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + this._split.disconnect(); + this._leftFilter.dispose(); + this._rightFilter.dispose(); + this._merge.disconnect(); + this._leftGain.disconnect(); + this._rightGain.disconnect(); + this.leftDelay.disconnect(); + this.rightDelay.disconnect(); + this._split = undefined; + this._leftFilter = undefined; + this._rightFilter = undefined; + this._merge = undefined; + this._leftGain = undefined; + this._rightGain = undefined; + this.leftDelay = undefined; + this.rightDelay = undefined; + }; + })(filter, effect); + var reverb; + ("use strict"); + reverb = (function () { + var CustomError = errorHandler; + var Effect = effect; + /** + * Reverb adds depth to a sound through a large number of decaying + * echoes. It creates the perception that sound is occurring in a + * physical space. The p5.Reverb has paramters for Time (how long does the + * reverb last) and decayRate (how much the sound decays with each echo) + * that can be set with the .set() or .process() methods. The p5.Convolver + * extends p5.Reverb allowing you to recreate the sound of actual physical + * spaces through convolution. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Reverb + * @extends p5.Effect + * @constructor + * @example + *
+ * var soundFile, reverb; + * function preload() { + * soundFile = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * reverb = new p5.Reverb(); + * soundFile.disconnect(); // so we'll only hear reverb... + * + * // connect soundFile to reverb, process w/ + * // 3 second reverbTime, decayRate of 2% + * reverb.process(soundFile, 3, 2); + * soundFile.play(); + * } + *
+ */ + p5.Reverb = function () { + Effect.call(this); + this._initConvolverNode(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + // default params + this._seconds = 3; + this._decay = 2; + this._reverse = false; + this._buildImpulse(); + }; + p5.Reverb.prototype = Object.create(Effect.prototype); + p5.Reverb.prototype._initConvolverNode = function () { + this.convolverNode = this.ac.createConvolver(); + this.input.connect(this.convolverNode); + this.convolverNode.connect(this.wet); + }; + p5.Reverb.prototype._teardownConvolverNode = function () { + if (this.convolverNode) { + this.convolverNode.disconnect(); + delete this.convolverNode; + } + }; + p5.Reverb.prototype._setBuffer = function (audioBuffer) { + this._teardownConvolverNode(); + this._initConvolverNode(); + this.convolverNode.buffer = audioBuffer; + }; + /** + * Connect a source to the reverb, and assign reverb parameters. + * + * @method process + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + p5.Reverb.prototype.process = function (src, seconds, decayRate, reverse) { + src.connect(this.input); + var rebuild = false; + if (seconds) { + this._seconds = seconds; + rebuild = true; + } + if (decayRate) { + this._decay = decayRate; + } + if (reverse) { + this._reverse = reverse; + } + if (rebuild) { + this._buildImpulse(); + } + }; + /** + * Set the reverb settings. Similar to .process(), but without + * assigning a new input. + * + * @method set + * @param {Number} [seconds] Duration of the reverb, in seconds. + * Min: 0, Max: 10. Defaults to 3. + * @param {Number} [decayRate] Percentage of decay with each echo. + * Min: 0, Max: 100. Defaults to 2. + * @param {Boolean} [reverse] Play the reverb backwards or forwards. + */ + p5.Reverb.prototype.set = function (seconds, decayRate, reverse) { + var rebuild = false; + if (seconds) { + this._seconds = seconds; + rebuild = true; + } + if (decayRate) { + this._decay = decayRate; + } + if (reverse) { + this._reverse = reverse; + } + if (rebuild) { + this._buildImpulse(); + } + }; + // DocBlocks for methods inherited from p5.Effect + /** + * Set the output level of the reverb effect. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + /** + * Disconnect all output. + * + * @method disconnect + */ + /** + * Inspired by Simple Reverb by Jordan Santell + * https://github.com/web-audio-components/simple-reverb/blob/master/index.js + * + * Utility function for building an impulse response + * based on the module parameters. + * + * @private + */ + p5.Reverb.prototype._buildImpulse = function () { + var rate = this.ac.sampleRate; + var length = rate * this._seconds; + var decay = this._decay; + var impulse = this.ac.createBuffer(2, length, rate); + var impulseL = impulse.getChannelData(0); + var impulseR = impulse.getChannelData(1); + var n, i; + for (i = 0; i < length; i++) { + n = this._reverse ? length - i : i; + impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay); + } + this._setBuffer(impulse); + }; + p5.Reverb.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + this._teardownConvolverNode(); + }; + // ======================================================================= + // *** p5.Convolver *** + // ======================================================================= + /** + *

p5.Convolver extends p5.Reverb. It can emulate the sound of real + * physical spaces through a process called + * convolution.

+ * + *

Convolution multiplies any audio input by an "impulse response" + * to simulate the dispersion of sound over time. The impulse response is + * generated from an audio file that you provide. One way to + * generate an impulse response is to pop a balloon in a reverberant space + * and record the echo. Convolution can also be used to experiment with + * sound.

+ * + *

Use the method createConvolution(path) to instantiate a + * p5.Convolver with a path to your impulse response audio file.

+ * + * @class p5.Convolver + * @extends p5.Effect + * @constructor + * @param {String} path path to a sound file + * @param {Function} [callback] function to call when loading succeeds + * @param {Function} [errorCallback] function to call if loading fails. + * This function will receive an error or + * XMLHttpRequest object with information + * about what went wrong. + * @example + *
+ * var cVerb, sound; + * function preload() { + * // We have both MP3 and OGG versions of all sound assets + * soundFormats('ogg', 'mp3'); + * + * // Try replacing 'bx-spring' with other soundfiles like + * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' + * cVerb = createConvolver('assets/bx-spring.mp3'); + * + * // Try replacing 'Damscray_DancingTiger' with + * // 'beat', 'doorbell', lucky_dragons_-_power_melody' + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.Convolver = function (path, callback, errorCallback) { + p5.Reverb.call(this); + /** + * Internally, the p5.Convolver uses the a + * + * Web Audio Convolver Node. + * + * @property {ConvolverNode} convolverNode + */ + this._initConvolverNode(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + if (path) { + this.impulses = []; + this._loadBuffer(path, callback, errorCallback); + } else { + // parameters + this._seconds = 3; + this._decay = 2; + this._reverse = false; + this._buildImpulse(); + } + }; + p5.Convolver.prototype = Object.create(p5.Reverb.prototype); + p5.prototype.registerPreloadMethod("createConvolver", p5.prototype); + /** + * Create a p5.Convolver. Accepts a path to a soundfile + * that will be used to generate an impulse response. + * + * @method createConvolver + * @param {String} path path to a sound file + * @param {Function} [callback] function to call if loading is successful. + * The object will be passed in as the argument + * to the callback function. + * @param {Function} [errorCallback] function to call if loading is not successful. + * A custom error will be passed in as the argument + * to the callback function. + * @return {p5.Convolver} + * @example + *
+ * var cVerb, sound; + * function preload() { + * // We have both MP3 and OGG versions of all sound assets + * soundFormats('ogg', 'mp3'); + * + * // Try replacing 'bx-spring' with other soundfiles like + * // 'concrete-tunnel' 'small-plate' 'drum' 'beatbox' + * cVerb = createConvolver('assets/bx-spring.mp3'); + * + * // Try replacing 'Damscray_DancingTiger' with + * // 'beat', 'doorbell', lucky_dragons_-_power_melody' + * sound = loadSound('assets/Damscray_DancingTiger.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.prototype.createConvolver = function (path, callback, errorCallback) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + var self = this; + var cReverb = new p5.Convolver( + path, + function (buffer) { + if (typeof callback === "function") { + callback(buffer); + } + if (typeof self._decrementPreload === "function") { + self._decrementPreload(); + } + }, + errorCallback + ); + cReverb.impulses = []; + return cReverb; + }; + /** + * Private method to load a buffer as an Impulse Response, + * assign it to the convolverNode, and add to the Array of .impulses. + * + * @param {String} path + * @param {Function} callback + * @param {Function} errorCallback + * @private + */ + p5.Convolver.prototype._loadBuffer = function ( + path, + callback, + errorCallback + ) { + var path = p5.prototype._checkFileFormats(path); + var self = this; + var errorTrace = new Error().stack; + var ac = p5.prototype.getAudioContext(); + var request = new XMLHttpRequest(); + request.open("GET", path, true); + request.responseType = "arraybuffer"; + request.onload = function () { + if (request.status === 200) { + // on success loading file: + ac.decodeAudioData( + request.response, + function (buff) { + var buffer = {}; + var chunks = path.split("/"); + buffer.name = chunks[chunks.length - 1]; + buffer.audioBuffer = buff; + self.impulses.push(buffer); + self._setBuffer(buffer.audioBuffer); + if (callback) { + callback(buffer); + } + }, // error decoding buffer. "e" is undefined in Chrome 11/22/2015 + function () { + var err = new CustomError( + "decodeAudioData", + errorTrace, + self.url + ); + var msg = "AudioContext error at decodeAudioData for " + self.url; + if (errorCallback) { + err.msg = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + ); + } else { + var err = new CustomError("loadConvolver", errorTrace, self.url); + var msg = + "Unable to load " + + self.url + + ". The request status was: " + + request.status + + " (" + + request.statusText + + ")"; + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + } + }; + // if there is another error, aside from 404... + request.onerror = function () { + var err = new CustomError("loadConvolver", errorTrace, self.url); + var msg = + "There was no response from the server at " + + self.url + + ". Check the url and internet connectivity."; + if (errorCallback) { + err.message = msg; + errorCallback(err); + } else { + console.error( + msg + "\n The error stack trace includes: \n" + err.stack + ); + } + }; + request.send(); + }; + p5.Convolver.prototype.set = null; + /** + * Connect a source to the reverb, and assign reverb parameters. + * + * @method process + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + * @example + *
+ * var cVerb, sound; + * function preload() { + * soundFormats('ogg', 'mp3'); + * + * cVerb = createConvolver('assets/concrete-tunnel.mp3'); + * + * sound = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * // disconnect from master output... + * sound.disconnect(); + * + * // ...and process with (i.e. connect to) cVerb + * // so that we only hear the convolution + * cVerb.process(sound); + * + * sound.play(); + * } + *
+ */ + p5.Convolver.prototype.process = function (src) { + src.connect(this.input); + }; + /** + * If you load multiple impulse files using the .addImpulse method, + * they will be stored as Objects in this Array. Toggle between them + * with the toggleImpulse(id) method. + * + * @property {Array} impulses + */ + p5.Convolver.prototype.impulses = []; + /** + * Load and assign a new Impulse Response to the p5.Convolver. + * The impulse is added to the .impulses array. Previous + * impulses can be accessed with the .toggleImpulse(id) + * method. + * + * @method addImpulse + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + p5.Convolver.prototype.addImpulse = function ( + path, + callback, + errorCallback + ) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + this._loadBuffer(path, callback, errorCallback); + }; + /** + * Similar to .addImpulse, except that the .impulses + * Array is reset to save memory. A new .impulses + * array is created with this impulse as the only item. + * + * @method resetImpulse + * @param {String} path path to a sound file + * @param {Function} callback function (optional) + * @param {Function} errorCallback function (optional) + */ + p5.Convolver.prototype.resetImpulse = function ( + path, + callback, + errorCallback + ) { + // if loading locally without a server + if ( + window.location.origin.indexOf("file://") > -1 && + window.cordova === "undefined" + ) { + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + } + this.impulses = []; + this._loadBuffer(path, callback, errorCallback); + }; + /** + * If you have used .addImpulse() to add multiple impulses + * to a p5.Convolver, then you can use this method to toggle between + * the items in the .impulses Array. Accepts a parameter + * to identify which impulse you wish to use, identified either by its + * original filename (String) or by its position in the .impulses + * Array (Number).
+ * You can access the objects in the .impulses Array directly. Each + * Object has two attributes: an .audioBuffer (type: + * Web Audio + * AudioBuffer) and a .name, a String that corresponds + * with the original filename. + * + * @method toggleImpulse + * @param {String|Number} id Identify the impulse by its original filename + * (String), or by its position in the + * .impulses Array (Number). + */ + p5.Convolver.prototype.toggleImpulse = function (id) { + if (typeof id === "number" && id < this.impulses.length) { + this._setBuffer(this.impulses[id].audioBuffer); + } + if (typeof id === "string") { + for (var i = 0; i < this.impulses.length; i++) { + if (this.impulses[i].name === id) { + this._setBuffer(this.impulses[i].audioBuffer); + break; + } + } + } + }; + p5.Convolver.prototype.dispose = function () { + p5.Reverb.prototype.dispose.apply(this); + // remove all the Impulse Response buffers + for (var i in this.impulses) { + if (this.impulses[i]) { + this.impulses[i] = null; + } + } + }; + })(errorHandler, effect); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_TimelineState; + Tone_core_TimelineState = (function (Tone) { + "use strict"; + Tone.TimelineState = function (initial) { + Tone.Timeline.call(this); + this._initial = initial; + }; + Tone.extend(Tone.TimelineState, Tone.Timeline); + Tone.TimelineState.prototype.getValueAtTime = function (time) { + var event = this.get(time); + if (event !== null) { + return event.state; + } else { + return this._initial; + } + }; + Tone.TimelineState.prototype.setStateAtTime = function (state, time) { + this.add({ + state: state, + time: time, + }); + }; + return Tone.TimelineState; + })(Tone_core_Tone, Tone_core_Timeline); + /** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/ + var Tone_core_Clock; + Tone_core_Clock = (function (Tone) { + "use strict"; + Tone.Clock = function () { + Tone.Emitter.call(this); + var options = this.optionsObject( + arguments, + ["callback", "frequency"], + Tone.Clock.defaults + ); + this.callback = options.callback; + this._nextTick = 0; + this._lastState = Tone.State.Stopped; + this.frequency = new Tone.TimelineSignal( + options.frequency, + Tone.Type.Frequency + ); + this._readOnly("frequency"); + this.ticks = 0; + this._state = new Tone.TimelineState(Tone.State.Stopped); + this._boundLoop = this._loop.bind(this); + this.context.on("tick", this._boundLoop); + }; + Tone.extend(Tone.Clock, Tone.Emitter); + Tone.Clock.defaults = { + callback: Tone.noOp, + frequency: 1, + lookAhead: "auto", + }; + Object.defineProperty(Tone.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }); + Tone.Clock.prototype.start = function (time, offset) { + time = this.toSeconds(time); + if (this._state.getValueAtTime(time) !== Tone.State.Started) { + this._state.add({ + state: Tone.State.Started, + time: time, + offset: offset, + }); + } + return this; + }; + Tone.Clock.prototype.stop = function (time) { + time = this.toSeconds(time); + this._state.cancel(time); + this._state.setStateAtTime(Tone.State.Stopped, time); + return this; + }; + Tone.Clock.prototype.pause = function (time) { + time = this.toSeconds(time); + if (this._state.getValueAtTime(time) === Tone.State.Started) { + this._state.setStateAtTime(Tone.State.Paused, time); + } + return this; + }; + Tone.Clock.prototype._loop = function () { + var now = this.now(); + var lookAhead = this.context.lookAhead; + var updateInterval = this.context.updateInterval; + var lagCompensation = this.context.lag * 2; + var loopInterval = now + lookAhead + updateInterval + lagCompensation; + while (loopInterval > this._nextTick && this._state) { + var currentState = this._state.getValueAtTime(this._nextTick); + if (currentState !== this._lastState) { + this._lastState = currentState; + var event = this._state.get(this._nextTick); + if (currentState === Tone.State.Started) { + this._nextTick = event.time; + if (!this.isUndef(event.offset)) { + this.ticks = event.offset; + } + this.emit("start", event.time, this.ticks); + } else if (currentState === Tone.State.Stopped) { + this.ticks = 0; + this.emit("stop", event.time); + } else if (currentState === Tone.State.Paused) { + this.emit("pause", event.time); + } + } + var tickTime = this._nextTick; + if (this.frequency) { + this._nextTick += 1 / this.frequency.getValueAtTime(this._nextTick); + if (currentState === Tone.State.Started) { + this.callback(tickTime); + this.ticks++; + } + } + } + }; + Tone.Clock.prototype.getStateAtTime = function (time) { + time = this.toSeconds(time); + return this._state.getValueAtTime(time); + }; + Tone.Clock.prototype.dispose = function () { + Tone.Emitter.prototype.dispose.call(this); + this.context.off("tick", this._boundLoop); + this._writable("frequency"); + this.frequency.dispose(); + this.frequency = null; + this._boundLoop = null; + this._nextTick = Infinity; + this.callback = null; + this._state.dispose(); + this._state = null; + }; + return Tone.Clock; + })( + Tone_core_Tone, + Tone_signal_TimelineSignal, + Tone_core_TimelineState, + Tone_core_Emitter + ); + var metro; + ("use strict"); + metro = (function () { + var p5sound = master; + // requires the Tone.js library's Clock (MIT license, Yotam Mann) + // https://github.com/TONEnoTONE/Tone.js/ + var Clock = Tone_core_Clock; + p5.Metro = function () { + this.clock = new Clock({ callback: this.ontick.bind(this) }); + this.syncedParts = []; + this.bpm = 120; + // gets overridden by p5.Part + this._init(); + this.prevTick = 0; + this.tatumTime = 0; + this.tickCallback = function () {}; + }; + p5.Metro.prototype.ontick = function (tickTime) { + var elapsedTime = tickTime - this.prevTick; + var secondsFromNow = tickTime - p5sound.audiocontext.currentTime; + if (elapsedTime - this.tatumTime <= -0.02) { + return; + } else { + // console.log('ok', this.syncedParts[0].phrases[0].name); + this.prevTick = tickTime; + // for all of the active things on the metro: + var self = this; + this.syncedParts.forEach(function (thisPart) { + if (!thisPart.isPlaying) return; + thisPart.incrementStep(secondsFromNow); + // each synced source keeps track of its own beat number + thisPart.phrases.forEach(function (thisPhrase) { + var phraseArray = thisPhrase.sequence; + var bNum = self.metroTicks % phraseArray.length; + if ( + phraseArray[bNum] !== 0 && + (self.metroTicks < phraseArray.length || !thisPhrase.looping) + ) { + thisPhrase.callback(secondsFromNow, phraseArray[bNum]); + } + }); + }); + this.metroTicks += 1; + this.tickCallback(secondsFromNow); + } + }; + p5.Metro.prototype.setBPM = function (bpm, rampTime) { + var beatTime = 60 / (bpm * this.tatums); + var now = p5sound.audiocontext.currentTime; + this.tatumTime = beatTime; + var rampTime = rampTime || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, now); + this.clock.frequency.linearRampToValueAtTime(bpm, now + rampTime); + this.bpm = bpm; + }; + p5.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }; + p5.Metro.prototype._init = function () { + this.metroTicks = 0; + }; + // clear existing synced parts, add only this one + p5.Metro.prototype.resetSync = function (part) { + this.syncedParts = [part]; + }; + // push a new synced part to the array + p5.Metro.prototype.pushSync = function (part) { + this.syncedParts.push(part); + }; + p5.Metro.prototype.start = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.clock.start(now + t); + this.setBPM(this.bpm); + }; + p5.Metro.prototype.stop = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + this.clock.stop(now + t); + }; + p5.Metro.prototype.beatLength = function (tatums) { + this.tatums = 1 / tatums / 4; + }; + })(master, Tone_core_Clock); + var looper; + ("use strict"); + looper = (function () { + var p5sound = master; + var BPM = 120; + /** + * Set the global tempo, in beats per minute, for all + * p5.Parts. This method will impact all active p5.Parts. + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} rampTime Seconds from now + */ + p5.prototype.setBPM = function (bpm, rampTime) { + BPM = bpm; + for (var i in p5sound.parts) { + if (p5sound.parts[i]) { + p5sound.parts[i].setBPM(bpm, rampTime); + } + } + }; + /** + *

A phrase is a pattern of musical events over time, i.e. + * a series of notes and rests.

+ * + *

Phrases must be added to a p5.Part for playback, and + * each part can play multiple phrases at the same time. + * For example, one Phrase might be a kick drum, another + * could be a snare, and another could be the bassline.

+ * + *

The first parameter is a name so that the phrase can be + * modified or deleted later. The callback is a a function that + * this phrase will call at every step—for example it might be + * called playNote(value){}. The array determines + * which value is passed into the callback at each step of the + * phrase. It can be numbers, an object with multiple numbers, + * or a zero (0) indicates a rest so the callback won't be called).

+ * + * @class p5.Phrase + * @constructor + * @param {String} name Name so that you can access the Phrase. + * @param {Function} callback The name of a function that this phrase + * will call. Typically it will play a sound, + * and accept two parameters: a time at which + * to play the sound (in seconds from now), + * and a value from the sequence array. The + * time should be passed into the play() or + * start() method to ensure precision. + * @param {Array} sequence Array of values to pass into the callback + * at each step of the phrase. + * @example + *
+ * var mySound, myPhrase, myPart; + * var pattern = [1,0,0,2,0,2,0,0]; + * var msg = 'click to play'; + * + * function preload() { + * mySound = loadSound('assets/beatbox.mp3'); + * } + * + * function setup() { + * noStroke(); + * fill(255); + * textAlign(CENTER); + * masterVolume(0.1); + * + * myPhrase = new p5.Phrase('bbox', makeSound, pattern); + * myPart = new p5.Part(); + * myPart.addPhrase(myPhrase); + * myPart.setBPM(60); + * } + * + * function draw() { + * background(0); + * text(msg, width/2, height/2); + * } + * + * function makeSound(time, playbackRate) { + * mySound.rate(playbackRate); + * mySound.play(time); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * myPart.start(); + * msg = 'playing pattern'; + * } + * } + * + *
+ */ + p5.Phrase = function (name, callback, sequence) { + this.phraseStep = 0; + this.name = name; + this.callback = callback; + /** + * Array of values to pass into the callback + * at each step of the phrase. Depending on the callback + * function's requirements, these values may be numbers, + * strings, or an object with multiple parameters. + * Zero (0) indicates a rest. + * + * @property {Array} sequence + */ + this.sequence = sequence; + }; + /** + *

A p5.Part plays back one or more p5.Phrases. Instantiate a part + * with steps and tatums. By default, each step represents a 1/16th note.

+ * + *

See p5.Phrase for more about musical timing.

+ * + * @class p5.Part + * @constructor + * @param {Number} [steps] Steps in the part + * @param {Number} [tatums] Divisions of a beat, e.g. use 1/4, or 0.25 for a quater note (default is 1/16, a sixteenth note) + * @example + *
+ * var box, drum, myPart; + * var boxPat = [1,0,0,2,0,2,0,0]; + * var drumPat = [0,1,1,0,2,0,1,0]; + * var msg = 'click to play'; + * + * function preload() { + * box = loadSound('assets/beatbox.mp3'); + * drum = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * noStroke(); + * fill(255); + * textAlign(CENTER); + * masterVolume(0.1); + * + * var boxPhrase = new p5.Phrase('box', playBox, boxPat); + * var drumPhrase = new p5.Phrase('drum', playDrum, drumPat); + * myPart = new p5.Part(); + * myPart.addPhrase(boxPhrase); + * myPart.addPhrase(drumPhrase); + * myPart.setBPM(60); + * masterVolume(0.1); + * } + * + * function draw() { + * background(0); + * text(msg, width/2, height/2); + * } + * + * function playBox(time, playbackRate) { + * box.rate(playbackRate); + * box.play(time); + * } + * + * function playDrum(time, playbackRate) { + * drum.rate(playbackRate); + * drum.play(time); + * } + * + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * myPart.start(); + * msg = 'playing part'; + * } + * } + *
+ */ + p5.Part = function (steps, bLength) { + this.length = steps || 0; + // how many beats + this.partStep = 0; + this.phrases = []; + this.isPlaying = false; + this.noLoop(); + this.tatums = bLength || 0.0625; + // defaults to quarter note + this.metro = new p5.Metro(); + this.metro._init(); + this.metro.beatLength(this.tatums); + this.metro.setBPM(BPM); + p5sound.parts.push(this); + this.callback = function () {}; + }; + /** + * Set the tempo of this part, in Beats Per Minute. + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} [rampTime] Seconds from now + */ + p5.Part.prototype.setBPM = function (tempo, rampTime) { + this.metro.setBPM(tempo, rampTime); + }; + /** + * Returns the tempo, in Beats Per Minute, of this part. + * + * @method getBPM + * @return {Number} + */ + p5.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }; + /** + * Start playback of this part. It will play + * through all of its phrases at a speed + * determined by setBPM. + * + * @method start + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.start = function (time) { + if (!this.isPlaying) { + this.isPlaying = true; + this.metro.resetSync(this); + var t = time || 0; + this.metro.start(t); + } + }; + /** + * Loop playback of this part. It will begin + * looping through all of its phrases at a speed + * determined by setBPM. + * + * @method loop + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.loop = function (time) { + this.looping = true; + // rest onended function + this.onended = function () { + this.partStep = 0; + }; + var t = time || 0; + this.start(t); + }; + /** + * Tell the part to stop looping. + * + * @method noLoop + */ + p5.Part.prototype.noLoop = function () { + this.looping = false; + // rest onended function + this.onended = function () { + this.stop(); + }; + }; + /** + * Stop the part and cue it to step 0. Playback will resume from the begining of the Part when it is played again. + * + * @method stop + * @param {Number} [time] seconds from now + */ + p5.Part.prototype.stop = function (time) { + this.partStep = 0; + this.pause(time); + }; + /** + * Pause the part. Playback will resume + * from the current step. + * + * @method pause + * @param {Number} time seconds from now + */ + p5.Part.prototype.pause = function (time) { + this.isPlaying = false; + var t = time || 0; + this.metro.stop(t); + }; + /** + * Add a p5.Phrase to this Part. + * + * @method addPhrase + * @param {p5.Phrase} phrase reference to a p5.Phrase + */ + p5.Part.prototype.addPhrase = function (name, callback, array) { + var p; + if (arguments.length === 3) { + p = new p5.Phrase(name, callback, array); + } else if (arguments[0] instanceof p5.Phrase) { + p = arguments[0]; + } else { + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + } + this.phrases.push(p); + // reset the length if phrase is longer than part's existing length + if (p.sequence.length > this.length) { + this.length = p.sequence.length; + } + }; + /** + * Remove a phrase from this part, based on the name it was + * given when it was created. + * + * @method removePhrase + * @param {String} phraseName + */ + p5.Part.prototype.removePhrase = function (name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases.splice(i, 1); + } + } + }; + /** + * Get a phrase from this part, based on the name it was + * given when it was created. Now you can modify its array. + * + * @method getPhrase + * @param {String} phraseName + */ + p5.Part.prototype.getPhrase = function (name) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + return this.phrases[i]; + } + } + }; + /** + * Find all sequences with the specified name, and replace their patterns with the specified array. + * + * @method replaceSequence + * @param {String} phraseName + * @param {Array} sequence Array of values to pass into the callback + * at each step of the phrase. + */ + p5.Part.prototype.replaceSequence = function (name, array) { + for (var i in this.phrases) { + if (this.phrases[i].name === name) { + this.phrases[i].sequence = array; + } + } + }; + p5.Part.prototype.incrementStep = function (time) { + if (this.partStep < this.length - 1) { + this.callback(time); + this.partStep += 1; + } else { + if (!this.looping && this.partStep === this.length - 1) { + console.log("done"); + // this.callback(time); + this.onended(); + } + } + }; + /** + * Set the function that will be called at every step. This will clear the previous function. + * + * @method onStep + * @param {Function} callback The name of the callback + * you want to fire + * on every beat/tatum. + */ + p5.Part.prototype.onStep = function (callback) { + this.callback = callback; + }; + // =============== + // p5.Score + // =============== + /** + * A Score consists of a series of Parts. The parts will + * be played back in order. For example, you could have an + * A part, a B part, and a C part, and play them back in this order + * new p5.Score(a, a, b, a, c) + * + * @class p5.Score + * @constructor + * @param {p5.Part} [...parts] One or multiple parts, to be played in sequence. + */ + p5.Score = function () { + // for all of the arguments + this.parts = []; + this.currentPart = 0; + var thisScore = this; + for (var i in arguments) { + if (arguments[i] && this.parts[i]) { + this.parts[i] = arguments[i]; + this.parts[i].nextPart = this.parts[i + 1]; + this.parts[i].onended = function () { + thisScore.resetPart(i); + playNextPart(thisScore); + }; + } + } + this.looping = false; + }; + p5.Score.prototype.onended = function () { + if (this.looping) { + // this.resetParts(); + this.parts[0].start(); + } else { + this.parts[this.parts.length - 1].onended = function () { + this.stop(); + this.resetParts(); + }; + } + this.currentPart = 0; + }; + /** + * Start playback of the score. + * + * @method start + */ + p5.Score.prototype.start = function () { + this.parts[this.currentPart].start(); + this.scoreStep = 0; + }; + /** + * Stop playback of the score. + * + * @method stop + */ + p5.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(); + this.currentPart = 0; + this.scoreStep = 0; + }; + /** + * Pause playback of the score. + * + * @method pause + */ + p5.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }; + /** + * Loop playback of the score. + * + * @method loop + */ + p5.Score.prototype.loop = function () { + this.looping = true; + this.start(); + }; + /** + * Stop looping playback of the score. If it + * is currently playing, this will go into effect + * after the current round of playback completes. + * + * @method noLoop + */ + p5.Score.prototype.noLoop = function () { + this.looping = false; + }; + p5.Score.prototype.resetParts = function () { + var self = this; + this.parts.forEach(function (part) { + self.resetParts[part]; + }); + }; + p5.Score.prototype.resetPart = function (i) { + this.parts[i].stop(); + this.parts[i].partStep = 0; + for (var p in this.parts[i].phrases) { + if (this.parts[i]) { + this.parts[i].phrases[p].phraseStep = 0; + } + } + }; + /** + * Set the tempo for all parts in the score + * + * @method setBPM + * @param {Number} BPM Beats Per Minute + * @param {Number} rampTime Seconds from now + */ + p5.Score.prototype.setBPM = function (bpm, rampTime) { + for (var i in this.parts) { + if (this.parts[i]) { + this.parts[i].setBPM(bpm, rampTime); + } + } + }; + function playNextPart(aScore) { + aScore.currentPart++; + if (aScore.currentPart >= aScore.parts.length) { + aScore.scoreStep = 0; + aScore.onended(); + } else { + aScore.scoreStep = 0; + aScore.parts[aScore.currentPart - 1].stop(); + aScore.parts[aScore.currentPart].start(); + } } - if (this.input) { + })(master); + var soundloop; + ("use strict"); + soundloop = (function () { + var p5sound = master; + var Clock = Tone_core_Clock; + /** + * SoundLoop + * + * @class p5.SoundLoop + * @constructor + * + * @param {Function} callback this function will be called on each iteration of theloop + * @param {Number|String} [interval] amount of time or beats for each iteration of the loop + * defaults to 1 + * + * @example + *
+ * var click; + * var looper1; + * + * function preload() { + * click = loadSound('assets/drum.mp3'); + * } + * + * function setup() { + * //the looper's callback is passed the timeFromNow + * //this value should be used as a reference point from + * //which to schedule sounds + * looper1 = new p5.SoundLoop(function(timeFromNow){ + * click.play(timeFromNow); + * background(255 * (looper1.iterations % 2)); + * }, 2); + * + * //stop after 10 iteratios; + * looper1.maxIterations = 10; + * //start the loop + * looper1.start(); + * } + *
+ */ + p5.SoundLoop = function (callback, interval) { + this.callback = callback; + /** + * musicalTimeMode uses Tone.Time convention + * true if string, false if number + * @property {Boolean} musicalTimeMode + */ + this.musicalTimeMode = typeof this._interval === "number" ? false : true; + this._interval = interval || 1; + /** + * musicalTimeMode variables + * modify these only when the interval is specified in musicalTime format as a string + */ + this._timeSignature = 4; + this._bpm = 60; + this.isPlaying = false; + /** + * Set a limit to the number of loops to play. defaults to Infinity + * @property {Number} maxIterations + */ + this.maxIterations = Infinity; + var self = this; + this.clock = new Clock({ + callback: function (time) { + var timeFromNow = time - p5sound.audiocontext.currentTime; + /** + * Do not initiate the callback if timeFromNow is < 0 + * This ususually occurs for a few milliseconds when the page + * is not fully loaded + * + * The callback should only be called until maxIterations is reached + */ + if (timeFromNow > 0 && self.iterations <= self.maxIterations) { + self.callback(timeFromNow); + } + }, + frequency: this._calcFreq(), + }); + }; + /** + * Start the loop + * @method start + * @param {Number} [timeFromNow] schedule a starting time + */ + p5.SoundLoop.prototype.start = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (!this.isPlaying) { + this.clock.start(now + t); + this.isPlaying = true; + } + }; + /** + * Stop the loop + * @method stop + * @param {Number} [timeFromNow] schedule a stopping time + */ + p5.SoundLoop.prototype.stop = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.stop(now + t); + this.isPlaying = false; + } + }; + /** + * Pause the loop + * @method pause + * @param {Number} [timeFromNow] schedule a pausing time + */ + p5.SoundLoop.prototype.pause = function (timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.pause(now + t); + this.isPlaying = false; + } + }; + /** + * Synchronize loops. Use this method to start two more more loops in synchronization + * or to start a loop in synchronization with a loop that is already playing + * This method will schedule the implicit loop in sync with the explicit master loop + * i.e. loopToStart.syncedStart(loopToSyncWith) + * + * @method syncedStart + * @param {Object} otherLoop a p5.SoundLoop to sync with + * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds + */ + p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (!otherLoop.isPlaying) { + otherLoop.clock.start(now + t); + otherLoop.isPlaying = true; + this.clock.start(now + t); + this.isPlaying = true; + } else if (otherLoop.isPlaying) { + var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; + this.clock.start(now + time); + this.isPlaying = true; + } + }; + /** + * Updates frequency value, reflected in next callback + * @private + * @method _update + */ + p5.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }; + /** + * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature + * @private + * @method _calcFreq + * @return {Number} new clock frequency value + */ + p5.SoundLoop.prototype._calcFreq = function () { + //Seconds mode, bpm / timesignature has no effect + if (typeof this._interval === "number") { + this.musicalTimeMode = false; + return 1 / this._interval; + } else if (typeof this._interval === "string") { + this.musicalTimeMode = true; + return ( + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4) + ); + } + }; + /** + * Convert notation from musical time format to seconds + * Uses Tone.Time convention + * @private + * @method _convertNotation + * @param {String} value value to be converted + * @return {Number} converted value in seconds + */ + p5.SoundLoop.prototype._convertNotation = function (value) { + var type = value.slice(-1); + value = Number(value.slice(0, -1)); + switch (type) { + case "m": + return this._measure(value); + case "n": + return this._note(value); + default: + console.warn( + "Specified interval is not formatted correctly. See Tone.js " + + "timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time" + ); + } + }; + /** + * Helper conversion methods of measure and note + * @private + * @method _measure + * @private + * @method _note + */ + p5.SoundLoop.prototype._measure = function (value) { + return value * this._timeSignature; + }; + p5.SoundLoop.prototype._note = function (value) { + return this._timeSignature / value; + }; + /** + * Getters and Setters, setting any paramter will result in a change in the clock's + * frequency, that will be reflected after the next callback + * beats per minute (defaults to 60) + * @property {Number} bpm + */ + Object.defineProperty(p5.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (bpm) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the BPM in "seconds" mode has no effect. ' + + "BPM is only relevant in musicalTimeMode " + + "when the interval is specified as a string " + + '("2n", "4n", "1m"...etc)' + ); + } + this._bpm = bpm; + this._update(); + }, + }); + /** + * number of quarter notes in a measure (defaults to 4) + * @property {Number} timeSignature + */ + Object.defineProperty(p5.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (timeSig) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the timeSignature in "seconds" mode has no effect. ' + + "BPM is only relevant in musicalTimeMode " + + "when the interval is specified as a string " + + '("2n", "4n", "1m"...etc)' + ); + } + this._timeSignature = timeSig; + this._update(); + }, + }); + /** + * length of the loops interval + * @property {Number|String} interval + */ + Object.defineProperty(p5.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (interval) { + this.musicalTimeMode = typeof interval === "Number" ? false : true; + this._interval = interval; + this._update(); + }, + }); + /** + * how many times the callback has been called so far + * @property {Number} iterations + * @readonly + */ + Object.defineProperty(p5.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }); + return p5.SoundLoop; + })(master, Tone_core_Clock); + var compressor; + compressor = (function () { + "use strict"; + var p5sound = master; + var Effect = effect; + var CustomError = errorHandler; + /** + * Compressor is an audio effect class that performs dynamics compression + * on an audio input source. This is a very commonly used technique in music + * and sound production. Compression creates an overall louder, richer, + * and fuller sound by lowering the volume of louds and raising that of softs. + * Compression can be used to avoid clipping (sound distortion due to + * peaks in volume) and is especially useful when many sounds are played + * at once. Compression can be used on indivudal sound sources in addition + * to the master output. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Compressor + * @constructor + * @extends p5.Effect + * + * + */ + p5.Compressor = function () { + Effect.call(this); + /** + * The p5.Compressor is built with a Web Audio Dynamics Compressor Node + * + * @property {AudioNode} compressor + */ + this.compressor = this.ac.createDynamicsCompressor(); + this.input.connect(this.compressor); + this.compressor.connect(this.wet); + }; + p5.Compressor.prototype = Object.create(Effect.prototype); + /** + * Performs the same function as .connect, but also accepts + * optional parameters to set compressor's audioParams + * @method process + * + * @param {Object} src Sound source to be connected + * + * @param {Number} [attack] The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [threshold] The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [release] The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ + p5.Compressor.prototype.process = function ( + src, + attack, + knee, + ratio, + threshold, + release + ) { + src.connect(this.input); + this.set(attack, knee, ratio, threshold, release); + }; + /** + * Set the paramters of a compressor. + * @method set + * @param {Number} attack The amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} knee A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} ratio The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + */ + p5.Compressor.prototype.set = function ( + attack, + knee, + ratio, + threshold, + release + ) { + if (typeof attack !== "undefined") { + this.attack(attack); + } + if (typeof knee !== "undefined") { + this.knee(knee); + } + if (typeof ratio !== "undefined") { + this.ratio(ratio); + } + if (typeof threshold !== "undefined") { + this.threshold(threshold); + } + if (typeof release !== "undefined") { + this.release(release); + } + }; + /** + * Get current attack or set value w/ time ramp + * + * + * @method attack + * @param {Number} [attack] Attack is the amount of time (in seconds) to reduce the gain by 10dB, + * default = .003, range 0 - 1 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.attack = function (attack, time) { + var t = time || 0; + if (typeof attack == "number") { + this.compressor.attack.value = attack; + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.attack.linearRampToValueAtTime( + attack, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof attack !== "undefined") { + attack.connect(this.compressor.attack); + } + return this.compressor.attack.value; + }; + /** + * Get current knee or set value w/ time ramp + * + * @method knee + * @param {Number} [knee] A decibel value representing the range above the + * threshold where the curve smoothly transitions to the "ratio" portion. + * default = 30, range 0 - 40 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.knee = function (knee, time) { + var t = time || 0; + if (typeof knee == "number") { + this.compressor.knee.value = knee; + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.knee.linearRampToValueAtTime( + knee, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof knee !== "undefined") { + knee.connect(this.compressor.knee); + } + return this.compressor.knee.value; + }; + /** + * Get current ratio or set value w/ time ramp + * @method ratio + * + * @param {Number} [ratio] The amount of dB change in input for a 1 dB change in output + * default = 12, range 1 - 20 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.ratio = function (ratio, time) { + var t = time || 0; + if (typeof ratio == "number") { + this.compressor.ratio.value = ratio; + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.ratio.linearRampToValueAtTime( + ratio, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof ratio !== "undefined") { + ratio.connect(this.compressor.ratio); + } + return this.compressor.ratio.value; + }; + /** + * Get current threshold or set value w/ time ramp + * @method threshold + * + * @param {Number} threshold The decibel value above which the compression will start taking effect + * default = -24, range -100 - 0 + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.threshold = function (threshold, time) { + var t = time || 0; + if (typeof threshold == "number") { + this.compressor.threshold.value = threshold; + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.threshold.linearRampToValueAtTime( + threshold, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof threshold !== "undefined") { + threshold.connect(this.compressor.threshold); + } + return this.compressor.threshold.value; + }; + /** + * Get current release or set value w/ time ramp + * @method release + * + * @param {Number} release The amount of time (in seconds) to increase the gain by 10dB + * default = .25, range 0 - 1 + * + * @param {Number} [time] Assign time value to schedule the change in value + */ + p5.Compressor.prototype.release = function (release, time) { + var t = time || 0; + if (typeof release == "number") { + this.compressor.release.value = release; + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + t + ); + this.compressor.release.linearRampToValueAtTime( + release, + this.ac.currentTime + 0.02 + t + ); + } else if (typeof number !== "undefined") { + release.connect(this.compressor.release); + } + return this.compressor.release.value; + }; + /** + * Return the current reduction value + * + * @method reduction + * @return {Number} Value of the amount of gain reduction that is applied to the signal + */ + p5.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }; + p5.Compressor.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.compressor) { + this.compressor.disconnect(); + delete this.compressor; + } + }; + return p5.Compressor; + })(master, effect, errorHandler); + var soundRecorder; + ("use strict"); + soundRecorder = (function () { + // inspiration: recorder.js, Tone.js & typedarray.org + var p5sound = master; + var convertToWav = helpers.convertToWav; + var ac = p5sound.audiocontext; + /** + *

Record sounds for playback and/or to save as a .wav file. + * The p5.SoundRecorder records all sound output from your sketch, + * or can be assigned a specific source with setInput().

+ *

The record() method accepts a p5.SoundFile as a parameter. + * When playback is stopped (either after the given amount of time, + * or with the stop() method), the p5.SoundRecorder will send its + * recording to that p5.SoundFile for playback.

+ * + * @class p5.SoundRecorder + * @constructor + * @example + *
+ * var mic, recorder, soundFile; + * var state = 0; + * + * function setup() { + * background(200); + * // create an audio in + * mic = new p5.AudioIn(); + * + * // prompts user to enable their browser mic + * mic.start(); + * + * // create a sound recorder + * recorder = new p5.SoundRecorder(); + * + * // connect the mic to the recorder + * recorder.setInput(mic); + * + * // this sound file will be used to + * // playback & save the recording + * soundFile = new p5.SoundFile(); + * + * text('keyPress to record', 20, 20); + * } + * + * function keyPressed() { + * // make sure user enabled the mic + * if (state === 0 && mic.enabled) { + * + * // record to our p5.SoundFile + * recorder.record(soundFile); + * + * background(255,0,0); + * text('Recording!', 20, 20); + * state++; + * } + * else if (state === 1) { + * background(0,255,0); + * + * // stop recorder and + * // send result to soundFile + * recorder.stop(); + * + * text('Stopped', 20, 20); + * state++; + * } + * + * else if (state === 2) { + * soundFile.play(); // play the result! + * save(soundFile, 'mySound.wav'); + * state++; + * } + * } + *
+ */ + p5.SoundRecorder = function () { + this.input = ac.createGain(); + this.output = ac.createGain(); + this.recording = false; + this.bufferSize = 1024; + this._channels = 2; + // stereo (default) + this._clear(); + // initialize variables + this._jsNode = ac.createScriptProcessor( + this.bufferSize, + this._channels, + 2 + ); + this._jsNode.onaudioprocess = this._audioprocess.bind(this); + /** + * callback invoked when the recording is over + * @private + * @type Function(Float32Array) + */ + this._callback = function () {}; + // connections + this._jsNode.connect(p5.soundOut._silentNode); + this.setInput(); + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connect a specific device to the p5.SoundRecorder. + * If no parameter is given, p5.SoundRecorer will record + * all audible p5.sound from your sketch. + * + * @method setInput + * @param {Object} [unit] p5.sound object or a web audio unit + * that outputs sound + */ + p5.SoundRecorder.prototype.setInput = function (unit) { this.input.disconnect(); - delete this.input; - } - }; -}(master); -var audioVoice; -'use strict'; -audioVoice = function () { - var p5sound = master; - /** - * Base class for monophonic synthesizers. Any extensions of this class - * should follow the API and implement the methods below in order to - * remain compatible with p5.PolySynth(); - * - * @class p5.AudioVoice - * @constructor - */ - p5.AudioVoice = function () { - this.ac = p5sound.audiocontext; - this.output = this.ac.createGain(); - this.connect(); - p5sound.soundArray.push(this); - }; - p5.AudioVoice.prototype.play = function (note, velocity, secondsFromNow, sustime) { - }; - p5.AudioVoice.prototype.triggerAttack = function (note, velocity, secondsFromNow) { - }; - p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) { - }; - p5.AudioVoice.prototype.amp = function (vol, rampTime) { - }; - /** - * Connect to p5 objects or Web Audio Nodes - * @method connect - * @param {Object} unit - */ - p5.AudioVoice.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect from soundOut - * @method disconnect - */ - p5.AudioVoice.prototype.disconnect = function () { - this.output.disconnect(); - }; - p5.AudioVoice.prototype.dispose = function () { - if (this.output) { + this.input = null; + this.input = ac.createGain(); + this.input.connect(this._jsNode); + this.input.connect(this.output); + if (unit) { + unit.connect(this.input); + } else { + p5.soundOut.output.connect(this.input); + } + }; + /** + * Start recording. To access the recording, provide + * a p5.SoundFile as the first parameter. The p5.SoundRecorder + * will send its recording to that p5.SoundFile for playback once + * recording is complete. Optional parameters include duration + * (in seconds) of the recording, and a callback function that + * will be called once the complete recording has been + * transfered to the p5.SoundFile. + * + * @method record + * @param {p5.SoundFile} soundFile p5.SoundFile + * @param {Number} [duration] Time (in seconds) + * @param {Function} [callback] The name of a function that will be + * called once the recording completes + */ + p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { + this.recording = true; + if (duration) { + this.sampleLimit = Math.round(duration * ac.sampleRate); + } + if (sFile && callback) { + this._callback = function () { + this.buffer = this._getBuffer(); + sFile.setBuffer(this.buffer); + callback(); + }; + } else if (sFile) { + this._callback = function () { + this.buffer = this._getBuffer(); + sFile.setBuffer(this.buffer); + }; + } + }; + /** + * Stop the recording. Once the recording is stopped, + * the results will be sent to the p5.SoundFile that + * was given on .record(), and if a callback function + * was provided on record, that function will be called. + * + * @method stop + */ + p5.SoundRecorder.prototype.stop = function () { + this.recording = false; + this._callback(); + this._clear(); + }; + p5.SoundRecorder.prototype._clear = function () { + this._leftBuffers = []; + this._rightBuffers = []; + this.recordedSamples = 0; + this.sampleLimit = null; + }; + /** + * internal method called on audio process + * + * @private + * @param {AudioProcessorEvent} event + */ + p5.SoundRecorder.prototype._audioprocess = function (event) { + if (this.recording === false) { + return; + } else if (this.recording === true) { + // if we are past the duration, then stop... else: + if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) { + this.stop(); + } else { + // get channel data + var left = event.inputBuffer.getChannelData(0); + var right = event.inputBuffer.getChannelData(1); + // clone the samples + this._leftBuffers.push(new Float32Array(left)); + this._rightBuffers.push(new Float32Array(right)); + this.recordedSamples += this.bufferSize; + } + } + }; + p5.SoundRecorder.prototype._getBuffer = function () { + var buffers = []; + buffers.push(this._mergeBuffers(this._leftBuffers)); + buffers.push(this._mergeBuffers(this._rightBuffers)); + return buffers; + }; + p5.SoundRecorder.prototype._mergeBuffers = function (channelBuffer) { + var result = new Float32Array(this.recordedSamples); + var offset = 0; + var lng = channelBuffer.length; + for (var i = 0; i < lng; i++) { + var buffer = channelBuffer[i]; + result.set(buffer, offset); + offset += buffer.length; + } + return result; + }; + p5.SoundRecorder.prototype.dispose = function () { + this._clear(); + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + this._callback = function () {}; + if (this.input) { + this.input.disconnect(); + } + this.input = null; + this._jsNode = null; + }; + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. + * For uploading audio to a server, use + * `p5.SoundFile.saveBlob`. + * + * @for p5 + * @method saveSound + * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save + * @param {String} fileName name of the resulting .wav file. + */ + // add to p5.prototype as this is used by the p5 `save()` method. + p5.prototype.saveSound = function (soundFile, fileName) { + const dataView = convertToWav(soundFile.buffer); + p5.prototype.writeFile([dataView], fileName, "wav"); + }; + })(master, helpers); + var peakdetect; + ("use strict"); + peakdetect = (function () { + /** + *

PeakDetect works in conjunction with p5.FFT to + * look for onsets in some or all of the frequency spectrum. + *

+ *

+ * To use p5.PeakDetect, call update in the draw loop + * and pass in a p5.FFT object. + *

+ *

+ * You can listen for a specific part of the frequency spectrum by + * setting the range between freq1 and freq2. + *

+ * + *

threshold is the threshold for detecting a peak, + * scaled between 0 and 1. It is logarithmic, so 0.1 is half as loud + * as 1.0.

+ * + *

+ * The update method is meant to be run in the draw loop, and + * frames determines how many loops must pass before + * another peak can be detected. + * For example, if the frameRate() = 60, you could detect the beat of a + * 120 beat-per-minute song with this equation: + * framesPerPeak = 60 / (estimatedBPM / 60 ); + *

+ * + *

+ * Based on example contribtued by @b2renger, and a simple beat detection + * explanation by Felix Turner. + *

+ * + * @class p5.PeakDetect + * @constructor + * @param {Number} [freq1] lowFrequency - defaults to 20Hz + * @param {Number} [freq2] highFrequency - defaults to 20000 Hz + * @param {Number} [threshold] Threshold for detecting a beat between 0 and 1 + * scaled logarithmically where 0.1 is 1/2 the loudness + * of 1.0. Defaults to 0.35. + * @param {Number} [framesPerPeak] Defaults to 20. + * @example + *
+ * + * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 10; + * + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * background(0); + * noStroke(); + * fill(255); + * textAlign(CENTER); + * + * // p5.PeakDetect requires a p5.FFT + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * } + * + * function draw() { + * background(0); + * text('click to play/pause', width/2, height/2); + * + * // peakDetect accepts an fft post-analysis + * fft.analyze(); + * peakDetect.update(fft); + * + * if ( peakDetect.isDetected ) { + * ellipseWidth = 50; + * } else { + * ellipseWidth *= 0.95; + * } + * + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // toggle play/stop when canvas is clicked + * function mouseClicked() { + * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * } + * } + *
+ */ + p5.PeakDetect = function (freq1, freq2, threshold, _framesPerPeak) { + // framesPerPeak determines how often to look for a beat. + // If a beat is provided, try to look for a beat based on bpm + this.framesPerPeak = _framesPerPeak || 20; + this.framesSinceLastPeak = 0; + this.decayRate = 0.95; + this.threshold = threshold || 0.35; + this.cutoff = 0; + // how much to increase the cutoff + // TO DO: document this / figure out how to make it accessible + this.cutoffMult = 1.5; + this.energy = 0; + this.penergy = 0; + // TO DO: document this property / figure out how to make it accessible + this.currentValue = 0; + /** + * isDetected is set to true when a peak is detected. + * + * @attribute isDetected {Boolean} + * @default false + */ + this.isDetected = false; + this.f1 = freq1 || 40; + this.f2 = freq2 || 20000; + // function to call when a peak is detected + this._onPeak = function () {}; + }; + /** + * The update method is run in the draw loop. + * + * Accepts an FFT object. You must call .analyze() + * on the FFT object prior to updating the peakDetect + * because it relies on a completed FFT analysis. + * + * @method update + * @param {p5.FFT} fftObject A p5.FFT object + */ + p5.PeakDetect.prototype.update = function (fftObject) { + var nrg = (this.energy = fftObject.getEnergy(this.f1, this.f2) / 255); + if (nrg > this.cutoff && nrg > this.threshold && nrg - this.penergy > 0) { + // trigger callback + this._onPeak(); + this.isDetected = true; + // debounce + this.cutoff = nrg * this.cutoffMult; + this.framesSinceLastPeak = 0; + } else { + this.isDetected = false; + if (this.framesSinceLastPeak <= this.framesPerPeak) { + this.framesSinceLastPeak++; + } else { + this.cutoff *= this.decayRate; + this.cutoff = Math.max(this.cutoff, this.threshold); + } + } + this.currentValue = nrg; + this.penergy = nrg; + }; + /** + * onPeak accepts two arguments: a function to call when + * a peak is detected. The value of the peak, + * between 0.0 and 1.0, is passed to the callback. + * + * @method onPeak + * @param {Function} callback Name of a function that will + * be called when a peak is + * detected. + * @param {Object} [val] Optional value to pass + * into the function when + * a peak is detected. + * @example + *
+ * var cnv, soundFile, fft, peakDetect; + * var ellipseWidth = 0; + * + * function preload() { + * soundFile = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * cnv = createCanvas(100,100); + * textAlign(CENTER); + * + * fft = new p5.FFT(); + * peakDetect = new p5.PeakDetect(); + * + * setupSound(); + * + * // when a beat is detected, call triggerBeat() + * peakDetect.onPeak(triggerBeat); + * } + * + * function draw() { + * background(0); + * fill(255); + * text('click to play', width/2, height/2); + * + * fft.analyze(); + * peakDetect.update(fft); + * + * ellipseWidth *= 0.95; + * ellipse(width/2, height/2, ellipseWidth, ellipseWidth); + * } + * + * // this function is called by peakDetect.onPeak + * function triggerBeat() { + * ellipseWidth = 50; + * } + * + * // mouseclick starts/stops sound + * function setupSound() { + * cnv.mouseClicked( function() { + * if (soundFile.isPlaying() ) { + * soundFile.stop(); + * } else { + * soundFile.play(); + * } + * }); + * } + *
+ */ + p5.PeakDetect.prototype.onPeak = function (callback, val) { + var self = this; + self._onPeak = function () { + callback(self.energy, val); + }; + }; + })(); + var gain; + ("use strict"); + gain = (function () { + var p5sound = master; + /** + * A gain node is usefull to set the relative volume of sound. + * It's typically used to build mixers. + * + * @class p5.Gain + * @constructor + * @example + *
+ * + * // load two soundfile and crossfade beetween them + * var sound1,sound2; + * var gain1, gain2, gain3; + * + * function preload(){ + * soundFormats('ogg', 'mp3'); + * sound1 = loadSound('assets/Damscray_-_Dancing_Tiger_01'); + * sound2 = loadSound('assets/beat.mp3'); + * } + * + * function setup() { + * createCanvas(400,200); + * + * // create a 'master' gain to which we will connect both soundfiles + * gain3 = new p5.Gain(); + * gain3.connect(); + * + * // setup first sound for playing + * sound1.rate(1); + * sound1.loop(); + * sound1.disconnect(); // diconnect from p5 output + * + * gain1 = new p5.Gain(); // setup a gain node + * gain1.setInput(sound1); // connect the first sound to its input + * gain1.connect(gain3); // connect its output to the 'master' + * + * sound2.rate(1); + * sound2.disconnect(); + * sound2.loop(); + * + * gain2 = new p5.Gain(); + * gain2.setInput(sound2); + * gain2.connect(gain3); + * + * } + * + * function draw(){ + * background(180); + * + * // calculate the horizontal distance beetween the mouse and the right of the screen + * var d = dist(mouseX,0,width,0); + * + * // map the horizontal position of the mouse to values useable for volume control of sound1 + * var vol1 = map(mouseX,0,width,0,1); + * var vol2 = 1-vol1; // when sound1 is loud, sound2 is quiet and vice versa + * + * gain1.amp(vol1,0.5,0); + * gain2.amp(vol2,0.5,0); + * + * // map the vertical position of the mouse to values useable for 'master volume control' + * var vol3 = map(mouseY,0,height,0,1); + * gain3.amp(vol3,0.5,0); + * } + *
+ * + */ + p5.Gain = function () { + this.ac = p5sound.audiocontext; + this.input = this.ac.createGain(); + this.output = this.ac.createGain(); + // otherwise, Safari distorts + this.input.gain.value = 0.5; + this.input.connect(this.output); + // add to the soundArray + p5sound.soundArray.push(this); + }; + /** + * Connect a source to the gain node. + * + * @method setInput + * @param {Object} src p5.sound / Web Audio object with a sound + * output. + */ + p5.Gain.prototype.setInput = function (src) { + src.connect(this.input); + }; + /** + * Send output to a p5.sound or web audio object + * + * @method connect + * @param {Object} unit + */ + p5.Gain.prototype.connect = function (unit) { + var u = unit || p5.soundOut.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all output. + * + * @method disconnect + */ + p5.Gain.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Set the output level of the gain node. + * + * @method amp + * @param {Number} volume amplitude between 0 and 1.0 + * @param {Number} [rampTime] create a fade that lasts rampTime + * @param {Number} [timeFromNow] schedule this event to happen + * seconds from now + */ + p5.Gain.prototype.amp = function (vol, rampTime, tFromNow) { + var rampTime = rampTime || 0; + var tFromNow = tFromNow || 0; + var now = p5sound.audiocontext.currentTime; + var currentVol = this.output.gain.value; + this.output.gain.cancelScheduledValues(now); + this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow); + this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime); + }; + p5.Gain.prototype.dispose = function () { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this.input) { + this.input.disconnect(); + delete this.input; + } + }; + })(master); + var audioVoice; + ("use strict"); + audioVoice = (function () { + var p5sound = master; + /** + * Base class for monophonic synthesizers. Any extensions of this class + * should follow the API and implement the methods below in order to + * remain compatible with p5.PolySynth(); + * + * @class p5.AudioVoice + * @constructor + */ + p5.AudioVoice = function () { + this.ac = p5sound.audiocontext; + this.output = this.ac.createGain(); + this.connect(); + p5sound.soundArray.push(this); + }; + p5.AudioVoice.prototype.play = function ( + note, + velocity, + secondsFromNow, + sustime + ) {}; + p5.AudioVoice.prototype.triggerAttack = function ( + note, + velocity, + secondsFromNow + ) {}; + p5.AudioVoice.prototype.triggerRelease = function (secondsFromNow) {}; + p5.AudioVoice.prototype.amp = function (vol, rampTime) {}; + /** + * Connect to p5 objects or Web Audio Nodes + * @method connect + * @param {Object} unit + */ + p5.AudioVoice.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect from soundOut + * @method disconnect + */ + p5.AudioVoice.prototype.disconnect = function () { this.output.disconnect(); - delete this.output; - } - }; - return p5.AudioVoice; -}(master); -var monosynth; -'use strict'; -monosynth = function () { - var p5sound = master; - var AudioVoice = audioVoice; - var noteToFreq = helpers.noteToFreq; - var DEFAULT_SUSTAIN = 0.15; - /** - * A MonoSynth is used as a single voice for sound synthesis. - * This is a class to be used in conjunction with the PolySynth - * class. Custom synthetisers should be built inheriting from - * this class. - * - * @class p5.MonoSynth - * @constructor - * @example - *
- * var monoSynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * monoSynth = new p5.MonoSynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // time from now (in seconds) - * var time = 0; - * // note duration (in seconds) - * var dur = 0.25; - * // velocity (volume, from 0 to 1) - * var v = 0.2; - * - * monoSynth.play("G3", v, time, dur); - * monoSynth.play("C4", v, time += dur, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- **/ - p5.MonoSynth = function () { - AudioVoice.call(this); - this.oscillator = new p5.Oscillator(); - this.env = new p5.Envelope(); - this.env.setRange(1, 0); - this.env.setExp(true); - //set params - this.setADSR(0.02, 0.25, 0.05, 0.35); - // oscillator --> env --> this.output (gain) --> p5.soundOut - this.oscillator.disconnect(); - this.oscillator.connect(this.output); - this.env.disconnect(); - this.env.setInput(this.output.gain); - // reset oscillator gain to 1.0 - this.oscillator.output.gain.value = 1; - this.oscillator.start(); - this.connect(); - p5sound.soundArray.push(this); - }; - p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype); - /** - * Play tells the MonoSynth to start playing a note. This method schedules - * the calling of .triggerAttack and .triggerRelease. - * - * @method play - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var monoSynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * monoSynth = new p5.MonoSynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // time from now (in seconds) - * var time = 0; - * // note duration (in seconds) - * var dur = 1/6; - * // note velocity (volume, from 0 to 1) - * var v = random(); - * - * monoSynth.play("Fb3", v, 0, dur); - * monoSynth.play("Gb3", v, time += dur, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- * - */ - p5.MonoSynth.prototype.play = function (note, velocity, secondsFromNow, susTime) { - this.triggerAttack(note, velocity, ~~secondsFromNow); - this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); - }; - /** - * Trigger the Attack, and Decay portion of the Envelope. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @param {String | Number} note the note you want to play, specified as a - * frequency in Hertz (Number) or as a midi - * value in Note/Octave format ("C4", "Eb3"...etc") - * See - * Tone. Defaults to 440 hz - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @method triggerAttack - * @example - *
- * var monoSynth = new p5.MonoSynth(); - * - * function mousePressed() { - * monoSynth.triggerAttack("E3"); - * } - * - * function mouseReleased() { - * monoSynth.triggerRelease(); - * } - *
- */ - p5.MonoSynth.prototype.triggerAttack = function (note, velocity, secondsFromNow) { - var secondsFromNow = ~~secondsFromNow; - var freq = noteToFreq(note); - var vel = velocity || 0.1; - this.oscillator.freq(freq, 0, secondsFromNow); - this.env.ramp(this.output.gain, secondsFromNow, vel); - }; - /** - * Trigger the release of the Envelope. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @param {Number} secondsFromNow time to trigger the release - * @method triggerRelease - * @example - *
- * var monoSynth = new p5.MonoSynth(); - * - * function mousePressed() { - * monoSynth.triggerAttack("E3"); - * } - * - * function mouseReleased() { - * monoSynth.triggerRelease(); - * } - *
- */ - p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) { - var secondsFromNow = secondsFromNow || 0; - this.env.ramp(this.output.gain, secondsFromNow, 0); - }; - /** - * Set values like a traditional - * - * ADSR envelope - * . - * - * @method setADSR - * @param {Number} attackTime Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - */ - p5.MonoSynth.prototype.setADSR = function (attack, decay, sustain, release) { - this.env.setADSR(attack, decay, sustain, release); - }; - /** - * Getters and Setters - * @property {Number} attack - */ - /** - * @property {Number} decay - */ - /** - * @property {Number} sustain - */ - /** - * @property {Number} release - */ - Object.defineProperties(p5.MonoSynth.prototype, { - 'attack': { - get: function () { - return this.env.aTime; + }; + p5.AudioVoice.prototype.dispose = function () { + if (this.output) { + this.output.disconnect(); + delete this.output; + } + }; + return p5.AudioVoice; + })(master); + var monosynth; + ("use strict"); + monosynth = (function () { + var p5sound = master; + var AudioVoice = audioVoice; + var noteToFreq = helpers.noteToFreq; + var DEFAULT_SUSTAIN = 0.15; + /** + * A MonoSynth is used as a single voice for sound synthesis. + * This is a class to be used in conjunction with the PolySynth + * class. Custom synthetisers should be built inheriting from + * this class. + * + * @class p5.MonoSynth + * @constructor + * @example + *
+ * var monoSynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * monoSynth = new p5.MonoSynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // time from now (in seconds) + * var time = 0; + * // note duration (in seconds) + * var dur = 0.25; + * // velocity (volume, from 0 to 1) + * var v = 0.2; + * + * monoSynth.play("G3", v, time, dur); + * monoSynth.play("C4", v, time += dur, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ **/ + p5.MonoSynth = function () { + AudioVoice.call(this); + this.oscillator = new p5.Oscillator(); + this.env = new p5.Envelope(); + this.env.setRange(1, 0); + this.env.setExp(true); + //set params + this.setADSR(0.02, 0.25, 0.05, 0.35); + // oscillator --> env --> this.output (gain) --> p5.soundOut + this.oscillator.disconnect(); + this.oscillator.connect(this.output); + this.env.disconnect(); + this.env.setInput(this.output.gain); + // reset oscillator gain to 1.0 + this.oscillator.output.gain.value = 1; + this.oscillator.start(); + this.connect(); + p5sound.soundArray.push(this); + }; + p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype); + /** + * Play tells the MonoSynth to start playing a note. This method schedules + * the calling of .triggerAttack and .triggerRelease. + * + * @method play + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var monoSynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * monoSynth = new p5.MonoSynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // time from now (in seconds) + * var time = 0; + * // note duration (in seconds) + * var dur = 1/6; + * // note velocity (volume, from 0 to 1) + * var v = random(); + * + * monoSynth.play("Fb3", v, 0, dur); + * monoSynth.play("Gb3", v, time += dur, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ * + */ + p5.MonoSynth.prototype.play = function ( + note, + velocity, + secondsFromNow, + susTime + ) { + this.triggerAttack(note, velocity, ~~secondsFromNow); + this.triggerRelease(~~secondsFromNow + (susTime || DEFAULT_SUSTAIN)); + }; + /** + * Trigger the Attack, and Decay portion of the Envelope. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @param {String | Number} note the note you want to play, specified as a + * frequency in Hertz (Number) or as a midi + * value in Note/Octave format ("C4", "Eb3"...etc") + * See + * Tone. Defaults to 440 hz + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @method triggerAttack + * @example + *
+ * var monoSynth = new p5.MonoSynth(); + * + * function mousePressed() { + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + p5.MonoSynth.prototype.triggerAttack = function ( + note, + velocity, + secondsFromNow + ) { + var secondsFromNow = ~~secondsFromNow; + var freq = noteToFreq(note); + var vel = velocity || 0.1; + this.oscillator.freq(freq, 0, secondsFromNow); + this.env.ramp(this.output.gain, secondsFromNow, vel); + }; + /** + * Trigger the release of the Envelope. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @param {Number} secondsFromNow time to trigger the release + * @method triggerRelease + * @example + *
+ * var monoSynth = new p5.MonoSynth(); + * + * function mousePressed() { + * monoSynth.triggerAttack("E3"); + * } + * + * function mouseReleased() { + * monoSynth.triggerRelease(); + * } + *
+ */ + p5.MonoSynth.prototype.triggerRelease = function (secondsFromNow) { + var secondsFromNow = secondsFromNow || 0; + this.env.ramp(this.output.gain, secondsFromNow, 0); + }; + /** + * Set values like a traditional + * + * ADSR envelope + * . + * + * @method setADSR + * @param {Number} attackTime Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + */ + p5.MonoSynth.prototype.setADSR = function ( + attack, + decay, + sustain, + release + ) { + this.env.setADSR(attack, decay, sustain, release); + }; + /** + * Getters and Setters + * @property {Number} attack + */ + /** + * @property {Number} decay + */ + /** + * @property {Number} sustain + */ + /** + * @property {Number} release + */ + Object.defineProperties(p5.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (attack) { + this.env.setADSR( + attack, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, }, - set: function (attack) { - this.env.setADSR(attack, this.env.dTime, this.env.sPercent, this.env.rTime); - } - }, - 'decay': { - get: function () { - return this.env.dTime; + decay: { + get: function () { + return this.env.dTime; + }, + set: function (decay) { + this.env.setADSR( + this.env.aTime, + decay, + this.env.sPercent, + this.env.rTime + ); + }, }, - set: function (decay) { - this.env.setADSR(this.env.aTime, decay, this.env.sPercent, this.env.rTime); - } - }, - 'sustain': { - get: function () { - return this.env.sPercent; + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (sustain) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + sustain, + this.env.rTime + ); + }, }, - set: function (sustain) { - this.env.setADSR(this.env.aTime, this.env.dTime, sustain, this.env.rTime); - } - }, - 'release': { - get: function () { - return this.env.rTime; + release: { + get: function () { + return this.env.rTime; + }, + set: function (release) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + release + ); + }, }, - set: function (release) { - this.env.setADSR(this.env.aTime, this.env.dTime, this.env.sPercent, release); + }); + /** + * MonoSynth amp + * @method amp + * @param {Number} vol desired volume + * @param {Number} [rampTime] Time to reach new volume + * @return {Number} new volume value + */ + p5.MonoSynth.prototype.amp = function (vol, rampTime) { + var t = rampTime || 0; + if (typeof vol !== "undefined") { + this.oscillator.amp(vol, t); } - } - }); - /** - * MonoSynth amp - * @method amp - * @param {Number} vol desired volume - * @param {Number} [rampTime] Time to reach new volume - * @return {Number} new volume value - */ - p5.MonoSynth.prototype.amp = function (vol, rampTime) { - var t = rampTime || 0; - if (typeof vol !== 'undefined') { - this.oscillator.amp(vol, t); - } - return this.oscillator.amp().value; - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.MonoSynth.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.MonoSynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - */ - p5.MonoSynth.prototype.dispose = function () { - AudioVoice.prototype.dispose.apply(this); - if (this.env) { - this.env.dispose(); - } - if (this.oscillator) { - this.oscillator.dispose(); - } - }; -}(master, audioVoice, helpers); -var polysynth; -'use strict'; -polysynth = function () { - var p5sound = master; - var TimelineSignal = Tone_signal_TimelineSignal; - var noteToFreq = helpers.noteToFreq; - /** - * An AudioVoice is used as a single voice for sound synthesis. - * The PolySynth class holds an array of AudioVoice, and deals - * with voices allocations, with setting notes to be played, and - * parameters to be set. - * - * @class p5.PolySynth - * @constructor - * - * @param {Number} [synthVoice] A monophonic synth voice inheriting - * the AudioVoice class. Defaults to p5.MonoSynth - * @param {Number} [maxVoices] Number of voices, defaults to 8; - * @example - *
- * var polySynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * polySynth = new p5.PolySynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // note duration (in seconds) - * var dur = 1.5; - * - * // time from now (in seconds) - * var time = 0; - * - * // velocity (volume, from 0 to 1) - * var vel = 0.1; - * - * // notes can overlap with each other - * polySynth.play("G2", vel, 0, dur); - * polySynth.play("C3", vel, time += 1/3, dur); - * polySynth.play("G3", vel, time += 1/3, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- **/ - p5.PolySynth = function (audioVoice, maxVoices) { - //audiovoices will contain maxVoices many monophonic synths - this.audiovoices = []; - /** - * An object that holds information about which notes have been played and - * which notes are currently being played. New notes are added as keys - * on the fly. While a note has been attacked, but not released, the value of the - * key is the audiovoice which is generating that note. When notes are released, - * the value of the key becomes undefined. - * @property notes - */ - this.notes = {}; - //indices of the most recently used, and least recently used audiovoice - this._newest = 0; - this._oldest = 0; - /** - * A PolySynth must have at least 1 voice, defaults to 8 - * @property polyvalue - */ - this.maxVoices = maxVoices || 8; - /** - * Monosynth that generates the sound for each note that is triggered. The - * p5.PolySynth defaults to using the p5.MonoSynth as its voice. - * @property AudioVoice - */ - this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; + return this.oscillator.amp().value; + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.MonoSynth.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.MonoSynth.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + */ + p5.MonoSynth.prototype.dispose = function () { + AudioVoice.prototype.dispose.apply(this); + if (this.env) { + this.env.dispose(); + } + if (this.oscillator) { + this.oscillator.dispose(); + } + }; + })(master, audioVoice, helpers); + var polysynth; + ("use strict"); + polysynth = (function () { + var p5sound = master; + var TimelineSignal = Tone_signal_TimelineSignal; + var noteToFreq = helpers.noteToFreq; /** + * An AudioVoice is used as a single voice for sound synthesis. + * The PolySynth class holds an array of AudioVoice, and deals + * with voices allocations, with setting notes to be played, and + * parameters to be set. + * + * @class p5.PolySynth + * @constructor + * + * @param {Number} [synthVoice] A monophonic synth voice inheriting + * the AudioVoice class. Defaults to p5.MonoSynth + * @param {Number} [maxVoices] Number of voices, defaults to 8; + * @example + *
+ * var polySynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * polySynth = new p5.PolySynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // note duration (in seconds) + * var dur = 1.5; + * + * // time from now (in seconds) + * var time = 0; + * + * // velocity (volume, from 0 to 1) + * var vel = 0.1; + * + * // notes can overlap with each other + * polySynth.play("G2", vel, 0, dur); + * polySynth.play("C3", vel, time += 1/3, dur); + * polySynth.play("G3", vel, time += 1/3, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ **/ + p5.PolySynth = function (audioVoice, maxVoices) { + //audiovoices will contain maxVoices many monophonic synths + this.audiovoices = []; + /** + * An object that holds information about which notes have been played and + * which notes are currently being played. New notes are added as keys + * on the fly. While a note has been attacked, but not released, the value of the + * key is the audiovoice which is generating that note. When notes are released, + * the value of the key becomes undefined. + * @property notes + */ + this.notes = {}; + //indices of the most recently used, and least recently used audiovoice + this._newest = 0; + this._oldest = 0; + /** + * A PolySynth must have at least 1 voice, defaults to 8 + * @property polyvalue + */ + this.maxVoices = maxVoices || 8; + /** + * Monosynth that generates the sound for each note that is triggered. The + * p5.PolySynth defaults to using the p5.MonoSynth as its voice. + * @property AudioVoice + */ + this.AudioVoice = audioVoice === undefined ? p5.MonoSynth : audioVoice; + /** * This value must only change as a note is attacked or released. Due to delay * and sustain times, Tone.TimelineSignal is required to schedule the change in value. - * @private + * @private * @property {Tone.TimelineSignal} _voicesInUse */ - this._voicesInUse = new TimelineSignal(0); - this.output = p5sound.audiocontext.createGain(); - this.connect(); - //Construct the appropriate number of audiovoices - this._allocateVoices(); - p5sound.soundArray.push(this); - }; - /** - * Construct the appropriate number of audiovoices - * @private - * @method _allocateVoices - */ - p5.PolySynth.prototype._allocateVoices = function () { - for (var i = 0; i < this.maxVoices; i++) { - this.audiovoices.push(new this.AudioVoice()); - this.audiovoices[i].disconnect(); - this.audiovoices[i].connect(this.output); - } - }; - /** - * Play a note by triggering noteAttack and noteRelease with sustain time - * - * @method play - * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) - * @param {Number} [secondsFromNow] time from now (in seconds) at which to play - * @param {Number} [sustainTime] time to sustain before releasing the envelope - * @example - *
- * var polySynth; - * - * function setup() { - * var cnv = createCanvas(100, 100); - * cnv.mousePressed(playSynth); - * - * polySynth = new p5.PolySynth(); - * - * textAlign(CENTER); - * text('click to play', width/2, height/2); - * } - * - * function playSynth() { - * // note duration (in seconds) - * var dur = 0.1; - * - * // time from now (in seconds) - * var time = 0; - * - * // velocity (volume, from 0 to 1) - * var vel = 0.1; - * - * polySynth.play("G2", vel, 0, dur); - * polySynth.play("C3", vel, 0, dur); - * polySynth.play("G3", vel, 0, dur); - * - * background(random(255), random(255), 255); - * text('click to play', width/2, height/2); - * } - *
- */ - p5.PolySynth.prototype.play = function (note, velocity, secondsFromNow, susTime) { - var susTime = susTime || 1; - this.noteAttack(note, velocity, secondsFromNow); - this.noteRelease(note, secondsFromNow + susTime); - }; - /** - * noteADSR sets the envelope for a specific note that has just been triggered. - * Using this method modifies the envelope of whichever audiovoice is being used - * to play the desired note. The envelope should be reset before noteRelease is called - * in order to prevent the modified envelope from being used on other notes. - * - * @method noteADSR - * @param {Number} [note] Midi note on which ADSR should be set. - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow) { - var now = p5sound.audiocontext.currentTime; - var timeFromNow = timeFromNow || 0; - var t = now + timeFromNow; - this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); - }; - /** - * Set the PolySynths global envelope. This method modifies the envelopes of each - * monosynth so that all notes are played with this envelope. - * - * @method setADSR - * @param {Number} [attackTime] Time (in seconds before envelope - * reaches Attack Level - * @param {Number} [decayTime] Time (in seconds) before envelope - * reaches Decay/Sustain Level - * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, - * where 1.0 = attackLevel, 0.0 = releaseLevel. - * The susRatio determines the decayLevel and the level at which the - * sustain portion of the envelope will sustain. - * For example, if attackLevel is 0.4, releaseLevel is 0, - * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is - * increased to 1.0 (using setRange), - * then decayLevel would increase proportionally, to become 0.5. - * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) - **/ - p5.PolySynth.prototype.setADSR = function (a, d, s, r) { - this.audiovoices.forEach(function (voice) { - voice.setADSR(a, d, s, r); - }); - }; - /** - * Trigger the Attack, and Decay portion of a MonoSynth. - * Similar to holding down a key on a piano, but it will - * hold the sustain level until you let go. - * - * @method noteAttack - * @param {Number} [note] midi note on which attack should be triggered. - * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ - * @param {Number} [secondsFromNow] time from now (in seconds) - * @example - *
- * var polySynth = new p5.PolySynth(); - * var pitches = ["G", "D", "G", "C"]; - * var octaves = [2, 3, 4]; - * - * function mousePressed() { - * // play a chord: multiple notes at the same time - * for (var i = 0; i < 4; i++) { - * var note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } - * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); - * } - *
- */ - p5.PolySynth.prototype.noteAttack = function (_note, _velocity, secondsFromNow) { - //this value goes to the audiovoices which handle their own scheduling - var secondsFromNow = ~~secondsFromNow; - //this value is used by this._voicesInUse - var acTime = p5sound.audiocontext.currentTime + secondsFromNow; - //Convert note to frequency if necessary. This is because entries into this.notes - //should be based on frequency for the sake of consistency. - var note = noteToFreq(_note); - var velocity = _velocity || 0.1; - var currentVoice; - //Release the note if it is already playing - if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) { - this.noteRelease(note, 0); - } - //Check to see how many voices are in use at the time the note will start - if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { - currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); - } else { - currentVoice = this._oldest; - var oldestNote = p5.prototype.freqToMidi(this.audiovoices[this._oldest].oscillator.freq().value); - this.noteRelease(oldestNote); - this._oldest = (this._oldest + 1) % (this.maxVoices - 1); - } - //Overrite the entry in the notes object. A note (frequency value) - //corresponds to the index of the audiovoice that is playing it - this.notes[note] = new TimelineSignal(); - this.notes[note].setValueAtTime(currentVoice, acTime); - //Find the scheduled change in this._voicesInUse that will be previous to this new note - //Add 1 and schedule this value at time 't', when this note will start playing - var previousVal = this._voicesInUse._searchBefore(acTime) === null ? 0 : this._voicesInUse._searchBefore(acTime).value; - this._voicesInUse.setValueAtTime(previousVal + 1, acTime); - //Then update all scheduled values that follow to increase by 1 - this._updateAfter(acTime, 1); - this._newest = currentVoice; - //The audiovoice handles the actual scheduling of the note - if (typeof velocity === 'number') { - var maxRange = 1 / this._voicesInUse.getValueAtTime(acTime) * 2; - velocity = velocity > maxRange ? maxRange : velocity; - } - this.audiovoices[currentVoice].triggerAttack(note, velocity, secondsFromNow); - }; - /** - * Private method to ensure accurate values of this._voicesInUse - * Any time a new value is scheduled, it is necessary to increment all subsequent - * scheduledValues after attack, and decrement all subsequent - * scheduledValues after release - * - * @private - * @param {[type]} time [description] - * @param {[type]} value [description] - * @return {[type]} [description] - */ - p5.PolySynth.prototype._updateAfter = function (time, value) { - if (this._voicesInUse._searchAfter(time) === null) { - return; - } else { - this._voicesInUse._searchAfter(time).value += value; - var nextTime = this._voicesInUse._searchAfter(time).time; - this._updateAfter(nextTime, value); - } - }; - /** - * Trigger the Release of an AudioVoice note. This is similar to releasing - * the key on a piano and letting the sound fade according to the - * release level and release time. - * - * @method noteRelease - * @param {Number} [note] midi note on which attack should be triggered. - * If no value is provided, all notes will be released. - * @param {Number} [secondsFromNow] time to trigger the release - * @example - *
- * var pitches = ["G", "D", "G", "C"]; - * var octaves = [2, 3, 4]; - * var polySynth = new p5.PolySynth(); - * - * function mousePressed() { - * // play a chord: multiple notes at the same time - * for (var i = 0; i < 4; i++) { - * var note = random(pitches) + random(octaves); - * polySynth.noteAttack(note, 0.1); - * } - * } - * - * function mouseReleased() { - * // release all voices - * polySynth.noteRelease(); - * } - *
- * - */ - p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) { - var now = p5sound.audiocontext.currentTime; - var tFromNow = secondsFromNow || 0; - var t = now + tFromNow; - // if a note value is not provided, release all voices - if (!_note) { + this._voicesInUse = new TimelineSignal(0); + this.output = p5sound.audiocontext.createGain(); + this.connect(); + //Construct the appropriate number of audiovoices + this._allocateVoices(); + p5sound.soundArray.push(this); + }; + /** + * Construct the appropriate number of audiovoices + * @private + * @method _allocateVoices + */ + p5.PolySynth.prototype._allocateVoices = function () { + for (var i = 0; i < this.maxVoices; i++) { + this.audiovoices.push(new this.AudioVoice()); + this.audiovoices[i].disconnect(); + this.audiovoices[i].connect(this.output); + } + }; + /** + * Play a note by triggering noteAttack and noteRelease with sustain time + * + * @method play + * @param {Number} [note] midi note to play (ranging from 0 to 127 - 60 being a middle C) + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1) + * @param {Number} [secondsFromNow] time from now (in seconds) at which to play + * @param {Number} [sustainTime] time to sustain before releasing the envelope + * @example + *
+ * var polySynth; + * + * function setup() { + * var cnv = createCanvas(100, 100); + * cnv.mousePressed(playSynth); + * + * polySynth = new p5.PolySynth(); + * + * textAlign(CENTER); + * text('click to play', width/2, height/2); + * } + * + * function playSynth() { + * // note duration (in seconds) + * var dur = 0.1; + * + * // time from now (in seconds) + * var time = 0; + * + * // velocity (volume, from 0 to 1) + * var vel = 0.1; + * + * polySynth.play("G2", vel, 0, dur); + * polySynth.play("C3", vel, 0, dur); + * polySynth.play("G3", vel, 0, dur); + * + * background(random(255), random(255), 255); + * text('click to play', width/2, height/2); + * } + *
+ */ + p5.PolySynth.prototype.play = function ( + note, + velocity, + secondsFromNow, + susTime + ) { + var susTime = susTime || 1; + this.noteAttack(note, velocity, secondsFromNow); + this.noteRelease(note, secondsFromNow + susTime); + }; + /** + * noteADSR sets the envelope for a specific note that has just been triggered. + * Using this method modifies the envelope of whichever audiovoice is being used + * to play the desired note. The envelope should be reset before noteRelease is called + * in order to prevent the modified envelope from being used on other notes. + * + * @method noteADSR + * @param {Number} [note] Midi note on which ADSR should be set. + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + p5.PolySynth.prototype.noteADSR = function (note, a, d, s, r, timeFromNow) { + var now = p5sound.audiocontext.currentTime; + var timeFromNow = timeFromNow || 0; + var t = now + timeFromNow; + this.audiovoices[this.notes[note].getValueAtTime(t)].setADSR(a, d, s, r); + }; + /** + * Set the PolySynths global envelope. This method modifies the envelopes of each + * monosynth so that all notes are played with this envelope. + * + * @method setADSR + * @param {Number} [attackTime] Time (in seconds before envelope + * reaches Attack Level + * @param {Number} [decayTime] Time (in seconds) before envelope + * reaches Decay/Sustain Level + * @param {Number} [susRatio] Ratio between attackLevel and releaseLevel, on a scale from 0 to 1, + * where 1.0 = attackLevel, 0.0 = releaseLevel. + * The susRatio determines the decayLevel and the level at which the + * sustain portion of the envelope will sustain. + * For example, if attackLevel is 0.4, releaseLevel is 0, + * and susAmt is 0.5, the decayLevel would be 0.2. If attackLevel is + * increased to 1.0 (using setRange), + * then decayLevel would increase proportionally, to become 0.5. + * @param {Number} [releaseTime] Time in seconds from now (defaults to 0) + **/ + p5.PolySynth.prototype.setADSR = function (a, d, s, r) { this.audiovoices.forEach(function (voice) { - voice.triggerRelease(tFromNow); + voice.setADSR(a, d, s, r); }); - this._voicesInUse.setValueAtTime(0, t); - for (var n in this.notes) { - this.notes[n].dispose(); - delete this.notes[n]; - } - return; - } - //Make sure note is in frequency inorder to query the this.notes object - var note = noteToFreq(_note); - if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { - console.warn('Cannot release a note that is not already playing'); - } else { + }; + /** + * Trigger the Attack, and Decay portion of a MonoSynth. + * Similar to holding down a key on a piano, but it will + * hold the sustain level until you let go. + * + * @method noteAttack + * @param {Number} [note] midi note on which attack should be triggered. + * @param {Number} [velocity] velocity of the note to play (ranging from 0 to 1)/ + * @param {Number} [secondsFromNow] time from now (in seconds) + * @example + *
+ * var polySynth = new p5.PolySynth(); + * var pitches = ["G", "D", "G", "C"]; + * var octaves = [2, 3, 4]; + * + * function mousePressed() { + * // play a chord: multiple notes at the same time + * for (var i = 0; i < 4; i++) { + * var note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ */ + p5.PolySynth.prototype.noteAttack = function ( + _note, + _velocity, + secondsFromNow + ) { + //this value goes to the audiovoices which handle their own scheduling + var secondsFromNow = ~~secondsFromNow; + //this value is used by this._voicesInUse + var acTime = p5sound.audiocontext.currentTime + secondsFromNow; + //Convert note to frequency if necessary. This is because entries into this.notes + //should be based on frequency for the sake of consistency. + var note = noteToFreq(_note); + var velocity = _velocity || 0.1; + var currentVoice; + //Release the note if it is already playing + if ( + this.notes[note] && + this.notes[note].getValueAtTime(acTime) !== null + ) { + this.noteRelease(note, 0); + } + //Check to see how many voices are in use at the time the note will start + if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) { + currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0); + } else { + currentVoice = this._oldest; + var oldestNote = p5.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(oldestNote); + this._oldest = (this._oldest + 1) % (this.maxVoices - 1); + } + //Overrite the entry in the notes object. A note (frequency value) + //corresponds to the index of the audiovoice that is playing it + this.notes[note] = new TimelineSignal(); + this.notes[note].setValueAtTime(currentVoice, acTime); //Find the scheduled change in this._voicesInUse that will be previous to this new note - //subtract 1 and schedule this value at time 't', when this note will stop playing - var previousVal = Math.max(~~this._voicesInUse.getValueAtTime(t).value, 1); - this._voicesInUse.setValueAtTime(previousVal - 1, t); - //Then update all scheduled values that follow to decrease by 1 but never go below 0 - if (previousVal > 0) { - this._updateAfter(t, -1); - } - this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease(tFromNow); - this.notes[note].dispose(); - delete this.notes[note]; - this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); - } - }; - /** - * Connect to a p5.sound / Web Audio object. - * - * @method connect - * @param {Object} unit A p5.sound or Web Audio object - */ - p5.PolySynth.prototype.connect = function (unit) { - var u = unit || p5sound.input; - this.output.connect(u.input ? u.input : u); - }; - /** - * Disconnect all outputs - * - * @method disconnect - */ - p5.PolySynth.prototype.disconnect = function () { - if (this.output) { - this.output.disconnect(); - } - }; - /** - * Get rid of the MonoSynth and free up its resources / memory. - * - * @method dispose - */ - p5.PolySynth.prototype.dispose = function () { - this.audiovoices.forEach(function (voice) { - voice.dispose(); - }); - if (this.output) { - this.output.disconnect(); - delete this.output; - } - }; -}(master, Tone_signal_TimelineSignal, helpers); -var distortion; -'use strict'; -distortion = function () { - var Effect = effect; - /* - * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) - */ - function makeDistortionCurve(amount) { - var k = typeof amount === 'number' ? amount : 50; - var numSamples = 44100; - var curve = new Float32Array(numSamples); - var deg = Math.PI / 180; - var i = 0; - var x; - for (; i < numSamples; ++i) { - x = i * 2 / numSamples - 1; - curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x)); - } - return curve; - } - /** - * A Distortion effect created with a Waveshaper Node, - * with an approach adapted from - * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) - * - * This class extends p5.Effect. - * Methods amp(), chain(), - * drywet(), connect(), and - * disconnect() are available. - * - * @class p5.Distortion - * @extends p5.Effect - * @constructor - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - * - */ - p5.Distortion = function (amount, oversample) { - Effect.call(this); - if (typeof amount === 'undefined') { - amount = 0.25; - } - if (typeof amount !== 'number') { - throw new Error('amount must be a number'); - } - if (typeof oversample === 'undefined') { - oversample = '2x'; - } - if (typeof oversample !== 'string') { - throw new Error('oversample must be a String'); + //Add 1 and schedule this value at time 't', when this note will start playing + var previousVal = + this._voicesInUse._searchBefore(acTime) === null + ? 0 + : this._voicesInUse._searchBefore(acTime).value; + this._voicesInUse.setValueAtTime(previousVal + 1, acTime); + //Then update all scheduled values that follow to increase by 1 + this._updateAfter(acTime, 1); + this._newest = currentVoice; + //The audiovoice handles the actual scheduling of the note + if (typeof velocity === "number") { + var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2; + velocity = velocity > maxRange ? maxRange : velocity; + } + this.audiovoices[currentVoice].triggerAttack( + note, + velocity, + secondsFromNow + ); + }; + /** + * Private method to ensure accurate values of this._voicesInUse + * Any time a new value is scheduled, it is necessary to increment all subsequent + * scheduledValues after attack, and decrement all subsequent + * scheduledValues after release + * + * @private + * @param {[type]} time [description] + * @param {[type]} value [description] + * @return {[type]} [description] + */ + p5.PolySynth.prototype._updateAfter = function (time, value) { + if (this._voicesInUse._searchAfter(time) === null) { + return; + } else { + this._voicesInUse._searchAfter(time).value += value; + var nextTime = this._voicesInUse._searchAfter(time).time; + this._updateAfter(nextTime, value); + } + }; + /** + * Trigger the Release of an AudioVoice note. This is similar to releasing + * the key on a piano and letting the sound fade according to the + * release level and release time. + * + * @method noteRelease + * @param {Number} [note] midi note on which attack should be triggered. + * If no value is provided, all notes will be released. + * @param {Number} [secondsFromNow] time to trigger the release + * @example + *
+ * var pitches = ["G", "D", "G", "C"]; + * var octaves = [2, 3, 4]; + * var polySynth = new p5.PolySynth(); + * + * function mousePressed() { + * // play a chord: multiple notes at the same time + * for (var i = 0; i < 4; i++) { + * var note = random(pitches) + random(octaves); + * polySynth.noteAttack(note, 0.1); + * } + * } + * + * function mouseReleased() { + * // release all voices + * polySynth.noteRelease(); + * } + *
+ * + */ + p5.PolySynth.prototype.noteRelease = function (_note, secondsFromNow) { + var now = p5sound.audiocontext.currentTime; + var tFromNow = secondsFromNow || 0; + var t = now + tFromNow; + // if a note value is not provided, release all voices + if (!_note) { + this.audiovoices.forEach(function (voice) { + voice.triggerRelease(tFromNow); + }); + this._voicesInUse.setValueAtTime(0, t); + for (var n in this.notes) { + this.notes[n].dispose(); + delete this.notes[n]; + } + return; + } + //Make sure note is in frequency inorder to query the this.notes object + var note = noteToFreq(_note); + if (!this.notes[note] || this.notes[note].getValueAtTime(t) === null) { + console.warn("Cannot release a note that is not already playing"); + } else { + //Find the scheduled change in this._voicesInUse that will be previous to this new note + //subtract 1 and schedule this value at time 't', when this note will stop playing + var previousVal = Math.max( + ~~this._voicesInUse.getValueAtTime(t).value, + 1 + ); + this._voicesInUse.setValueAtTime(previousVal - 1, t); + //Then update all scheduled values that follow to decrease by 1 but never go below 0 + if (previousVal > 0) { + this._updateAfter(t, -1); + } + this.audiovoices[this.notes[note].getValueAtTime(t)].triggerRelease( + tFromNow + ); + this.notes[note].dispose(); + delete this.notes[note]; + this._newest = + this._newest === 0 ? 0 : (this._newest - 1) % (this.maxVoices - 1); + } + }; + /** + * Connect to a p5.sound / Web Audio object. + * + * @method connect + * @param {Object} unit A p5.sound or Web Audio object + */ + p5.PolySynth.prototype.connect = function (unit) { + var u = unit || p5sound.input; + this.output.connect(u.input ? u.input : u); + }; + /** + * Disconnect all outputs + * + * @method disconnect + */ + p5.PolySynth.prototype.disconnect = function () { + if (this.output) { + this.output.disconnect(); + } + }; + /** + * Get rid of the MonoSynth and free up its resources / memory. + * + * @method dispose + */ + p5.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (voice) { + voice.dispose(); + }); + if (this.output) { + this.output.disconnect(); + delete this.output; + } + }; + })(master, Tone_signal_TimelineSignal, helpers); + var distortion; + ("use strict"); + distortion = (function () { + var Effect = effect; + /* + * Adapted from [Kevin Ennis on StackOverflow](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) + */ + function makeDistortionCurve(amount) { + var k = typeof amount === "number" ? amount : 50; + var numSamples = 44100; + var curve = new Float32Array(numSamples); + var deg = Math.PI / 180; + var i = 0; + var x; + for (; i < numSamples; ++i) { + x = (i * 2) / numSamples - 1; + curve[i] = ((3 + k) * x * 20 * deg) / (Math.PI + k * Math.abs(x)); + } + return curve; } - var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); - /** - * The p5.Distortion is built with a - * - * Web Audio WaveShaper Node. - * - * @property {AudioNode} WaveShaperNode - */ - this.waveShaperNode = this.ac.createWaveShaper(); - this.amount = curveAmount; - this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - this.waveShaperNode.oversample = oversample; - this.input.connect(this.waveShaperNode); - this.waveShaperNode.connect(this.wet); - }; - p5.Distortion.prototype = Object.create(Effect.prototype); - /** - * Process a sound source, optionally specify amount and oversample values. - * - * @method process - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.process = function (src, amount, oversample) { - src.connect(this.input); - this.set(amount, oversample); - }; - /** - * Set the amount and oversample of the waveshaper distortion. - * - * @method set - * @param {Number} [amount=0.25] Unbounded distortion amount. - * Normal values range from 0-1. - * @param {String} [oversample='none'] 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.set = function (amount, oversample) { - if (amount) { + /** + * A Distortion effect created with a Waveshaper Node, + * with an approach adapted from + * [Kevin Ennis](http://stackoverflow.com/questions/22312841/waveshaper-node-in-webaudio-how-to-emulate-distortion) + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Distortion + * @extends p5.Effect + * @constructor + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + * + */ + p5.Distortion = function (amount, oversample) { + Effect.call(this); + if (typeof amount === "undefined") { + amount = 0.25; + } + if (typeof amount !== "number") { + throw new Error("amount must be a number"); + } + if (typeof oversample === "undefined") { + oversample = "2x"; + } + if (typeof oversample !== "string") { + throw new Error("oversample must be a String"); + } var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); + /** + * The p5.Distortion is built with a + * + * Web Audio WaveShaper Node. + * + * @property {AudioNode} WaveShaperNode + */ + this.waveShaperNode = this.ac.createWaveShaper(); this.amount = curveAmount; this.waveShaperNode.curve = makeDistortionCurve(curveAmount); - } - if (oversample) { this.waveShaperNode.oversample = oversample; - } - }; - /** - * Return the distortion amount, typically between 0-1. - * - * @method getAmount - * @return {Number} Unbounded distortion amount. - * Normal values range from 0-1. - */ - p5.Distortion.prototype.getAmount = function () { - return this.amount; - }; - /** - * Return the oversampling. - * - * @method getOversample - * - * @return {String} Oversample can either be 'none', '2x', or '4x'. - */ - p5.Distortion.prototype.getOversample = function () { - return this.waveShaperNode.oversample; - }; - p5.Distortion.prototype.dispose = function () { - Effect.prototype.dispose.apply(this); - if (this.waveShaperNode) { - this.waveShaperNode.disconnect(); - this.waveShaperNode = null; - } - }; -}(effect); -var src_app; -'use strict'; -src_app = function () { - var p5SOUND = master; - return p5SOUND; -}(shims, audiocontext, master, helpers, errorHandler, panner, soundfile, amplitude, fft, signal, oscillator, envelope, pulse, noise, audioin, filter, eq, panner3d, listener3d, delay, reverb, metro, looper, soundloop, compressor, soundRecorder, peakdetect, gain, monosynth, polysynth, distortion, audioVoice, monosynth, polysynth); -})); \ No newline at end of file + this.input.connect(this.waveShaperNode); + this.waveShaperNode.connect(this.wet); + }; + p5.Distortion.prototype = Object.create(Effect.prototype); + /** + * Process a sound source, optionally specify amount and oversample values. + * + * @method process + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.process = function (src, amount, oversample) { + src.connect(this.input); + this.set(amount, oversample); + }; + /** + * Set the amount and oversample of the waveshaper distortion. + * + * @method set + * @param {Number} [amount=0.25] Unbounded distortion amount. + * Normal values range from 0-1. + * @param {String} [oversample='none'] 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.set = function (amount, oversample) { + if (amount) { + var curveAmount = p5.prototype.map(amount, 0, 1, 0, 2000); + this.amount = curveAmount; + this.waveShaperNode.curve = makeDistortionCurve(curveAmount); + } + if (oversample) { + this.waveShaperNode.oversample = oversample; + } + }; + /** + * Return the distortion amount, typically between 0-1. + * + * @method getAmount + * @return {Number} Unbounded distortion amount. + * Normal values range from 0-1. + */ + p5.Distortion.prototype.getAmount = function () { + return this.amount; + }; + /** + * Return the oversampling. + * + * @method getOversample + * + * @return {String} Oversample can either be 'none', '2x', or '4x'. + */ + p5.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }; + p5.Distortion.prototype.dispose = function () { + Effect.prototype.dispose.apply(this); + if (this.waveShaperNode) { + this.waveShaperNode.disconnect(); + this.waveShaperNode = null; + } + }; + })(effect); + var src_app; + ("use strict"); + src_app = (function () { + var p5SOUND = master; + return p5SOUND; + })( + shims, + audiocontext, + master, + helpers, + errorHandler, + panner, + soundfile, + amplitude, + fft, + signal, + oscillator, + envelope, + pulse, + noise, + audioin, + filter, + eq, + panner3d, + listener3d, + delay, + reverb, + metro, + looper, + soundloop, + compressor, + soundRecorder, + peakdetect, + gain, + monosynth, + polysynth, + distortion, + audioVoice, + monosynth, + polysynth + ); +}); diff --git a/week7-runway/runway_Cartoon_style_mirror_hosted_model/p5.sound.min.js b/week7-runway/runway_Cartoon_style_mirror_hosted_model/p5.sound.min.js index fe65a81..2c88ede 100644 --- a/week7-runway/runway_Cartoon_style_mirror_hosted_model/p5.sound.min.js +++ b/week7-runway/runway_Cartoon_style_mirror_hosted_model/p5.sound.min.js @@ -1,3 +1,7708 @@ -/** [p5.sound] Version: 0.3.12 - 2020-01-06 */ - !function(n){var i={};function o(t){if(i[t])return i[t].exports;var e=i[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=n,o.c=i,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)o.d(n,i,function(t){return e[t]}.bind(null,i));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=31)}([function(t,e,n){var i;void 0===(i=function(){"use strict";function c(t,e){this.isUndef(t)||1===t?this.input=this.context.createGain():1t)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var i=this._searchAfter(t);i&&(this.cancelScheduledValues(t),i.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):i.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.linearRampToValueAtTime(t,n),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,n),this},u.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},u.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},u.TimelineSignal.prototype.getValueAtTime=function(t){t=this.toSeconds(t);var e=this._searchAfter(t),n=this._searchBefore(t),i=this._initial;if(null===n)i=this._initial;else if(n.type===u.TimelineSignal.Type.Target){var o,r=this._events.getBefore(n.time);o=null===r?this._initial:r.value,i=this._exponentialApproach(n.time,o,n.value,n.constant,t)}else i=n.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,t):null===e?n.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,e.time,e.value,t):n.value;return i},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,n,i,o){return n+(e-n)*Math.exp(-(o-t)/i)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,n,i,o){return e+(o-t)/(n-t)*(i-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,n,i,o){return(e=Math.max(this._minOutput,e))*Math.pow(i/e,(o-t)/(n-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,n,i){var o=e.length;if(t+n<=i)return e[o-1];if(i<=t)return e[0];var r=(i-t)/n,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),u=e[s],p=e[a];return a===s?u:this._linearInterpolate(s,u,a,p,r*(o-1))},u.TimelineSignal.prototype.dispose=function(){u.Signal.prototype.dispose.call(this),u.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},u.TimelineSignal}.apply(e,i))||(t.exports=o)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var e=n(4);return p5.Filter=function(t){e.call(this),this.biquad=this.ac.createBiquadFilter(),this.input.connect(this.biquad),this.biquad.connect(this.wet),t&&this.setType(t),this._on=!0,this._untoggledType=this.biquad.type},p5.Filter.prototype=Object.create(e.prototype),p5.Filter.prototype.process=function(t,e,n,i){t.connect(this.input),this.set(e,n,i)},p5.Filter.prototype.set=function(t,e,n){t&&this.freq(t,n),e&&this.res(e,n)},p5.Filter.prototype.freq=function(t,e){var n=e||0;return t<=0&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},p5.Filter.prototype.res=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},p5.Filter.prototype.gain=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},p5.Filter.prototype.toggle=function(){return this._on=!this._on,!0===this._on?this.biquad.type=this._untoggledType:!1===this._on&&(this.biquad.type="allpass"),this._on},p5.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},p5.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},p5.LowPass=function(){p5.Filter.call(this,"lowpass")},p5.LowPass.prototype=Object.create(p5.Filter.prototype),p5.HighPass=function(){p5.Filter.call(this,"highpass")},p5.HighPass.prototype=Object.create(p5.Filter.prototype),p5.BandPass=function(){p5.Filter.call(this,"bandpass")},p5.BandPass.prototype=Object.create(p5.Filter.prototype),p5.Filter}.call(e,n,e,t))||(t.exports=i)},function(t,e,n){var i,o;i=[n(0),n(7),n(25),n(2),n(9)],void 0===(o=function(e){"use strict";return e.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new e.Gain,this._neg=new e.Negate,this._param=this.input[1]=new e.Signal(t),this._param.chain(this._neg,this._sum)},e.extend(e.Subtract,e.Signal),e.Subtract.prototype.dispose=function(){return e.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},e.Subtract}.apply(e,i))||(t.exports=o)},function(i,o,r){"use strict";(function(t){var e,n;t.TONE_SILENCE_VERSION_LOGGING=!0,e=[r(35),r(12),r(0)],void 0===(n=function(i,t,e){var o=new window.AudioContext;return e.context.dispose(),e.setContext(o),p5.prototype.getAudioContext=function(){return o},p5.prototype.userStartAudio=function(t,e){var n=t;return t instanceof p5.Element?n=t.elt:t instanceof Array&&t[0]instanceof p5.Element&&(n=t.map(function(t){return t.elt})),i(o,n,e)},o}.apply(o,e))||(i.exports=n)}).call(this,r(34))},function(t,e,n){var i,o;i=[n(0)],void 0===(o=function(s){"use strict";return s.Emitter=function(){this._events={}},s.extend(s.Emitter),s.Emitter.prototype.on=function(t,e){for(var n=t.split(/\W+/),i=0;ithis.memory){var n=this.length-this.memory;this._timeline.splice(0,n)}return this},e.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},e.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},e.Timeline.prototype.peek=function(){return this._timeline[0]},e.Timeline.prototype.shift=function(){return this._timeline.shift()},e.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+1=t&&(this._timeline=[]);return this},e.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);0<=e&&(this._timeline=this._timeline.slice(e+1))}return this},e.Timeline.prototype._search=function(t){var e=0,n=this._timeline.length,i=n;if(0t)return o;r.time>t?i=o:r.time=t;)n--;return this._iterate(e,n+1),this},e.Timeline.prototype.forEachAtTime=function(e,n){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&n(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(3),n(2)],void 0===(o=function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(2),n(3),n(5)],void 0===(o=function(t){"use strict";return t.GreaterThanZero=function(){this._thresh=this.output=new t.WaveShaper(function(t){return t<=0?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(14),n(66),n(18),n(12)],void 0===(o=function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var n=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=n.time,this.isUndef(n.offset)||(this.ticks=n.offset),this.emit("start",n.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",n.time)):e===o.State.Paused&&this.emit("pause",n.time)}var i=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(i),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}.apply(e,i))||(t.exports=o)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var n=i(1),e=i(29),r=i(6).noteToFreq;p5.MonoSynth=function(){e.call(this),this.oscillator=new p5.Oscillator,this.env=new p5.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),n.soundArray.push(this)},p5.MonoSynth.prototype=Object.create(p5.AudioVoice.prototype),p5.MonoSynth.prototype.play=function(t,e,n,i){this.triggerAttack(t,e,~~n),this.triggerRelease(~~n+(i||.15))},p5.MonoSynth.prototype.triggerAttack=function(t,e,n){n=~~n;var i=r(t),o=e||.1;this.oscillator.freq(i,0,n),this.env.ramp(this.output.gain,n,o)},p5.MonoSynth.prototype.triggerRelease=function(t){t=t||0;this.env.ramp(this.output.gain,t,0)},p5.MonoSynth.prototype.setADSR=function(t,e,n,i){this.env.setADSR(t,e,n,i)},Object.defineProperties(p5.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),p5.MonoSynth.prototype.amp=function(t,e){var n=e||0;return void 0!==t&&this.oscillator.amp(t,n),this.oscillator.amp().value},p5.MonoSynth.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},p5.MonoSynth.prototype.dispose=function(){e.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}.call(e,i,e,t))||(t.exports=n)},function(t,e,i){"use strict";var n;void 0===(n=function(){var n=i(1);return p5.AudioVoice=function(){this.ac=n.audiocontext,this.output=this.ac.createGain(),this.connect(),n.soundArray.push(this)},p5.AudioVoice.prototype.play=function(t,e,n,i){},p5.AudioVoice.prototype.triggerAttack=function(t,e,n){},p5.AudioVoice.prototype.triggerRelease=function(t){},p5.AudioVoice.prototype.amp=function(t,e){},p5.AudioVoice.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},p5.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},p5.AudioVoice}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var c=n(1),h=n(14),l=n(6).noteToFreq;p5.PolySynth=function(t,e){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=e||8,this.AudioVoice=void 0===t?p5.MonoSynth:t,this._voicesInUse=new h(0),this.output=c.audiocontext.createGain(),this.connect(),this._allocateVoices(),c.soundArray.push(this)},p5.PolySynth.prototype._allocateVoices=function(){for(var t=0;t= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'},function(t,e,n){"use strict";var i;function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}void 0===(i=function(t){var a=n(1).audiocontext;void 0!==a.createStereoPanner?(p5.Panner=function(t,e){this.stereoPanner=this.input=a.createStereoPanner(),t.connect(this.stereoPanner),this.stereoPanner.connect(e)},p5.Panner.prototype.pan=function(t,e){var n=e||0,i=a.currentTime+n;this.stereoPanner.pan.linearRampToValueAtTime(t,i)},p5.Panner.prototype.inputChannels=function(){},p5.Panner.prototype.connect=function(t){this.stereoPanner.connect(t)},p5.Panner.prototype.disconnect=function(){this.stereoPanner&&this.stereoPanner.disconnect()}):(p5.Panner=function(t,e,n){this.input=a.createGain(),t.connect(this.input),this.left=a.createGain(),this.right=a.createGain(),this.left.channelInterpretation="discrete",this.right.channelInterpretation="discrete",1this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var n=t||0,i=e||void 0;this.isPlaying()&&(this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,n,i))},p5.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},p5.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},p5.SoundFile.prototype.frames=function(){return this.buffer.length},p5.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t=t||5*window.width,this.buffer){for(var e=this.buffer,n=e.length/t,i=~~(n/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;sr[u])&&(r[u]=h)}return r}},p5.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/p.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var n=this.buffer.numberOfChannels,i=0;ie){var r=t[o],s=new c(r,o);n[o]=s,o+=6e3}o++}return n}function m(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+n[s])/2:n[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){t=t||3;var n=[],i={lo:(e=e||15.625)/Math.pow(2,1/(2*t)),ctr:e,hi:e*Math.pow(2,1/(2*t))};n.push(i);for(var o=c.audiocontext.sampleRate/2;i.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,i&&(this._leftFilter.freq(i),this._rightFilter.freq(i))},p5.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},p5.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(1<=t)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},p5.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},p5.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},p5.Delay.prototype.dispose=function(){n.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var p=n(11),e=n(4);p5.Reverb=function(){e.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},p5.Reverb.prototype=Object.create(e.prototype),p5.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},p5.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},p5.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},p5.Reverb.prototype.process=function(t,e,n,i){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),n&&(this._decay=n),i&&(this._reverse=i),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,n){var i=!1;t&&(this._seconds=t,i=!0),e&&(this._decay=e),n&&(this._reverse=n),i&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,n=this.ac.sampleRate,i=n*this._seconds,o=this._decay,r=this.ac.createBuffer(2,i,n),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;e=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}p5.prototype.setBPM=function(t,e){for(var n in o=t,i.parts)i.parts[n]&&i.parts[n].setBPM(t,e)},p5.Phrase=function(t,e,n){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=n},p5.Part=function(t,e){this.length=t||0,this.partStep=0,this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=e||.0625,this.metro=new p5.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(o),i.parts.push(this),this.callback=function(){}},p5.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},p5.Part.prototype.getBPM=function(){return this.metro.getBPM()},p5.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},p5.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},p5.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},p5.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},p5.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},p5.Part.prototype.addPhrase=function(t,e,n){var i;if(3===arguments.length)i=new p5.Phrase(t,e,n);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";i=t}this.phrases.push(i),i.sequence.length>this.length&&(this.length=i.sequence.length)},p5.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},p5.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},p5.Part.prototype.replaceSequence=function(t,e){for(var n in this.phrases)this.phrases[n].name===t&&(this.phrases[n].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStepthis.cutoff&&e>this.threshold&&0 t + ) + this.cancelScheduledValues(t), + this.linearRampToValueAtTime(e, t); + else { + var i = this._searchAfter(t); + i && + (this.cancelScheduledValues(t), + i.type === u.TimelineSignal.Type.Linear + ? this.linearRampToValueAtTime(e, t) + : i.type === u.TimelineSignal.Type.Exponential && + this.exponentialRampToValueAtTime(e, t)), + this.setValueAtTime(e, t); + } + return this; + }), + (u.TimelineSignal.prototype.linearRampToValueBetween = function ( + t, + e, + n + ) { + return ( + this.setRampPoint(e), this.linearRampToValueAtTime(t, n), this + ); + }), + (u.TimelineSignal.prototype.exponentialRampToValueBetween = + function (t, e, n) { + return ( + this.setRampPoint(e), + this.exponentialRampToValueAtTime(t, n), + this + ); + }), + (u.TimelineSignal.prototype._searchBefore = function (t) { + return this._events.get(t); + }), + (u.TimelineSignal.prototype._searchAfter = function (t) { + return this._events.getAfter(t); + }), + (u.TimelineSignal.prototype.getValueAtTime = function (t) { + t = this.toSeconds(t); + var e = this._searchAfter(t), + n = this._searchBefore(t), + i = this._initial; + if (null === n) i = this._initial; + else if (n.type === u.TimelineSignal.Type.Target) { + var o, + r = this._events.getBefore(n.time); + (o = null === r ? this._initial : r.value), + (i = this._exponentialApproach( + n.time, + o, + n.value, + n.constant, + t + )); + } else + i = + n.type === u.TimelineSignal.Type.Curve + ? this._curveInterpolate(n.time, n.value, n.duration, t) + : null === e + ? n.value + : e.type === u.TimelineSignal.Type.Linear + ? this._linearInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : e.type === u.TimelineSignal.Type.Exponential + ? this._exponentialInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : n.value; + return i; + }), + (u.TimelineSignal.prototype.connect = + u.SignalBase.prototype.connect), + (u.TimelineSignal.prototype._exponentialApproach = function ( + t, + e, + n, + i, + o + ) { + return n + (e - n) * Math.exp(-(o - t) / i); + }), + (u.TimelineSignal.prototype._linearInterpolate = function ( + t, + e, + n, + i, + o + ) { + return e + ((o - t) / (n - t)) * (i - e); + }), + (u.TimelineSignal.prototype._exponentialInterpolate = function ( + t, + e, + n, + i, + o + ) { + return ( + (e = Math.max(this._minOutput, e)) * + Math.pow(i / e, (o - t) / (n - t)) + ); + }), + (u.TimelineSignal.prototype._curveInterpolate = function ( + t, + e, + n, + i + ) { + var o = e.length; + if (t + n <= i) return e[o - 1]; + if (i <= t) return e[0]; + var r = (i - t) / n, + s = Math.floor((o - 1) * r), + a = Math.ceil((o - 1) * r), + u = e[s], + p = e[a]; + return a === s + ? u + : this._linearInterpolate(s, u, a, p, r * (o - 1)); + }), + (u.TimelineSignal.prototype.dispose = function () { + u.Signal.prototype.dispose.call(this), + u.Param.prototype.dispose.call(this), + this._events.dispose(), + (this._events = null); + }), + u.TimelineSignal + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(4); + return ( + (p5.Filter = function (t) { + e.call(this), + (this.biquad = this.ac.createBiquadFilter()), + this.input.connect(this.biquad), + this.biquad.connect(this.wet), + t && this.setType(t), + (this._on = !0), + (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype = Object.create(e.prototype)), + (p5.Filter.prototype.process = function (t, e, n, i) { + t.connect(this.input), this.set(e, n, i); + }), + (p5.Filter.prototype.set = function (t, e, n) { + t && this.freq(t, n), e && this.res(e, n); + }), + (p5.Filter.prototype.freq = function (t, e) { + var n = e || 0; + return ( + t <= 0 && (t = 1), + "number" == typeof t + ? (this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.frequency.exponentialRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.frequency), + this.biquad.frequency.value + ); + }), + (p5.Filter.prototype.res = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.Q.value = t), + this.biquad.Q.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.Q.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.Q), + this.biquad.Q.value + ); + }), + (p5.Filter.prototype.gain = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.gain.value = t), + this.biquad.gain.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.gain.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.gain), + this.biquad.gain.value + ); + }), + (p5.Filter.prototype.toggle = function () { + return ( + (this._on = !this._on), + !0 === this._on + ? (this.biquad.type = this._untoggledType) + : !1 === this._on && (this.biquad.type = "allpass"), + this._on + ); + }), + (p5.Filter.prototype.setType = function (t) { + (this.biquad.type = t), (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.biquad && (this.biquad.disconnect(), delete this.biquad); + }), + (p5.LowPass = function () { + p5.Filter.call(this, "lowpass"); + }), + (p5.LowPass.prototype = Object.create(p5.Filter.prototype)), + (p5.HighPass = function () { + p5.Filter.call(this, "highpass"); + }), + (p5.HighPass.prototype = Object.create(p5.Filter.prototype)), + (p5.BandPass = function () { + p5.Filter.call(this, "bandpass"); + }), + (p5.BandPass.prototype = Object.create(p5.Filter.prototype)), + p5.Filter + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(7), n(25), n(2), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Subtract = function (t) { + this.createInsOuts(2, 0), + (this._sum = this.input[0] = this.output = new e.Gain()), + (this._neg = new e.Negate()), + (this._param = this.input[1] = new e.Signal(t)), + this._param.chain(this._neg, this._sum); + }), + e.extend(e.Subtract, e.Signal), + (e.Subtract.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._neg.dispose(), + (this._neg = null), + this._sum.disconnect(), + (this._sum = null), + this._param.dispose(), + (this._param = null), + this + ); + }), + e.Subtract + ); + }.apply(e, i)) || (t.exports = o); + }, + function (i, o, r) { + "use strict"; + (function (t) { + var e, n; + (t.TONE_SILENCE_VERSION_LOGGING = !0), + (e = [r(35), r(12), r(0)]), + void 0 === + (n = function (i, t, e) { + var o = new window.AudioContext(); + return ( + e.context.dispose(), + e.setContext(o), + (p5.prototype.getAudioContext = function () { + return o; + }), + (p5.prototype.userStartAudio = function (t, e) { + var n = t; + return ( + t instanceof p5.Element + ? (n = t.elt) + : t instanceof Array && + t[0] instanceof p5.Element && + (n = t.map(function (t) { + return t.elt; + })), + i(o, n, e) + ); + }), + o + ); + }.apply(o, e)) || (i.exports = n); + }).call(this, r(34)); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (s) { + "use strict"; + return ( + (s.Emitter = function () { + this._events = {}; + }), + s.extend(s.Emitter), + (s.Emitter.prototype.on = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) { + var o = n[i]; + this._events.hasOwnProperty(o) || (this._events[o] = []), + this._events[o].push(e); + } + return this; + }), + (s.Emitter.prototype.off = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) + if (((t = n[i]), this._events.hasOwnProperty(t))) + if (s.prototype.isUndef(e)) this._events[t] = []; + else + for (var o = this._events[t], r = 0; r < o.length; r++) + o[r] === e && o.splice(r, 1); + return this; + }), + (s.Emitter.prototype.emit = function (t) { + if (this._events) { + var e = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(t)) + for (var n = this._events[t], i = 0, o = n.length; i < o; i++) + n[i].apply(this, e); + } + return this; + }), + (s.Emitter.mixin = function (t) { + var e = ["on", "off", "emit"]; + t._events = {}; + for (var n = 0; n < e.length; n++) { + var i = e[n], + o = s.Emitter.prototype[i]; + t[i] = o; + } + }), + (s.Emitter.prototype.dispose = function () { + return ( + s.prototype.dispose.call(this), (this._events = null), this + ); + }), + s.Emitter + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.SignalBase = function () {}), + i.extend(i.SignalBase), + (i.SignalBase.prototype.connect = function (t, e, n) { + return ( + (i.Signal && i.Signal === t.constructor) || + (i.Param && i.Param === t.constructor) || + (i.TimelineSignal && i.TimelineSignal === t.constructor) + ? (t._param.cancelScheduledValues(0), + (t._param.value = 0), + (t.overridden = !0)) + : t instanceof AudioParam && + (t.cancelScheduledValues(0), (t.value = 0)), + i.prototype.connect.call(this, t, e, n), + this + ); + }), + i.SignalBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (n) { + return ( + (n.Time = function (t, e) { + if (!(this instanceof n.Time)) return new n.Time(t, e); + (this._plusNow = !1), n.TimeBase.call(this, t, e); + }), + n.extend(n.Time, n.TimeBase), + (n.Time.prototype._unaryExpressions = Object.create( + n.TimeBase.prototype._unaryExpressions + )), + (n.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + return n.Transport.nextSubdivision(t()); + }, + }), + (n.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (t) { + return (this._plusNow = !0), t(); + }, + }), + (n.Time.prototype.quantize = function (t, e) { + return ( + (e = this.defaultArg(e, 1)), + (this._expr = function (t, e, n) { + return ( + (t = t()), + (e = e.toSeconds()), + t + (Math.round(t / e) * e - t) * n + ); + }.bind(this, this._expr, new this.constructor(t), e)), + this + ); + }), + (n.Time.prototype.addNow = function () { + return (this._plusNow = !0), this; + }), + (n.Time.prototype._defaultExpr = function () { + return (this._plusNow = !0), this._noOp; + }), + (n.Time.prototype.copy = function (t) { + return ( + n.TimeBase.prototype.copy.call(this, t), + (this._plusNow = t._plusNow), + this + ); + }), + (n.Time.prototype.toNotation = function () { + var t = this.toSeconds(), + e = this._toNotationHelper(t, [ + "1m", + "2n", + "4n", + "8n", + "16n", + "32n", + "64n", + "128n", + ]), + n = this._toNotationHelper(t, [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ]); + return n.split("+").length < e.split("+").length ? n : e; + }), + (n.Time.prototype._toNotationHelper = function (t, e) { + for ( + var n = this._notationToUnits(e[e.length - 1]), i = "", o = 0; + o < e.length; + o++ + ) { + var r = this._notationToUnits(e[o]), + s = t / r; + if ( + (1 - (s % 1) < 1e-6 && (s += 1e-6), 0 < (s = Math.floor(s))) + ) { + if ( + ((i += 1 === s ? e[o] : s.toString() + "*" + e[o]), + (t -= s * r) < n) + ) + break; + i += " + "; + } + } + return "" === i && (i = "0"), i; + }), + (n.Time.prototype._notationToUnits = function (t) { + for ( + var e = this._primaryExpressions, n = [e.n, e.t, e.m], i = 0; + i < n.length; + i++ + ) { + var o = n[i], + r = t.match(o.regexp); + if (r) return o.method.call(this, r[1]); + } + }), + (n.Time.prototype.toBarsBeatsSixteenths = function () { + var t = this._beatsToUnits(1), + e = this.toSeconds() / t, + n = Math.floor(e / this._timeSignature()), + i = (e % 1) * 4; + return ( + (e = Math.floor(e) % this._timeSignature()), + 3 < (i = i.toString()).length && (i = parseFloat(i).toFixed(3)), + [n, e, i].join(":") + ); + }), + (n.Time.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * n.Transport.PPQ); + }), + (n.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }), + (n.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + (n.Time.prototype.toSeconds = function () { + return this.valueOf(); + }), + (n.Time.prototype.toMilliseconds = function () { + return 1e3 * this.toSeconds(); + }), + (n.Time.prototype.valueOf = function () { + return this._expr() + (this._plusNow ? this.now() : 0); + }), + n.Time + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + return ( + (i.TimeBase = function (t, e) { + if (!(this instanceof i.TimeBase)) return new i.TimeBase(t, e); + if (((this._expr = this._noOp), t instanceof i.TimeBase)) + this.copy(t); + else if (!this.isUndef(e) || this.isNumber(t)) { + e = this.defaultArg(e, this._defaultUnits); + var n = this._primaryExpressions[e].method; + this._expr = n.bind(this, t); + } else + this.isString(t) + ? this.set(t) + : this.isUndef(t) && (this._expr = this._defaultExpr()); + }), + i.extend(i.TimeBase), + (i.TimeBase.prototype.set = function (t) { + return (this._expr = this._parseExprString(t)), this; + }), + (i.TimeBase.prototype.clone = function () { + var t = new this.constructor(); + return t.copy(this), t; + }), + (i.TimeBase.prototype.copy = function (t) { + var e = t._expr(); + return this.set(e); + }), + (i.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (t) { + return 1 === (t = parseInt(t)) + ? this._beatsToUnits(this._timeSignature()) + : this._beatsToUnits(4 / t); + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (t) { + return ( + (t = parseInt(t)), this._beatsToUnits(8 / (3 * parseInt(t))) + ); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (t) { + return this._beatsToUnits( + parseInt(t) * this._timeSignature() + ); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (t) { + return this._ticksToUnits(parseInt(t)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (t) { + return this._frequencyToUnits(parseFloat(t)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 0; + return ( + t && + "0" !== t && + (i += this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i += this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i += this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (t) { + return this._secondsToUnits(parseFloat(t)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (t) { + return parseInt(t) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (t) { + return this._primaryExpressions[ + this._defaultUnits + ].method.call(this, t); + }, + }, + }), + (i.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (t, e) { + return t() + e(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (t, e) { + return t() - e(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (t, e) { + return t() * e(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (t, e) { + return t() / e(); + }, + }, + }), + (i.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (t) { + return -t(); + }, + }, + }), + (i.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }), + (i.TimeBase.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim()), this); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t, e) { + for ( + var n = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ], + i = 0; + i < n.length; + i++ + ) { + var o = e[n[i]]; + for (var r in o) { + var s = o[r], + a = s.regexp, + u = t.match(a); + if (null !== u) + return { + method: s.method, + precedence: s.precedence, + regexp: s.regexp, + value: u[0], + }; + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (i.TimeBase.prototype._matchGroup = function (t, e, n) { + if (!this.isUndef(t)) + for (var i in e) { + var o = e[i]; + if (o.regexp.test(t.value)) { + if (this.isUndef(n)) return o; + if (o.precedence === n) return o; + } + } + return !1; + }), + (i.TimeBase.prototype._parseBinary = function (t, e) { + var n; + this.isUndef(e) && (e = 2), + (n = e < 0 ? this._parseUnary(t) : this._parseBinary(t, e - 1)); + for ( + var i = t.peek(); + i && this._matchGroup(i, this._binaryExpressions, e); + + ) + (n = (i = t.next()).method.bind( + this, + n, + this._parseBinary(t, e - 1) + )), + (i = t.peek()); + return n; + }), + (i.TimeBase.prototype._parseUnary = function (t) { + var e, n; + e = t.peek(); + var i = this._matchGroup(e, this._unaryExpressions); + return i + ? ((e = t.next()), + (n = this._parseUnary(t)), + i.method.bind(this, n)) + : this._parsePrimary(t); + }), + (i.TimeBase.prototype._parsePrimary = function (t) { + var e, n; + if (((e = t.peek()), this.isUndef(e))) + throw new SyntaxError( + "Tone.TimeBase: Unexpected end of expression" + ); + if (this._matchGroup(e, this._primaryExpressions)) { + var i = (e = t.next()).value.match(e.regexp); + return e.method.bind(this, i[1], i[2], i[3]); + } + if (e && "(" === e.value) { + if ( + (t.next(), + (n = this._parseBinary(t)), + !(e = t.next()) || ")" !== e.value) + ) + throw new SyntaxError("Expected )"); + return n; + } + throw new SyntaxError( + "Tone.TimeBase: Cannot process token " + e.value + ); + }), + (i.TimeBase.prototype._parseExprString = function (t) { + this.isString(t) || (t = t.toString()); + var e = this._tokenize(t); + return this._parseBinary(e); + }), + (i.TimeBase.prototype._noOp = function () { + return 0; + }), + (i.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }), + (i.TimeBase.prototype._defaultUnits = "s"), + (i.TimeBase.prototype._frequencyToUnits = function (t) { + return 1 / t; + }), + (i.TimeBase.prototype._beatsToUnits = function (t) { + return (60 / i.Transport.bpm.value) * t; + }), + (i.TimeBase.prototype._secondsToUnits = function (t) { + return t; + }), + (i.TimeBase.prototype._ticksToUnits = function (t) { + return t * (this._beatsToUnits(1) / i.Transport.PPQ); + }), + (i.TimeBase.prototype._timeSignature = function () { + return i.Transport.timeSignature; + }), + (i.TimeBase.prototype._pushExpr = function (t, e, n) { + return ( + t instanceof i.TimeBase || (t = new this.constructor(t, n)), + (this._expr = this._binaryExpressions[e].method.bind( + this, + this._expr, + t._expr + )), + this + ); + }), + (i.TimeBase.prototype.add = function (t, e) { + return this._pushExpr(t, "+", e); + }), + (i.TimeBase.prototype.sub = function (t, e) { + return this._pushExpr(t, "-", e); + }), + (i.TimeBase.prototype.mult = function (t, e) { + return this._pushExpr(t, "*", e); + }), + (i.TimeBase.prototype.div = function (t, e) { + return this._pushExpr(t, "/", e); + }), + (i.TimeBase.prototype.valueOf = function () { + return this._expr(); + }), + (i.TimeBase.prototype.dispose = function () { + this._expr = null; + }), + i.TimeBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.Param = function () { + var t = this.optionsObject( + arguments, + ["param", "units", "convert"], + i.Param.defaults + ); + (this._param = this.input = t.param), + (this.units = t.units), + (this.convert = t.convert), + (this.overridden = !1), + (this._lfo = null), + this.isObject(t.lfo) + ? (this.value = t.lfo) + : this.isUndef(t.value) || (this.value = t.value); + }), + i.extend(i.Param), + (i.Param.defaults = { + units: i.Type.Default, + convert: !0, + param: void 0, + }), + Object.defineProperty(i.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (t) { + if (this.isObject(t)) { + if (this.isUndef(i.LFO)) + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + this._lfo && this._lfo.dispose(), + (this._lfo = new i.LFO(t).start()), + this._lfo.connect(this.input); + } else { + var e = this._fromUnits(t); + this._param.cancelScheduledValues(0), (this._param.value = e); + } + }, + }), + (i.Param.prototype._fromUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Time: + return this.toSeconds(t); + case i.Type.Frequency: + return this.toFrequency(t); + case i.Type.Decibels: + return this.dbToGain(t); + case i.Type.NormalRange: + return Math.min(Math.max(t, 0), 1); + case i.Type.AudioRange: + return Math.min(Math.max(t, -1), 1); + case i.Type.Positive: + return Math.max(t, 0); + default: + return t; + } + }), + (i.Param.prototype._toUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Decibels: + return this.gainToDb(t); + default: + return t; + } + }), + (i.Param.prototype._minOutput = 1e-5), + (i.Param.prototype.setValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (e = this.toSeconds(e)) <= this.now() + this.blockTime + ? (this._param.value = t) + : this._param.setValueAtTime(t, e), + this + ); + }), + (i.Param.prototype.setRampPoint = function (t) { + t = this.defaultArg(t, this.now()); + var e = this._param.value; + return ( + 0 === e && (e = this._minOutput), + this._param.setValueAtTime(e, t), + this + ); + }), + (i.Param.prototype.linearRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + this._param.linearRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + this._param.exponentialRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.exponentialRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.linearRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.linearRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.setTargetAtTime = function (t, e, n) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + (n = Math.max(this._minOutput, n)), + this._param.setTargetAtTime(t, this.toSeconds(e), n), + this + ); + }), + (i.Param.prototype.setValueCurveAtTime = function (t, e, n) { + for (var i = 0; i < t.length; i++) t[i] = this._fromUnits(t[i]); + return ( + this._param.setValueCurveAtTime( + t, + this.toSeconds(e), + this.toSeconds(n) + ), + this + ); + }), + (i.Param.prototype.cancelScheduledValues = function (t) { + return this._param.cancelScheduledValues(this.toSeconds(t)), this; + }), + (i.Param.prototype.rampTo = function (t, e, n) { + return ( + (e = this.defaultArg(e, 0)), + this.units === i.Type.Frequency || + this.units === i.Type.BPM || + this.units === i.Type.Decibels + ? this.exponentialRampToValue(t, e, n) + : this.linearRampToValue(t, e, n), + this + ); + }), + Object.defineProperty(i.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, + }), + (i.Param.prototype.dispose = function () { + return ( + i.prototype.dispose.call(this), + (this._param = null), + this._lfo && (this._lfo.dispose(), (this._lfo = null)), + this + ); + }), + i.Param + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1), + o = n(7), + r = n(3), + p = n(13); + (p5.Oscillator = function (t, e) { + if ("string" == typeof t) { + var n = e; + (e = t), (t = n); + } + if ("number" == typeof e) { + n = e; + (e = t), (t = n); + } + (this.started = !1), + (this.phaseAmount = void 0), + (this.oscillator = s.audiocontext.createOscillator()), + (this.f = t || 440), + (this.oscillator.type = e || "sine"), + this.oscillator.frequency.setValueAtTime( + this.f, + s.audiocontext.currentTime + ), + (this.output = s.audiocontext.createGain()), + (this._freqMods = []), + (this.output.gain.value = 0.5), + this.output.gain.setValueAtTime(0.5, s.audiocontext.currentTime), + this.oscillator.connect(this.output), + (this.panPosition = 0), + (this.connection = s.input), + (this.panner = new p5.Panner(this.output, this.connection, 1)), + (this.mathOps = [this.output]), + s.soundArray.push(this); + }), + (p5.Oscillator.prototype.start = function (t, e) { + if (this.started) { + var n = s.audiocontext.currentTime; + this.stop(n); + } + if (!this.started) { + var i = e || this.f, + o = this.oscillator.type; + for (var r in (this.oscillator && + (this.oscillator.disconnect(), delete this.oscillator), + (this.oscillator = s.audiocontext.createOscillator()), + (this.oscillator.frequency.value = Math.abs(i)), + (this.oscillator.type = o), + this.oscillator.connect(this.output), + (t = t || 0), + this.oscillator.start(t + s.audiocontext.currentTime), + (this.freqNode = this.oscillator.frequency), + this._freqMods)) + void 0 !== this._freqMods[r].connect && + this._freqMods[r].connect(this.oscillator.frequency); + this.started = !0; + } + }), + (p5.Oscillator.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), (this.started = !1); + } + }), + (p5.Oscillator.prototype.amp = function (t, e, n) { + if ("number" == typeof t) { + (e = e || 0), (n = n || 0); + var i = s.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime(t, i + n + e); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp), + (p5.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }), + (p5.Oscillator.prototype.freq = function (t, e, n) { + if ("number" != typeof t || isNaN(t)) { + if (!t) return this.oscillator.frequency; + t.output && (t = t.output), + t.connect(this.oscillator.frequency), + this._freqMods.push(t); + } else { + this.f = t; + var i = s.audiocontext.currentTime; + (n = n || 0), (e = e || 0); + 0 === e + ? this.oscillator.frequency.setValueAtTime(t, n + i) + : 0 < t + ? this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ) + : this.oscillator.frequency.linearRampToValueAtTime( + t, + n + e + i + ), + this.phaseAmount && this.phase(this.phaseAmount); + } + }), + (p5.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }), + (p5.Oscillator.prototype.setType = function (t) { + this.oscillator.type = t; + }), + (p5.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }), + (p5.Oscillator.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? (this.panner.connect(t.input), (this.connection = t.input)) + : (this.panner.connect(t), (this.connection = t)) + : this.panner.connect(s.input); + }), + (p5.Oscillator.prototype.disconnect = function () { + this.output && this.output.disconnect(), + this.panner && + (this.panner.disconnect(), + this.output && this.output.connect(this.panner)), + (this.oscMods = []); + }), + (p5.Oscillator.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.Oscillator.prototype.getPan = function () { + return this.panPosition; + }), + (p5.Oscillator.prototype.dispose = function () { + var t = s.soundArray.indexOf(this); + if ((s.soundArray.splice(t, 1), this.oscillator)) { + var e = s.audiocontext.currentTime; + this.stop(e), + this.disconnect(), + (this.panner = null), + (this.oscillator = null); + } + this.osc2 && this.osc2.dispose(); + }), + (p5.Oscillator.prototype.phase = function (t) { + var e = p5.prototype.map(t, 0, 1, 0, 1 / this.f), + n = s.audiocontext.currentTime; + (this.phaseAmount = t), + this.dNode || + ((this.dNode = s.audiocontext.createDelay()), + this.oscillator.disconnect(), + this.oscillator.connect(this.dNode), + this.dNode.connect(this.output)), + this.dNode.delayTime.setValueAtTime(e, n); + }); + function c(t, e, n, i, o) { + var r = t.oscillator; + for (var s in t.mathOps) + t.mathOps[s] instanceof o && + (r.disconnect(), + t.mathOps[s].dispose(), + (n = s) < t.mathOps.length - 2 && (i = t.mathOps[s + 1])); + return ( + n === t.mathOps.length - 1 && t.mathOps.push(i), + 0 < s && (r = t.mathOps[s - 1]), + r.disconnect(), + r.connect(e), + e.connect(i), + (t.mathOps[n] = e), + t + ); + } + (p5.Oscillator.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, o); + }), + (p5.Oscillator.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, r); + }), + (p5.Oscillator.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new p(o, r), + a = this.mathOps.length - 1, + u = this.output; + return c(this, s, a, u, p); + }), + (p5.SinOsc = function (t) { + p5.Oscillator.call(this, t, "sine"); + }), + (p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.TriOsc = function (t) { + p5.Oscillator.call(this, t, "triangle"); + }), + (p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SawOsc = function (t) { + p5.Oscillator.call(this, t, "sawtooth"); + }), + (p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SqrOsc = function (t) { + p5.Oscillator.call(this, t, "square"); + }), + (p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Timeline = function () { + var t = this.optionsObject( + arguments, + ["memory"], + e.Timeline.defaults + ); + (this._timeline = []), + (this._toRemove = []), + (this._iterating = !1), + (this.memory = t.memory); + }), + e.extend(e.Timeline), + (e.Timeline.defaults = { memory: 1 / 0 }), + Object.defineProperty(e.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }), + (e.Timeline.prototype.add = function (t) { + if (this.isUndef(t.time)) + throw new Error( + "Tone.Timeline: events must have a time attribute" + ); + if (this._timeline.length) { + var e = this._search(t.time); + this._timeline.splice(e + 1, 0, t); + } else this._timeline.push(t); + if (this.length > this.memory) { + var n = this.length - this.memory; + this._timeline.splice(0, n); + } + return this; + }), + (e.Timeline.prototype.remove = function (t) { + if (this._iterating) this._toRemove.push(t); + else { + var e = this._timeline.indexOf(t); + -1 !== e && this._timeline.splice(e, 1); + } + return this; + }), + (e.Timeline.prototype.get = function (t) { + var e = this._search(t); + return -1 !== e ? this._timeline[e] : null; + }), + (e.Timeline.prototype.peek = function () { + return this._timeline[0]; + }), + (e.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }), + (e.Timeline.prototype.getAfter = function (t) { + var e = this._search(t); + return e + 1 < this._timeline.length + ? this._timeline[e + 1] + : null; + }), + (e.Timeline.prototype.getBefore = function (t) { + var e = this._timeline.length; + if (0 < e && this._timeline[e - 1].time < t) + return this._timeline[e - 1]; + var n = this._search(t); + return 0 <= n - 1 ? this._timeline[n - 1] : null; + }), + (e.Timeline.prototype.cancel = function (t) { + if (1 < this._timeline.length) { + var e = this._search(t); + if (0 <= e) + if (this._timeline[e].time === t) { + for (var n = e; 0 <= n && this._timeline[n].time === t; n--) + e = n; + this._timeline = this._timeline.slice(0, e); + } else this._timeline = this._timeline.slice(0, e + 1); + else this._timeline = []; + } else + 1 === this._timeline.length && + this._timeline[0].time >= t && + (this._timeline = []); + return this; + }), + (e.Timeline.prototype.cancelBefore = function (t) { + if (this._timeline.length) { + var e = this._search(t); + 0 <= e && (this._timeline = this._timeline.slice(e + 1)); + } + return this; + }), + (e.Timeline.prototype._search = function (t) { + var e = 0, + n = this._timeline.length, + i = n; + if (0 < n && this._timeline[n - 1].time <= t) return n - 1; + for (; e < i; ) { + var o = Math.floor(e + (i - e) / 2), + r = this._timeline[o], + s = this._timeline[o + 1]; + if (r.time === t) { + for (var a = o; a < this._timeline.length; a++) + this._timeline[a].time === t && (o = a); + return o; + } + if (r.time < t && s.time > t) return o; + r.time > t ? (i = o) : r.time < t && (e = o + 1); + } + return -1; + }), + (e.Timeline.prototype._iterate = function (t, e, n) { + (this._iterating = !0), + (e = this.defaultArg(e, 0)), + (n = this.defaultArg(n, this._timeline.length - 1)); + for (var i = e; i <= n; i++) t(this._timeline[i]); + if (((this._iterating = !1), 0 < this._toRemove.length)) { + for (var o = 0; o < this._toRemove.length; o++) { + var r = this._timeline.indexOf(this._toRemove[o]); + -1 !== r && this._timeline.splice(r, 1); + } + this._toRemove = []; + } + }), + (e.Timeline.prototype.forEach = function (t) { + return this._iterate(t), this; + }), + (e.Timeline.prototype.forEachBefore = function (t, e) { + var n = this._search(t); + return -1 !== n && this._iterate(e, 0, n), this; + }), + (e.Timeline.prototype.forEachAfter = function (t, e) { + var n = this._search(t); + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachFrom = function (t, e) { + for ( + var n = this._search(t); + 0 <= n && this._timeline[n].time >= t; + + ) + n--; + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachAtTime = function (e, n) { + var t = this._search(e); + return ( + -1 !== t && + this._iterate( + function (t) { + t.time === e && n(t); + }, + 0, + t + ), + this + ); + }), + (e.Timeline.prototype.dispose = function () { + e.prototype.dispose.call(this), + (this._timeline = null), + (this._toRemove = null); + }), + e.Timeline + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(3), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Negate = function () { + this._multiply = this.input = this.output = new t.Multiply(-1); + }), + t.extend(t.Negate, t.SignalBase), + (t.Negate.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._multiply.dispose(), + (this._multiply = null), + this + ); + }), + t.Negate + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(3), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.GreaterThanZero = function () { + (this._thresh = this.output = + new t.WaveShaper(function (t) { + return t <= 0 ? 0 : 1; + }, 127)), + (this._scale = this.input = new t.Multiply(1e4)), + this._scale.connect(this._thresh); + }), + t.extend(t.GreaterThanZero, t.SignalBase), + (t.GreaterThanZero.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._scale.dispose(), + (this._scale = null), + this._thresh.dispose(), + (this._thresh = null), + this + ); + }), + t.GreaterThanZero + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(14), n(66), n(18), n(12)]), + void 0 === + (o = function (o) { + "use strict"; + return ( + (o.Clock = function () { + o.Emitter.call(this); + var t = this.optionsObject( + arguments, + ["callback", "frequency"], + o.Clock.defaults + ); + (this.callback = t.callback), + (this._nextTick = 0), + (this._lastState = o.State.Stopped), + (this.frequency = new o.TimelineSignal( + t.frequency, + o.Type.Frequency + )), + this._readOnly("frequency"), + (this.ticks = 0), + (this._state = new o.TimelineState(o.State.Stopped)), + (this._boundLoop = this._loop.bind(this)), + this.context.on("tick", this._boundLoop); + }), + o.extend(o.Clock, o.Emitter), + (o.Clock.defaults = { + callback: o.noOp, + frequency: 1, + lookAhead: "auto", + }), + Object.defineProperty(o.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }), + (o.Clock.prototype.start = function (t, e) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) !== o.State.Started && + this._state.add({ + state: o.State.Started, + time: t, + offset: e, + }), + this + ); + }), + (o.Clock.prototype.stop = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.cancel(t), + this._state.setStateAtTime(o.State.Stopped, t), + this + ); + }), + (o.Clock.prototype.pause = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) === o.State.Started && + this._state.setStateAtTime(o.State.Paused, t), + this + ); + }), + (o.Clock.prototype._loop = function () { + for ( + var t = + this.now() + + this.context.lookAhead + + this.context.updateInterval + + 2 * this.context.lag; + t > this._nextTick && this._state; + + ) { + var e = this._state.getValueAtTime(this._nextTick); + if (e !== this._lastState) { + this._lastState = e; + var n = this._state.get(this._nextTick); + e === o.State.Started + ? ((this._nextTick = n.time), + this.isUndef(n.offset) || (this.ticks = n.offset), + this.emit("start", n.time, this.ticks)) + : e === o.State.Stopped + ? ((this.ticks = 0), this.emit("stop", n.time)) + : e === o.State.Paused && this.emit("pause", n.time); + } + var i = this._nextTick; + this.frequency && + ((this._nextTick += + 1 / this.frequency.getValueAtTime(this._nextTick)), + e === o.State.Started && (this.callback(i), this.ticks++)); + } + }), + (o.Clock.prototype.getStateAtTime = function (t) { + return (t = this.toSeconds(t)), this._state.getValueAtTime(t); + }), + (o.Clock.prototype.dispose = function () { + o.Emitter.prototype.dispose.call(this), + this.context.off("tick", this._boundLoop), + this._writable("frequency"), + this.frequency.dispose(), + (this.frequency = null), + (this._boundLoop = null), + (this._nextTick = 1 / 0), + (this.callback = null), + this._state.dispose(), + (this._state = null); + }), + o.Clock + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = i(1), + e = i(29), + r = i(6).noteToFreq; + (p5.MonoSynth = function () { + e.call(this), + (this.oscillator = new p5.Oscillator()), + (this.env = new p5.Envelope()), + this.env.setRange(1, 0), + this.env.setExp(!0), + this.setADSR(0.02, 0.25, 0.05, 0.35), + this.oscillator.disconnect(), + this.oscillator.connect(this.output), + this.env.disconnect(), + this.env.setInput(this.output.gain), + (this.oscillator.output.gain.value = 1), + this.oscillator.start(), + this.connect(), + n.soundArray.push(this); + }), + (p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype)), + (p5.MonoSynth.prototype.play = function (t, e, n, i) { + this.triggerAttack(t, e, ~~n), + this.triggerRelease(~~n + (i || 0.15)); + }), + (p5.MonoSynth.prototype.triggerAttack = function (t, e, n) { + n = ~~n; + var i = r(t), + o = e || 0.1; + this.oscillator.freq(i, 0, n), + this.env.ramp(this.output.gain, n, o); + }), + (p5.MonoSynth.prototype.triggerRelease = function (t) { + t = t || 0; + this.env.ramp(this.output.gain, t, 0); + }), + (p5.MonoSynth.prototype.setADSR = function (t, e, n, i) { + this.env.setADSR(t, e, n, i); + }), + Object.defineProperties(p5.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (t) { + this.env.setADSR( + t, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, + }, + decay: { + get: function () { + return this.env.dTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + t, + this.env.sPercent, + this.env.rTime + ); + }, + }, + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + t, + this.env.rTime + ); + }, + }, + release: { + get: function () { + return this.env.rTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + t + ); + }, + }, + }), + (p5.MonoSynth.prototype.amp = function (t, e) { + var n = e || 0; + return ( + void 0 !== t && this.oscillator.amp(t, n), + this.oscillator.amp().value + ); + }), + (p5.MonoSynth.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.MonoSynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.MonoSynth.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.env && this.env.dispose(), + this.oscillator && this.oscillator.dispose(); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function () { + var n = i(1); + return ( + (p5.AudioVoice = function () { + (this.ac = n.audiocontext), + (this.output = this.ac.createGain()), + this.connect(), + n.soundArray.push(this); + }), + (p5.AudioVoice.prototype.play = function (t, e, n, i) {}), + (p5.AudioVoice.prototype.triggerAttack = function (t, e, n) {}), + (p5.AudioVoice.prototype.triggerRelease = function (t) {}), + (p5.AudioVoice.prototype.amp = function (t, e) {}), + (p5.AudioVoice.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.AudioVoice.prototype.disconnect = function () { + this.output.disconnect(); + }), + (p5.AudioVoice.prototype.dispose = function () { + this.output && (this.output.disconnect(), delete this.output); + }), + p5.AudioVoice + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var c = n(1), + h = n(14), + l = n(6).noteToFreq; + (p5.PolySynth = function (t, e) { + (this.audiovoices = []), + (this.notes = {}), + (this._newest = 0), + (this._oldest = 0), + (this.maxVoices = e || 8), + (this.AudioVoice = void 0 === t ? p5.MonoSynth : t), + (this._voicesInUse = new h(0)), + (this.output = c.audiocontext.createGain()), + this.connect(), + this._allocateVoices(), + c.soundArray.push(this); + }), + (p5.PolySynth.prototype._allocateVoices = function () { + for (var t = 0; t < this.maxVoices; t++) + this.audiovoices.push(new this.AudioVoice()), + this.audiovoices[t].disconnect(), + this.audiovoices[t].connect(this.output); + }), + (p5.PolySynth.prototype.play = function (t, e, n, i) { + i = i || 1; + this.noteAttack(t, e, n), this.noteRelease(t, n + i); + }), + (p5.PolySynth.prototype.noteADSR = function (t, e, n, i, o, r) { + var s = c.audiocontext.currentTime + (r = r || 0); + this.audiovoices[this.notes[t].getValueAtTime(s)].setADSR( + e, + n, + i, + o + ); + }), + (p5.PolySynth.prototype.setADSR = function (e, n, i, o) { + this.audiovoices.forEach(function (t) { + t.setADSR(e, n, i, o); + }); + }), + (p5.PolySynth.prototype.noteAttack = function (t, e, n) { + n = ~~n; + var i, + o = c.audiocontext.currentTime + n, + r = l(t), + s = e || 0.1; + if ( + (this.notes[r] && + null !== this.notes[r].getValueAtTime(o) && + this.noteRelease(r, 0), + this._voicesInUse.getValueAtTime(o) < this.maxVoices) + ) + i = Math.max(~~this._voicesInUse.getValueAtTime(o), 0); + else { + i = this._oldest; + var a = p5.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(a), + (this._oldest = (this._oldest + 1) % (this.maxVoices - 1)); + } + (this.notes[r] = new h()), this.notes[r].setValueAtTime(i, o); + var u = + null === this._voicesInUse._searchBefore(o) + ? 0 + : this._voicesInUse._searchBefore(o).value; + if ( + (this._voicesInUse.setValueAtTime(u + 1, o), + this._updateAfter(o, 1), + (this._newest = i), + "number" == typeof s) + ) { + var p = (1 / this._voicesInUse.getValueAtTime(o)) * 2; + s = p < s ? p : s; + } + this.audiovoices[i].triggerAttack(r, s, n); + }), + (p5.PolySynth.prototype._updateAfter = function (t, e) { + if (null !== this._voicesInUse._searchAfter(t)) { + this._voicesInUse._searchAfter(t).value += e; + var n = this._voicesInUse._searchAfter(t).time; + this._updateAfter(n, e); + } + }), + (p5.PolySynth.prototype.noteRelease = function (t, e) { + var n = c.audiocontext.currentTime, + i = e || 0, + o = n + i; + if (t) { + var r = l(t); + if (this.notes[r] && null !== this.notes[r].getValueAtTime(o)) { + var s = Math.max( + ~~this._voicesInUse.getValueAtTime(o).value, + 1 + ); + this._voicesInUse.setValueAtTime(s - 1, o), + 0 < s && this._updateAfter(o, -1), + this.audiovoices[ + this.notes[r].getValueAtTime(o) + ].triggerRelease(i), + this.notes[r].dispose(), + delete this.notes[r], + (this._newest = + 0 === this._newest + ? 0 + : (this._newest - 1) % (this.maxVoices - 1)); + } else; + } else + for (var a in (this.audiovoices.forEach(function (t) { + t.triggerRelease(i); + }), + this._voicesInUse.setValueAtTime(0, o), + this.notes)) + this.notes[a].dispose(), delete this.notes[a]; + }), + (p5.PolySynth.prototype.connect = function (t) { + var e = t || c.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.PolySynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (t) { + t.dispose(); + }), + this.output && (this.output.disconnect(), delete this.output); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(32), n(33), n(17); + var e = n(1); + return ( + n(6), + n(11), + n(36), + n(40), + n(41), + n(42), + n(43), + n(44), + n(23), + n(47), + n(48), + n(49), + n(50), + n(15), + n(59), + n(61), + n(62), + n(63), + n(64), + n(65), + n(67), + n(68), + n(69), + n(70), + n(71), + n(72), + n(28), + n(30), + n(73), + n(29), + n(28), + n(30), + e + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + function c(t) { + var i = this, + o = {}, + r = -1; + this.parameters.forEach(function (t, e) { + var n = a[++r] || (a[r] = new Float32Array(i.bufferSize)); + n.fill(t.value), (o[e] = n); + }), + this.processor.realm.exec( + "self.sampleRate=sampleRate=" + + this.context.sampleRate + + ";self.currentTime=currentTime=" + + this.context.currentTime + ); + var e = s(t.inputBuffer), + n = s(t.outputBuffer); + this.instance.process([e], [n], o); + } + function s(t) { + for (var e = [], n = 0; n < t.numberOfChannels; n++) + e[n] = t.getChannelData(n); + return e; + } + function h(t) { + return t.$$processors || (t.$$processors = {}); + } + function n(t) { + this.$$context = t; + } + var l, a; + (a = []), + "function" != typeof AudioWorkletNode && + ((self.AudioWorkletNode = function (t, e, n) { + var i = h(t)[e], + o = t.createScriptProcessor( + void 0, + 2, + n && n.outputChannelCount ? n.outputChannelCount[0] : 2 + ); + if (((o.parameters = new Map()), i.properties)) + for (var r = 0; r < i.properties.length; r++) { + var s = i.properties[r], + a = t.createGain().gain; + (a.value = s.defaultValue), o.parameters.set(s.name, a); + } + var u = new MessageChannel(); + l = u.port2; + var p = new i.Processor(n || {}); + return ( + (l = null), + (o.port = u.port1), + (o.processor = i), + (o.instance = p), + (o.onaudioprocess = c), + o + ); + }), + Object.defineProperty( + (self.AudioContext || self.webkitAudioContext).prototype, + "audioWorklet", + { + get: function () { + return ( + this.$$audioWorklet || + (this.$$audioWorklet = new self.AudioWorklet(this)) + ); + }, + } + ), + (self.AudioWorklet = + ((n.prototype.addModule = function (t, e) { + var o = this; + return fetch(t) + .then(function (t) { + if (!t.ok) throw Error(t.status); + return t.text(); + }) + .then(function (t) { + var n = { + sampleRate: 0, + currentTime: 0, + AudioWorkletProcessor: function () { + this.port = l; + }, + registerProcessor: function (t, e) { + h(o.$$context)[t] = { + realm: i, + context: n, + Processor: e, + properties: e.parameterDescriptors || [], + }; + }, + }, + i = new (function (t, e) { + var n = document.createElement("iframe"); + (n.style.cssText = + "position:absolute;left:0;top:-999px;width:1px;height:1px;"), + e.appendChild(n); + var i = n.contentWindow, + o = i.document, + r = "var window,$hook"; + for (var s in i) + s in t || "eval" === s || ((r += ","), (r += s)); + for (var a in t) + (r += ","), (r += a), (r += "=self."), (r += a); + var u = o.createElement("script"); + u.appendChild( + o.createTextNode( + 'function $hook(self,console) {"use strict";\n ' + + r + + ";return function() {return eval(arguments[0])}}" + ) + ), + o.body.appendChild(u), + (this.exec = i.$hook(t, console)); + })((n.self = n), document.documentElement); + return i.exec(((e && e.transpile) || String)(t)), null; + }); + }), + n))); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + function n(t) { + t && + (t.setTargetAtTime || (t.setTargetAtTime = t.setTargetValueAtTime)); + } + window, + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") && + ((window.AudioContext = window.webkitAudioContext), + "function" != typeof AudioContext.prototype.createGain && + (AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode), + "function" != typeof AudioContext.prototype.createDelay && + (AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode), + "function" != typeof AudioContext.prototype.createScriptProcessor && + (AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode), + "function" != typeof AudioContext.prototype.createPeriodicWave && + (AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable), + (AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain), + (AudioContext.prototype.createGain = function () { + var t = this.internal_createGain(); + return n(t.gain), t; + }), + (AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay), + (AudioContext.prototype.createDelay = function (t) { + var e = t + ? this.internal_createDelay(t) + : this.internal_createDelay(); + return n(e.delayTime), e; + }), + (AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource), + (AudioContext.prototype.createBufferSource = function () { + var i = this.internal_createBufferSource(); + return ( + i.start + ? ((i.internal_start = i.start), + (i.start = function (t, e, n) { + void 0 !== n + ? i.internal_start(t || 0, e, n) + : i.internal_start(t || 0, e || 0); + })) + : (i.start = function (t, e, n) { + e || n + ? this.noteGrainOn(t || 0, e, n) + : this.noteOn(t || 0); + }), + i.stop + ? ((i.internal_stop = i.stop), + (i.stop = function (t) { + i.internal_stop(t || 0); + })) + : (i.stop = function (t) { + this.noteOff(t || 0); + }), + n(i.playbackRate), + i + ); + }), + (AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor), + (AudioContext.prototype.createDynamicsCompressor = function () { + var t = this.internal_createDynamicsCompressor(); + return ( + n(t.threshold), + n(t.knee), + n(t.ratio), + n(t.reduction), + n(t.attack), + n(t.release), + t + ); + }), + (AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter), + (AudioContext.prototype.createBiquadFilter = function () { + var t = this.internal_createBiquadFilter(); + return n(t.frequency), n(t.detune), n(t.Q), n(t.gain), t; + }), + "function" != typeof AudioContext.prototype.createOscillator && + ((AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator), + (AudioContext.prototype.createOscillator = function () { + var e = this.internal_createOscillator(); + return ( + e.start + ? ((e.internal_start = e.start), + (e.start = function (t) { + e.internal_start(t || 0); + })) + : (e.start = function (t) { + this.noteOn(t || 0); + }), + e.stop + ? ((e.internal_stop = e.stop), + (e.stop = function (t) { + e.internal_stop(t || 0); + })) + : (e.stop = function (t) { + this.noteOff(t || 0); + }), + e.setPeriodicWave || (e.setPeriodicWave = e.setWaveTable), + n(e.frequency), + n(e.detune), + e + ); + }))), + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") && + (window.OfflineAudioContext = window.webkitOfflineAudioContext), + (navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia); + var e = document.createElement("audio"); + p5.prototype.isSupported = function () { + return !!e.canPlayType; + }; + p5.prototype.isFileSupported = function (t) { + switch (t.toLowerCase()) { + case "mp3": + return !!e.canPlayType && e.canPlayType("audio/mpeg;"); + case "wav": + return !!e.canPlayType && e.canPlayType('audio/wav; codecs="1"'); + case "ogg": + return ( + !!e.canPlayType && e.canPlayType('audio/ogg; codecs="vorbis"') + ); + case "aac": + case "m4a": + case "mp4": + return ( + !!e.canPlayType && + (e.canPlayType("audio/x-m4a;") || e.canPlayType("audio/aac;")) + ); + case "aif": + case "aiff": + return !!e.canPlayType && e.canPlayType("audio/x-aiff;"); + default: + return !1; + } + }; + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + var n; + n = (function () { + return this; + })(); + try { + n = n || new Function("return this")(); + } catch (t) { + "object" == typeof window && (n = window); + } + t.exports = n; + }, + function (t, e, n) { + var i, o, r; + (o = []), + void 0 === + (r = + "function" == + typeof (i = function () { + var s = function (t, e) { + (this._dragged = !1), + (this._element = t), + (this._bindedMove = this._moved.bind(this)), + (this._bindedEnd = this._ended.bind(this, e)), + t.addEventListener("touchstart", this._bindedEnd), + t.addEventListener("touchmove", this._bindedMove), + t.addEventListener("touchend", this._bindedEnd), + t.addEventListener("mouseup", this._bindedEnd); + }; + function r(t) { + return "running" === t.state; + } + return ( + (s.prototype._moved = function (t) { + this._dragged = !0; + }), + (s.prototype._ended = function (t) { + this._dragged || + (function (t) { + var e = t.createBuffer(1, 1, t.sampleRate), + n = t.createBufferSource(); + (n.buffer = e), + n.connect(t.destination), + n.start(0), + t.resume && t.resume(); + })(t), + (this._dragged = !1); + }), + (s.prototype.dispose = function () { + this._element.removeEventListener( + "touchstart", + this._bindedEnd + ), + this._element.removeEventListener( + "touchmove", + this._bindedMove + ), + this._element.removeEventListener( + "touchend", + this._bindedEnd + ), + this._element.removeEventListener("mouseup", this._bindedEnd), + (this._bindedMove = null), + (this._bindedEnd = null), + (this._element = null); + }), + function (e, t, n) { + var i = new Promise(function (t) { + !(function (e, n) { + r(e) + ? n() + : (function t() { + r(e) + ? n() + : (requestAnimationFrame(t), + e.resume && e.resume()); + })(); + })(e, t); + }), + o = []; + return ( + (function t(e, n, i) { + if (Array.isArray(e) || (NodeList && e instanceof NodeList)) + for (var o = 0; o < e.length; o++) t(e[o], n, i); + else if ("string" == typeof e) + t(document.querySelectorAll(e), n, i); + else if (e.jquery && "function" == typeof e.toArray) + t(e.toArray(), n, i); + else if (Element && e instanceof Element) { + var r = new s(e, i); + n.push(r); + } + })((t = t || document.body), o, e), + i.then(function () { + for (var t = 0; t < o.length; t++) o[t].dispose(); + (o = null), n && n(); + }), + i + ); + } + ); + }) + ? i.apply(e, o) + : i) || (t.exports = r); + }, + function (t, e, n) { + var i = n(1), + o = [n(37).default, n(38).default, n(39).default], + r = i.audiocontext, + s = !1; + p5.prototype.registerMethod("init", function () { + if (!s) { + this.preload || window.preload || (this.preload = function () {}), + this._incrementPreload(); + var t = function () { + (s = !0), this._decrementPreload(); + }.bind(this); + Promise.all( + o.map(function (t) { + var e = new Blob([t], { type: "application/javascript" }), + n = URL.createObjectURL(e); + return r.audioWorklet.addModule(n); + }) + ).then(t); + } + }); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'); + }, + function (t, e, n) { + "use strict"; + var i; + function o(t) { + return (o = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (i = function (t) { + var a = n(1).audiocontext; + void 0 !== a.createStereoPanner + ? ((p5.Panner = function (t, e) { + (this.stereoPanner = this.input = a.createStereoPanner()), + t.connect(this.stereoPanner), + this.stereoPanner.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n; + this.stereoPanner.pan.linearRampToValueAtTime(t, i); + }), + (p5.Panner.prototype.inputChannels = function () {}), + (p5.Panner.prototype.connect = function (t) { + this.stereoPanner.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.stereoPanner && this.stereoPanner.disconnect(); + })) + : ((p5.Panner = function (t, e, n) { + (this.input = a.createGain()), + t.connect(this.input), + (this.left = a.createGain()), + (this.right = a.createGain()), + (this.left.channelInterpretation = "discrete"), + (this.right.channelInterpretation = "discrete"), + 1 < n + ? ((this.splitter = a.createChannelSplitter(2)), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)) + : (this.input.connect(this.left), + this.input.connect(this.right)), + (this.output = a.createChannelMerger(2)), + this.left.connect(this.output, 0, 1), + this.right.connect(this.output, 0, 0), + this.output.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n, + o = (t + 1) / 2, + r = Math.cos((o * Math.PI) / 2), + s = Math.sin((o * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(s, i), + this.right.gain.linearRampToValueAtTime(r, i); + }), + (p5.Panner.prototype.inputChannels = function (t) { + 1 === t + ? (this.input.disconnect(), + this.input.connect(this.left), + this.input.connect(this.right)) + : 2 === t && + (o("undefined" === this.splitter) && + (this.splitter = a.createChannelSplitter(2)), + this.input.disconnect(), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)); + }), + (p5.Panner.prototype.connect = function (t) { + this.output.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.output && this.output.disconnect(); + })); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, o) { + "use strict"; + var n; + function l(t) { + return (l = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (n = function (t) { + var a = o(11), + u = o(1), + p = u.audiocontext, + e = o(6), + n = e.midiToFreq, + i = e.convertToWav, + r = e.safeBufferSize, + s = o(10); + (p5.SoundFile = function (t, e, n, i) { + if (void 0 !== t) { + if ("string" == typeof t || "string" == typeof t[0]) { + var o = p5.prototype._checkFileFormats(t); + this.url = o; + } else if ( + "object" === l(t) && + !( + window.File && + window.FileReader && + window.FileList && + window.Blob + ) + ) + throw "Unable to load file because the File API is not supported"; + t.file && (t = t.file), (this.file = t); + } + (this._onended = function () {}), + (this._looping = !1), + (this._playing = !1), + (this._paused = !1), + (this._pauseTime = 0), + (this._cues = []), + (this._cueIDCounter = 0), + (this._lastPos = 0), + (this._counterNode = null), + (this._workletNode = null), + (this.bufferSourceNodes = []), + (this.bufferSourceNode = null), + (this.buffer = null), + (this.playbackRate = 1), + (this.input = u.audiocontext.createGain()), + (this.output = u.audiocontext.createGain()), + (this.reversed = !1), + (this.startTime = 0), + (this.endTime = null), + (this.pauseTime = 0), + (this.mode = "sustain"), + (this.startMillis = null), + (this.panPosition = 0), + (this.panner = new p5.Panner(this.output, u.input, 2)), + (this.url || this.file) && this.load(e, n), + u.soundArray.push(this), + (this._whileLoading = "function" == typeof i ? i : function () {}), + (this._clearOnEnd = function (t) { + var e = t.target, + n = this; + (e._playing = !1), + e.removeEventListener("ended", n._clearOnEnd), + n._onended(n), + n.bufferSourceNodes + .map(function (t, e) { + return e; + }) + .reverse() + .forEach(function (t) { + !1 === n.bufferSourceNodes[t]._playing && + n.bufferSourceNodes.splice(t, 1); + }), + 0 === n.bufferSourceNodes.length && (n._playing = !1); + }.bind(this)); + }), + p5.prototype.registerPreloadMethod("loadSound", p5.prototype), + (p5.prototype.loadSound = function (t, e, n, i) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var o = this; + return new p5.SoundFile( + t, + function () { + "function" == typeof e && e.apply(o, arguments), + "function" == typeof o._decrementPreload && + o._decrementPreload(); + }, + n, + i + ); + }), + (p5.SoundFile.prototype.load = function (n, i) { + var o = this, + r = new Error().stack; + if (void 0 !== this.url && "" !== this.url) { + var s = new XMLHttpRequest(); + s.addEventListener( + "progress", + function (t) { + o._updateProgress(t); + }, + !1 + ), + s.open("GET", this.url, !0), + (s.responseType = "arraybuffer"), + (s.onload = function () { + if (200 === s.status) { + if (!o.panner) return; + p.decodeAudioData( + s.response, + function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }, + function () { + if (o.panner) { + var t = new a("decodeAudioData", r, o.url), + e = + "AudioContext error at decodeAudioData for " + + o.url; + i && ((t.msg = e), i(t)); + } + } + ); + } else { + if (!o.panner) return; + var t = new a("loadSound", r, o.url), + e = + "Unable to load " + + o.url + + ". The request status was: " + + s.status + + " (" + + s.statusText + + ")"; + i && ((t.message = e), i(t)); + } + }), + (s.onerror = function () { + var t = new a("loadSound", r, o.url), + e = + "There was no response from the server at " + + o.url + + ". Check the url and internet connectivity."; + i && ((t.message = e), i(t)); + }), + s.send(); + } else if (void 0 !== this.file) { + var t = new FileReader(); + (t.onload = function () { + o.panner && + p.decodeAudioData(t.result, function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }); + }), + (t.onerror = function (t) { + o.panner && onerror && onerror(t); + }), + t.readAsArrayBuffer(this.file); + } + }), + (p5.SoundFile.prototype._updateProgress = function (t) { + if (t.lengthComputable) { + var e = (t.loaded / t.total) * 0.99; + this._whileLoading(e, t); + } else this._whileLoading("size unknown"); + }), + (p5.SoundFile.prototype.isLoaded = function () { + return !!this.buffer; + }), + (p5.SoundFile.prototype.play = function (t, e, n, i, o) { + if (this.output) { + var r, + s, + a = t || 0; + if ( + (a < 0 && (a = 0), + (a += u.audiocontext.currentTime), + void 0 !== e && this.rate(e), + void 0 !== n && this.setVolume(n), + !this.buffer) + ) + throw "not ready to play file, buffer has yet to load. Try preload()"; + if ( + ((this._pauseTime = 0), + "restart" === this.mode && + this.buffer && + this.bufferSourceNode && + (this.bufferSourceNode.stop(a), this._counterNode.stop(a)), + "untildone" !== this.mode || !this.isPlaying()) + ) { + if ( + ((this.bufferSourceNode = this._initSourceNode()), + delete this._counterNode, + (this._counterNode = this._initCounterNode()), + i) + ) { + if (!(0 <= i && i < this.buffer.duration)) + throw "start time out of range"; + r = i; + } else r = 0; + (o = + o && + (o <= this.buffer.duration - r ? o : this.buffer.duration)), + this._paused + ? (this.bufferSourceNode.start(a, this.pauseTime, o), + this._counterNode.start(a, this.pauseTime, o)) + : (this.bufferSourceNode.start(a, r, o), + this._counterNode.start(a, r, o)), + (this._playing = !0), + (this._paused = !1), + this.bufferSourceNodes.push(this.bufferSourceNode), + (this.bufferSourceNode._arrayIndex = + this.bufferSourceNodes.length - 1), + this.bufferSourceNode.addEventListener( + "ended", + this._clearOnEnd + ), + (this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping), + !0 === this._looping && + ((s = o || r - 1e-15), + (this.bufferSourceNode.loopStart = r), + (this.bufferSourceNode.loopEnd = s), + (this._counterNode.loopStart = r), + (this._counterNode.loopEnd = s)); + } + } + }), + (p5.SoundFile.prototype.playMode = function (t) { + var e = t.toLowerCase(); + if ("restart" === e && this.buffer && this.bufferSourceNode) + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) { + var i = u.audiocontext.currentTime; + this.bufferSourceNodes[n].stop(i); + } + if ("restart" !== e && "sustain" !== e && "untildone" !== e) + throw 'Invalid play mode. Must be either "restart" or "sustain"'; + this.mode = e; + }), + (p5.SoundFile.prototype.pause = function (t) { + var e = (t || 0) + u.audiocontext.currentTime; + this.isPlaying() && this.buffer && this.bufferSourceNode + ? ((this._paused = !0), + (this._playing = !1), + (this.pauseTime = this.currentTime()), + this.bufferSourceNode.stop(e), + this._counterNode.stop(e), + (this._pauseTime = this.currentTime())) + : (this._pauseTime = 0); + }), + (p5.SoundFile.prototype.loop = function (t, e, n, i, o) { + (this._looping = !0), this.play(t, e, n, i, o); + }), + (p5.SoundFile.prototype.setLoop = function (t) { + if (!0 === t) this._looping = !0; + else { + if (!1 !== t) throw "Error: setLoop accepts either true or false"; + this._looping = !1; + } + this.bufferSourceNode && + ((this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping)); + }), + (p5.SoundFile.prototype.isLooping = function () { + return ( + !!this.bufferSourceNode && + !0 === this._looping && + !0 === this.isPlaying() + ); + }), + (p5.SoundFile.prototype.isPlaying = function () { + return this._playing; + }), + (p5.SoundFile.prototype.isPaused = function () { + return this._paused; + }), + (p5.SoundFile.prototype.stop = function (t) { + var e = t || 0; + if ("sustain" === this.mode || "untildone" === this.mode) + this.stopAll(e), + (this._playing = !1), + (this.pauseTime = 0), + (this._paused = !1); + else if (this.buffer && this.bufferSourceNode) { + var n = u.audiocontext.currentTime, + i = e || 0; + (this.pauseTime = 0), + this.bufferSourceNode.stop(n + i), + this._counterNode.stop(n + i), + (this._playing = !1), + (this._paused = !1); + } + }), + (p5.SoundFile.prototype.stopAll = function (t) { + var e = u.audiocontext.currentTime, + n = t || 0; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + var o = this.bufferSourceNodes[i]; + if (o) + try { + o.stop(e + n); + } catch (t) {} + } + this._counterNode.stop(e + n), this._onended(this); + } + }), + (p5.SoundFile.prototype.setVolume = function (t, e, n) { + if ("number" == typeof t) { + var i = e || 0, + o = n || 0, + r = u.audiocontext.currentTime, + s = this.output.gain.value; + this.output.gain.cancelScheduledValues(r + o), + this.output.gain.linearRampToValueAtTime(s, r + o), + this.output.gain.linearRampToValueAtTime(t, r + o + i); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }), + (p5.SoundFile.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.SoundFile.prototype.getPan = function () { + return this.panPosition; + }), + (p5.SoundFile.prototype.rate = function (t) { + var e = !1; + if (void 0 === t) return this.playbackRate; + if ( + (0 === (this.playbackRate = t) + ? (t = 1e-13) + : t < 0 && !this.reversed + ? ((t = Math.abs(t)), (e = !0)) + : 0 < t && this.reversed && (e = !0), + this.bufferSourceNode) + ) { + var n = u.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(n), + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ), + this._counterNode.playbackRate.cancelScheduledValues(n), + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ); + } + return e && this.reverseBuffer(), this.playbackRate; + }), + (p5.SoundFile.prototype.setPitch = function (t) { + var e = n(t) / n(60); + this.rate(e); + }), + (p5.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }), + (p5.SoundFile.prototype.duration = function () { + return this.buffer ? this.buffer.duration : 0; + }), + (p5.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / p.sampleRate + : this._lastPos / p.sampleRate; + }), + (p5.SoundFile.prototype.jump = function (t, e) { + if (t < 0 || t > this.buffer.duration) + throw "jump time out of range"; + if (e > this.buffer.duration - t) throw "end time out of range"; + var n = t || 0, + i = e || void 0; + this.isPlaying() && + (this.stop(0), + this.play(0, this.playbackRate, this.output.gain.value, n, i)); + }), + (p5.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }), + (p5.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }), + (p5.SoundFile.prototype.frames = function () { + return this.buffer.length; + }), + (p5.SoundFile.prototype.getPeaks = function (t) { + if (!this.buffer) + throw "Cannot load peaks yet, buffer is not loaded"; + if (((t = t || 5 * window.width), this.buffer)) { + for ( + var e = this.buffer, + n = e.length / t, + i = ~~(n / 10) || 1, + o = e.numberOfChannels, + r = new Float32Array(Math.round(t)), + s = 0; + s < o; + s++ + ) + for (var a = e.getChannelData(s), u = 0; u < t; u++) { + for ( + var p = ~~(u * n), c = ~~(p + n), h = 0, l = p; + l < c; + l += i + ) { + var f = a[l]; + h < f ? (h = f) : h < -f && (h = f); + } + (0 === s || Math.abs(h) > r[u]) && (r[u] = h); + } + return r; + } + }), + (p5.SoundFile.prototype.reverseBuffer = function () { + if (!this.buffer) throw "SoundFile is not done loading"; + var t = this._lastPos / p.sampleRate, + e = this.getVolume(); + this.setVolume(0, 0.001); + for (var n = this.buffer.numberOfChannels, i = 0; i < n; i++) + this.buffer.getChannelData(i).reverse(); + (this.reversed = !this.reversed), + this.isPlaying() && t && this.jump(this.duration() - t), + this.setVolume(e, 0.001); + }), + (p5.SoundFile.prototype.onended = function (t) { + return (this._onended = t), this; + }), + (p5.SoundFile.prototype.add = function () {}), + (p5.SoundFile.prototype.dispose = function () { + var t = u.audiocontext.currentTime, + e = u.soundArray.indexOf(this); + if ( + (u.soundArray.splice(e, 1), + this.stop(t), + this.buffer && this.bufferSourceNode) + ) { + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) + if (null !== this.bufferSourceNodes[n]) { + this.bufferSourceNodes[n].disconnect(); + try { + this.bufferSourceNodes[n].stop(t); + } catch (t) {} + this.bufferSourceNodes[n] = null; + } + if (this.isPlaying()) { + try { + this._counterNode.stop(t); + } catch (t) {} + this._counterNode = null; + } + } + this.output && (this.output.disconnect(), (this.output = null)), + this.panner && (this.panner.disconnect(), (this.panner = null)); + }), + (p5.SoundFile.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.panner.connect(t.input) + : this.panner.connect(t) + : this.panner.connect(u.input); + }), + (p5.SoundFile.prototype.disconnect = function () { + this.panner && this.panner.disconnect(); + }), + (p5.SoundFile.prototype.getLevel = function () {}), + (p5.SoundFile.prototype.setPath = function (t, e) { + var n = p5.prototype._checkFileFormats(t); + (this.url = n), this.load(e); + }), + (p5.SoundFile.prototype.setBuffer = function (t) { + var e = t.length, + n = t[0].length, + i = p.createBuffer(e, n, p.sampleRate); + t[0] instanceof Float32Array || (t[0] = new Float32Array(t[0])); + for (var o = 0; o < e; o++) { + i.getChannelData(o).set(t[o]); + } + (this.buffer = i), this.panner.inputChannels(e); + }); + (p5.SoundFile.prototype._initCounterNode = function () { + var e = this, + n = this, + t = p.currentTime, + i = p.createBufferSource(), + o = r(256); + return ( + n._workletNode && + (n._workletNode.disconnect(), delete n._workletNode), + (n._workletNode = new AudioWorkletNode(p, s.soundFileProcessor, { + processorOptions: { bufferSize: o }, + })), + (n._workletNode.port.onmessage = function (t) { + if ("position" === t.data.name) { + if (0 === t.data.position) return; + (e._lastPos = t.data.position), e._onTimeUpdate(n._lastPos); + } + }), + (i.buffer = (function (t) { + for ( + var e = t.length, + n = p.createBuffer(1, t.length, p.sampleRate), + i = n.getChannelData(0), + o = 0; + o < e; + o++ + ) + i[o] = o; + return n; + })(n.buffer)), + i.playbackRate.setValueAtTime(n.playbackRate, t), + i.connect(n._workletNode), + n._workletNode.connect(p5.soundOut._silentNode), + i + ); + }), + (p5.SoundFile.prototype._initSourceNode = function () { + var t = p.createBufferSource(); + return ( + (t.buffer = this.buffer), + (t.playbackRate.value = this.playbackRate), + t.connect(this.output), + t + ); + }), + (p5.SoundFile.prototype.processPeaks = function (r, t, e, n) { + var i = this.buffer.length, + o = this.buffer.sampleRate, + s = this.buffer, + a = [], + u = t || 0.9, + p = e || 0.22, + c = n || 200, + h = new window.OfflineAudioContext(1, i, o), + l = h.createBufferSource(); + l.buffer = s; + var f = h.createBiquadFilter(); + (f.type = "lowpass"), + l.connect(f), + f.connect(h.destination), + l.start(0), + h.startRendering(), + (h.oncomplete = function (t) { + if (self.panner) { + for ( + var e = t.renderedBuffer, n = e.getChannelData(0); + (a = d(n, u)), + (u -= 0.005), + Object.keys(a).length < c && p <= u; + + ); + var i = (function (t, i) { + var o = []; + return ( + t.forEach(function (e) { + try { + var n = Math.abs(60 / (e.interval / i)); + if ( + ((n = m(n)), + !o.some(function (t) { + if (t.tempo === n) return (t.count += e.count); + })) + ) { + if (isNaN(n)) return; + o.push({ tempo: Math.round(n), count: e.count }); + } + } catch (t) { + throw t; + } + }), + o + ); + })( + (function (t) { + for ( + var e = [], n = Object.keys(t).sort(), i = 0; + i < n.length; + i++ + ) + for (var o = 0; o < 10; o++) { + var r = t[n[i]], + s = t[n[i + o]]; + if (r && s) { + var a = r.sampleIndex, + u = s.sampleIndex - a; + 0 < u && r.intervals.push(u), + e.some(function (t) { + if (t.interval === u) return t.count++, t; + }) || e.push({ interval: u, count: 1 }); + } + } + return e; + })(a), + e.sampleRate + ) + .sort(function (t, e) { + return e.count - t.count; + }) + .splice(0, 5); + this.tempo = i[0].tempo; + var o = (function (t, e, n, i) { + for ( + var o = [], r = Object.keys(t).sort(), s = 0; + s < r.length; + s++ + ) + for ( + var a = r[s], u = t[a], p = 0; + p < u.intervals.length; + p++ + ) { + var c = Math.round(Math.abs(60 / (u.intervals[p] / n))); + (c = m(c)), + Math.abs(c - e) < i && o.push(u.sampleIndex / n); + } + return (o = o.filter(function (t, e, n) { + if (0.01 < n[e + 1] - t) return !0; + })); + })(a, i[0].tempo, e.sampleRate, 5); + r(o); + } + }); + }); + var c = function (t, e) { + (this.sampleIndex = e), + (this.amplitude = t), + (this.tempos = []), + (this.intervals = []); + }; + function d(t, e) { + for (var n = {}, i = t.length, o = 0; o < i; o++) { + if (t[o] > e) { + var r = t[o], + s = new c(r, o); + (n[o] = s), (o += 6e3); + } + o++; + } + return n; + } + function m(t) { + if (isFinite(t) && 0 !== t) { + for (; t < 90; ) t *= 2; + for (; 180 < t && 90 < t; ) t /= 2; + return t; + } + } + function h(t, e, n, i) { + (this.callback = t), (this.time = e), (this.id = n), (this.val = i); + } + (p5.SoundFile.prototype.addCue = function (t, e, n) { + var i = this._cueIDCounter++, + o = new h(e, t, i, n); + return this._cues.push(o), i; + }), + (p5.SoundFile.prototype.removeCue = function (t) { + for (var e = this._cues.length, n = 0; n < e; n++) { + if (this._cues[n].id === t) { + this._cues.splice(n, 1); + break; + } + } + this._cues.length; + }), + (p5.SoundFile.prototype.clearCues = function () { + this._cues = []; + }), + (p5.SoundFile.prototype._onTimeUpdate = function (t) { + for ( + var e = t / this.buffer.sampleRate, n = this._cues.length, i = 0; + i < n; + i++ + ) { + var o = this._cues[i], + r = o.time, + s = o.val; + ~~this._prevUpdateTime <= r && r <= e && o.callback(s); + } + this._prevUpdateTime = e; + }), + (p5.SoundFile.prototype.save = function (t) { + p5.prototype.saveSound(this, t, "wav"); + }), + (p5.SoundFile.prototype.getBlob = function () { + var t = i(this.buffer); + return new Blob([t], { type: "audio/wav" }); + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = o(1), + e = o(6).safeBufferSize, + i = o(10); + (p5.Amplitude = function (t) { + (this.bufferSize = e(2048)), + (this.audiocontext = n.audiocontext), + (this._workletNode = new AudioWorkletNode( + this.audiocontext, + i.amplitudeProcessor, + { + outputChannelCount: [1], + parameterData: { smoothing: t || 0 }, + processorOptions: { + normalize: !1, + smoothing: t || 0, + numInputChannels: 2, + bufferSize: this.bufferSize, + }, + } + )), + (this._workletNode.port.onmessage = function (t) { + "amplitude" === t.data.name && + ((this.volume = t.data.volume), + (this.volNorm = t.data.volNorm), + (this.stereoVol = t.data.stereoVol), + (this.stereoVolNorm = t.data.stereoVolNorm)); + }.bind(this)), + (this.input = this._workletNode), + (this.output = this.audiocontext.createGain()), + (this.volume = 0), + (this.volNorm = 0), + (this.stereoVol = [0, 0]), + (this.stereoVolNorm = [0, 0]), + (this.normalize = !1), + this._workletNode.connect(this.output), + (this.output.gain.value = 0), + this.output.connect(this.audiocontext.destination), + n.meter.connect(this._workletNode), + n.soundArray.push(this); + }), + (p5.Amplitude.prototype.setInput = function (t, e) { + n.meter.disconnect(), + e && (this._workletNode.parameters.get("smoothing").value = e), + null == t + ? n.meter.connect(this._workletNode) + : t instanceof p5.Signal + ? t.output.connect(this._workletNode) + : t + ? (t.connect(this._workletNode), + this._workletNode.disconnect(), + this._workletNode.connect(this.output)) + : n.meter.connect(this._workletNode); + }), + (p5.Amplitude.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : this.output.connect(t) + : this.output.connect(this.panner.connect(n.input)); + }), + (p5.Amplitude.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Amplitude.prototype.getLevel = function (t) { + return void 0 !== t + ? this.normalize + ? this.stereoVolNorm[t] + : this.stereoVol[t] + : this.normalize + ? this.volNorm + : this.volume; + }), + (p5.Amplitude.prototype.toggleNormalize = function (t) { + (this.normalize = "boolean" == typeof t ? t : !this.normalize), + this._workletNode.port.postMessage({ + name: "toggleNormalize", + normalize: this.normalize, + }); + }), + (p5.Amplitude.prototype.smooth = function (t) { + 0 <= t && + t < 1 && + this._workletNode.port.postMessage({ + name: "smoothing", + smoothing: t, + }); + }), + (p5.Amplitude.prototype.dispose = function () { + var t = n.soundArray.indexOf(this); + n.soundArray.splice(t, 1), + this.input && (this.input.disconnect(), delete this.input), + this.output && (this.output.disconnect(), delete this.output), + this._workletNode.disconnect(), + delete this._workletNode; + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var c = o(1); + (p5.FFT = function (t, e) { + (this.input = this.analyser = c.audiocontext.createAnalyser()), + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (t) { + this.analyser.fftSize = 2 * t; + }, + configurable: !0, + enumerable: !0, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (t) { + this.analyser.smoothingTimeConstant = t; + }, + configurable: !0, + enumerable: !0, + }, + }), + this.smooth(t), + (this.bins = e || 1024), + c.fftMeter.connect(this.analyser), + (this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.bass = [20, 140]), + (this.lowMid = [140, 400]), + (this.mid = [400, 2600]), + (this.highMid = [2600, 5200]), + (this.treble = [5200, 14e3]), + c.soundArray.push(this); + }), + (p5.FFT.prototype.setInput = function (t) { + t + ? (t.output + ? t.output.connect(this.analyser) + : t.connect && t.connect(this.analyser), + c.fftMeter.disconnect()) + : c.fftMeter.connect(this.analyser); + }), + (p5.FFT.prototype.waveform = function () { + for (var t, e, n = 0; n < arguments.length; n++) + "number" == typeof arguments[n] && + ((t = arguments[n]), (this.analyser.fftSize = 2 * t)), + "string" == typeof arguments[n] && (e = arguments[n]); + if (e && !p5.prototype._isSafari()) + return ( + s(this, this.timeDomain), + this.analyser.getFloatTimeDomainData(this.timeDomain), + this.timeDomain + ); + a(this, this.timeDomain), + this.analyser.getByteTimeDomainData(this.timeDomain); + for (var i = new Array(), o = 0; o < this.timeDomain.length; o++) { + var r = p5.prototype.map(this.timeDomain[o], 0, 255, -1, 1); + i.push(r); + } + return i; + }), + (p5.FFT.prototype.analyze = function () { + for (var t, e = 0; e < arguments.length; e++) + "number" == typeof arguments[e] && + ((this.bins = arguments[e]), + (this.analyser.fftSize = 2 * this.bins)), + "string" == typeof arguments[e] && (t = arguments[e]); + return t && "db" === t.toLowerCase() + ? (n(this), + this.analyser.getFloatFrequencyData(this.freqDomain), + this.freqDomain) + : (i(this, this.freqDomain), + this.analyser.getByteFrequencyData(this.freqDomain), + Array.apply([], this.freqDomain)); + }), + (p5.FFT.prototype.getEnergy = function (t, e) { + var n = c.audiocontext.sampleRate / 2; + if ( + ("bass" === t + ? ((t = this.bass[0]), (e = this.bass[1])) + : "lowMid" === t + ? ((t = this.lowMid[0]), (e = this.lowMid[1])) + : "mid" === t + ? ((t = this.mid[0]), (e = this.mid[1])) + : "highMid" === t + ? ((t = this.highMid[0]), (e = this.highMid[1])) + : "treble" === t && + ((t = this.treble[0]), (e = this.treble[1])), + "number" != typeof t) + ) + throw "invalid input for getEnergy()"; + if (e) { + if (t && e) { + if (e < t) { + var i = e; + (e = t), (t = i); + } + for ( + var o = Math.round((t / n) * this.freqDomain.length), + r = Math.round((e / n) * this.freqDomain.length), + s = 0, + a = 0, + u = o; + u <= r; + u++ + ) + (s += this.freqDomain[u]), (a += 1); + return s / a; + } + throw "invalid input for getEnergy()"; + } + var p = Math.round((t / n) * this.freqDomain.length); + return this.freqDomain[p]; + }), + (p5.FFT.prototype.getFreq = function (t, e) { + return this.getEnergy(t, e); + }), + (p5.FFT.prototype.getCentroid = function () { + for ( + var t = c.audiocontext.sampleRate / 2, e = 0, n = 0, i = 0; + i < this.freqDomain.length; + i++ + ) + (e += i * this.freqDomain[i]), (n += this.freqDomain[i]); + var o = 0; + return 0 !== n && (o = e / n), o * (t / this.freqDomain.length); + }), + (p5.FFT.prototype.smooth = function (t) { + return void 0 !== t && (this.smoothing = t), this.smoothing; + }), + (p5.FFT.prototype.dispose = function () { + var t = c.soundArray.indexOf(this); + c.soundArray.splice(t, 1), + this.analyser && + (this.analyser.disconnect(), delete this.analyser); + }), + (p5.FFT.prototype.linAverages = function (t) { + t = t || 16; + for ( + var e = this.freqDomain, + n = e.length, + i = Math.floor(n / t), + o = new Array(t), + r = 0, + s = 0; + s < n; + s++ + ) + (o[r] = void 0 !== o[r] ? (o[r] + e[s]) / 2 : e[s]), + s % i == i - 1 && r++; + return o; + }), + (p5.FFT.prototype.logAverages = function (t) { + for ( + var e = c.audiocontext.sampleRate / 2, + n = this.freqDomain, + i = n.length, + o = new Array(t.length), + r = 0, + s = 0; + s < i; + s++ + ) { + Math.round((s * e) / this.freqDomain.length) > t[r].hi && r++, + (o[r] = void 0 !== o[r] ? (o[r] + n[s]) / 2 : n[s]); + } + return o; + }), + (p5.FFT.prototype.getOctaveBands = function (t, e) { + t = t || 3; + var n = [], + i = { + lo: (e = e || 15.625) / Math.pow(2, 1 / (2 * t)), + ctr: e, + hi: e * Math.pow(2, 1 / (2 * t)), + }; + n.push(i); + for (var o = c.audiocontext.sampleRate / 2; i.hi < o; ) { + var r = {}; + (r.lo = i.hi), + (r.ctr = i.ctr * Math.pow(2, 1 / t)), + (r.hi = r.ctr * Math.pow(2, 1 / (2 * t))), + n.push(r), + (i = r); + } + return n; + }); + var n = function (t) { + t.freqDomain instanceof Float32Array == !1 && + (t.freqDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + i = function (t) { + t.freqDomain instanceof Uint8Array == !1 && + (t.freqDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }, + s = function (t) { + t.timeDomain instanceof Float32Array == !1 && + (t.timeDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + a = function (t) { + t.timeDomain instanceof Uint8Array == !1 && + (t.timeDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }; + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = o(2), + n = o(7), + i = o(3), + a = o(13); + (p5.Signal = function (t) { + return new e(t); + }), + (e.prototype.fade = e.prototype.linearRampToValueAtTime), + (i.prototype.fade = e.prototype.fade), + (n.prototype.fade = e.prototype.fade), + (a.prototype.fade = e.prototype.fade), + (e.prototype.setInput = function (t) { + t.connect(this); + }), + (i.prototype.setInput = e.prototype.setInput), + (n.prototype.setInput = e.prototype.setInput), + (a.prototype.setInput = e.prototype.setInput), + (e.prototype.add = function (t) { + var e = new n(t); + return this.connect(e), e; + }), + (i.prototype.add = e.prototype.add), + (n.prototype.add = e.prototype.add), + (a.prototype.add = e.prototype.add), + (e.prototype.mult = function (t) { + var e = new i(t); + return this.connect(e), e; + }), + (i.prototype.mult = e.prototype.mult), + (n.prototype.mult = e.prototype.mult), + (a.prototype.mult = e.prototype.mult), + (e.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new a(o, r); + return this.connect(s), s; + }), + (i.prototype.scale = e.prototype.scale), + (n.prototype.scale = e.prototype.scale), + (a.prototype.scale = e.prototype.scale); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (o) { + (o.Frequency = function (t, e) { + if (!(this instanceof o.Frequency)) return new o.Frequency(t, e); + o.TimeBase.call(this, t, e); + }), + o.extend(o.Frequency, o.TimeBase), + (o.Frequency.prototype._primaryExpressions = Object.create( + o.TimeBase.prototype._primaryExpressions + )), + (o.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (t) { + return this.midiToFrequency(t); + }, + }), + (o.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (t, e) { + var n = i[t.toLowerCase()] + 12 * (parseInt(e) + 1); + return this.midiToFrequency(n); + }, + }), + (o.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 1; + return ( + t && + "0" !== t && + (i *= this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i *= this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i *= this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }), + (o.Frequency.prototype.transpose = function (t) { + return ( + (this._expr = function (t, e) { + return t() * this.intervalToFrequencyRatio(e); + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.harmonize = function (t) { + return ( + (this._expr = function (t, e) { + for (var n = t(), i = [], o = 0; o < e.length; o++) + i[o] = n * this.intervalToFrequencyRatio(e[o]); + return i; + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }), + (o.Frequency.prototype.toNote = function () { + var t = this.valueOf(), + e = Math.log(t / o.Frequency.A4) / Math.LN2, + n = Math.round(12 * e) + 57, + i = Math.floor(n / 12); + return i < 0 && (n += -12 * i), r[n % 12] + i.toString(); + }), + (o.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }), + (o.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }), + (o.Frequency.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * o.Transport.PPQ); + }), + (o.Frequency.prototype._frequencyToUnits = function (t) { + return t; + }), + (o.Frequency.prototype._ticksToUnits = function (t) { + return 1 / ((60 * t) / (o.Transport.bpm.value * o.Transport.PPQ)); + }), + (o.Frequency.prototype._beatsToUnits = function (t) { + return 1 / o.TimeBase.prototype._beatsToUnits.call(this, t); + }), + (o.Frequency.prototype._secondsToUnits = function (t) { + return 1 / t; + }), + (o.Frequency.prototype._defaultUnits = "hz"); + var i = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }, + r = [ + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B", + ]; + return ( + (o.Frequency.A4 = 440), + (o.Frequency.prototype.midiToFrequency = function (t) { + return o.Frequency.A4 * Math.pow(2, (t - 69) / 12); + }), + (o.Frequency.prototype.frequencyToMidi = function (t) { + return 69 + (12 * Math.log(t / o.Frequency.A4)) / Math.LN2; + }), + o.Frequency + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(20)]), + void 0 === + (o = function (i) { + return ( + (i.TransportTime = function (t, e) { + if (!(this instanceof i.TransportTime)) + return new i.TransportTime(t, e); + i.Time.call(this, t, e); + }), + i.extend(i.TransportTime, i.Time), + (i.TransportTime.prototype._unaryExpressions = Object.create( + i.Time.prototype._unaryExpressions + )), + (i.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + var e = this._secondsToTicks(t()), + n = Math.ceil(i.Transport.ticks / e); + return this._ticksToUnits(n * e); + }, + }), + (i.TransportTime.prototype._secondsToTicks = function (t) { + var e = t / this._beatsToUnits(1); + return Math.round(e * i.Transport.PPQ); + }), + (i.TransportTime.prototype.valueOf = function () { + return ( + this._secondsToTicks(this._expr()) + + (this._plusNow ? i.Transport.ticks : 0) + ); + }), + (i.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }), + (i.TransportTime.prototype.toSeconds = function () { + return this._expr() + (this._plusNow ? i.Transport.seconds : 0); + }), + (i.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + i.TransportTime + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var u = n(1), + o = n(7), + r = n(3), + a = n(13), + s = n(14); + (p5.Envelope = function (t, e, n, i, o, r) { + (this.aTime = t || 0.1), + (this.aLevel = e || 1), + (this.dTime = n || 0.5), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + (this._rampHighPercentage = 0.98), + (this._rampLowPercentage = 0.02), + (this.output = u.audiocontext.createGain()), + (this.control = new s()), + this._init(), + this.control.connect(this.output), + (this.connection = null), + (this.mathOps = [this.control]), + (this.isExponential = !1), + (this.sourceToClear = null), + (this.wasTriggered = !1), + u.soundArray.push(this); + }), + (p5.Envelope.prototype._init = function () { + var t = u.audiocontext.currentTime; + this.control.setTargetAtTime(1e-5, t, 0.001), + this._setRampAD(this.aTime, this.dTime); + }), + (p5.Envelope.prototype.set = function (t, e, n, i, o, r) { + (this.aTime = t), + (this.aLevel = e), + (this.dTime = n || 0), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + this._setRampAD(t, n); + }), + (p5.Envelope.prototype.setADSR = function (t, e, n, i) { + (this.aTime = t), + (this.dTime = e || 0), + (this.sPercent = n || 0), + (this.dLevel = + void 0 !== n + ? n * (this.aLevel - this.rLevel) + this.rLevel + : 0), + (this.rTime = i || 0), + this._setRampAD(t, e); + }), + (p5.Envelope.prototype.setRange = function (t, e) { + (this.aLevel = t || 1), (this.rLevel = e || 0); + }), + (p5.Envelope.prototype._setRampAD = function (t, e) { + (this._rampAttackTime = this.checkExpInput(t)), + (this._rampDecayTime = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = t / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = e / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setRampPercentages = function (t, e) { + (this._rampHighPercentage = this.checkExpInput(t)), + (this._rampLowPercentage = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = + this._rampAttackTime / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = this._rampDecayTime / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setInput = function () { + for (var t = 0; t < arguments.length; t++) + this.connect(arguments[t]); + }), + (p5.Envelope.prototype.setExp = function (t) { + this.isExponential = t; + }), + (p5.Envelope.prototype.checkExpInput = function (t) { + return t <= 0 && (t = 1e-8), t; + }), + (p5.Envelope.prototype.play = function (t, e, n) { + var i = e || 0; + n = n || 0; + t && this.connection !== t && this.connect(t), + this.triggerAttack(t, i), + this.triggerRelease(t, i + this.aTime + this.dTime + n); + }), + (p5.Envelope.prototype.triggerAttack = function (t, e) { + var n = u.audiocontext.currentTime + (e || 0); + (this.lastAttack = n), + (this.wasTriggered = !0), + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.aTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.aLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (n += this.dTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.dLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)); + }), + (p5.Envelope.prototype.triggerRelease = function (t, e) { + if (this.wasTriggered) { + var n = u.audiocontext.currentTime + (e || 0); + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.rTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.rLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (this.wasTriggered = !1); + } + }), + (p5.Envelope.prototype.ramp = function (t, e, n, i) { + var o = u.audiocontext.currentTime + (e || 0), + r = this.checkExpInput(n), + s = void 0 !== i ? this.checkExpInput(i) : void 0; + t && this.connection !== t && this.connect(t); + var a = this.checkExpInput(this.control.getValueAtTime(o)); + a < r + ? (this.control.setTargetAtTime(r, o, this._rampAttackTC), + (o += this._rampAttackTime)) + : r < a && + (this.control.setTargetAtTime(r, o, this._rampDecayTC), + (o += this._rampDecayTime)), + void 0 !== s && + (r < s + ? this.control.setTargetAtTime(s, o, this._rampAttackTC) + : s < r && + this.control.setTargetAtTime(s, o, this._rampDecayTC)); + }), + (p5.Envelope.prototype.connect = function (t) { + ((this.connection = t) instanceof p5.Oscillator || + t instanceof p5.SoundFile || + t instanceof p5.AudioIn || + t instanceof p5.Reverb || + t instanceof p5.Noise || + t instanceof p5.Filter || + t instanceof p5.Delay) && + (t = t.output.gain), + t instanceof AudioParam && + t.setValueAtTime(0, u.audiocontext.currentTime), + t instanceof p5.Signal && t.setValue(0), + this.output.connect(t); + }), + (p5.Envelope.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Envelope.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, o); + }), + (p5.Envelope.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, r); + }), + (p5.Envelope.prototype.scale = function (t, e, n, i) { + var o = new a(t, e, n, i), + r = this.mathOps.length, + s = this.output; + return p5.prototype._mathChain(this, o, r, s, a); + }), + (p5.Envelope.prototype.dispose = function () { + var t = u.soundArray.indexOf(this); + u.soundArray.splice(t, 1), + this.disconnect(), + this.control && (this.control.dispose(), (this.control = null)); + for (var e = 1; e < this.mathOps.length; e++) + this.mathOps[e].dispose(); + }), + (p5.Env = function (t, e, n, i, o, r) { + p5.Envelope.call(this, t, e, n, i, o, r); + }), + (p5.Env.prototype = Object.create(p5.Envelope.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1); + function a() { + for ( + var t = s.audiocontext, + e = t.createBuffer(1, 2048, t.sampleRate), + n = e.getChannelData(0), + i = 0; + i < 2048; + i++ + ) + n[i] = 1; + var o = t.createBufferSource(); + return (o.buffer = e), (o.loop = !0), o; + } + n(23), + (p5.Pulse = function (t, e) { + p5.Oscillator.call(this, t, "sawtooth"), + (this.w = e || 0), + (this.osc2 = new p5.SawOsc(t)), + (this.dNode = s.audiocontext.createDelay()), + (this.dcOffset = a()), + (this.dcGain = s.audiocontext.createGain()), + this.dcOffset.connect(this.dcGain), + this.dcGain.connect(this.output), + (this.f = t || 440); + var n = this.w / this.oscillator.frequency.value; + (this.dNode.delayTime.value = n), + (this.dcGain.gain.value = 1.7 * (0.5 - this.w)), + this.osc2.disconnect(), + this.osc2.panner.disconnect(), + this.osc2.amp(-1), + this.osc2.output.connect(this.dNode), + this.dNode.connect(this.output), + (this.output.gain.value = 1), + this.output.connect(this.panner); + }), + (p5.Pulse.prototype = Object.create(p5.Oscillator.prototype)), + (p5.Pulse.prototype.width = function (t) { + if ("number" == typeof t) { + if (t <= 1 && 0 <= t) { + this.w = t; + var e = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = e; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + t.connect(this.dNode.delayTime); + var n = new p5.SignalAdd(-0.5); + n.setInput(t), + (n = (n = n.mult(-1)).mult(1.7)).connect(this.dcGain.gain); + } + }), + (p5.Pulse.prototype.start = function (t, e) { + var n = s.audiocontext.currentTime, + i = e || 0; + if (!this.started) { + var o = t || this.f, + r = this.oscillator.type; + (this.oscillator = s.audiocontext.createOscillator()), + this.oscillator.frequency.setValueAtTime(o, n), + (this.oscillator.type = r), + this.oscillator.connect(this.output), + this.oscillator.start(i + n), + (this.osc2.oscillator = s.audiocontext.createOscillator()), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + (this.osc2.oscillator.type = r), + this.osc2.oscillator.connect(this.osc2.output), + this.osc2.start(i + n), + (this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]), + (this.dcOffset = a()), + this.dcOffset.connect(this.dcGain), + this.dcOffset.start(i + n), + void 0 !== this.mods && + void 0 !== this.mods.frequency && + (this.mods.frequency.connect(this.freqNode[0]), + this.mods.frequency.connect(this.freqNode[1])), + (this.started = !0), + (this.osc2.started = !0); + } + }), + (p5.Pulse.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), + this.osc2.oscillator && this.osc2.oscillator.stop(e + n), + this.dcOffset.stop(e + n), + (this.started = !1), + (this.osc2.started = !1); + } + }), + (p5.Pulse.prototype.freq = function (t, e, n) { + if ("number" == typeof t) { + this.f = t; + var i = s.audiocontext.currentTime, + o = + ((e = e || 0), (n = n || 0), this.oscillator.frequency.value); + this.oscillator.frequency.cancelScheduledValues(i), + this.oscillator.frequency.setValueAtTime(o, i + n), + this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.osc2.oscillator.frequency.cancelScheduledValues(i), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.freqMod && + (this.freqMod.output.disconnect(), (this.freqMod = null)); + } else + t.output && + (t.output.disconnect(), + t.output.connect(this.oscillator.frequency), + t.output.connect(this.osc2.oscillator.frequency), + (this.freqMod = t)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var l = r(1); + (p5.Noise = function (t) { + var e; + p5.Oscillator.call(this), + delete this.f, + delete this.freq, + delete this.oscillator, + (e = "brown" === t ? o : "pink" === t ? i : n), + (this.buffer = e); + }), + (p5.Noise.prototype = Object.create(p5.Oscillator.prototype)); + var n = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0; + i < t; + i++ + ) + n[i] = 2 * Math.random() - 1; + return (e.type = "white"), e; + })(), + i = (function () { + var t, + e, + n, + i, + o, + r, + s, + a = 2 * l.audiocontext.sampleRate, + u = l.audiocontext.createBuffer(1, a, l.audiocontext.sampleRate), + p = u.getChannelData(0); + t = e = n = i = o = r = s = 0; + for (var c = 0; c < a; c++) { + var h = 2 * Math.random() - 1; + (t = 0.99886 * t + 0.0555179 * h), + (e = 0.99332 * e + 0.0750759 * h), + (n = 0.969 * n + 0.153852 * h), + (i = 0.8665 * i + 0.3104856 * h), + (o = 0.55 * o + 0.5329522 * h), + (r = -0.7616 * r - 0.016898 * h), + (p[c] = t + e + n + i + o + r + s + 0.5362 * h), + (p[c] *= 0.11), + (s = 0.115926 * h); + } + return (u.type = "pink"), u; + })(), + o = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0, + o = 0; + o < t; + o++ + ) { + var r = 2 * Math.random() - 1; + (n[o] = (i + 0.02 * r) / 1.02), (i = n[o]), (n[o] *= 3.5); + } + return (e.type = "brown"), e; + })(); + (p5.Noise.prototype.setType = function (t) { + switch (t) { + case "white": + this.buffer = n; + break; + case "pink": + this.buffer = i; + break; + case "brown": + this.buffer = o; + break; + default: + this.buffer = n; + } + if (this.started) { + var e = l.audiocontext.currentTime; + this.stop(e), this.start(e + 0.01); + } + }), + (p5.Noise.prototype.getType = function () { + return this.buffer.type; + }), + (p5.Noise.prototype.start = function () { + this.started && this.stop(), + (this.noise = l.audiocontext.createBufferSource()), + (this.noise.buffer = this.buffer), + (this.noise.loop = !0), + this.noise.connect(this.output); + var t = l.audiocontext.currentTime; + this.noise.start(t), (this.started = !0); + }), + (p5.Noise.prototype.stop = function () { + var t = l.audiocontext.currentTime; + this.noise && (this.noise.stop(t), (this.started = !1)); + }), + (p5.Noise.prototype.dispose = function () { + var t = l.audiocontext.currentTime, + e = l.soundArray.indexOf(this); + l.soundArray.splice(e, 1), + this.noise && (this.noise.disconnect(), this.stop(t)), + this.output && this.output.disconnect(), + this.panner && this.panner.disconnect(), + (this.output = null), + (this.panner = null), + (this.buffer = null), + (this.noise = null); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (r.inputSources = []), + (p5.AudioIn = function (t) { + (this.input = r.audiocontext.createGain()), + (this.output = r.audiocontext.createGain()), + (this.stream = null), + (this.mediaStream = null), + (this.currentSource = null), + (this.enabled = !1), + (this.amplitude = new p5.Amplitude()), + this.output.connect(this.amplitude.input), + (window.MediaStreamTrack && + window.navigator.mediaDevices && + window.navigator.mediaDevices.getUserMedia) || + (t + ? t() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + )), + r.soundArray.push(this); + }), + (p5.AudioIn.prototype.start = function (e, n) { + var i = this; + this.stream && this.stop(); + var t = r.inputSources[i.currentSource], + o = { + audio: { + sampleRate: r.audiocontext.sampleRate, + echoCancellation: !1, + }, + }; + r.inputSources[this.currentSource] && + (o.audio.deviceId = t.deviceId), + window.navigator.mediaDevices + .getUserMedia(o) + .then(function (t) { + (i.stream = t), + (i.enabled = !0), + (i.mediaStream = r.audiocontext.createMediaStreamSource(t)), + i.mediaStream.connect(i.output), + i.amplitude.setInput(i.output), + e && e(); + }) + .catch(function (t) { + n && n(t); + }); + }), + (p5.AudioIn.prototype.stop = function () { + this.stream && + (this.stream.getTracks().forEach(function (t) { + t.stop(); + }), + this.mediaStream.disconnect(), + delete this.mediaStream, + delete this.stream); + }), + (p5.AudioIn.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : t.hasOwnProperty("analyser") + ? this.output.connect(t.analyser) + : this.output.connect(t) + : this.output.connect(r.input); + }), + (p5.AudioIn.prototype.disconnect = function () { + this.output && + (this.output.disconnect(), + this.output.connect(this.amplitude.input)); + }), + (p5.AudioIn.prototype.getLevel = function (t) { + return ( + t && (this.amplitude.smoothing = t), this.amplitude.getLevel() + ); + }), + (p5.AudioIn.prototype.amp = function (t, e) { + if (e) { + var n = e || 0, + i = this.output.gain.value; + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(i, r.audiocontext.currentTime), + this.output.gain.linearRampToValueAtTime( + t, + n + r.audiocontext.currentTime + ); + } else + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(t, r.audiocontext.currentTime); + }), + (p5.AudioIn.prototype.getSources = function (i, o) { + return new Promise(function (e, n) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (t) { + (r.inputSources = t.filter(function (t) { + return "audioinput" === t.kind; + })), + e(r.inputSources), + i && i(r.inputSources); + }) + .catch(function (t) { + n(t), o && o(t); + }); + }); + }), + (p5.AudioIn.prototype.setSource = function (t) { + 0 < r.inputSources.length && + t < r.inputSources.length && + (this.currentSource = t), + this.stream && this.stream.active && this.start(); + }), + (p5.AudioIn.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.stop(), + this.output && this.output.disconnect(), + this.amplitude && this.amplitude.disconnect(), + delete this.amplitude, + delete this.output; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(52), n(58), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.CrossFade = function (t) { + this.createInsOuts(2, 1), + (this.a = this.input[0] = new e.Gain()), + (this.b = this.input[1] = new e.Gain()), + (this.fade = new e.Signal( + this.defaultArg(t, 0.5), + e.Type.NormalRange + )), + (this._equalPowerA = new e.EqualPowerGain()), + (this._equalPowerB = new e.EqualPowerGain()), + (this._invert = new e.Expr("1 - $0")), + this.a.connect(this.output), + this.b.connect(this.output), + this.fade.chain(this._equalPowerB, this.b.gain), + this.fade.chain(this._invert, this._equalPowerA, this.a.gain), + this._readOnly("fade"); + }), + e.extend(e.CrossFade), + (e.CrossFade.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._writable("fade"), + this._equalPowerA.dispose(), + (this._equalPowerA = null), + this._equalPowerB.dispose(), + (this._equalPowerB = null), + this.fade.dispose(), + (this.fade = null), + this._invert.dispose(), + (this._invert = null), + this.a.dispose(), + (this.a = null), + this.b.dispose(), + (this.b = null), + this + ); + }), + e.CrossFade + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [ + n(0), + n(7), + n(16), + n(3), + n(53), + n(26), + n(54), + n(25), + n(55), + n(56), + n(57), + ]), + void 0 === + (o = function (u) { + "use strict"; + function n(t, e, n) { + var i = new t(); + return ( + n._eval(e[0]).connect(i, 0, 0), n._eval(e[1]).connect(i, 0, 1), i + ); + } + function i(t, e, n) { + var i = new t(); + return n._eval(e[0]).connect(i, 0, 0), i; + } + function o(t) { + return t ? parseFloat(t) : void 0; + } + function r(t) { + return t && t.args ? parseFloat(t.args) : void 0; + } + return ( + (u.Expr = function () { + var t = this._replacements(Array.prototype.slice.call(arguments)), + e = this._parseInputs(t); + (this._nodes = []), (this.input = new Array(e)); + for (var n = 0; n < e; n++) + this.input[n] = this.context.createGain(); + var i, + o = this._parseTree(t); + try { + i = this._eval(o); + } catch (e) { + throw ( + (this._disposeNodes(), + new Error("Tone.Expr: Could evaluate expression: " + t)) + ); + } + this.output = i; + }), + u.extend(u.Expr, u.SignalBase), + (u.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (t) { + return new u.Signal(o(t)); + }, + }, + input: { + regexp: /^\$\d/, + method: function (t, e) { + return e.input[o(t.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { regexp: /^abs/, method: i.bind(this, u.Abs) }, + mod: { + regexp: /^mod/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Modulo(n); + return e._eval(t[0]).connect(i), i; + }, + }, + pow: { + regexp: /^pow/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Pow(n); + return e._eval(t[0]).connect(i), i; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (t, e) { + var n = new u.AudioToGain(); + return e._eval(t[0]).connect(n), n; + }, + }, + }, + binary: { + "+": { + regexp: /^\+/, + precedence: 1, + method: n.bind(this, u.Add), + }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (t, e) { + return 1 === t.length + ? i(u.Negate, t, e) + : n(u.Subtract, t, e); + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: n.bind(this, u.Multiply), + }, + }, + unary: { + "-": { regexp: /^\-/, method: i.bind(this, u.Negate) }, + "!": { regexp: /^\!/, method: i.bind(this, u.NOT) }, + }, + }), + (u.Expr.prototype._parseInputs = function (t) { + var e = t.match(/\$\d/g), + n = 0; + if (null !== e) + for (var i = 0; i < e.length; i++) { + var o = parseInt(e[i].substr(1)) + 1; + n = Math.max(n, o); + } + return n; + }), + (u.Expr.prototype._replacements = function (t) { + for (var e = t.shift(), n = 0; n < t.length; n++) + e = e.replace(/\%/i, t[n]); + return e; + }), + (u.Expr.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim())); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t) { + for (var e in u.Expr._Expressions) { + var n = u.Expr._Expressions[e]; + for (var i in n) { + var o = n[i], + r = o.regexp, + s = t.match(r); + if (null !== s) + return { type: e, value: s[0], method: o.method }; + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (u.Expr.prototype._parseTree = function (t) { + var i = this._tokenize(t), + s = this.isUndef.bind(this); + function o(t, e) { + return !s(t) && "glue" === t.type && t.value === e; + } + function r(t, e, n) { + var i = u.Expr._Expressions[e]; + if (!s(t)) + for (var o in i) { + var r = i[o]; + if (r.regexp.test(t.value)) { + if (s(n)) return !0; + if (r.precedence === n) return !0; + } + } + return !1; + } + function a(t) { + var e; + s(t) && (t = 5), + (e = + t < 0 + ? (function t() { + var e, n; + return r((e = i.peek()), "unary") + ? ((e = i.next()), + (n = t()), + { + operator: e.value, + method: e.method, + args: [n], + }) + : (function () { + var t, e; + if (((t = i.peek()), s(t))) + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + if ("func" === t.type) + return (function (t) { + var e = []; + if (!o(i.next(), "(")) + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + + t.value + + '"' + ); + if ( + (o(i.peek(), ")") || + (e = (function () { + for ( + var t, e = []; + (t = a()), + !s(t) && + (e.push(t), o(i.peek(), ",")); + + ) + i.next(); + return e; + })()), + o(i.next(), ")")) + ) + return { + method: t.method, + args: e, + name: name, + }; + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + + t.value + + '"' + ); + })((t = i.next())); + if ("value" === t.type) + return { + method: (t = i.next()).method, + args: t.value, + }; + if (o(t, "(")) { + if ( + (i.next(), + (e = a()), + !o((t = i.next()), ")")) + ) + throw new SyntaxError("Expected )"); + return e; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + + t.value + ); + })(); + })() + : a(t - 1)); + for (var n = i.peek(); r(n, "binary", t); ) + (e = { + operator: (n = i.next()).value, + method: n.method, + args: [e, a(t - 1)], + }), + (n = i.peek()); + return e; + } + return a(); + }), + (u.Expr.prototype._eval = function (t) { + if (!this.isUndef(t)) { + var e = t.method(t.args, this); + return this._nodes.push(e), e; + } + }), + (u.Expr.prototype._disposeNodes = function () { + for (var t = 0; t < this._nodes.length; t++) { + var e = this._nodes[t]; + this.isFunction(e.dispose) + ? e.dispose() + : this.isFunction(e.disconnect) && e.disconnect(), + (e = null), + (this._nodes[t] = null); + } + this._nodes = null; + }), + (u.Expr.prototype.dispose = function () { + u.prototype.dispose.call(this), this._disposeNodes(); + }), + u.Expr + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(26), n(16), n(2)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.GreaterThan = function (t) { + this.createInsOuts(2, 0), + (this._param = this.input[0] = new e.Subtract(t)), + (this.input[1] = this._param.input[1]), + (this._gtz = this.output = new e.GreaterThanZero()), + this._param.connect(this._gtz); + }), + e.extend(e.GreaterThan, e.Signal), + (e.GreaterThan.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._param.dispose(), + (this._param = null), + this._gtz.dispose(), + (this._gtz = null), + this + ); + }), + e.GreaterThan + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(19)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Abs = function () { + this._abs = + this.input = + this.output = + new t.WaveShaper(function (t) { + return 0 === t ? 0 : Math.abs(t); + }, 127); + }), + t.extend(t.Abs, t.SignalBase), + (t.Abs.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._abs.dispose(), + (this._abs = null), + this + ); + }), + t.Abs + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(3), n(16)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Modulo = function (t) { + this.createInsOuts(1, 0), + (this._shaper = new e.WaveShaper(Math.pow(2, 16))), + (this._multiply = new e.Multiply()), + (this._subtract = this.output = new e.Subtract()), + (this._modSignal = new e.Signal(t)), + this.input.fan(this._shaper, this._subtract), + this._modSignal.connect(this._multiply, 0, 0), + this._shaper.connect(this._multiply, 0, 1), + this._multiply.connect(this._subtract, 0, 1), + this._setWaveShaper(t); + }), + e.extend(e.Modulo, e.SignalBase), + (e.Modulo.prototype._setWaveShaper = function (e) { + this._shaper.setMap(function (t) { + return Math.floor((t + 1e-4) / e); + }); + }), + Object.defineProperty(e.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (t) { + (this._modSignal.value = t), this._setWaveShaper(t); + }, + }), + (e.Modulo.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._shaper.dispose(), + (this._shaper = null), + this._multiply.dispose(), + (this._multiply = null), + this._subtract.dispose(), + (this._subtract = null), + this._modSignal.dispose(), + (this._modSignal = null), + this + ); + }), + e.Modulo + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Pow = function (t) { + (this._exp = this.defaultArg(t, 1)), + (this._expScaler = + this.input = + this.output = + new e.WaveShaper(this._expFunc(this._exp), 8192)); + }), + e.extend(e.Pow, e.SignalBase), + Object.defineProperty(e.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (t) { + (this._exp = t), + this._expScaler.setMap(this._expFunc(this._exp)); + }, + }), + (e.Pow.prototype._expFunc = function (e) { + return function (t) { + return Math.pow(Math.abs(t), e); + }; + }), + (e.Pow.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._expScaler.dispose(), + (this._expScaler = null), + this + ); + }), + e.Pow + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.AudioToGain = function () { + this._norm = + this.input = + this.output = + new t.WaveShaper(function (t) { + return (t + 1) / 2; + }); + }), + t.extend(t.AudioToGain, t.SignalBase), + (t.AudioToGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._norm.dispose(), + (this._norm = null), + this + ); + }), + t.AudioToGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new t.WaveShaper( + function (t) { + return Math.abs(t) < 0.001 ? 0 : this.equalPowerScale(t); + }.bind(this), + 4096 + ); + }), + t.extend(t.EqualPowerGain, t.SignalBase), + (t.EqualPowerGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._eqPower.dispose(), + (this._eqPower = null), + this + ); + }), + t.EqualPowerGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var r = i(4), + n = i(60); + return ( + (p5.EQ = function (t) { + var e, n, i; + r.call(this), + (e = 3 === (t = 3 === t || 8 === t ? t : 3) ? Math.pow(2, 3) : 2), + (this.bands = []); + for (var o = 0; o < t; o++) + (i = + o === t - 1 + ? ((n = 21e3), 0.01) + : 0 === o + ? ((n = 100), 0.1) + : ((n = + 1 === o + ? 3 === t + ? 360 * e + : 360 + : this.bands[o - 1].freq() * e), + 1)), + (this.bands[o] = this._newBand(n, i)), + 0 < o + ? this.bands[o - 1].connect(this.bands[o].biquad) + : this.input.connect(this.bands[o].biquad); + this.bands[t - 1].connect(this.output); + }), + (p5.EQ.prototype = Object.create(r.prototype)), + (p5.EQ.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.EQ.prototype.set = function () { + if (arguments.length === 2 * this.bands.length) + for (var t = 0; t < arguments.length; t += 2) + this.bands[t / 2].freq(arguments[t]), + this.bands[t / 2].gain(arguments[t + 1]); + }), + (p5.EQ.prototype._newBand = function (t, e) { + return new n(t, e); + }), + (p5.EQ.prototype.dispose = function () { + if ((r.prototype.dispose.apply(this), this.bands)) { + for (; 0 < this.bands.length; ) this.bands.pop().dispose(); + delete this.bands; + } + }), + p5.EQ + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + function e(t, e) { + n.call(this, "peaking"), + this.disconnect(), + this.set(t, e), + (this.biquad.gain.value = 0), + delete this.input, + delete this.output, + delete this._drywet, + delete this.wet; + } + var n = o(15), + i = o(1); + return ( + ((e.prototype = Object.create(n.prototype)).amp = function () {}), + (e.prototype.drywet = function () {}), + (e.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.biquad + ? this.biquad.connect(e.input ? e.input : e) + : this.output.connect(e.input ? e.input : e); + }), + (e.prototype.disconnect = function () { + this.biquad && this.biquad.disconnect(); + }), + (e.prototype.dispose = function () { + var t = i.soundArray.indexOf(this); + i.soundArray.splice(t, 1), this.disconnect(), delete this.biquad; + }), + e + ); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(1); + var e = n(4); + return ( + (p5.Panner3D = function () { + e.call(this), + (this.panner = this.ac.createPanner()), + (this.panner.panningModel = "HRTF"), + (this.panner.distanceModel = "linear"), + this.panner.connect(this.output), + this.input.connect(this.panner); + }), + (p5.Panner3D.prototype = Object.create(e.prototype)), + (p5.Panner3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Panner3D.prototype.set = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ] + ); + }), + (p5.Panner3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionX.value = t), + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionX), + this.panner.positionX.value + ); + }), + (p5.Panner3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionY.value = t), + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionY), + this.panner.positionY.value + ); + }), + (p5.Panner3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionZ.value = t), + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionZ), + this.panner.positionZ.value + ); + }), + (p5.Panner3D.prototype.orient = function (t, e, n, i) { + return ( + this.orientX(t, i), + this.orientY(e, i), + this.orientZ(n, i), + [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ] + ); + }), + (p5.Panner3D.prototype.orientX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationX.value = t), + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationX), + this.panner.orientationX.value + ); + }), + (p5.Panner3D.prototype.orientY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationY.value = t), + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationY), + this.panner.orientationY.value + ); + }), + (p5.Panner3D.prototype.orientZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationZ.value = t), + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationZ), + this.panner.orientationZ.value + ); + }), + (p5.Panner3D.prototype.setFalloff = function (t, e) { + this.maxDist(t), this.rolloff(e); + }), + (p5.Panner3D.prototype.maxDist = function (t) { + return ( + "number" == typeof t && (this.panner.maxDistance = t), + this.panner.maxDistance + ); + }), + (p5.Panner3D.prototype.rolloff = function (t) { + return ( + "number" == typeof t && (this.panner.rolloffFactor = t), + this.panner.rolloffFactor + ); + }), + (p5.Panner3D.dispose = function () { + e.prototype.dispose.apply(this), + this.panner && (this.panner.disconnect(), delete this.panner); + }), + p5.Panner3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(1); + n(4); + return ( + (p5.Listener3D = function (t) { + (this.ac = e.audiocontext), (this.listener = this.ac.listener); + }), + (p5.Listener3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Listener3D.prototype.position = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ] + ); + }), + (p5.Listener3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionX.value = t), + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionX), + this.listener.positionX.value + ); + }), + (p5.Listener3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionY.value = t), + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionY), + this.listener.positionY.value + ); + }), + (p5.Listener3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionZ.value = t), + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionZ), + this.listener.positionZ.value + ); + }), + (p5.Listener3D.prototype.orient = function (t, e, n, i, o, r, s) { + return ( + 3 === arguments.length || 4 === arguments.length + ? ((s = i), this.orientForward(t, e, n, s)) + : (6 !== arguments.length && 7 !== arguments) || + (this.orientForward(t, e, n), this.orientUp(i, o, r, s)), + [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ] + ); + }), + (p5.Listener3D.prototype.orientForward = function (t, e, n, i) { + return ( + this.forwardX(t, i), + this.forwardY(e, i), + this.forwardZ(n, i), + [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ] + ); + }), + (p5.Listener3D.prototype.orientUp = function (t, e, n, i) { + return ( + this.upX(t, i), + this.upY(e, i), + this.upZ(n, i), + [this.listener.upX, this.listener.upY, this.listener.upZ] + ); + }), + (p5.Listener3D.prototype.forwardX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardX.value = t), + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardX), + this.listener.forwardX.value + ); + }), + (p5.Listener3D.prototype.forwardY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardY.value = t), + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardY), + this.listener.forwardY.value + ); + }), + (p5.Listener3D.prototype.forwardZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardZ.value = t), + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardZ), + this.listener.forwardZ.value + ); + }), + (p5.Listener3D.prototype.upX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upX.value = t), + this.listener.upX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upX), + this.listener.upX.value + ); + }), + (p5.Listener3D.prototype.upY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upY.value = t), + this.listener.upY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upY), + this.listener.upY.value + ); + }), + (p5.Listener3D.prototype.upZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upZ.value = t), + this.listener.upZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upZ), + this.listener.upZ.value + ); + }), + p5.Listener3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = i(15), + n = i(4); + (p5.Delay = function () { + n.call(this), + (this._split = this.ac.createChannelSplitter(2)), + (this._merge = this.ac.createChannelMerger(2)), + (this._leftGain = this.ac.createGain()), + (this._rightGain = this.ac.createGain()), + (this.leftDelay = this.ac.createDelay()), + (this.rightDelay = this.ac.createDelay()), + (this._leftFilter = new e()), + (this._rightFilter = new e()), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this.input.connect(this._split), + this.leftDelay.connect(this._leftGain), + this.rightDelay.connect(this._rightGain), + this._leftGain.connect(this._leftFilter.input), + this._rightGain.connect(this._rightFilter.input), + this._merge.connect(this.wet), + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime), + this._rightFilter.biquad.gain.setValueAtTime( + 1, + this.ac.currentTime + ), + this.setType(0), + (this._maxDelay = this.leftDelay.delayTime.maxValue), + this.feedback(0.5); + }), + (p5.Delay.prototype = Object.create(n.prototype)), + (p5.Delay.prototype.process = function (t, e, n, i) { + var o = n || 0, + r = e || 0; + if (1 <= o) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + if (r >= this._maxDelay) + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + t.connect(this.input), + this.leftDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + this.rightDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + (this._leftGain.gain.value = o), + (this._rightGain.gain.value = o), + i && (this._leftFilter.freq(i), this._rightFilter.freq(i)); + }), + (p5.Delay.prototype.delayTime = function (t) { + "number" != typeof t + ? (t.connect(this.leftDelay.delayTime), + t.connect(this.rightDelay.delayTime)) + : (this.leftDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.rightDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ), + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + )); + }), + (p5.Delay.prototype.feedback = function (t) { + if (t && "number" != typeof t) + t.connect(this._leftGain.gain), t.connect(this._rightGain.gain); + else { + if (1 <= t) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + "number" == typeof t && + ((this._leftGain.gain.value = t), + (this._rightGain.gain.value = t)); + } + return this._leftGain.gain.value; + }), + (p5.Delay.prototype.filter = function (t, e) { + this._leftFilter.set(t, e), this._rightFilter.set(t, e); + }), + (p5.Delay.prototype.setType = function (t) { + switch ( + (1 === t && (t = "pingPong"), + this._split.disconnect(), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._split.connect(this.leftDelay, 0), + this._split.connect(this.rightDelay, 1), + t) + ) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type), + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.rightDelay), + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.leftDelay), + this._rightFilter.output.connect(this.rightDelay); + } + }), + (p5.Delay.prototype.dispose = function () { + n.prototype.dispose.apply(this), + this._split.disconnect(), + this._leftFilter.dispose(), + this._rightFilter.dispose(), + this._merge.disconnect(), + this._leftGain.disconnect(), + this._rightGain.disconnect(), + this.leftDelay.disconnect(), + this.rightDelay.disconnect(), + (this._split = void 0), + (this._leftFilter = void 0), + (this._rightFilter = void 0), + (this._merge = void 0), + (this._leftGain = void 0), + (this._rightGain = void 0), + (this.leftDelay = void 0), + (this.rightDelay = void 0); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var p = n(11), + e = n(4); + (p5.Reverb = function () { + e.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + (this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse(); + }), + (p5.Reverb.prototype = Object.create(e.prototype)), + (p5.Reverb.prototype._initConvolverNode = function () { + (this.convolverNode = this.ac.createConvolver()), + this.input.connect(this.convolverNode), + this.convolverNode.connect(this.wet); + }), + (p5.Reverb.prototype._teardownConvolverNode = function () { + this.convolverNode && + (this.convolverNode.disconnect(), delete this.convolverNode); + }), + (p5.Reverb.prototype._setBuffer = function (t) { + this._teardownConvolverNode(), + this._initConvolverNode(), + (this.convolverNode.buffer = t); + }), + (p5.Reverb.prototype.process = function (t, e, n, i) { + t.connect(this.input); + var o = !1; + e && ((this._seconds = e), (o = !0)), + n && (this._decay = n), + i && (this._reverse = i), + o && this._buildImpulse(); + }), + (p5.Reverb.prototype.set = function (t, e, n) { + var i = !1; + t && ((this._seconds = t), (i = !0)), + e && (this._decay = e), + n && (this._reverse = n), + i && this._buildImpulse(); + }), + (p5.Reverb.prototype._buildImpulse = function () { + var t, + e, + n = this.ac.sampleRate, + i = n * this._seconds, + o = this._decay, + r = this.ac.createBuffer(2, i, n), + s = r.getChannelData(0), + a = r.getChannelData(1); + for (e = 0; e < i; e++) + (t = this._reverse ? i - e : e), + (s[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)), + (a[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)); + this._setBuffer(r); + }), + (p5.Reverb.prototype.dispose = function () { + e.prototype.dispose.apply(this), this._teardownConvolverNode(); + }), + (p5.Convolver = function (t, e, n) { + p5.Reverb.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + t + ? ((this.impulses = []), this._loadBuffer(t, e, n)) + : ((this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse()); + }), + (p5.Convolver.prototype = Object.create(p5.Reverb.prototype)), + p5.prototype.registerPreloadMethod("createConvolver", p5.prototype), + (p5.prototype.createConvolver = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var i = this, + o = new p5.Convolver( + t, + function (t) { + "function" == typeof e && e(t), + "function" == typeof i._decrementPreload && + i._decrementPreload(); + }, + n + ); + return (o.impulses = []), o; + }), + (p5.Convolver.prototype._loadBuffer = function (i, o, n) { + i = p5.prototype._checkFileFormats(i); + var r = this, + s = new Error().stack, + a = p5.prototype.getAudioContext(), + u = new XMLHttpRequest(); + u.open("GET", i, !0), + (u.responseType = "arraybuffer"), + (u.onload = function () { + if (200 === u.status) + a.decodeAudioData( + u.response, + function (t) { + var e = {}, + n = i.split("/"); + (e.name = n[n.length - 1]), + (e.audioBuffer = t), + r.impulses.push(e), + r._setBuffer(e.audioBuffer), + o && o(e); + }, + function () { + var t = new p("decodeAudioData", s, r.url), + e = + "AudioContext error at decodeAudioData for " + r.url; + n && ((t.msg = e), n(t)); + } + ); + else { + var t = new p("loadConvolver", s, r.url), + e = + "Unable to load " + + r.url + + ". The request status was: " + + u.status + + " (" + + u.statusText + + ")"; + n && ((t.message = e), n(t)); + } + }), + (u.onerror = function () { + var t = new p("loadConvolver", s, r.url), + e = + "There was no response from the server at " + + r.url + + ". Check the url and internet connectivity."; + n && ((t.message = e), n(t)); + }), + u.send(); + }), + (p5.Convolver.prototype.set = null), + (p5.Convolver.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Convolver.prototype.impulses = []), + (p5.Convolver.prototype.addImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.resetImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + (this.impulses = []), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.toggleImpulse = function (t) { + if ( + ("number" == typeof t && + t < this.impulses.length && + this._setBuffer(this.impulses[t].audioBuffer), + "string" == typeof t) + ) + for (var e = 0; e < this.impulses.length; e++) + if (this.impulses[e].name === t) { + this._setBuffer(this.impulses[e].audioBuffer); + break; + } + }), + (p5.Convolver.prototype.dispose = function () { + for (var t in (p5.Reverb.prototype.dispose.apply(this), + this.impulses)) + this.impulses[t] && (this.impulses[t] = null); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + e = n(27); + (p5.Metro = function () { + (this.clock = new e({ callback: this.ontick.bind(this) })), + (this.syncedParts = []), + (this.bpm = 120), + this._init(), + (this.prevTick = 0), + (this.tatumTime = 0), + (this.tickCallback = function () {}); + }), + (p5.Metro.prototype.ontick = function (t) { + var e = t - this.prevTick, + i = t - r.audiocontext.currentTime; + if (!(e - this.tatumTime <= -0.02)) { + this.prevTick = t; + var o = this; + this.syncedParts.forEach(function (t) { + t.isPlaying && + (t.incrementStep(i), + t.phrases.forEach(function (t) { + var e = t.sequence, + n = o.metroTicks % e.length; + 0 !== e[n] && + (o.metroTicks < e.length || !t.looping) && + t.callback(i, e[n]); + })); + }), + (this.metroTicks += 1), + this.tickCallback(i); + } + }), + (p5.Metro.prototype.setBPM = function (t, e) { + var n = 60 / (t * this.tatums), + i = r.audiocontext.currentTime; + this.tatumTime = n; + e = e || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, i), + this.clock.frequency.linearRampToValueAtTime(t, i + e), + (this.bpm = t); + }), + (p5.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }), + (p5.Metro.prototype._init = function () { + this.metroTicks = 0; + }), + (p5.Metro.prototype.resetSync = function (t) { + this.syncedParts = [t]; + }), + (p5.Metro.prototype.pushSync = function (t) { + this.syncedParts.push(t); + }), + (p5.Metro.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.start(n + e), this.setBPM(this.bpm); + }), + (p5.Metro.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.stop(n + e); + }), + (p5.Metro.prototype.beatLength = function (t) { + this.tatums = 1 / t / 4; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(24), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.TimelineState = function (t) { + e.Timeline.call(this), (this._initial = t); + }), + e.extend(e.TimelineState, e.Timeline), + (e.TimelineState.prototype.getValueAtTime = function (t) { + var e = this.get(t); + return null !== e ? e.state : this._initial; + }), + (e.TimelineState.prototype.setStateAtTime = function (t, e) { + this.add({ state: t, time: e }); + }), + e.TimelineState + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var i = r(1), + o = 120; + function n(t) { + t.currentPart++, + t.currentPart >= t.parts.length + ? ((t.scoreStep = 0), t.onended()) + : ((t.scoreStep = 0), + t.parts[t.currentPart - 1].stop(), + t.parts[t.currentPart].start()); + } + (p5.prototype.setBPM = function (t, e) { + for (var n in ((o = t), i.parts)) + i.parts[n] && i.parts[n].setBPM(t, e); + }), + (p5.Phrase = function (t, e, n) { + (this.phraseStep = 0), + (this.name = t), + (this.callback = e), + (this.sequence = n); + }), + (p5.Part = function (t, e) { + (this.length = t || 0), + (this.partStep = 0), + (this.phrases = []), + (this.isPlaying = !1), + this.noLoop(), + (this.tatums = e || 0.0625), + (this.metro = new p5.Metro()), + this.metro._init(), + this.metro.beatLength(this.tatums), + this.metro.setBPM(o), + i.parts.push(this), + (this.callback = function () {}); + }), + (p5.Part.prototype.setBPM = function (t, e) { + this.metro.setBPM(t, e); + }), + (p5.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }), + (p5.Part.prototype.start = function (t) { + if (!this.isPlaying) { + (this.isPlaying = !0), this.metro.resetSync(this); + var e = t || 0; + this.metro.start(e); + } + }), + (p5.Part.prototype.loop = function (t) { + (this.looping = !0), + (this.onended = function () { + this.partStep = 0; + }); + var e = t || 0; + this.start(e); + }), + (p5.Part.prototype.noLoop = function () { + (this.looping = !1), + (this.onended = function () { + this.stop(); + }); + }), + (p5.Part.prototype.stop = function (t) { + (this.partStep = 0), this.pause(t); + }), + (p5.Part.prototype.pause = function (t) { + this.isPlaying = !1; + var e = t || 0; + this.metro.stop(e); + }), + (p5.Part.prototype.addPhrase = function (t, e, n) { + var i; + if (3 === arguments.length) i = new p5.Phrase(t, e, n); + else { + if (!(t instanceof p5.Phrase)) + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + i = t; + } + this.phrases.push(i), + i.sequence.length > this.length && + (this.length = i.sequence.length); + }), + (p5.Part.prototype.removePhrase = function (t) { + for (var e in this.phrases) + this.phrases[e].name === t && this.phrases.splice(e, 1); + }), + (p5.Part.prototype.getPhrase = function (t) { + for (var e in this.phrases) + if (this.phrases[e].name === t) return this.phrases[e]; + }), + (p5.Part.prototype.replaceSequence = function (t, e) { + for (var n in this.phrases) + this.phrases[n].name === t && (this.phrases[n].sequence = e); + }), + (p5.Part.prototype.incrementStep = function (t) { + this.partStep < this.length - 1 + ? (this.callback(t), (this.partStep += 1)) + : this.looping || + this.partStep !== this.length - 1 || + this.onended(); + }), + (p5.Part.prototype.onStep = function (t) { + this.callback = t; + }), + (p5.Score = function () { + (this.parts = []), (this.currentPart = 0); + var t = this; + for (var e in arguments) + arguments[e] && + this.parts[e] && + ((this.parts[e] = arguments[e]), + (this.parts[e].nextPart = this.parts[e + 1]), + (this.parts[e].onended = function () { + t.resetPart(e), n(t); + })); + this.looping = !1; + }), + (p5.Score.prototype.onended = function () { + this.looping + ? this.parts[0].start() + : (this.parts[this.parts.length - 1].onended = function () { + this.stop(), this.resetParts(); + }), + (this.currentPart = 0); + }), + (p5.Score.prototype.start = function () { + this.parts[this.currentPart].start(), (this.scoreStep = 0); + }), + (p5.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(), + (this.currentPart = 0), + (this.scoreStep = 0); + }), + (p5.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }), + (p5.Score.prototype.loop = function () { + (this.looping = !0), this.start(); + }), + (p5.Score.prototype.noLoop = function () { + this.looping = !1; + }), + (p5.Score.prototype.resetParts = function () { + var e = this; + this.parts.forEach(function (t) { + e.resetParts[t]; + }); + }), + (p5.Score.prototype.resetPart = function (t) { + for (var e in (this.parts[t].stop(), + (this.parts[t].partStep = 0), + this.parts[t].phrases)) + this.parts[t] && (this.parts[t].phrases[e].phraseStep = 0); + }), + (p5.Score.prototype.setBPM = function (t, e) { + for (var n in this.parts) + this.parts[n] && this.parts[n].setBPM(t, e); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + i = n(27); + return ( + (p5.SoundLoop = function (t, e) { + (this.callback = t), + (this.musicalTimeMode = "number" != typeof this._interval), + (this._interval = e || 1), + (this._timeSignature = 4), + (this._bpm = 60), + (this.isPlaying = !1), + (this.maxIterations = 1 / 0); + var n = this; + this.clock = new i({ + callback: function (t) { + var e = t - r.audiocontext.currentTime; + 0 < e && n.iterations <= n.maxIterations && n.callback(e); + }, + frequency: this._calcFreq(), + }); + }), + (p5.SoundLoop.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying || (this.clock.start(n + e), (this.isPlaying = !0)); + }), + (p5.SoundLoop.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.stop(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.pause = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.pause(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.syncedStart = function (t, e) { + var n = e || 0, + i = r.audiocontext.currentTime; + if (t.isPlaying) { + if (t.isPlaying) { + var o = t.clock._nextTick - r.audiocontext.currentTime; + this.clock.start(i + o), (this.isPlaying = !0); + } + } else + t.clock.start(i + n), + (t.isPlaying = !0), + this.clock.start(i + n), + (this.isPlaying = !0); + }), + (p5.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }), + (p5.SoundLoop.prototype._calcFreq = function () { + return "number" == typeof this._interval + ? ((this.musicalTimeMode = !1), 1 / this._interval) + : "string" == typeof this._interval + ? ((this.musicalTimeMode = !0), + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4)) + : void 0; + }), + (p5.SoundLoop.prototype._convertNotation = function (t) { + var e = t.slice(-1); + switch (((t = Number(t.slice(0, -1))), e)) { + case "m": + return this._measure(t); + case "n": + return this._note(t); + } + }), + (p5.SoundLoop.prototype._measure = function (t) { + return t * this._timeSignature; + }), + (p5.SoundLoop.prototype._note = function (t) { + return this._timeSignature / t; + }), + Object.defineProperty(p5.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (t) { + this.musicalTimeMode, (this._bpm = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (t) { + this.musicalTimeMode, (this._timeSignature = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (t) { + (this.musicalTimeMode = "Number" != typeof t), + (this._interval = t), + this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }), + p5.SoundLoop + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i; + void 0 === + (i = function (t) { + "use strict"; + n(1); + var e = n(4); + n(11); + return ( + (p5.Compressor = function () { + e.call(this), + (this.compressor = this.ac.createDynamicsCompressor()), + this.input.connect(this.compressor), + this.compressor.connect(this.wet); + }), + (p5.Compressor.prototype = Object.create(e.prototype)), + (p5.Compressor.prototype.process = function (t, e, n, i, o, r) { + t.connect(this.input), this.set(e, n, i, o, r); + }), + (p5.Compressor.prototype.set = function (t, e, n, i, o) { + void 0 !== t && this.attack(t), + void 0 !== e && this.knee(e), + void 0 !== n && this.ratio(n), + void 0 !== i && this.threshold(i), + void 0 !== o && this.release(o); + }), + (p5.Compressor.prototype.attack = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.attack.value = t), + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.attack.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.attack), + this.compressor.attack.value + ); + }), + (p5.Compressor.prototype.knee = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.knee.value = t), + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.knee.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.knee), + this.compressor.knee.value + ); + }), + (p5.Compressor.prototype.ratio = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.ratio.value = t), + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.ratio.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.ratio), + this.compressor.ratio.value + ); + }), + (p5.Compressor.prototype.threshold = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.threshold.value = t), + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.threshold.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.threshold), + this.compressor.threshold.value + ); + }), + (p5.Compressor.prototype.release = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.release.value = t), + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.release.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : "undefined" != typeof number && + t.connect(this.compressor.release), + this.compressor.release.value + ); + }), + (p5.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }), + (p5.Compressor.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.compressor && + (this.compressor.disconnect(), delete this.compressor); + }), + p5.Compressor + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, a) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = a(1), + n = a(6), + i = n.convertToWav, + o = n.safeBufferSize, + r = a(10), + s = e.audiocontext; + (p5.SoundRecorder = function () { + (this.input = s.createGain()), + (this.output = s.createGain()), + (this._inputChannels = 2), + (this._outputChannels = 2); + var t = o(1024); + (this._workletNode = new AudioWorkletNode(s, r.recorderProcessor, { + outputChannelCount: [this._outputChannels], + processorOptions: { + numInputChannels: this._inputChannels, + bufferSize: t, + }, + })), + (this._workletNode.port.onmessage = function (t) { + if ("buffers" === t.data.name) { + var e = [ + new Float32Array(t.data.leftBuffer), + new Float32Array(t.data.rightBuffer), + ]; + this._callback(e); + } + }.bind(this)), + (this._callback = function () {}), + this._workletNode.connect(p5.soundOut._silentNode), + this.setInput(), + e.soundArray.push(this); + }), + (p5.SoundRecorder.prototype.setInput = function (t) { + this.input.disconnect(), + (this.input = null), + (this.input = s.createGain()), + this.input.connect(this._workletNode), + this.input.connect(this.output), + t + ? t.connect(this.input) + : p5.soundOut.output.connect(this.input); + }), + (p5.SoundRecorder.prototype.record = function (e, t, n) { + this._workletNode.port.postMessage({ name: "start", duration: t }), + e && n + ? (this._callback = function (t) { + e.setBuffer(t), n(); + }) + : e && + (this._callback = function (t) { + e.setBuffer(t); + }); + }), + (p5.SoundRecorder.prototype.stop = function () { + this._workletNode.port.postMessage({ name: "stop" }); + }), + (p5.SoundRecorder.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + (this._callback = function () {}), + this.input && this.input.disconnect(), + (this.input = null), + (this._workletNode = null); + }), + (p5.prototype.saveSound = function (t, e) { + var n = i(t.buffer); + p5.prototype.writeFile([n], e, "wav"); + }); + }.call(e, a, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + (p5.PeakDetect = function (t, e, n, i) { + (this.framesPerPeak = i || 20), + (this.framesSinceLastPeak = 0), + (this.decayRate = 0.95), + (this.threshold = n || 0.35), + (this.cutoff = 0), + (this.cutoffMult = 1.5), + (this.energy = 0), + (this.penergy = 0), + (this.currentValue = 0), + (this.isDetected = !1), + (this.f1 = t || 40), + (this.f2 = e || 2e4), + (this._onPeak = function () {}); + }), + (p5.PeakDetect.prototype.update = function (t) { + var e = (this.energy = t.getEnergy(this.f1, this.f2) / 255); + e > this.cutoff && e > this.threshold && 0 < e - this.penergy + ? (this._onPeak(), + (this.isDetected = !0), + (this.cutoff = e * this.cutoffMult), + (this.framesSinceLastPeak = 0)) + : ((this.isDetected = !1), + this.framesSinceLastPeak <= this.framesPerPeak + ? this.framesSinceLastPeak++ + : ((this.cutoff *= this.decayRate), + (this.cutoff = Math.max(this.cutoff, this.threshold)))), + (this.currentValue = e), + (this.penergy = e); + }), + (p5.PeakDetect.prototype.onPeak = function (t, e) { + var n = this; + n._onPeak = function () { + t(n.energy, e); + }; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (p5.Gain = function () { + (this.ac = r.audiocontext), + (this.input = this.ac.createGain()), + (this.output = this.ac.createGain()), + (this.input.gain.value = 0.5), + this.input.connect(this.output), + r.soundArray.push(this); + }), + (p5.Gain.prototype.setInput = function (t) { + t.connect(this.input); + }), + (p5.Gain.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.Gain.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Gain.prototype.amp = function (t, e, n) { + (e = e || 0), (n = n || 0); + var i = r.audiocontext.currentTime, + o = this.output.gain.value; + this.output.gain.cancelScheduledValues(i), + this.output.gain.linearRampToValueAtTime(o, i + n), + this.output.gain.linearRampToValueAtTime(t, i + n + e); + }), + (p5.Gain.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.output && (this.output.disconnect(), delete this.output), + this.input && (this.input.disconnect(), delete this.input); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var i = n(4); + function o(t) { + for ( + var e, + n = "number" == typeof t ? t : 50, + i = new Float32Array(44100), + o = Math.PI / 180, + r = 0; + r < 44100; + ++r + ) + (e = (2 * r) / 44100 - 1), + (i[r] = ((3 + n) * e * 20 * o) / (Math.PI + n * Math.abs(e))); + return i; + } + (p5.Distortion = function (t, e) { + if ((i.call(this), void 0 === t && (t = 0.25), "number" != typeof t)) + throw new Error("amount must be a number"); + if ((void 0 === e && (e = "2x"), "string" != typeof e)) + throw new Error("oversample must be a String"); + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.waveShaperNode = this.ac.createWaveShaper()), + (this.amount = n), + (this.waveShaperNode.curve = o(n)), + (this.waveShaperNode.oversample = e), + this.input.connect(this.waveShaperNode), + this.waveShaperNode.connect(this.wet); + }), + (p5.Distortion.prototype = Object.create(i.prototype)), + (p5.Distortion.prototype.process = function (t, e, n) { + t.connect(this.input), this.set(e, n); + }), + (p5.Distortion.prototype.set = function (t, e) { + if (t) { + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.amount = n), (this.waveShaperNode.curve = o(n)); + } + e && (this.waveShaperNode.oversample = e); + }), + (p5.Distortion.prototype.getAmount = function () { + return this.amount; + }), + (p5.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }), + (p5.Distortion.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this.waveShaperNode && + (this.waveShaperNode.disconnect(), + (this.waveShaperNode = null)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, +]); +//# sourceMappingURL=p5.sound.min.js.map diff --git a/week7-runway/runway_MUNIT_flower_mirror_hosted_model/p5.sound.min.js b/week7-runway/runway_MUNIT_flower_mirror_hosted_model/p5.sound.min.js index fe65a81..2c88ede 100644 --- a/week7-runway/runway_MUNIT_flower_mirror_hosted_model/p5.sound.min.js +++ b/week7-runway/runway_MUNIT_flower_mirror_hosted_model/p5.sound.min.js @@ -1,3 +1,7708 @@ -/** [p5.sound] Version: 0.3.12 - 2020-01-06 */ - !function(n){var i={};function o(t){if(i[t])return i[t].exports;var e=i[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=n,o.c=i,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)o.d(n,i,function(t){return e[t]}.bind(null,i));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=31)}([function(t,e,n){var i;void 0===(i=function(){"use strict";function c(t,e){this.isUndef(t)||1===t?this.input=this.context.createGain():1t)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var i=this._searchAfter(t);i&&(this.cancelScheduledValues(t),i.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):i.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.linearRampToValueAtTime(t,n),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,n),this},u.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},u.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},u.TimelineSignal.prototype.getValueAtTime=function(t){t=this.toSeconds(t);var e=this._searchAfter(t),n=this._searchBefore(t),i=this._initial;if(null===n)i=this._initial;else if(n.type===u.TimelineSignal.Type.Target){var o,r=this._events.getBefore(n.time);o=null===r?this._initial:r.value,i=this._exponentialApproach(n.time,o,n.value,n.constant,t)}else i=n.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,t):null===e?n.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,e.time,e.value,t):n.value;return i},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,n,i,o){return n+(e-n)*Math.exp(-(o-t)/i)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,n,i,o){return e+(o-t)/(n-t)*(i-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,n,i,o){return(e=Math.max(this._minOutput,e))*Math.pow(i/e,(o-t)/(n-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,n,i){var o=e.length;if(t+n<=i)return e[o-1];if(i<=t)return e[0];var r=(i-t)/n,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),u=e[s],p=e[a];return a===s?u:this._linearInterpolate(s,u,a,p,r*(o-1))},u.TimelineSignal.prototype.dispose=function(){u.Signal.prototype.dispose.call(this),u.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},u.TimelineSignal}.apply(e,i))||(t.exports=o)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var e=n(4);return p5.Filter=function(t){e.call(this),this.biquad=this.ac.createBiquadFilter(),this.input.connect(this.biquad),this.biquad.connect(this.wet),t&&this.setType(t),this._on=!0,this._untoggledType=this.biquad.type},p5.Filter.prototype=Object.create(e.prototype),p5.Filter.prototype.process=function(t,e,n,i){t.connect(this.input),this.set(e,n,i)},p5.Filter.prototype.set=function(t,e,n){t&&this.freq(t,n),e&&this.res(e,n)},p5.Filter.prototype.freq=function(t,e){var n=e||0;return t<=0&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},p5.Filter.prototype.res=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},p5.Filter.prototype.gain=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},p5.Filter.prototype.toggle=function(){return this._on=!this._on,!0===this._on?this.biquad.type=this._untoggledType:!1===this._on&&(this.biquad.type="allpass"),this._on},p5.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},p5.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},p5.LowPass=function(){p5.Filter.call(this,"lowpass")},p5.LowPass.prototype=Object.create(p5.Filter.prototype),p5.HighPass=function(){p5.Filter.call(this,"highpass")},p5.HighPass.prototype=Object.create(p5.Filter.prototype),p5.BandPass=function(){p5.Filter.call(this,"bandpass")},p5.BandPass.prototype=Object.create(p5.Filter.prototype),p5.Filter}.call(e,n,e,t))||(t.exports=i)},function(t,e,n){var i,o;i=[n(0),n(7),n(25),n(2),n(9)],void 0===(o=function(e){"use strict";return e.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new e.Gain,this._neg=new e.Negate,this._param=this.input[1]=new e.Signal(t),this._param.chain(this._neg,this._sum)},e.extend(e.Subtract,e.Signal),e.Subtract.prototype.dispose=function(){return e.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},e.Subtract}.apply(e,i))||(t.exports=o)},function(i,o,r){"use strict";(function(t){var e,n;t.TONE_SILENCE_VERSION_LOGGING=!0,e=[r(35),r(12),r(0)],void 0===(n=function(i,t,e){var o=new window.AudioContext;return e.context.dispose(),e.setContext(o),p5.prototype.getAudioContext=function(){return o},p5.prototype.userStartAudio=function(t,e){var n=t;return t instanceof p5.Element?n=t.elt:t instanceof Array&&t[0]instanceof p5.Element&&(n=t.map(function(t){return t.elt})),i(o,n,e)},o}.apply(o,e))||(i.exports=n)}).call(this,r(34))},function(t,e,n){var i,o;i=[n(0)],void 0===(o=function(s){"use strict";return s.Emitter=function(){this._events={}},s.extend(s.Emitter),s.Emitter.prototype.on=function(t,e){for(var n=t.split(/\W+/),i=0;ithis.memory){var n=this.length-this.memory;this._timeline.splice(0,n)}return this},e.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},e.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},e.Timeline.prototype.peek=function(){return this._timeline[0]},e.Timeline.prototype.shift=function(){return this._timeline.shift()},e.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+1=t&&(this._timeline=[]);return this},e.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);0<=e&&(this._timeline=this._timeline.slice(e+1))}return this},e.Timeline.prototype._search=function(t){var e=0,n=this._timeline.length,i=n;if(0t)return o;r.time>t?i=o:r.time=t;)n--;return this._iterate(e,n+1),this},e.Timeline.prototype.forEachAtTime=function(e,n){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&n(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(3),n(2)],void 0===(o=function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(2),n(3),n(5)],void 0===(o=function(t){"use strict";return t.GreaterThanZero=function(){this._thresh=this.output=new t.WaveShaper(function(t){return t<=0?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(14),n(66),n(18),n(12)],void 0===(o=function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var n=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=n.time,this.isUndef(n.offset)||(this.ticks=n.offset),this.emit("start",n.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",n.time)):e===o.State.Paused&&this.emit("pause",n.time)}var i=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(i),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}.apply(e,i))||(t.exports=o)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var n=i(1),e=i(29),r=i(6).noteToFreq;p5.MonoSynth=function(){e.call(this),this.oscillator=new p5.Oscillator,this.env=new p5.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),n.soundArray.push(this)},p5.MonoSynth.prototype=Object.create(p5.AudioVoice.prototype),p5.MonoSynth.prototype.play=function(t,e,n,i){this.triggerAttack(t,e,~~n),this.triggerRelease(~~n+(i||.15))},p5.MonoSynth.prototype.triggerAttack=function(t,e,n){n=~~n;var i=r(t),o=e||.1;this.oscillator.freq(i,0,n),this.env.ramp(this.output.gain,n,o)},p5.MonoSynth.prototype.triggerRelease=function(t){t=t||0;this.env.ramp(this.output.gain,t,0)},p5.MonoSynth.prototype.setADSR=function(t,e,n,i){this.env.setADSR(t,e,n,i)},Object.defineProperties(p5.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),p5.MonoSynth.prototype.amp=function(t,e){var n=e||0;return void 0!==t&&this.oscillator.amp(t,n),this.oscillator.amp().value},p5.MonoSynth.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},p5.MonoSynth.prototype.dispose=function(){e.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}.call(e,i,e,t))||(t.exports=n)},function(t,e,i){"use strict";var n;void 0===(n=function(){var n=i(1);return p5.AudioVoice=function(){this.ac=n.audiocontext,this.output=this.ac.createGain(),this.connect(),n.soundArray.push(this)},p5.AudioVoice.prototype.play=function(t,e,n,i){},p5.AudioVoice.prototype.triggerAttack=function(t,e,n){},p5.AudioVoice.prototype.triggerRelease=function(t){},p5.AudioVoice.prototype.amp=function(t,e){},p5.AudioVoice.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},p5.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},p5.AudioVoice}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var c=n(1),h=n(14),l=n(6).noteToFreq;p5.PolySynth=function(t,e){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=e||8,this.AudioVoice=void 0===t?p5.MonoSynth:t,this._voicesInUse=new h(0),this.output=c.audiocontext.createGain(),this.connect(),this._allocateVoices(),c.soundArray.push(this)},p5.PolySynth.prototype._allocateVoices=function(){for(var t=0;t= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'},function(t,e,n){"use strict";var i;function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}void 0===(i=function(t){var a=n(1).audiocontext;void 0!==a.createStereoPanner?(p5.Panner=function(t,e){this.stereoPanner=this.input=a.createStereoPanner(),t.connect(this.stereoPanner),this.stereoPanner.connect(e)},p5.Panner.prototype.pan=function(t,e){var n=e||0,i=a.currentTime+n;this.stereoPanner.pan.linearRampToValueAtTime(t,i)},p5.Panner.prototype.inputChannels=function(){},p5.Panner.prototype.connect=function(t){this.stereoPanner.connect(t)},p5.Panner.prototype.disconnect=function(){this.stereoPanner&&this.stereoPanner.disconnect()}):(p5.Panner=function(t,e,n){this.input=a.createGain(),t.connect(this.input),this.left=a.createGain(),this.right=a.createGain(),this.left.channelInterpretation="discrete",this.right.channelInterpretation="discrete",1this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var n=t||0,i=e||void 0;this.isPlaying()&&(this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,n,i))},p5.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},p5.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},p5.SoundFile.prototype.frames=function(){return this.buffer.length},p5.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t=t||5*window.width,this.buffer){for(var e=this.buffer,n=e.length/t,i=~~(n/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;sr[u])&&(r[u]=h)}return r}},p5.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/p.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var n=this.buffer.numberOfChannels,i=0;ie){var r=t[o],s=new c(r,o);n[o]=s,o+=6e3}o++}return n}function m(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+n[s])/2:n[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){t=t||3;var n=[],i={lo:(e=e||15.625)/Math.pow(2,1/(2*t)),ctr:e,hi:e*Math.pow(2,1/(2*t))};n.push(i);for(var o=c.audiocontext.sampleRate/2;i.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,i&&(this._leftFilter.freq(i),this._rightFilter.freq(i))},p5.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},p5.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(1<=t)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},p5.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},p5.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},p5.Delay.prototype.dispose=function(){n.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var p=n(11),e=n(4);p5.Reverb=function(){e.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},p5.Reverb.prototype=Object.create(e.prototype),p5.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},p5.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},p5.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},p5.Reverb.prototype.process=function(t,e,n,i){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),n&&(this._decay=n),i&&(this._reverse=i),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,n){var i=!1;t&&(this._seconds=t,i=!0),e&&(this._decay=e),n&&(this._reverse=n),i&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,n=this.ac.sampleRate,i=n*this._seconds,o=this._decay,r=this.ac.createBuffer(2,i,n),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;e=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}p5.prototype.setBPM=function(t,e){for(var n in o=t,i.parts)i.parts[n]&&i.parts[n].setBPM(t,e)},p5.Phrase=function(t,e,n){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=n},p5.Part=function(t,e){this.length=t||0,this.partStep=0,this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=e||.0625,this.metro=new p5.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(o),i.parts.push(this),this.callback=function(){}},p5.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},p5.Part.prototype.getBPM=function(){return this.metro.getBPM()},p5.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},p5.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},p5.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},p5.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},p5.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},p5.Part.prototype.addPhrase=function(t,e,n){var i;if(3===arguments.length)i=new p5.Phrase(t,e,n);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";i=t}this.phrases.push(i),i.sequence.length>this.length&&(this.length=i.sequence.length)},p5.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},p5.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},p5.Part.prototype.replaceSequence=function(t,e){for(var n in this.phrases)this.phrases[n].name===t&&(this.phrases[n].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStepthis.cutoff&&e>this.threshold&&0 t + ) + this.cancelScheduledValues(t), + this.linearRampToValueAtTime(e, t); + else { + var i = this._searchAfter(t); + i && + (this.cancelScheduledValues(t), + i.type === u.TimelineSignal.Type.Linear + ? this.linearRampToValueAtTime(e, t) + : i.type === u.TimelineSignal.Type.Exponential && + this.exponentialRampToValueAtTime(e, t)), + this.setValueAtTime(e, t); + } + return this; + }), + (u.TimelineSignal.prototype.linearRampToValueBetween = function ( + t, + e, + n + ) { + return ( + this.setRampPoint(e), this.linearRampToValueAtTime(t, n), this + ); + }), + (u.TimelineSignal.prototype.exponentialRampToValueBetween = + function (t, e, n) { + return ( + this.setRampPoint(e), + this.exponentialRampToValueAtTime(t, n), + this + ); + }), + (u.TimelineSignal.prototype._searchBefore = function (t) { + return this._events.get(t); + }), + (u.TimelineSignal.prototype._searchAfter = function (t) { + return this._events.getAfter(t); + }), + (u.TimelineSignal.prototype.getValueAtTime = function (t) { + t = this.toSeconds(t); + var e = this._searchAfter(t), + n = this._searchBefore(t), + i = this._initial; + if (null === n) i = this._initial; + else if (n.type === u.TimelineSignal.Type.Target) { + var o, + r = this._events.getBefore(n.time); + (o = null === r ? this._initial : r.value), + (i = this._exponentialApproach( + n.time, + o, + n.value, + n.constant, + t + )); + } else + i = + n.type === u.TimelineSignal.Type.Curve + ? this._curveInterpolate(n.time, n.value, n.duration, t) + : null === e + ? n.value + : e.type === u.TimelineSignal.Type.Linear + ? this._linearInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : e.type === u.TimelineSignal.Type.Exponential + ? this._exponentialInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : n.value; + return i; + }), + (u.TimelineSignal.prototype.connect = + u.SignalBase.prototype.connect), + (u.TimelineSignal.prototype._exponentialApproach = function ( + t, + e, + n, + i, + o + ) { + return n + (e - n) * Math.exp(-(o - t) / i); + }), + (u.TimelineSignal.prototype._linearInterpolate = function ( + t, + e, + n, + i, + o + ) { + return e + ((o - t) / (n - t)) * (i - e); + }), + (u.TimelineSignal.prototype._exponentialInterpolate = function ( + t, + e, + n, + i, + o + ) { + return ( + (e = Math.max(this._minOutput, e)) * + Math.pow(i / e, (o - t) / (n - t)) + ); + }), + (u.TimelineSignal.prototype._curveInterpolate = function ( + t, + e, + n, + i + ) { + var o = e.length; + if (t + n <= i) return e[o - 1]; + if (i <= t) return e[0]; + var r = (i - t) / n, + s = Math.floor((o - 1) * r), + a = Math.ceil((o - 1) * r), + u = e[s], + p = e[a]; + return a === s + ? u + : this._linearInterpolate(s, u, a, p, r * (o - 1)); + }), + (u.TimelineSignal.prototype.dispose = function () { + u.Signal.prototype.dispose.call(this), + u.Param.prototype.dispose.call(this), + this._events.dispose(), + (this._events = null); + }), + u.TimelineSignal + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(4); + return ( + (p5.Filter = function (t) { + e.call(this), + (this.biquad = this.ac.createBiquadFilter()), + this.input.connect(this.biquad), + this.biquad.connect(this.wet), + t && this.setType(t), + (this._on = !0), + (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype = Object.create(e.prototype)), + (p5.Filter.prototype.process = function (t, e, n, i) { + t.connect(this.input), this.set(e, n, i); + }), + (p5.Filter.prototype.set = function (t, e, n) { + t && this.freq(t, n), e && this.res(e, n); + }), + (p5.Filter.prototype.freq = function (t, e) { + var n = e || 0; + return ( + t <= 0 && (t = 1), + "number" == typeof t + ? (this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.frequency.exponentialRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.frequency), + this.biquad.frequency.value + ); + }), + (p5.Filter.prototype.res = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.Q.value = t), + this.biquad.Q.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.Q.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.Q), + this.biquad.Q.value + ); + }), + (p5.Filter.prototype.gain = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.gain.value = t), + this.biquad.gain.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.gain.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.gain), + this.biquad.gain.value + ); + }), + (p5.Filter.prototype.toggle = function () { + return ( + (this._on = !this._on), + !0 === this._on + ? (this.biquad.type = this._untoggledType) + : !1 === this._on && (this.biquad.type = "allpass"), + this._on + ); + }), + (p5.Filter.prototype.setType = function (t) { + (this.biquad.type = t), (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.biquad && (this.biquad.disconnect(), delete this.biquad); + }), + (p5.LowPass = function () { + p5.Filter.call(this, "lowpass"); + }), + (p5.LowPass.prototype = Object.create(p5.Filter.prototype)), + (p5.HighPass = function () { + p5.Filter.call(this, "highpass"); + }), + (p5.HighPass.prototype = Object.create(p5.Filter.prototype)), + (p5.BandPass = function () { + p5.Filter.call(this, "bandpass"); + }), + (p5.BandPass.prototype = Object.create(p5.Filter.prototype)), + p5.Filter + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(7), n(25), n(2), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Subtract = function (t) { + this.createInsOuts(2, 0), + (this._sum = this.input[0] = this.output = new e.Gain()), + (this._neg = new e.Negate()), + (this._param = this.input[1] = new e.Signal(t)), + this._param.chain(this._neg, this._sum); + }), + e.extend(e.Subtract, e.Signal), + (e.Subtract.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._neg.dispose(), + (this._neg = null), + this._sum.disconnect(), + (this._sum = null), + this._param.dispose(), + (this._param = null), + this + ); + }), + e.Subtract + ); + }.apply(e, i)) || (t.exports = o); + }, + function (i, o, r) { + "use strict"; + (function (t) { + var e, n; + (t.TONE_SILENCE_VERSION_LOGGING = !0), + (e = [r(35), r(12), r(0)]), + void 0 === + (n = function (i, t, e) { + var o = new window.AudioContext(); + return ( + e.context.dispose(), + e.setContext(o), + (p5.prototype.getAudioContext = function () { + return o; + }), + (p5.prototype.userStartAudio = function (t, e) { + var n = t; + return ( + t instanceof p5.Element + ? (n = t.elt) + : t instanceof Array && + t[0] instanceof p5.Element && + (n = t.map(function (t) { + return t.elt; + })), + i(o, n, e) + ); + }), + o + ); + }.apply(o, e)) || (i.exports = n); + }).call(this, r(34)); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (s) { + "use strict"; + return ( + (s.Emitter = function () { + this._events = {}; + }), + s.extend(s.Emitter), + (s.Emitter.prototype.on = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) { + var o = n[i]; + this._events.hasOwnProperty(o) || (this._events[o] = []), + this._events[o].push(e); + } + return this; + }), + (s.Emitter.prototype.off = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) + if (((t = n[i]), this._events.hasOwnProperty(t))) + if (s.prototype.isUndef(e)) this._events[t] = []; + else + for (var o = this._events[t], r = 0; r < o.length; r++) + o[r] === e && o.splice(r, 1); + return this; + }), + (s.Emitter.prototype.emit = function (t) { + if (this._events) { + var e = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(t)) + for (var n = this._events[t], i = 0, o = n.length; i < o; i++) + n[i].apply(this, e); + } + return this; + }), + (s.Emitter.mixin = function (t) { + var e = ["on", "off", "emit"]; + t._events = {}; + for (var n = 0; n < e.length; n++) { + var i = e[n], + o = s.Emitter.prototype[i]; + t[i] = o; + } + }), + (s.Emitter.prototype.dispose = function () { + return ( + s.prototype.dispose.call(this), (this._events = null), this + ); + }), + s.Emitter + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.SignalBase = function () {}), + i.extend(i.SignalBase), + (i.SignalBase.prototype.connect = function (t, e, n) { + return ( + (i.Signal && i.Signal === t.constructor) || + (i.Param && i.Param === t.constructor) || + (i.TimelineSignal && i.TimelineSignal === t.constructor) + ? (t._param.cancelScheduledValues(0), + (t._param.value = 0), + (t.overridden = !0)) + : t instanceof AudioParam && + (t.cancelScheduledValues(0), (t.value = 0)), + i.prototype.connect.call(this, t, e, n), + this + ); + }), + i.SignalBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (n) { + return ( + (n.Time = function (t, e) { + if (!(this instanceof n.Time)) return new n.Time(t, e); + (this._plusNow = !1), n.TimeBase.call(this, t, e); + }), + n.extend(n.Time, n.TimeBase), + (n.Time.prototype._unaryExpressions = Object.create( + n.TimeBase.prototype._unaryExpressions + )), + (n.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + return n.Transport.nextSubdivision(t()); + }, + }), + (n.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (t) { + return (this._plusNow = !0), t(); + }, + }), + (n.Time.prototype.quantize = function (t, e) { + return ( + (e = this.defaultArg(e, 1)), + (this._expr = function (t, e, n) { + return ( + (t = t()), + (e = e.toSeconds()), + t + (Math.round(t / e) * e - t) * n + ); + }.bind(this, this._expr, new this.constructor(t), e)), + this + ); + }), + (n.Time.prototype.addNow = function () { + return (this._plusNow = !0), this; + }), + (n.Time.prototype._defaultExpr = function () { + return (this._plusNow = !0), this._noOp; + }), + (n.Time.prototype.copy = function (t) { + return ( + n.TimeBase.prototype.copy.call(this, t), + (this._plusNow = t._plusNow), + this + ); + }), + (n.Time.prototype.toNotation = function () { + var t = this.toSeconds(), + e = this._toNotationHelper(t, [ + "1m", + "2n", + "4n", + "8n", + "16n", + "32n", + "64n", + "128n", + ]), + n = this._toNotationHelper(t, [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ]); + return n.split("+").length < e.split("+").length ? n : e; + }), + (n.Time.prototype._toNotationHelper = function (t, e) { + for ( + var n = this._notationToUnits(e[e.length - 1]), i = "", o = 0; + o < e.length; + o++ + ) { + var r = this._notationToUnits(e[o]), + s = t / r; + if ( + (1 - (s % 1) < 1e-6 && (s += 1e-6), 0 < (s = Math.floor(s))) + ) { + if ( + ((i += 1 === s ? e[o] : s.toString() + "*" + e[o]), + (t -= s * r) < n) + ) + break; + i += " + "; + } + } + return "" === i && (i = "0"), i; + }), + (n.Time.prototype._notationToUnits = function (t) { + for ( + var e = this._primaryExpressions, n = [e.n, e.t, e.m], i = 0; + i < n.length; + i++ + ) { + var o = n[i], + r = t.match(o.regexp); + if (r) return o.method.call(this, r[1]); + } + }), + (n.Time.prototype.toBarsBeatsSixteenths = function () { + var t = this._beatsToUnits(1), + e = this.toSeconds() / t, + n = Math.floor(e / this._timeSignature()), + i = (e % 1) * 4; + return ( + (e = Math.floor(e) % this._timeSignature()), + 3 < (i = i.toString()).length && (i = parseFloat(i).toFixed(3)), + [n, e, i].join(":") + ); + }), + (n.Time.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * n.Transport.PPQ); + }), + (n.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }), + (n.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + (n.Time.prototype.toSeconds = function () { + return this.valueOf(); + }), + (n.Time.prototype.toMilliseconds = function () { + return 1e3 * this.toSeconds(); + }), + (n.Time.prototype.valueOf = function () { + return this._expr() + (this._plusNow ? this.now() : 0); + }), + n.Time + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + return ( + (i.TimeBase = function (t, e) { + if (!(this instanceof i.TimeBase)) return new i.TimeBase(t, e); + if (((this._expr = this._noOp), t instanceof i.TimeBase)) + this.copy(t); + else if (!this.isUndef(e) || this.isNumber(t)) { + e = this.defaultArg(e, this._defaultUnits); + var n = this._primaryExpressions[e].method; + this._expr = n.bind(this, t); + } else + this.isString(t) + ? this.set(t) + : this.isUndef(t) && (this._expr = this._defaultExpr()); + }), + i.extend(i.TimeBase), + (i.TimeBase.prototype.set = function (t) { + return (this._expr = this._parseExprString(t)), this; + }), + (i.TimeBase.prototype.clone = function () { + var t = new this.constructor(); + return t.copy(this), t; + }), + (i.TimeBase.prototype.copy = function (t) { + var e = t._expr(); + return this.set(e); + }), + (i.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (t) { + return 1 === (t = parseInt(t)) + ? this._beatsToUnits(this._timeSignature()) + : this._beatsToUnits(4 / t); + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (t) { + return ( + (t = parseInt(t)), this._beatsToUnits(8 / (3 * parseInt(t))) + ); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (t) { + return this._beatsToUnits( + parseInt(t) * this._timeSignature() + ); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (t) { + return this._ticksToUnits(parseInt(t)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (t) { + return this._frequencyToUnits(parseFloat(t)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 0; + return ( + t && + "0" !== t && + (i += this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i += this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i += this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (t) { + return this._secondsToUnits(parseFloat(t)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (t) { + return parseInt(t) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (t) { + return this._primaryExpressions[ + this._defaultUnits + ].method.call(this, t); + }, + }, + }), + (i.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (t, e) { + return t() + e(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (t, e) { + return t() - e(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (t, e) { + return t() * e(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (t, e) { + return t() / e(); + }, + }, + }), + (i.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (t) { + return -t(); + }, + }, + }), + (i.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }), + (i.TimeBase.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim()), this); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t, e) { + for ( + var n = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ], + i = 0; + i < n.length; + i++ + ) { + var o = e[n[i]]; + for (var r in o) { + var s = o[r], + a = s.regexp, + u = t.match(a); + if (null !== u) + return { + method: s.method, + precedence: s.precedence, + regexp: s.regexp, + value: u[0], + }; + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (i.TimeBase.prototype._matchGroup = function (t, e, n) { + if (!this.isUndef(t)) + for (var i in e) { + var o = e[i]; + if (o.regexp.test(t.value)) { + if (this.isUndef(n)) return o; + if (o.precedence === n) return o; + } + } + return !1; + }), + (i.TimeBase.prototype._parseBinary = function (t, e) { + var n; + this.isUndef(e) && (e = 2), + (n = e < 0 ? this._parseUnary(t) : this._parseBinary(t, e - 1)); + for ( + var i = t.peek(); + i && this._matchGroup(i, this._binaryExpressions, e); + + ) + (n = (i = t.next()).method.bind( + this, + n, + this._parseBinary(t, e - 1) + )), + (i = t.peek()); + return n; + }), + (i.TimeBase.prototype._parseUnary = function (t) { + var e, n; + e = t.peek(); + var i = this._matchGroup(e, this._unaryExpressions); + return i + ? ((e = t.next()), + (n = this._parseUnary(t)), + i.method.bind(this, n)) + : this._parsePrimary(t); + }), + (i.TimeBase.prototype._parsePrimary = function (t) { + var e, n; + if (((e = t.peek()), this.isUndef(e))) + throw new SyntaxError( + "Tone.TimeBase: Unexpected end of expression" + ); + if (this._matchGroup(e, this._primaryExpressions)) { + var i = (e = t.next()).value.match(e.regexp); + return e.method.bind(this, i[1], i[2], i[3]); + } + if (e && "(" === e.value) { + if ( + (t.next(), + (n = this._parseBinary(t)), + !(e = t.next()) || ")" !== e.value) + ) + throw new SyntaxError("Expected )"); + return n; + } + throw new SyntaxError( + "Tone.TimeBase: Cannot process token " + e.value + ); + }), + (i.TimeBase.prototype._parseExprString = function (t) { + this.isString(t) || (t = t.toString()); + var e = this._tokenize(t); + return this._parseBinary(e); + }), + (i.TimeBase.prototype._noOp = function () { + return 0; + }), + (i.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }), + (i.TimeBase.prototype._defaultUnits = "s"), + (i.TimeBase.prototype._frequencyToUnits = function (t) { + return 1 / t; + }), + (i.TimeBase.prototype._beatsToUnits = function (t) { + return (60 / i.Transport.bpm.value) * t; + }), + (i.TimeBase.prototype._secondsToUnits = function (t) { + return t; + }), + (i.TimeBase.prototype._ticksToUnits = function (t) { + return t * (this._beatsToUnits(1) / i.Transport.PPQ); + }), + (i.TimeBase.prototype._timeSignature = function () { + return i.Transport.timeSignature; + }), + (i.TimeBase.prototype._pushExpr = function (t, e, n) { + return ( + t instanceof i.TimeBase || (t = new this.constructor(t, n)), + (this._expr = this._binaryExpressions[e].method.bind( + this, + this._expr, + t._expr + )), + this + ); + }), + (i.TimeBase.prototype.add = function (t, e) { + return this._pushExpr(t, "+", e); + }), + (i.TimeBase.prototype.sub = function (t, e) { + return this._pushExpr(t, "-", e); + }), + (i.TimeBase.prototype.mult = function (t, e) { + return this._pushExpr(t, "*", e); + }), + (i.TimeBase.prototype.div = function (t, e) { + return this._pushExpr(t, "/", e); + }), + (i.TimeBase.prototype.valueOf = function () { + return this._expr(); + }), + (i.TimeBase.prototype.dispose = function () { + this._expr = null; + }), + i.TimeBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.Param = function () { + var t = this.optionsObject( + arguments, + ["param", "units", "convert"], + i.Param.defaults + ); + (this._param = this.input = t.param), + (this.units = t.units), + (this.convert = t.convert), + (this.overridden = !1), + (this._lfo = null), + this.isObject(t.lfo) + ? (this.value = t.lfo) + : this.isUndef(t.value) || (this.value = t.value); + }), + i.extend(i.Param), + (i.Param.defaults = { + units: i.Type.Default, + convert: !0, + param: void 0, + }), + Object.defineProperty(i.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (t) { + if (this.isObject(t)) { + if (this.isUndef(i.LFO)) + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + this._lfo && this._lfo.dispose(), + (this._lfo = new i.LFO(t).start()), + this._lfo.connect(this.input); + } else { + var e = this._fromUnits(t); + this._param.cancelScheduledValues(0), (this._param.value = e); + } + }, + }), + (i.Param.prototype._fromUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Time: + return this.toSeconds(t); + case i.Type.Frequency: + return this.toFrequency(t); + case i.Type.Decibels: + return this.dbToGain(t); + case i.Type.NormalRange: + return Math.min(Math.max(t, 0), 1); + case i.Type.AudioRange: + return Math.min(Math.max(t, -1), 1); + case i.Type.Positive: + return Math.max(t, 0); + default: + return t; + } + }), + (i.Param.prototype._toUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Decibels: + return this.gainToDb(t); + default: + return t; + } + }), + (i.Param.prototype._minOutput = 1e-5), + (i.Param.prototype.setValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (e = this.toSeconds(e)) <= this.now() + this.blockTime + ? (this._param.value = t) + : this._param.setValueAtTime(t, e), + this + ); + }), + (i.Param.prototype.setRampPoint = function (t) { + t = this.defaultArg(t, this.now()); + var e = this._param.value; + return ( + 0 === e && (e = this._minOutput), + this._param.setValueAtTime(e, t), + this + ); + }), + (i.Param.prototype.linearRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + this._param.linearRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + this._param.exponentialRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.exponentialRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.linearRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.linearRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.setTargetAtTime = function (t, e, n) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + (n = Math.max(this._minOutput, n)), + this._param.setTargetAtTime(t, this.toSeconds(e), n), + this + ); + }), + (i.Param.prototype.setValueCurveAtTime = function (t, e, n) { + for (var i = 0; i < t.length; i++) t[i] = this._fromUnits(t[i]); + return ( + this._param.setValueCurveAtTime( + t, + this.toSeconds(e), + this.toSeconds(n) + ), + this + ); + }), + (i.Param.prototype.cancelScheduledValues = function (t) { + return this._param.cancelScheduledValues(this.toSeconds(t)), this; + }), + (i.Param.prototype.rampTo = function (t, e, n) { + return ( + (e = this.defaultArg(e, 0)), + this.units === i.Type.Frequency || + this.units === i.Type.BPM || + this.units === i.Type.Decibels + ? this.exponentialRampToValue(t, e, n) + : this.linearRampToValue(t, e, n), + this + ); + }), + Object.defineProperty(i.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, + }), + (i.Param.prototype.dispose = function () { + return ( + i.prototype.dispose.call(this), + (this._param = null), + this._lfo && (this._lfo.dispose(), (this._lfo = null)), + this + ); + }), + i.Param + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1), + o = n(7), + r = n(3), + p = n(13); + (p5.Oscillator = function (t, e) { + if ("string" == typeof t) { + var n = e; + (e = t), (t = n); + } + if ("number" == typeof e) { + n = e; + (e = t), (t = n); + } + (this.started = !1), + (this.phaseAmount = void 0), + (this.oscillator = s.audiocontext.createOscillator()), + (this.f = t || 440), + (this.oscillator.type = e || "sine"), + this.oscillator.frequency.setValueAtTime( + this.f, + s.audiocontext.currentTime + ), + (this.output = s.audiocontext.createGain()), + (this._freqMods = []), + (this.output.gain.value = 0.5), + this.output.gain.setValueAtTime(0.5, s.audiocontext.currentTime), + this.oscillator.connect(this.output), + (this.panPosition = 0), + (this.connection = s.input), + (this.panner = new p5.Panner(this.output, this.connection, 1)), + (this.mathOps = [this.output]), + s.soundArray.push(this); + }), + (p5.Oscillator.prototype.start = function (t, e) { + if (this.started) { + var n = s.audiocontext.currentTime; + this.stop(n); + } + if (!this.started) { + var i = e || this.f, + o = this.oscillator.type; + for (var r in (this.oscillator && + (this.oscillator.disconnect(), delete this.oscillator), + (this.oscillator = s.audiocontext.createOscillator()), + (this.oscillator.frequency.value = Math.abs(i)), + (this.oscillator.type = o), + this.oscillator.connect(this.output), + (t = t || 0), + this.oscillator.start(t + s.audiocontext.currentTime), + (this.freqNode = this.oscillator.frequency), + this._freqMods)) + void 0 !== this._freqMods[r].connect && + this._freqMods[r].connect(this.oscillator.frequency); + this.started = !0; + } + }), + (p5.Oscillator.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), (this.started = !1); + } + }), + (p5.Oscillator.prototype.amp = function (t, e, n) { + if ("number" == typeof t) { + (e = e || 0), (n = n || 0); + var i = s.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime(t, i + n + e); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp), + (p5.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }), + (p5.Oscillator.prototype.freq = function (t, e, n) { + if ("number" != typeof t || isNaN(t)) { + if (!t) return this.oscillator.frequency; + t.output && (t = t.output), + t.connect(this.oscillator.frequency), + this._freqMods.push(t); + } else { + this.f = t; + var i = s.audiocontext.currentTime; + (n = n || 0), (e = e || 0); + 0 === e + ? this.oscillator.frequency.setValueAtTime(t, n + i) + : 0 < t + ? this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ) + : this.oscillator.frequency.linearRampToValueAtTime( + t, + n + e + i + ), + this.phaseAmount && this.phase(this.phaseAmount); + } + }), + (p5.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }), + (p5.Oscillator.prototype.setType = function (t) { + this.oscillator.type = t; + }), + (p5.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }), + (p5.Oscillator.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? (this.panner.connect(t.input), (this.connection = t.input)) + : (this.panner.connect(t), (this.connection = t)) + : this.panner.connect(s.input); + }), + (p5.Oscillator.prototype.disconnect = function () { + this.output && this.output.disconnect(), + this.panner && + (this.panner.disconnect(), + this.output && this.output.connect(this.panner)), + (this.oscMods = []); + }), + (p5.Oscillator.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.Oscillator.prototype.getPan = function () { + return this.panPosition; + }), + (p5.Oscillator.prototype.dispose = function () { + var t = s.soundArray.indexOf(this); + if ((s.soundArray.splice(t, 1), this.oscillator)) { + var e = s.audiocontext.currentTime; + this.stop(e), + this.disconnect(), + (this.panner = null), + (this.oscillator = null); + } + this.osc2 && this.osc2.dispose(); + }), + (p5.Oscillator.prototype.phase = function (t) { + var e = p5.prototype.map(t, 0, 1, 0, 1 / this.f), + n = s.audiocontext.currentTime; + (this.phaseAmount = t), + this.dNode || + ((this.dNode = s.audiocontext.createDelay()), + this.oscillator.disconnect(), + this.oscillator.connect(this.dNode), + this.dNode.connect(this.output)), + this.dNode.delayTime.setValueAtTime(e, n); + }); + function c(t, e, n, i, o) { + var r = t.oscillator; + for (var s in t.mathOps) + t.mathOps[s] instanceof o && + (r.disconnect(), + t.mathOps[s].dispose(), + (n = s) < t.mathOps.length - 2 && (i = t.mathOps[s + 1])); + return ( + n === t.mathOps.length - 1 && t.mathOps.push(i), + 0 < s && (r = t.mathOps[s - 1]), + r.disconnect(), + r.connect(e), + e.connect(i), + (t.mathOps[n] = e), + t + ); + } + (p5.Oscillator.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, o); + }), + (p5.Oscillator.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, r); + }), + (p5.Oscillator.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new p(o, r), + a = this.mathOps.length - 1, + u = this.output; + return c(this, s, a, u, p); + }), + (p5.SinOsc = function (t) { + p5.Oscillator.call(this, t, "sine"); + }), + (p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.TriOsc = function (t) { + p5.Oscillator.call(this, t, "triangle"); + }), + (p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SawOsc = function (t) { + p5.Oscillator.call(this, t, "sawtooth"); + }), + (p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SqrOsc = function (t) { + p5.Oscillator.call(this, t, "square"); + }), + (p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Timeline = function () { + var t = this.optionsObject( + arguments, + ["memory"], + e.Timeline.defaults + ); + (this._timeline = []), + (this._toRemove = []), + (this._iterating = !1), + (this.memory = t.memory); + }), + e.extend(e.Timeline), + (e.Timeline.defaults = { memory: 1 / 0 }), + Object.defineProperty(e.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }), + (e.Timeline.prototype.add = function (t) { + if (this.isUndef(t.time)) + throw new Error( + "Tone.Timeline: events must have a time attribute" + ); + if (this._timeline.length) { + var e = this._search(t.time); + this._timeline.splice(e + 1, 0, t); + } else this._timeline.push(t); + if (this.length > this.memory) { + var n = this.length - this.memory; + this._timeline.splice(0, n); + } + return this; + }), + (e.Timeline.prototype.remove = function (t) { + if (this._iterating) this._toRemove.push(t); + else { + var e = this._timeline.indexOf(t); + -1 !== e && this._timeline.splice(e, 1); + } + return this; + }), + (e.Timeline.prototype.get = function (t) { + var e = this._search(t); + return -1 !== e ? this._timeline[e] : null; + }), + (e.Timeline.prototype.peek = function () { + return this._timeline[0]; + }), + (e.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }), + (e.Timeline.prototype.getAfter = function (t) { + var e = this._search(t); + return e + 1 < this._timeline.length + ? this._timeline[e + 1] + : null; + }), + (e.Timeline.prototype.getBefore = function (t) { + var e = this._timeline.length; + if (0 < e && this._timeline[e - 1].time < t) + return this._timeline[e - 1]; + var n = this._search(t); + return 0 <= n - 1 ? this._timeline[n - 1] : null; + }), + (e.Timeline.prototype.cancel = function (t) { + if (1 < this._timeline.length) { + var e = this._search(t); + if (0 <= e) + if (this._timeline[e].time === t) { + for (var n = e; 0 <= n && this._timeline[n].time === t; n--) + e = n; + this._timeline = this._timeline.slice(0, e); + } else this._timeline = this._timeline.slice(0, e + 1); + else this._timeline = []; + } else + 1 === this._timeline.length && + this._timeline[0].time >= t && + (this._timeline = []); + return this; + }), + (e.Timeline.prototype.cancelBefore = function (t) { + if (this._timeline.length) { + var e = this._search(t); + 0 <= e && (this._timeline = this._timeline.slice(e + 1)); + } + return this; + }), + (e.Timeline.prototype._search = function (t) { + var e = 0, + n = this._timeline.length, + i = n; + if (0 < n && this._timeline[n - 1].time <= t) return n - 1; + for (; e < i; ) { + var o = Math.floor(e + (i - e) / 2), + r = this._timeline[o], + s = this._timeline[o + 1]; + if (r.time === t) { + for (var a = o; a < this._timeline.length; a++) + this._timeline[a].time === t && (o = a); + return o; + } + if (r.time < t && s.time > t) return o; + r.time > t ? (i = o) : r.time < t && (e = o + 1); + } + return -1; + }), + (e.Timeline.prototype._iterate = function (t, e, n) { + (this._iterating = !0), + (e = this.defaultArg(e, 0)), + (n = this.defaultArg(n, this._timeline.length - 1)); + for (var i = e; i <= n; i++) t(this._timeline[i]); + if (((this._iterating = !1), 0 < this._toRemove.length)) { + for (var o = 0; o < this._toRemove.length; o++) { + var r = this._timeline.indexOf(this._toRemove[o]); + -1 !== r && this._timeline.splice(r, 1); + } + this._toRemove = []; + } + }), + (e.Timeline.prototype.forEach = function (t) { + return this._iterate(t), this; + }), + (e.Timeline.prototype.forEachBefore = function (t, e) { + var n = this._search(t); + return -1 !== n && this._iterate(e, 0, n), this; + }), + (e.Timeline.prototype.forEachAfter = function (t, e) { + var n = this._search(t); + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachFrom = function (t, e) { + for ( + var n = this._search(t); + 0 <= n && this._timeline[n].time >= t; + + ) + n--; + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachAtTime = function (e, n) { + var t = this._search(e); + return ( + -1 !== t && + this._iterate( + function (t) { + t.time === e && n(t); + }, + 0, + t + ), + this + ); + }), + (e.Timeline.prototype.dispose = function () { + e.prototype.dispose.call(this), + (this._timeline = null), + (this._toRemove = null); + }), + e.Timeline + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(3), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Negate = function () { + this._multiply = this.input = this.output = new t.Multiply(-1); + }), + t.extend(t.Negate, t.SignalBase), + (t.Negate.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._multiply.dispose(), + (this._multiply = null), + this + ); + }), + t.Negate + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(3), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.GreaterThanZero = function () { + (this._thresh = this.output = + new t.WaveShaper(function (t) { + return t <= 0 ? 0 : 1; + }, 127)), + (this._scale = this.input = new t.Multiply(1e4)), + this._scale.connect(this._thresh); + }), + t.extend(t.GreaterThanZero, t.SignalBase), + (t.GreaterThanZero.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._scale.dispose(), + (this._scale = null), + this._thresh.dispose(), + (this._thresh = null), + this + ); + }), + t.GreaterThanZero + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(14), n(66), n(18), n(12)]), + void 0 === + (o = function (o) { + "use strict"; + return ( + (o.Clock = function () { + o.Emitter.call(this); + var t = this.optionsObject( + arguments, + ["callback", "frequency"], + o.Clock.defaults + ); + (this.callback = t.callback), + (this._nextTick = 0), + (this._lastState = o.State.Stopped), + (this.frequency = new o.TimelineSignal( + t.frequency, + o.Type.Frequency + )), + this._readOnly("frequency"), + (this.ticks = 0), + (this._state = new o.TimelineState(o.State.Stopped)), + (this._boundLoop = this._loop.bind(this)), + this.context.on("tick", this._boundLoop); + }), + o.extend(o.Clock, o.Emitter), + (o.Clock.defaults = { + callback: o.noOp, + frequency: 1, + lookAhead: "auto", + }), + Object.defineProperty(o.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }), + (o.Clock.prototype.start = function (t, e) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) !== o.State.Started && + this._state.add({ + state: o.State.Started, + time: t, + offset: e, + }), + this + ); + }), + (o.Clock.prototype.stop = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.cancel(t), + this._state.setStateAtTime(o.State.Stopped, t), + this + ); + }), + (o.Clock.prototype.pause = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) === o.State.Started && + this._state.setStateAtTime(o.State.Paused, t), + this + ); + }), + (o.Clock.prototype._loop = function () { + for ( + var t = + this.now() + + this.context.lookAhead + + this.context.updateInterval + + 2 * this.context.lag; + t > this._nextTick && this._state; + + ) { + var e = this._state.getValueAtTime(this._nextTick); + if (e !== this._lastState) { + this._lastState = e; + var n = this._state.get(this._nextTick); + e === o.State.Started + ? ((this._nextTick = n.time), + this.isUndef(n.offset) || (this.ticks = n.offset), + this.emit("start", n.time, this.ticks)) + : e === o.State.Stopped + ? ((this.ticks = 0), this.emit("stop", n.time)) + : e === o.State.Paused && this.emit("pause", n.time); + } + var i = this._nextTick; + this.frequency && + ((this._nextTick += + 1 / this.frequency.getValueAtTime(this._nextTick)), + e === o.State.Started && (this.callback(i), this.ticks++)); + } + }), + (o.Clock.prototype.getStateAtTime = function (t) { + return (t = this.toSeconds(t)), this._state.getValueAtTime(t); + }), + (o.Clock.prototype.dispose = function () { + o.Emitter.prototype.dispose.call(this), + this.context.off("tick", this._boundLoop), + this._writable("frequency"), + this.frequency.dispose(), + (this.frequency = null), + (this._boundLoop = null), + (this._nextTick = 1 / 0), + (this.callback = null), + this._state.dispose(), + (this._state = null); + }), + o.Clock + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = i(1), + e = i(29), + r = i(6).noteToFreq; + (p5.MonoSynth = function () { + e.call(this), + (this.oscillator = new p5.Oscillator()), + (this.env = new p5.Envelope()), + this.env.setRange(1, 0), + this.env.setExp(!0), + this.setADSR(0.02, 0.25, 0.05, 0.35), + this.oscillator.disconnect(), + this.oscillator.connect(this.output), + this.env.disconnect(), + this.env.setInput(this.output.gain), + (this.oscillator.output.gain.value = 1), + this.oscillator.start(), + this.connect(), + n.soundArray.push(this); + }), + (p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype)), + (p5.MonoSynth.prototype.play = function (t, e, n, i) { + this.triggerAttack(t, e, ~~n), + this.triggerRelease(~~n + (i || 0.15)); + }), + (p5.MonoSynth.prototype.triggerAttack = function (t, e, n) { + n = ~~n; + var i = r(t), + o = e || 0.1; + this.oscillator.freq(i, 0, n), + this.env.ramp(this.output.gain, n, o); + }), + (p5.MonoSynth.prototype.triggerRelease = function (t) { + t = t || 0; + this.env.ramp(this.output.gain, t, 0); + }), + (p5.MonoSynth.prototype.setADSR = function (t, e, n, i) { + this.env.setADSR(t, e, n, i); + }), + Object.defineProperties(p5.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (t) { + this.env.setADSR( + t, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, + }, + decay: { + get: function () { + return this.env.dTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + t, + this.env.sPercent, + this.env.rTime + ); + }, + }, + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + t, + this.env.rTime + ); + }, + }, + release: { + get: function () { + return this.env.rTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + t + ); + }, + }, + }), + (p5.MonoSynth.prototype.amp = function (t, e) { + var n = e || 0; + return ( + void 0 !== t && this.oscillator.amp(t, n), + this.oscillator.amp().value + ); + }), + (p5.MonoSynth.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.MonoSynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.MonoSynth.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.env && this.env.dispose(), + this.oscillator && this.oscillator.dispose(); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function () { + var n = i(1); + return ( + (p5.AudioVoice = function () { + (this.ac = n.audiocontext), + (this.output = this.ac.createGain()), + this.connect(), + n.soundArray.push(this); + }), + (p5.AudioVoice.prototype.play = function (t, e, n, i) {}), + (p5.AudioVoice.prototype.triggerAttack = function (t, e, n) {}), + (p5.AudioVoice.prototype.triggerRelease = function (t) {}), + (p5.AudioVoice.prototype.amp = function (t, e) {}), + (p5.AudioVoice.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.AudioVoice.prototype.disconnect = function () { + this.output.disconnect(); + }), + (p5.AudioVoice.prototype.dispose = function () { + this.output && (this.output.disconnect(), delete this.output); + }), + p5.AudioVoice + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var c = n(1), + h = n(14), + l = n(6).noteToFreq; + (p5.PolySynth = function (t, e) { + (this.audiovoices = []), + (this.notes = {}), + (this._newest = 0), + (this._oldest = 0), + (this.maxVoices = e || 8), + (this.AudioVoice = void 0 === t ? p5.MonoSynth : t), + (this._voicesInUse = new h(0)), + (this.output = c.audiocontext.createGain()), + this.connect(), + this._allocateVoices(), + c.soundArray.push(this); + }), + (p5.PolySynth.prototype._allocateVoices = function () { + for (var t = 0; t < this.maxVoices; t++) + this.audiovoices.push(new this.AudioVoice()), + this.audiovoices[t].disconnect(), + this.audiovoices[t].connect(this.output); + }), + (p5.PolySynth.prototype.play = function (t, e, n, i) { + i = i || 1; + this.noteAttack(t, e, n), this.noteRelease(t, n + i); + }), + (p5.PolySynth.prototype.noteADSR = function (t, e, n, i, o, r) { + var s = c.audiocontext.currentTime + (r = r || 0); + this.audiovoices[this.notes[t].getValueAtTime(s)].setADSR( + e, + n, + i, + o + ); + }), + (p5.PolySynth.prototype.setADSR = function (e, n, i, o) { + this.audiovoices.forEach(function (t) { + t.setADSR(e, n, i, o); + }); + }), + (p5.PolySynth.prototype.noteAttack = function (t, e, n) { + n = ~~n; + var i, + o = c.audiocontext.currentTime + n, + r = l(t), + s = e || 0.1; + if ( + (this.notes[r] && + null !== this.notes[r].getValueAtTime(o) && + this.noteRelease(r, 0), + this._voicesInUse.getValueAtTime(o) < this.maxVoices) + ) + i = Math.max(~~this._voicesInUse.getValueAtTime(o), 0); + else { + i = this._oldest; + var a = p5.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(a), + (this._oldest = (this._oldest + 1) % (this.maxVoices - 1)); + } + (this.notes[r] = new h()), this.notes[r].setValueAtTime(i, o); + var u = + null === this._voicesInUse._searchBefore(o) + ? 0 + : this._voicesInUse._searchBefore(o).value; + if ( + (this._voicesInUse.setValueAtTime(u + 1, o), + this._updateAfter(o, 1), + (this._newest = i), + "number" == typeof s) + ) { + var p = (1 / this._voicesInUse.getValueAtTime(o)) * 2; + s = p < s ? p : s; + } + this.audiovoices[i].triggerAttack(r, s, n); + }), + (p5.PolySynth.prototype._updateAfter = function (t, e) { + if (null !== this._voicesInUse._searchAfter(t)) { + this._voicesInUse._searchAfter(t).value += e; + var n = this._voicesInUse._searchAfter(t).time; + this._updateAfter(n, e); + } + }), + (p5.PolySynth.prototype.noteRelease = function (t, e) { + var n = c.audiocontext.currentTime, + i = e || 0, + o = n + i; + if (t) { + var r = l(t); + if (this.notes[r] && null !== this.notes[r].getValueAtTime(o)) { + var s = Math.max( + ~~this._voicesInUse.getValueAtTime(o).value, + 1 + ); + this._voicesInUse.setValueAtTime(s - 1, o), + 0 < s && this._updateAfter(o, -1), + this.audiovoices[ + this.notes[r].getValueAtTime(o) + ].triggerRelease(i), + this.notes[r].dispose(), + delete this.notes[r], + (this._newest = + 0 === this._newest + ? 0 + : (this._newest - 1) % (this.maxVoices - 1)); + } else; + } else + for (var a in (this.audiovoices.forEach(function (t) { + t.triggerRelease(i); + }), + this._voicesInUse.setValueAtTime(0, o), + this.notes)) + this.notes[a].dispose(), delete this.notes[a]; + }), + (p5.PolySynth.prototype.connect = function (t) { + var e = t || c.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.PolySynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (t) { + t.dispose(); + }), + this.output && (this.output.disconnect(), delete this.output); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(32), n(33), n(17); + var e = n(1); + return ( + n(6), + n(11), + n(36), + n(40), + n(41), + n(42), + n(43), + n(44), + n(23), + n(47), + n(48), + n(49), + n(50), + n(15), + n(59), + n(61), + n(62), + n(63), + n(64), + n(65), + n(67), + n(68), + n(69), + n(70), + n(71), + n(72), + n(28), + n(30), + n(73), + n(29), + n(28), + n(30), + e + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + function c(t) { + var i = this, + o = {}, + r = -1; + this.parameters.forEach(function (t, e) { + var n = a[++r] || (a[r] = new Float32Array(i.bufferSize)); + n.fill(t.value), (o[e] = n); + }), + this.processor.realm.exec( + "self.sampleRate=sampleRate=" + + this.context.sampleRate + + ";self.currentTime=currentTime=" + + this.context.currentTime + ); + var e = s(t.inputBuffer), + n = s(t.outputBuffer); + this.instance.process([e], [n], o); + } + function s(t) { + for (var e = [], n = 0; n < t.numberOfChannels; n++) + e[n] = t.getChannelData(n); + return e; + } + function h(t) { + return t.$$processors || (t.$$processors = {}); + } + function n(t) { + this.$$context = t; + } + var l, a; + (a = []), + "function" != typeof AudioWorkletNode && + ((self.AudioWorkletNode = function (t, e, n) { + var i = h(t)[e], + o = t.createScriptProcessor( + void 0, + 2, + n && n.outputChannelCount ? n.outputChannelCount[0] : 2 + ); + if (((o.parameters = new Map()), i.properties)) + for (var r = 0; r < i.properties.length; r++) { + var s = i.properties[r], + a = t.createGain().gain; + (a.value = s.defaultValue), o.parameters.set(s.name, a); + } + var u = new MessageChannel(); + l = u.port2; + var p = new i.Processor(n || {}); + return ( + (l = null), + (o.port = u.port1), + (o.processor = i), + (o.instance = p), + (o.onaudioprocess = c), + o + ); + }), + Object.defineProperty( + (self.AudioContext || self.webkitAudioContext).prototype, + "audioWorklet", + { + get: function () { + return ( + this.$$audioWorklet || + (this.$$audioWorklet = new self.AudioWorklet(this)) + ); + }, + } + ), + (self.AudioWorklet = + ((n.prototype.addModule = function (t, e) { + var o = this; + return fetch(t) + .then(function (t) { + if (!t.ok) throw Error(t.status); + return t.text(); + }) + .then(function (t) { + var n = { + sampleRate: 0, + currentTime: 0, + AudioWorkletProcessor: function () { + this.port = l; + }, + registerProcessor: function (t, e) { + h(o.$$context)[t] = { + realm: i, + context: n, + Processor: e, + properties: e.parameterDescriptors || [], + }; + }, + }, + i = new (function (t, e) { + var n = document.createElement("iframe"); + (n.style.cssText = + "position:absolute;left:0;top:-999px;width:1px;height:1px;"), + e.appendChild(n); + var i = n.contentWindow, + o = i.document, + r = "var window,$hook"; + for (var s in i) + s in t || "eval" === s || ((r += ","), (r += s)); + for (var a in t) + (r += ","), (r += a), (r += "=self."), (r += a); + var u = o.createElement("script"); + u.appendChild( + o.createTextNode( + 'function $hook(self,console) {"use strict";\n ' + + r + + ";return function() {return eval(arguments[0])}}" + ) + ), + o.body.appendChild(u), + (this.exec = i.$hook(t, console)); + })((n.self = n), document.documentElement); + return i.exec(((e && e.transpile) || String)(t)), null; + }); + }), + n))); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + function n(t) { + t && + (t.setTargetAtTime || (t.setTargetAtTime = t.setTargetValueAtTime)); + } + window, + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") && + ((window.AudioContext = window.webkitAudioContext), + "function" != typeof AudioContext.prototype.createGain && + (AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode), + "function" != typeof AudioContext.prototype.createDelay && + (AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode), + "function" != typeof AudioContext.prototype.createScriptProcessor && + (AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode), + "function" != typeof AudioContext.prototype.createPeriodicWave && + (AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable), + (AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain), + (AudioContext.prototype.createGain = function () { + var t = this.internal_createGain(); + return n(t.gain), t; + }), + (AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay), + (AudioContext.prototype.createDelay = function (t) { + var e = t + ? this.internal_createDelay(t) + : this.internal_createDelay(); + return n(e.delayTime), e; + }), + (AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource), + (AudioContext.prototype.createBufferSource = function () { + var i = this.internal_createBufferSource(); + return ( + i.start + ? ((i.internal_start = i.start), + (i.start = function (t, e, n) { + void 0 !== n + ? i.internal_start(t || 0, e, n) + : i.internal_start(t || 0, e || 0); + })) + : (i.start = function (t, e, n) { + e || n + ? this.noteGrainOn(t || 0, e, n) + : this.noteOn(t || 0); + }), + i.stop + ? ((i.internal_stop = i.stop), + (i.stop = function (t) { + i.internal_stop(t || 0); + })) + : (i.stop = function (t) { + this.noteOff(t || 0); + }), + n(i.playbackRate), + i + ); + }), + (AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor), + (AudioContext.prototype.createDynamicsCompressor = function () { + var t = this.internal_createDynamicsCompressor(); + return ( + n(t.threshold), + n(t.knee), + n(t.ratio), + n(t.reduction), + n(t.attack), + n(t.release), + t + ); + }), + (AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter), + (AudioContext.prototype.createBiquadFilter = function () { + var t = this.internal_createBiquadFilter(); + return n(t.frequency), n(t.detune), n(t.Q), n(t.gain), t; + }), + "function" != typeof AudioContext.prototype.createOscillator && + ((AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator), + (AudioContext.prototype.createOscillator = function () { + var e = this.internal_createOscillator(); + return ( + e.start + ? ((e.internal_start = e.start), + (e.start = function (t) { + e.internal_start(t || 0); + })) + : (e.start = function (t) { + this.noteOn(t || 0); + }), + e.stop + ? ((e.internal_stop = e.stop), + (e.stop = function (t) { + e.internal_stop(t || 0); + })) + : (e.stop = function (t) { + this.noteOff(t || 0); + }), + e.setPeriodicWave || (e.setPeriodicWave = e.setWaveTable), + n(e.frequency), + n(e.detune), + e + ); + }))), + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") && + (window.OfflineAudioContext = window.webkitOfflineAudioContext), + (navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia); + var e = document.createElement("audio"); + p5.prototype.isSupported = function () { + return !!e.canPlayType; + }; + p5.prototype.isFileSupported = function (t) { + switch (t.toLowerCase()) { + case "mp3": + return !!e.canPlayType && e.canPlayType("audio/mpeg;"); + case "wav": + return !!e.canPlayType && e.canPlayType('audio/wav; codecs="1"'); + case "ogg": + return ( + !!e.canPlayType && e.canPlayType('audio/ogg; codecs="vorbis"') + ); + case "aac": + case "m4a": + case "mp4": + return ( + !!e.canPlayType && + (e.canPlayType("audio/x-m4a;") || e.canPlayType("audio/aac;")) + ); + case "aif": + case "aiff": + return !!e.canPlayType && e.canPlayType("audio/x-aiff;"); + default: + return !1; + } + }; + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + var n; + n = (function () { + return this; + })(); + try { + n = n || new Function("return this")(); + } catch (t) { + "object" == typeof window && (n = window); + } + t.exports = n; + }, + function (t, e, n) { + var i, o, r; + (o = []), + void 0 === + (r = + "function" == + typeof (i = function () { + var s = function (t, e) { + (this._dragged = !1), + (this._element = t), + (this._bindedMove = this._moved.bind(this)), + (this._bindedEnd = this._ended.bind(this, e)), + t.addEventListener("touchstart", this._bindedEnd), + t.addEventListener("touchmove", this._bindedMove), + t.addEventListener("touchend", this._bindedEnd), + t.addEventListener("mouseup", this._bindedEnd); + }; + function r(t) { + return "running" === t.state; + } + return ( + (s.prototype._moved = function (t) { + this._dragged = !0; + }), + (s.prototype._ended = function (t) { + this._dragged || + (function (t) { + var e = t.createBuffer(1, 1, t.sampleRate), + n = t.createBufferSource(); + (n.buffer = e), + n.connect(t.destination), + n.start(0), + t.resume && t.resume(); + })(t), + (this._dragged = !1); + }), + (s.prototype.dispose = function () { + this._element.removeEventListener( + "touchstart", + this._bindedEnd + ), + this._element.removeEventListener( + "touchmove", + this._bindedMove + ), + this._element.removeEventListener( + "touchend", + this._bindedEnd + ), + this._element.removeEventListener("mouseup", this._bindedEnd), + (this._bindedMove = null), + (this._bindedEnd = null), + (this._element = null); + }), + function (e, t, n) { + var i = new Promise(function (t) { + !(function (e, n) { + r(e) + ? n() + : (function t() { + r(e) + ? n() + : (requestAnimationFrame(t), + e.resume && e.resume()); + })(); + })(e, t); + }), + o = []; + return ( + (function t(e, n, i) { + if (Array.isArray(e) || (NodeList && e instanceof NodeList)) + for (var o = 0; o < e.length; o++) t(e[o], n, i); + else if ("string" == typeof e) + t(document.querySelectorAll(e), n, i); + else if (e.jquery && "function" == typeof e.toArray) + t(e.toArray(), n, i); + else if (Element && e instanceof Element) { + var r = new s(e, i); + n.push(r); + } + })((t = t || document.body), o, e), + i.then(function () { + for (var t = 0; t < o.length; t++) o[t].dispose(); + (o = null), n && n(); + }), + i + ); + } + ); + }) + ? i.apply(e, o) + : i) || (t.exports = r); + }, + function (t, e, n) { + var i = n(1), + o = [n(37).default, n(38).default, n(39).default], + r = i.audiocontext, + s = !1; + p5.prototype.registerMethod("init", function () { + if (!s) { + this.preload || window.preload || (this.preload = function () {}), + this._incrementPreload(); + var t = function () { + (s = !0), this._decrementPreload(); + }.bind(this); + Promise.all( + o.map(function (t) { + var e = new Blob([t], { type: "application/javascript" }), + n = URL.createObjectURL(e); + return r.audioWorklet.addModule(n); + }) + ).then(t); + } + }); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'); + }, + function (t, e, n) { + "use strict"; + var i; + function o(t) { + return (o = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (i = function (t) { + var a = n(1).audiocontext; + void 0 !== a.createStereoPanner + ? ((p5.Panner = function (t, e) { + (this.stereoPanner = this.input = a.createStereoPanner()), + t.connect(this.stereoPanner), + this.stereoPanner.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n; + this.stereoPanner.pan.linearRampToValueAtTime(t, i); + }), + (p5.Panner.prototype.inputChannels = function () {}), + (p5.Panner.prototype.connect = function (t) { + this.stereoPanner.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.stereoPanner && this.stereoPanner.disconnect(); + })) + : ((p5.Panner = function (t, e, n) { + (this.input = a.createGain()), + t.connect(this.input), + (this.left = a.createGain()), + (this.right = a.createGain()), + (this.left.channelInterpretation = "discrete"), + (this.right.channelInterpretation = "discrete"), + 1 < n + ? ((this.splitter = a.createChannelSplitter(2)), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)) + : (this.input.connect(this.left), + this.input.connect(this.right)), + (this.output = a.createChannelMerger(2)), + this.left.connect(this.output, 0, 1), + this.right.connect(this.output, 0, 0), + this.output.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n, + o = (t + 1) / 2, + r = Math.cos((o * Math.PI) / 2), + s = Math.sin((o * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(s, i), + this.right.gain.linearRampToValueAtTime(r, i); + }), + (p5.Panner.prototype.inputChannels = function (t) { + 1 === t + ? (this.input.disconnect(), + this.input.connect(this.left), + this.input.connect(this.right)) + : 2 === t && + (o("undefined" === this.splitter) && + (this.splitter = a.createChannelSplitter(2)), + this.input.disconnect(), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)); + }), + (p5.Panner.prototype.connect = function (t) { + this.output.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.output && this.output.disconnect(); + })); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, o) { + "use strict"; + var n; + function l(t) { + return (l = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (n = function (t) { + var a = o(11), + u = o(1), + p = u.audiocontext, + e = o(6), + n = e.midiToFreq, + i = e.convertToWav, + r = e.safeBufferSize, + s = o(10); + (p5.SoundFile = function (t, e, n, i) { + if (void 0 !== t) { + if ("string" == typeof t || "string" == typeof t[0]) { + var o = p5.prototype._checkFileFormats(t); + this.url = o; + } else if ( + "object" === l(t) && + !( + window.File && + window.FileReader && + window.FileList && + window.Blob + ) + ) + throw "Unable to load file because the File API is not supported"; + t.file && (t = t.file), (this.file = t); + } + (this._onended = function () {}), + (this._looping = !1), + (this._playing = !1), + (this._paused = !1), + (this._pauseTime = 0), + (this._cues = []), + (this._cueIDCounter = 0), + (this._lastPos = 0), + (this._counterNode = null), + (this._workletNode = null), + (this.bufferSourceNodes = []), + (this.bufferSourceNode = null), + (this.buffer = null), + (this.playbackRate = 1), + (this.input = u.audiocontext.createGain()), + (this.output = u.audiocontext.createGain()), + (this.reversed = !1), + (this.startTime = 0), + (this.endTime = null), + (this.pauseTime = 0), + (this.mode = "sustain"), + (this.startMillis = null), + (this.panPosition = 0), + (this.panner = new p5.Panner(this.output, u.input, 2)), + (this.url || this.file) && this.load(e, n), + u.soundArray.push(this), + (this._whileLoading = "function" == typeof i ? i : function () {}), + (this._clearOnEnd = function (t) { + var e = t.target, + n = this; + (e._playing = !1), + e.removeEventListener("ended", n._clearOnEnd), + n._onended(n), + n.bufferSourceNodes + .map(function (t, e) { + return e; + }) + .reverse() + .forEach(function (t) { + !1 === n.bufferSourceNodes[t]._playing && + n.bufferSourceNodes.splice(t, 1); + }), + 0 === n.bufferSourceNodes.length && (n._playing = !1); + }.bind(this)); + }), + p5.prototype.registerPreloadMethod("loadSound", p5.prototype), + (p5.prototype.loadSound = function (t, e, n, i) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var o = this; + return new p5.SoundFile( + t, + function () { + "function" == typeof e && e.apply(o, arguments), + "function" == typeof o._decrementPreload && + o._decrementPreload(); + }, + n, + i + ); + }), + (p5.SoundFile.prototype.load = function (n, i) { + var o = this, + r = new Error().stack; + if (void 0 !== this.url && "" !== this.url) { + var s = new XMLHttpRequest(); + s.addEventListener( + "progress", + function (t) { + o._updateProgress(t); + }, + !1 + ), + s.open("GET", this.url, !0), + (s.responseType = "arraybuffer"), + (s.onload = function () { + if (200 === s.status) { + if (!o.panner) return; + p.decodeAudioData( + s.response, + function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }, + function () { + if (o.panner) { + var t = new a("decodeAudioData", r, o.url), + e = + "AudioContext error at decodeAudioData for " + + o.url; + i && ((t.msg = e), i(t)); + } + } + ); + } else { + if (!o.panner) return; + var t = new a("loadSound", r, o.url), + e = + "Unable to load " + + o.url + + ". The request status was: " + + s.status + + " (" + + s.statusText + + ")"; + i && ((t.message = e), i(t)); + } + }), + (s.onerror = function () { + var t = new a("loadSound", r, o.url), + e = + "There was no response from the server at " + + o.url + + ". Check the url and internet connectivity."; + i && ((t.message = e), i(t)); + }), + s.send(); + } else if (void 0 !== this.file) { + var t = new FileReader(); + (t.onload = function () { + o.panner && + p.decodeAudioData(t.result, function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }); + }), + (t.onerror = function (t) { + o.panner && onerror && onerror(t); + }), + t.readAsArrayBuffer(this.file); + } + }), + (p5.SoundFile.prototype._updateProgress = function (t) { + if (t.lengthComputable) { + var e = (t.loaded / t.total) * 0.99; + this._whileLoading(e, t); + } else this._whileLoading("size unknown"); + }), + (p5.SoundFile.prototype.isLoaded = function () { + return !!this.buffer; + }), + (p5.SoundFile.prototype.play = function (t, e, n, i, o) { + if (this.output) { + var r, + s, + a = t || 0; + if ( + (a < 0 && (a = 0), + (a += u.audiocontext.currentTime), + void 0 !== e && this.rate(e), + void 0 !== n && this.setVolume(n), + !this.buffer) + ) + throw "not ready to play file, buffer has yet to load. Try preload()"; + if ( + ((this._pauseTime = 0), + "restart" === this.mode && + this.buffer && + this.bufferSourceNode && + (this.bufferSourceNode.stop(a), this._counterNode.stop(a)), + "untildone" !== this.mode || !this.isPlaying()) + ) { + if ( + ((this.bufferSourceNode = this._initSourceNode()), + delete this._counterNode, + (this._counterNode = this._initCounterNode()), + i) + ) { + if (!(0 <= i && i < this.buffer.duration)) + throw "start time out of range"; + r = i; + } else r = 0; + (o = + o && + (o <= this.buffer.duration - r ? o : this.buffer.duration)), + this._paused + ? (this.bufferSourceNode.start(a, this.pauseTime, o), + this._counterNode.start(a, this.pauseTime, o)) + : (this.bufferSourceNode.start(a, r, o), + this._counterNode.start(a, r, o)), + (this._playing = !0), + (this._paused = !1), + this.bufferSourceNodes.push(this.bufferSourceNode), + (this.bufferSourceNode._arrayIndex = + this.bufferSourceNodes.length - 1), + this.bufferSourceNode.addEventListener( + "ended", + this._clearOnEnd + ), + (this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping), + !0 === this._looping && + ((s = o || r - 1e-15), + (this.bufferSourceNode.loopStart = r), + (this.bufferSourceNode.loopEnd = s), + (this._counterNode.loopStart = r), + (this._counterNode.loopEnd = s)); + } + } + }), + (p5.SoundFile.prototype.playMode = function (t) { + var e = t.toLowerCase(); + if ("restart" === e && this.buffer && this.bufferSourceNode) + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) { + var i = u.audiocontext.currentTime; + this.bufferSourceNodes[n].stop(i); + } + if ("restart" !== e && "sustain" !== e && "untildone" !== e) + throw 'Invalid play mode. Must be either "restart" or "sustain"'; + this.mode = e; + }), + (p5.SoundFile.prototype.pause = function (t) { + var e = (t || 0) + u.audiocontext.currentTime; + this.isPlaying() && this.buffer && this.bufferSourceNode + ? ((this._paused = !0), + (this._playing = !1), + (this.pauseTime = this.currentTime()), + this.bufferSourceNode.stop(e), + this._counterNode.stop(e), + (this._pauseTime = this.currentTime())) + : (this._pauseTime = 0); + }), + (p5.SoundFile.prototype.loop = function (t, e, n, i, o) { + (this._looping = !0), this.play(t, e, n, i, o); + }), + (p5.SoundFile.prototype.setLoop = function (t) { + if (!0 === t) this._looping = !0; + else { + if (!1 !== t) throw "Error: setLoop accepts either true or false"; + this._looping = !1; + } + this.bufferSourceNode && + ((this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping)); + }), + (p5.SoundFile.prototype.isLooping = function () { + return ( + !!this.bufferSourceNode && + !0 === this._looping && + !0 === this.isPlaying() + ); + }), + (p5.SoundFile.prototype.isPlaying = function () { + return this._playing; + }), + (p5.SoundFile.prototype.isPaused = function () { + return this._paused; + }), + (p5.SoundFile.prototype.stop = function (t) { + var e = t || 0; + if ("sustain" === this.mode || "untildone" === this.mode) + this.stopAll(e), + (this._playing = !1), + (this.pauseTime = 0), + (this._paused = !1); + else if (this.buffer && this.bufferSourceNode) { + var n = u.audiocontext.currentTime, + i = e || 0; + (this.pauseTime = 0), + this.bufferSourceNode.stop(n + i), + this._counterNode.stop(n + i), + (this._playing = !1), + (this._paused = !1); + } + }), + (p5.SoundFile.prototype.stopAll = function (t) { + var e = u.audiocontext.currentTime, + n = t || 0; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + var o = this.bufferSourceNodes[i]; + if (o) + try { + o.stop(e + n); + } catch (t) {} + } + this._counterNode.stop(e + n), this._onended(this); + } + }), + (p5.SoundFile.prototype.setVolume = function (t, e, n) { + if ("number" == typeof t) { + var i = e || 0, + o = n || 0, + r = u.audiocontext.currentTime, + s = this.output.gain.value; + this.output.gain.cancelScheduledValues(r + o), + this.output.gain.linearRampToValueAtTime(s, r + o), + this.output.gain.linearRampToValueAtTime(t, r + o + i); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }), + (p5.SoundFile.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.SoundFile.prototype.getPan = function () { + return this.panPosition; + }), + (p5.SoundFile.prototype.rate = function (t) { + var e = !1; + if (void 0 === t) return this.playbackRate; + if ( + (0 === (this.playbackRate = t) + ? (t = 1e-13) + : t < 0 && !this.reversed + ? ((t = Math.abs(t)), (e = !0)) + : 0 < t && this.reversed && (e = !0), + this.bufferSourceNode) + ) { + var n = u.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(n), + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ), + this._counterNode.playbackRate.cancelScheduledValues(n), + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ); + } + return e && this.reverseBuffer(), this.playbackRate; + }), + (p5.SoundFile.prototype.setPitch = function (t) { + var e = n(t) / n(60); + this.rate(e); + }), + (p5.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }), + (p5.SoundFile.prototype.duration = function () { + return this.buffer ? this.buffer.duration : 0; + }), + (p5.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / p.sampleRate + : this._lastPos / p.sampleRate; + }), + (p5.SoundFile.prototype.jump = function (t, e) { + if (t < 0 || t > this.buffer.duration) + throw "jump time out of range"; + if (e > this.buffer.duration - t) throw "end time out of range"; + var n = t || 0, + i = e || void 0; + this.isPlaying() && + (this.stop(0), + this.play(0, this.playbackRate, this.output.gain.value, n, i)); + }), + (p5.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }), + (p5.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }), + (p5.SoundFile.prototype.frames = function () { + return this.buffer.length; + }), + (p5.SoundFile.prototype.getPeaks = function (t) { + if (!this.buffer) + throw "Cannot load peaks yet, buffer is not loaded"; + if (((t = t || 5 * window.width), this.buffer)) { + for ( + var e = this.buffer, + n = e.length / t, + i = ~~(n / 10) || 1, + o = e.numberOfChannels, + r = new Float32Array(Math.round(t)), + s = 0; + s < o; + s++ + ) + for (var a = e.getChannelData(s), u = 0; u < t; u++) { + for ( + var p = ~~(u * n), c = ~~(p + n), h = 0, l = p; + l < c; + l += i + ) { + var f = a[l]; + h < f ? (h = f) : h < -f && (h = f); + } + (0 === s || Math.abs(h) > r[u]) && (r[u] = h); + } + return r; + } + }), + (p5.SoundFile.prototype.reverseBuffer = function () { + if (!this.buffer) throw "SoundFile is not done loading"; + var t = this._lastPos / p.sampleRate, + e = this.getVolume(); + this.setVolume(0, 0.001); + for (var n = this.buffer.numberOfChannels, i = 0; i < n; i++) + this.buffer.getChannelData(i).reverse(); + (this.reversed = !this.reversed), + this.isPlaying() && t && this.jump(this.duration() - t), + this.setVolume(e, 0.001); + }), + (p5.SoundFile.prototype.onended = function (t) { + return (this._onended = t), this; + }), + (p5.SoundFile.prototype.add = function () {}), + (p5.SoundFile.prototype.dispose = function () { + var t = u.audiocontext.currentTime, + e = u.soundArray.indexOf(this); + if ( + (u.soundArray.splice(e, 1), + this.stop(t), + this.buffer && this.bufferSourceNode) + ) { + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) + if (null !== this.bufferSourceNodes[n]) { + this.bufferSourceNodes[n].disconnect(); + try { + this.bufferSourceNodes[n].stop(t); + } catch (t) {} + this.bufferSourceNodes[n] = null; + } + if (this.isPlaying()) { + try { + this._counterNode.stop(t); + } catch (t) {} + this._counterNode = null; + } + } + this.output && (this.output.disconnect(), (this.output = null)), + this.panner && (this.panner.disconnect(), (this.panner = null)); + }), + (p5.SoundFile.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.panner.connect(t.input) + : this.panner.connect(t) + : this.panner.connect(u.input); + }), + (p5.SoundFile.prototype.disconnect = function () { + this.panner && this.panner.disconnect(); + }), + (p5.SoundFile.prototype.getLevel = function () {}), + (p5.SoundFile.prototype.setPath = function (t, e) { + var n = p5.prototype._checkFileFormats(t); + (this.url = n), this.load(e); + }), + (p5.SoundFile.prototype.setBuffer = function (t) { + var e = t.length, + n = t[0].length, + i = p.createBuffer(e, n, p.sampleRate); + t[0] instanceof Float32Array || (t[0] = new Float32Array(t[0])); + for (var o = 0; o < e; o++) { + i.getChannelData(o).set(t[o]); + } + (this.buffer = i), this.panner.inputChannels(e); + }); + (p5.SoundFile.prototype._initCounterNode = function () { + var e = this, + n = this, + t = p.currentTime, + i = p.createBufferSource(), + o = r(256); + return ( + n._workletNode && + (n._workletNode.disconnect(), delete n._workletNode), + (n._workletNode = new AudioWorkletNode(p, s.soundFileProcessor, { + processorOptions: { bufferSize: o }, + })), + (n._workletNode.port.onmessage = function (t) { + if ("position" === t.data.name) { + if (0 === t.data.position) return; + (e._lastPos = t.data.position), e._onTimeUpdate(n._lastPos); + } + }), + (i.buffer = (function (t) { + for ( + var e = t.length, + n = p.createBuffer(1, t.length, p.sampleRate), + i = n.getChannelData(0), + o = 0; + o < e; + o++ + ) + i[o] = o; + return n; + })(n.buffer)), + i.playbackRate.setValueAtTime(n.playbackRate, t), + i.connect(n._workletNode), + n._workletNode.connect(p5.soundOut._silentNode), + i + ); + }), + (p5.SoundFile.prototype._initSourceNode = function () { + var t = p.createBufferSource(); + return ( + (t.buffer = this.buffer), + (t.playbackRate.value = this.playbackRate), + t.connect(this.output), + t + ); + }), + (p5.SoundFile.prototype.processPeaks = function (r, t, e, n) { + var i = this.buffer.length, + o = this.buffer.sampleRate, + s = this.buffer, + a = [], + u = t || 0.9, + p = e || 0.22, + c = n || 200, + h = new window.OfflineAudioContext(1, i, o), + l = h.createBufferSource(); + l.buffer = s; + var f = h.createBiquadFilter(); + (f.type = "lowpass"), + l.connect(f), + f.connect(h.destination), + l.start(0), + h.startRendering(), + (h.oncomplete = function (t) { + if (self.panner) { + for ( + var e = t.renderedBuffer, n = e.getChannelData(0); + (a = d(n, u)), + (u -= 0.005), + Object.keys(a).length < c && p <= u; + + ); + var i = (function (t, i) { + var o = []; + return ( + t.forEach(function (e) { + try { + var n = Math.abs(60 / (e.interval / i)); + if ( + ((n = m(n)), + !o.some(function (t) { + if (t.tempo === n) return (t.count += e.count); + })) + ) { + if (isNaN(n)) return; + o.push({ tempo: Math.round(n), count: e.count }); + } + } catch (t) { + throw t; + } + }), + o + ); + })( + (function (t) { + for ( + var e = [], n = Object.keys(t).sort(), i = 0; + i < n.length; + i++ + ) + for (var o = 0; o < 10; o++) { + var r = t[n[i]], + s = t[n[i + o]]; + if (r && s) { + var a = r.sampleIndex, + u = s.sampleIndex - a; + 0 < u && r.intervals.push(u), + e.some(function (t) { + if (t.interval === u) return t.count++, t; + }) || e.push({ interval: u, count: 1 }); + } + } + return e; + })(a), + e.sampleRate + ) + .sort(function (t, e) { + return e.count - t.count; + }) + .splice(0, 5); + this.tempo = i[0].tempo; + var o = (function (t, e, n, i) { + for ( + var o = [], r = Object.keys(t).sort(), s = 0; + s < r.length; + s++ + ) + for ( + var a = r[s], u = t[a], p = 0; + p < u.intervals.length; + p++ + ) { + var c = Math.round(Math.abs(60 / (u.intervals[p] / n))); + (c = m(c)), + Math.abs(c - e) < i && o.push(u.sampleIndex / n); + } + return (o = o.filter(function (t, e, n) { + if (0.01 < n[e + 1] - t) return !0; + })); + })(a, i[0].tempo, e.sampleRate, 5); + r(o); + } + }); + }); + var c = function (t, e) { + (this.sampleIndex = e), + (this.amplitude = t), + (this.tempos = []), + (this.intervals = []); + }; + function d(t, e) { + for (var n = {}, i = t.length, o = 0; o < i; o++) { + if (t[o] > e) { + var r = t[o], + s = new c(r, o); + (n[o] = s), (o += 6e3); + } + o++; + } + return n; + } + function m(t) { + if (isFinite(t) && 0 !== t) { + for (; t < 90; ) t *= 2; + for (; 180 < t && 90 < t; ) t /= 2; + return t; + } + } + function h(t, e, n, i) { + (this.callback = t), (this.time = e), (this.id = n), (this.val = i); + } + (p5.SoundFile.prototype.addCue = function (t, e, n) { + var i = this._cueIDCounter++, + o = new h(e, t, i, n); + return this._cues.push(o), i; + }), + (p5.SoundFile.prototype.removeCue = function (t) { + for (var e = this._cues.length, n = 0; n < e; n++) { + if (this._cues[n].id === t) { + this._cues.splice(n, 1); + break; + } + } + this._cues.length; + }), + (p5.SoundFile.prototype.clearCues = function () { + this._cues = []; + }), + (p5.SoundFile.prototype._onTimeUpdate = function (t) { + for ( + var e = t / this.buffer.sampleRate, n = this._cues.length, i = 0; + i < n; + i++ + ) { + var o = this._cues[i], + r = o.time, + s = o.val; + ~~this._prevUpdateTime <= r && r <= e && o.callback(s); + } + this._prevUpdateTime = e; + }), + (p5.SoundFile.prototype.save = function (t) { + p5.prototype.saveSound(this, t, "wav"); + }), + (p5.SoundFile.prototype.getBlob = function () { + var t = i(this.buffer); + return new Blob([t], { type: "audio/wav" }); + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = o(1), + e = o(6).safeBufferSize, + i = o(10); + (p5.Amplitude = function (t) { + (this.bufferSize = e(2048)), + (this.audiocontext = n.audiocontext), + (this._workletNode = new AudioWorkletNode( + this.audiocontext, + i.amplitudeProcessor, + { + outputChannelCount: [1], + parameterData: { smoothing: t || 0 }, + processorOptions: { + normalize: !1, + smoothing: t || 0, + numInputChannels: 2, + bufferSize: this.bufferSize, + }, + } + )), + (this._workletNode.port.onmessage = function (t) { + "amplitude" === t.data.name && + ((this.volume = t.data.volume), + (this.volNorm = t.data.volNorm), + (this.stereoVol = t.data.stereoVol), + (this.stereoVolNorm = t.data.stereoVolNorm)); + }.bind(this)), + (this.input = this._workletNode), + (this.output = this.audiocontext.createGain()), + (this.volume = 0), + (this.volNorm = 0), + (this.stereoVol = [0, 0]), + (this.stereoVolNorm = [0, 0]), + (this.normalize = !1), + this._workletNode.connect(this.output), + (this.output.gain.value = 0), + this.output.connect(this.audiocontext.destination), + n.meter.connect(this._workletNode), + n.soundArray.push(this); + }), + (p5.Amplitude.prototype.setInput = function (t, e) { + n.meter.disconnect(), + e && (this._workletNode.parameters.get("smoothing").value = e), + null == t + ? n.meter.connect(this._workletNode) + : t instanceof p5.Signal + ? t.output.connect(this._workletNode) + : t + ? (t.connect(this._workletNode), + this._workletNode.disconnect(), + this._workletNode.connect(this.output)) + : n.meter.connect(this._workletNode); + }), + (p5.Amplitude.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : this.output.connect(t) + : this.output.connect(this.panner.connect(n.input)); + }), + (p5.Amplitude.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Amplitude.prototype.getLevel = function (t) { + return void 0 !== t + ? this.normalize + ? this.stereoVolNorm[t] + : this.stereoVol[t] + : this.normalize + ? this.volNorm + : this.volume; + }), + (p5.Amplitude.prototype.toggleNormalize = function (t) { + (this.normalize = "boolean" == typeof t ? t : !this.normalize), + this._workletNode.port.postMessage({ + name: "toggleNormalize", + normalize: this.normalize, + }); + }), + (p5.Amplitude.prototype.smooth = function (t) { + 0 <= t && + t < 1 && + this._workletNode.port.postMessage({ + name: "smoothing", + smoothing: t, + }); + }), + (p5.Amplitude.prototype.dispose = function () { + var t = n.soundArray.indexOf(this); + n.soundArray.splice(t, 1), + this.input && (this.input.disconnect(), delete this.input), + this.output && (this.output.disconnect(), delete this.output), + this._workletNode.disconnect(), + delete this._workletNode; + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var c = o(1); + (p5.FFT = function (t, e) { + (this.input = this.analyser = c.audiocontext.createAnalyser()), + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (t) { + this.analyser.fftSize = 2 * t; + }, + configurable: !0, + enumerable: !0, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (t) { + this.analyser.smoothingTimeConstant = t; + }, + configurable: !0, + enumerable: !0, + }, + }), + this.smooth(t), + (this.bins = e || 1024), + c.fftMeter.connect(this.analyser), + (this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.bass = [20, 140]), + (this.lowMid = [140, 400]), + (this.mid = [400, 2600]), + (this.highMid = [2600, 5200]), + (this.treble = [5200, 14e3]), + c.soundArray.push(this); + }), + (p5.FFT.prototype.setInput = function (t) { + t + ? (t.output + ? t.output.connect(this.analyser) + : t.connect && t.connect(this.analyser), + c.fftMeter.disconnect()) + : c.fftMeter.connect(this.analyser); + }), + (p5.FFT.prototype.waveform = function () { + for (var t, e, n = 0; n < arguments.length; n++) + "number" == typeof arguments[n] && + ((t = arguments[n]), (this.analyser.fftSize = 2 * t)), + "string" == typeof arguments[n] && (e = arguments[n]); + if (e && !p5.prototype._isSafari()) + return ( + s(this, this.timeDomain), + this.analyser.getFloatTimeDomainData(this.timeDomain), + this.timeDomain + ); + a(this, this.timeDomain), + this.analyser.getByteTimeDomainData(this.timeDomain); + for (var i = new Array(), o = 0; o < this.timeDomain.length; o++) { + var r = p5.prototype.map(this.timeDomain[o], 0, 255, -1, 1); + i.push(r); + } + return i; + }), + (p5.FFT.prototype.analyze = function () { + for (var t, e = 0; e < arguments.length; e++) + "number" == typeof arguments[e] && + ((this.bins = arguments[e]), + (this.analyser.fftSize = 2 * this.bins)), + "string" == typeof arguments[e] && (t = arguments[e]); + return t && "db" === t.toLowerCase() + ? (n(this), + this.analyser.getFloatFrequencyData(this.freqDomain), + this.freqDomain) + : (i(this, this.freqDomain), + this.analyser.getByteFrequencyData(this.freqDomain), + Array.apply([], this.freqDomain)); + }), + (p5.FFT.prototype.getEnergy = function (t, e) { + var n = c.audiocontext.sampleRate / 2; + if ( + ("bass" === t + ? ((t = this.bass[0]), (e = this.bass[1])) + : "lowMid" === t + ? ((t = this.lowMid[0]), (e = this.lowMid[1])) + : "mid" === t + ? ((t = this.mid[0]), (e = this.mid[1])) + : "highMid" === t + ? ((t = this.highMid[0]), (e = this.highMid[1])) + : "treble" === t && + ((t = this.treble[0]), (e = this.treble[1])), + "number" != typeof t) + ) + throw "invalid input for getEnergy()"; + if (e) { + if (t && e) { + if (e < t) { + var i = e; + (e = t), (t = i); + } + for ( + var o = Math.round((t / n) * this.freqDomain.length), + r = Math.round((e / n) * this.freqDomain.length), + s = 0, + a = 0, + u = o; + u <= r; + u++ + ) + (s += this.freqDomain[u]), (a += 1); + return s / a; + } + throw "invalid input for getEnergy()"; + } + var p = Math.round((t / n) * this.freqDomain.length); + return this.freqDomain[p]; + }), + (p5.FFT.prototype.getFreq = function (t, e) { + return this.getEnergy(t, e); + }), + (p5.FFT.prototype.getCentroid = function () { + for ( + var t = c.audiocontext.sampleRate / 2, e = 0, n = 0, i = 0; + i < this.freqDomain.length; + i++ + ) + (e += i * this.freqDomain[i]), (n += this.freqDomain[i]); + var o = 0; + return 0 !== n && (o = e / n), o * (t / this.freqDomain.length); + }), + (p5.FFT.prototype.smooth = function (t) { + return void 0 !== t && (this.smoothing = t), this.smoothing; + }), + (p5.FFT.prototype.dispose = function () { + var t = c.soundArray.indexOf(this); + c.soundArray.splice(t, 1), + this.analyser && + (this.analyser.disconnect(), delete this.analyser); + }), + (p5.FFT.prototype.linAverages = function (t) { + t = t || 16; + for ( + var e = this.freqDomain, + n = e.length, + i = Math.floor(n / t), + o = new Array(t), + r = 0, + s = 0; + s < n; + s++ + ) + (o[r] = void 0 !== o[r] ? (o[r] + e[s]) / 2 : e[s]), + s % i == i - 1 && r++; + return o; + }), + (p5.FFT.prototype.logAverages = function (t) { + for ( + var e = c.audiocontext.sampleRate / 2, + n = this.freqDomain, + i = n.length, + o = new Array(t.length), + r = 0, + s = 0; + s < i; + s++ + ) { + Math.round((s * e) / this.freqDomain.length) > t[r].hi && r++, + (o[r] = void 0 !== o[r] ? (o[r] + n[s]) / 2 : n[s]); + } + return o; + }), + (p5.FFT.prototype.getOctaveBands = function (t, e) { + t = t || 3; + var n = [], + i = { + lo: (e = e || 15.625) / Math.pow(2, 1 / (2 * t)), + ctr: e, + hi: e * Math.pow(2, 1 / (2 * t)), + }; + n.push(i); + for (var o = c.audiocontext.sampleRate / 2; i.hi < o; ) { + var r = {}; + (r.lo = i.hi), + (r.ctr = i.ctr * Math.pow(2, 1 / t)), + (r.hi = r.ctr * Math.pow(2, 1 / (2 * t))), + n.push(r), + (i = r); + } + return n; + }); + var n = function (t) { + t.freqDomain instanceof Float32Array == !1 && + (t.freqDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + i = function (t) { + t.freqDomain instanceof Uint8Array == !1 && + (t.freqDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }, + s = function (t) { + t.timeDomain instanceof Float32Array == !1 && + (t.timeDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + a = function (t) { + t.timeDomain instanceof Uint8Array == !1 && + (t.timeDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }; + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = o(2), + n = o(7), + i = o(3), + a = o(13); + (p5.Signal = function (t) { + return new e(t); + }), + (e.prototype.fade = e.prototype.linearRampToValueAtTime), + (i.prototype.fade = e.prototype.fade), + (n.prototype.fade = e.prototype.fade), + (a.prototype.fade = e.prototype.fade), + (e.prototype.setInput = function (t) { + t.connect(this); + }), + (i.prototype.setInput = e.prototype.setInput), + (n.prototype.setInput = e.prototype.setInput), + (a.prototype.setInput = e.prototype.setInput), + (e.prototype.add = function (t) { + var e = new n(t); + return this.connect(e), e; + }), + (i.prototype.add = e.prototype.add), + (n.prototype.add = e.prototype.add), + (a.prototype.add = e.prototype.add), + (e.prototype.mult = function (t) { + var e = new i(t); + return this.connect(e), e; + }), + (i.prototype.mult = e.prototype.mult), + (n.prototype.mult = e.prototype.mult), + (a.prototype.mult = e.prototype.mult), + (e.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new a(o, r); + return this.connect(s), s; + }), + (i.prototype.scale = e.prototype.scale), + (n.prototype.scale = e.prototype.scale), + (a.prototype.scale = e.prototype.scale); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (o) { + (o.Frequency = function (t, e) { + if (!(this instanceof o.Frequency)) return new o.Frequency(t, e); + o.TimeBase.call(this, t, e); + }), + o.extend(o.Frequency, o.TimeBase), + (o.Frequency.prototype._primaryExpressions = Object.create( + o.TimeBase.prototype._primaryExpressions + )), + (o.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (t) { + return this.midiToFrequency(t); + }, + }), + (o.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (t, e) { + var n = i[t.toLowerCase()] + 12 * (parseInt(e) + 1); + return this.midiToFrequency(n); + }, + }), + (o.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 1; + return ( + t && + "0" !== t && + (i *= this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i *= this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i *= this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }), + (o.Frequency.prototype.transpose = function (t) { + return ( + (this._expr = function (t, e) { + return t() * this.intervalToFrequencyRatio(e); + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.harmonize = function (t) { + return ( + (this._expr = function (t, e) { + for (var n = t(), i = [], o = 0; o < e.length; o++) + i[o] = n * this.intervalToFrequencyRatio(e[o]); + return i; + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }), + (o.Frequency.prototype.toNote = function () { + var t = this.valueOf(), + e = Math.log(t / o.Frequency.A4) / Math.LN2, + n = Math.round(12 * e) + 57, + i = Math.floor(n / 12); + return i < 0 && (n += -12 * i), r[n % 12] + i.toString(); + }), + (o.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }), + (o.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }), + (o.Frequency.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * o.Transport.PPQ); + }), + (o.Frequency.prototype._frequencyToUnits = function (t) { + return t; + }), + (o.Frequency.prototype._ticksToUnits = function (t) { + return 1 / ((60 * t) / (o.Transport.bpm.value * o.Transport.PPQ)); + }), + (o.Frequency.prototype._beatsToUnits = function (t) { + return 1 / o.TimeBase.prototype._beatsToUnits.call(this, t); + }), + (o.Frequency.prototype._secondsToUnits = function (t) { + return 1 / t; + }), + (o.Frequency.prototype._defaultUnits = "hz"); + var i = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }, + r = [ + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B", + ]; + return ( + (o.Frequency.A4 = 440), + (o.Frequency.prototype.midiToFrequency = function (t) { + return o.Frequency.A4 * Math.pow(2, (t - 69) / 12); + }), + (o.Frequency.prototype.frequencyToMidi = function (t) { + return 69 + (12 * Math.log(t / o.Frequency.A4)) / Math.LN2; + }), + o.Frequency + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(20)]), + void 0 === + (o = function (i) { + return ( + (i.TransportTime = function (t, e) { + if (!(this instanceof i.TransportTime)) + return new i.TransportTime(t, e); + i.Time.call(this, t, e); + }), + i.extend(i.TransportTime, i.Time), + (i.TransportTime.prototype._unaryExpressions = Object.create( + i.Time.prototype._unaryExpressions + )), + (i.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + var e = this._secondsToTicks(t()), + n = Math.ceil(i.Transport.ticks / e); + return this._ticksToUnits(n * e); + }, + }), + (i.TransportTime.prototype._secondsToTicks = function (t) { + var e = t / this._beatsToUnits(1); + return Math.round(e * i.Transport.PPQ); + }), + (i.TransportTime.prototype.valueOf = function () { + return ( + this._secondsToTicks(this._expr()) + + (this._plusNow ? i.Transport.ticks : 0) + ); + }), + (i.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }), + (i.TransportTime.prototype.toSeconds = function () { + return this._expr() + (this._plusNow ? i.Transport.seconds : 0); + }), + (i.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + i.TransportTime + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var u = n(1), + o = n(7), + r = n(3), + a = n(13), + s = n(14); + (p5.Envelope = function (t, e, n, i, o, r) { + (this.aTime = t || 0.1), + (this.aLevel = e || 1), + (this.dTime = n || 0.5), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + (this._rampHighPercentage = 0.98), + (this._rampLowPercentage = 0.02), + (this.output = u.audiocontext.createGain()), + (this.control = new s()), + this._init(), + this.control.connect(this.output), + (this.connection = null), + (this.mathOps = [this.control]), + (this.isExponential = !1), + (this.sourceToClear = null), + (this.wasTriggered = !1), + u.soundArray.push(this); + }), + (p5.Envelope.prototype._init = function () { + var t = u.audiocontext.currentTime; + this.control.setTargetAtTime(1e-5, t, 0.001), + this._setRampAD(this.aTime, this.dTime); + }), + (p5.Envelope.prototype.set = function (t, e, n, i, o, r) { + (this.aTime = t), + (this.aLevel = e), + (this.dTime = n || 0), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + this._setRampAD(t, n); + }), + (p5.Envelope.prototype.setADSR = function (t, e, n, i) { + (this.aTime = t), + (this.dTime = e || 0), + (this.sPercent = n || 0), + (this.dLevel = + void 0 !== n + ? n * (this.aLevel - this.rLevel) + this.rLevel + : 0), + (this.rTime = i || 0), + this._setRampAD(t, e); + }), + (p5.Envelope.prototype.setRange = function (t, e) { + (this.aLevel = t || 1), (this.rLevel = e || 0); + }), + (p5.Envelope.prototype._setRampAD = function (t, e) { + (this._rampAttackTime = this.checkExpInput(t)), + (this._rampDecayTime = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = t / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = e / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setRampPercentages = function (t, e) { + (this._rampHighPercentage = this.checkExpInput(t)), + (this._rampLowPercentage = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = + this._rampAttackTime / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = this._rampDecayTime / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setInput = function () { + for (var t = 0; t < arguments.length; t++) + this.connect(arguments[t]); + }), + (p5.Envelope.prototype.setExp = function (t) { + this.isExponential = t; + }), + (p5.Envelope.prototype.checkExpInput = function (t) { + return t <= 0 && (t = 1e-8), t; + }), + (p5.Envelope.prototype.play = function (t, e, n) { + var i = e || 0; + n = n || 0; + t && this.connection !== t && this.connect(t), + this.triggerAttack(t, i), + this.triggerRelease(t, i + this.aTime + this.dTime + n); + }), + (p5.Envelope.prototype.triggerAttack = function (t, e) { + var n = u.audiocontext.currentTime + (e || 0); + (this.lastAttack = n), + (this.wasTriggered = !0), + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.aTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.aLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (n += this.dTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.dLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)); + }), + (p5.Envelope.prototype.triggerRelease = function (t, e) { + if (this.wasTriggered) { + var n = u.audiocontext.currentTime + (e || 0); + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.rTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.rLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (this.wasTriggered = !1); + } + }), + (p5.Envelope.prototype.ramp = function (t, e, n, i) { + var o = u.audiocontext.currentTime + (e || 0), + r = this.checkExpInput(n), + s = void 0 !== i ? this.checkExpInput(i) : void 0; + t && this.connection !== t && this.connect(t); + var a = this.checkExpInput(this.control.getValueAtTime(o)); + a < r + ? (this.control.setTargetAtTime(r, o, this._rampAttackTC), + (o += this._rampAttackTime)) + : r < a && + (this.control.setTargetAtTime(r, o, this._rampDecayTC), + (o += this._rampDecayTime)), + void 0 !== s && + (r < s + ? this.control.setTargetAtTime(s, o, this._rampAttackTC) + : s < r && + this.control.setTargetAtTime(s, o, this._rampDecayTC)); + }), + (p5.Envelope.prototype.connect = function (t) { + ((this.connection = t) instanceof p5.Oscillator || + t instanceof p5.SoundFile || + t instanceof p5.AudioIn || + t instanceof p5.Reverb || + t instanceof p5.Noise || + t instanceof p5.Filter || + t instanceof p5.Delay) && + (t = t.output.gain), + t instanceof AudioParam && + t.setValueAtTime(0, u.audiocontext.currentTime), + t instanceof p5.Signal && t.setValue(0), + this.output.connect(t); + }), + (p5.Envelope.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Envelope.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, o); + }), + (p5.Envelope.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, r); + }), + (p5.Envelope.prototype.scale = function (t, e, n, i) { + var o = new a(t, e, n, i), + r = this.mathOps.length, + s = this.output; + return p5.prototype._mathChain(this, o, r, s, a); + }), + (p5.Envelope.prototype.dispose = function () { + var t = u.soundArray.indexOf(this); + u.soundArray.splice(t, 1), + this.disconnect(), + this.control && (this.control.dispose(), (this.control = null)); + for (var e = 1; e < this.mathOps.length; e++) + this.mathOps[e].dispose(); + }), + (p5.Env = function (t, e, n, i, o, r) { + p5.Envelope.call(this, t, e, n, i, o, r); + }), + (p5.Env.prototype = Object.create(p5.Envelope.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1); + function a() { + for ( + var t = s.audiocontext, + e = t.createBuffer(1, 2048, t.sampleRate), + n = e.getChannelData(0), + i = 0; + i < 2048; + i++ + ) + n[i] = 1; + var o = t.createBufferSource(); + return (o.buffer = e), (o.loop = !0), o; + } + n(23), + (p5.Pulse = function (t, e) { + p5.Oscillator.call(this, t, "sawtooth"), + (this.w = e || 0), + (this.osc2 = new p5.SawOsc(t)), + (this.dNode = s.audiocontext.createDelay()), + (this.dcOffset = a()), + (this.dcGain = s.audiocontext.createGain()), + this.dcOffset.connect(this.dcGain), + this.dcGain.connect(this.output), + (this.f = t || 440); + var n = this.w / this.oscillator.frequency.value; + (this.dNode.delayTime.value = n), + (this.dcGain.gain.value = 1.7 * (0.5 - this.w)), + this.osc2.disconnect(), + this.osc2.panner.disconnect(), + this.osc2.amp(-1), + this.osc2.output.connect(this.dNode), + this.dNode.connect(this.output), + (this.output.gain.value = 1), + this.output.connect(this.panner); + }), + (p5.Pulse.prototype = Object.create(p5.Oscillator.prototype)), + (p5.Pulse.prototype.width = function (t) { + if ("number" == typeof t) { + if (t <= 1 && 0 <= t) { + this.w = t; + var e = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = e; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + t.connect(this.dNode.delayTime); + var n = new p5.SignalAdd(-0.5); + n.setInput(t), + (n = (n = n.mult(-1)).mult(1.7)).connect(this.dcGain.gain); + } + }), + (p5.Pulse.prototype.start = function (t, e) { + var n = s.audiocontext.currentTime, + i = e || 0; + if (!this.started) { + var o = t || this.f, + r = this.oscillator.type; + (this.oscillator = s.audiocontext.createOscillator()), + this.oscillator.frequency.setValueAtTime(o, n), + (this.oscillator.type = r), + this.oscillator.connect(this.output), + this.oscillator.start(i + n), + (this.osc2.oscillator = s.audiocontext.createOscillator()), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + (this.osc2.oscillator.type = r), + this.osc2.oscillator.connect(this.osc2.output), + this.osc2.start(i + n), + (this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]), + (this.dcOffset = a()), + this.dcOffset.connect(this.dcGain), + this.dcOffset.start(i + n), + void 0 !== this.mods && + void 0 !== this.mods.frequency && + (this.mods.frequency.connect(this.freqNode[0]), + this.mods.frequency.connect(this.freqNode[1])), + (this.started = !0), + (this.osc2.started = !0); + } + }), + (p5.Pulse.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), + this.osc2.oscillator && this.osc2.oscillator.stop(e + n), + this.dcOffset.stop(e + n), + (this.started = !1), + (this.osc2.started = !1); + } + }), + (p5.Pulse.prototype.freq = function (t, e, n) { + if ("number" == typeof t) { + this.f = t; + var i = s.audiocontext.currentTime, + o = + ((e = e || 0), (n = n || 0), this.oscillator.frequency.value); + this.oscillator.frequency.cancelScheduledValues(i), + this.oscillator.frequency.setValueAtTime(o, i + n), + this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.osc2.oscillator.frequency.cancelScheduledValues(i), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.freqMod && + (this.freqMod.output.disconnect(), (this.freqMod = null)); + } else + t.output && + (t.output.disconnect(), + t.output.connect(this.oscillator.frequency), + t.output.connect(this.osc2.oscillator.frequency), + (this.freqMod = t)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var l = r(1); + (p5.Noise = function (t) { + var e; + p5.Oscillator.call(this), + delete this.f, + delete this.freq, + delete this.oscillator, + (e = "brown" === t ? o : "pink" === t ? i : n), + (this.buffer = e); + }), + (p5.Noise.prototype = Object.create(p5.Oscillator.prototype)); + var n = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0; + i < t; + i++ + ) + n[i] = 2 * Math.random() - 1; + return (e.type = "white"), e; + })(), + i = (function () { + var t, + e, + n, + i, + o, + r, + s, + a = 2 * l.audiocontext.sampleRate, + u = l.audiocontext.createBuffer(1, a, l.audiocontext.sampleRate), + p = u.getChannelData(0); + t = e = n = i = o = r = s = 0; + for (var c = 0; c < a; c++) { + var h = 2 * Math.random() - 1; + (t = 0.99886 * t + 0.0555179 * h), + (e = 0.99332 * e + 0.0750759 * h), + (n = 0.969 * n + 0.153852 * h), + (i = 0.8665 * i + 0.3104856 * h), + (o = 0.55 * o + 0.5329522 * h), + (r = -0.7616 * r - 0.016898 * h), + (p[c] = t + e + n + i + o + r + s + 0.5362 * h), + (p[c] *= 0.11), + (s = 0.115926 * h); + } + return (u.type = "pink"), u; + })(), + o = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0, + o = 0; + o < t; + o++ + ) { + var r = 2 * Math.random() - 1; + (n[o] = (i + 0.02 * r) / 1.02), (i = n[o]), (n[o] *= 3.5); + } + return (e.type = "brown"), e; + })(); + (p5.Noise.prototype.setType = function (t) { + switch (t) { + case "white": + this.buffer = n; + break; + case "pink": + this.buffer = i; + break; + case "brown": + this.buffer = o; + break; + default: + this.buffer = n; + } + if (this.started) { + var e = l.audiocontext.currentTime; + this.stop(e), this.start(e + 0.01); + } + }), + (p5.Noise.prototype.getType = function () { + return this.buffer.type; + }), + (p5.Noise.prototype.start = function () { + this.started && this.stop(), + (this.noise = l.audiocontext.createBufferSource()), + (this.noise.buffer = this.buffer), + (this.noise.loop = !0), + this.noise.connect(this.output); + var t = l.audiocontext.currentTime; + this.noise.start(t), (this.started = !0); + }), + (p5.Noise.prototype.stop = function () { + var t = l.audiocontext.currentTime; + this.noise && (this.noise.stop(t), (this.started = !1)); + }), + (p5.Noise.prototype.dispose = function () { + var t = l.audiocontext.currentTime, + e = l.soundArray.indexOf(this); + l.soundArray.splice(e, 1), + this.noise && (this.noise.disconnect(), this.stop(t)), + this.output && this.output.disconnect(), + this.panner && this.panner.disconnect(), + (this.output = null), + (this.panner = null), + (this.buffer = null), + (this.noise = null); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (r.inputSources = []), + (p5.AudioIn = function (t) { + (this.input = r.audiocontext.createGain()), + (this.output = r.audiocontext.createGain()), + (this.stream = null), + (this.mediaStream = null), + (this.currentSource = null), + (this.enabled = !1), + (this.amplitude = new p5.Amplitude()), + this.output.connect(this.amplitude.input), + (window.MediaStreamTrack && + window.navigator.mediaDevices && + window.navigator.mediaDevices.getUserMedia) || + (t + ? t() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + )), + r.soundArray.push(this); + }), + (p5.AudioIn.prototype.start = function (e, n) { + var i = this; + this.stream && this.stop(); + var t = r.inputSources[i.currentSource], + o = { + audio: { + sampleRate: r.audiocontext.sampleRate, + echoCancellation: !1, + }, + }; + r.inputSources[this.currentSource] && + (o.audio.deviceId = t.deviceId), + window.navigator.mediaDevices + .getUserMedia(o) + .then(function (t) { + (i.stream = t), + (i.enabled = !0), + (i.mediaStream = r.audiocontext.createMediaStreamSource(t)), + i.mediaStream.connect(i.output), + i.amplitude.setInput(i.output), + e && e(); + }) + .catch(function (t) { + n && n(t); + }); + }), + (p5.AudioIn.prototype.stop = function () { + this.stream && + (this.stream.getTracks().forEach(function (t) { + t.stop(); + }), + this.mediaStream.disconnect(), + delete this.mediaStream, + delete this.stream); + }), + (p5.AudioIn.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : t.hasOwnProperty("analyser") + ? this.output.connect(t.analyser) + : this.output.connect(t) + : this.output.connect(r.input); + }), + (p5.AudioIn.prototype.disconnect = function () { + this.output && + (this.output.disconnect(), + this.output.connect(this.amplitude.input)); + }), + (p5.AudioIn.prototype.getLevel = function (t) { + return ( + t && (this.amplitude.smoothing = t), this.amplitude.getLevel() + ); + }), + (p5.AudioIn.prototype.amp = function (t, e) { + if (e) { + var n = e || 0, + i = this.output.gain.value; + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(i, r.audiocontext.currentTime), + this.output.gain.linearRampToValueAtTime( + t, + n + r.audiocontext.currentTime + ); + } else + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(t, r.audiocontext.currentTime); + }), + (p5.AudioIn.prototype.getSources = function (i, o) { + return new Promise(function (e, n) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (t) { + (r.inputSources = t.filter(function (t) { + return "audioinput" === t.kind; + })), + e(r.inputSources), + i && i(r.inputSources); + }) + .catch(function (t) { + n(t), o && o(t); + }); + }); + }), + (p5.AudioIn.prototype.setSource = function (t) { + 0 < r.inputSources.length && + t < r.inputSources.length && + (this.currentSource = t), + this.stream && this.stream.active && this.start(); + }), + (p5.AudioIn.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.stop(), + this.output && this.output.disconnect(), + this.amplitude && this.amplitude.disconnect(), + delete this.amplitude, + delete this.output; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(52), n(58), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.CrossFade = function (t) { + this.createInsOuts(2, 1), + (this.a = this.input[0] = new e.Gain()), + (this.b = this.input[1] = new e.Gain()), + (this.fade = new e.Signal( + this.defaultArg(t, 0.5), + e.Type.NormalRange + )), + (this._equalPowerA = new e.EqualPowerGain()), + (this._equalPowerB = new e.EqualPowerGain()), + (this._invert = new e.Expr("1 - $0")), + this.a.connect(this.output), + this.b.connect(this.output), + this.fade.chain(this._equalPowerB, this.b.gain), + this.fade.chain(this._invert, this._equalPowerA, this.a.gain), + this._readOnly("fade"); + }), + e.extend(e.CrossFade), + (e.CrossFade.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._writable("fade"), + this._equalPowerA.dispose(), + (this._equalPowerA = null), + this._equalPowerB.dispose(), + (this._equalPowerB = null), + this.fade.dispose(), + (this.fade = null), + this._invert.dispose(), + (this._invert = null), + this.a.dispose(), + (this.a = null), + this.b.dispose(), + (this.b = null), + this + ); + }), + e.CrossFade + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [ + n(0), + n(7), + n(16), + n(3), + n(53), + n(26), + n(54), + n(25), + n(55), + n(56), + n(57), + ]), + void 0 === + (o = function (u) { + "use strict"; + function n(t, e, n) { + var i = new t(); + return ( + n._eval(e[0]).connect(i, 0, 0), n._eval(e[1]).connect(i, 0, 1), i + ); + } + function i(t, e, n) { + var i = new t(); + return n._eval(e[0]).connect(i, 0, 0), i; + } + function o(t) { + return t ? parseFloat(t) : void 0; + } + function r(t) { + return t && t.args ? parseFloat(t.args) : void 0; + } + return ( + (u.Expr = function () { + var t = this._replacements(Array.prototype.slice.call(arguments)), + e = this._parseInputs(t); + (this._nodes = []), (this.input = new Array(e)); + for (var n = 0; n < e; n++) + this.input[n] = this.context.createGain(); + var i, + o = this._parseTree(t); + try { + i = this._eval(o); + } catch (e) { + throw ( + (this._disposeNodes(), + new Error("Tone.Expr: Could evaluate expression: " + t)) + ); + } + this.output = i; + }), + u.extend(u.Expr, u.SignalBase), + (u.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (t) { + return new u.Signal(o(t)); + }, + }, + input: { + regexp: /^\$\d/, + method: function (t, e) { + return e.input[o(t.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { regexp: /^abs/, method: i.bind(this, u.Abs) }, + mod: { + regexp: /^mod/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Modulo(n); + return e._eval(t[0]).connect(i), i; + }, + }, + pow: { + regexp: /^pow/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Pow(n); + return e._eval(t[0]).connect(i), i; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (t, e) { + var n = new u.AudioToGain(); + return e._eval(t[0]).connect(n), n; + }, + }, + }, + binary: { + "+": { + regexp: /^\+/, + precedence: 1, + method: n.bind(this, u.Add), + }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (t, e) { + return 1 === t.length + ? i(u.Negate, t, e) + : n(u.Subtract, t, e); + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: n.bind(this, u.Multiply), + }, + }, + unary: { + "-": { regexp: /^\-/, method: i.bind(this, u.Negate) }, + "!": { regexp: /^\!/, method: i.bind(this, u.NOT) }, + }, + }), + (u.Expr.prototype._parseInputs = function (t) { + var e = t.match(/\$\d/g), + n = 0; + if (null !== e) + for (var i = 0; i < e.length; i++) { + var o = parseInt(e[i].substr(1)) + 1; + n = Math.max(n, o); + } + return n; + }), + (u.Expr.prototype._replacements = function (t) { + for (var e = t.shift(), n = 0; n < t.length; n++) + e = e.replace(/\%/i, t[n]); + return e; + }), + (u.Expr.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim())); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t) { + for (var e in u.Expr._Expressions) { + var n = u.Expr._Expressions[e]; + for (var i in n) { + var o = n[i], + r = o.regexp, + s = t.match(r); + if (null !== s) + return { type: e, value: s[0], method: o.method }; + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (u.Expr.prototype._parseTree = function (t) { + var i = this._tokenize(t), + s = this.isUndef.bind(this); + function o(t, e) { + return !s(t) && "glue" === t.type && t.value === e; + } + function r(t, e, n) { + var i = u.Expr._Expressions[e]; + if (!s(t)) + for (var o in i) { + var r = i[o]; + if (r.regexp.test(t.value)) { + if (s(n)) return !0; + if (r.precedence === n) return !0; + } + } + return !1; + } + function a(t) { + var e; + s(t) && (t = 5), + (e = + t < 0 + ? (function t() { + var e, n; + return r((e = i.peek()), "unary") + ? ((e = i.next()), + (n = t()), + { + operator: e.value, + method: e.method, + args: [n], + }) + : (function () { + var t, e; + if (((t = i.peek()), s(t))) + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + if ("func" === t.type) + return (function (t) { + var e = []; + if (!o(i.next(), "(")) + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + + t.value + + '"' + ); + if ( + (o(i.peek(), ")") || + (e = (function () { + for ( + var t, e = []; + (t = a()), + !s(t) && + (e.push(t), o(i.peek(), ",")); + + ) + i.next(); + return e; + })()), + o(i.next(), ")")) + ) + return { + method: t.method, + args: e, + name: name, + }; + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + + t.value + + '"' + ); + })((t = i.next())); + if ("value" === t.type) + return { + method: (t = i.next()).method, + args: t.value, + }; + if (o(t, "(")) { + if ( + (i.next(), + (e = a()), + !o((t = i.next()), ")")) + ) + throw new SyntaxError("Expected )"); + return e; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + + t.value + ); + })(); + })() + : a(t - 1)); + for (var n = i.peek(); r(n, "binary", t); ) + (e = { + operator: (n = i.next()).value, + method: n.method, + args: [e, a(t - 1)], + }), + (n = i.peek()); + return e; + } + return a(); + }), + (u.Expr.prototype._eval = function (t) { + if (!this.isUndef(t)) { + var e = t.method(t.args, this); + return this._nodes.push(e), e; + } + }), + (u.Expr.prototype._disposeNodes = function () { + for (var t = 0; t < this._nodes.length; t++) { + var e = this._nodes[t]; + this.isFunction(e.dispose) + ? e.dispose() + : this.isFunction(e.disconnect) && e.disconnect(), + (e = null), + (this._nodes[t] = null); + } + this._nodes = null; + }), + (u.Expr.prototype.dispose = function () { + u.prototype.dispose.call(this), this._disposeNodes(); + }), + u.Expr + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(26), n(16), n(2)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.GreaterThan = function (t) { + this.createInsOuts(2, 0), + (this._param = this.input[0] = new e.Subtract(t)), + (this.input[1] = this._param.input[1]), + (this._gtz = this.output = new e.GreaterThanZero()), + this._param.connect(this._gtz); + }), + e.extend(e.GreaterThan, e.Signal), + (e.GreaterThan.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._param.dispose(), + (this._param = null), + this._gtz.dispose(), + (this._gtz = null), + this + ); + }), + e.GreaterThan + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(19)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Abs = function () { + this._abs = + this.input = + this.output = + new t.WaveShaper(function (t) { + return 0 === t ? 0 : Math.abs(t); + }, 127); + }), + t.extend(t.Abs, t.SignalBase), + (t.Abs.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._abs.dispose(), + (this._abs = null), + this + ); + }), + t.Abs + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(3), n(16)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Modulo = function (t) { + this.createInsOuts(1, 0), + (this._shaper = new e.WaveShaper(Math.pow(2, 16))), + (this._multiply = new e.Multiply()), + (this._subtract = this.output = new e.Subtract()), + (this._modSignal = new e.Signal(t)), + this.input.fan(this._shaper, this._subtract), + this._modSignal.connect(this._multiply, 0, 0), + this._shaper.connect(this._multiply, 0, 1), + this._multiply.connect(this._subtract, 0, 1), + this._setWaveShaper(t); + }), + e.extend(e.Modulo, e.SignalBase), + (e.Modulo.prototype._setWaveShaper = function (e) { + this._shaper.setMap(function (t) { + return Math.floor((t + 1e-4) / e); + }); + }), + Object.defineProperty(e.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (t) { + (this._modSignal.value = t), this._setWaveShaper(t); + }, + }), + (e.Modulo.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._shaper.dispose(), + (this._shaper = null), + this._multiply.dispose(), + (this._multiply = null), + this._subtract.dispose(), + (this._subtract = null), + this._modSignal.dispose(), + (this._modSignal = null), + this + ); + }), + e.Modulo + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Pow = function (t) { + (this._exp = this.defaultArg(t, 1)), + (this._expScaler = + this.input = + this.output = + new e.WaveShaper(this._expFunc(this._exp), 8192)); + }), + e.extend(e.Pow, e.SignalBase), + Object.defineProperty(e.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (t) { + (this._exp = t), + this._expScaler.setMap(this._expFunc(this._exp)); + }, + }), + (e.Pow.prototype._expFunc = function (e) { + return function (t) { + return Math.pow(Math.abs(t), e); + }; + }), + (e.Pow.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._expScaler.dispose(), + (this._expScaler = null), + this + ); + }), + e.Pow + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.AudioToGain = function () { + this._norm = + this.input = + this.output = + new t.WaveShaper(function (t) { + return (t + 1) / 2; + }); + }), + t.extend(t.AudioToGain, t.SignalBase), + (t.AudioToGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._norm.dispose(), + (this._norm = null), + this + ); + }), + t.AudioToGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new t.WaveShaper( + function (t) { + return Math.abs(t) < 0.001 ? 0 : this.equalPowerScale(t); + }.bind(this), + 4096 + ); + }), + t.extend(t.EqualPowerGain, t.SignalBase), + (t.EqualPowerGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._eqPower.dispose(), + (this._eqPower = null), + this + ); + }), + t.EqualPowerGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var r = i(4), + n = i(60); + return ( + (p5.EQ = function (t) { + var e, n, i; + r.call(this), + (e = 3 === (t = 3 === t || 8 === t ? t : 3) ? Math.pow(2, 3) : 2), + (this.bands = []); + for (var o = 0; o < t; o++) + (i = + o === t - 1 + ? ((n = 21e3), 0.01) + : 0 === o + ? ((n = 100), 0.1) + : ((n = + 1 === o + ? 3 === t + ? 360 * e + : 360 + : this.bands[o - 1].freq() * e), + 1)), + (this.bands[o] = this._newBand(n, i)), + 0 < o + ? this.bands[o - 1].connect(this.bands[o].biquad) + : this.input.connect(this.bands[o].biquad); + this.bands[t - 1].connect(this.output); + }), + (p5.EQ.prototype = Object.create(r.prototype)), + (p5.EQ.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.EQ.prototype.set = function () { + if (arguments.length === 2 * this.bands.length) + for (var t = 0; t < arguments.length; t += 2) + this.bands[t / 2].freq(arguments[t]), + this.bands[t / 2].gain(arguments[t + 1]); + }), + (p5.EQ.prototype._newBand = function (t, e) { + return new n(t, e); + }), + (p5.EQ.prototype.dispose = function () { + if ((r.prototype.dispose.apply(this), this.bands)) { + for (; 0 < this.bands.length; ) this.bands.pop().dispose(); + delete this.bands; + } + }), + p5.EQ + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + function e(t, e) { + n.call(this, "peaking"), + this.disconnect(), + this.set(t, e), + (this.biquad.gain.value = 0), + delete this.input, + delete this.output, + delete this._drywet, + delete this.wet; + } + var n = o(15), + i = o(1); + return ( + ((e.prototype = Object.create(n.prototype)).amp = function () {}), + (e.prototype.drywet = function () {}), + (e.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.biquad + ? this.biquad.connect(e.input ? e.input : e) + : this.output.connect(e.input ? e.input : e); + }), + (e.prototype.disconnect = function () { + this.biquad && this.biquad.disconnect(); + }), + (e.prototype.dispose = function () { + var t = i.soundArray.indexOf(this); + i.soundArray.splice(t, 1), this.disconnect(), delete this.biquad; + }), + e + ); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(1); + var e = n(4); + return ( + (p5.Panner3D = function () { + e.call(this), + (this.panner = this.ac.createPanner()), + (this.panner.panningModel = "HRTF"), + (this.panner.distanceModel = "linear"), + this.panner.connect(this.output), + this.input.connect(this.panner); + }), + (p5.Panner3D.prototype = Object.create(e.prototype)), + (p5.Panner3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Panner3D.prototype.set = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ] + ); + }), + (p5.Panner3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionX.value = t), + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionX), + this.panner.positionX.value + ); + }), + (p5.Panner3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionY.value = t), + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionY), + this.panner.positionY.value + ); + }), + (p5.Panner3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionZ.value = t), + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionZ), + this.panner.positionZ.value + ); + }), + (p5.Panner3D.prototype.orient = function (t, e, n, i) { + return ( + this.orientX(t, i), + this.orientY(e, i), + this.orientZ(n, i), + [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ] + ); + }), + (p5.Panner3D.prototype.orientX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationX.value = t), + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationX), + this.panner.orientationX.value + ); + }), + (p5.Panner3D.prototype.orientY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationY.value = t), + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationY), + this.panner.orientationY.value + ); + }), + (p5.Panner3D.prototype.orientZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationZ.value = t), + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationZ), + this.panner.orientationZ.value + ); + }), + (p5.Panner3D.prototype.setFalloff = function (t, e) { + this.maxDist(t), this.rolloff(e); + }), + (p5.Panner3D.prototype.maxDist = function (t) { + return ( + "number" == typeof t && (this.panner.maxDistance = t), + this.panner.maxDistance + ); + }), + (p5.Panner3D.prototype.rolloff = function (t) { + return ( + "number" == typeof t && (this.panner.rolloffFactor = t), + this.panner.rolloffFactor + ); + }), + (p5.Panner3D.dispose = function () { + e.prototype.dispose.apply(this), + this.panner && (this.panner.disconnect(), delete this.panner); + }), + p5.Panner3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(1); + n(4); + return ( + (p5.Listener3D = function (t) { + (this.ac = e.audiocontext), (this.listener = this.ac.listener); + }), + (p5.Listener3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Listener3D.prototype.position = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ] + ); + }), + (p5.Listener3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionX.value = t), + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionX), + this.listener.positionX.value + ); + }), + (p5.Listener3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionY.value = t), + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionY), + this.listener.positionY.value + ); + }), + (p5.Listener3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionZ.value = t), + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionZ), + this.listener.positionZ.value + ); + }), + (p5.Listener3D.prototype.orient = function (t, e, n, i, o, r, s) { + return ( + 3 === arguments.length || 4 === arguments.length + ? ((s = i), this.orientForward(t, e, n, s)) + : (6 !== arguments.length && 7 !== arguments) || + (this.orientForward(t, e, n), this.orientUp(i, o, r, s)), + [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ] + ); + }), + (p5.Listener3D.prototype.orientForward = function (t, e, n, i) { + return ( + this.forwardX(t, i), + this.forwardY(e, i), + this.forwardZ(n, i), + [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ] + ); + }), + (p5.Listener3D.prototype.orientUp = function (t, e, n, i) { + return ( + this.upX(t, i), + this.upY(e, i), + this.upZ(n, i), + [this.listener.upX, this.listener.upY, this.listener.upZ] + ); + }), + (p5.Listener3D.prototype.forwardX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardX.value = t), + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardX), + this.listener.forwardX.value + ); + }), + (p5.Listener3D.prototype.forwardY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardY.value = t), + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardY), + this.listener.forwardY.value + ); + }), + (p5.Listener3D.prototype.forwardZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardZ.value = t), + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardZ), + this.listener.forwardZ.value + ); + }), + (p5.Listener3D.prototype.upX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upX.value = t), + this.listener.upX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upX), + this.listener.upX.value + ); + }), + (p5.Listener3D.prototype.upY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upY.value = t), + this.listener.upY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upY), + this.listener.upY.value + ); + }), + (p5.Listener3D.prototype.upZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upZ.value = t), + this.listener.upZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upZ), + this.listener.upZ.value + ); + }), + p5.Listener3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = i(15), + n = i(4); + (p5.Delay = function () { + n.call(this), + (this._split = this.ac.createChannelSplitter(2)), + (this._merge = this.ac.createChannelMerger(2)), + (this._leftGain = this.ac.createGain()), + (this._rightGain = this.ac.createGain()), + (this.leftDelay = this.ac.createDelay()), + (this.rightDelay = this.ac.createDelay()), + (this._leftFilter = new e()), + (this._rightFilter = new e()), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this.input.connect(this._split), + this.leftDelay.connect(this._leftGain), + this.rightDelay.connect(this._rightGain), + this._leftGain.connect(this._leftFilter.input), + this._rightGain.connect(this._rightFilter.input), + this._merge.connect(this.wet), + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime), + this._rightFilter.biquad.gain.setValueAtTime( + 1, + this.ac.currentTime + ), + this.setType(0), + (this._maxDelay = this.leftDelay.delayTime.maxValue), + this.feedback(0.5); + }), + (p5.Delay.prototype = Object.create(n.prototype)), + (p5.Delay.prototype.process = function (t, e, n, i) { + var o = n || 0, + r = e || 0; + if (1 <= o) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + if (r >= this._maxDelay) + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + t.connect(this.input), + this.leftDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + this.rightDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + (this._leftGain.gain.value = o), + (this._rightGain.gain.value = o), + i && (this._leftFilter.freq(i), this._rightFilter.freq(i)); + }), + (p5.Delay.prototype.delayTime = function (t) { + "number" != typeof t + ? (t.connect(this.leftDelay.delayTime), + t.connect(this.rightDelay.delayTime)) + : (this.leftDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.rightDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ), + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + )); + }), + (p5.Delay.prototype.feedback = function (t) { + if (t && "number" != typeof t) + t.connect(this._leftGain.gain), t.connect(this._rightGain.gain); + else { + if (1 <= t) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + "number" == typeof t && + ((this._leftGain.gain.value = t), + (this._rightGain.gain.value = t)); + } + return this._leftGain.gain.value; + }), + (p5.Delay.prototype.filter = function (t, e) { + this._leftFilter.set(t, e), this._rightFilter.set(t, e); + }), + (p5.Delay.prototype.setType = function (t) { + switch ( + (1 === t && (t = "pingPong"), + this._split.disconnect(), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._split.connect(this.leftDelay, 0), + this._split.connect(this.rightDelay, 1), + t) + ) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type), + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.rightDelay), + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.leftDelay), + this._rightFilter.output.connect(this.rightDelay); + } + }), + (p5.Delay.prototype.dispose = function () { + n.prototype.dispose.apply(this), + this._split.disconnect(), + this._leftFilter.dispose(), + this._rightFilter.dispose(), + this._merge.disconnect(), + this._leftGain.disconnect(), + this._rightGain.disconnect(), + this.leftDelay.disconnect(), + this.rightDelay.disconnect(), + (this._split = void 0), + (this._leftFilter = void 0), + (this._rightFilter = void 0), + (this._merge = void 0), + (this._leftGain = void 0), + (this._rightGain = void 0), + (this.leftDelay = void 0), + (this.rightDelay = void 0); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var p = n(11), + e = n(4); + (p5.Reverb = function () { + e.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + (this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse(); + }), + (p5.Reverb.prototype = Object.create(e.prototype)), + (p5.Reverb.prototype._initConvolverNode = function () { + (this.convolverNode = this.ac.createConvolver()), + this.input.connect(this.convolverNode), + this.convolverNode.connect(this.wet); + }), + (p5.Reverb.prototype._teardownConvolverNode = function () { + this.convolverNode && + (this.convolverNode.disconnect(), delete this.convolverNode); + }), + (p5.Reverb.prototype._setBuffer = function (t) { + this._teardownConvolverNode(), + this._initConvolverNode(), + (this.convolverNode.buffer = t); + }), + (p5.Reverb.prototype.process = function (t, e, n, i) { + t.connect(this.input); + var o = !1; + e && ((this._seconds = e), (o = !0)), + n && (this._decay = n), + i && (this._reverse = i), + o && this._buildImpulse(); + }), + (p5.Reverb.prototype.set = function (t, e, n) { + var i = !1; + t && ((this._seconds = t), (i = !0)), + e && (this._decay = e), + n && (this._reverse = n), + i && this._buildImpulse(); + }), + (p5.Reverb.prototype._buildImpulse = function () { + var t, + e, + n = this.ac.sampleRate, + i = n * this._seconds, + o = this._decay, + r = this.ac.createBuffer(2, i, n), + s = r.getChannelData(0), + a = r.getChannelData(1); + for (e = 0; e < i; e++) + (t = this._reverse ? i - e : e), + (s[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)), + (a[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)); + this._setBuffer(r); + }), + (p5.Reverb.prototype.dispose = function () { + e.prototype.dispose.apply(this), this._teardownConvolverNode(); + }), + (p5.Convolver = function (t, e, n) { + p5.Reverb.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + t + ? ((this.impulses = []), this._loadBuffer(t, e, n)) + : ((this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse()); + }), + (p5.Convolver.prototype = Object.create(p5.Reverb.prototype)), + p5.prototype.registerPreloadMethod("createConvolver", p5.prototype), + (p5.prototype.createConvolver = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var i = this, + o = new p5.Convolver( + t, + function (t) { + "function" == typeof e && e(t), + "function" == typeof i._decrementPreload && + i._decrementPreload(); + }, + n + ); + return (o.impulses = []), o; + }), + (p5.Convolver.prototype._loadBuffer = function (i, o, n) { + i = p5.prototype._checkFileFormats(i); + var r = this, + s = new Error().stack, + a = p5.prototype.getAudioContext(), + u = new XMLHttpRequest(); + u.open("GET", i, !0), + (u.responseType = "arraybuffer"), + (u.onload = function () { + if (200 === u.status) + a.decodeAudioData( + u.response, + function (t) { + var e = {}, + n = i.split("/"); + (e.name = n[n.length - 1]), + (e.audioBuffer = t), + r.impulses.push(e), + r._setBuffer(e.audioBuffer), + o && o(e); + }, + function () { + var t = new p("decodeAudioData", s, r.url), + e = + "AudioContext error at decodeAudioData for " + r.url; + n && ((t.msg = e), n(t)); + } + ); + else { + var t = new p("loadConvolver", s, r.url), + e = + "Unable to load " + + r.url + + ". The request status was: " + + u.status + + " (" + + u.statusText + + ")"; + n && ((t.message = e), n(t)); + } + }), + (u.onerror = function () { + var t = new p("loadConvolver", s, r.url), + e = + "There was no response from the server at " + + r.url + + ". Check the url and internet connectivity."; + n && ((t.message = e), n(t)); + }), + u.send(); + }), + (p5.Convolver.prototype.set = null), + (p5.Convolver.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Convolver.prototype.impulses = []), + (p5.Convolver.prototype.addImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.resetImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + (this.impulses = []), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.toggleImpulse = function (t) { + if ( + ("number" == typeof t && + t < this.impulses.length && + this._setBuffer(this.impulses[t].audioBuffer), + "string" == typeof t) + ) + for (var e = 0; e < this.impulses.length; e++) + if (this.impulses[e].name === t) { + this._setBuffer(this.impulses[e].audioBuffer); + break; + } + }), + (p5.Convolver.prototype.dispose = function () { + for (var t in (p5.Reverb.prototype.dispose.apply(this), + this.impulses)) + this.impulses[t] && (this.impulses[t] = null); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + e = n(27); + (p5.Metro = function () { + (this.clock = new e({ callback: this.ontick.bind(this) })), + (this.syncedParts = []), + (this.bpm = 120), + this._init(), + (this.prevTick = 0), + (this.tatumTime = 0), + (this.tickCallback = function () {}); + }), + (p5.Metro.prototype.ontick = function (t) { + var e = t - this.prevTick, + i = t - r.audiocontext.currentTime; + if (!(e - this.tatumTime <= -0.02)) { + this.prevTick = t; + var o = this; + this.syncedParts.forEach(function (t) { + t.isPlaying && + (t.incrementStep(i), + t.phrases.forEach(function (t) { + var e = t.sequence, + n = o.metroTicks % e.length; + 0 !== e[n] && + (o.metroTicks < e.length || !t.looping) && + t.callback(i, e[n]); + })); + }), + (this.metroTicks += 1), + this.tickCallback(i); + } + }), + (p5.Metro.prototype.setBPM = function (t, e) { + var n = 60 / (t * this.tatums), + i = r.audiocontext.currentTime; + this.tatumTime = n; + e = e || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, i), + this.clock.frequency.linearRampToValueAtTime(t, i + e), + (this.bpm = t); + }), + (p5.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }), + (p5.Metro.prototype._init = function () { + this.metroTicks = 0; + }), + (p5.Metro.prototype.resetSync = function (t) { + this.syncedParts = [t]; + }), + (p5.Metro.prototype.pushSync = function (t) { + this.syncedParts.push(t); + }), + (p5.Metro.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.start(n + e), this.setBPM(this.bpm); + }), + (p5.Metro.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.stop(n + e); + }), + (p5.Metro.prototype.beatLength = function (t) { + this.tatums = 1 / t / 4; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(24), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.TimelineState = function (t) { + e.Timeline.call(this), (this._initial = t); + }), + e.extend(e.TimelineState, e.Timeline), + (e.TimelineState.prototype.getValueAtTime = function (t) { + var e = this.get(t); + return null !== e ? e.state : this._initial; + }), + (e.TimelineState.prototype.setStateAtTime = function (t, e) { + this.add({ state: t, time: e }); + }), + e.TimelineState + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var i = r(1), + o = 120; + function n(t) { + t.currentPart++, + t.currentPart >= t.parts.length + ? ((t.scoreStep = 0), t.onended()) + : ((t.scoreStep = 0), + t.parts[t.currentPart - 1].stop(), + t.parts[t.currentPart].start()); + } + (p5.prototype.setBPM = function (t, e) { + for (var n in ((o = t), i.parts)) + i.parts[n] && i.parts[n].setBPM(t, e); + }), + (p5.Phrase = function (t, e, n) { + (this.phraseStep = 0), + (this.name = t), + (this.callback = e), + (this.sequence = n); + }), + (p5.Part = function (t, e) { + (this.length = t || 0), + (this.partStep = 0), + (this.phrases = []), + (this.isPlaying = !1), + this.noLoop(), + (this.tatums = e || 0.0625), + (this.metro = new p5.Metro()), + this.metro._init(), + this.metro.beatLength(this.tatums), + this.metro.setBPM(o), + i.parts.push(this), + (this.callback = function () {}); + }), + (p5.Part.prototype.setBPM = function (t, e) { + this.metro.setBPM(t, e); + }), + (p5.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }), + (p5.Part.prototype.start = function (t) { + if (!this.isPlaying) { + (this.isPlaying = !0), this.metro.resetSync(this); + var e = t || 0; + this.metro.start(e); + } + }), + (p5.Part.prototype.loop = function (t) { + (this.looping = !0), + (this.onended = function () { + this.partStep = 0; + }); + var e = t || 0; + this.start(e); + }), + (p5.Part.prototype.noLoop = function () { + (this.looping = !1), + (this.onended = function () { + this.stop(); + }); + }), + (p5.Part.prototype.stop = function (t) { + (this.partStep = 0), this.pause(t); + }), + (p5.Part.prototype.pause = function (t) { + this.isPlaying = !1; + var e = t || 0; + this.metro.stop(e); + }), + (p5.Part.prototype.addPhrase = function (t, e, n) { + var i; + if (3 === arguments.length) i = new p5.Phrase(t, e, n); + else { + if (!(t instanceof p5.Phrase)) + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + i = t; + } + this.phrases.push(i), + i.sequence.length > this.length && + (this.length = i.sequence.length); + }), + (p5.Part.prototype.removePhrase = function (t) { + for (var e in this.phrases) + this.phrases[e].name === t && this.phrases.splice(e, 1); + }), + (p5.Part.prototype.getPhrase = function (t) { + for (var e in this.phrases) + if (this.phrases[e].name === t) return this.phrases[e]; + }), + (p5.Part.prototype.replaceSequence = function (t, e) { + for (var n in this.phrases) + this.phrases[n].name === t && (this.phrases[n].sequence = e); + }), + (p5.Part.prototype.incrementStep = function (t) { + this.partStep < this.length - 1 + ? (this.callback(t), (this.partStep += 1)) + : this.looping || + this.partStep !== this.length - 1 || + this.onended(); + }), + (p5.Part.prototype.onStep = function (t) { + this.callback = t; + }), + (p5.Score = function () { + (this.parts = []), (this.currentPart = 0); + var t = this; + for (var e in arguments) + arguments[e] && + this.parts[e] && + ((this.parts[e] = arguments[e]), + (this.parts[e].nextPart = this.parts[e + 1]), + (this.parts[e].onended = function () { + t.resetPart(e), n(t); + })); + this.looping = !1; + }), + (p5.Score.prototype.onended = function () { + this.looping + ? this.parts[0].start() + : (this.parts[this.parts.length - 1].onended = function () { + this.stop(), this.resetParts(); + }), + (this.currentPart = 0); + }), + (p5.Score.prototype.start = function () { + this.parts[this.currentPart].start(), (this.scoreStep = 0); + }), + (p5.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(), + (this.currentPart = 0), + (this.scoreStep = 0); + }), + (p5.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }), + (p5.Score.prototype.loop = function () { + (this.looping = !0), this.start(); + }), + (p5.Score.prototype.noLoop = function () { + this.looping = !1; + }), + (p5.Score.prototype.resetParts = function () { + var e = this; + this.parts.forEach(function (t) { + e.resetParts[t]; + }); + }), + (p5.Score.prototype.resetPart = function (t) { + for (var e in (this.parts[t].stop(), + (this.parts[t].partStep = 0), + this.parts[t].phrases)) + this.parts[t] && (this.parts[t].phrases[e].phraseStep = 0); + }), + (p5.Score.prototype.setBPM = function (t, e) { + for (var n in this.parts) + this.parts[n] && this.parts[n].setBPM(t, e); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + i = n(27); + return ( + (p5.SoundLoop = function (t, e) { + (this.callback = t), + (this.musicalTimeMode = "number" != typeof this._interval), + (this._interval = e || 1), + (this._timeSignature = 4), + (this._bpm = 60), + (this.isPlaying = !1), + (this.maxIterations = 1 / 0); + var n = this; + this.clock = new i({ + callback: function (t) { + var e = t - r.audiocontext.currentTime; + 0 < e && n.iterations <= n.maxIterations && n.callback(e); + }, + frequency: this._calcFreq(), + }); + }), + (p5.SoundLoop.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying || (this.clock.start(n + e), (this.isPlaying = !0)); + }), + (p5.SoundLoop.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.stop(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.pause = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.pause(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.syncedStart = function (t, e) { + var n = e || 0, + i = r.audiocontext.currentTime; + if (t.isPlaying) { + if (t.isPlaying) { + var o = t.clock._nextTick - r.audiocontext.currentTime; + this.clock.start(i + o), (this.isPlaying = !0); + } + } else + t.clock.start(i + n), + (t.isPlaying = !0), + this.clock.start(i + n), + (this.isPlaying = !0); + }), + (p5.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }), + (p5.SoundLoop.prototype._calcFreq = function () { + return "number" == typeof this._interval + ? ((this.musicalTimeMode = !1), 1 / this._interval) + : "string" == typeof this._interval + ? ((this.musicalTimeMode = !0), + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4)) + : void 0; + }), + (p5.SoundLoop.prototype._convertNotation = function (t) { + var e = t.slice(-1); + switch (((t = Number(t.slice(0, -1))), e)) { + case "m": + return this._measure(t); + case "n": + return this._note(t); + } + }), + (p5.SoundLoop.prototype._measure = function (t) { + return t * this._timeSignature; + }), + (p5.SoundLoop.prototype._note = function (t) { + return this._timeSignature / t; + }), + Object.defineProperty(p5.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (t) { + this.musicalTimeMode, (this._bpm = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (t) { + this.musicalTimeMode, (this._timeSignature = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (t) { + (this.musicalTimeMode = "Number" != typeof t), + (this._interval = t), + this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }), + p5.SoundLoop + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i; + void 0 === + (i = function (t) { + "use strict"; + n(1); + var e = n(4); + n(11); + return ( + (p5.Compressor = function () { + e.call(this), + (this.compressor = this.ac.createDynamicsCompressor()), + this.input.connect(this.compressor), + this.compressor.connect(this.wet); + }), + (p5.Compressor.prototype = Object.create(e.prototype)), + (p5.Compressor.prototype.process = function (t, e, n, i, o, r) { + t.connect(this.input), this.set(e, n, i, o, r); + }), + (p5.Compressor.prototype.set = function (t, e, n, i, o) { + void 0 !== t && this.attack(t), + void 0 !== e && this.knee(e), + void 0 !== n && this.ratio(n), + void 0 !== i && this.threshold(i), + void 0 !== o && this.release(o); + }), + (p5.Compressor.prototype.attack = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.attack.value = t), + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.attack.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.attack), + this.compressor.attack.value + ); + }), + (p5.Compressor.prototype.knee = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.knee.value = t), + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.knee.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.knee), + this.compressor.knee.value + ); + }), + (p5.Compressor.prototype.ratio = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.ratio.value = t), + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.ratio.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.ratio), + this.compressor.ratio.value + ); + }), + (p5.Compressor.prototype.threshold = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.threshold.value = t), + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.threshold.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.threshold), + this.compressor.threshold.value + ); + }), + (p5.Compressor.prototype.release = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.release.value = t), + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.release.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : "undefined" != typeof number && + t.connect(this.compressor.release), + this.compressor.release.value + ); + }), + (p5.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }), + (p5.Compressor.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.compressor && + (this.compressor.disconnect(), delete this.compressor); + }), + p5.Compressor + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, a) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = a(1), + n = a(6), + i = n.convertToWav, + o = n.safeBufferSize, + r = a(10), + s = e.audiocontext; + (p5.SoundRecorder = function () { + (this.input = s.createGain()), + (this.output = s.createGain()), + (this._inputChannels = 2), + (this._outputChannels = 2); + var t = o(1024); + (this._workletNode = new AudioWorkletNode(s, r.recorderProcessor, { + outputChannelCount: [this._outputChannels], + processorOptions: { + numInputChannels: this._inputChannels, + bufferSize: t, + }, + })), + (this._workletNode.port.onmessage = function (t) { + if ("buffers" === t.data.name) { + var e = [ + new Float32Array(t.data.leftBuffer), + new Float32Array(t.data.rightBuffer), + ]; + this._callback(e); + } + }.bind(this)), + (this._callback = function () {}), + this._workletNode.connect(p5.soundOut._silentNode), + this.setInput(), + e.soundArray.push(this); + }), + (p5.SoundRecorder.prototype.setInput = function (t) { + this.input.disconnect(), + (this.input = null), + (this.input = s.createGain()), + this.input.connect(this._workletNode), + this.input.connect(this.output), + t + ? t.connect(this.input) + : p5.soundOut.output.connect(this.input); + }), + (p5.SoundRecorder.prototype.record = function (e, t, n) { + this._workletNode.port.postMessage({ name: "start", duration: t }), + e && n + ? (this._callback = function (t) { + e.setBuffer(t), n(); + }) + : e && + (this._callback = function (t) { + e.setBuffer(t); + }); + }), + (p5.SoundRecorder.prototype.stop = function () { + this._workletNode.port.postMessage({ name: "stop" }); + }), + (p5.SoundRecorder.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + (this._callback = function () {}), + this.input && this.input.disconnect(), + (this.input = null), + (this._workletNode = null); + }), + (p5.prototype.saveSound = function (t, e) { + var n = i(t.buffer); + p5.prototype.writeFile([n], e, "wav"); + }); + }.call(e, a, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + (p5.PeakDetect = function (t, e, n, i) { + (this.framesPerPeak = i || 20), + (this.framesSinceLastPeak = 0), + (this.decayRate = 0.95), + (this.threshold = n || 0.35), + (this.cutoff = 0), + (this.cutoffMult = 1.5), + (this.energy = 0), + (this.penergy = 0), + (this.currentValue = 0), + (this.isDetected = !1), + (this.f1 = t || 40), + (this.f2 = e || 2e4), + (this._onPeak = function () {}); + }), + (p5.PeakDetect.prototype.update = function (t) { + var e = (this.energy = t.getEnergy(this.f1, this.f2) / 255); + e > this.cutoff && e > this.threshold && 0 < e - this.penergy + ? (this._onPeak(), + (this.isDetected = !0), + (this.cutoff = e * this.cutoffMult), + (this.framesSinceLastPeak = 0)) + : ((this.isDetected = !1), + this.framesSinceLastPeak <= this.framesPerPeak + ? this.framesSinceLastPeak++ + : ((this.cutoff *= this.decayRate), + (this.cutoff = Math.max(this.cutoff, this.threshold)))), + (this.currentValue = e), + (this.penergy = e); + }), + (p5.PeakDetect.prototype.onPeak = function (t, e) { + var n = this; + n._onPeak = function () { + t(n.energy, e); + }; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (p5.Gain = function () { + (this.ac = r.audiocontext), + (this.input = this.ac.createGain()), + (this.output = this.ac.createGain()), + (this.input.gain.value = 0.5), + this.input.connect(this.output), + r.soundArray.push(this); + }), + (p5.Gain.prototype.setInput = function (t) { + t.connect(this.input); + }), + (p5.Gain.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.Gain.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Gain.prototype.amp = function (t, e, n) { + (e = e || 0), (n = n || 0); + var i = r.audiocontext.currentTime, + o = this.output.gain.value; + this.output.gain.cancelScheduledValues(i), + this.output.gain.linearRampToValueAtTime(o, i + n), + this.output.gain.linearRampToValueAtTime(t, i + n + e); + }), + (p5.Gain.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.output && (this.output.disconnect(), delete this.output), + this.input && (this.input.disconnect(), delete this.input); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var i = n(4); + function o(t) { + for ( + var e, + n = "number" == typeof t ? t : 50, + i = new Float32Array(44100), + o = Math.PI / 180, + r = 0; + r < 44100; + ++r + ) + (e = (2 * r) / 44100 - 1), + (i[r] = ((3 + n) * e * 20 * o) / (Math.PI + n * Math.abs(e))); + return i; + } + (p5.Distortion = function (t, e) { + if ((i.call(this), void 0 === t && (t = 0.25), "number" != typeof t)) + throw new Error("amount must be a number"); + if ((void 0 === e && (e = "2x"), "string" != typeof e)) + throw new Error("oversample must be a String"); + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.waveShaperNode = this.ac.createWaveShaper()), + (this.amount = n), + (this.waveShaperNode.curve = o(n)), + (this.waveShaperNode.oversample = e), + this.input.connect(this.waveShaperNode), + this.waveShaperNode.connect(this.wet); + }), + (p5.Distortion.prototype = Object.create(i.prototype)), + (p5.Distortion.prototype.process = function (t, e, n) { + t.connect(this.input), this.set(e, n); + }), + (p5.Distortion.prototype.set = function (t, e) { + if (t) { + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.amount = n), (this.waveShaperNode.curve = o(n)); + } + e && (this.waveShaperNode.oversample = e); + }), + (p5.Distortion.prototype.getAmount = function () { + return this.amount; + }), + (p5.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }), + (p5.Distortion.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this.waveShaperNode && + (this.waveShaperNode.disconnect(), + (this.waveShaperNode = null)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, +]); +//# sourceMappingURL=p5.sound.min.js.map diff --git a/week7-runway/runway_u2net_hosted_model/p5.sound.min.js b/week7-runway/runway_u2net_hosted_model/p5.sound.min.js index fe65a81..2c88ede 100644 --- a/week7-runway/runway_u2net_hosted_model/p5.sound.min.js +++ b/week7-runway/runway_u2net_hosted_model/p5.sound.min.js @@ -1,3 +1,7708 @@ -/** [p5.sound] Version: 0.3.12 - 2020-01-06 */ - !function(n){var i={};function o(t){if(i[t])return i[t].exports;var e=i[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=n,o.c=i,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)o.d(n,i,function(t){return e[t]}.bind(null,i));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=31)}([function(t,e,n){var i;void 0===(i=function(){"use strict";function c(t,e){this.isUndef(t)||1===t?this.input=this.context.createGain():1t)this.cancelScheduledValues(t),this.linearRampToValueAtTime(e,t);else{var i=this._searchAfter(t);i&&(this.cancelScheduledValues(t),i.type===u.TimelineSignal.Type.Linear?this.linearRampToValueAtTime(e,t):i.type===u.TimelineSignal.Type.Exponential&&this.exponentialRampToValueAtTime(e,t)),this.setValueAtTime(e,t)}return this},u.TimelineSignal.prototype.linearRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.linearRampToValueAtTime(t,n),this},u.TimelineSignal.prototype.exponentialRampToValueBetween=function(t,e,n){return this.setRampPoint(e),this.exponentialRampToValueAtTime(t,n),this},u.TimelineSignal.prototype._searchBefore=function(t){return this._events.get(t)},u.TimelineSignal.prototype._searchAfter=function(t){return this._events.getAfter(t)},u.TimelineSignal.prototype.getValueAtTime=function(t){t=this.toSeconds(t);var e=this._searchAfter(t),n=this._searchBefore(t),i=this._initial;if(null===n)i=this._initial;else if(n.type===u.TimelineSignal.Type.Target){var o,r=this._events.getBefore(n.time);o=null===r?this._initial:r.value,i=this._exponentialApproach(n.time,o,n.value,n.constant,t)}else i=n.type===u.TimelineSignal.Type.Curve?this._curveInterpolate(n.time,n.value,n.duration,t):null===e?n.value:e.type===u.TimelineSignal.Type.Linear?this._linearInterpolate(n.time,n.value,e.time,e.value,t):e.type===u.TimelineSignal.Type.Exponential?this._exponentialInterpolate(n.time,n.value,e.time,e.value,t):n.value;return i},u.TimelineSignal.prototype.connect=u.SignalBase.prototype.connect,u.TimelineSignal.prototype._exponentialApproach=function(t,e,n,i,o){return n+(e-n)*Math.exp(-(o-t)/i)},u.TimelineSignal.prototype._linearInterpolate=function(t,e,n,i,o){return e+(o-t)/(n-t)*(i-e)},u.TimelineSignal.prototype._exponentialInterpolate=function(t,e,n,i,o){return(e=Math.max(this._minOutput,e))*Math.pow(i/e,(o-t)/(n-t))},u.TimelineSignal.prototype._curveInterpolate=function(t,e,n,i){var o=e.length;if(t+n<=i)return e[o-1];if(i<=t)return e[0];var r=(i-t)/n,s=Math.floor((o-1)*r),a=Math.ceil((o-1)*r),u=e[s],p=e[a];return a===s?u:this._linearInterpolate(s,u,a,p,r*(o-1))},u.TimelineSignal.prototype.dispose=function(){u.Signal.prototype.dispose.call(this),u.Param.prototype.dispose.call(this),this._events.dispose(),this._events=null},u.TimelineSignal}.apply(e,i))||(t.exports=o)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var e=n(4);return p5.Filter=function(t){e.call(this),this.biquad=this.ac.createBiquadFilter(),this.input.connect(this.biquad),this.biquad.connect(this.wet),t&&this.setType(t),this._on=!0,this._untoggledType=this.biquad.type},p5.Filter.prototype=Object.create(e.prototype),p5.Filter.prototype.process=function(t,e,n,i){t.connect(this.input),this.set(e,n,i)},p5.Filter.prototype.set=function(t,e,n){t&&this.freq(t,n),e&&this.res(e,n)},p5.Filter.prototype.freq=function(t,e){var n=e||0;return t<=0&&(t=1),"number"==typeof t?(this.biquad.frequency.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.frequency.exponentialRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.frequency),this.biquad.frequency.value},p5.Filter.prototype.res=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.Q.value=t,this.biquad.Q.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.Q.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.Q),this.biquad.Q.value},p5.Filter.prototype.gain=function(t,e){var n=e||0;return"number"==typeof t?(this.biquad.gain.value=t,this.biquad.gain.cancelScheduledValues(this.ac.currentTime+.01+n),this.biquad.gain.linearRampToValueAtTime(t,this.ac.currentTime+.02+n)):t&&t.connect(this.biquad.gain),this.biquad.gain.value},p5.Filter.prototype.toggle=function(){return this._on=!this._on,!0===this._on?this.biquad.type=this._untoggledType:!1===this._on&&(this.biquad.type="allpass"),this._on},p5.Filter.prototype.setType=function(t){this.biquad.type=t,this._untoggledType=this.biquad.type},p5.Filter.prototype.dispose=function(){e.prototype.dispose.apply(this),this.biquad&&(this.biquad.disconnect(),delete this.biquad)},p5.LowPass=function(){p5.Filter.call(this,"lowpass")},p5.LowPass.prototype=Object.create(p5.Filter.prototype),p5.HighPass=function(){p5.Filter.call(this,"highpass")},p5.HighPass.prototype=Object.create(p5.Filter.prototype),p5.BandPass=function(){p5.Filter.call(this,"bandpass")},p5.BandPass.prototype=Object.create(p5.Filter.prototype),p5.Filter}.call(e,n,e,t))||(t.exports=i)},function(t,e,n){var i,o;i=[n(0),n(7),n(25),n(2),n(9)],void 0===(o=function(e){"use strict";return e.Subtract=function(t){this.createInsOuts(2,0),this._sum=this.input[0]=this.output=new e.Gain,this._neg=new e.Negate,this._param=this.input[1]=new e.Signal(t),this._param.chain(this._neg,this._sum)},e.extend(e.Subtract,e.Signal),e.Subtract.prototype.dispose=function(){return e.prototype.dispose.call(this),this._neg.dispose(),this._neg=null,this._sum.disconnect(),this._sum=null,this._param.dispose(),this._param=null,this},e.Subtract}.apply(e,i))||(t.exports=o)},function(i,o,r){"use strict";(function(t){var e,n;t.TONE_SILENCE_VERSION_LOGGING=!0,e=[r(35),r(12),r(0)],void 0===(n=function(i,t,e){var o=new window.AudioContext;return e.context.dispose(),e.setContext(o),p5.prototype.getAudioContext=function(){return o},p5.prototype.userStartAudio=function(t,e){var n=t;return t instanceof p5.Element?n=t.elt:t instanceof Array&&t[0]instanceof p5.Element&&(n=t.map(function(t){return t.elt})),i(o,n,e)},o}.apply(o,e))||(i.exports=n)}).call(this,r(34))},function(t,e,n){var i,o;i=[n(0)],void 0===(o=function(s){"use strict";return s.Emitter=function(){this._events={}},s.extend(s.Emitter),s.Emitter.prototype.on=function(t,e){for(var n=t.split(/\W+/),i=0;ithis.memory){var n=this.length-this.memory;this._timeline.splice(0,n)}return this},e.Timeline.prototype.remove=function(t){if(this._iterating)this._toRemove.push(t);else{var e=this._timeline.indexOf(t);-1!==e&&this._timeline.splice(e,1)}return this},e.Timeline.prototype.get=function(t){var e=this._search(t);return-1!==e?this._timeline[e]:null},e.Timeline.prototype.peek=function(){return this._timeline[0]},e.Timeline.prototype.shift=function(){return this._timeline.shift()},e.Timeline.prototype.getAfter=function(t){var e=this._search(t);return e+1=t&&(this._timeline=[]);return this},e.Timeline.prototype.cancelBefore=function(t){if(this._timeline.length){var e=this._search(t);0<=e&&(this._timeline=this._timeline.slice(e+1))}return this},e.Timeline.prototype._search=function(t){var e=0,n=this._timeline.length,i=n;if(0t)return o;r.time>t?i=o:r.time=t;)n--;return this._iterate(e,n+1),this},e.Timeline.prototype.forEachAtTime=function(e,n){var t=this._search(e);return-1!==t&&this._iterate(function(t){t.time===e&&n(t)},0,t),this},e.Timeline.prototype.dispose=function(){e.prototype.dispose.call(this),this._timeline=null,this._toRemove=null},e.Timeline}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(3),n(2)],void 0===(o=function(t){"use strict";return t.Negate=function(){this._multiply=this.input=this.output=new t.Multiply(-1)},t.extend(t.Negate,t.SignalBase),t.Negate.prototype.dispose=function(){return t.prototype.dispose.call(this),this._multiply.dispose(),this._multiply=null,this},t.Negate}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(2),n(3),n(5)],void 0===(o=function(t){"use strict";return t.GreaterThanZero=function(){this._thresh=this.output=new t.WaveShaper(function(t){return t<=0?0:1},127),this._scale=this.input=new t.Multiply(1e4),this._scale.connect(this._thresh)},t.extend(t.GreaterThanZero,t.SignalBase),t.GreaterThanZero.prototype.dispose=function(){return t.prototype.dispose.call(this),this._scale.dispose(),this._scale=null,this._thresh.dispose(),this._thresh=null,this},t.GreaterThanZero}.apply(e,i))||(t.exports=o)},function(t,e,n){var i,o;i=[n(0),n(14),n(66),n(18),n(12)],void 0===(o=function(o){"use strict";return o.Clock=function(){o.Emitter.call(this);var t=this.optionsObject(arguments,["callback","frequency"],o.Clock.defaults);this.callback=t.callback,this._nextTick=0,this._lastState=o.State.Stopped,this.frequency=new o.TimelineSignal(t.frequency,o.Type.Frequency),this._readOnly("frequency"),this.ticks=0,this._state=new o.TimelineState(o.State.Stopped),this._boundLoop=this._loop.bind(this),this.context.on("tick",this._boundLoop)},o.extend(o.Clock,o.Emitter),o.Clock.defaults={callback:o.noOp,frequency:1,lookAhead:"auto"},Object.defineProperty(o.Clock.prototype,"state",{get:function(){return this._state.getValueAtTime(this.now())}}),o.Clock.prototype.start=function(t,e){return t=this.toSeconds(t),this._state.getValueAtTime(t)!==o.State.Started&&this._state.add({state:o.State.Started,time:t,offset:e}),this},o.Clock.prototype.stop=function(t){return t=this.toSeconds(t),this._state.cancel(t),this._state.setStateAtTime(o.State.Stopped,t),this},o.Clock.prototype.pause=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)===o.State.Started&&this._state.setStateAtTime(o.State.Paused,t),this},o.Clock.prototype._loop=function(){for(var t=this.now()+this.context.lookAhead+this.context.updateInterval+2*this.context.lag;t>this._nextTick&&this._state;){var e=this._state.getValueAtTime(this._nextTick);if(e!==this._lastState){this._lastState=e;var n=this._state.get(this._nextTick);e===o.State.Started?(this._nextTick=n.time,this.isUndef(n.offset)||(this.ticks=n.offset),this.emit("start",n.time,this.ticks)):e===o.State.Stopped?(this.ticks=0,this.emit("stop",n.time)):e===o.State.Paused&&this.emit("pause",n.time)}var i=this._nextTick;this.frequency&&(this._nextTick+=1/this.frequency.getValueAtTime(this._nextTick),e===o.State.Started&&(this.callback(i),this.ticks++))}},o.Clock.prototype.getStateAtTime=function(t){return t=this.toSeconds(t),this._state.getValueAtTime(t)},o.Clock.prototype.dispose=function(){o.Emitter.prototype.dispose.call(this),this.context.off("tick",this._boundLoop),this._writable("frequency"),this.frequency.dispose(),this.frequency=null,this._boundLoop=null,this._nextTick=1/0,this.callback=null,this._state.dispose(),this._state=null},o.Clock}.apply(e,i))||(t.exports=o)},function(t,e,i){"use strict";var n;void 0===(n=function(t){var n=i(1),e=i(29),r=i(6).noteToFreq;p5.MonoSynth=function(){e.call(this),this.oscillator=new p5.Oscillator,this.env=new p5.Envelope,this.env.setRange(1,0),this.env.setExp(!0),this.setADSR(.02,.25,.05,.35),this.oscillator.disconnect(),this.oscillator.connect(this.output),this.env.disconnect(),this.env.setInput(this.output.gain),this.oscillator.output.gain.value=1,this.oscillator.start(),this.connect(),n.soundArray.push(this)},p5.MonoSynth.prototype=Object.create(p5.AudioVoice.prototype),p5.MonoSynth.prototype.play=function(t,e,n,i){this.triggerAttack(t,e,~~n),this.triggerRelease(~~n+(i||.15))},p5.MonoSynth.prototype.triggerAttack=function(t,e,n){n=~~n;var i=r(t),o=e||.1;this.oscillator.freq(i,0,n),this.env.ramp(this.output.gain,n,o)},p5.MonoSynth.prototype.triggerRelease=function(t){t=t||0;this.env.ramp(this.output.gain,t,0)},p5.MonoSynth.prototype.setADSR=function(t,e,n,i){this.env.setADSR(t,e,n,i)},Object.defineProperties(p5.MonoSynth.prototype,{attack:{get:function(){return this.env.aTime},set:function(t){this.env.setADSR(t,this.env.dTime,this.env.sPercent,this.env.rTime)}},decay:{get:function(){return this.env.dTime},set:function(t){this.env.setADSR(this.env.aTime,t,this.env.sPercent,this.env.rTime)}},sustain:{get:function(){return this.env.sPercent},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,t,this.env.rTime)}},release:{get:function(){return this.env.rTime},set:function(t){this.env.setADSR(this.env.aTime,this.env.dTime,this.env.sPercent,t)}}}),p5.MonoSynth.prototype.amp=function(t,e){var n=e||0;return void 0!==t&&this.oscillator.amp(t,n),this.oscillator.amp().value},p5.MonoSynth.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.MonoSynth.prototype.disconnect=function(){this.output&&this.output.disconnect()},p5.MonoSynth.prototype.dispose=function(){e.prototype.dispose.apply(this),this.env&&this.env.dispose(),this.oscillator&&this.oscillator.dispose()}}.call(e,i,e,t))||(t.exports=n)},function(t,e,i){"use strict";var n;void 0===(n=function(){var n=i(1);return p5.AudioVoice=function(){this.ac=n.audiocontext,this.output=this.ac.createGain(),this.connect(),n.soundArray.push(this)},p5.AudioVoice.prototype.play=function(t,e,n,i){},p5.AudioVoice.prototype.triggerAttack=function(t,e,n){},p5.AudioVoice.prototype.triggerRelease=function(t){},p5.AudioVoice.prototype.amp=function(t,e){},p5.AudioVoice.prototype.connect=function(t){var e=t||n.input;this.output.connect(e.input?e.input:e)},p5.AudioVoice.prototype.disconnect=function(){this.output.disconnect()},p5.AudioVoice.prototype.dispose=function(){this.output&&(this.output.disconnect(),delete this.output)},p5.AudioVoice}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var c=n(1),h=n(14),l=n(6).noteToFreq;p5.PolySynth=function(t,e){this.audiovoices=[],this.notes={},this._newest=0,this._oldest=0,this.maxVoices=e||8,this.AudioVoice=void 0===t?p5.MonoSynth:t,this._voicesInUse=new h(0),this.output=c.audiocontext.createGain(),this.connect(),this._allocateVoices(),c.soundArray.push(this)},p5.PolySynth.prototype._allocateVoices=function(){for(var t=0;t= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'},function(t,e,n){"use strict";n.r(e),e.default='function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'},function(t,e,n){"use strict";var i;function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}void 0===(i=function(t){var a=n(1).audiocontext;void 0!==a.createStereoPanner?(p5.Panner=function(t,e){this.stereoPanner=this.input=a.createStereoPanner(),t.connect(this.stereoPanner),this.stereoPanner.connect(e)},p5.Panner.prototype.pan=function(t,e){var n=e||0,i=a.currentTime+n;this.stereoPanner.pan.linearRampToValueAtTime(t,i)},p5.Panner.prototype.inputChannels=function(){},p5.Panner.prototype.connect=function(t){this.stereoPanner.connect(t)},p5.Panner.prototype.disconnect=function(){this.stereoPanner&&this.stereoPanner.disconnect()}):(p5.Panner=function(t,e,n){this.input=a.createGain(),t.connect(this.input),this.left=a.createGain(),this.right=a.createGain(),this.left.channelInterpretation="discrete",this.right.channelInterpretation="discrete",1this.buffer.duration)throw"jump time out of range";if(e>this.buffer.duration-t)throw"end time out of range";var n=t||0,i=e||void 0;this.isPlaying()&&(this.stop(0),this.play(0,this.playbackRate,this.output.gain.value,n,i))},p5.SoundFile.prototype.channels=function(){return this.buffer.numberOfChannels},p5.SoundFile.prototype.sampleRate=function(){return this.buffer.sampleRate},p5.SoundFile.prototype.frames=function(){return this.buffer.length},p5.SoundFile.prototype.getPeaks=function(t){if(!this.buffer)throw"Cannot load peaks yet, buffer is not loaded";if(t=t||5*window.width,this.buffer){for(var e=this.buffer,n=e.length/t,i=~~(n/10)||1,o=e.numberOfChannels,r=new Float32Array(Math.round(t)),s=0;sr[u])&&(r[u]=h)}return r}},p5.SoundFile.prototype.reverseBuffer=function(){if(!this.buffer)throw"SoundFile is not done loading";var t=this._lastPos/p.sampleRate,e=this.getVolume();this.setVolume(0,.001);for(var n=this.buffer.numberOfChannels,i=0;ie){var r=t[o],s=new c(r,o);n[o]=s,o+=6e3}o++}return n}function m(t){if(isFinite(t)&&0!==t){for(;t<90;)t*=2;for(;180t[r].hi&&r++,o[r]=void 0!==o[r]?(o[r]+n[s])/2:n[s]}return o},p5.FFT.prototype.getOctaveBands=function(t,e){t=t||3;var n=[],i={lo:(e=e||15.625)/Math.pow(2,1/(2*t)),ctr:e,hi:e*Math.pow(2,1/(2*t))};n.push(i);for(var o=c.audiocontext.sampleRate/2;i.hi=this._maxDelay)throw new Error("Delay Time exceeds maximum delay time of "+this._maxDelay+" second.");t.connect(this.input),this.leftDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this.rightDelay.delayTime.setValueAtTime(r,this.ac.currentTime),this._leftGain.gain.value=o,this._rightGain.gain.value=o,i&&(this._leftFilter.freq(i),this._rightFilter.freq(i))},p5.Delay.prototype.delayTime=function(t){"number"!=typeof t?(t.connect(this.leftDelay.delayTime),t.connect(this.rightDelay.delayTime)):(this.leftDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.rightDelay.delayTime.cancelScheduledValues(this.ac.currentTime),this.leftDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime),this.rightDelay.delayTime.linearRampToValueAtTime(t,this.ac.currentTime))},p5.Delay.prototype.feedback=function(t){if(t&&"number"!=typeof t)t.connect(this._leftGain.gain),t.connect(this._rightGain.gain);else{if(1<=t)throw new Error("Feedback value will force a positive feedback loop.");"number"==typeof t&&(this._leftGain.gain.value=t,this._rightGain.gain.value=t)}return this._leftGain.gain.value},p5.Delay.prototype.filter=function(t,e){this._leftFilter.set(t,e),this._rightFilter.set(t,e)},p5.Delay.prototype.setType=function(t){switch(1===t&&(t="pingPong"),this._split.disconnect(),this._leftFilter.disconnect(),this._rightFilter.disconnect(),this._split.connect(this.leftDelay,0),this._split.connect(this.rightDelay,1),t){case"pingPong":this._rightFilter.setType(this._leftFilter.biquad.type),this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.rightDelay),this._rightFilter.output.connect(this.leftDelay);break;default:this._leftFilter.output.connect(this._merge,0,0),this._rightFilter.output.connect(this._merge,0,1),this._leftFilter.output.connect(this.leftDelay),this._rightFilter.output.connect(this.rightDelay)}},p5.Delay.prototype.dispose=function(){n.prototype.dispose.apply(this),this._split.disconnect(),this._leftFilter.dispose(),this._rightFilter.dispose(),this._merge.disconnect(),this._leftGain.disconnect(),this._rightGain.disconnect(),this.leftDelay.disconnect(),this.rightDelay.disconnect(),this._split=void 0,this._leftFilter=void 0,this._rightFilter=void 0,this._merge=void 0,this._leftGain=void 0,this._rightGain=void 0,this.leftDelay=void 0,this.rightDelay=void 0}}.call(e,i,e,t))||(t.exports=n)},function(t,e,n){"use strict";var i;void 0===(i=function(t){var p=n(11),e=n(4);p5.Reverb=function(){e.call(this),this._initConvolverNode(),this.input.gain.value=.5,this._seconds=3,this._decay=2,this._reverse=!1,this._buildImpulse()},p5.Reverb.prototype=Object.create(e.prototype),p5.Reverb.prototype._initConvolverNode=function(){this.convolverNode=this.ac.createConvolver(),this.input.connect(this.convolverNode),this.convolverNode.connect(this.wet)},p5.Reverb.prototype._teardownConvolverNode=function(){this.convolverNode&&(this.convolverNode.disconnect(),delete this.convolverNode)},p5.Reverb.prototype._setBuffer=function(t){this._teardownConvolverNode(),this._initConvolverNode(),this.convolverNode.buffer=t},p5.Reverb.prototype.process=function(t,e,n,i){t.connect(this.input);var o=!1;e&&(this._seconds=e,o=!0),n&&(this._decay=n),i&&(this._reverse=i),o&&this._buildImpulse()},p5.Reverb.prototype.set=function(t,e,n){var i=!1;t&&(this._seconds=t,i=!0),e&&(this._decay=e),n&&(this._reverse=n),i&&this._buildImpulse()},p5.Reverb.prototype._buildImpulse=function(){var t,e,n=this.ac.sampleRate,i=n*this._seconds,o=this._decay,r=this.ac.createBuffer(2,i,n),s=r.getChannelData(0),a=r.getChannelData(1);for(e=0;e=t.parts.length?(t.scoreStep=0,t.onended()):(t.scoreStep=0,t.parts[t.currentPart-1].stop(),t.parts[t.currentPart].start())}p5.prototype.setBPM=function(t,e){for(var n in o=t,i.parts)i.parts[n]&&i.parts[n].setBPM(t,e)},p5.Phrase=function(t,e,n){this.phraseStep=0,this.name=t,this.callback=e,this.sequence=n},p5.Part=function(t,e){this.length=t||0,this.partStep=0,this.phrases=[],this.isPlaying=!1,this.noLoop(),this.tatums=e||.0625,this.metro=new p5.Metro,this.metro._init(),this.metro.beatLength(this.tatums),this.metro.setBPM(o),i.parts.push(this),this.callback=function(){}},p5.Part.prototype.setBPM=function(t,e){this.metro.setBPM(t,e)},p5.Part.prototype.getBPM=function(){return this.metro.getBPM()},p5.Part.prototype.start=function(t){if(!this.isPlaying){this.isPlaying=!0,this.metro.resetSync(this);var e=t||0;this.metro.start(e)}},p5.Part.prototype.loop=function(t){this.looping=!0,this.onended=function(){this.partStep=0};var e=t||0;this.start(e)},p5.Part.prototype.noLoop=function(){this.looping=!1,this.onended=function(){this.stop()}},p5.Part.prototype.stop=function(t){this.partStep=0,this.pause(t)},p5.Part.prototype.pause=function(t){this.isPlaying=!1;var e=t||0;this.metro.stop(e)},p5.Part.prototype.addPhrase=function(t,e,n){var i;if(3===arguments.length)i=new p5.Phrase(t,e,n);else{if(!(t instanceof p5.Phrase))throw"invalid input. addPhrase accepts name, callback, array or a p5.Phrase";i=t}this.phrases.push(i),i.sequence.length>this.length&&(this.length=i.sequence.length)},p5.Part.prototype.removePhrase=function(t){for(var e in this.phrases)this.phrases[e].name===t&&this.phrases.splice(e,1)},p5.Part.prototype.getPhrase=function(t){for(var e in this.phrases)if(this.phrases[e].name===t)return this.phrases[e]},p5.Part.prototype.replaceSequence=function(t,e){for(var n in this.phrases)this.phrases[n].name===t&&(this.phrases[n].sequence=e)},p5.Part.prototype.incrementStep=function(t){this.partStepthis.cutoff&&e>this.threshold&&0 t + ) + this.cancelScheduledValues(t), + this.linearRampToValueAtTime(e, t); + else { + var i = this._searchAfter(t); + i && + (this.cancelScheduledValues(t), + i.type === u.TimelineSignal.Type.Linear + ? this.linearRampToValueAtTime(e, t) + : i.type === u.TimelineSignal.Type.Exponential && + this.exponentialRampToValueAtTime(e, t)), + this.setValueAtTime(e, t); + } + return this; + }), + (u.TimelineSignal.prototype.linearRampToValueBetween = function ( + t, + e, + n + ) { + return ( + this.setRampPoint(e), this.linearRampToValueAtTime(t, n), this + ); + }), + (u.TimelineSignal.prototype.exponentialRampToValueBetween = + function (t, e, n) { + return ( + this.setRampPoint(e), + this.exponentialRampToValueAtTime(t, n), + this + ); + }), + (u.TimelineSignal.prototype._searchBefore = function (t) { + return this._events.get(t); + }), + (u.TimelineSignal.prototype._searchAfter = function (t) { + return this._events.getAfter(t); + }), + (u.TimelineSignal.prototype.getValueAtTime = function (t) { + t = this.toSeconds(t); + var e = this._searchAfter(t), + n = this._searchBefore(t), + i = this._initial; + if (null === n) i = this._initial; + else if (n.type === u.TimelineSignal.Type.Target) { + var o, + r = this._events.getBefore(n.time); + (o = null === r ? this._initial : r.value), + (i = this._exponentialApproach( + n.time, + o, + n.value, + n.constant, + t + )); + } else + i = + n.type === u.TimelineSignal.Type.Curve + ? this._curveInterpolate(n.time, n.value, n.duration, t) + : null === e + ? n.value + : e.type === u.TimelineSignal.Type.Linear + ? this._linearInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : e.type === u.TimelineSignal.Type.Exponential + ? this._exponentialInterpolate( + n.time, + n.value, + e.time, + e.value, + t + ) + : n.value; + return i; + }), + (u.TimelineSignal.prototype.connect = + u.SignalBase.prototype.connect), + (u.TimelineSignal.prototype._exponentialApproach = function ( + t, + e, + n, + i, + o + ) { + return n + (e - n) * Math.exp(-(o - t) / i); + }), + (u.TimelineSignal.prototype._linearInterpolate = function ( + t, + e, + n, + i, + o + ) { + return e + ((o - t) / (n - t)) * (i - e); + }), + (u.TimelineSignal.prototype._exponentialInterpolate = function ( + t, + e, + n, + i, + o + ) { + return ( + (e = Math.max(this._minOutput, e)) * + Math.pow(i / e, (o - t) / (n - t)) + ); + }), + (u.TimelineSignal.prototype._curveInterpolate = function ( + t, + e, + n, + i + ) { + var o = e.length; + if (t + n <= i) return e[o - 1]; + if (i <= t) return e[0]; + var r = (i - t) / n, + s = Math.floor((o - 1) * r), + a = Math.ceil((o - 1) * r), + u = e[s], + p = e[a]; + return a === s + ? u + : this._linearInterpolate(s, u, a, p, r * (o - 1)); + }), + (u.TimelineSignal.prototype.dispose = function () { + u.Signal.prototype.dispose.call(this), + u.Param.prototype.dispose.call(this), + this._events.dispose(), + (this._events = null); + }), + u.TimelineSignal + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(4); + return ( + (p5.Filter = function (t) { + e.call(this), + (this.biquad = this.ac.createBiquadFilter()), + this.input.connect(this.biquad), + this.biquad.connect(this.wet), + t && this.setType(t), + (this._on = !0), + (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype = Object.create(e.prototype)), + (p5.Filter.prototype.process = function (t, e, n, i) { + t.connect(this.input), this.set(e, n, i); + }), + (p5.Filter.prototype.set = function (t, e, n) { + t && this.freq(t, n), e && this.res(e, n); + }), + (p5.Filter.prototype.freq = function (t, e) { + var n = e || 0; + return ( + t <= 0 && (t = 1), + "number" == typeof t + ? (this.biquad.frequency.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.frequency.exponentialRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.frequency), + this.biquad.frequency.value + ); + }), + (p5.Filter.prototype.res = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.Q.value = t), + this.biquad.Q.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.Q.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.Q), + this.biquad.Q.value + ); + }), + (p5.Filter.prototype.gain = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.biquad.gain.value = t), + this.biquad.gain.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.biquad.gain.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.biquad.gain), + this.biquad.gain.value + ); + }), + (p5.Filter.prototype.toggle = function () { + return ( + (this._on = !this._on), + !0 === this._on + ? (this.biquad.type = this._untoggledType) + : !1 === this._on && (this.biquad.type = "allpass"), + this._on + ); + }), + (p5.Filter.prototype.setType = function (t) { + (this.biquad.type = t), (this._untoggledType = this.biquad.type); + }), + (p5.Filter.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.biquad && (this.biquad.disconnect(), delete this.biquad); + }), + (p5.LowPass = function () { + p5.Filter.call(this, "lowpass"); + }), + (p5.LowPass.prototype = Object.create(p5.Filter.prototype)), + (p5.HighPass = function () { + p5.Filter.call(this, "highpass"); + }), + (p5.HighPass.prototype = Object.create(p5.Filter.prototype)), + (p5.BandPass = function () { + p5.Filter.call(this, "bandpass"); + }), + (p5.BandPass.prototype = Object.create(p5.Filter.prototype)), + p5.Filter + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(7), n(25), n(2), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Subtract = function (t) { + this.createInsOuts(2, 0), + (this._sum = this.input[0] = this.output = new e.Gain()), + (this._neg = new e.Negate()), + (this._param = this.input[1] = new e.Signal(t)), + this._param.chain(this._neg, this._sum); + }), + e.extend(e.Subtract, e.Signal), + (e.Subtract.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._neg.dispose(), + (this._neg = null), + this._sum.disconnect(), + (this._sum = null), + this._param.dispose(), + (this._param = null), + this + ); + }), + e.Subtract + ); + }.apply(e, i)) || (t.exports = o); + }, + function (i, o, r) { + "use strict"; + (function (t) { + var e, n; + (t.TONE_SILENCE_VERSION_LOGGING = !0), + (e = [r(35), r(12), r(0)]), + void 0 === + (n = function (i, t, e) { + var o = new window.AudioContext(); + return ( + e.context.dispose(), + e.setContext(o), + (p5.prototype.getAudioContext = function () { + return o; + }), + (p5.prototype.userStartAudio = function (t, e) { + var n = t; + return ( + t instanceof p5.Element + ? (n = t.elt) + : t instanceof Array && + t[0] instanceof p5.Element && + (n = t.map(function (t) { + return t.elt; + })), + i(o, n, e) + ); + }), + o + ); + }.apply(o, e)) || (i.exports = n); + }).call(this, r(34)); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (s) { + "use strict"; + return ( + (s.Emitter = function () { + this._events = {}; + }), + s.extend(s.Emitter), + (s.Emitter.prototype.on = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) { + var o = n[i]; + this._events.hasOwnProperty(o) || (this._events[o] = []), + this._events[o].push(e); + } + return this; + }), + (s.Emitter.prototype.off = function (t, e) { + for (var n = t.split(/\W+/), i = 0; i < n.length; i++) + if (((t = n[i]), this._events.hasOwnProperty(t))) + if (s.prototype.isUndef(e)) this._events[t] = []; + else + for (var o = this._events[t], r = 0; r < o.length; r++) + o[r] === e && o.splice(r, 1); + return this; + }), + (s.Emitter.prototype.emit = function (t) { + if (this._events) { + var e = Array.apply(null, arguments).slice(1); + if (this._events.hasOwnProperty(t)) + for (var n = this._events[t], i = 0, o = n.length; i < o; i++) + n[i].apply(this, e); + } + return this; + }), + (s.Emitter.mixin = function (t) { + var e = ["on", "off", "emit"]; + t._events = {}; + for (var n = 0; n < e.length; n++) { + var i = e[n], + o = s.Emitter.prototype[i]; + t[i] = o; + } + }), + (s.Emitter.prototype.dispose = function () { + return ( + s.prototype.dispose.call(this), (this._events = null), this + ); + }), + s.Emitter + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.SignalBase = function () {}), + i.extend(i.SignalBase), + (i.SignalBase.prototype.connect = function (t, e, n) { + return ( + (i.Signal && i.Signal === t.constructor) || + (i.Param && i.Param === t.constructor) || + (i.TimelineSignal && i.TimelineSignal === t.constructor) + ? (t._param.cancelScheduledValues(0), + (t._param.value = 0), + (t.overridden = !0)) + : t instanceof AudioParam && + (t.cancelScheduledValues(0), (t.value = 0)), + i.prototype.connect.call(this, t, e, n), + this + ); + }), + i.SignalBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (n) { + return ( + (n.Time = function (t, e) { + if (!(this instanceof n.Time)) return new n.Time(t, e); + (this._plusNow = !1), n.TimeBase.call(this, t, e); + }), + n.extend(n.Time, n.TimeBase), + (n.Time.prototype._unaryExpressions = Object.create( + n.TimeBase.prototype._unaryExpressions + )), + (n.Time.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + return n.Transport.nextSubdivision(t()); + }, + }), + (n.Time.prototype._unaryExpressions.now = { + regexp: /^\+/, + method: function (t) { + return (this._plusNow = !0), t(); + }, + }), + (n.Time.prototype.quantize = function (t, e) { + return ( + (e = this.defaultArg(e, 1)), + (this._expr = function (t, e, n) { + return ( + (t = t()), + (e = e.toSeconds()), + t + (Math.round(t / e) * e - t) * n + ); + }.bind(this, this._expr, new this.constructor(t), e)), + this + ); + }), + (n.Time.prototype.addNow = function () { + return (this._plusNow = !0), this; + }), + (n.Time.prototype._defaultExpr = function () { + return (this._plusNow = !0), this._noOp; + }), + (n.Time.prototype.copy = function (t) { + return ( + n.TimeBase.prototype.copy.call(this, t), + (this._plusNow = t._plusNow), + this + ); + }), + (n.Time.prototype.toNotation = function () { + var t = this.toSeconds(), + e = this._toNotationHelper(t, [ + "1m", + "2n", + "4n", + "8n", + "16n", + "32n", + "64n", + "128n", + ]), + n = this._toNotationHelper(t, [ + "1m", + "2n", + "2t", + "4n", + "4t", + "8n", + "8t", + "16n", + "16t", + "32n", + "32t", + "64n", + "64t", + "128n", + ]); + return n.split("+").length < e.split("+").length ? n : e; + }), + (n.Time.prototype._toNotationHelper = function (t, e) { + for ( + var n = this._notationToUnits(e[e.length - 1]), i = "", o = 0; + o < e.length; + o++ + ) { + var r = this._notationToUnits(e[o]), + s = t / r; + if ( + (1 - (s % 1) < 1e-6 && (s += 1e-6), 0 < (s = Math.floor(s))) + ) { + if ( + ((i += 1 === s ? e[o] : s.toString() + "*" + e[o]), + (t -= s * r) < n) + ) + break; + i += " + "; + } + } + return "" === i && (i = "0"), i; + }), + (n.Time.prototype._notationToUnits = function (t) { + for ( + var e = this._primaryExpressions, n = [e.n, e.t, e.m], i = 0; + i < n.length; + i++ + ) { + var o = n[i], + r = t.match(o.regexp); + if (r) return o.method.call(this, r[1]); + } + }), + (n.Time.prototype.toBarsBeatsSixteenths = function () { + var t = this._beatsToUnits(1), + e = this.toSeconds() / t, + n = Math.floor(e / this._timeSignature()), + i = (e % 1) * 4; + return ( + (e = Math.floor(e) % this._timeSignature()), + 3 < (i = i.toString()).length && (i = parseFloat(i).toFixed(3)), + [n, e, i].join(":") + ); + }), + (n.Time.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * n.Transport.PPQ); + }), + (n.Time.prototype.toSamples = function () { + return this.toSeconds() * this.context.sampleRate; + }), + (n.Time.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + (n.Time.prototype.toSeconds = function () { + return this.valueOf(); + }), + (n.Time.prototype.toMilliseconds = function () { + return 1e3 * this.toSeconds(); + }), + (n.Time.prototype.valueOf = function () { + return this._expr() + (this._plusNow ? this.now() : 0); + }), + n.Time + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0)]), + void 0 === + (o = function (i) { + return ( + (i.TimeBase = function (t, e) { + if (!(this instanceof i.TimeBase)) return new i.TimeBase(t, e); + if (((this._expr = this._noOp), t instanceof i.TimeBase)) + this.copy(t); + else if (!this.isUndef(e) || this.isNumber(t)) { + e = this.defaultArg(e, this._defaultUnits); + var n = this._primaryExpressions[e].method; + this._expr = n.bind(this, t); + } else + this.isString(t) + ? this.set(t) + : this.isUndef(t) && (this._expr = this._defaultExpr()); + }), + i.extend(i.TimeBase), + (i.TimeBase.prototype.set = function (t) { + return (this._expr = this._parseExprString(t)), this; + }), + (i.TimeBase.prototype.clone = function () { + var t = new this.constructor(); + return t.copy(this), t; + }), + (i.TimeBase.prototype.copy = function (t) { + var e = t._expr(); + return this.set(e); + }), + (i.TimeBase.prototype._primaryExpressions = { + n: { + regexp: /^(\d+)n/i, + method: function (t) { + return 1 === (t = parseInt(t)) + ? this._beatsToUnits(this._timeSignature()) + : this._beatsToUnits(4 / t); + }, + }, + t: { + regexp: /^(\d+)t/i, + method: function (t) { + return ( + (t = parseInt(t)), this._beatsToUnits(8 / (3 * parseInt(t))) + ); + }, + }, + m: { + regexp: /^(\d+)m/i, + method: function (t) { + return this._beatsToUnits( + parseInt(t) * this._timeSignature() + ); + }, + }, + i: { + regexp: /^(\d+)i/i, + method: function (t) { + return this._ticksToUnits(parseInt(t)); + }, + }, + hz: { + regexp: /^(\d+(?:\.\d+)?)hz/i, + method: function (t) { + return this._frequencyToUnits(parseFloat(t)); + }, + }, + tr: { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 0; + return ( + t && + "0" !== t && + (i += this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i += this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i += this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }, + s: { + regexp: /^(\d+(?:\.\d+)?s)/, + method: function (t) { + return this._secondsToUnits(parseFloat(t)); + }, + }, + samples: { + regexp: /^(\d+)samples/, + method: function (t) { + return parseInt(t) / this.context.sampleRate; + }, + }, + default: { + regexp: /^(\d+(?:\.\d+)?)/, + method: function (t) { + return this._primaryExpressions[ + this._defaultUnits + ].method.call(this, t); + }, + }, + }), + (i.TimeBase.prototype._binaryExpressions = { + "+": { + regexp: /^\+/, + precedence: 2, + method: function (t, e) { + return t() + e(); + }, + }, + "-": { + regexp: /^\-/, + precedence: 2, + method: function (t, e) { + return t() - e(); + }, + }, + "*": { + regexp: /^\*/, + precedence: 1, + method: function (t, e) { + return t() * e(); + }, + }, + "/": { + regexp: /^\//, + precedence: 1, + method: function (t, e) { + return t() / e(); + }, + }, + }), + (i.TimeBase.prototype._unaryExpressions = { + neg: { + regexp: /^\-/, + method: function (t) { + return -t(); + }, + }, + }), + (i.TimeBase.prototype._syntaxGlue = { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + }), + (i.TimeBase.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim()), this); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t, e) { + for ( + var n = [ + "_binaryExpressions", + "_unaryExpressions", + "_primaryExpressions", + "_syntaxGlue", + ], + i = 0; + i < n.length; + i++ + ) { + var o = e[n[i]]; + for (var r in o) { + var s = o[r], + a = s.regexp, + u = t.match(a); + if (null !== u) + return { + method: s.method, + precedence: s.precedence, + regexp: s.regexp, + value: u[0], + }; + } + } + throw new SyntaxError("Tone.TimeBase: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (i.TimeBase.prototype._matchGroup = function (t, e, n) { + if (!this.isUndef(t)) + for (var i in e) { + var o = e[i]; + if (o.regexp.test(t.value)) { + if (this.isUndef(n)) return o; + if (o.precedence === n) return o; + } + } + return !1; + }), + (i.TimeBase.prototype._parseBinary = function (t, e) { + var n; + this.isUndef(e) && (e = 2), + (n = e < 0 ? this._parseUnary(t) : this._parseBinary(t, e - 1)); + for ( + var i = t.peek(); + i && this._matchGroup(i, this._binaryExpressions, e); + + ) + (n = (i = t.next()).method.bind( + this, + n, + this._parseBinary(t, e - 1) + )), + (i = t.peek()); + return n; + }), + (i.TimeBase.prototype._parseUnary = function (t) { + var e, n; + e = t.peek(); + var i = this._matchGroup(e, this._unaryExpressions); + return i + ? ((e = t.next()), + (n = this._parseUnary(t)), + i.method.bind(this, n)) + : this._parsePrimary(t); + }), + (i.TimeBase.prototype._parsePrimary = function (t) { + var e, n; + if (((e = t.peek()), this.isUndef(e))) + throw new SyntaxError( + "Tone.TimeBase: Unexpected end of expression" + ); + if (this._matchGroup(e, this._primaryExpressions)) { + var i = (e = t.next()).value.match(e.regexp); + return e.method.bind(this, i[1], i[2], i[3]); + } + if (e && "(" === e.value) { + if ( + (t.next(), + (n = this._parseBinary(t)), + !(e = t.next()) || ")" !== e.value) + ) + throw new SyntaxError("Expected )"); + return n; + } + throw new SyntaxError( + "Tone.TimeBase: Cannot process token " + e.value + ); + }), + (i.TimeBase.prototype._parseExprString = function (t) { + this.isString(t) || (t = t.toString()); + var e = this._tokenize(t); + return this._parseBinary(e); + }), + (i.TimeBase.prototype._noOp = function () { + return 0; + }), + (i.TimeBase.prototype._defaultExpr = function () { + return this._noOp; + }), + (i.TimeBase.prototype._defaultUnits = "s"), + (i.TimeBase.prototype._frequencyToUnits = function (t) { + return 1 / t; + }), + (i.TimeBase.prototype._beatsToUnits = function (t) { + return (60 / i.Transport.bpm.value) * t; + }), + (i.TimeBase.prototype._secondsToUnits = function (t) { + return t; + }), + (i.TimeBase.prototype._ticksToUnits = function (t) { + return t * (this._beatsToUnits(1) / i.Transport.PPQ); + }), + (i.TimeBase.prototype._timeSignature = function () { + return i.Transport.timeSignature; + }), + (i.TimeBase.prototype._pushExpr = function (t, e, n) { + return ( + t instanceof i.TimeBase || (t = new this.constructor(t, n)), + (this._expr = this._binaryExpressions[e].method.bind( + this, + this._expr, + t._expr + )), + this + ); + }), + (i.TimeBase.prototype.add = function (t, e) { + return this._pushExpr(t, "+", e); + }), + (i.TimeBase.prototype.sub = function (t, e) { + return this._pushExpr(t, "-", e); + }), + (i.TimeBase.prototype.mult = function (t, e) { + return this._pushExpr(t, "*", e); + }), + (i.TimeBase.prototype.div = function (t, e) { + return this._pushExpr(t, "/", e); + }), + (i.TimeBase.prototype.valueOf = function () { + return this._expr(); + }), + (i.TimeBase.prototype.dispose = function () { + this._expr = null; + }), + i.TimeBase + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (i) { + "use strict"; + return ( + (i.Param = function () { + var t = this.optionsObject( + arguments, + ["param", "units", "convert"], + i.Param.defaults + ); + (this._param = this.input = t.param), + (this.units = t.units), + (this.convert = t.convert), + (this.overridden = !1), + (this._lfo = null), + this.isObject(t.lfo) + ? (this.value = t.lfo) + : this.isUndef(t.value) || (this.value = t.value); + }), + i.extend(i.Param), + (i.Param.defaults = { + units: i.Type.Default, + convert: !0, + param: void 0, + }), + Object.defineProperty(i.Param.prototype, "value", { + get: function () { + return this._toUnits(this._param.value); + }, + set: function (t) { + if (this.isObject(t)) { + if (this.isUndef(i.LFO)) + throw new Error( + "Include 'Tone.LFO' to use an LFO as a Param value." + ); + this._lfo && this._lfo.dispose(), + (this._lfo = new i.LFO(t).start()), + this._lfo.connect(this.input); + } else { + var e = this._fromUnits(t); + this._param.cancelScheduledValues(0), (this._param.value = e); + } + }, + }), + (i.Param.prototype._fromUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Time: + return this.toSeconds(t); + case i.Type.Frequency: + return this.toFrequency(t); + case i.Type.Decibels: + return this.dbToGain(t); + case i.Type.NormalRange: + return Math.min(Math.max(t, 0), 1); + case i.Type.AudioRange: + return Math.min(Math.max(t, -1), 1); + case i.Type.Positive: + return Math.max(t, 0); + default: + return t; + } + }), + (i.Param.prototype._toUnits = function (t) { + if (!this.convert && !this.isUndef(this.convert)) return t; + switch (this.units) { + case i.Type.Decibels: + return this.gainToDb(t); + default: + return t; + } + }), + (i.Param.prototype._minOutput = 1e-5), + (i.Param.prototype.setValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (e = this.toSeconds(e)) <= this.now() + this.blockTime + ? (this._param.value = t) + : this._param.setValueAtTime(t, e), + this + ); + }), + (i.Param.prototype.setRampPoint = function (t) { + t = this.defaultArg(t, this.now()); + var e = this._param.value; + return ( + 0 === e && (e = this._minOutput), + this._param.setValueAtTime(e, t), + this + ); + }), + (i.Param.prototype.linearRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + this._param.linearRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValueAtTime = function (t, e) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + this._param.exponentialRampToValueAtTime(t, this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.exponentialRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.exponentialRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.linearRampToValue = function (t, e, n) { + return ( + (n = this.toSeconds(n)), + this.setRampPoint(n), + this.linearRampToValueAtTime(t, n + this.toSeconds(e)), + this + ); + }), + (i.Param.prototype.setTargetAtTime = function (t, e, n) { + return ( + (t = this._fromUnits(t)), + (t = Math.max(this._minOutput, t)), + (n = Math.max(this._minOutput, n)), + this._param.setTargetAtTime(t, this.toSeconds(e), n), + this + ); + }), + (i.Param.prototype.setValueCurveAtTime = function (t, e, n) { + for (var i = 0; i < t.length; i++) t[i] = this._fromUnits(t[i]); + return ( + this._param.setValueCurveAtTime( + t, + this.toSeconds(e), + this.toSeconds(n) + ), + this + ); + }), + (i.Param.prototype.cancelScheduledValues = function (t) { + return this._param.cancelScheduledValues(this.toSeconds(t)), this; + }), + (i.Param.prototype.rampTo = function (t, e, n) { + return ( + (e = this.defaultArg(e, 0)), + this.units === i.Type.Frequency || + this.units === i.Type.BPM || + this.units === i.Type.Decibels + ? this.exponentialRampToValue(t, e, n) + : this.linearRampToValue(t, e, n), + this + ); + }), + Object.defineProperty(i.Param.prototype, "lfo", { + get: function () { + return this._lfo; + }, + }), + (i.Param.prototype.dispose = function () { + return ( + i.prototype.dispose.call(this), + (this._param = null), + this._lfo && (this._lfo.dispose(), (this._lfo = null)), + this + ); + }), + i.Param + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1), + o = n(7), + r = n(3), + p = n(13); + (p5.Oscillator = function (t, e) { + if ("string" == typeof t) { + var n = e; + (e = t), (t = n); + } + if ("number" == typeof e) { + n = e; + (e = t), (t = n); + } + (this.started = !1), + (this.phaseAmount = void 0), + (this.oscillator = s.audiocontext.createOscillator()), + (this.f = t || 440), + (this.oscillator.type = e || "sine"), + this.oscillator.frequency.setValueAtTime( + this.f, + s.audiocontext.currentTime + ), + (this.output = s.audiocontext.createGain()), + (this._freqMods = []), + (this.output.gain.value = 0.5), + this.output.gain.setValueAtTime(0.5, s.audiocontext.currentTime), + this.oscillator.connect(this.output), + (this.panPosition = 0), + (this.connection = s.input), + (this.panner = new p5.Panner(this.output, this.connection, 1)), + (this.mathOps = [this.output]), + s.soundArray.push(this); + }), + (p5.Oscillator.prototype.start = function (t, e) { + if (this.started) { + var n = s.audiocontext.currentTime; + this.stop(n); + } + if (!this.started) { + var i = e || this.f, + o = this.oscillator.type; + for (var r in (this.oscillator && + (this.oscillator.disconnect(), delete this.oscillator), + (this.oscillator = s.audiocontext.createOscillator()), + (this.oscillator.frequency.value = Math.abs(i)), + (this.oscillator.type = o), + this.oscillator.connect(this.output), + (t = t || 0), + this.oscillator.start(t + s.audiocontext.currentTime), + (this.freqNode = this.oscillator.frequency), + this._freqMods)) + void 0 !== this._freqMods[r].connect && + this._freqMods[r].connect(this.oscillator.frequency); + this.started = !0; + } + }), + (p5.Oscillator.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), (this.started = !1); + } + }), + (p5.Oscillator.prototype.amp = function (t, e, n) { + if ("number" == typeof t) { + (e = e || 0), (n = n || 0); + var i = s.audiocontext.currentTime; + this.output.gain.linearRampToValueAtTime(t, i + n + e); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.Oscillator.prototype.fade = p5.Oscillator.prototype.amp), + (p5.Oscillator.prototype.getAmp = function () { + return this.output.gain.value; + }), + (p5.Oscillator.prototype.freq = function (t, e, n) { + if ("number" != typeof t || isNaN(t)) { + if (!t) return this.oscillator.frequency; + t.output && (t = t.output), + t.connect(this.oscillator.frequency), + this._freqMods.push(t); + } else { + this.f = t; + var i = s.audiocontext.currentTime; + (n = n || 0), (e = e || 0); + 0 === e + ? this.oscillator.frequency.setValueAtTime(t, n + i) + : 0 < t + ? this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ) + : this.oscillator.frequency.linearRampToValueAtTime( + t, + n + e + i + ), + this.phaseAmount && this.phase(this.phaseAmount); + } + }), + (p5.Oscillator.prototype.getFreq = function () { + return this.oscillator.frequency.value; + }), + (p5.Oscillator.prototype.setType = function (t) { + this.oscillator.type = t; + }), + (p5.Oscillator.prototype.getType = function () { + return this.oscillator.type; + }), + (p5.Oscillator.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? (this.panner.connect(t.input), (this.connection = t.input)) + : (this.panner.connect(t), (this.connection = t)) + : this.panner.connect(s.input); + }), + (p5.Oscillator.prototype.disconnect = function () { + this.output && this.output.disconnect(), + this.panner && + (this.panner.disconnect(), + this.output && this.output.connect(this.panner)), + (this.oscMods = []); + }), + (p5.Oscillator.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.Oscillator.prototype.getPan = function () { + return this.panPosition; + }), + (p5.Oscillator.prototype.dispose = function () { + var t = s.soundArray.indexOf(this); + if ((s.soundArray.splice(t, 1), this.oscillator)) { + var e = s.audiocontext.currentTime; + this.stop(e), + this.disconnect(), + (this.panner = null), + (this.oscillator = null); + } + this.osc2 && this.osc2.dispose(); + }), + (p5.Oscillator.prototype.phase = function (t) { + var e = p5.prototype.map(t, 0, 1, 0, 1 / this.f), + n = s.audiocontext.currentTime; + (this.phaseAmount = t), + this.dNode || + ((this.dNode = s.audiocontext.createDelay()), + this.oscillator.disconnect(), + this.oscillator.connect(this.dNode), + this.dNode.connect(this.output)), + this.dNode.delayTime.setValueAtTime(e, n); + }); + function c(t, e, n, i, o) { + var r = t.oscillator; + for (var s in t.mathOps) + t.mathOps[s] instanceof o && + (r.disconnect(), + t.mathOps[s].dispose(), + (n = s) < t.mathOps.length - 2 && (i = t.mathOps[s + 1])); + return ( + n === t.mathOps.length - 1 && t.mathOps.push(i), + 0 < s && (r = t.mathOps[s - 1]), + r.disconnect(), + r.connect(e), + e.connect(i), + (t.mathOps[n] = e), + t + ); + } + (p5.Oscillator.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, o); + }), + (p5.Oscillator.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length - 1, + i = this.output; + return c(this, e, n, i, r); + }), + (p5.Oscillator.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new p(o, r), + a = this.mathOps.length - 1, + u = this.output; + return c(this, s, a, u, p); + }), + (p5.SinOsc = function (t) { + p5.Oscillator.call(this, t, "sine"); + }), + (p5.SinOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.TriOsc = function (t) { + p5.Oscillator.call(this, t, "triangle"); + }), + (p5.TriOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SawOsc = function (t) { + p5.Oscillator.call(this, t, "sawtooth"); + }), + (p5.SawOsc.prototype = Object.create(p5.Oscillator.prototype)), + (p5.SqrOsc = function (t) { + p5.Oscillator.call(this, t, "square"); + }), + (p5.SqrOsc.prototype = Object.create(p5.Oscillator.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Timeline = function () { + var t = this.optionsObject( + arguments, + ["memory"], + e.Timeline.defaults + ); + (this._timeline = []), + (this._toRemove = []), + (this._iterating = !1), + (this.memory = t.memory); + }), + e.extend(e.Timeline), + (e.Timeline.defaults = { memory: 1 / 0 }), + Object.defineProperty(e.Timeline.prototype, "length", { + get: function () { + return this._timeline.length; + }, + }), + (e.Timeline.prototype.add = function (t) { + if (this.isUndef(t.time)) + throw new Error( + "Tone.Timeline: events must have a time attribute" + ); + if (this._timeline.length) { + var e = this._search(t.time); + this._timeline.splice(e + 1, 0, t); + } else this._timeline.push(t); + if (this.length > this.memory) { + var n = this.length - this.memory; + this._timeline.splice(0, n); + } + return this; + }), + (e.Timeline.prototype.remove = function (t) { + if (this._iterating) this._toRemove.push(t); + else { + var e = this._timeline.indexOf(t); + -1 !== e && this._timeline.splice(e, 1); + } + return this; + }), + (e.Timeline.prototype.get = function (t) { + var e = this._search(t); + return -1 !== e ? this._timeline[e] : null; + }), + (e.Timeline.prototype.peek = function () { + return this._timeline[0]; + }), + (e.Timeline.prototype.shift = function () { + return this._timeline.shift(); + }), + (e.Timeline.prototype.getAfter = function (t) { + var e = this._search(t); + return e + 1 < this._timeline.length + ? this._timeline[e + 1] + : null; + }), + (e.Timeline.prototype.getBefore = function (t) { + var e = this._timeline.length; + if (0 < e && this._timeline[e - 1].time < t) + return this._timeline[e - 1]; + var n = this._search(t); + return 0 <= n - 1 ? this._timeline[n - 1] : null; + }), + (e.Timeline.prototype.cancel = function (t) { + if (1 < this._timeline.length) { + var e = this._search(t); + if (0 <= e) + if (this._timeline[e].time === t) { + for (var n = e; 0 <= n && this._timeline[n].time === t; n--) + e = n; + this._timeline = this._timeline.slice(0, e); + } else this._timeline = this._timeline.slice(0, e + 1); + else this._timeline = []; + } else + 1 === this._timeline.length && + this._timeline[0].time >= t && + (this._timeline = []); + return this; + }), + (e.Timeline.prototype.cancelBefore = function (t) { + if (this._timeline.length) { + var e = this._search(t); + 0 <= e && (this._timeline = this._timeline.slice(e + 1)); + } + return this; + }), + (e.Timeline.prototype._search = function (t) { + var e = 0, + n = this._timeline.length, + i = n; + if (0 < n && this._timeline[n - 1].time <= t) return n - 1; + for (; e < i; ) { + var o = Math.floor(e + (i - e) / 2), + r = this._timeline[o], + s = this._timeline[o + 1]; + if (r.time === t) { + for (var a = o; a < this._timeline.length; a++) + this._timeline[a].time === t && (o = a); + return o; + } + if (r.time < t && s.time > t) return o; + r.time > t ? (i = o) : r.time < t && (e = o + 1); + } + return -1; + }), + (e.Timeline.prototype._iterate = function (t, e, n) { + (this._iterating = !0), + (e = this.defaultArg(e, 0)), + (n = this.defaultArg(n, this._timeline.length - 1)); + for (var i = e; i <= n; i++) t(this._timeline[i]); + if (((this._iterating = !1), 0 < this._toRemove.length)) { + for (var o = 0; o < this._toRemove.length; o++) { + var r = this._timeline.indexOf(this._toRemove[o]); + -1 !== r && this._timeline.splice(r, 1); + } + this._toRemove = []; + } + }), + (e.Timeline.prototype.forEach = function (t) { + return this._iterate(t), this; + }), + (e.Timeline.prototype.forEachBefore = function (t, e) { + var n = this._search(t); + return -1 !== n && this._iterate(e, 0, n), this; + }), + (e.Timeline.prototype.forEachAfter = function (t, e) { + var n = this._search(t); + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachFrom = function (t, e) { + for ( + var n = this._search(t); + 0 <= n && this._timeline[n].time >= t; + + ) + n--; + return this._iterate(e, n + 1), this; + }), + (e.Timeline.prototype.forEachAtTime = function (e, n) { + var t = this._search(e); + return ( + -1 !== t && + this._iterate( + function (t) { + t.time === e && n(t); + }, + 0, + t + ), + this + ); + }), + (e.Timeline.prototype.dispose = function () { + e.prototype.dispose.call(this), + (this._timeline = null), + (this._toRemove = null); + }), + e.Timeline + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(3), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Negate = function () { + this._multiply = this.input = this.output = new t.Multiply(-1); + }), + t.extend(t.Negate, t.SignalBase), + (t.Negate.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._multiply.dispose(), + (this._multiply = null), + this + ); + }), + t.Negate + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(3), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.GreaterThanZero = function () { + (this._thresh = this.output = + new t.WaveShaper(function (t) { + return t <= 0 ? 0 : 1; + }, 127)), + (this._scale = this.input = new t.Multiply(1e4)), + this._scale.connect(this._thresh); + }), + t.extend(t.GreaterThanZero, t.SignalBase), + (t.GreaterThanZero.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._scale.dispose(), + (this._scale = null), + this._thresh.dispose(), + (this._thresh = null), + this + ); + }), + t.GreaterThanZero + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(14), n(66), n(18), n(12)]), + void 0 === + (o = function (o) { + "use strict"; + return ( + (o.Clock = function () { + o.Emitter.call(this); + var t = this.optionsObject( + arguments, + ["callback", "frequency"], + o.Clock.defaults + ); + (this.callback = t.callback), + (this._nextTick = 0), + (this._lastState = o.State.Stopped), + (this.frequency = new o.TimelineSignal( + t.frequency, + o.Type.Frequency + )), + this._readOnly("frequency"), + (this.ticks = 0), + (this._state = new o.TimelineState(o.State.Stopped)), + (this._boundLoop = this._loop.bind(this)), + this.context.on("tick", this._boundLoop); + }), + o.extend(o.Clock, o.Emitter), + (o.Clock.defaults = { + callback: o.noOp, + frequency: 1, + lookAhead: "auto", + }), + Object.defineProperty(o.Clock.prototype, "state", { + get: function () { + return this._state.getValueAtTime(this.now()); + }, + }), + (o.Clock.prototype.start = function (t, e) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) !== o.State.Started && + this._state.add({ + state: o.State.Started, + time: t, + offset: e, + }), + this + ); + }), + (o.Clock.prototype.stop = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.cancel(t), + this._state.setStateAtTime(o.State.Stopped, t), + this + ); + }), + (o.Clock.prototype.pause = function (t) { + return ( + (t = this.toSeconds(t)), + this._state.getValueAtTime(t) === o.State.Started && + this._state.setStateAtTime(o.State.Paused, t), + this + ); + }), + (o.Clock.prototype._loop = function () { + for ( + var t = + this.now() + + this.context.lookAhead + + this.context.updateInterval + + 2 * this.context.lag; + t > this._nextTick && this._state; + + ) { + var e = this._state.getValueAtTime(this._nextTick); + if (e !== this._lastState) { + this._lastState = e; + var n = this._state.get(this._nextTick); + e === o.State.Started + ? ((this._nextTick = n.time), + this.isUndef(n.offset) || (this.ticks = n.offset), + this.emit("start", n.time, this.ticks)) + : e === o.State.Stopped + ? ((this.ticks = 0), this.emit("stop", n.time)) + : e === o.State.Paused && this.emit("pause", n.time); + } + var i = this._nextTick; + this.frequency && + ((this._nextTick += + 1 / this.frequency.getValueAtTime(this._nextTick)), + e === o.State.Started && (this.callback(i), this.ticks++)); + } + }), + (o.Clock.prototype.getStateAtTime = function (t) { + return (t = this.toSeconds(t)), this._state.getValueAtTime(t); + }), + (o.Clock.prototype.dispose = function () { + o.Emitter.prototype.dispose.call(this), + this.context.off("tick", this._boundLoop), + this._writable("frequency"), + this.frequency.dispose(), + (this.frequency = null), + (this._boundLoop = null), + (this._nextTick = 1 / 0), + (this.callback = null), + this._state.dispose(), + (this._state = null); + }), + o.Clock + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = i(1), + e = i(29), + r = i(6).noteToFreq; + (p5.MonoSynth = function () { + e.call(this), + (this.oscillator = new p5.Oscillator()), + (this.env = new p5.Envelope()), + this.env.setRange(1, 0), + this.env.setExp(!0), + this.setADSR(0.02, 0.25, 0.05, 0.35), + this.oscillator.disconnect(), + this.oscillator.connect(this.output), + this.env.disconnect(), + this.env.setInput(this.output.gain), + (this.oscillator.output.gain.value = 1), + this.oscillator.start(), + this.connect(), + n.soundArray.push(this); + }), + (p5.MonoSynth.prototype = Object.create(p5.AudioVoice.prototype)), + (p5.MonoSynth.prototype.play = function (t, e, n, i) { + this.triggerAttack(t, e, ~~n), + this.triggerRelease(~~n + (i || 0.15)); + }), + (p5.MonoSynth.prototype.triggerAttack = function (t, e, n) { + n = ~~n; + var i = r(t), + o = e || 0.1; + this.oscillator.freq(i, 0, n), + this.env.ramp(this.output.gain, n, o); + }), + (p5.MonoSynth.prototype.triggerRelease = function (t) { + t = t || 0; + this.env.ramp(this.output.gain, t, 0); + }), + (p5.MonoSynth.prototype.setADSR = function (t, e, n, i) { + this.env.setADSR(t, e, n, i); + }), + Object.defineProperties(p5.MonoSynth.prototype, { + attack: { + get: function () { + return this.env.aTime; + }, + set: function (t) { + this.env.setADSR( + t, + this.env.dTime, + this.env.sPercent, + this.env.rTime + ); + }, + }, + decay: { + get: function () { + return this.env.dTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + t, + this.env.sPercent, + this.env.rTime + ); + }, + }, + sustain: { + get: function () { + return this.env.sPercent; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + t, + this.env.rTime + ); + }, + }, + release: { + get: function () { + return this.env.rTime; + }, + set: function (t) { + this.env.setADSR( + this.env.aTime, + this.env.dTime, + this.env.sPercent, + t + ); + }, + }, + }), + (p5.MonoSynth.prototype.amp = function (t, e) { + var n = e || 0; + return ( + void 0 !== t && this.oscillator.amp(t, n), + this.oscillator.amp().value + ); + }), + (p5.MonoSynth.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.MonoSynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.MonoSynth.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.env && this.env.dispose(), + this.oscillator && this.oscillator.dispose(); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function () { + var n = i(1); + return ( + (p5.AudioVoice = function () { + (this.ac = n.audiocontext), + (this.output = this.ac.createGain()), + this.connect(), + n.soundArray.push(this); + }), + (p5.AudioVoice.prototype.play = function (t, e, n, i) {}), + (p5.AudioVoice.prototype.triggerAttack = function (t, e, n) {}), + (p5.AudioVoice.prototype.triggerRelease = function (t) {}), + (p5.AudioVoice.prototype.amp = function (t, e) {}), + (p5.AudioVoice.prototype.connect = function (t) { + var e = t || n.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.AudioVoice.prototype.disconnect = function () { + this.output.disconnect(); + }), + (p5.AudioVoice.prototype.dispose = function () { + this.output && (this.output.disconnect(), delete this.output); + }), + p5.AudioVoice + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var c = n(1), + h = n(14), + l = n(6).noteToFreq; + (p5.PolySynth = function (t, e) { + (this.audiovoices = []), + (this.notes = {}), + (this._newest = 0), + (this._oldest = 0), + (this.maxVoices = e || 8), + (this.AudioVoice = void 0 === t ? p5.MonoSynth : t), + (this._voicesInUse = new h(0)), + (this.output = c.audiocontext.createGain()), + this.connect(), + this._allocateVoices(), + c.soundArray.push(this); + }), + (p5.PolySynth.prototype._allocateVoices = function () { + for (var t = 0; t < this.maxVoices; t++) + this.audiovoices.push(new this.AudioVoice()), + this.audiovoices[t].disconnect(), + this.audiovoices[t].connect(this.output); + }), + (p5.PolySynth.prototype.play = function (t, e, n, i) { + i = i || 1; + this.noteAttack(t, e, n), this.noteRelease(t, n + i); + }), + (p5.PolySynth.prototype.noteADSR = function (t, e, n, i, o, r) { + var s = c.audiocontext.currentTime + (r = r || 0); + this.audiovoices[this.notes[t].getValueAtTime(s)].setADSR( + e, + n, + i, + o + ); + }), + (p5.PolySynth.prototype.setADSR = function (e, n, i, o) { + this.audiovoices.forEach(function (t) { + t.setADSR(e, n, i, o); + }); + }), + (p5.PolySynth.prototype.noteAttack = function (t, e, n) { + n = ~~n; + var i, + o = c.audiocontext.currentTime + n, + r = l(t), + s = e || 0.1; + if ( + (this.notes[r] && + null !== this.notes[r].getValueAtTime(o) && + this.noteRelease(r, 0), + this._voicesInUse.getValueAtTime(o) < this.maxVoices) + ) + i = Math.max(~~this._voicesInUse.getValueAtTime(o), 0); + else { + i = this._oldest; + var a = p5.prototype.freqToMidi( + this.audiovoices[this._oldest].oscillator.freq().value + ); + this.noteRelease(a), + (this._oldest = (this._oldest + 1) % (this.maxVoices - 1)); + } + (this.notes[r] = new h()), this.notes[r].setValueAtTime(i, o); + var u = + null === this._voicesInUse._searchBefore(o) + ? 0 + : this._voicesInUse._searchBefore(o).value; + if ( + (this._voicesInUse.setValueAtTime(u + 1, o), + this._updateAfter(o, 1), + (this._newest = i), + "number" == typeof s) + ) { + var p = (1 / this._voicesInUse.getValueAtTime(o)) * 2; + s = p < s ? p : s; + } + this.audiovoices[i].triggerAttack(r, s, n); + }), + (p5.PolySynth.prototype._updateAfter = function (t, e) { + if (null !== this._voicesInUse._searchAfter(t)) { + this._voicesInUse._searchAfter(t).value += e; + var n = this._voicesInUse._searchAfter(t).time; + this._updateAfter(n, e); + } + }), + (p5.PolySynth.prototype.noteRelease = function (t, e) { + var n = c.audiocontext.currentTime, + i = e || 0, + o = n + i; + if (t) { + var r = l(t); + if (this.notes[r] && null !== this.notes[r].getValueAtTime(o)) { + var s = Math.max( + ~~this._voicesInUse.getValueAtTime(o).value, + 1 + ); + this._voicesInUse.setValueAtTime(s - 1, o), + 0 < s && this._updateAfter(o, -1), + this.audiovoices[ + this.notes[r].getValueAtTime(o) + ].triggerRelease(i), + this.notes[r].dispose(), + delete this.notes[r], + (this._newest = + 0 === this._newest + ? 0 + : (this._newest - 1) % (this.maxVoices - 1)); + } else; + } else + for (var a in (this.audiovoices.forEach(function (t) { + t.triggerRelease(i); + }), + this._voicesInUse.setValueAtTime(0, o), + this.notes)) + this.notes[a].dispose(), delete this.notes[a]; + }), + (p5.PolySynth.prototype.connect = function (t) { + var e = t || c.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.PolySynth.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.PolySynth.prototype.dispose = function () { + this.audiovoices.forEach(function (t) { + t.dispose(); + }), + this.output && (this.output.disconnect(), delete this.output); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(32), n(33), n(17); + var e = n(1); + return ( + n(6), + n(11), + n(36), + n(40), + n(41), + n(42), + n(43), + n(44), + n(23), + n(47), + n(48), + n(49), + n(50), + n(15), + n(59), + n(61), + n(62), + n(63), + n(64), + n(65), + n(67), + n(68), + n(69), + n(70), + n(71), + n(72), + n(28), + n(30), + n(73), + n(29), + n(28), + n(30), + e + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + function c(t) { + var i = this, + o = {}, + r = -1; + this.parameters.forEach(function (t, e) { + var n = a[++r] || (a[r] = new Float32Array(i.bufferSize)); + n.fill(t.value), (o[e] = n); + }), + this.processor.realm.exec( + "self.sampleRate=sampleRate=" + + this.context.sampleRate + + ";self.currentTime=currentTime=" + + this.context.currentTime + ); + var e = s(t.inputBuffer), + n = s(t.outputBuffer); + this.instance.process([e], [n], o); + } + function s(t) { + for (var e = [], n = 0; n < t.numberOfChannels; n++) + e[n] = t.getChannelData(n); + return e; + } + function h(t) { + return t.$$processors || (t.$$processors = {}); + } + function n(t) { + this.$$context = t; + } + var l, a; + (a = []), + "function" != typeof AudioWorkletNode && + ((self.AudioWorkletNode = function (t, e, n) { + var i = h(t)[e], + o = t.createScriptProcessor( + void 0, + 2, + n && n.outputChannelCount ? n.outputChannelCount[0] : 2 + ); + if (((o.parameters = new Map()), i.properties)) + for (var r = 0; r < i.properties.length; r++) { + var s = i.properties[r], + a = t.createGain().gain; + (a.value = s.defaultValue), o.parameters.set(s.name, a); + } + var u = new MessageChannel(); + l = u.port2; + var p = new i.Processor(n || {}); + return ( + (l = null), + (o.port = u.port1), + (o.processor = i), + (o.instance = p), + (o.onaudioprocess = c), + o + ); + }), + Object.defineProperty( + (self.AudioContext || self.webkitAudioContext).prototype, + "audioWorklet", + { + get: function () { + return ( + this.$$audioWorklet || + (this.$$audioWorklet = new self.AudioWorklet(this)) + ); + }, + } + ), + (self.AudioWorklet = + ((n.prototype.addModule = function (t, e) { + var o = this; + return fetch(t) + .then(function (t) { + if (!t.ok) throw Error(t.status); + return t.text(); + }) + .then(function (t) { + var n = { + sampleRate: 0, + currentTime: 0, + AudioWorkletProcessor: function () { + this.port = l; + }, + registerProcessor: function (t, e) { + h(o.$$context)[t] = { + realm: i, + context: n, + Processor: e, + properties: e.parameterDescriptors || [], + }; + }, + }, + i = new (function (t, e) { + var n = document.createElement("iframe"); + (n.style.cssText = + "position:absolute;left:0;top:-999px;width:1px;height:1px;"), + e.appendChild(n); + var i = n.contentWindow, + o = i.document, + r = "var window,$hook"; + for (var s in i) + s in t || "eval" === s || ((r += ","), (r += s)); + for (var a in t) + (r += ","), (r += a), (r += "=self."), (r += a); + var u = o.createElement("script"); + u.appendChild( + o.createTextNode( + 'function $hook(self,console) {"use strict";\n ' + + r + + ";return function() {return eval(arguments[0])}}" + ) + ), + o.body.appendChild(u), + (this.exec = i.$hook(t, console)); + })((n.self = n), document.documentElement); + return i.exec(((e && e.transpile) || String)(t)), null; + }); + }), + n))); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + function n(t) { + t && + (t.setTargetAtTime || (t.setTargetAtTime = t.setTargetValueAtTime)); + } + window, + window.hasOwnProperty("webkitAudioContext") && + !window.hasOwnProperty("AudioContext") && + ((window.AudioContext = window.webkitAudioContext), + "function" != typeof AudioContext.prototype.createGain && + (AudioContext.prototype.createGain = + AudioContext.prototype.createGainNode), + "function" != typeof AudioContext.prototype.createDelay && + (AudioContext.prototype.createDelay = + AudioContext.prototype.createDelayNode), + "function" != typeof AudioContext.prototype.createScriptProcessor && + (AudioContext.prototype.createScriptProcessor = + AudioContext.prototype.createJavaScriptNode), + "function" != typeof AudioContext.prototype.createPeriodicWave && + (AudioContext.prototype.createPeriodicWave = + AudioContext.prototype.createWaveTable), + (AudioContext.prototype.internal_createGain = + AudioContext.prototype.createGain), + (AudioContext.prototype.createGain = function () { + var t = this.internal_createGain(); + return n(t.gain), t; + }), + (AudioContext.prototype.internal_createDelay = + AudioContext.prototype.createDelay), + (AudioContext.prototype.createDelay = function (t) { + var e = t + ? this.internal_createDelay(t) + : this.internal_createDelay(); + return n(e.delayTime), e; + }), + (AudioContext.prototype.internal_createBufferSource = + AudioContext.prototype.createBufferSource), + (AudioContext.prototype.createBufferSource = function () { + var i = this.internal_createBufferSource(); + return ( + i.start + ? ((i.internal_start = i.start), + (i.start = function (t, e, n) { + void 0 !== n + ? i.internal_start(t || 0, e, n) + : i.internal_start(t || 0, e || 0); + })) + : (i.start = function (t, e, n) { + e || n + ? this.noteGrainOn(t || 0, e, n) + : this.noteOn(t || 0); + }), + i.stop + ? ((i.internal_stop = i.stop), + (i.stop = function (t) { + i.internal_stop(t || 0); + })) + : (i.stop = function (t) { + this.noteOff(t || 0); + }), + n(i.playbackRate), + i + ); + }), + (AudioContext.prototype.internal_createDynamicsCompressor = + AudioContext.prototype.createDynamicsCompressor), + (AudioContext.prototype.createDynamicsCompressor = function () { + var t = this.internal_createDynamicsCompressor(); + return ( + n(t.threshold), + n(t.knee), + n(t.ratio), + n(t.reduction), + n(t.attack), + n(t.release), + t + ); + }), + (AudioContext.prototype.internal_createBiquadFilter = + AudioContext.prototype.createBiquadFilter), + (AudioContext.prototype.createBiquadFilter = function () { + var t = this.internal_createBiquadFilter(); + return n(t.frequency), n(t.detune), n(t.Q), n(t.gain), t; + }), + "function" != typeof AudioContext.prototype.createOscillator && + ((AudioContext.prototype.internal_createOscillator = + AudioContext.prototype.createOscillator), + (AudioContext.prototype.createOscillator = function () { + var e = this.internal_createOscillator(); + return ( + e.start + ? ((e.internal_start = e.start), + (e.start = function (t) { + e.internal_start(t || 0); + })) + : (e.start = function (t) { + this.noteOn(t || 0); + }), + e.stop + ? ((e.internal_stop = e.stop), + (e.stop = function (t) { + e.internal_stop(t || 0); + })) + : (e.stop = function (t) { + this.noteOff(t || 0); + }), + e.setPeriodicWave || (e.setPeriodicWave = e.setWaveTable), + n(e.frequency), + n(e.detune), + e + ); + }))), + window.hasOwnProperty("webkitOfflineAudioContext") && + !window.hasOwnProperty("OfflineAudioContext") && + (window.OfflineAudioContext = window.webkitOfflineAudioContext), + (navigator.getUserMedia = + navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia); + var e = document.createElement("audio"); + p5.prototype.isSupported = function () { + return !!e.canPlayType; + }; + p5.prototype.isFileSupported = function (t) { + switch (t.toLowerCase()) { + case "mp3": + return !!e.canPlayType && e.canPlayType("audio/mpeg;"); + case "wav": + return !!e.canPlayType && e.canPlayType('audio/wav; codecs="1"'); + case "ogg": + return ( + !!e.canPlayType && e.canPlayType('audio/ogg; codecs="vorbis"') + ); + case "aac": + case "m4a": + case "mp4": + return ( + !!e.canPlayType && + (e.canPlayType("audio/x-m4a;") || e.canPlayType("audio/aac;")) + ); + case "aif": + case "aiff": + return !!e.canPlayType && e.canPlayType("audio/x-aiff;"); + default: + return !1; + } + }; + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e) { + var n; + n = (function () { + return this; + })(); + try { + n = n || new Function("return this")(); + } catch (t) { + "object" == typeof window && (n = window); + } + t.exports = n; + }, + function (t, e, n) { + var i, o, r; + (o = []), + void 0 === + (r = + "function" == + typeof (i = function () { + var s = function (t, e) { + (this._dragged = !1), + (this._element = t), + (this._bindedMove = this._moved.bind(this)), + (this._bindedEnd = this._ended.bind(this, e)), + t.addEventListener("touchstart", this._bindedEnd), + t.addEventListener("touchmove", this._bindedMove), + t.addEventListener("touchend", this._bindedEnd), + t.addEventListener("mouseup", this._bindedEnd); + }; + function r(t) { + return "running" === t.state; + } + return ( + (s.prototype._moved = function (t) { + this._dragged = !0; + }), + (s.prototype._ended = function (t) { + this._dragged || + (function (t) { + var e = t.createBuffer(1, 1, t.sampleRate), + n = t.createBufferSource(); + (n.buffer = e), + n.connect(t.destination), + n.start(0), + t.resume && t.resume(); + })(t), + (this._dragged = !1); + }), + (s.prototype.dispose = function () { + this._element.removeEventListener( + "touchstart", + this._bindedEnd + ), + this._element.removeEventListener( + "touchmove", + this._bindedMove + ), + this._element.removeEventListener( + "touchend", + this._bindedEnd + ), + this._element.removeEventListener("mouseup", this._bindedEnd), + (this._bindedMove = null), + (this._bindedEnd = null), + (this._element = null); + }), + function (e, t, n) { + var i = new Promise(function (t) { + !(function (e, n) { + r(e) + ? n() + : (function t() { + r(e) + ? n() + : (requestAnimationFrame(t), + e.resume && e.resume()); + })(); + })(e, t); + }), + o = []; + return ( + (function t(e, n, i) { + if (Array.isArray(e) || (NodeList && e instanceof NodeList)) + for (var o = 0; o < e.length; o++) t(e[o], n, i); + else if ("string" == typeof e) + t(document.querySelectorAll(e), n, i); + else if (e.jquery && "function" == typeof e.toArray) + t(e.toArray(), n, i); + else if (Element && e instanceof Element) { + var r = new s(e, i); + n.push(r); + } + })((t = t || document.body), o, e), + i.then(function () { + for (var t = 0; t < o.length; t++) o[t].dispose(); + (o = null), n && n(); + }), + i + ); + } + ); + }) + ? i.apply(e, o) + : i) || (t.exports = r); + }, + function (t, e, n) { + var i = n(1), + o = [n(37).default, n(38).default, n(39).default], + r = i.audiocontext, + s = !1; + p5.prototype.registerMethod("init", function () { + if (!s) { + this.preload || window.preload || (this.preload = function () {}), + this._incrementPreload(); + var t = function () { + (s = !0), this._decrementPreload(); + }.bind(this); + Promise.all( + o.map(function (t) { + var e = new Blob([t], { type: "application/javascript" }), + n = URL.createObjectURL(e); + return r.audioWorklet.addModule(n); + }) + ).then(t); + } + }); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar RecorderProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(RecorderProcessor, _AudioWorkletProcesso);\n\n function RecorderProcessor(options) {\n var _this;\n\n _classCallCheck(this, RecorderProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(RecorderProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 2;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.bufferSize = processorOptions.bufferSize || 1024;\n _this.recording = false;\n\n _this.clear();\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'start\') {\n _this.record(data.duration);\n } else if (data.name === \'stop\') {\n _this.stop();\n }\n };\n\n return _this;\n }\n\n _createClass(RecorderProcessor, [{\n key: "process",\n value: function process(inputs) {\n if (!this.recording) {\n return true;\n } else if (this.sampleLimit && this.recordedSamples >= this.sampleLimit) {\n this.stop();\n return true;\n }\n\n var input = inputs[0];\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numOutputChannels; ++channel) {\n var inputChannelCopy = this.inputRingBufferArraySequence[channel].slice();\n\n if (channel === 0) {\n this.leftBuffers.push(inputChannelCopy);\n\n if (this.numInputChannels === 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n } else if (channel === 1 && this.numInputChannels > 1) {\n this.rightBuffers.push(inputChannelCopy);\n }\n }\n\n this.recordedSamples += this.bufferSize;\n }\n\n return true;\n }\n }, {\n key: "record",\n value: function record(duration) {\n if (duration) {\n this.sampleLimit = Math.round(duration * sampleRate);\n }\n\n this.recording = true;\n }\n }, {\n key: "stop",\n value: function stop() {\n this.recording = false;\n var buffers = this.getBuffers();\n var leftBuffer = buffers[0].buffer;\n var rightBuffer = buffers[1].buffer;\n this.port.postMessage({\n name: \'buffers\',\n leftBuffer: leftBuffer,\n rightBuffer: rightBuffer\n }, [leftBuffer, rightBuffer]);\n this.clear();\n }\n }, {\n key: "getBuffers",\n value: function getBuffers() {\n var buffers = [];\n buffers.push(this.mergeBuffers(this.leftBuffers));\n buffers.push(this.mergeBuffers(this.rightBuffers));\n return buffers;\n }\n }, {\n key: "mergeBuffers",\n value: function mergeBuffers(channelBuffer) {\n var result = new Float32Array(this.recordedSamples);\n var offset = 0;\n var lng = channelBuffer.length;\n\n for (var i = 0; i < lng; i++) {\n var buffer = channelBuffer[i];\n result.set(buffer, offset);\n offset += buffer.length;\n }\n\n return result;\n }\n }, {\n key: "clear",\n value: function clear() {\n var _this2 = this;\n\n this.leftBuffers = [];\n this.rightBuffers = [];\n this.inputRingBuffer = new RingBuffer(this.bufferSize, this.numInputChannels);\n this.inputRingBufferArraySequence = new Array(this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this2.bufferSize);\n });\n this.recordedSamples = 0;\n this.sampleLimit = null;\n }\n }]);\n\n return RecorderProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.recorderProcessor, RecorderProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar SoundFileProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(SoundFileProcessor, _AudioWorkletProcesso);\n\n function SoundFileProcessor(options) {\n var _this;\n\n _classCallCheck(this, SoundFileProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(SoundFileProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.bufferSize = processorOptions.bufferSize || 256;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, 1);\n _this.inputRingBufferArraySequence = [new Float32Array(_this.bufferSize)];\n return _this;\n }\n\n _createClass(SoundFileProcessor, [{\n key: "process",\n value: function process(inputs) {\n var input = inputs[0]; // we only care about the first input channel, because that contains the position data\n\n this.inputRingBuffer.push([input[0]]);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n var inputChannel = this.inputRingBufferArraySequence[0];\n var position = inputChannel[inputChannel.length - 1] || 0;\n this.port.postMessage({\n name: \'position\',\n position: position\n });\n }\n\n return true;\n }\n }]);\n\n return SoundFileProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.soundFileProcessor, SoundFileProcessor);'); + }, + function (t, e, n) { + "use strict"; + n.r(e), + (e.default = + 'function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// import dependencies via preval.require so that they\'re available as values at compile time\nvar processorNames = {\n "recorderProcessor": "recorder-processor",\n "soundFileProcessor": "sound-file-processor",\n "amplitudeProcessor": "amplitude-processor"\n};\nvar RingBuffer = {\n "default":\n /*#__PURE__*/\n function () {\n /**\n * @constructor\n * @param {number} length Buffer length in frames.\n * @param {number} channelCount Buffer channel count.\n */\n function RingBuffer(length, channelCount) {\n _classCallCheck(this, RingBuffer);\n\n this._readIndex = 0;\n this._writeIndex = 0;\n this._framesAvailable = 0;\n this._channelCount = channelCount;\n this._length = length;\n this._channelData = [];\n\n for (var i = 0; i < this._channelCount; ++i) {\n this._channelData[i] = new Float32Array(length);\n }\n }\n /**\n * Getter for Available frames in buffer.\n *\n * @return {number} Available frames in buffer.\n */\n\n\n _createClass(RingBuffer, [{\n key: "push",\n\n /**\n * Push a sequence of Float32Arrays to buffer.\n *\n * @param {array} arraySequence A sequence of Float32Arrays.\n */\n value: function push(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // Transfer data from the |arraySequence| storage to the internal buffer.\n var sourceLength = arraySequence[0].length;\n\n for (var i = 0; i < sourceLength; ++i) {\n var writeIndex = (this._writeIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n this._channelData[channel][writeIndex] = arraySequence[channel][i];\n }\n }\n\n this._writeIndex += sourceLength;\n\n if (this._writeIndex >= this._length) {\n this._writeIndex = 0;\n } // For excessive frames, the buffer will be overwritten.\n\n\n this._framesAvailable += sourceLength;\n\n if (this._framesAvailable > this._length) {\n this._framesAvailable = this._length;\n }\n }\n /**\n * Pull data out of buffer and fill a given sequence of Float32Arrays.\n *\n * @param {array} arraySequence An array of Float32Arrays.\n */\n\n }, {\n key: "pull",\n value: function pull(arraySequence) {\n // The channel count of arraySequence and the length of each channel must\n // match with this buffer obejct.\n // If the FIFO is completely empty, do nothing.\n if (this._framesAvailable === 0) {\n return;\n }\n\n var destinationLength = arraySequence[0].length; // Transfer data from the internal buffer to the |arraySequence| storage.\n\n for (var i = 0; i < destinationLength; ++i) {\n var readIndex = (this._readIndex + i) % this._length;\n\n for (var channel = 0; channel < this._channelCount; ++channel) {\n arraySequence[channel][i] = this._channelData[channel][readIndex];\n }\n }\n\n this._readIndex += destinationLength;\n\n if (this._readIndex >= this._length) {\n this._readIndex = 0;\n }\n\n this._framesAvailable -= destinationLength;\n\n if (this._framesAvailable < 0) {\n this._framesAvailable = 0;\n }\n }\n }, {\n key: "framesAvailable",\n get: function get() {\n return this._framesAvailable;\n }\n }]);\n\n return RingBuffer;\n }()\n}["default"];\n\nvar AmplitudeProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(AmplitudeProcessor, _AudioWorkletProcesso);\n\n function AmplitudeProcessor(options) {\n var _this;\n\n _classCallCheck(this, AmplitudeProcessor);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(AmplitudeProcessor).call(this));\n var processorOptions = options.processorOptions || {};\n _this.numOutputChannels = options.outputChannelCount || 1;\n _this.numInputChannels = processorOptions.numInputChannels || 2;\n _this.normalize = processorOptions.normalize || false;\n _this.smoothing = processorOptions.smoothing || 0;\n _this.bufferSize = processorOptions.bufferSize || 2048;\n _this.inputRingBuffer = new RingBuffer(_this.bufferSize, _this.numInputChannels);\n _this.outputRingBuffer = new RingBuffer(_this.bufferSize, _this.numOutputChannels);\n _this.inputRingBufferArraySequence = new Array(_this.numInputChannels).fill(null).map(function () {\n return new Float32Array(_this.bufferSize);\n });\n _this.stereoVol = [0, 0];\n _this.stereoVolNorm = [0, 0];\n _this.volMax = 0.001;\n\n _this.port.onmessage = function (event) {\n var data = event.data;\n\n if (data.name === \'toggleNormalize\') {\n _this.normalize = data.normalize;\n } else if (data.name === \'smoothing\') {\n _this.smoothing = Math.max(0, Math.min(1, data.smoothing));\n }\n };\n\n return _this;\n } // TO DO make this stereo / dependent on # of audio channels\n\n\n _createClass(AmplitudeProcessor, [{\n key: "process",\n value: function process(inputs, outputs) {\n var input = inputs[0];\n var output = outputs[0];\n var smoothing = this.smoothing;\n this.inputRingBuffer.push(input);\n\n if (this.inputRingBuffer.framesAvailable >= this.bufferSize) {\n this.inputRingBuffer.pull(this.inputRingBufferArraySequence);\n\n for (var channel = 0; channel < this.numInputChannels; ++channel) {\n var inputBuffer = this.inputRingBufferArraySequence[channel];\n var bufLength = inputBuffer.length;\n var sum = 0;\n\n for (var i = 0; i < bufLength; i++) {\n var x = inputBuffer[i];\n\n if (this.normalize) {\n sum += Math.max(Math.min(x / this.volMax, 1), -1) * Math.max(Math.min(x / this.volMax, 1), -1);\n } else {\n sum += x * x;\n }\n } // ... then take the square root of the sum.\n\n\n var rms = Math.sqrt(sum / bufLength);\n this.stereoVol[channel] = Math.max(rms, this.stereoVol[channel] * smoothing);\n this.volMax = Math.max(this.stereoVol[channel], this.volMax);\n } // calculate stero normalized volume and add volume from all channels together\n\n\n var volSum = 0;\n\n for (var index = 0; index < this.stereoVol.length; index++) {\n this.stereoVolNorm[index] = Math.max(Math.min(this.stereoVol[index] / this.volMax, 1), 0);\n volSum += this.stereoVol[index];\n } // volume is average of channels\n\n\n var volume = volSum / this.stereoVol.length; // normalized value\n\n var volNorm = Math.max(Math.min(volume / this.volMax, 1), 0);\n this.port.postMessage({\n name: \'amplitude\',\n volume: volume,\n volNorm: volNorm,\n stereoVol: this.stereoVol,\n stereoVolNorm: this.stereoVolNorm\n }); // pass input through to output\n\n this.outputRingBuffer.push(this.inputRingBufferArraySequence);\n } // pull 128 frames out of the ring buffer\n // if the ring buffer does not have enough frames, the output will be silent\n\n\n this.outputRingBuffer.pull(output);\n return true;\n }\n }]);\n\n return AmplitudeProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(processorNames.amplitudeProcessor, AmplitudeProcessor);'); + }, + function (t, e, n) { + "use strict"; + var i; + function o(t) { + return (o = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (i = function (t) { + var a = n(1).audiocontext; + void 0 !== a.createStereoPanner + ? ((p5.Panner = function (t, e) { + (this.stereoPanner = this.input = a.createStereoPanner()), + t.connect(this.stereoPanner), + this.stereoPanner.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n; + this.stereoPanner.pan.linearRampToValueAtTime(t, i); + }), + (p5.Panner.prototype.inputChannels = function () {}), + (p5.Panner.prototype.connect = function (t) { + this.stereoPanner.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.stereoPanner && this.stereoPanner.disconnect(); + })) + : ((p5.Panner = function (t, e, n) { + (this.input = a.createGain()), + t.connect(this.input), + (this.left = a.createGain()), + (this.right = a.createGain()), + (this.left.channelInterpretation = "discrete"), + (this.right.channelInterpretation = "discrete"), + 1 < n + ? ((this.splitter = a.createChannelSplitter(2)), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)) + : (this.input.connect(this.left), + this.input.connect(this.right)), + (this.output = a.createChannelMerger(2)), + this.left.connect(this.output, 0, 1), + this.right.connect(this.output, 0, 0), + this.output.connect(e); + }), + (p5.Panner.prototype.pan = function (t, e) { + var n = e || 0, + i = a.currentTime + n, + o = (t + 1) / 2, + r = Math.cos((o * Math.PI) / 2), + s = Math.sin((o * Math.PI) / 2); + this.left.gain.linearRampToValueAtTime(s, i), + this.right.gain.linearRampToValueAtTime(r, i); + }), + (p5.Panner.prototype.inputChannels = function (t) { + 1 === t + ? (this.input.disconnect(), + this.input.connect(this.left), + this.input.connect(this.right)) + : 2 === t && + (o("undefined" === this.splitter) && + (this.splitter = a.createChannelSplitter(2)), + this.input.disconnect(), + this.input.connect(this.splitter), + this.splitter.connect(this.left, 1), + this.splitter.connect(this.right, 0)); + }), + (p5.Panner.prototype.connect = function (t) { + this.output.connect(t); + }), + (p5.Panner.prototype.disconnect = function () { + this.output && this.output.disconnect(); + })); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, o) { + "use strict"; + var n; + function l(t) { + return (l = + "function" == typeof Symbol && "symbol" == typeof Symbol.iterator + ? function (t) { + return typeof t; + } + : function (t) { + return t && + "function" == typeof Symbol && + t.constructor === Symbol && + t !== Symbol.prototype + ? "symbol" + : typeof t; + })(t); + } + void 0 === + (n = function (t) { + var a = o(11), + u = o(1), + p = u.audiocontext, + e = o(6), + n = e.midiToFreq, + i = e.convertToWav, + r = e.safeBufferSize, + s = o(10); + (p5.SoundFile = function (t, e, n, i) { + if (void 0 !== t) { + if ("string" == typeof t || "string" == typeof t[0]) { + var o = p5.prototype._checkFileFormats(t); + this.url = o; + } else if ( + "object" === l(t) && + !( + window.File && + window.FileReader && + window.FileList && + window.Blob + ) + ) + throw "Unable to load file because the File API is not supported"; + t.file && (t = t.file), (this.file = t); + } + (this._onended = function () {}), + (this._looping = !1), + (this._playing = !1), + (this._paused = !1), + (this._pauseTime = 0), + (this._cues = []), + (this._cueIDCounter = 0), + (this._lastPos = 0), + (this._counterNode = null), + (this._workletNode = null), + (this.bufferSourceNodes = []), + (this.bufferSourceNode = null), + (this.buffer = null), + (this.playbackRate = 1), + (this.input = u.audiocontext.createGain()), + (this.output = u.audiocontext.createGain()), + (this.reversed = !1), + (this.startTime = 0), + (this.endTime = null), + (this.pauseTime = 0), + (this.mode = "sustain"), + (this.startMillis = null), + (this.panPosition = 0), + (this.panner = new p5.Panner(this.output, u.input, 2)), + (this.url || this.file) && this.load(e, n), + u.soundArray.push(this), + (this._whileLoading = "function" == typeof i ? i : function () {}), + (this._clearOnEnd = function (t) { + var e = t.target, + n = this; + (e._playing = !1), + e.removeEventListener("ended", n._clearOnEnd), + n._onended(n), + n.bufferSourceNodes + .map(function (t, e) { + return e; + }) + .reverse() + .forEach(function (t) { + !1 === n.bufferSourceNodes[t]._playing && + n.bufferSourceNodes.splice(t, 1); + }), + 0 === n.bufferSourceNodes.length && (n._playing = !1); + }.bind(this)); + }), + p5.prototype.registerPreloadMethod("loadSound", p5.prototype), + (p5.prototype.loadSound = function (t, e, n, i) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + window.alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var o = this; + return new p5.SoundFile( + t, + function () { + "function" == typeof e && e.apply(o, arguments), + "function" == typeof o._decrementPreload && + o._decrementPreload(); + }, + n, + i + ); + }), + (p5.SoundFile.prototype.load = function (n, i) { + var o = this, + r = new Error().stack; + if (void 0 !== this.url && "" !== this.url) { + var s = new XMLHttpRequest(); + s.addEventListener( + "progress", + function (t) { + o._updateProgress(t); + }, + !1 + ), + s.open("GET", this.url, !0), + (s.responseType = "arraybuffer"), + (s.onload = function () { + if (200 === s.status) { + if (!o.panner) return; + p.decodeAudioData( + s.response, + function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }, + function () { + if (o.panner) { + var t = new a("decodeAudioData", r, o.url), + e = + "AudioContext error at decodeAudioData for " + + o.url; + i && ((t.msg = e), i(t)); + } + } + ); + } else { + if (!o.panner) return; + var t = new a("loadSound", r, o.url), + e = + "Unable to load " + + o.url + + ". The request status was: " + + s.status + + " (" + + s.statusText + + ")"; + i && ((t.message = e), i(t)); + } + }), + (s.onerror = function () { + var t = new a("loadSound", r, o.url), + e = + "There was no response from the server at " + + o.url + + ". Check the url and internet connectivity."; + i && ((t.message = e), i(t)); + }), + s.send(); + } else if (void 0 !== this.file) { + var t = new FileReader(); + (t.onload = function () { + o.panner && + p.decodeAudioData(t.result, function (t) { + o.panner && + ((o.buffer = t), + o.panner.inputChannels(t.numberOfChannels), + n && n(o)); + }); + }), + (t.onerror = function (t) { + o.panner && onerror && onerror(t); + }), + t.readAsArrayBuffer(this.file); + } + }), + (p5.SoundFile.prototype._updateProgress = function (t) { + if (t.lengthComputable) { + var e = (t.loaded / t.total) * 0.99; + this._whileLoading(e, t); + } else this._whileLoading("size unknown"); + }), + (p5.SoundFile.prototype.isLoaded = function () { + return !!this.buffer; + }), + (p5.SoundFile.prototype.play = function (t, e, n, i, o) { + if (this.output) { + var r, + s, + a = t || 0; + if ( + (a < 0 && (a = 0), + (a += u.audiocontext.currentTime), + void 0 !== e && this.rate(e), + void 0 !== n && this.setVolume(n), + !this.buffer) + ) + throw "not ready to play file, buffer has yet to load. Try preload()"; + if ( + ((this._pauseTime = 0), + "restart" === this.mode && + this.buffer && + this.bufferSourceNode && + (this.bufferSourceNode.stop(a), this._counterNode.stop(a)), + "untildone" !== this.mode || !this.isPlaying()) + ) { + if ( + ((this.bufferSourceNode = this._initSourceNode()), + delete this._counterNode, + (this._counterNode = this._initCounterNode()), + i) + ) { + if (!(0 <= i && i < this.buffer.duration)) + throw "start time out of range"; + r = i; + } else r = 0; + (o = + o && + (o <= this.buffer.duration - r ? o : this.buffer.duration)), + this._paused + ? (this.bufferSourceNode.start(a, this.pauseTime, o), + this._counterNode.start(a, this.pauseTime, o)) + : (this.bufferSourceNode.start(a, r, o), + this._counterNode.start(a, r, o)), + (this._playing = !0), + (this._paused = !1), + this.bufferSourceNodes.push(this.bufferSourceNode), + (this.bufferSourceNode._arrayIndex = + this.bufferSourceNodes.length - 1), + this.bufferSourceNode.addEventListener( + "ended", + this._clearOnEnd + ), + (this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping), + !0 === this._looping && + ((s = o || r - 1e-15), + (this.bufferSourceNode.loopStart = r), + (this.bufferSourceNode.loopEnd = s), + (this._counterNode.loopStart = r), + (this._counterNode.loopEnd = s)); + } + } + }), + (p5.SoundFile.prototype.playMode = function (t) { + var e = t.toLowerCase(); + if ("restart" === e && this.buffer && this.bufferSourceNode) + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) { + var i = u.audiocontext.currentTime; + this.bufferSourceNodes[n].stop(i); + } + if ("restart" !== e && "sustain" !== e && "untildone" !== e) + throw 'Invalid play mode. Must be either "restart" or "sustain"'; + this.mode = e; + }), + (p5.SoundFile.prototype.pause = function (t) { + var e = (t || 0) + u.audiocontext.currentTime; + this.isPlaying() && this.buffer && this.bufferSourceNode + ? ((this._paused = !0), + (this._playing = !1), + (this.pauseTime = this.currentTime()), + this.bufferSourceNode.stop(e), + this._counterNode.stop(e), + (this._pauseTime = this.currentTime())) + : (this._pauseTime = 0); + }), + (p5.SoundFile.prototype.loop = function (t, e, n, i, o) { + (this._looping = !0), this.play(t, e, n, i, o); + }), + (p5.SoundFile.prototype.setLoop = function (t) { + if (!0 === t) this._looping = !0; + else { + if (!1 !== t) throw "Error: setLoop accepts either true or false"; + this._looping = !1; + } + this.bufferSourceNode && + ((this.bufferSourceNode.loop = this._looping), + (this._counterNode.loop = this._looping)); + }), + (p5.SoundFile.prototype.isLooping = function () { + return ( + !!this.bufferSourceNode && + !0 === this._looping && + !0 === this.isPlaying() + ); + }), + (p5.SoundFile.prototype.isPlaying = function () { + return this._playing; + }), + (p5.SoundFile.prototype.isPaused = function () { + return this._paused; + }), + (p5.SoundFile.prototype.stop = function (t) { + var e = t || 0; + if ("sustain" === this.mode || "untildone" === this.mode) + this.stopAll(e), + (this._playing = !1), + (this.pauseTime = 0), + (this._paused = !1); + else if (this.buffer && this.bufferSourceNode) { + var n = u.audiocontext.currentTime, + i = e || 0; + (this.pauseTime = 0), + this.bufferSourceNode.stop(n + i), + this._counterNode.stop(n + i), + (this._playing = !1), + (this._paused = !1); + } + }), + (p5.SoundFile.prototype.stopAll = function (t) { + var e = u.audiocontext.currentTime, + n = t || 0; + if (this.buffer && this.bufferSourceNode) { + for (var i in this.bufferSourceNodes) { + var o = this.bufferSourceNodes[i]; + if (o) + try { + o.stop(e + n); + } catch (t) {} + } + this._counterNode.stop(e + n), this._onended(this); + } + }), + (p5.SoundFile.prototype.setVolume = function (t, e, n) { + if ("number" == typeof t) { + var i = e || 0, + o = n || 0, + r = u.audiocontext.currentTime, + s = this.output.gain.value; + this.output.gain.cancelScheduledValues(r + o), + this.output.gain.linearRampToValueAtTime(s, r + o), + this.output.gain.linearRampToValueAtTime(t, r + o + i); + } else { + if (!t) return this.output.gain; + t.connect(this.output.gain); + } + }), + (p5.SoundFile.prototype.amp = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.fade = p5.SoundFile.prototype.setVolume), + (p5.SoundFile.prototype.getVolume = function () { + return this.output.gain.value; + }), + (p5.SoundFile.prototype.pan = function (t, e) { + (this.panPosition = t), this.panner.pan(t, e); + }), + (p5.SoundFile.prototype.getPan = function () { + return this.panPosition; + }), + (p5.SoundFile.prototype.rate = function (t) { + var e = !1; + if (void 0 === t) return this.playbackRate; + if ( + (0 === (this.playbackRate = t) + ? (t = 1e-13) + : t < 0 && !this.reversed + ? ((t = Math.abs(t)), (e = !0)) + : 0 < t && this.reversed && (e = !0), + this.bufferSourceNode) + ) { + var n = u.audiocontext.currentTime; + this.bufferSourceNode.playbackRate.cancelScheduledValues(n), + this.bufferSourceNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ), + this._counterNode.playbackRate.cancelScheduledValues(n), + this._counterNode.playbackRate.linearRampToValueAtTime( + Math.abs(t), + n + ); + } + return e && this.reverseBuffer(), this.playbackRate; + }), + (p5.SoundFile.prototype.setPitch = function (t) { + var e = n(t) / n(60); + this.rate(e); + }), + (p5.SoundFile.prototype.getPlaybackRate = function () { + return this.playbackRate; + }), + (p5.SoundFile.prototype.duration = function () { + return this.buffer ? this.buffer.duration : 0; + }), + (p5.SoundFile.prototype.currentTime = function () { + return this.reversed + ? Math.abs(this._lastPos - this.buffer.length) / p.sampleRate + : this._lastPos / p.sampleRate; + }), + (p5.SoundFile.prototype.jump = function (t, e) { + if (t < 0 || t > this.buffer.duration) + throw "jump time out of range"; + if (e > this.buffer.duration - t) throw "end time out of range"; + var n = t || 0, + i = e || void 0; + this.isPlaying() && + (this.stop(0), + this.play(0, this.playbackRate, this.output.gain.value, n, i)); + }), + (p5.SoundFile.prototype.channels = function () { + return this.buffer.numberOfChannels; + }), + (p5.SoundFile.prototype.sampleRate = function () { + return this.buffer.sampleRate; + }), + (p5.SoundFile.prototype.frames = function () { + return this.buffer.length; + }), + (p5.SoundFile.prototype.getPeaks = function (t) { + if (!this.buffer) + throw "Cannot load peaks yet, buffer is not loaded"; + if (((t = t || 5 * window.width), this.buffer)) { + for ( + var e = this.buffer, + n = e.length / t, + i = ~~(n / 10) || 1, + o = e.numberOfChannels, + r = new Float32Array(Math.round(t)), + s = 0; + s < o; + s++ + ) + for (var a = e.getChannelData(s), u = 0; u < t; u++) { + for ( + var p = ~~(u * n), c = ~~(p + n), h = 0, l = p; + l < c; + l += i + ) { + var f = a[l]; + h < f ? (h = f) : h < -f && (h = f); + } + (0 === s || Math.abs(h) > r[u]) && (r[u] = h); + } + return r; + } + }), + (p5.SoundFile.prototype.reverseBuffer = function () { + if (!this.buffer) throw "SoundFile is not done loading"; + var t = this._lastPos / p.sampleRate, + e = this.getVolume(); + this.setVolume(0, 0.001); + for (var n = this.buffer.numberOfChannels, i = 0; i < n; i++) + this.buffer.getChannelData(i).reverse(); + (this.reversed = !this.reversed), + this.isPlaying() && t && this.jump(this.duration() - t), + this.setVolume(e, 0.001); + }), + (p5.SoundFile.prototype.onended = function (t) { + return (this._onended = t), this; + }), + (p5.SoundFile.prototype.add = function () {}), + (p5.SoundFile.prototype.dispose = function () { + var t = u.audiocontext.currentTime, + e = u.soundArray.indexOf(this); + if ( + (u.soundArray.splice(e, 1), + this.stop(t), + this.buffer && this.bufferSourceNode) + ) { + for (var n = 0; n < this.bufferSourceNodes.length - 1; n++) + if (null !== this.bufferSourceNodes[n]) { + this.bufferSourceNodes[n].disconnect(); + try { + this.bufferSourceNodes[n].stop(t); + } catch (t) {} + this.bufferSourceNodes[n] = null; + } + if (this.isPlaying()) { + try { + this._counterNode.stop(t); + } catch (t) {} + this._counterNode = null; + } + } + this.output && (this.output.disconnect(), (this.output = null)), + this.panner && (this.panner.disconnect(), (this.panner = null)); + }), + (p5.SoundFile.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.panner.connect(t.input) + : this.panner.connect(t) + : this.panner.connect(u.input); + }), + (p5.SoundFile.prototype.disconnect = function () { + this.panner && this.panner.disconnect(); + }), + (p5.SoundFile.prototype.getLevel = function () {}), + (p5.SoundFile.prototype.setPath = function (t, e) { + var n = p5.prototype._checkFileFormats(t); + (this.url = n), this.load(e); + }), + (p5.SoundFile.prototype.setBuffer = function (t) { + var e = t.length, + n = t[0].length, + i = p.createBuffer(e, n, p.sampleRate); + t[0] instanceof Float32Array || (t[0] = new Float32Array(t[0])); + for (var o = 0; o < e; o++) { + i.getChannelData(o).set(t[o]); + } + (this.buffer = i), this.panner.inputChannels(e); + }); + (p5.SoundFile.prototype._initCounterNode = function () { + var e = this, + n = this, + t = p.currentTime, + i = p.createBufferSource(), + o = r(256); + return ( + n._workletNode && + (n._workletNode.disconnect(), delete n._workletNode), + (n._workletNode = new AudioWorkletNode(p, s.soundFileProcessor, { + processorOptions: { bufferSize: o }, + })), + (n._workletNode.port.onmessage = function (t) { + if ("position" === t.data.name) { + if (0 === t.data.position) return; + (e._lastPos = t.data.position), e._onTimeUpdate(n._lastPos); + } + }), + (i.buffer = (function (t) { + for ( + var e = t.length, + n = p.createBuffer(1, t.length, p.sampleRate), + i = n.getChannelData(0), + o = 0; + o < e; + o++ + ) + i[o] = o; + return n; + })(n.buffer)), + i.playbackRate.setValueAtTime(n.playbackRate, t), + i.connect(n._workletNode), + n._workletNode.connect(p5.soundOut._silentNode), + i + ); + }), + (p5.SoundFile.prototype._initSourceNode = function () { + var t = p.createBufferSource(); + return ( + (t.buffer = this.buffer), + (t.playbackRate.value = this.playbackRate), + t.connect(this.output), + t + ); + }), + (p5.SoundFile.prototype.processPeaks = function (r, t, e, n) { + var i = this.buffer.length, + o = this.buffer.sampleRate, + s = this.buffer, + a = [], + u = t || 0.9, + p = e || 0.22, + c = n || 200, + h = new window.OfflineAudioContext(1, i, o), + l = h.createBufferSource(); + l.buffer = s; + var f = h.createBiquadFilter(); + (f.type = "lowpass"), + l.connect(f), + f.connect(h.destination), + l.start(0), + h.startRendering(), + (h.oncomplete = function (t) { + if (self.panner) { + for ( + var e = t.renderedBuffer, n = e.getChannelData(0); + (a = d(n, u)), + (u -= 0.005), + Object.keys(a).length < c && p <= u; + + ); + var i = (function (t, i) { + var o = []; + return ( + t.forEach(function (e) { + try { + var n = Math.abs(60 / (e.interval / i)); + if ( + ((n = m(n)), + !o.some(function (t) { + if (t.tempo === n) return (t.count += e.count); + })) + ) { + if (isNaN(n)) return; + o.push({ tempo: Math.round(n), count: e.count }); + } + } catch (t) { + throw t; + } + }), + o + ); + })( + (function (t) { + for ( + var e = [], n = Object.keys(t).sort(), i = 0; + i < n.length; + i++ + ) + for (var o = 0; o < 10; o++) { + var r = t[n[i]], + s = t[n[i + o]]; + if (r && s) { + var a = r.sampleIndex, + u = s.sampleIndex - a; + 0 < u && r.intervals.push(u), + e.some(function (t) { + if (t.interval === u) return t.count++, t; + }) || e.push({ interval: u, count: 1 }); + } + } + return e; + })(a), + e.sampleRate + ) + .sort(function (t, e) { + return e.count - t.count; + }) + .splice(0, 5); + this.tempo = i[0].tempo; + var o = (function (t, e, n, i) { + for ( + var o = [], r = Object.keys(t).sort(), s = 0; + s < r.length; + s++ + ) + for ( + var a = r[s], u = t[a], p = 0; + p < u.intervals.length; + p++ + ) { + var c = Math.round(Math.abs(60 / (u.intervals[p] / n))); + (c = m(c)), + Math.abs(c - e) < i && o.push(u.sampleIndex / n); + } + return (o = o.filter(function (t, e, n) { + if (0.01 < n[e + 1] - t) return !0; + })); + })(a, i[0].tempo, e.sampleRate, 5); + r(o); + } + }); + }); + var c = function (t, e) { + (this.sampleIndex = e), + (this.amplitude = t), + (this.tempos = []), + (this.intervals = []); + }; + function d(t, e) { + for (var n = {}, i = t.length, o = 0; o < i; o++) { + if (t[o] > e) { + var r = t[o], + s = new c(r, o); + (n[o] = s), (o += 6e3); + } + o++; + } + return n; + } + function m(t) { + if (isFinite(t) && 0 !== t) { + for (; t < 90; ) t *= 2; + for (; 180 < t && 90 < t; ) t /= 2; + return t; + } + } + function h(t, e, n, i) { + (this.callback = t), (this.time = e), (this.id = n), (this.val = i); + } + (p5.SoundFile.prototype.addCue = function (t, e, n) { + var i = this._cueIDCounter++, + o = new h(e, t, i, n); + return this._cues.push(o), i; + }), + (p5.SoundFile.prototype.removeCue = function (t) { + for (var e = this._cues.length, n = 0; n < e; n++) { + if (this._cues[n].id === t) { + this._cues.splice(n, 1); + break; + } + } + this._cues.length; + }), + (p5.SoundFile.prototype.clearCues = function () { + this._cues = []; + }), + (p5.SoundFile.prototype._onTimeUpdate = function (t) { + for ( + var e = t / this.buffer.sampleRate, n = this._cues.length, i = 0; + i < n; + i++ + ) { + var o = this._cues[i], + r = o.time, + s = o.val; + ~~this._prevUpdateTime <= r && r <= e && o.callback(s); + } + this._prevUpdateTime = e; + }), + (p5.SoundFile.prototype.save = function (t) { + p5.prototype.saveSound(this, t, "wav"); + }), + (p5.SoundFile.prototype.getBlob = function () { + var t = i(this.buffer); + return new Blob([t], { type: "audio/wav" }); + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var n = o(1), + e = o(6).safeBufferSize, + i = o(10); + (p5.Amplitude = function (t) { + (this.bufferSize = e(2048)), + (this.audiocontext = n.audiocontext), + (this._workletNode = new AudioWorkletNode( + this.audiocontext, + i.amplitudeProcessor, + { + outputChannelCount: [1], + parameterData: { smoothing: t || 0 }, + processorOptions: { + normalize: !1, + smoothing: t || 0, + numInputChannels: 2, + bufferSize: this.bufferSize, + }, + } + )), + (this._workletNode.port.onmessage = function (t) { + "amplitude" === t.data.name && + ((this.volume = t.data.volume), + (this.volNorm = t.data.volNorm), + (this.stereoVol = t.data.stereoVol), + (this.stereoVolNorm = t.data.stereoVolNorm)); + }.bind(this)), + (this.input = this._workletNode), + (this.output = this.audiocontext.createGain()), + (this.volume = 0), + (this.volNorm = 0), + (this.stereoVol = [0, 0]), + (this.stereoVolNorm = [0, 0]), + (this.normalize = !1), + this._workletNode.connect(this.output), + (this.output.gain.value = 0), + this.output.connect(this.audiocontext.destination), + n.meter.connect(this._workletNode), + n.soundArray.push(this); + }), + (p5.Amplitude.prototype.setInput = function (t, e) { + n.meter.disconnect(), + e && (this._workletNode.parameters.get("smoothing").value = e), + null == t + ? n.meter.connect(this._workletNode) + : t instanceof p5.Signal + ? t.output.connect(this._workletNode) + : t + ? (t.connect(this._workletNode), + this._workletNode.disconnect(), + this._workletNode.connect(this.output)) + : n.meter.connect(this._workletNode); + }), + (p5.Amplitude.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : this.output.connect(t) + : this.output.connect(this.panner.connect(n.input)); + }), + (p5.Amplitude.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Amplitude.prototype.getLevel = function (t) { + return void 0 !== t + ? this.normalize + ? this.stereoVolNorm[t] + : this.stereoVol[t] + : this.normalize + ? this.volNorm + : this.volume; + }), + (p5.Amplitude.prototype.toggleNormalize = function (t) { + (this.normalize = "boolean" == typeof t ? t : !this.normalize), + this._workletNode.port.postMessage({ + name: "toggleNormalize", + normalize: this.normalize, + }); + }), + (p5.Amplitude.prototype.smooth = function (t) { + 0 <= t && + t < 1 && + this._workletNode.port.postMessage({ + name: "smoothing", + smoothing: t, + }); + }), + (p5.Amplitude.prototype.dispose = function () { + var t = n.soundArray.indexOf(this); + n.soundArray.splice(t, 1), + this.input && (this.input.disconnect(), delete this.input), + this.output && (this.output.disconnect(), delete this.output), + this._workletNode.disconnect(), + delete this._workletNode; + }); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var c = o(1); + (p5.FFT = function (t, e) { + (this.input = this.analyser = c.audiocontext.createAnalyser()), + Object.defineProperties(this, { + bins: { + get: function () { + return this.analyser.fftSize / 2; + }, + set: function (t) { + this.analyser.fftSize = 2 * t; + }, + configurable: !0, + enumerable: !0, + }, + smoothing: { + get: function () { + return this.analyser.smoothingTimeConstant; + }, + set: function (t) { + this.analyser.smoothingTimeConstant = t; + }, + configurable: !0, + enumerable: !0, + }, + }), + this.smooth(t), + (this.bins = e || 1024), + c.fftMeter.connect(this.analyser), + (this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount)), + (this.bass = [20, 140]), + (this.lowMid = [140, 400]), + (this.mid = [400, 2600]), + (this.highMid = [2600, 5200]), + (this.treble = [5200, 14e3]), + c.soundArray.push(this); + }), + (p5.FFT.prototype.setInput = function (t) { + t + ? (t.output + ? t.output.connect(this.analyser) + : t.connect && t.connect(this.analyser), + c.fftMeter.disconnect()) + : c.fftMeter.connect(this.analyser); + }), + (p5.FFT.prototype.waveform = function () { + for (var t, e, n = 0; n < arguments.length; n++) + "number" == typeof arguments[n] && + ((t = arguments[n]), (this.analyser.fftSize = 2 * t)), + "string" == typeof arguments[n] && (e = arguments[n]); + if (e && !p5.prototype._isSafari()) + return ( + s(this, this.timeDomain), + this.analyser.getFloatTimeDomainData(this.timeDomain), + this.timeDomain + ); + a(this, this.timeDomain), + this.analyser.getByteTimeDomainData(this.timeDomain); + for (var i = new Array(), o = 0; o < this.timeDomain.length; o++) { + var r = p5.prototype.map(this.timeDomain[o], 0, 255, -1, 1); + i.push(r); + } + return i; + }), + (p5.FFT.prototype.analyze = function () { + for (var t, e = 0; e < arguments.length; e++) + "number" == typeof arguments[e] && + ((this.bins = arguments[e]), + (this.analyser.fftSize = 2 * this.bins)), + "string" == typeof arguments[e] && (t = arguments[e]); + return t && "db" === t.toLowerCase() + ? (n(this), + this.analyser.getFloatFrequencyData(this.freqDomain), + this.freqDomain) + : (i(this, this.freqDomain), + this.analyser.getByteFrequencyData(this.freqDomain), + Array.apply([], this.freqDomain)); + }), + (p5.FFT.prototype.getEnergy = function (t, e) { + var n = c.audiocontext.sampleRate / 2; + if ( + ("bass" === t + ? ((t = this.bass[0]), (e = this.bass[1])) + : "lowMid" === t + ? ((t = this.lowMid[0]), (e = this.lowMid[1])) + : "mid" === t + ? ((t = this.mid[0]), (e = this.mid[1])) + : "highMid" === t + ? ((t = this.highMid[0]), (e = this.highMid[1])) + : "treble" === t && + ((t = this.treble[0]), (e = this.treble[1])), + "number" != typeof t) + ) + throw "invalid input for getEnergy()"; + if (e) { + if (t && e) { + if (e < t) { + var i = e; + (e = t), (t = i); + } + for ( + var o = Math.round((t / n) * this.freqDomain.length), + r = Math.round((e / n) * this.freqDomain.length), + s = 0, + a = 0, + u = o; + u <= r; + u++ + ) + (s += this.freqDomain[u]), (a += 1); + return s / a; + } + throw "invalid input for getEnergy()"; + } + var p = Math.round((t / n) * this.freqDomain.length); + return this.freqDomain[p]; + }), + (p5.FFT.prototype.getFreq = function (t, e) { + return this.getEnergy(t, e); + }), + (p5.FFT.prototype.getCentroid = function () { + for ( + var t = c.audiocontext.sampleRate / 2, e = 0, n = 0, i = 0; + i < this.freqDomain.length; + i++ + ) + (e += i * this.freqDomain[i]), (n += this.freqDomain[i]); + var o = 0; + return 0 !== n && (o = e / n), o * (t / this.freqDomain.length); + }), + (p5.FFT.prototype.smooth = function (t) { + return void 0 !== t && (this.smoothing = t), this.smoothing; + }), + (p5.FFT.prototype.dispose = function () { + var t = c.soundArray.indexOf(this); + c.soundArray.splice(t, 1), + this.analyser && + (this.analyser.disconnect(), delete this.analyser); + }), + (p5.FFT.prototype.linAverages = function (t) { + t = t || 16; + for ( + var e = this.freqDomain, + n = e.length, + i = Math.floor(n / t), + o = new Array(t), + r = 0, + s = 0; + s < n; + s++ + ) + (o[r] = void 0 !== o[r] ? (o[r] + e[s]) / 2 : e[s]), + s % i == i - 1 && r++; + return o; + }), + (p5.FFT.prototype.logAverages = function (t) { + for ( + var e = c.audiocontext.sampleRate / 2, + n = this.freqDomain, + i = n.length, + o = new Array(t.length), + r = 0, + s = 0; + s < i; + s++ + ) { + Math.round((s * e) / this.freqDomain.length) > t[r].hi && r++, + (o[r] = void 0 !== o[r] ? (o[r] + n[s]) / 2 : n[s]); + } + return o; + }), + (p5.FFT.prototype.getOctaveBands = function (t, e) { + t = t || 3; + var n = [], + i = { + lo: (e = e || 15.625) / Math.pow(2, 1 / (2 * t)), + ctr: e, + hi: e * Math.pow(2, 1 / (2 * t)), + }; + n.push(i); + for (var o = c.audiocontext.sampleRate / 2; i.hi < o; ) { + var r = {}; + (r.lo = i.hi), + (r.ctr = i.ctr * Math.pow(2, 1 / t)), + (r.hi = r.ctr * Math.pow(2, 1 / (2 * t))), + n.push(r), + (i = r); + } + return n; + }); + var n = function (t) { + t.freqDomain instanceof Float32Array == !1 && + (t.freqDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + i = function (t) { + t.freqDomain instanceof Uint8Array == !1 && + (t.freqDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }, + s = function (t) { + t.timeDomain instanceof Float32Array == !1 && + (t.timeDomain = new Float32Array(t.analyser.frequencyBinCount)); + }, + a = function (t) { + t.timeDomain instanceof Uint8Array == !1 && + (t.timeDomain = new Uint8Array(t.analyser.frequencyBinCount)); + }; + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = o(2), + n = o(7), + i = o(3), + a = o(13); + (p5.Signal = function (t) { + return new e(t); + }), + (e.prototype.fade = e.prototype.linearRampToValueAtTime), + (i.prototype.fade = e.prototype.fade), + (n.prototype.fade = e.prototype.fade), + (a.prototype.fade = e.prototype.fade), + (e.prototype.setInput = function (t) { + t.connect(this); + }), + (i.prototype.setInput = e.prototype.setInput), + (n.prototype.setInput = e.prototype.setInput), + (a.prototype.setInput = e.prototype.setInput), + (e.prototype.add = function (t) { + var e = new n(t); + return this.connect(e), e; + }), + (i.prototype.add = e.prototype.add), + (n.prototype.add = e.prototype.add), + (a.prototype.add = e.prototype.add), + (e.prototype.mult = function (t) { + var e = new i(t); + return this.connect(e), e; + }), + (i.prototype.mult = e.prototype.mult), + (n.prototype.mult = e.prototype.mult), + (a.prototype.mult = e.prototype.mult), + (e.prototype.scale = function (t, e, n, i) { + var o, r; + r = + 4 === arguments.length + ? ((o = p5.prototype.map(n, t, e, 0, 1) - 0.5), + p5.prototype.map(i, t, e, 0, 1) - 0.5) + : ((o = t), e); + var s = new a(o, r); + return this.connect(s), s; + }), + (i.prototype.scale = e.prototype.scale), + (n.prototype.scale = e.prototype.scale), + (a.prototype.scale = e.prototype.scale); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(21)]), + void 0 === + (o = function (o) { + (o.Frequency = function (t, e) { + if (!(this instanceof o.Frequency)) return new o.Frequency(t, e); + o.TimeBase.call(this, t, e); + }), + o.extend(o.Frequency, o.TimeBase), + (o.Frequency.prototype._primaryExpressions = Object.create( + o.TimeBase.prototype._primaryExpressions + )), + (o.Frequency.prototype._primaryExpressions.midi = { + regexp: /^(\d+(?:\.\d+)?midi)/, + method: function (t) { + return this.midiToFrequency(t); + }, + }), + (o.Frequency.prototype._primaryExpressions.note = { + regexp: /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i, + method: function (t, e) { + var n = i[t.toLowerCase()] + 12 * (parseInt(e) + 1); + return this.midiToFrequency(n); + }, + }), + (o.Frequency.prototype._primaryExpressions.tr = { + regexp: /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):?(\d+(?:\.\d+)?)?/, + method: function (t, e, n) { + var i = 1; + return ( + t && + "0" !== t && + (i *= this._beatsToUnits( + this._timeSignature() * parseFloat(t) + )), + e && "0" !== e && (i *= this._beatsToUnits(parseFloat(e))), + n && + "0" !== n && + (i *= this._beatsToUnits(parseFloat(n) / 4)), + i + ); + }, + }), + (o.Frequency.prototype.transpose = function (t) { + return ( + (this._expr = function (t, e) { + return t() * this.intervalToFrequencyRatio(e); + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.harmonize = function (t) { + return ( + (this._expr = function (t, e) { + for (var n = t(), i = [], o = 0; o < e.length; o++) + i[o] = n * this.intervalToFrequencyRatio(e[o]); + return i; + }.bind(this, this._expr, t)), + this + ); + }), + (o.Frequency.prototype.toMidi = function () { + return this.frequencyToMidi(this.valueOf()); + }), + (o.Frequency.prototype.toNote = function () { + var t = this.valueOf(), + e = Math.log(t / o.Frequency.A4) / Math.LN2, + n = Math.round(12 * e) + 57, + i = Math.floor(n / 12); + return i < 0 && (n += -12 * i), r[n % 12] + i.toString(); + }), + (o.Frequency.prototype.toSeconds = function () { + return 1 / this.valueOf(); + }), + (o.Frequency.prototype.toFrequency = function () { + return this.valueOf(); + }), + (o.Frequency.prototype.toTicks = function () { + var t = this._beatsToUnits(1), + e = this.valueOf() / t; + return Math.floor(e * o.Transport.PPQ); + }), + (o.Frequency.prototype._frequencyToUnits = function (t) { + return t; + }), + (o.Frequency.prototype._ticksToUnits = function (t) { + return 1 / ((60 * t) / (o.Transport.bpm.value * o.Transport.PPQ)); + }), + (o.Frequency.prototype._beatsToUnits = function (t) { + return 1 / o.TimeBase.prototype._beatsToUnits.call(this, t); + }), + (o.Frequency.prototype._secondsToUnits = function (t) { + return 1 / t; + }), + (o.Frequency.prototype._defaultUnits = "hz"); + var i = { + cbb: -2, + cb: -1, + c: 0, + "c#": 1, + cx: 2, + dbb: 0, + db: 1, + d: 2, + "d#": 3, + dx: 4, + ebb: 2, + eb: 3, + e: 4, + "e#": 5, + ex: 6, + fbb: 3, + fb: 4, + f: 5, + "f#": 6, + fx: 7, + gbb: 5, + gb: 6, + g: 7, + "g#": 8, + gx: 9, + abb: 7, + ab: 8, + a: 9, + "a#": 10, + ax: 11, + bbb: 9, + bb: 10, + b: 11, + "b#": 12, + bx: 13, + }, + r = [ + "C", + "C#", + "D", + "D#", + "E", + "F", + "F#", + "G", + "G#", + "A", + "A#", + "B", + ]; + return ( + (o.Frequency.A4 = 440), + (o.Frequency.prototype.midiToFrequency = function (t) { + return o.Frequency.A4 * Math.pow(2, (t - 69) / 12); + }), + (o.Frequency.prototype.frequencyToMidi = function (t) { + return 69 + (12 * Math.log(t / o.Frequency.A4)) / Math.LN2; + }), + o.Frequency + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(20)]), + void 0 === + (o = function (i) { + return ( + (i.TransportTime = function (t, e) { + if (!(this instanceof i.TransportTime)) + return new i.TransportTime(t, e); + i.Time.call(this, t, e); + }), + i.extend(i.TransportTime, i.Time), + (i.TransportTime.prototype._unaryExpressions = Object.create( + i.Time.prototype._unaryExpressions + )), + (i.TransportTime.prototype._unaryExpressions.quantize = { + regexp: /^@/, + method: function (t) { + var e = this._secondsToTicks(t()), + n = Math.ceil(i.Transport.ticks / e); + return this._ticksToUnits(n * e); + }, + }), + (i.TransportTime.prototype._secondsToTicks = function (t) { + var e = t / this._beatsToUnits(1); + return Math.round(e * i.Transport.PPQ); + }), + (i.TransportTime.prototype.valueOf = function () { + return ( + this._secondsToTicks(this._expr()) + + (this._plusNow ? i.Transport.ticks : 0) + ); + }), + (i.TransportTime.prototype.toTicks = function () { + return this.valueOf(); + }), + (i.TransportTime.prototype.toSeconds = function () { + return this._expr() + (this._plusNow ? i.Transport.seconds : 0); + }), + (i.TransportTime.prototype.toFrequency = function () { + return 1 / this.toSeconds(); + }), + i.TransportTime + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var u = n(1), + o = n(7), + r = n(3), + a = n(13), + s = n(14); + (p5.Envelope = function (t, e, n, i, o, r) { + (this.aTime = t || 0.1), + (this.aLevel = e || 1), + (this.dTime = n || 0.5), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + (this._rampHighPercentage = 0.98), + (this._rampLowPercentage = 0.02), + (this.output = u.audiocontext.createGain()), + (this.control = new s()), + this._init(), + this.control.connect(this.output), + (this.connection = null), + (this.mathOps = [this.control]), + (this.isExponential = !1), + (this.sourceToClear = null), + (this.wasTriggered = !1), + u.soundArray.push(this); + }), + (p5.Envelope.prototype._init = function () { + var t = u.audiocontext.currentTime; + this.control.setTargetAtTime(1e-5, t, 0.001), + this._setRampAD(this.aTime, this.dTime); + }), + (p5.Envelope.prototype.set = function (t, e, n, i, o, r) { + (this.aTime = t), + (this.aLevel = e), + (this.dTime = n || 0), + (this.dLevel = i || 0), + (this.rTime = o || 0), + (this.rLevel = r || 0), + this._setRampAD(t, n); + }), + (p5.Envelope.prototype.setADSR = function (t, e, n, i) { + (this.aTime = t), + (this.dTime = e || 0), + (this.sPercent = n || 0), + (this.dLevel = + void 0 !== n + ? n * (this.aLevel - this.rLevel) + this.rLevel + : 0), + (this.rTime = i || 0), + this._setRampAD(t, e); + }), + (p5.Envelope.prototype.setRange = function (t, e) { + (this.aLevel = t || 1), (this.rLevel = e || 0); + }), + (p5.Envelope.prototype._setRampAD = function (t, e) { + (this._rampAttackTime = this.checkExpInput(t)), + (this._rampDecayTime = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = t / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = e / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setRampPercentages = function (t, e) { + (this._rampHighPercentage = this.checkExpInput(t)), + (this._rampLowPercentage = this.checkExpInput(e)); + var n = 1; + (n = Math.log( + 1 / this.checkExpInput(1 - this._rampHighPercentage) + )), + (this._rampAttackTC = + this._rampAttackTime / this.checkExpInput(n)), + (n = Math.log(1 / this._rampLowPercentage)), + (this._rampDecayTC = this._rampDecayTime / this.checkExpInput(n)); + }), + (p5.Envelope.prototype.setInput = function () { + for (var t = 0; t < arguments.length; t++) + this.connect(arguments[t]); + }), + (p5.Envelope.prototype.setExp = function (t) { + this.isExponential = t; + }), + (p5.Envelope.prototype.checkExpInput = function (t) { + return t <= 0 && (t = 1e-8), t; + }), + (p5.Envelope.prototype.play = function (t, e, n) { + var i = e || 0; + n = n || 0; + t && this.connection !== t && this.connect(t), + this.triggerAttack(t, i), + this.triggerRelease(t, i + this.aTime + this.dTime + n); + }), + (p5.Envelope.prototype.triggerAttack = function (t, e) { + var n = u.audiocontext.currentTime + (e || 0); + (this.lastAttack = n), + (this.wasTriggered = !0), + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.aTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.aLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.aLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (n += this.dTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.dLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.dLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)); + }), + (p5.Envelope.prototype.triggerRelease = function (t, e) { + if (this.wasTriggered) { + var n = u.audiocontext.currentTime + (e || 0); + t && this.connection !== t && this.connect(t); + var i = this.control.getValueAtTime(n); + !0 === this.isExponential + ? this.control.exponentialRampToValueAtTime( + this.checkExpInput(i), + n + ) + : this.control.linearRampToValueAtTime(i, n), + (n += this.rTime), + !0 === this.isExponential + ? (this.control.exponentialRampToValueAtTime( + this.checkExpInput(this.rLevel), + n + ), + (i = this.checkExpInput(this.control.getValueAtTime(n))), + this.control.cancelScheduledValues(n), + this.control.exponentialRampToValueAtTime(i, n)) + : (this.control.linearRampToValueAtTime(this.rLevel, n), + (i = this.control.getValueAtTime(n)), + this.control.cancelScheduledValues(n), + this.control.linearRampToValueAtTime(i, n)), + (this.wasTriggered = !1); + } + }), + (p5.Envelope.prototype.ramp = function (t, e, n, i) { + var o = u.audiocontext.currentTime + (e || 0), + r = this.checkExpInput(n), + s = void 0 !== i ? this.checkExpInput(i) : void 0; + t && this.connection !== t && this.connect(t); + var a = this.checkExpInput(this.control.getValueAtTime(o)); + a < r + ? (this.control.setTargetAtTime(r, o, this._rampAttackTC), + (o += this._rampAttackTime)) + : r < a && + (this.control.setTargetAtTime(r, o, this._rampDecayTC), + (o += this._rampDecayTime)), + void 0 !== s && + (r < s + ? this.control.setTargetAtTime(s, o, this._rampAttackTC) + : s < r && + this.control.setTargetAtTime(s, o, this._rampDecayTC)); + }), + (p5.Envelope.prototype.connect = function (t) { + ((this.connection = t) instanceof p5.Oscillator || + t instanceof p5.SoundFile || + t instanceof p5.AudioIn || + t instanceof p5.Reverb || + t instanceof p5.Noise || + t instanceof p5.Filter || + t instanceof p5.Delay) && + (t = t.output.gain), + t instanceof AudioParam && + t.setValueAtTime(0, u.audiocontext.currentTime), + t instanceof p5.Signal && t.setValue(0), + this.output.connect(t); + }), + (p5.Envelope.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Envelope.prototype.add = function (t) { + var e = new o(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, o); + }), + (p5.Envelope.prototype.mult = function (t) { + var e = new r(t), + n = this.mathOps.length, + i = this.output; + return p5.prototype._mathChain(this, e, n, i, r); + }), + (p5.Envelope.prototype.scale = function (t, e, n, i) { + var o = new a(t, e, n, i), + r = this.mathOps.length, + s = this.output; + return p5.prototype._mathChain(this, o, r, s, a); + }), + (p5.Envelope.prototype.dispose = function () { + var t = u.soundArray.indexOf(this); + u.soundArray.splice(t, 1), + this.disconnect(), + this.control && (this.control.dispose(), (this.control = null)); + for (var e = 1; e < this.mathOps.length; e++) + this.mathOps[e].dispose(); + }), + (p5.Env = function (t, e, n, i, o, r) { + p5.Envelope.call(this, t, e, n, i, o, r); + }), + (p5.Env.prototype = Object.create(p5.Envelope.prototype)); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var s = n(1); + function a() { + for ( + var t = s.audiocontext, + e = t.createBuffer(1, 2048, t.sampleRate), + n = e.getChannelData(0), + i = 0; + i < 2048; + i++ + ) + n[i] = 1; + var o = t.createBufferSource(); + return (o.buffer = e), (o.loop = !0), o; + } + n(23), + (p5.Pulse = function (t, e) { + p5.Oscillator.call(this, t, "sawtooth"), + (this.w = e || 0), + (this.osc2 = new p5.SawOsc(t)), + (this.dNode = s.audiocontext.createDelay()), + (this.dcOffset = a()), + (this.dcGain = s.audiocontext.createGain()), + this.dcOffset.connect(this.dcGain), + this.dcGain.connect(this.output), + (this.f = t || 440); + var n = this.w / this.oscillator.frequency.value; + (this.dNode.delayTime.value = n), + (this.dcGain.gain.value = 1.7 * (0.5 - this.w)), + this.osc2.disconnect(), + this.osc2.panner.disconnect(), + this.osc2.amp(-1), + this.osc2.output.connect(this.dNode), + this.dNode.connect(this.output), + (this.output.gain.value = 1), + this.output.connect(this.panner); + }), + (p5.Pulse.prototype = Object.create(p5.Oscillator.prototype)), + (p5.Pulse.prototype.width = function (t) { + if ("number" == typeof t) { + if (t <= 1 && 0 <= t) { + this.w = t; + var e = this.w / this.oscillator.frequency.value; + this.dNode.delayTime.value = e; + } + this.dcGain.gain.value = 1.7 * (0.5 - this.w); + } else { + t.connect(this.dNode.delayTime); + var n = new p5.SignalAdd(-0.5); + n.setInput(t), + (n = (n = n.mult(-1)).mult(1.7)).connect(this.dcGain.gain); + } + }), + (p5.Pulse.prototype.start = function (t, e) { + var n = s.audiocontext.currentTime, + i = e || 0; + if (!this.started) { + var o = t || this.f, + r = this.oscillator.type; + (this.oscillator = s.audiocontext.createOscillator()), + this.oscillator.frequency.setValueAtTime(o, n), + (this.oscillator.type = r), + this.oscillator.connect(this.output), + this.oscillator.start(i + n), + (this.osc2.oscillator = s.audiocontext.createOscillator()), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + (this.osc2.oscillator.type = r), + this.osc2.oscillator.connect(this.osc2.output), + this.osc2.start(i + n), + (this.freqNode = [ + this.oscillator.frequency, + this.osc2.oscillator.frequency, + ]), + (this.dcOffset = a()), + this.dcOffset.connect(this.dcGain), + this.dcOffset.start(i + n), + void 0 !== this.mods && + void 0 !== this.mods.frequency && + (this.mods.frequency.connect(this.freqNode[0]), + this.mods.frequency.connect(this.freqNode[1])), + (this.started = !0), + (this.osc2.started = !0); + } + }), + (p5.Pulse.prototype.stop = function (t) { + if (this.started) { + var e = t || 0, + n = s.audiocontext.currentTime; + this.oscillator.stop(e + n), + this.osc2.oscillator && this.osc2.oscillator.stop(e + n), + this.dcOffset.stop(e + n), + (this.started = !1), + (this.osc2.started = !1); + } + }), + (p5.Pulse.prototype.freq = function (t, e, n) { + if ("number" == typeof t) { + this.f = t; + var i = s.audiocontext.currentTime, + o = + ((e = e || 0), (n = n || 0), this.oscillator.frequency.value); + this.oscillator.frequency.cancelScheduledValues(i), + this.oscillator.frequency.setValueAtTime(o, i + n), + this.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.osc2.oscillator.frequency.cancelScheduledValues(i), + this.osc2.oscillator.frequency.setValueAtTime(o, i + n), + this.osc2.oscillator.frequency.exponentialRampToValueAtTime( + t, + n + e + i + ), + this.freqMod && + (this.freqMod.output.disconnect(), (this.freqMod = null)); + } else + t.output && + (t.output.disconnect(), + t.output.connect(this.oscillator.frequency), + t.output.connect(this.osc2.oscillator.frequency), + (this.freqMod = t)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var l = r(1); + (p5.Noise = function (t) { + var e; + p5.Oscillator.call(this), + delete this.f, + delete this.freq, + delete this.oscillator, + (e = "brown" === t ? o : "pink" === t ? i : n), + (this.buffer = e); + }), + (p5.Noise.prototype = Object.create(p5.Oscillator.prototype)); + var n = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0; + i < t; + i++ + ) + n[i] = 2 * Math.random() - 1; + return (e.type = "white"), e; + })(), + i = (function () { + var t, + e, + n, + i, + o, + r, + s, + a = 2 * l.audiocontext.sampleRate, + u = l.audiocontext.createBuffer(1, a, l.audiocontext.sampleRate), + p = u.getChannelData(0); + t = e = n = i = o = r = s = 0; + for (var c = 0; c < a; c++) { + var h = 2 * Math.random() - 1; + (t = 0.99886 * t + 0.0555179 * h), + (e = 0.99332 * e + 0.0750759 * h), + (n = 0.969 * n + 0.153852 * h), + (i = 0.8665 * i + 0.3104856 * h), + (o = 0.55 * o + 0.5329522 * h), + (r = -0.7616 * r - 0.016898 * h), + (p[c] = t + e + n + i + o + r + s + 0.5362 * h), + (p[c] *= 0.11), + (s = 0.115926 * h); + } + return (u.type = "pink"), u; + })(), + o = (function () { + for ( + var t = 2 * l.audiocontext.sampleRate, + e = l.audiocontext.createBuffer( + 1, + t, + l.audiocontext.sampleRate + ), + n = e.getChannelData(0), + i = 0, + o = 0; + o < t; + o++ + ) { + var r = 2 * Math.random() - 1; + (n[o] = (i + 0.02 * r) / 1.02), (i = n[o]), (n[o] *= 3.5); + } + return (e.type = "brown"), e; + })(); + (p5.Noise.prototype.setType = function (t) { + switch (t) { + case "white": + this.buffer = n; + break; + case "pink": + this.buffer = i; + break; + case "brown": + this.buffer = o; + break; + default: + this.buffer = n; + } + if (this.started) { + var e = l.audiocontext.currentTime; + this.stop(e), this.start(e + 0.01); + } + }), + (p5.Noise.prototype.getType = function () { + return this.buffer.type; + }), + (p5.Noise.prototype.start = function () { + this.started && this.stop(), + (this.noise = l.audiocontext.createBufferSource()), + (this.noise.buffer = this.buffer), + (this.noise.loop = !0), + this.noise.connect(this.output); + var t = l.audiocontext.currentTime; + this.noise.start(t), (this.started = !0); + }), + (p5.Noise.prototype.stop = function () { + var t = l.audiocontext.currentTime; + this.noise && (this.noise.stop(t), (this.started = !1)); + }), + (p5.Noise.prototype.dispose = function () { + var t = l.audiocontext.currentTime, + e = l.soundArray.indexOf(this); + l.soundArray.splice(e, 1), + this.noise && (this.noise.disconnect(), this.stop(t)), + this.output && this.output.disconnect(), + this.panner && this.panner.disconnect(), + (this.output = null), + (this.panner = null), + (this.buffer = null), + (this.noise = null); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (r.inputSources = []), + (p5.AudioIn = function (t) { + (this.input = r.audiocontext.createGain()), + (this.output = r.audiocontext.createGain()), + (this.stream = null), + (this.mediaStream = null), + (this.currentSource = null), + (this.enabled = !1), + (this.amplitude = new p5.Amplitude()), + this.output.connect(this.amplitude.input), + (window.MediaStreamTrack && + window.navigator.mediaDevices && + window.navigator.mediaDevices.getUserMedia) || + (t + ? t() + : window.alert( + "This browser does not support MediaStreamTrack and mediaDevices" + )), + r.soundArray.push(this); + }), + (p5.AudioIn.prototype.start = function (e, n) { + var i = this; + this.stream && this.stop(); + var t = r.inputSources[i.currentSource], + o = { + audio: { + sampleRate: r.audiocontext.sampleRate, + echoCancellation: !1, + }, + }; + r.inputSources[this.currentSource] && + (o.audio.deviceId = t.deviceId), + window.navigator.mediaDevices + .getUserMedia(o) + .then(function (t) { + (i.stream = t), + (i.enabled = !0), + (i.mediaStream = r.audiocontext.createMediaStreamSource(t)), + i.mediaStream.connect(i.output), + i.amplitude.setInput(i.output), + e && e(); + }) + .catch(function (t) { + n && n(t); + }); + }), + (p5.AudioIn.prototype.stop = function () { + this.stream && + (this.stream.getTracks().forEach(function (t) { + t.stop(); + }), + this.mediaStream.disconnect(), + delete this.mediaStream, + delete this.stream); + }), + (p5.AudioIn.prototype.connect = function (t) { + t + ? t.hasOwnProperty("input") + ? this.output.connect(t.input) + : t.hasOwnProperty("analyser") + ? this.output.connect(t.analyser) + : this.output.connect(t) + : this.output.connect(r.input); + }), + (p5.AudioIn.prototype.disconnect = function () { + this.output && + (this.output.disconnect(), + this.output.connect(this.amplitude.input)); + }), + (p5.AudioIn.prototype.getLevel = function (t) { + return ( + t && (this.amplitude.smoothing = t), this.amplitude.getLevel() + ); + }), + (p5.AudioIn.prototype.amp = function (t, e) { + if (e) { + var n = e || 0, + i = this.output.gain.value; + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(i, r.audiocontext.currentTime), + this.output.gain.linearRampToValueAtTime( + t, + n + r.audiocontext.currentTime + ); + } else + this.output.gain.cancelScheduledValues( + r.audiocontext.currentTime + ), + this.output.gain.setValueAtTime(t, r.audiocontext.currentTime); + }), + (p5.AudioIn.prototype.getSources = function (i, o) { + return new Promise(function (e, n) { + window.navigator.mediaDevices + .enumerateDevices() + .then(function (t) { + (r.inputSources = t.filter(function (t) { + return "audioinput" === t.kind; + })), + e(r.inputSources), + i && i(r.inputSources); + }) + .catch(function (t) { + n(t), o && o(t); + }); + }); + }), + (p5.AudioIn.prototype.setSource = function (t) { + 0 < r.inputSources.length && + t < r.inputSources.length && + (this.currentSource = t), + this.stream && this.stream.active && this.start(); + }), + (p5.AudioIn.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.stop(), + this.output && this.output.disconnect(), + this.amplitude && this.amplitude.disconnect(), + delete this.amplitude, + delete this.output; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(2), n(52), n(58), n(9)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.CrossFade = function (t) { + this.createInsOuts(2, 1), + (this.a = this.input[0] = new e.Gain()), + (this.b = this.input[1] = new e.Gain()), + (this.fade = new e.Signal( + this.defaultArg(t, 0.5), + e.Type.NormalRange + )), + (this._equalPowerA = new e.EqualPowerGain()), + (this._equalPowerB = new e.EqualPowerGain()), + (this._invert = new e.Expr("1 - $0")), + this.a.connect(this.output), + this.b.connect(this.output), + this.fade.chain(this._equalPowerB, this.b.gain), + this.fade.chain(this._invert, this._equalPowerA, this.a.gain), + this._readOnly("fade"); + }), + e.extend(e.CrossFade), + (e.CrossFade.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._writable("fade"), + this._equalPowerA.dispose(), + (this._equalPowerA = null), + this._equalPowerB.dispose(), + (this._equalPowerB = null), + this.fade.dispose(), + (this.fade = null), + this._invert.dispose(), + (this._invert = null), + this.a.dispose(), + (this.a = null), + this.b.dispose(), + (this.b = null), + this + ); + }), + e.CrossFade + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [ + n(0), + n(7), + n(16), + n(3), + n(53), + n(26), + n(54), + n(25), + n(55), + n(56), + n(57), + ]), + void 0 === + (o = function (u) { + "use strict"; + function n(t, e, n) { + var i = new t(); + return ( + n._eval(e[0]).connect(i, 0, 0), n._eval(e[1]).connect(i, 0, 1), i + ); + } + function i(t, e, n) { + var i = new t(); + return n._eval(e[0]).connect(i, 0, 0), i; + } + function o(t) { + return t ? parseFloat(t) : void 0; + } + function r(t) { + return t && t.args ? parseFloat(t.args) : void 0; + } + return ( + (u.Expr = function () { + var t = this._replacements(Array.prototype.slice.call(arguments)), + e = this._parseInputs(t); + (this._nodes = []), (this.input = new Array(e)); + for (var n = 0; n < e; n++) + this.input[n] = this.context.createGain(); + var i, + o = this._parseTree(t); + try { + i = this._eval(o); + } catch (e) { + throw ( + (this._disposeNodes(), + new Error("Tone.Expr: Could evaluate expression: " + t)) + ); + } + this.output = i; + }), + u.extend(u.Expr, u.SignalBase), + (u.Expr._Expressions = { + value: { + signal: { + regexp: /^\d+\.\d+|^\d+/, + method: function (t) { + return new u.Signal(o(t)); + }, + }, + input: { + regexp: /^\$\d/, + method: function (t, e) { + return e.input[o(t.substr(1))]; + }, + }, + }, + glue: { + "(": { regexp: /^\(/ }, + ")": { regexp: /^\)/ }, + ",": { regexp: /^,/ }, + }, + func: { + abs: { regexp: /^abs/, method: i.bind(this, u.Abs) }, + mod: { + regexp: /^mod/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Modulo(n); + return e._eval(t[0]).connect(i), i; + }, + }, + pow: { + regexp: /^pow/, + method: function (t, e) { + var n = r(t[1]), + i = new u.Pow(n); + return e._eval(t[0]).connect(i), i; + }, + }, + a2g: { + regexp: /^a2g/, + method: function (t, e) { + var n = new u.AudioToGain(); + return e._eval(t[0]).connect(n), n; + }, + }, + }, + binary: { + "+": { + regexp: /^\+/, + precedence: 1, + method: n.bind(this, u.Add), + }, + "-": { + regexp: /^\-/, + precedence: 1, + method: function (t, e) { + return 1 === t.length + ? i(u.Negate, t, e) + : n(u.Subtract, t, e); + }, + }, + "*": { + regexp: /^\*/, + precedence: 0, + method: n.bind(this, u.Multiply), + }, + }, + unary: { + "-": { regexp: /^\-/, method: i.bind(this, u.Negate) }, + "!": { regexp: /^\!/, method: i.bind(this, u.NOT) }, + }, + }), + (u.Expr.prototype._parseInputs = function (t) { + var e = t.match(/\$\d/g), + n = 0; + if (null !== e) + for (var i = 0; i < e.length; i++) { + var o = parseInt(e[i].substr(1)) + 1; + n = Math.max(n, o); + } + return n; + }), + (u.Expr.prototype._replacements = function (t) { + for (var e = t.shift(), n = 0; n < t.length; n++) + e = e.replace(/\%/i, t[n]); + return e; + }), + (u.Expr.prototype._tokenize = function (t) { + for (var e = -1, n = []; 0 < t.length; ) { + var i = o((t = t.trim())); + n.push(i), (t = t.substr(i.value.length)); + } + function o(t) { + for (var e in u.Expr._Expressions) { + var n = u.Expr._Expressions[e]; + for (var i in n) { + var o = n[i], + r = o.regexp, + s = t.match(r); + if (null !== s) + return { type: e, value: s[0], method: o.method }; + } + } + throw new SyntaxError("Tone.Expr: Unexpected token " + t); + } + return { + next: function () { + return n[++e]; + }, + peek: function () { + return n[e + 1]; + }, + }; + }), + (u.Expr.prototype._parseTree = function (t) { + var i = this._tokenize(t), + s = this.isUndef.bind(this); + function o(t, e) { + return !s(t) && "glue" === t.type && t.value === e; + } + function r(t, e, n) { + var i = u.Expr._Expressions[e]; + if (!s(t)) + for (var o in i) { + var r = i[o]; + if (r.regexp.test(t.value)) { + if (s(n)) return !0; + if (r.precedence === n) return !0; + } + } + return !1; + } + function a(t) { + var e; + s(t) && (t = 5), + (e = + t < 0 + ? (function t() { + var e, n; + return r((e = i.peek()), "unary") + ? ((e = i.next()), + (n = t()), + { + operator: e.value, + method: e.method, + args: [n], + }) + : (function () { + var t, e; + if (((t = i.peek()), s(t))) + throw new SyntaxError( + "Tone.Expr: Unexpected termination of expression" + ); + if ("func" === t.type) + return (function (t) { + var e = []; + if (!o(i.next(), "(")) + throw new SyntaxError( + 'Tone.Expr: Expected ( in a function call "' + + t.value + + '"' + ); + if ( + (o(i.peek(), ")") || + (e = (function () { + for ( + var t, e = []; + (t = a()), + !s(t) && + (e.push(t), o(i.peek(), ",")); + + ) + i.next(); + return e; + })()), + o(i.next(), ")")) + ) + return { + method: t.method, + args: e, + name: name, + }; + throw new SyntaxError( + 'Tone.Expr: Expected ) in a function call "' + + t.value + + '"' + ); + })((t = i.next())); + if ("value" === t.type) + return { + method: (t = i.next()).method, + args: t.value, + }; + if (o(t, "(")) { + if ( + (i.next(), + (e = a()), + !o((t = i.next()), ")")) + ) + throw new SyntaxError("Expected )"); + return e; + } + throw new SyntaxError( + "Tone.Expr: Parse error, cannot process token " + + t.value + ); + })(); + })() + : a(t - 1)); + for (var n = i.peek(); r(n, "binary", t); ) + (e = { + operator: (n = i.next()).value, + method: n.method, + args: [e, a(t - 1)], + }), + (n = i.peek()); + return e; + } + return a(); + }), + (u.Expr.prototype._eval = function (t) { + if (!this.isUndef(t)) { + var e = t.method(t.args, this); + return this._nodes.push(e), e; + } + }), + (u.Expr.prototype._disposeNodes = function () { + for (var t = 0; t < this._nodes.length; t++) { + var e = this._nodes[t]; + this.isFunction(e.dispose) + ? e.dispose() + : this.isFunction(e.disconnect) && e.disconnect(), + (e = null), + (this._nodes[t] = null); + } + this._nodes = null; + }), + (u.Expr.prototype.dispose = function () { + u.prototype.dispose.call(this), this._disposeNodes(); + }), + u.Expr + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(26), n(16), n(2)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.GreaterThan = function (t) { + this.createInsOuts(2, 0), + (this._param = this.input[0] = new e.Subtract(t)), + (this.input[1] = this._param.input[1]), + (this._gtz = this.output = new e.GreaterThanZero()), + this._param.connect(this._gtz); + }), + e.extend(e.GreaterThan, e.Signal), + (e.GreaterThan.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._param.dispose(), + (this._param = null), + this._gtz.dispose(), + (this._gtz = null), + this + ); + }), + e.GreaterThan + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(19)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.Abs = function () { + this._abs = + this.input = + this.output = + new t.WaveShaper(function (t) { + return 0 === t ? 0 : Math.abs(t); + }, 127); + }), + t.extend(t.Abs, t.SignalBase), + (t.Abs.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._abs.dispose(), + (this._abs = null), + this + ); + }), + t.Abs + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(3), n(16)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Modulo = function (t) { + this.createInsOuts(1, 0), + (this._shaper = new e.WaveShaper(Math.pow(2, 16))), + (this._multiply = new e.Multiply()), + (this._subtract = this.output = new e.Subtract()), + (this._modSignal = new e.Signal(t)), + this.input.fan(this._shaper, this._subtract), + this._modSignal.connect(this._multiply, 0, 0), + this._shaper.connect(this._multiply, 0, 1), + this._multiply.connect(this._subtract, 0, 1), + this._setWaveShaper(t); + }), + e.extend(e.Modulo, e.SignalBase), + (e.Modulo.prototype._setWaveShaper = function (e) { + this._shaper.setMap(function (t) { + return Math.floor((t + 1e-4) / e); + }); + }), + Object.defineProperty(e.Modulo.prototype, "value", { + get: function () { + return this._modSignal.value; + }, + set: function (t) { + (this._modSignal.value = t), this._setWaveShaper(t); + }, + }), + (e.Modulo.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._shaper.dispose(), + (this._shaper = null), + this._multiply.dispose(), + (this._multiply = null), + this._subtract.dispose(), + (this._subtract = null), + this._modSignal.dispose(), + (this._modSignal = null), + this + ); + }), + e.Modulo + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.Pow = function (t) { + (this._exp = this.defaultArg(t, 1)), + (this._expScaler = + this.input = + this.output = + new e.WaveShaper(this._expFunc(this._exp), 8192)); + }), + e.extend(e.Pow, e.SignalBase), + Object.defineProperty(e.Pow.prototype, "value", { + get: function () { + return this._exp; + }, + set: function (t) { + (this._exp = t), + this._expScaler.setMap(this._expFunc(this._exp)); + }, + }), + (e.Pow.prototype._expFunc = function (e) { + return function (t) { + return Math.pow(Math.abs(t), e); + }; + }), + (e.Pow.prototype.dispose = function () { + return ( + e.prototype.dispose.call(this), + this._expScaler.dispose(), + (this._expScaler = null), + this + ); + }), + e.Pow + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5), n(2)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.AudioToGain = function () { + this._norm = + this.input = + this.output = + new t.WaveShaper(function (t) { + return (t + 1) / 2; + }); + }), + t.extend(t.AudioToGain, t.SignalBase), + (t.AudioToGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._norm.dispose(), + (this._norm = null), + this + ); + }), + t.AudioToGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(5)]), + void 0 === + (o = function (t) { + "use strict"; + return ( + (t.EqualPowerGain = function () { + this._eqPower = + this.input = + this.output = + new t.WaveShaper( + function (t) { + return Math.abs(t) < 0.001 ? 0 : this.equalPowerScale(t); + }.bind(this), + 4096 + ); + }), + t.extend(t.EqualPowerGain, t.SignalBase), + (t.EqualPowerGain.prototype.dispose = function () { + return ( + t.prototype.dispose.call(this), + this._eqPower.dispose(), + (this._eqPower = null), + this + ); + }), + t.EqualPowerGain + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var r = i(4), + n = i(60); + return ( + (p5.EQ = function (t) { + var e, n, i; + r.call(this), + (e = 3 === (t = 3 === t || 8 === t ? t : 3) ? Math.pow(2, 3) : 2), + (this.bands = []); + for (var o = 0; o < t; o++) + (i = + o === t - 1 + ? ((n = 21e3), 0.01) + : 0 === o + ? ((n = 100), 0.1) + : ((n = + 1 === o + ? 3 === t + ? 360 * e + : 360 + : this.bands[o - 1].freq() * e), + 1)), + (this.bands[o] = this._newBand(n, i)), + 0 < o + ? this.bands[o - 1].connect(this.bands[o].biquad) + : this.input.connect(this.bands[o].biquad); + this.bands[t - 1].connect(this.output); + }), + (p5.EQ.prototype = Object.create(r.prototype)), + (p5.EQ.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.EQ.prototype.set = function () { + if (arguments.length === 2 * this.bands.length) + for (var t = 0; t < arguments.length; t += 2) + this.bands[t / 2].freq(arguments[t]), + this.bands[t / 2].gain(arguments[t + 1]); + }), + (p5.EQ.prototype._newBand = function (t, e) { + return new n(t, e); + }), + (p5.EQ.prototype.dispose = function () { + if ((r.prototype.dispose.apply(this), this.bands)) { + for (; 0 < this.bands.length; ) this.bands.pop().dispose(); + delete this.bands; + } + }), + p5.EQ + ); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, o) { + "use strict"; + var n; + void 0 === + (n = function (t) { + function e(t, e) { + n.call(this, "peaking"), + this.disconnect(), + this.set(t, e), + (this.biquad.gain.value = 0), + delete this.input, + delete this.output, + delete this._drywet, + delete this.wet; + } + var n = o(15), + i = o(1); + return ( + ((e.prototype = Object.create(n.prototype)).amp = function () {}), + (e.prototype.drywet = function () {}), + (e.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.biquad + ? this.biquad.connect(e.input ? e.input : e) + : this.output.connect(e.input ? e.input : e); + }), + (e.prototype.disconnect = function () { + this.biquad && this.biquad.disconnect(); + }), + (e.prototype.dispose = function () { + var t = i.soundArray.indexOf(this); + i.soundArray.splice(t, 1), this.disconnect(), delete this.biquad; + }), + e + ); + }.call(e, o, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + n(1); + var e = n(4); + return ( + (p5.Panner3D = function () { + e.call(this), + (this.panner = this.ac.createPanner()), + (this.panner.panningModel = "HRTF"), + (this.panner.distanceModel = "linear"), + this.panner.connect(this.output), + this.input.connect(this.panner); + }), + (p5.Panner3D.prototype = Object.create(e.prototype)), + (p5.Panner3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Panner3D.prototype.set = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.panner.positionX.value, + this.panner.positionY.value, + this.panner.positionZ.value, + ] + ); + }), + (p5.Panner3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionX.value = t), + this.panner.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionX), + this.panner.positionX.value + ); + }), + (p5.Panner3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionY.value = t), + this.panner.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionY), + this.panner.positionY.value + ); + }), + (p5.Panner3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.positionZ.value = t), + this.panner.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.positionZ), + this.panner.positionZ.value + ); + }), + (p5.Panner3D.prototype.orient = function (t, e, n, i) { + return ( + this.orientX(t, i), + this.orientY(e, i), + this.orientZ(n, i), + [ + this.panner.orientationX.value, + this.panner.orientationY.value, + this.panner.orientationZ.value, + ] + ); + }), + (p5.Panner3D.prototype.orientX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationX.value = t), + this.panner.orientationX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationX), + this.panner.orientationX.value + ); + }), + (p5.Panner3D.prototype.orientY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationY.value = t), + this.panner.orientationY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationY), + this.panner.orientationY.value + ); + }), + (p5.Panner3D.prototype.orientZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.panner.orientationZ.value = t), + this.panner.orientationZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.panner.orientationZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.panner.orientationZ), + this.panner.orientationZ.value + ); + }), + (p5.Panner3D.prototype.setFalloff = function (t, e) { + this.maxDist(t), this.rolloff(e); + }), + (p5.Panner3D.prototype.maxDist = function (t) { + return ( + "number" == typeof t && (this.panner.maxDistance = t), + this.panner.maxDistance + ); + }), + (p5.Panner3D.prototype.rolloff = function (t) { + return ( + "number" == typeof t && (this.panner.rolloffFactor = t), + this.panner.rolloffFactor + ); + }), + (p5.Panner3D.dispose = function () { + e.prototype.dispose.apply(this), + this.panner && (this.panner.disconnect(), delete this.panner); + }), + p5.Panner3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var e = n(1); + n(4); + return ( + (p5.Listener3D = function (t) { + (this.ac = e.audiocontext), (this.listener = this.ac.listener); + }), + (p5.Listener3D.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Listener3D.prototype.position = function (t, e, n, i) { + return ( + this.positionX(t, i), + this.positionY(e, i), + this.positionZ(n, i), + [ + this.listener.positionX.value, + this.listener.positionY.value, + this.listener.positionZ.value, + ] + ); + }), + (p5.Listener3D.prototype.positionX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionX.value = t), + this.listener.positionX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionX), + this.listener.positionX.value + ); + }), + (p5.Listener3D.prototype.positionY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionY.value = t), + this.listener.positionY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionY), + this.listener.positionY.value + ); + }), + (p5.Listener3D.prototype.positionZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.positionZ.value = t), + this.listener.positionZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.positionZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.positionZ), + this.listener.positionZ.value + ); + }), + (p5.Listener3D.prototype.orient = function (t, e, n, i, o, r, s) { + return ( + 3 === arguments.length || 4 === arguments.length + ? ((s = i), this.orientForward(t, e, n, s)) + : (6 !== arguments.length && 7 !== arguments) || + (this.orientForward(t, e, n), this.orientUp(i, o, r, s)), + [ + this.listener.forwardX.value, + this.listener.forwardY.value, + this.listener.forwardZ.value, + this.listener.upX.value, + this.listener.upY.value, + this.listener.upZ.value, + ] + ); + }), + (p5.Listener3D.prototype.orientForward = function (t, e, n, i) { + return ( + this.forwardX(t, i), + this.forwardY(e, i), + this.forwardZ(n, i), + [ + this.listener.forwardX, + this.listener.forwardY, + this.listener.forwardZ, + ] + ); + }), + (p5.Listener3D.prototype.orientUp = function (t, e, n, i) { + return ( + this.upX(t, i), + this.upY(e, i), + this.upZ(n, i), + [this.listener.upX, this.listener.upY, this.listener.upZ] + ); + }), + (p5.Listener3D.prototype.forwardX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardX.value = t), + this.listener.forwardX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardX), + this.listener.forwardX.value + ); + }), + (p5.Listener3D.prototype.forwardY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardY.value = t), + this.listener.forwardY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardY), + this.listener.forwardY.value + ); + }), + (p5.Listener3D.prototype.forwardZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.forwardZ.value = t), + this.listener.forwardZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.forwardZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.forwardZ), + this.listener.forwardZ.value + ); + }), + (p5.Listener3D.prototype.upX = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upX.value = t), + this.listener.upX.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upX.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upX), + this.listener.upX.value + ); + }), + (p5.Listener3D.prototype.upY = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upY.value = t), + this.listener.upY.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upY.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upY), + this.listener.upY.value + ); + }), + (p5.Listener3D.prototype.upZ = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.listener.upZ.value = t), + this.listener.upZ.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.listener.upZ.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : t && t.connect(this.listener.upZ), + this.listener.upZ.value + ); + }), + p5.Listener3D + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, i) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = i(15), + n = i(4); + (p5.Delay = function () { + n.call(this), + (this._split = this.ac.createChannelSplitter(2)), + (this._merge = this.ac.createChannelMerger(2)), + (this._leftGain = this.ac.createGain()), + (this._rightGain = this.ac.createGain()), + (this.leftDelay = this.ac.createDelay()), + (this.rightDelay = this.ac.createDelay()), + (this._leftFilter = new e()), + (this._rightFilter = new e()), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._leftFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._rightFilter.biquad.frequency.setValueAtTime( + 1200, + this.ac.currentTime + ), + this._leftFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this._rightFilter.biquad.Q.setValueAtTime(0.3, this.ac.currentTime), + this.input.connect(this._split), + this.leftDelay.connect(this._leftGain), + this.rightDelay.connect(this._rightGain), + this._leftGain.connect(this._leftFilter.input), + this._rightGain.connect(this._rightFilter.input), + this._merge.connect(this.wet), + this._leftFilter.biquad.gain.setValueAtTime(1, this.ac.currentTime), + this._rightFilter.biquad.gain.setValueAtTime( + 1, + this.ac.currentTime + ), + this.setType(0), + (this._maxDelay = this.leftDelay.delayTime.maxValue), + this.feedback(0.5); + }), + (p5.Delay.prototype = Object.create(n.prototype)), + (p5.Delay.prototype.process = function (t, e, n, i) { + var o = n || 0, + r = e || 0; + if (1 <= o) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + if (r >= this._maxDelay) + throw new Error( + "Delay Time exceeds maximum delay time of " + + this._maxDelay + + " second." + ); + t.connect(this.input), + this.leftDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + this.rightDelay.delayTime.setValueAtTime(r, this.ac.currentTime), + (this._leftGain.gain.value = o), + (this._rightGain.gain.value = o), + i && (this._leftFilter.freq(i), this._rightFilter.freq(i)); + }), + (p5.Delay.prototype.delayTime = function (t) { + "number" != typeof t + ? (t.connect(this.leftDelay.delayTime), + t.connect(this.rightDelay.delayTime)) + : (this.leftDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.rightDelay.delayTime.cancelScheduledValues( + this.ac.currentTime + ), + this.leftDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + ), + this.rightDelay.delayTime.linearRampToValueAtTime( + t, + this.ac.currentTime + )); + }), + (p5.Delay.prototype.feedback = function (t) { + if (t && "number" != typeof t) + t.connect(this._leftGain.gain), t.connect(this._rightGain.gain); + else { + if (1 <= t) + throw new Error( + "Feedback value will force a positive feedback loop." + ); + "number" == typeof t && + ((this._leftGain.gain.value = t), + (this._rightGain.gain.value = t)); + } + return this._leftGain.gain.value; + }), + (p5.Delay.prototype.filter = function (t, e) { + this._leftFilter.set(t, e), this._rightFilter.set(t, e); + }), + (p5.Delay.prototype.setType = function (t) { + switch ( + (1 === t && (t = "pingPong"), + this._split.disconnect(), + this._leftFilter.disconnect(), + this._rightFilter.disconnect(), + this._split.connect(this.leftDelay, 0), + this._split.connect(this.rightDelay, 1), + t) + ) { + case "pingPong": + this._rightFilter.setType(this._leftFilter.biquad.type), + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.rightDelay), + this._rightFilter.output.connect(this.leftDelay); + break; + default: + this._leftFilter.output.connect(this._merge, 0, 0), + this._rightFilter.output.connect(this._merge, 0, 1), + this._leftFilter.output.connect(this.leftDelay), + this._rightFilter.output.connect(this.rightDelay); + } + }), + (p5.Delay.prototype.dispose = function () { + n.prototype.dispose.apply(this), + this._split.disconnect(), + this._leftFilter.dispose(), + this._rightFilter.dispose(), + this._merge.disconnect(), + this._leftGain.disconnect(), + this._rightGain.disconnect(), + this.leftDelay.disconnect(), + this.rightDelay.disconnect(), + (this._split = void 0), + (this._leftFilter = void 0), + (this._rightFilter = void 0), + (this._merge = void 0), + (this._leftGain = void 0), + (this._rightGain = void 0), + (this.leftDelay = void 0), + (this.rightDelay = void 0); + }); + }.call(e, i, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var p = n(11), + e = n(4); + (p5.Reverb = function () { + e.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + (this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse(); + }), + (p5.Reverb.prototype = Object.create(e.prototype)), + (p5.Reverb.prototype._initConvolverNode = function () { + (this.convolverNode = this.ac.createConvolver()), + this.input.connect(this.convolverNode), + this.convolverNode.connect(this.wet); + }), + (p5.Reverb.prototype._teardownConvolverNode = function () { + this.convolverNode && + (this.convolverNode.disconnect(), delete this.convolverNode); + }), + (p5.Reverb.prototype._setBuffer = function (t) { + this._teardownConvolverNode(), + this._initConvolverNode(), + (this.convolverNode.buffer = t); + }), + (p5.Reverb.prototype.process = function (t, e, n, i) { + t.connect(this.input); + var o = !1; + e && ((this._seconds = e), (o = !0)), + n && (this._decay = n), + i && (this._reverse = i), + o && this._buildImpulse(); + }), + (p5.Reverb.prototype.set = function (t, e, n) { + var i = !1; + t && ((this._seconds = t), (i = !0)), + e && (this._decay = e), + n && (this._reverse = n), + i && this._buildImpulse(); + }), + (p5.Reverb.prototype._buildImpulse = function () { + var t, + e, + n = this.ac.sampleRate, + i = n * this._seconds, + o = this._decay, + r = this.ac.createBuffer(2, i, n), + s = r.getChannelData(0), + a = r.getChannelData(1); + for (e = 0; e < i; e++) + (t = this._reverse ? i - e : e), + (s[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)), + (a[e] = (2 * Math.random() - 1) * Math.pow(1 - t / i, o)); + this._setBuffer(r); + }), + (p5.Reverb.prototype.dispose = function () { + e.prototype.dispose.apply(this), this._teardownConvolverNode(); + }), + (p5.Convolver = function (t, e, n) { + p5.Reverb.call(this), + this._initConvolverNode(), + (this.input.gain.value = 0.5), + t + ? ((this.impulses = []), this._loadBuffer(t, e, n)) + : ((this._seconds = 3), + (this._decay = 2), + (this._reverse = !1), + this._buildImpulse()); + }), + (p5.Convolver.prototype = Object.create(p5.Reverb.prototype)), + p5.prototype.registerPreloadMethod("createConvolver", p5.prototype), + (p5.prototype.createConvolver = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ); + var i = this, + o = new p5.Convolver( + t, + function (t) { + "function" == typeof e && e(t), + "function" == typeof i._decrementPreload && + i._decrementPreload(); + }, + n + ); + return (o.impulses = []), o; + }), + (p5.Convolver.prototype._loadBuffer = function (i, o, n) { + i = p5.prototype._checkFileFormats(i); + var r = this, + s = new Error().stack, + a = p5.prototype.getAudioContext(), + u = new XMLHttpRequest(); + u.open("GET", i, !0), + (u.responseType = "arraybuffer"), + (u.onload = function () { + if (200 === u.status) + a.decodeAudioData( + u.response, + function (t) { + var e = {}, + n = i.split("/"); + (e.name = n[n.length - 1]), + (e.audioBuffer = t), + r.impulses.push(e), + r._setBuffer(e.audioBuffer), + o && o(e); + }, + function () { + var t = new p("decodeAudioData", s, r.url), + e = + "AudioContext error at decodeAudioData for " + r.url; + n && ((t.msg = e), n(t)); + } + ); + else { + var t = new p("loadConvolver", s, r.url), + e = + "Unable to load " + + r.url + + ". The request status was: " + + u.status + + " (" + + u.statusText + + ")"; + n && ((t.message = e), n(t)); + } + }), + (u.onerror = function () { + var t = new p("loadConvolver", s, r.url), + e = + "There was no response from the server at " + + r.url + + ". Check the url and internet connectivity."; + n && ((t.message = e), n(t)); + }), + u.send(); + }), + (p5.Convolver.prototype.set = null), + (p5.Convolver.prototype.process = function (t) { + t.connect(this.input); + }), + (p5.Convolver.prototype.impulses = []), + (p5.Convolver.prototype.addImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.resetImpulse = function (t, e, n) { + -1 < window.location.origin.indexOf("file://") && + "undefined" === window.cordova && + alert( + "This sketch may require a server to load external files. Please see http://bit.ly/1qcInwS" + ), + (this.impulses = []), + this._loadBuffer(t, e, n); + }), + (p5.Convolver.prototype.toggleImpulse = function (t) { + if ( + ("number" == typeof t && + t < this.impulses.length && + this._setBuffer(this.impulses[t].audioBuffer), + "string" == typeof t) + ) + for (var e = 0; e < this.impulses.length; e++) + if (this.impulses[e].name === t) { + this._setBuffer(this.impulses[e].audioBuffer); + break; + } + }), + (p5.Convolver.prototype.dispose = function () { + for (var t in (p5.Reverb.prototype.dispose.apply(this), + this.impulses)) + this.impulses[t] && (this.impulses[t] = null); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + e = n(27); + (p5.Metro = function () { + (this.clock = new e({ callback: this.ontick.bind(this) })), + (this.syncedParts = []), + (this.bpm = 120), + this._init(), + (this.prevTick = 0), + (this.tatumTime = 0), + (this.tickCallback = function () {}); + }), + (p5.Metro.prototype.ontick = function (t) { + var e = t - this.prevTick, + i = t - r.audiocontext.currentTime; + if (!(e - this.tatumTime <= -0.02)) { + this.prevTick = t; + var o = this; + this.syncedParts.forEach(function (t) { + t.isPlaying && + (t.incrementStep(i), + t.phrases.forEach(function (t) { + var e = t.sequence, + n = o.metroTicks % e.length; + 0 !== e[n] && + (o.metroTicks < e.length || !t.looping) && + t.callback(i, e[n]); + })); + }), + (this.metroTicks += 1), + this.tickCallback(i); + } + }), + (p5.Metro.prototype.setBPM = function (t, e) { + var n = 60 / (t * this.tatums), + i = r.audiocontext.currentTime; + this.tatumTime = n; + e = e || 0; + this.clock.frequency.setValueAtTime(this.clock.frequency.value, i), + this.clock.frequency.linearRampToValueAtTime(t, i + e), + (this.bpm = t); + }), + (p5.Metro.prototype.getBPM = function () { + return (this.clock.getRate() / this.tatums) * 60; + }), + (p5.Metro.prototype._init = function () { + this.metroTicks = 0; + }), + (p5.Metro.prototype.resetSync = function (t) { + this.syncedParts = [t]; + }), + (p5.Metro.prototype.pushSync = function (t) { + this.syncedParts.push(t); + }), + (p5.Metro.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.start(n + e), this.setBPM(this.bpm); + }), + (p5.Metro.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.clock.stop(n + e); + }), + (p5.Metro.prototype.beatLength = function (t) { + this.tatums = 1 / t / 4; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i, o; + (i = [n(0), n(24), n(8)]), + void 0 === + (o = function (e) { + "use strict"; + return ( + (e.TimelineState = function (t) { + e.Timeline.call(this), (this._initial = t); + }), + e.extend(e.TimelineState, e.Timeline), + (e.TimelineState.prototype.getValueAtTime = function (t) { + var e = this.get(t); + return null !== e ? e.state : this._initial; + }), + (e.TimelineState.prototype.setStateAtTime = function (t, e) { + this.add({ state: t, time: e }); + }), + e.TimelineState + ); + }.apply(e, i)) || (t.exports = o); + }, + function (t, e, r) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var i = r(1), + o = 120; + function n(t) { + t.currentPart++, + t.currentPart >= t.parts.length + ? ((t.scoreStep = 0), t.onended()) + : ((t.scoreStep = 0), + t.parts[t.currentPart - 1].stop(), + t.parts[t.currentPart].start()); + } + (p5.prototype.setBPM = function (t, e) { + for (var n in ((o = t), i.parts)) + i.parts[n] && i.parts[n].setBPM(t, e); + }), + (p5.Phrase = function (t, e, n) { + (this.phraseStep = 0), + (this.name = t), + (this.callback = e), + (this.sequence = n); + }), + (p5.Part = function (t, e) { + (this.length = t || 0), + (this.partStep = 0), + (this.phrases = []), + (this.isPlaying = !1), + this.noLoop(), + (this.tatums = e || 0.0625), + (this.metro = new p5.Metro()), + this.metro._init(), + this.metro.beatLength(this.tatums), + this.metro.setBPM(o), + i.parts.push(this), + (this.callback = function () {}); + }), + (p5.Part.prototype.setBPM = function (t, e) { + this.metro.setBPM(t, e); + }), + (p5.Part.prototype.getBPM = function () { + return this.metro.getBPM(); + }), + (p5.Part.prototype.start = function (t) { + if (!this.isPlaying) { + (this.isPlaying = !0), this.metro.resetSync(this); + var e = t || 0; + this.metro.start(e); + } + }), + (p5.Part.prototype.loop = function (t) { + (this.looping = !0), + (this.onended = function () { + this.partStep = 0; + }); + var e = t || 0; + this.start(e); + }), + (p5.Part.prototype.noLoop = function () { + (this.looping = !1), + (this.onended = function () { + this.stop(); + }); + }), + (p5.Part.prototype.stop = function (t) { + (this.partStep = 0), this.pause(t); + }), + (p5.Part.prototype.pause = function (t) { + this.isPlaying = !1; + var e = t || 0; + this.metro.stop(e); + }), + (p5.Part.prototype.addPhrase = function (t, e, n) { + var i; + if (3 === arguments.length) i = new p5.Phrase(t, e, n); + else { + if (!(t instanceof p5.Phrase)) + throw "invalid input. addPhrase accepts name, callback, array or a p5.Phrase"; + i = t; + } + this.phrases.push(i), + i.sequence.length > this.length && + (this.length = i.sequence.length); + }), + (p5.Part.prototype.removePhrase = function (t) { + for (var e in this.phrases) + this.phrases[e].name === t && this.phrases.splice(e, 1); + }), + (p5.Part.prototype.getPhrase = function (t) { + for (var e in this.phrases) + if (this.phrases[e].name === t) return this.phrases[e]; + }), + (p5.Part.prototype.replaceSequence = function (t, e) { + for (var n in this.phrases) + this.phrases[n].name === t && (this.phrases[n].sequence = e); + }), + (p5.Part.prototype.incrementStep = function (t) { + this.partStep < this.length - 1 + ? (this.callback(t), (this.partStep += 1)) + : this.looping || + this.partStep !== this.length - 1 || + this.onended(); + }), + (p5.Part.prototype.onStep = function (t) { + this.callback = t; + }), + (p5.Score = function () { + (this.parts = []), (this.currentPart = 0); + var t = this; + for (var e in arguments) + arguments[e] && + this.parts[e] && + ((this.parts[e] = arguments[e]), + (this.parts[e].nextPart = this.parts[e + 1]), + (this.parts[e].onended = function () { + t.resetPart(e), n(t); + })); + this.looping = !1; + }), + (p5.Score.prototype.onended = function () { + this.looping + ? this.parts[0].start() + : (this.parts[this.parts.length - 1].onended = function () { + this.stop(), this.resetParts(); + }), + (this.currentPart = 0); + }), + (p5.Score.prototype.start = function () { + this.parts[this.currentPart].start(), (this.scoreStep = 0); + }), + (p5.Score.prototype.stop = function () { + this.parts[this.currentPart].stop(), + (this.currentPart = 0), + (this.scoreStep = 0); + }), + (p5.Score.prototype.pause = function () { + this.parts[this.currentPart].stop(); + }), + (p5.Score.prototype.loop = function () { + (this.looping = !0), this.start(); + }), + (p5.Score.prototype.noLoop = function () { + this.looping = !1; + }), + (p5.Score.prototype.resetParts = function () { + var e = this; + this.parts.forEach(function (t) { + e.resetParts[t]; + }); + }), + (p5.Score.prototype.resetPart = function (t) { + for (var e in (this.parts[t].stop(), + (this.parts[t].partStep = 0), + this.parts[t].phrases)) + this.parts[t] && (this.parts[t].phrases[e].phraseStep = 0); + }), + (p5.Score.prototype.setBPM = function (t, e) { + for (var n in this.parts) + this.parts[n] && this.parts[n].setBPM(t, e); + }); + }.call(e, r, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1), + i = n(27); + return ( + (p5.SoundLoop = function (t, e) { + (this.callback = t), + (this.musicalTimeMode = "number" != typeof this._interval), + (this._interval = e || 1), + (this._timeSignature = 4), + (this._bpm = 60), + (this.isPlaying = !1), + (this.maxIterations = 1 / 0); + var n = this; + this.clock = new i({ + callback: function (t) { + var e = t - r.audiocontext.currentTime; + 0 < e && n.iterations <= n.maxIterations && n.callback(e); + }, + frequency: this._calcFreq(), + }); + }), + (p5.SoundLoop.prototype.start = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying || (this.clock.start(n + e), (this.isPlaying = !0)); + }), + (p5.SoundLoop.prototype.stop = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.stop(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.pause = function (t) { + var e = t || 0, + n = r.audiocontext.currentTime; + this.isPlaying && (this.clock.pause(n + e), (this.isPlaying = !1)); + }), + (p5.SoundLoop.prototype.syncedStart = function (t, e) { + var n = e || 0, + i = r.audiocontext.currentTime; + if (t.isPlaying) { + if (t.isPlaying) { + var o = t.clock._nextTick - r.audiocontext.currentTime; + this.clock.start(i + o), (this.isPlaying = !0); + } + } else + t.clock.start(i + n), + (t.isPlaying = !0), + this.clock.start(i + n), + (this.isPlaying = !0); + }), + (p5.SoundLoop.prototype._update = function () { + this.clock.frequency.value = this._calcFreq(); + }), + (p5.SoundLoop.prototype._calcFreq = function () { + return "number" == typeof this._interval + ? ((this.musicalTimeMode = !1), 1 / this._interval) + : "string" == typeof this._interval + ? ((this.musicalTimeMode = !0), + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4)) + : void 0; + }), + (p5.SoundLoop.prototype._convertNotation = function (t) { + var e = t.slice(-1); + switch (((t = Number(t.slice(0, -1))), e)) { + case "m": + return this._measure(t); + case "n": + return this._note(t); + } + }), + (p5.SoundLoop.prototype._measure = function (t) { + return t * this._timeSignature; + }), + (p5.SoundLoop.prototype._note = function (t) { + return this._timeSignature / t; + }), + Object.defineProperty(p5.SoundLoop.prototype, "bpm", { + get: function () { + return this._bpm; + }, + set: function (t) { + this.musicalTimeMode, (this._bpm = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "timeSignature", { + get: function () { + return this._timeSignature; + }, + set: function (t) { + this.musicalTimeMode, (this._timeSignature = t), this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "interval", { + get: function () { + return this._interval; + }, + set: function (t) { + (this.musicalTimeMode = "Number" != typeof t), + (this._interval = t), + this._update(); + }, + }), + Object.defineProperty(p5.SoundLoop.prototype, "iterations", { + get: function () { + return this.clock.ticks; + }, + }), + p5.SoundLoop + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + var i; + void 0 === + (i = function (t) { + "use strict"; + n(1); + var e = n(4); + n(11); + return ( + (p5.Compressor = function () { + e.call(this), + (this.compressor = this.ac.createDynamicsCompressor()), + this.input.connect(this.compressor), + this.compressor.connect(this.wet); + }), + (p5.Compressor.prototype = Object.create(e.prototype)), + (p5.Compressor.prototype.process = function (t, e, n, i, o, r) { + t.connect(this.input), this.set(e, n, i, o, r); + }), + (p5.Compressor.prototype.set = function (t, e, n, i, o) { + void 0 !== t && this.attack(t), + void 0 !== e && this.knee(e), + void 0 !== n && this.ratio(n), + void 0 !== i && this.threshold(i), + void 0 !== o && this.release(o); + }), + (p5.Compressor.prototype.attack = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.attack.value = t), + this.compressor.attack.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.attack.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.attack), + this.compressor.attack.value + ); + }), + (p5.Compressor.prototype.knee = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.knee.value = t), + this.compressor.knee.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.knee.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.knee), + this.compressor.knee.value + ); + }), + (p5.Compressor.prototype.ratio = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.ratio.value = t), + this.compressor.ratio.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.ratio.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.ratio), + this.compressor.ratio.value + ); + }), + (p5.Compressor.prototype.threshold = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.threshold.value = t), + this.compressor.threshold.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.threshold.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : void 0 !== t && t.connect(this.compressor.threshold), + this.compressor.threshold.value + ); + }), + (p5.Compressor.prototype.release = function (t, e) { + var n = e || 0; + return ( + "number" == typeof t + ? ((this.compressor.release.value = t), + this.compressor.release.cancelScheduledValues( + this.ac.currentTime + 0.01 + n + ), + this.compressor.release.linearRampToValueAtTime( + t, + this.ac.currentTime + 0.02 + n + )) + : "undefined" != typeof number && + t.connect(this.compressor.release), + this.compressor.release.value + ); + }), + (p5.Compressor.prototype.reduction = function () { + return this.compressor.reduction.value; + }), + (p5.Compressor.prototype.dispose = function () { + e.prototype.dispose.apply(this), + this.compressor && + (this.compressor.disconnect(), delete this.compressor); + }), + p5.Compressor + ); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, a) { + "use strict"; + var n; + void 0 === + (n = function (t) { + var e = a(1), + n = a(6), + i = n.convertToWav, + o = n.safeBufferSize, + r = a(10), + s = e.audiocontext; + (p5.SoundRecorder = function () { + (this.input = s.createGain()), + (this.output = s.createGain()), + (this._inputChannels = 2), + (this._outputChannels = 2); + var t = o(1024); + (this._workletNode = new AudioWorkletNode(s, r.recorderProcessor, { + outputChannelCount: [this._outputChannels], + processorOptions: { + numInputChannels: this._inputChannels, + bufferSize: t, + }, + })), + (this._workletNode.port.onmessage = function (t) { + if ("buffers" === t.data.name) { + var e = [ + new Float32Array(t.data.leftBuffer), + new Float32Array(t.data.rightBuffer), + ]; + this._callback(e); + } + }.bind(this)), + (this._callback = function () {}), + this._workletNode.connect(p5.soundOut._silentNode), + this.setInput(), + e.soundArray.push(this); + }), + (p5.SoundRecorder.prototype.setInput = function (t) { + this.input.disconnect(), + (this.input = null), + (this.input = s.createGain()), + this.input.connect(this._workletNode), + this.input.connect(this.output), + t + ? t.connect(this.input) + : p5.soundOut.output.connect(this.input); + }), + (p5.SoundRecorder.prototype.record = function (e, t, n) { + this._workletNode.port.postMessage({ name: "start", duration: t }), + e && n + ? (this._callback = function (t) { + e.setBuffer(t), n(); + }) + : e && + (this._callback = function (t) { + e.setBuffer(t); + }); + }), + (p5.SoundRecorder.prototype.stop = function () { + this._workletNode.port.postMessage({ name: "stop" }); + }), + (p5.SoundRecorder.prototype.dispose = function () { + var t = e.soundArray.indexOf(this); + e.soundArray.splice(t, 1), + (this._callback = function () {}), + this.input && this.input.disconnect(), + (this.input = null), + (this._workletNode = null); + }), + (p5.prototype.saveSound = function (t, e) { + var n = i(t.buffer); + p5.prototype.writeFile([n], e, "wav"); + }); + }.call(e, a, e, t)) || (t.exports = n); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function () { + (p5.PeakDetect = function (t, e, n, i) { + (this.framesPerPeak = i || 20), + (this.framesSinceLastPeak = 0), + (this.decayRate = 0.95), + (this.threshold = n || 0.35), + (this.cutoff = 0), + (this.cutoffMult = 1.5), + (this.energy = 0), + (this.penergy = 0), + (this.currentValue = 0), + (this.isDetected = !1), + (this.f1 = t || 40), + (this.f2 = e || 2e4), + (this._onPeak = function () {}); + }), + (p5.PeakDetect.prototype.update = function (t) { + var e = (this.energy = t.getEnergy(this.f1, this.f2) / 255); + e > this.cutoff && e > this.threshold && 0 < e - this.penergy + ? (this._onPeak(), + (this.isDetected = !0), + (this.cutoff = e * this.cutoffMult), + (this.framesSinceLastPeak = 0)) + : ((this.isDetected = !1), + this.framesSinceLastPeak <= this.framesPerPeak + ? this.framesSinceLastPeak++ + : ((this.cutoff *= this.decayRate), + (this.cutoff = Math.max(this.cutoff, this.threshold)))), + (this.currentValue = e), + (this.penergy = e); + }), + (p5.PeakDetect.prototype.onPeak = function (t, e) { + var n = this; + n._onPeak = function () { + t(n.energy, e); + }; + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var r = n(1); + (p5.Gain = function () { + (this.ac = r.audiocontext), + (this.input = this.ac.createGain()), + (this.output = this.ac.createGain()), + (this.input.gain.value = 0.5), + this.input.connect(this.output), + r.soundArray.push(this); + }), + (p5.Gain.prototype.setInput = function (t) { + t.connect(this.input); + }), + (p5.Gain.prototype.connect = function (t) { + var e = t || p5.soundOut.input; + this.output.connect(e.input ? e.input : e); + }), + (p5.Gain.prototype.disconnect = function () { + this.output && this.output.disconnect(); + }), + (p5.Gain.prototype.amp = function (t, e, n) { + (e = e || 0), (n = n || 0); + var i = r.audiocontext.currentTime, + o = this.output.gain.value; + this.output.gain.cancelScheduledValues(i), + this.output.gain.linearRampToValueAtTime(o, i + n), + this.output.gain.linearRampToValueAtTime(t, i + n + e); + }), + (p5.Gain.prototype.dispose = function () { + var t = r.soundArray.indexOf(this); + r.soundArray.splice(t, 1), + this.output && (this.output.disconnect(), delete this.output), + this.input && (this.input.disconnect(), delete this.input); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, + function (t, e, n) { + "use strict"; + var i; + void 0 === + (i = function (t) { + var i = n(4); + function o(t) { + for ( + var e, + n = "number" == typeof t ? t : 50, + i = new Float32Array(44100), + o = Math.PI / 180, + r = 0; + r < 44100; + ++r + ) + (e = (2 * r) / 44100 - 1), + (i[r] = ((3 + n) * e * 20 * o) / (Math.PI + n * Math.abs(e))); + return i; + } + (p5.Distortion = function (t, e) { + if ((i.call(this), void 0 === t && (t = 0.25), "number" != typeof t)) + throw new Error("amount must be a number"); + if ((void 0 === e && (e = "2x"), "string" != typeof e)) + throw new Error("oversample must be a String"); + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.waveShaperNode = this.ac.createWaveShaper()), + (this.amount = n), + (this.waveShaperNode.curve = o(n)), + (this.waveShaperNode.oversample = e), + this.input.connect(this.waveShaperNode), + this.waveShaperNode.connect(this.wet); + }), + (p5.Distortion.prototype = Object.create(i.prototype)), + (p5.Distortion.prototype.process = function (t, e, n) { + t.connect(this.input), this.set(e, n); + }), + (p5.Distortion.prototype.set = function (t, e) { + if (t) { + var n = p5.prototype.map(t, 0, 1, 0, 2e3); + (this.amount = n), (this.waveShaperNode.curve = o(n)); + } + e && (this.waveShaperNode.oversample = e); + }), + (p5.Distortion.prototype.getAmount = function () { + return this.amount; + }), + (p5.Distortion.prototype.getOversample = function () { + return this.waveShaperNode.oversample; + }), + (p5.Distortion.prototype.dispose = function () { + i.prototype.dispose.apply(this), + this.waveShaperNode && + (this.waveShaperNode.disconnect(), + (this.waveShaperNode = null)); + }); + }.call(e, n, e, t)) || (t.exports = i); + }, +]); +//# sourceMappingURL=p5.sound.min.js.map