├── icon.png
├── interval-timer.png
├── README.md
├── app.manifest
├── manifest.json
├── images
├── stop.svg
├── play.svg
├── start.svg
├── pause.svg
├── share.svg
├── reset.svg
└── octocat.svg
├── 3rdparty
└── NoSleep.min.js
├── index.html
└── interval-timer.js
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greggman/interval-timer/HEAD/icon.png
--------------------------------------------------------------------------------
/interval-timer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/greggman/interval-timer/HEAD/interval-timer.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Interval Timer
2 |
3 | [Click Here](https://greggman.github.io/interval-timer/)
4 |
5 | A simple interval timer. Settings are saved in the URL so set them to whatever
6 | you want and then make a bookmark.
7 |
8 | ## TO DO
9 |
10 | * Localize?
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app.manifest:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 |
3 | # version 7
4 |
5 | manifest.json
6 | icon.png
7 | images/reset.svg
8 | images/stop.svg
9 | images/start.svg
10 | images/play.svg
11 | images/share.svg
12 | images/pause.svg
13 | images/octocat.svg
14 | interval-timer.js
15 | 3rdparty/NoSleep.min.js
16 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Interval Timer",
3 | "name": "Interval Timer",
4 | "icons": [
5 | {
6 | "src": "icon.png",
7 | "type": "image/png",
8 | "sizes": "128x128"
9 | }
10 | ],
11 | "start_url": "index.html",
12 | "background_color": "#00C",
13 | "theme_color": "#00C",
14 | "display": "standalone"
15 | }
16 |
--------------------------------------------------------------------------------
/images/stop.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/images/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/images/start.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/images/pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/images/share.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/images/reset.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/images/octocat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/3rdparty/NoSleep.min.js:
--------------------------------------------------------------------------------
1 | /*! NoSleep.js v0.7.0 - git.io/vfn01 - Rich Tibbett - MIT license */
2 | (function webpackUniversalModuleDefinition(root, factory) {
3 | if(typeof exports === 'object' && typeof module === 'object')
4 | module.exports = factory();
5 | else if(typeof define === 'function' && define.amd)
6 | define([], factory);
7 | else if(typeof exports === 'object')
8 | exports["NoSleep"] = factory();
9 | else
10 | root["NoSleep"] = factory();
11 | })(this, function() {
12 | return /******/ (function(modules) { // webpackBootstrap
13 | /******/ // The module cache
14 | /******/ var installedModules = {};
15 | /******/
16 | /******/ // The require function
17 | /******/ function __webpack_require__(moduleId) {
18 | /******/
19 | /******/ // Check if module is in cache
20 | /******/ if(installedModules[moduleId]) {
21 | /******/ return installedModules[moduleId].exports;
22 | /******/ }
23 | /******/ // Create a new module (and put it into the cache)
24 | /******/ var module = installedModules[moduleId] = {
25 | /******/ i: moduleId,
26 | /******/ l: false,
27 | /******/ exports: {}
28 | /******/ };
29 | /******/
30 | /******/ // Execute the module function
31 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
32 | /******/
33 | /******/ // Flag the module as loaded
34 | /******/ module.l = true;
35 | /******/
36 | /******/ // Return the exports of the module
37 | /******/ return module.exports;
38 | /******/ }
39 | /******/
40 | /******/
41 | /******/ // expose the modules object (__webpack_modules__)
42 | /******/ __webpack_require__.m = modules;
43 | /******/
44 | /******/ // expose the module cache
45 | /******/ __webpack_require__.c = installedModules;
46 | /******/
47 | /******/ // define getter function for harmony exports
48 | /******/ __webpack_require__.d = function(exports, name, getter) {
49 | /******/ if(!__webpack_require__.o(exports, name)) {
50 | /******/ Object.defineProperty(exports, name, {
51 | /******/ configurable: false,
52 | /******/ enumerable: true,
53 | /******/ get: getter
54 | /******/ });
55 | /******/ }
56 | /******/ };
57 | /******/
58 | /******/ // getDefaultExport function for compatibility with non-harmony modules
59 | /******/ __webpack_require__.n = function(module) {
60 | /******/ var getter = module && module.__esModule ?
61 | /******/ function getDefault() { return module['default']; } :
62 | /******/ function getModuleExports() { return module; };
63 | /******/ __webpack_require__.d(getter, 'a', getter);
64 | /******/ return getter;
65 | /******/ };
66 | /******/
67 | /******/ // Object.prototype.hasOwnProperty.call
68 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
69 | /******/
70 | /******/ // __webpack_public_path__
71 | /******/ __webpack_require__.p = "";
72 | /******/
73 | /******/ // Load entry module and return exports
74 | /******/ return __webpack_require__(__webpack_require__.s = 0);
75 | /******/ })
76 | /************************************************************************/
77 | /******/ ([
78 | /* 0 */
79 | /***/ (function(module, exports, __webpack_require__) {
80 |
81 | "use strict";
82 |
83 |
84 | var _createClass = function () { function 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
85 |
86 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
87 |
88 | var mediaFile = __webpack_require__(1);
89 |
90 | // Detect iOS browsers < version 10
91 | var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream;
92 |
93 | var NoSleep = function () {
94 | function NoSleep() {
95 | _classCallCheck(this, NoSleep);
96 |
97 | if (oldIOS) {
98 | this.noSleepTimer = null;
99 | } else {
100 | // Set up no sleep video element
101 | this.noSleepVideo = document.createElement('video');
102 |
103 | this.noSleepVideo.setAttribute('muted', true);
104 | this.noSleepVideo.setAttribute('playsinline', '');
105 | this.noSleepVideo.setAttribute('src', mediaFile);
106 |
107 | this.noSleepVideo.addEventListener('timeupdate', function (e) {
108 | if (this.noSleepVideo.currentTime > 0.5) {
109 | this.noSleepVideo.currentTime = Math.random();
110 | }
111 | }.bind(this));
112 | }
113 | }
114 |
115 | _createClass(NoSleep, [{
116 | key: 'enable',
117 | value: function enable() {
118 | if (oldIOS) {
119 | this.disable();
120 | this.noSleepTimer = window.setInterval(function () {
121 | window.location.href = '/';
122 | window.setTimeout(window.stop, 0);
123 | }, 15000);
124 | } else {
125 | this.noSleepVideo.play();
126 | }
127 | }
128 | }, {
129 | key: 'disable',
130 | value: function disable() {
131 | if (oldIOS) {
132 | if (this.noSleepTimer) {
133 | window.clearInterval(this.noSleepTimer);
134 | this.noSleepTimer = null;
135 | }
136 | } else {
137 | this.noSleepVideo.pause();
138 | }
139 | }
140 | }]);
141 |
142 | return NoSleep;
143 | }();
144 |
145 | ;
146 |
147 | module.exports = NoSleep;
148 |
149 | /***/ }),
150 | /* 1 */
151 | /***/ (function(module, exports, __webpack_require__) {
152 |
153 | "use strict";
154 |
155 |
156 | module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQAD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';
157 |
158 | /***/ })
159 | /******/ ]);
160 | });
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Interval Timer
31 |
32 |
33 |
34 |
453 |
454 |
455 |
456 |
460 |
461 |
462 |
463 |
464 |
465 |
470 |
471 |
472 |
473 |
474 |
elapsed
475 |
00:00
476 |
477 |
478 |
interval
479 |
0/0
480 |
481 |
482 |
remaining
483 |
00:00
484 |
485 |
486 |
487 |
488 |
489 |

490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |

498 |
499 |
500 |
506 |
507 |
508 |

509 |
510 |
511 |

512 |
513 |
514 |
515 |
516 |
517 |
523 |
524 |
525 |
526 |
An Interval Timer
527 |
528 | Reset:
529 | Start:
530 | Stop:
531 |
532 |
On iOS/Android click the share icon
533 |
534 | and select "Add to Home Screen" for a better experience.
535 |
536 |
537 |
538 |
539 |
done
540 |
541 |
542 |
543 |
544 |
545 |
1010 |
1011 |
--------------------------------------------------------------------------------
/interval-timer.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId]) {
10 | /******/ return installedModules[moduleId].exports;
11 | /******/ }
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ i: moduleId,
15 | /******/ l: false,
16 | /******/ exports: {}
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.l = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // define getter function for harmony exports
37 | /******/ __webpack_require__.d = function(exports, name, getter) {
38 | /******/ if(!__webpack_require__.o(exports, name)) {
39 | /******/ Object.defineProperty(exports, name, {
40 | /******/ configurable: false,
41 | /******/ enumerable: true,
42 | /******/ get: getter
43 | /******/ });
44 | /******/ }
45 | /******/ };
46 | /******/
47 | /******/ // getDefaultExport function for compatibility with non-harmony modules
48 | /******/ __webpack_require__.n = function(module) {
49 | /******/ var getter = module && module.__esModule ?
50 | /******/ function getDefault() { return module['default']; } :
51 | /******/ function getModuleExports() { return module; };
52 | /******/ __webpack_require__.d(getter, 'a', getter);
53 | /******/ return getter;
54 | /******/ };
55 | /******/
56 | /******/ // Object.prototype.hasOwnProperty.call
57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
58 | /******/
59 | /******/ // __webpack_public_path__
60 | /******/ __webpack_require__.p = "";
61 | /******/
62 | /******/ // Load entry module and return exports
63 | /******/ return __webpack_require__(__webpack_require__.s = 1);
64 | /******/ })
65 | /************************************************************************/
66 | /******/ ([
67 | /* 0 */
68 | /***/ (function(module, exports, __webpack_require__) {
69 |
70 | "use strict";
71 | var __WEBPACK_AMD_DEFINE_RESULT__;
72 |
73 | !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
74 | var audio = {};
75 | (function(samplerate){
76 | this.SampleRate = samplerate || 44100;
77 | var SampleRate = this.SampleRate;
78 |
79 | // Do not modify parameters without changing code!
80 | var BitsPerSample = 16;
81 | var NumChannels = 1;
82 | var BlockAlign = NumChannels * BitsPerSample >> 3;
83 | var ByteRate = SampleRate * BlockAlign;
84 |
85 | // helper functions
86 | var chr = String.fromCharCode; // alias for getting converting int to char
87 |
88 | //////////////////////
89 | // Wave ///
90 | //////////////////////
91 |
92 | var waveTag="data:audio/wav;base64,";
93 | // constructs a wave from sample array
94 | var constructWave = function(data){
95 | var l;
96 | return pack( ["RIFF",36+(l=data.length),"WAVEfmt ",16,1,NumChannels,SampleRate,
97 | ByteRate,BlockAlign,BitsPerSample,"data",l,data],"s4s4224422s4s");
98 | };
99 |
100 | // creates an audio object from sample data
101 | this.make = function(arr){
102 | return new Audio(waveTag + btoa(constructWave(arrayToData(arr))))
103 | };
104 |
105 | // creates a wave file for downloading
106 | this.makeWaveFile = function(arr){
107 | dataToFile(waveTag + btoa(constructWave(arrayToData(arr))))
108 | };
109 |
110 | this.makeAudioBuffer = function(ctx, data) {
111 | var buffer = ctx.createBuffer(1, data.length, SampleRate);
112 | var array = buffer.getChannelData(0);
113 | for (var i = 0; i < data.length; ++i) {
114 | array[i] = data[i];
115 | }
116 | return buffer;
117 | };
118 |
119 | //////////////////////
120 | // General stuff ///
121 | //////////////////////
122 |
123 | // Converts an integer to String representation
124 | // a - number
125 | // i - number of bytes
126 | var istr = function(a,i){
127 | var m8 = 0xff; // 8 bit mask
128 | return i?chr(a&m8)+istr(a>>8,i-1):"";
129 | };
130 |
131 | // Packs array of data to a string
132 | // data - array
133 | // format - s is for string, numbers denote bytes to store in
134 | var pack = function(data,format){
135 | var out="";
136 | for(i=0;i> 8);
172 | };
173 | return out;
174 | }
175 |
176 | var arrayToData8bit = function(arr){
177 | var out="";
178 | var len = arr.length;
179 | for( i=0 ; i < len ; i++){
180 | var a = (arr[i] * 127 + 128) | 0;
181 | a = a < 0 ? 0 : 255 < a ? 255 : a;
182 | out += String.fromCharCode(a);
183 | };
184 | return out;
185 | }
186 |
187 | var arrayToData = function(arr){
188 | if( BitsPerSample == 16 )
189 | return arrayToData16bit(arr);
190 | else
191 | return arrayToData8bit(arr);
192 | }
193 |
194 | //////////////////////
195 | // Processing
196 | //////////////////////
197 |
198 | // adjusts volume of a buffer
199 | this.adjustVolume = function(data, v){
200 | for(i=0;i A ? 1.0 : sin(phase) < A ? -1.0 : A}
269 | };
270 | var generators = this.generators;
271 |
272 | this.g = {
273 | noise : function(count){ return generate(count,0, generators.noise) },
274 | sine : function(count, freq){ return generate(count, freq, generators.sine) },
275 | synth : function(count, freq){ return generate(count, freq, generators.synth) },
276 | saw : function(count, freq){ return generate(count, freq, generators.saw) },
277 | square : function(count, freq, A){ return generate(count, freq, generators.square, A) }
278 | };
279 | }).apply(audio);
280 |
281 | return audio;
282 | }).call(exports, __webpack_require__, exports, module),
283 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
284 |
285 |
286 | /***/ }),
287 | /* 1 */
288 | /***/ (function(module, exports, __webpack_require__) {
289 |
290 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
291 | __webpack_require__(2),
292 | ], __WEBPACK_AMD_DEFINE_RESULT__ = (function (
293 | AudioManager
294 | ) {
295 | window.AudioManager = AudioManager;
296 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
297 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
298 |
299 |
300 |
301 | /***/ }),
302 | /* 2 */
303 | /***/ (function(module, exports, __webpack_require__) {
304 |
305 | "use strict";
306 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
307 | * Copyright 2014, Gregg Tavares.
308 | * All rights reserved.
309 | *
310 | * Redistribution and use in source and binary forms, with or without
311 | * modification, are permitted provided that the following conditions are
312 | * met:
313 | *
314 | * * Redistributions of source code must retain the above copyright
315 | * notice, this list of conditions and the following disclaimer.
316 | * * Redistributions in binary form must reproduce the above
317 | * copyright notice, this list of conditions and the following disclaimer
318 | * in the documentation and/or other materials provided with the
319 | * distribution.
320 | * * Neither the name of Gregg Tavares. nor the names of its
321 | * contributors may be used to endorse or promote products derived from
322 | * this software without specific prior written permission.
323 | *
324 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
325 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
326 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
328 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
329 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
330 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
331 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
333 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
334 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
335 | */
336 |
337 |
338 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [
339 | __webpack_require__(3),
340 | __webpack_require__(5)
341 | ], __WEBPACK_AMD_DEFINE_RESULT__ = (function(
342 | jsfxlib,
343 | EventEmitter) {
344 |
345 | var webAudioAPI = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
346 |
347 | /**
348 | * @typedef {Object} AudioManager~Options
349 | * @property {callback} startedOnTouchCallback: **DEPREICATED**
350 | * Use `mgr.on(`started`)
351 | *
352 | * @property {callback} callback: **DEPRECATED** use
353 | * mgr.on('loaded').
354 | */
355 |
356 | /**
357 | * This can either be a path to a file OR jsfx data for sounds
358 | * generated at runtime. Example:
359 | *
360 | * var sounds = {
361 | * coin: { jsfx: ["square",0.0000,0.4000,0.0000,0.0240,0.4080,0.3480,20.0000,909.0000,2400.0000,0.0000,0.0000,0.0000,0.0100,0.0003,0.0000,0.2540,0.1090,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000], },
362 | * jump: { jsfx: ["square",0.0000,0.4000,0.0000,0.0960,0.0000,0.1720,20.0000,245.0000,2400.0000,0.3500,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.5000,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000], },
363 | * fire: { filename: "assets/fire.ogg", samples: 8, },
364 | * boom: { filename: "assets/explosion.ogg", samples: 8, },
365 | * };
366 | *
367 | *
368 | * Note Firefox doesn't support MP3s as far as I know so you'll need
369 | * to supply .ogg files for it. Conversely, Safari doesn't support .ogg.
370 | * The library handles loading .mp3 or .ogg files regardless of what you specify
371 | * when you init the library. In other words if you put `filename: "foo.mp3"`
372 | * the library will try to load `foo.mp3` or `foo.ogg` depending on if the
373 | * browser supports one or the other.
374 | *
375 | * @typedef {Object} AudioManager~Sound
376 | * @property {string?} filename path to the file to load
377 | * @property {number?} samples How many of this sound can play
378 | * simultainously. Note: this is NOT needed when using
379 | * the Web Audio API. It is only needed for legacy
380 | * browsers like IE11 and below.
381 | * @property {Array?} jsfx Data from jsfx. See http://egonelbre.com/project/jsfx/
382 | */
383 |
384 | /**
385 | * To use this include it with
386 | *
387 | *
388 | *
389 | * Then give it a list of sounds like this
390 | *
391 | * var audioMgr = new AudioManager({
392 | * fire: { filename: "assets/fire.ogg", samples: 8, },
393 | * explosion: { filename: "assets/explosion.ogg", samples: 6, },
394 | * hitshield: { filename: "assets/hitshield.ogg", samples: 6, },
395 | * launch: { filename: "assets/launch.ogg", samples: 2, },
396 | * gameover: { filename: "assets/gameover.ogg", samples: 1, },
397 | * play: { filename: "assets/play.ogg", samples: 1, },
398 | * });
399 | *
400 | * After that you can play sounds with
401 | *
402 | * audioMgr.playSound('explosion');
403 | * audioMgr.playSound('fire');
404 | *
405 | * The signature for `playSound` is
406 | * `playSound(name, when, loop)` where when is the time to play
407 | * the sound and loop is whether or not to play the sound
408 | * continuously in a loop.
409 | *
410 | * Playsound returns an object you can use to control the sound
411 | * though this part of the API is still in flux.
412 | *
413 | * `samples` is how may of that sound you want to be able to play at
414 | * the same time. THIS IS NOT NEEDED for any browser that supports the
415 | * Web Audio API. In other words it's only needed for IE.
416 | *
417 | * Also note Firefox doesn't support MP3s as far as I know so you'll need
418 | * to supply .ogg files for it. Conversely, Safari doesn't support .ogg.
419 | * The library handles loading .mp3 or .ogg files regardless of what you specify
420 | * when you init the library. In other words if you put `filename: "foo.mp3"`
421 | * the library will try to load `foo.mp3` or `foo.ogg` depending on if the
422 | * browser supports one or the other.
423 | *
424 | * @constructor
425 | * @param {Object(string:AudioManager~Sound}} sounds The sounds
426 | * to load
427 | * @param {AudioManager~Options} options Options
428 | * @fires AudioManager#loaded when all sounds have loaded
429 | * @fires AudioManager#started when the first sound has played.
430 | * On iOS no sounds can be played unless at least one is
431 | * first initiated during a use gesture event. This event
432 | * is useful for situtations where sounds 'should' start
433 | * right from the beginning even if the player as not
434 | * touched the screen. For exampme we might put up a
435 | * message, "touch the screen" and remove that message
436 | * when we get this event
437 | */
438 | var AudioManager = function(sounds, options) {
439 | options = options || {};
440 | var g_eventEmitter = new EventEmitter();
441 | var g_context;
442 | var g_audioMgr;
443 | var g_soundBank = {};
444 | var g_canPlay = false;
445 | var g_canPlayOgg;
446 | var g_canPlayMp3;
447 | var g_canPlayWav;
448 | var g_canPlayAif;
449 | var g_createFromFileFn;
450 | var g_createFromJSFXFn;
451 |
452 | var changeExt = function(filename, ext) {
453 | return filename.substring(0, filename.length - 3) + ext;
454 | };
455 |
456 | this.needUserGesture = function() {
457 | return true;
458 | };
459 |
460 | this.on = g_eventEmitter.on.bind(g_eventEmitter);
461 | this.addListener = this.on;
462 | this.addEventListener = this.on;
463 | this.removeListener = g_eventEmitter.removeListener.bind(g_eventEmitter);
464 | this.removeEventListener = this.removeListener;
465 |
466 | if (options.callback) {
467 | console.warn("AudioManager: options.callback is deprecated. Use mgr.on('loaded', ...)");
468 | this.on('loaded', options.callback);
469 | }
470 |
471 | if (options.startedOnTouchCallback) {
472 | console.warn("AudioManager: options.startedOnTouchCallback is deprecated. Use mgr.on('started', ...)");
473 | this.on('started', options.callback);
474 | }
475 |
476 | var WebAudioBuffer = function() {
477 | };
478 |
479 | WebAudioBuffer.prototype.play = function(opt_when, opt_loop) {
480 | if (!this.buffer) {
481 | console.log(this.name, " not loaded");
482 | return;
483 | }
484 | var src = g_context.createBufferSource();
485 | src.buffer = this.buffer;
486 | src.loop = opt_loop || false;
487 | src.connect(g_context.destination);
488 | if (src.start) {
489 | src.start(opt_when || 0);
490 | } else {
491 | src.noteOn(opt_when || 0);
492 | }
493 | return src;
494 | };
495 |
496 | var WebAudioJSFX = function(name, data, samples, opt_callback) {
497 | this.buffer = jsfxlib.createAudioBuffer(g_context, data);
498 | if (opt_callback) {
499 | setTimeout(opt_callback, 0);
500 | }
501 | };
502 |
503 | WebAudioJSFX.prototype = new WebAudioBuffer();
504 |
505 | function WebAudioSound(name, filename, samples, opt_callback) {
506 | this.name = name;
507 | var that = this;
508 | var req = new XMLHttpRequest();
509 | req.open("GET", filename, true);
510 | req.responseType = "arraybuffer";
511 | req.onload = function() {
512 | g_context.decodeAudioData(req.response, function onSuccess(decodedBuffer) {
513 | // Decoding was successful, do something useful with the audio buffer
514 | that.buffer = decodedBuffer;
515 | if (opt_callback) {
516 | opt_callback(false);
517 | }
518 | }, function onFailure() {
519 | console.error("failed to decoding audio buffer: " + filename);
520 | if (opt_callback) {
521 | opt_callback(true);
522 | }
523 | });
524 | }
525 | req.addEventListener("error", function(e) {
526 | console.error("failed to load:", filename, " : ", e.target.status);
527 | }, false);
528 | req.send();
529 | }
530 |
531 | WebAudioSound.prototype = new WebAudioBuffer();
532 |
533 | var AudioTagJSFX = function(name, data, samples, opt_callback) {
534 | this.samples = samples || 1;
535 | this.audio = {};
536 | this.playNdx = 0;
537 | for (var i = 0; i < samples; ++i) {
538 | this.audio[i] = jsfxlib.createWave(data);
539 | }
540 | if (opt_callback) {
541 | setTimeout(opt_callback, 0);
542 | }
543 | };
544 |
545 | AudioTagJSFX.prototype.play = function(opt_when, opt_loop) {
546 | this.playNdx = (this.playNdx + 1) % this.samples;
547 | var a = this.audio[this.playNdx];
548 | var b = new Audio();
549 | b.src = a.src;
550 | // TODO: use when
551 | b.addEventListener("canplaythrough", function() {
552 | b.play();
553 | }, false);
554 | b.load();
555 | };
556 |
557 | function AudioTagSound(name, filename, samples, opt_callback) {
558 | this.waiting_on_load = samples;
559 | this.samples = samples || 1;
560 | this.name = name;
561 | this.play_idx = 0;
562 | this.audio = {};
563 | for (var i = 0; i < samples; i++) {
564 | var audio = new Audio();
565 | var that = this;
566 | var checkCallback = function(err) {
567 | that.waiting_on_load--;
568 | if (opt_callback) {
569 | opt_callback(err);
570 | }
571 | };
572 | audio.addEventListener("canplaythrough", function() {
573 | checkCallback(false);
574 | }, false);
575 | audio.src = filename;
576 | audio.onerror = function() {
577 | checkCallback(true);
578 | };
579 | audio.load();
580 | this.audio[i] = audio;
581 | }
582 | };
583 |
584 | AudioTagSound.prototype.play = function(opt_when, opt_loop) {
585 | if (this.waiting_on_load > 0) {
586 | console.log(this.name, " not loaded");
587 | return;
588 | }
589 | this.play_idx = (this.play_idx + 1) % this.samples;
590 | var a = this.audio[this.play_idx];
591 | // console.log(this.name, ":", this.play_idx, ":", a.src);
592 | var b = new Audio();
593 | b.src = a.src;
594 | // TODO: use when
595 | b.addEventListener("canplaythrough", function() {
596 | b.play();
597 | }, false);
598 | b.load();
599 | };
600 |
601 | var handleError = function(filename, audio) {
602 | return function(e) {
603 | console.error("can't load ", filename);
604 | }
605 | };
606 |
607 | this.playSound = function(name, opt_when, opt_loop) {
608 | if (!g_canPlay)
609 | return;
610 | var sound = g_soundBank[name];
611 | if (!sound) {
612 | console.error("audio: '" + name + "' not known.");
613 | return;
614 | }
615 | return sound.play(opt_when, opt_loop);
616 | }.bind(this);
617 |
618 | this.getTime = function() {
619 | return g_context ? g_context.currentTime : Date.now() * 0.001;
620 | }.bind(this);
621 |
622 | // on iOS and possibly other devices you can't play any
623 | // sounds in the browser unless you first play a sound
624 | // in response to a user gesture. So, make something
625 | // to respond to a user gesture.
626 | var setupGesture = function() {
627 | if (this.needUserGesture()) {
628 | var count = 0;
629 | var elem = window;
630 | var that = this;
631 | var eventNames = ['touchstart', 'mousedown'];
632 | var playSoundToStartAudio = function() {
633 | ++count;
634 | if (count < 3) {
635 | // just playing any sound does not seem to work.
636 | var source = g_context.createOscillator();
637 | var gain = g_context.createGain();
638 | source.frequency.value = 1;
639 | source.connect(gain);
640 | gain.gain.value = 0;
641 | gain.connect(g_context.destination);
642 | if (source.start) {
643 | source.start(0);
644 | } else {
645 | source.noteOn(0);
646 | }
647 | setTimeout(function() {
648 | source.disconnect();
649 | }, 100);
650 | }
651 | if (count == 3) {
652 | for (var ii = 0; ii < eventNames.length; ++ii) {
653 | elem.removeEventListener(eventNames[ii], playSoundToStartAudio, false);
654 | }
655 | g_eventEmitter.emit('started');
656 | }
657 | }
658 |
659 | for (var ii = 0; ii < eventNames.length; ++ii) {
660 | elem.addEventListener(eventNames[ii], playSoundToStartAudio, false);
661 | }
662 | }
663 | }.bind(this);
664 |
665 | this.loadSound = function(soundName, filename, samples, opt_callback) {
666 | var ext = filename.substring(filename.length - 3);
667 | if (ext == 'ogg' && !g_canPlayOgg) {
668 | filename = changeExt(filename, "mp3");
669 | } else if (ext == 'mp3' && !g_canPlayMp3) {
670 | filename = changeExt(filename, "ogg");
671 | }
672 | var s = new g_createFromFileFn(soundName, filename, samples, opt_callback);
673 | g_soundBank[soundName] = s;
674 | return s;
675 | }.bind(this);
676 |
677 | this.makeJSFXSound = function(soundName, data, samples, opt_callback) {
678 | var s = new g_createFromJSFXFn(soundName, data, samples, opt_callback);
679 | g_soundBank[soundName] = s;
680 | return s;
681 | }.bind(this);
682 |
683 | this.loadSounds = function(sounds, opt_callback) {
684 | var soundsPending = 1;
685 | var soundsLoaded = function() {
686 | --soundsPending;
687 | if (soundsPending == 0 && opt_callback) {
688 | opt_callback();
689 | }
690 | };
691 |
692 | Object.keys(sounds).forEach(function(sound) {
693 | var data = sounds[sound];
694 | ++soundsPending;
695 | if (data.jsfx) {
696 | this.makeJSFXSound(sound, data.jsfx, data.samples, soundsLoaded);
697 | } else {
698 | this.loadSound(sound, data.filename, data.samples, soundsLoaded);
699 | }
700 | }.bind(this));
701 |
702 | // so that we generate a callback even if there are no sounds.
703 | // That way users don't have to restructure their code if they have no sounds or if they
704 | // disable sounds by passing none in.
705 | setTimeout(soundsLoaded, 0);
706 | };
707 |
708 | this.init = function(sounds) {
709 | var a = new Audio()
710 | g_canPlayOgg = a.canPlayType("audio/ogg");
711 | g_canPlayMp3 = a.canPlayType("audio/mp3");
712 | g_canPlayWav = a.canPlayType("audio/wav");
713 | g_canPlayAif = a.canPlayType("audio/aif") || a.canPlayType("audio/aiff");
714 | g_canPlay = g_canPlayOgg || g_canPlayMp3;
715 | if (!g_canPlay)
716 | return;
717 |
718 | if (webAudioAPI) {
719 | console.log("Using Web Audio API");
720 | g_context = new webAudioAPI();
721 |
722 | if (!g_context.createGain) { g_context.createGain = g_context.createGainNode.bind(g_context); }
723 |
724 | g_createFromFileFn = WebAudioSound;
725 | g_createFromJSFXFn = WebAudioJSFX;
726 | } else {
727 | console.log("Using Audio Tag");
728 | g_createFromFileFn = AudioTagSound;
729 | g_createFromJSFXFn = AudioTagJSFX;
730 | }
731 |
732 | var soundsPending = 1;
733 | var soundsLoaded = function() {
734 | --soundsPending;
735 | if (soundsPending == 0) {
736 | g_eventEmitter.emit('loaded');
737 | }
738 | };
739 |
740 | if (sounds) {
741 | Object.keys(sounds).forEach(function(sound) {
742 | var data = sounds[sound];
743 | ++soundsPending;
744 | if (data.jsfx) {
745 | this.makeJSFXSound(sound, data.jsfx, data.samples, soundsLoaded);
746 | } else {
747 | this.loadSound(sound, data.filename, data.samples, soundsLoaded);
748 | }
749 | }.bind(this));
750 | }
751 |
752 | // so that we generate a callback even if there are no sounds.
753 | // That way users don't have to restructure their code if they have no sounds or if they
754 | // disable sounds by passing none in.
755 | setTimeout(soundsLoaded, 0);
756 |
757 | if (webAudioAPI) {
758 | setupGesture();
759 | }
760 | }.bind(this);
761 | this.init(sounds);
762 |
763 | this.getSoundIds = function() {
764 | return Object.keys(g_soundBank);
765 | };
766 | };
767 |
768 | AudioManager.hasWebAudio = function() {
769 | return webAudioAPI !== undefined;
770 | };
771 |
772 | return AudioManager;
773 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
774 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
775 |
776 |
777 | /***/ }),
778 | /* 3 */
779 | /***/ (function(module, exports, __webpack_require__) {
780 |
781 | "use strict";
782 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
783 |
784 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(audio, jsfx) {
785 | var jsfxlib = {};
786 | (function () {
787 | // takes object with param arrays
788 | // audiolib = {
789 | // Sound : ["sine", 1, 2, 4, 1...
790 | // }
791 | //
792 | // returns object with audio samples
793 | // p.Sound.play()
794 | this.createWaves = function(lib){
795 | var sounds = {};
796 | for (var e in lib) {
797 | var data = lib[e];
798 | sounds[e] = this.createWave(data);
799 | }
800 | return sounds;
801 | }
802 |
803 | /* Create a single sound:
804 | var p = jsfxlib.createWave(["sine", 1,2,3, etc.]);
805 | p.play();
806 | */
807 | this.createWave = function(lib) {
808 | var params = this.arrayToParams(lib),
809 | data = jsfx.generate(params),
810 | wave = audio.make(data);
811 |
812 | return wave;
813 | }
814 |
815 | // takes object with param arrays
816 | //
817 | // var audiolib = {
818 | // someSound : ["sine", 1, 2, 4, 1...
819 | // }
820 | //
821 | // returns object with AudioBuffers you can use
822 | // with the Web Audio API
823 | //
824 | // var sounds = jsfxlib.createAudioBuffers(ctx, audiolib);
825 | // var ctx = new AudioContext();
826 | // var src = ctx.createBufferSource();
827 | // src.buffer = sounds.someSound;
828 | // src.connect(ctx.destination);
829 | // src.start();
830 | this.createAudioBuffers = function(ctx, lib) {
831 | var sounds = {};
832 | for (var e in lib) {
833 | var data = lib[e];
834 | sounds[e] = this.createAudioBuffer(ctx, data);
835 | }
836 | return sounds;
837 | }
838 |
839 | // Create a single AudioBuffer
840 | //
841 | // var buffer = jsfxlib.createAudioBuffer(ctx, ["sine", 1,2,3, etc.]);
842 | // var ctx = new AudioContext();
843 | // var src = ctx.createBufferSource();
844 | // src.buffer = buffer;
845 | // src.connect(ctx.destination);
846 | // src.start();
847 | this.createAudioBuffer = function(ctx, lib) {
848 | var params = this.arrayToParams(lib),
849 | data = jsfx.generate(params),
850 | buffer = audio.makeAudioBuffer(ctx, data);
851 |
852 | return buffer;
853 | }
854 |
855 | this.paramsToArray = function(params){
856 | var pararr = [];
857 | var len = jsfx.Parameters.length;
858 | for(var i = 0; i < len; i++){
859 | pararr.push(params[jsfx.Parameters[i].id]);
860 | }
861 | return pararr;
862 | }
863 |
864 | this.arrayToParams = function(pararr){
865 | var params = {};
866 | var len = jsfx.Parameters.length;
867 | for(var i = 0; i < len; i++){
868 | params[jsfx.Parameters[i].id] = pararr[i];
869 | }
870 | return params;
871 | }
872 | }).apply(jsfxlib);
873 |
874 | return jsfxlib;
875 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
876 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
877 |
878 |
879 |
880 | /***/ }),
881 | /* 4 */
882 | /***/ (function(module, exports, __webpack_require__) {
883 |
884 | "use strict";
885 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
886 |
887 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = (function(audio) {
888 | var jsfx = {};
889 | (function () {
890 | this.Parameters = []; // will be constructed in the end
891 |
892 | this.Generators = {
893 | square : audio.generators.square,
894 | saw : audio.generators.saw,
895 | sine : audio.generators.sine,
896 | noise : audio.generators.noise,
897 | synth : audio.generators.synth
898 | };
899 |
900 | this.getGeneratorNames = function(){
901 | var names = [];
902 | for(var e in this.Generators)
903 | names.push(e);
904 | return names;
905 | }
906 |
907 | var nameToParam = function(name){
908 | return name.replace(/ /g, "");
909 | }
910 |
911 | this.getParameters = function () {
912 | var params = [];
913 |
914 | var grp = 0;
915 |
916 | // add param
917 | var ap = function (name, min, max, def, step) {
918 | if (step === undefined)
919 | step = (max - min) / 1000;
920 | var param = { name: name, id: nameToParam(name),
921 | min: min, max: max, step:step, def: def,
922 | type: "range", group: grp};
923 | params.push(param);
924 | };
925 |
926 | // add option
927 | var ao = function(name, options, def){
928 | var param = {name: name, id: nameToParam(name),
929 | options: options, def: def,
930 | type: "option", group: grp };
931 | params.push(param);
932 | }
933 |
934 | var gens = this.getGeneratorNames();
935 | ao("Generator", gens, gens[0]);
936 | ap("Super Sampling Quality", 0, 16, 0, 1);
937 | ap("Master Volume", 0, 1, 0.4);
938 | grp++;
939 |
940 | ap("Attack Time", 0, 1, 0.1); // seconds
941 | ap("Sustain Time", 0, 2, 0.3); // seconds
942 | ap("Sustain Punch", 0, 3, 2);
943 | ap("Decay Time", 0, 2, 1); // seconds
944 | grp++;
945 |
946 | ap("Min Frequency", 20, 2400, 0, 1);
947 | ap("Start Frequency", 20, 2400, 440, 1);
948 | ap("Max Frequency", 20, 2400, 2000, 1);
949 | ap("Slide", -1, 1, 0);
950 | ap("Delta Slide", -1, 1, 0);
951 |
952 | grp++;
953 | ap("Vibrato Depth", 0, 1, 0);
954 | ap("Vibrato Frequency", 0.01, 48, 8);
955 | ap("Vibrato Depth Slide", -0.3, 1, 0);
956 | ap("Vibrato Frequency Slide", -1, 1, 0);
957 |
958 | grp++;
959 | ap("Change Amount", -1, 1, 0);
960 | ap("Change Speed", 0, 1, 0.1);
961 |
962 | grp++;
963 | ap("Square Duty", 0, 0.5, 0);
964 | ap("Square Duty Sweep", -1, 1, 0);
965 |
966 | grp++;
967 | ap("Repeat Speed", 0, 0.8, 0);
968 |
969 | grp++;
970 | ap("Phaser Offset", -1, 1, 0);
971 | ap("Phaser Sweep", -1, 1, 0);
972 |
973 | grp++;
974 | ap("LP Filter Cutoff", 0, 1, 1);
975 | ap("LP Filter Cutoff Sweep", -1, 1, 0);
976 | ap("LP Filter Resonance", 0, 1, 0);
977 | ap("HP Filter Cutoff", 0, 1, 0);
978 | ap("HP Filter Cutoff Sweep", -1, 1, 0);
979 |
980 | return params;
981 | };
982 |
983 |
984 | /**
985 | * Input params object has the same parameters as described above
986 | * except all the spaces have been removed
987 | *
988 | * This returns an array of float values of the generated audio.
989 | *
990 | * To make it into a wave use:
991 | * data = jsfx.generate(params)
992 | * audio.make(data)
993 | */
994 | this.generate = function(params){
995 | // useful consts/functions
996 | var TAU = 2 * Math.PI,
997 | sin = Math.sin,
998 | cos = Math.cos,
999 | pow = Math.pow,
1000 | abs = Math.abs;
1001 | var SampleRate = audio.SampleRate;
1002 |
1003 | // super sampling
1004 | var super_sampling_quality = params.SuperSamplingQuality | 0;
1005 | if(super_sampling_quality < 1) super_sampling_quality = 1;
1006 | SampleRate = SampleRate * super_sampling_quality;
1007 |
1008 | // enveloping initialization
1009 | var _ss = 1.0 + params.SustainPunch;
1010 | var envelopes = [ {from: 0.0, to: 1.0, time: params.AttackTime},
1011 | {from: _ss, to: 1.0, time: params.SustainTime},
1012 | {from: 1.0, to: 0.0, time: params.DecayTime}];
1013 | var envelopes_len = envelopes.length;
1014 |
1015 | // envelope sample calculation
1016 | for(var i = 0; i < envelopes_len; i++){
1017 | envelopes[i].samples = 1 + ((envelopes[i].time * SampleRate) | 0);
1018 | }
1019 | // envelope loop variables
1020 | var envelope = undefined;
1021 | var envelope_cur = 0.0;
1022 | var envelope_idx = -1;
1023 | var envelope_increment = 0.0;
1024 | var envelope_last = -1;
1025 |
1026 | // count total samples
1027 | var totalSamples = 0;
1028 | for(var i = 0; i < envelopes_len; i++){
1029 | totalSamples += envelopes[i].samples;
1030 | }
1031 |
1032 | // fix totalSample limit
1033 | if( totalSamples < SampleRate / 2){
1034 | totalSamples = SampleRate / 2;
1035 | }
1036 |
1037 | var outSamples = (totalSamples / super_sampling_quality)|0;
1038 |
1039 | // out data samples
1040 | var out = new Array(outSamples);
1041 | var sample = 0;
1042 | var sample_accumulator = 0;
1043 |
1044 | // main generator
1045 | var generator = jsfx.Generators[params.Generator];
1046 | if (generator === undefined)
1047 | generator = this.Generators.square;
1048 | var generator_A = 0;
1049 | var generator_B = 0;
1050 |
1051 | // square generator
1052 | generator_A = params.SquareDuty;
1053 | var square_slide = params.SquareDutySweep / SampleRate;
1054 |
1055 | // phase calculation
1056 | var phase = 0;
1057 | var phase_speed = params.StartFrequency * TAU / SampleRate;
1058 |
1059 | // phase slide calculation
1060 | var phase_slide = 1.0 + pow(params.Slide, 3.0) * 64.0 / SampleRate;
1061 | var phase_delta_slide = pow(params.DeltaSlide, 3.0) / (SampleRate * 1000);
1062 | if (super_sampling_quality !== undefined)
1063 | phase_delta_slide /= super_sampling_quality; // correction
1064 |
1065 | // frequency limiter
1066 | if(params.MinFrequency > params.StartFrequency)
1067 | params.MinFrequency = params.StartFrequency;
1068 |
1069 | if(params.MaxFrequency < params.StartFrequency)
1070 | params.MaxFrequency = params.StartFrequency;
1071 |
1072 | var phase_min_speed = params.MinFrequency * TAU / SampleRate;
1073 | var phase_max_speed = params.MaxFrequency * TAU / SampleRate;
1074 |
1075 | // frequency vibrato
1076 | var vibrato_phase = 0;
1077 | var vibrato_phase_speed = params.VibratoFrequency * TAU / SampleRate;
1078 | var vibrato_amplitude = params.VibratoDepth;
1079 |
1080 | // frequency vibrato slide
1081 | var vibrato_phase_slide = 1.0 + pow(params.VibratoFrequencySlide, 3.0) * 3.0 / SampleRate;
1082 | var vibrato_amplitude_slide = params.VibratoDepthSlide / SampleRate;
1083 |
1084 | // arpeggiator
1085 | var arpeggiator_time = 0;
1086 | var arpeggiator_limit = params.ChangeSpeed * SampleRate;
1087 | var arpeggiator_mod = pow(params.ChangeAmount, 2);
1088 | if (params.ChangeAmount > 0)
1089 | arpeggiator_mod = 1 + arpeggiator_mod * 10;
1090 | else
1091 | arpeggiator_mod = 1 - arpeggiator_mod * 0.9;
1092 |
1093 | // phaser
1094 | var phaser_max = 1024;
1095 | var phaser_mask = 1023;
1096 | var phaser_buffer = new Array(phaser_max);
1097 | for(var _i = 0; _i < phaser_max; _i++)
1098 | phaser_buffer[_i] = 0;
1099 | var phaser_pos = 0;
1100 | var phaser_offset = pow(params.PhaserOffset, 2.0) * (phaser_max - 4);
1101 | var phaser_offset_slide = pow(params.PhaserSweep, 3.0) * 4000 / SampleRate;
1102 | var phaser_enabled = (abs(phaser_offset_slide) > 0.00001) ||
1103 | (abs(phaser_offset) > 0.00001);
1104 |
1105 | // lowpass filter
1106 | var filters_enabled = (params.HPFilterCutoff > 0.001) || (params.LPFilterCutoff < 0.999);
1107 |
1108 | var lowpass_pos = 0;
1109 | var lowpass_pos_slide = 0;
1110 | var lowpass_cutoff = pow(params.LPFilterCutoff, 3.0) / 10;
1111 | var lowpass_cutoff_slide = 1.0 + params.HPFilterCutoffSweep / 10000;
1112 | var lowpass_damping = 5.0 / (1.0 + pow(params.LPFilterResonance, 2) * 20 ) *
1113 | (0.01 + params.LPFilterCutoff);
1114 | if ( lowpass_damping > 0.8)
1115 | lowpass_damping = 0.8;
1116 | lowpass_damping = 1.0 - lowpass_damping;
1117 | var lowpass_enabled = params.LPFilterCutoff < 0.999;
1118 |
1119 | // highpass filter
1120 | var highpass_accumulator = 0;
1121 | var highpass_cutoff = pow(params.HPFilterCutoff, 2.0) / 10;
1122 | var highpass_cutoff_slide = 1.0 + params.HPFilterCutoffSweep / 10000;
1123 |
1124 | // repeat
1125 | var repeat_time = 0;
1126 | var repeat_limit = totalSamples;
1127 | if (params.RepeatSpeed > 0){
1128 | repeat_limit = pow(1 - params.RepeatSpeed, 2.0) * SampleRate + 32;
1129 | }
1130 |
1131 | // master volume controller
1132 | var master_volume = params.MasterVolume;
1133 |
1134 | var k = 0;
1135 | for(var i = 0; i < totalSamples; i++){
1136 | // main generator
1137 | sample = generator(phase, generator_A, generator_B);
1138 |
1139 | // square generator
1140 | generator_A += square_slide;
1141 | if(generator_A < 0.0){
1142 | generator_A = 0.0;
1143 | } else if (generator_A > 0.5){
1144 | generator_A = 0.5;
1145 | }
1146 |
1147 | if( repeat_time > repeat_limit ){
1148 | // phase reset
1149 | phase = 0;
1150 | phase_speed = params.StartFrequency * TAU / SampleRate;
1151 | // phase slide reset
1152 | phase_slide = 1.0 + pow(params.Slide, 3.0) * 3.0 / SampleRate;
1153 | phase_delta_slide = pow(params.DeltaSlide, 3.0) / (SampleRate * 1000);
1154 | if (super_sampling_quality !== undefined)
1155 | phase_delta_slide /= super_sampling_quality; // correction
1156 | // arpeggiator reset
1157 | arpeggiator_time = 0;
1158 | arpeggiator_limit = params.ChangeSpeed * SampleRate;
1159 | arpeggiator_mod = 1 + (params.ChangeAmount | 0) / 12.0;
1160 | // repeat reset
1161 | repeat_time = 0;
1162 | }
1163 | repeat_time += 1;
1164 |
1165 | // phase calculation
1166 | phase += phase_speed;
1167 |
1168 | // phase slide calculation
1169 | phase_slide += phase_delta_slide;
1170 | phase_speed *= phase_slide;
1171 |
1172 | // arpeggiator
1173 | if ( arpeggiator_time > arpeggiator_limit ){
1174 | phase_speed *= arpeggiator_mod;
1175 | arpeggiator_limit = totalSamples;
1176 | }
1177 | arpeggiator_time += 1;
1178 |
1179 | // frequency limiter
1180 | if (phase_speed > phase_max_speed){
1181 | phase_speed = phase_max_speed;
1182 | } else if(phase_speed < phase_min_speed){
1183 | phase_speed = phase_min_speed;
1184 | }
1185 |
1186 | // frequency vibrato
1187 | vibrato_phase += vibrato_phase_speed;
1188 | var _vibrato_phase_mod = phase_speed * sin(vibrato_phase) * vibrato_amplitude;
1189 | phase += _vibrato_phase_mod;
1190 |
1191 | // frequency vibrato slide
1192 | vibrato_phase_speed *= vibrato_phase_slide;
1193 | if(vibrato_amplitude_slide){
1194 | vibrato_amplitude += vibrato_amplitude_slide;
1195 | if(vibrato_amplitude < 0){
1196 | vibrato_amplitude = 0;
1197 | vibrato_amplitude_slide = 0;
1198 | } else if (vibrato_amplitude > 1){
1199 | vibrato_amplitude = 1;
1200 | vibrato_amplitude_slide = 0;
1201 | }
1202 | }
1203 |
1204 | // filters
1205 | if( filters_enabled ){
1206 |
1207 | if( abs(highpass_cutoff) > 0.001){
1208 | highpass_cutoff *= highpass_cutoff_slide;
1209 | if(highpass_cutoff < 0.00001){
1210 | highpass_cutoff = 0.00001;
1211 | } else if(highpass_cutoff > 0.1){
1212 | highpass_cutoff = 0.1;
1213 | }
1214 | }
1215 |
1216 | var _lowpass_pos_old = lowpass_pos;
1217 | lowpass_cutoff *= lowpass_cutoff_slide;
1218 | if(lowpass_cutoff < 0.0){
1219 | lowpass_cutoff = 0.0;
1220 | } else if ( lowpass_cutoff > 0.1 ){
1221 | lowpass_cutoff = 0.1;
1222 | }
1223 | if(lowpass_enabled){
1224 | lowpass_pos_slide += (sample - lowpass_pos) * lowpass_cutoff;
1225 | lowpass_pos_slide *= lowpass_damping;
1226 | } else {
1227 | lowpass_pos = sample;
1228 | lowpass_pos_slide = 0;
1229 | }
1230 | lowpass_pos += lowpass_pos_slide;
1231 |
1232 | highpass_accumulator += lowpass_pos - _lowpass_pos_old;
1233 | highpass_accumulator *= 1.0 - highpass_cutoff;
1234 | sample = highpass_accumulator;
1235 | }
1236 |
1237 | // phaser
1238 | if (phaser_enabled) {
1239 | phaser_offset += phaser_offset_slide;
1240 | if( phaser_offset < 0){
1241 | phaser_offset = -phaser_offset;
1242 | phaser_offset_slide = -phaser_offset_slide;
1243 | }
1244 | if( phaser_offset > phaser_mask){
1245 | phaser_offset = phaser_mask;
1246 | phaser_offset_slide = 0;
1247 | }
1248 |
1249 | phaser_buffer[phaser_pos] = sample;
1250 | // phaser sample modification
1251 | var _p = (phaser_pos - (phaser_offset|0) + phaser_max) & phaser_mask;
1252 | sample += phaser_buffer[_p];
1253 | phaser_pos = (phaser_pos + 1) & phaser_mask;
1254 | }
1255 |
1256 | // envelope processing
1257 | if( i > envelope_last ){
1258 | envelope_idx += 1;
1259 | if(envelope_idx < envelopes_len) // fault protection
1260 | envelope = envelopes[envelope_idx];
1261 | else // the trailing envelope is silence
1262 | envelope = {from: 0, to: 0, samples: totalSamples};
1263 | envelope_cur = envelope.from;
1264 | envelope_increment = (envelope.to - envelope.from) / (envelope.samples + 1);
1265 | envelope_last += envelope.samples;
1266 | }
1267 | sample *= envelope_cur;
1268 | envelope_cur += envelope_increment;
1269 |
1270 | // master volume controller
1271 | sample *= master_volume;
1272 |
1273 | // prepare for next sample
1274 | if(super_sampling_quality > 1){
1275 | sample_accumulator += sample;
1276 | if( (i + 1) % super_sampling_quality === 0){
1277 | out[k] = sample_accumulator / super_sampling_quality;
1278 | k += 1;
1279 | sample_accumulator = 0;
1280 | }
1281 | } else {
1282 | out[i] = sample;
1283 | }
1284 | }
1285 |
1286 | // return out;
1287 |
1288 | // add padding 10ms
1289 | var len = (SampleRate / 100)|0;
1290 | var padding = new Array(len);
1291 | for(var i = 0; i < len; i++)
1292 | padding[i] = 0;
1293 | return padding.concat(out).concat(padding);
1294 | }
1295 |
1296 | this.Parameters = this.getParameters();
1297 |
1298 | }).apply(jsfx);
1299 |
1300 | return jsfx;
1301 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
1302 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
1303 |
1304 |
1305 |
1306 | /***/ }),
1307 | /* 5 */
1308 | /***/ (function(module, exports, __webpack_require__) {
1309 |
1310 | "use strict";
1311 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
1312 | * Copyright 2014, Gregg Tavares.
1313 | * All rights reserved.
1314 | *
1315 | * Redistribution and use in source and binary forms, with or without
1316 | * modification, are permitted provided that the following conditions are
1317 | * met:
1318 | *
1319 | * * Redistributions of source code must retain the above copyright
1320 | * notice, this list of conditions and the following disclaimer.
1321 | * * Redistributions in binary form must reproduce the above
1322 | * copyright notice, this list of conditions and the following disclaimer
1323 | * in the documentation and/or other materials provided with the
1324 | * distribution.
1325 | * * Neither the name of Gregg Tavares. nor the names of its
1326 | * contributors may be used to endorse or promote products derived from
1327 | * this software without specific prior written permission.
1328 | *
1329 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1330 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1331 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1332 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1333 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1334 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1335 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1336 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1337 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1338 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1339 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1340 | */
1341 |
1342 |
1343 |
1344 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
1345 |
1346 | /**
1347 | * This is similar to node's EventEmitter.
1348 | * The major difference is calling `addEventListner`
1349 | * or `removeEventListener` with `null` or `undefined`
1350 | * will remove all listeners for that event.
1351 | */
1352 | var EventEmitter = function() {
1353 | var events = {};
1354 | var maxListeners = 10;
1355 |
1356 | var setMaxListeners = function(max) {
1357 | maxListeners = max;
1358 | };
1359 |
1360 | var addEventListener = function(name, handler) {
1361 | if (!handler) {
1362 | delete events[name];
1363 | return;
1364 | }
1365 |
1366 | var handlers = events[name];
1367 | if (!handlers) {
1368 | handlers = [];
1369 | events[name] = handlers;
1370 | }
1371 | handlers.push(handler);
1372 | if (handlers.length > maxListeners) {
1373 | console.warn("More than " + maxListeners + " added to event " + name);
1374 | }
1375 | };
1376 |
1377 | var removeEventListener = function(name, handler) {
1378 | if (!handler) {
1379 | delete events[name];
1380 | return;
1381 | }
1382 |
1383 | var handlers = events[name];
1384 | if (handlers) {
1385 | var ndx = handlers.indexOf(handler);
1386 | if (ndx >= 0) {
1387 | handlers.splice(ndx, 1);
1388 | }
1389 | }
1390 | };
1391 |
1392 | var removeAllEventListeners = function() {
1393 | events = {};
1394 | };
1395 |
1396 | var emit = function(name) {
1397 | var handlers = events[name];
1398 | if (handlers) {
1399 | var args = Array.prototype.slice.call(arguments, 1);
1400 | handlers.forEach(function(handler) {
1401 | handler.apply(this, args);
1402 | });
1403 | }
1404 | };
1405 |
1406 | var listeners = function(name) {
1407 | return events[name];
1408 | };
1409 |
1410 | this.on = addEventListener;
1411 | this.addEventListener = addEventListener
1412 | this.removeEventListener = removeEventListener
1413 | this.removeAllEventListeners = removeAllEventListeners;
1414 | this.addListener = addEventListener
1415 | this.removeListener = removeEventListener
1416 | this.removeAllListeners = removeAllEventListeners;
1417 | this.emit = emit;
1418 | this.listeners = listeners;
1419 | this.setMaxListeners = setMaxListeners;
1420 | };
1421 |
1422 | return EventEmitter;
1423 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
1424 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
1425 |
1426 |
1427 |
1428 | /***/ })
1429 | /******/ ]);
--------------------------------------------------------------------------------