Browse Source

Merge branch 'feature-tianyong' into gym-test

TIANYONG 8 months ago
parent
commit
773a4a1830
100 changed files with 0 additions and 4909 deletions
  1. 0 1
      dist/css/index-aa672475.css
  2. 0 0
      dist/css/index-bbc78b9d.css
  3. 0 1
      dist/css/index-e2246bb5.css
  4. 0 0
      dist/css/instrument-babfb2c2.css
  5. 0 1
      dist/css/modeView-c4c5480d.css
  6. BIN
      dist/favicon.ico
  7. 0 68
      dist/flexible.js
  8. 0 14
      dist/helpers/html-to-image.js
  9. 0 19
      dist/helpers/html2canvas.js
  10. 0 0
      dist/helpers/lottie.min.js
  11. 0 0
      dist/helpers/plyr.css
  12. 0 0
      dist/helpers/plyr.min.js
  13. 0 0
      dist/helpers/qrcode.js
  14. 0 6
      dist/helpers/qs.min.js
  15. 0 4
      dist/helpers/rem-fit.min.js
  16. 0 0
      dist/js/index-03bddf2b.js
  17. 0 0
      dist/js/index-03c84c67.js
  18. 0 0
      dist/js/index-0bbf84fb.js
  19. 0 0
      dist/js/index-0d3b7b42.js
  20. 0 0
      dist/js/index-142fdf16.js
  21. 0 0
      dist/js/index-20c025d3.js
  22. 0 0
      dist/js/index-2270f2d1.js
  23. 0 0
      dist/js/index-2499965c.js
  24. 0 0
      dist/js/index-2a1343e0.js
  25. 0 0
      dist/js/index-330cb7c5.js
  26. 0 0
      dist/js/index-38262e39.js
  27. 0 0
      dist/js/index-4b43430a.js
  28. 0 0
      dist/js/index-58c2eaac.js
  29. 0 0
      dist/js/index-655a454b.js
  30. 0 0
      dist/js/index-6972bb98.js
  31. 0 0
      dist/js/index-71a277d3.js
  32. 0 0
      dist/js/index-7ad0b9f0.js
  33. 0 0
      dist/js/index-7f22768f.js
  34. 0 0
      dist/js/index-902205b3.js
  35. 0 0
      dist/js/index-91fbf033.js
  36. 0 0
      dist/js/index-97e45cdd.js
  37. 0 0
      dist/js/index-ad04d4cf.js
  38. 0 0
      dist/js/index-ad5b3309.js
  39. 0 0
      dist/js/index-c7652d9b.js
  40. 0 0
      dist/js/index-cef965b9.js
  41. 0 0
      dist/js/index-d0f39753.js
  42. 0 0
      dist/js/index-d13c0247.js
  43. 0 0
      dist/js/index-f01bef28.js
  44. 0 0
      dist/js/index-f23e3dbf.js
  45. 0 0
      dist/js/index-f5dd9e1d.js
  46. 0 0
      dist/js/index-f9270c49.js
  47. 0 0
      dist/js/index-legacy-0f6cde19.js
  48. 0 0
      dist/js/index-legacy-18f4a1c4.js
  49. 0 0
      dist/js/index-legacy-31794bdf.js
  50. 0 0
      dist/js/index-legacy-34e08e3e.js
  51. 0 0
      dist/js/index-legacy-36e7f78a.js
  52. 0 0
      dist/js/index-legacy-3851c136.js
  53. 0 0
      dist/js/index-legacy-3a02f1ea.js
  54. 0 0
      dist/js/index-legacy-3e4d4286.js
  55. 0 0
      dist/js/index-legacy-4514d1bb.js
  56. 0 0
      dist/js/index-legacy-457fb6fa.js
  57. 0 0
      dist/js/index-legacy-5fc4ec32.js
  58. 0 0
      dist/js/index-legacy-6888bad9.js
  59. 0 0
      dist/js/index-legacy-68c78177.js
  60. 0 0
      dist/js/index-legacy-733f2636.js
  61. 0 0
      dist/js/index-legacy-7e8508f0.js
  62. 0 0
      dist/js/index-legacy-7f19d6d4.js
  63. 0 0
      dist/js/index-legacy-9b4d7da4.js
  64. 0 0
      dist/js/index-legacy-a35707f4.js
  65. 0 0
      dist/js/index-legacy-ac9e06ec.js
  66. 0 0
      dist/js/index-legacy-b25f7627.js
  67. 0 0
      dist/js/index-legacy-b4dddc9f.js
  68. 0 0
      dist/js/index-legacy-c0c0450a.js
  69. 0 0
      dist/js/index-legacy-cb5028d7.js
  70. 0 0
      dist/js/index-legacy-d7f2e64d.js
  71. 0 0
      dist/js/index-legacy-d942ef39.js
  72. 0 0
      dist/js/index-legacy-eb6058b4.js
  73. 0 0
      dist/js/index-legacy-ec8184e8.js
  74. 0 0
      dist/js/index-legacy-f02b4e94.js
  75. 0 0
      dist/js/index-legacy-f4aeb5cd.js
  76. 0 0
      dist/js/index-legacy-f7c0163b.js
  77. 0 0
      dist/js/index-legacy-fbabd463.js
  78. 0 0
      dist/loading.json
  79. 0 11
      dist/loading.svg
  80. 0 24
      dist/midi/inc/jasmid/LICENSE
  81. 0 238
      dist/midi/inc/jasmid/midifile.js
  82. 0 102
      dist/midi/inc/jasmid/replayer.js
  83. 0 69
      dist/midi/inc/jasmid/stream.js
  84. 0 61
      dist/midi/inc/shim/Base64.js
  85. 0 81
      dist/midi/inc/shim/Base64binary.js
  86. 0 111
      dist/midi/inc/shim/WebAudioAPI.js
  87. 0 421
      dist/midi/inc/shim/WebMIDIAPI.js
  88. 0 179
      dist/midi/inc/tuna/README.md
  89. BIN
      dist/midi/inc/tuna/impulses/Sweetspot1M.wav
  90. BIN
      dist/midi/inc/tuna/impulses/impulse_guitar.wav
  91. BIN
      dist/midi/inc/tuna/impulses/impulse_rev.wav
  92. BIN
      dist/midi/inc/tuna/impulses/ir_rev_short.wav
  93. 0 2093
      dist/midi/inc/tuna/tuna.js
  94. 0 104
      dist/midi/index.html
  95. 0 85
      dist/midi/js/midi/audioDetect.js
  96. 0 161
      dist/midi/js/midi/gm.js
  97. 0 199
      dist/midi/js/midi/loader.js
  98. 0 380
      dist/midi/js/midi/player.js
  99. 0 150
      dist/midi/js/midi/plugin.audiotag.js
  100. 0 326
      dist/midi/js/midi/plugin.webaudio.js

+ 0 - 1
dist/css/index-aa672475.css

@@ -1 +0,0 @@
-body{overflow:hidden}._skeleton_li4n4_4{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_li4n4_15{width:100vw;height:auto;overflow:hidden;--header-height: 1.65333rem;background:transparent;position:relative}._detail_li4n4_15 ._mask_li4n4_23{position:absolute;z-index:6;width:100%;height:100%}._detail_li4n4_15 ._container_li4n4_29{margin:0;border-radius:.26667rem}._detail_li4n4_15 #osmdCanvasPage1{position:relative!important}._detail_li4n4_15 #musicAndSelection{height:initial!important;max-height:initial!important}._detail_li4n4_15 .smoothAnimationBox{height:0!important;overflow:hidden}._detail_li4n4_15 #cursorImg-0{margin-top:-20PX!important;opacity:0!important}._whiteBg_li4n4_48{background:#fff}

File diff suppressed because it is too large
+ 0 - 0
dist/css/index-bbc78b9d.css


+ 0 - 1
dist/css/index-e2246bb5.css

@@ -1 +0,0 @@
-._skeleton_vtlsh_1{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:.53333rem .8rem;background-color:#fff;z-index:1000;--van-skeleton-paragraph-height: .8rem}._detail_vtlsh_12{width:100vw;height:100vh;overflow:hidden;overflow-y:auto;--header-height: 1.65333rem;background:var(--container-background)}._detail_vtlsh_12 ._container_vtlsh_20{margin:0 .26667rem;border-radius:.26667rem}._detail_vtlsh_12 #musicAndSelection{overflow:initial!important;height:initial!important;max-height:initial!important}

File diff suppressed because it is too large
+ 0 - 0
dist/css/instrument-babfb2c2.css


+ 0 - 1
dist/css/modeView-c4c5480d.css

@@ -1 +0,0 @@
-._container_jp744_1{position:relative;width:7.41333rem;height:6.72rem;background:url(../png/icon_bg-d91f5fbc.png) no-repeat;background-size:contain;display:flex;flex-direction:column;padding-top:3.36rem}._close_jp744_11{position:absolute;right:0;top:.8rem;width:.64rem;height:.64rem}._title_jp744_18{margin-left:.37333rem;width:2.13333rem;display:block}._content_jp744_23{position:relative;padding:0 .34667rem .66667rem;font-size:.37333rem;font-weight:400;color:#333;line-height:.58667rem;z-index:10}._btns_jp744_32{margin:0 auto .61333rem;display:flex;justify-content:center;font-size:.42667rem;color:#777;line-height:.58667rem;text-align:center}._btns_jp744_32 ._btn_jp744_32{width:2.69333rem;height:.98667rem;cursor:pointer}._btns_jp744_32 ._btnCancel_jp744_46{margin-right:.26667rem}._btns_jp744_32 img{width:100%}

BIN
dist/favicon.ico


+ 0 - 68
dist/flexible.js

@@ -1,68 +0,0 @@
-! function (a, b) {
-  function c() {
-    try {
-      var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-      var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
-      var b = width > height ? height : width;
-      b / i > 640 && (b = 640 * i);
-      b / i < 375 && (b = 375 * i);
-      var c = b / 10;
-      // 老师端,fontsize计算
-      // if (window.location.search.includes('platform=pc') || window.location.search.includes('platform=PC')) {
-      //   c = width / 21.7;
-      // }
-      // console.log('fontSize:',c,'屏幕宽度:',width,'老师端:',window.location.search.includes('platform=pc'))
-      c = c || 64;
-      f.style.fontSize = c + "px", k.rem = a.rem = c
-      window.fontSize = c
-    } catch (error) {
-      f.style.fontSize = 37.5 + "px"
-      window.fontSize = 37.5
-    }
-
-  }
-  var d, e = a.document,
-    f = e.documentElement,
-    g = e.querySelector('meta[name="viewport"]'),
-    h = e.querySelector('meta[name="flexible"]'),
-    i = 0,
-    j = 0,
-    k = b.flexible || (b.flexible = {});
-  if (g) {
-    console.warn("将根据已有的meta标签来设置缩放比例");
-    var l = g.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
-    l && (j = parseFloat(l[1]), i = parseInt(1 / j))
-  } else if (h) {
-    var m = h.getAttribute("content");
-    if (m) {
-      var n = m.match(/initial\-dpr=([\d\.]+)/),
-        o = m.match(/maximum\-dpr=([\d\.]+)/);
-      n && (i = parseFloat(n[1]), j = parseFloat((1 / i).toFixed(2))), o && (i = parseFloat(o[1]), j = parseFloat((1 / i).toFixed(2)))
-    }
-  }
-  if (!i && !j) {
-    var p = a.navigator.userAgent,
-      q = (!!p.match(/android/gi), !!p.match(/iphone/gi)),
-      r = q && !!p.match(/OS 9_3/),
-      s = a.devicePixelRatio;
-    i = q && !r ? s >= 3 && (!i || i >= 3) ? 3 : s >= 2 && (!i || i >= 2) ? 2 : 1 : 1, j = 1 / i
-  }
-  if (f.setAttribute("data-dpr", i), !g)
-    if (g = e.createElement("meta"), g.setAttribute("name", "viewport"), g.setAttribute("content", "initial-scale=" + j + ", maximum-scale=" + j + ", minimum-scale=" + j + ", user-scalable=no"), f.firstElementChild) f.firstElementChild.appendChild(g);
-    else {
-      var t = e.createElement("div");
-      t.appendChild(g), e.write(t.innerHTML)
-    } a.addEventListener("resize", function () {
-    clearTimeout(d), d = setTimeout(c, 300)
-  }, !1), a.addEventListener("pageshow", function (a) {
-    a.persisted && (clearTimeout(d), d = setTimeout(c, 300))
-  }, !1), "complete" === e.readyState ? e.body.style.fontSize = 12 * i + "px" : e.addEventListener("DOMContentLoaded", function () {
-    e.body.style.fontSize = 12 * i + "px"
-  }, !1), c(), k.dpr = a.dpr = i, k.refreshRem = c, k.rem2px = function (a) {
-    var b = parseFloat(a) * this.rem;
-    return "string" == typeof a && a.match(/rem$/) && (b += "px"), b
-  }, k.px2rem = function (a) {
-    var b = parseFloat(a) / this.rem;
-    return "string" == typeof a && a.match(/px$/) && (b += "rem"), b
-  }
-}(window, window.lib || (window.lib = {}));

File diff suppressed because it is too large
+ 0 - 14
dist/helpers/html-to-image.js


File diff suppressed because it is too large
+ 0 - 19
dist/helpers/html2canvas.js


File diff suppressed because it is too large
+ 0 - 0
dist/helpers/lottie.min.js


File diff suppressed because it is too large
+ 0 - 0
dist/helpers/plyr.css


File diff suppressed because it is too large
+ 0 - 0
dist/helpers/plyr.min.js


File diff suppressed because it is too large
+ 0 - 0
dist/helpers/qrcode.js


File diff suppressed because it is too large
+ 0 - 6
dist/helpers/qs.min.js


File diff suppressed because it is too large
+ 0 - 4
dist/helpers/rem-fit.min.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-03bddf2b.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-03c84c67.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-0bbf84fb.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-0d3b7b42.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-142fdf16.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-20c025d3.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-2270f2d1.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-2499965c.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-2a1343e0.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-330cb7c5.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-38262e39.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-4b43430a.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-58c2eaac.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-655a454b.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-6972bb98.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-71a277d3.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-7ad0b9f0.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-7f22768f.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-902205b3.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-91fbf033.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-97e45cdd.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-ad04d4cf.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-ad5b3309.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-c7652d9b.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-cef965b9.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-d0f39753.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-d13c0247.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-f01bef28.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-f23e3dbf.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-f5dd9e1d.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-f9270c49.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-0f6cde19.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-18f4a1c4.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-31794bdf.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-34e08e3e.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-36e7f78a.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-3851c136.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-3a02f1ea.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-3e4d4286.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-4514d1bb.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-457fb6fa.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-5fc4ec32.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-6888bad9.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-68c78177.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-733f2636.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-7e8508f0.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-7f19d6d4.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-9b4d7da4.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-a35707f4.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-ac9e06ec.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-b25f7627.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-b4dddc9f.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-c0c0450a.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-cb5028d7.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-d7f2e64d.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-d942ef39.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-eb6058b4.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-ec8184e8.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-f02b4e94.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-f4aeb5cd.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-f7c0163b.js


File diff suppressed because it is too large
+ 0 - 0
dist/js/index-legacy-fbabd463.js


File diff suppressed because it is too large
+ 0 - 0
dist/loading.json


+ 0 - 11
dist/loading.svg

@@ -1,11 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin:auto;display:block;" width="100px" height="100px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
-<circle cx="27.5" cy="57.5" r="5" fill="#01c1b5">
-  <animate attributeName="cy" calcMode="spline" keySplines="0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5" repeatCount="indefinite" values="57.5;42.5;57.5;57.5" keyTimes="0;0.3;0.6;1" dur="1s" begin="-0.6s"></animate>
-</circle> <circle cx="42.5" cy="57.5" r="5" fill="#ff979e">
-  <animate attributeName="cy" calcMode="spline" keySplines="0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5" repeatCount="indefinite" values="57.5;42.5;57.5;57.5" keyTimes="0;0.3;0.6;1" dur="1s" begin="-0.44999999999999996s"></animate>
-</circle> <circle cx="57.5" cy="57.5" r="5" fill="#01c1b5">
-  <animate attributeName="cy" calcMode="spline" keySplines="0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5" repeatCount="indefinite" values="57.5;42.5;57.5;57.5" keyTimes="0;0.3;0.6;1" dur="1s" begin="-0.3s"></animate>
-</circle> <circle cx="72.5" cy="57.5" r="5" fill="#ff979e">
-  <animate attributeName="cy" calcMode="spline" keySplines="0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5" repeatCount="indefinite" values="57.5;42.5;57.5;57.5" keyTimes="0;0.3;0.6;1" dur="1s" begin="-0.15s"></animate>
-</circle>
-</svg>

+ 0 - 24
dist/midi/inc/jasmid/LICENSE

@@ -1,24 +0,0 @@
-Copyright (c) 2010, Matt Westcott & Ben Firshman
-All rights reserved.
- 
-Redistribution and use in source and binary forms, with or without 
-modification, are permitted provided that the following conditions are met:
- 
- * Redistributions of source code must retain the above copyright notice, this 
-   list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice, 
-   this list of conditions and the following disclaimer in the documentation 
-   and/or other materials provided with the distribution.
- * The names of its contributors may not be used to endorse or promote products 
-   derived from this software without specific prior written permission.
- 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 0 - 238
dist/midi/inc/jasmid/midifile.js

@@ -1,238 +0,0 @@
-/*
-class to parse the .mid file format
-(depends on stream.js)
-*/
-function MidiFile(data) {
-	function readChunk(stream) {
-		var id = stream.read(4);
-		var length = stream.readInt32();
-		return {
-			'id': id,
-			'length': length,
-			'data': stream.read(length)
-		};
-	}
-	
-	var lastEventTypeByte;
-	
-	function readEvent(stream) {
-		var event = {};
-		event.deltaTime = stream.readVarInt();
-		var eventTypeByte = stream.readInt8();
-		if ((eventTypeByte & 0xf0) == 0xf0) {
-			/* system / meta event */
-			if (eventTypeByte == 0xff) {
-				/* meta event */
-				event.type = 'meta';
-				var subtypeByte = stream.readInt8();
-				var length = stream.readVarInt();
-				switch(subtypeByte) {
-					case 0x00:
-						event.subtype = 'sequenceNumber';
-						if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length;
-						event.number = stream.readInt16();
-						return event;
-					case 0x01:
-						event.subtype = 'text';
-						event.text = stream.read(length);
-						return event;
-					case 0x02:
-						event.subtype = 'copyrightNotice';
-						event.text = stream.read(length);
-						return event;
-					case 0x03:
-						event.subtype = 'trackName';
-						event.text = stream.read(length);
-						return event;
-					case 0x04:
-						event.subtype = 'instrumentName';
-						event.text = stream.read(length);
-						return event;
-					case 0x05:
-						event.subtype = 'lyrics';
-						event.text = stream.read(length);
-						return event;
-					case 0x06:
-						event.subtype = 'marker';
-						event.text = stream.read(length);
-						return event;
-					case 0x07:
-						event.subtype = 'cuePoint';
-						event.text = stream.read(length);
-						return event;
-					case 0x20:
-						event.subtype = 'midiChannelPrefix';
-						if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length;
-						event.channel = stream.readInt8();
-						return event;
-					case 0x2f:
-						event.subtype = 'endOfTrack';
-						if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length;
-						return event;
-					case 0x51:
-						event.subtype = 'setTempo';
-						if (length != 3) throw "Expected length for setTempo event is 3, got " + length;
-						event.microsecondsPerBeat = (
-							(stream.readInt8() << 16)
-							+ (stream.readInt8() << 8)
-							+ stream.readInt8()
-						)
-						return event;
-					case 0x54:
-						event.subtype = 'smpteOffset';
-						if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length;
-						var hourByte = stream.readInt8();
-						event.frameRate = {
-							0x00: 24, 0x20: 25, 0x40: 29, 0x60: 30
-						}[hourByte & 0x60];
-						event.hour = hourByte & 0x1f;
-						event.min = stream.readInt8();
-						event.sec = stream.readInt8();
-						event.frame = stream.readInt8();
-						event.subframe = stream.readInt8();
-						return event;
-					case 0x58:
-						event.subtype = 'timeSignature';
-						if (length != 4) throw "Expected length for timeSignature event is 4, got " + length;
-						event.numerator = stream.readInt8();
-						event.denominator = Math.pow(2, stream.readInt8());
-						event.metronome = stream.readInt8();
-						event.thirtyseconds = stream.readInt8();
-						return event;
-					case 0x59:
-						event.subtype = 'keySignature';
-						if (length != 2) throw "Expected length for keySignature event is 2, got " + length;
-						event.key = stream.readInt8(true);
-						event.scale = stream.readInt8();
-						return event;
-					case 0x7f:
-						event.subtype = 'sequencerSpecific';
-						event.data = stream.read(length);
-						return event;
-					default:
-						// console.log("Unrecognised meta event subtype: " + subtypeByte);
-						event.subtype = 'unknown'
-						event.data = stream.read(length);
-						return event;
-				}
-				event.data = stream.read(length);
-				return event;
-			} else if (eventTypeByte == 0xf0) {
-				event.type = 'sysEx';
-				var length = stream.readVarInt();
-				event.data = stream.read(length);
-				return event;
-			} else if (eventTypeByte == 0xf7) {
-				event.type = 'dividedSysEx';
-				var length = stream.readVarInt();
-				event.data = stream.read(length);
-				return event;
-			} else {
-				throw "Unrecognised MIDI event type byte: " + eventTypeByte;
-			}
-		} else {
-			/* channel event */
-			var param1;
-			if ((eventTypeByte & 0x80) == 0) {
-				/* running status - reuse lastEventTypeByte as the event type.
-					eventTypeByte is actually the first parameter
-				*/
-				param1 = eventTypeByte;
-				eventTypeByte = lastEventTypeByte;
-			} else {
-				param1 = stream.readInt8();
-				lastEventTypeByte = eventTypeByte;
-			}
-			var eventType = eventTypeByte >> 4;
-			event.channel = eventTypeByte & 0x0f;
-			event.type = 'channel';
-			switch (eventType) {
-				case 0x08:
-					event.subtype = 'noteOff';
-					event.noteNumber = param1;
-					event.velocity = stream.readInt8();
-					return event;
-				case 0x09:
-					event.noteNumber = param1;
-					event.velocity = stream.readInt8();
-					if (event.velocity == 0) {
-						event.subtype = 'noteOff';
-					} else {
-						event.subtype = 'noteOn';
-					}
-					return event;
-				case 0x0a:
-					event.subtype = 'noteAftertouch';
-					event.noteNumber = param1;
-					event.amount = stream.readInt8();
-					return event;
-				case 0x0b:
-					event.subtype = 'controller';
-					event.controllerType = param1;
-					event.value = stream.readInt8();
-					return event;
-				case 0x0c:
-					event.subtype = 'programChange';
-					event.programNumber = param1;
-					return event;
-				case 0x0d:
-					event.subtype = 'channelAftertouch';
-					event.amount = param1;
-					return event;
-				case 0x0e:
-					event.subtype = 'pitchBend';
-					event.value = param1 + (stream.readInt8() << 7);
-					return event;
-				default:
-					throw "Unrecognised MIDI event type: " + eventType
-					/* 
-					console.log("Unrecognised MIDI event type: " + eventType);
-					stream.readInt8();
-					event.subtype = 'unknown';
-					return event;
-					*/
-			}
-		}
-	}
-	
-	stream = Stream(data);
-	var headerChunk = readChunk(stream);
-	if (headerChunk.id != 'MThd' || headerChunk.length != 6) {
-		throw "Bad .mid file - header not found";
-	}
-	var headerStream = Stream(headerChunk.data);
-	var formatType = headerStream.readInt16();
-	var trackCount = headerStream.readInt16();
-	var timeDivision = headerStream.readInt16();
-	
-	if (timeDivision & 0x8000) {
-		throw "Expressing time division in SMTPE frames is not supported yet"
-	} else {
-		ticksPerBeat = timeDivision;
-	}
-	
-	var header = {
-		'formatType': formatType,
-		'trackCount': trackCount,
-		'ticksPerBeat': ticksPerBeat
-	}
-	var tracks = [];
-	for (var i = 0; i < header.trackCount; i++) {
-		tracks[i] = [];
-		var trackChunk = readChunk(stream);
-		if (trackChunk.id != 'MTrk') {
-			throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id;
-		}
-		var trackStream = Stream(trackChunk.data);
-		while (!trackStream.eof()) {
-			var event = readEvent(trackStream);
-			tracks[i].push(event);
-			//console.log(event);
-		}
-	}
-	
-	return {
-		'header': header,
-		'tracks': tracks
-	}
-}

+ 0 - 102
dist/midi/inc/jasmid/replayer.js

@@ -1,102 +0,0 @@
-var clone = function (o) {
-	if (typeof o != 'object') return (o);
-	if (o == null) return (o);
-	var ret = (typeof o.length == 'number') ? [] : {};
-	for (var key in o) ret[key] = clone(o[key]);
-	return ret;
-};
-
-function Replayer(midiFile, timeWarp, eventProcessor, bpm) {
-	var trackStates = [];
-	var beatsPerMinute = bpm ? bpm : 120;
-	var bpmOverride = bpm ? true : false;
-
-	var ticksPerBeat = midiFile.header.ticksPerBeat;
-	
-	for (var i = 0; i < midiFile.tracks.length; i++) {
-		trackStates[i] = {
-			'nextEventIndex': 0,
-			'ticksToNextEvent': (
-				midiFile.tracks[i].length ?
-					midiFile.tracks[i][0].deltaTime :
-					null
-			)
-		};
-	}
-
-	var nextEventInfo;
-	var samplesToNextEvent = 0;
-	
-	function getNextEvent() {
-		var ticksToNextEvent = null;
-		var nextEventTrack = null;
-		var nextEventIndex = null;
-		
-		for (var i = 0; i < trackStates.length; i++) {
-			if (
-				trackStates[i].ticksToNextEvent != null
-				&& (ticksToNextEvent == null || trackStates[i].ticksToNextEvent < ticksToNextEvent)
-			) {
-				ticksToNextEvent = trackStates[i].ticksToNextEvent;
-				nextEventTrack = i;
-				nextEventIndex = trackStates[i].nextEventIndex;
-			}
-		}
-		if (nextEventTrack != null) {
-			/* consume event from that track */
-			var nextEvent = midiFile.tracks[nextEventTrack][nextEventIndex];
-			if (midiFile.tracks[nextEventTrack][nextEventIndex + 1]) {
-				trackStates[nextEventTrack].ticksToNextEvent += midiFile.tracks[nextEventTrack][nextEventIndex + 1].deltaTime;
-			} else {
-				trackStates[nextEventTrack].ticksToNextEvent = null;
-			}
-			trackStates[nextEventTrack].nextEventIndex += 1;
-			/* advance timings on all tracks by ticksToNextEvent */
-			for (var i = 0; i < trackStates.length; i++) {
-				if (trackStates[i].ticksToNextEvent != null) {
-					trackStates[i].ticksToNextEvent -= ticksToNextEvent
-				}
-			}
-			return {
-				"ticksToEvent": ticksToNextEvent,
-				"event": nextEvent,
-				"track": nextEventTrack
-			}
-		} else {
-			return null;
-		}
-	};
-	//
-	var midiEvent;
-	var temporal = [];
-	//
-	function processEvents() {
-		function processNext() {
-		    if (!bpmOverride && midiEvent.event.type == "meta" && midiEvent.event.subtype == "setTempo" ) {
-				// tempo change events can occur anywhere in the middle and affect events that follow
-				beatsPerMinute = 60000000 / midiEvent.event.microsecondsPerBeat;
-			}
-			///
-			var beatsToGenerate = 0;
-			var secondsToGenerate = 0;
-			if (midiEvent.ticksToEvent > 0) {
-				beatsToGenerate = midiEvent.ticksToEvent / ticksPerBeat;
-				secondsToGenerate = beatsToGenerate / (beatsPerMinute / 60);
-			}
-			///
-			var time = (secondsToGenerate * 1000 * timeWarp) || 0;
-			temporal.push([ midiEvent, time]);
-			midiEvent = getNextEvent();
-		};
-		///
-		if (midiEvent = getNextEvent()) {
-			while(midiEvent) processNext(true);
-		}
-	};
-	processEvents();
-	return {
-		"getData": function() {
-			return clone(temporal);
-		}
-	};
-};

+ 0 - 69
dist/midi/inc/jasmid/stream.js

@@ -1,69 +0,0 @@
-/* Wrapper for accessing strings through sequential reads */
-function Stream(str) {
-	var position = 0;
-	
-	function read(length) {
-		var result = str.substr(position, length);
-		position += length;
-		return result;
-	}
-	
-	/* read a big-endian 32-bit integer */
-	function readInt32() {
-		var result = (
-			(str.charCodeAt(position) << 24)
-			+ (str.charCodeAt(position + 1) << 16)
-			+ (str.charCodeAt(position + 2) << 8)
-			+ str.charCodeAt(position + 3));
-		position += 4;
-		return result;
-	}
-
-	/* read a big-endian 16-bit integer */
-	function readInt16() {
-		var result = (
-			(str.charCodeAt(position) << 8)
-			+ str.charCodeAt(position + 1));
-		position += 2;
-		return result;
-	}
-	
-	/* read an 8-bit integer */
-	function readInt8(signed) {
-		var result = str.charCodeAt(position);
-		if (signed && result > 127) result -= 256;
-		position += 1;
-		return result;
-	}
-	
-	function eof() {
-		return position >= str.length;
-	}
-	
-	/* read a MIDI-style variable-length integer
-		(big-endian value in groups of 7 bits,
-		with top bit set to signify that another byte follows)
-	*/
-	function readVarInt() {
-		var result = 0;
-		while (true) {
-			var b = readInt8();
-			if (b & 0x80) {
-				result += (b & 0x7f);
-				result <<= 7;
-			} else {
-				/* b is the last byte */
-				return result + b;
-			}
-		}
-	}
-	
-	return {
-		'eof': eof,
-		'read': read,
-		'readInt32': readInt32,
-		'readInt16': readInt16,
-		'readInt8': readInt8,
-		'readVarInt': readVarInt
-	}
-}

+ 0 - 61
dist/midi/inc/shim/Base64.js

@@ -1,61 +0,0 @@
-//https://github.com/davidchambers/Base64.js
-
-;(function () {
-  var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
-  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
-
-  function InvalidCharacterError(message) {
-    this.message = message;
-  }
-  InvalidCharacterError.prototype = new Error;
-  InvalidCharacterError.prototype.name = 'InvalidCharacterError';
-
-  // encoder
-  // [https://gist.github.com/999166] by [https://github.com/nignag]
-  object.btoa || (
-  object.btoa = function (input) {
-    for (
-      // initialize result and counter
-      var block, charCode, idx = 0, map = chars, output = '';
-      // if the next input index does not exist:
-      //   change the mapping table to "="
-      //   check if d has no fractional digits
-      input.charAt(idx | 0) || (map = '=', idx % 1);
-      // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
-      output += map.charAt(63 & block >> 8 - idx % 1 * 8)
-    ) {
-      charCode = input.charCodeAt(idx += 3/4);
-      if (charCode > 0xFF) {
-        throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
-      }
-      block = block << 8 | charCode;
-    }
-    return output;
-  });
-
-  // decoder
-  // [https://gist.github.com/1020396] by [https://github.com/atk]
-  object.atob || (
-  object.atob = function (input) {
-    input = input.replace(/=+$/, '')
-    if (input.length % 4 == 1) {
-      throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
-    }
-    for (
-      // initialize result and counters
-      var bc = 0, bs, buffer, idx = 0, output = '';
-      // get next character
-      buffer = input.charAt(idx++);
-      // character found in table? initialize bit storage and add its ascii value;
-      ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
-        // and if not first of each 4 characters,
-        // convert the first 8 bits to one ascii character
-        bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
-    ) {
-      // try to find character in table (0-63, not found => -1)
-      buffer = chars.indexOf(buffer);
-    }
-    return output;
-  });
-
-}());

+ 0 - 81
dist/midi/inc/shim/Base64binary.js

@@ -1,81 +0,0 @@
-/**
- * @license -------------------------------------------------------------------
- *   module: Base64Binary
- *      src: http://blog.danguer.com/2011/10/24/base64-binary-decoding-in-javascript/
- *  license: Simplified BSD License
- * -------------------------------------------------------------------
- * Copyright 2011, Daniel Guerrero. All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     - Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     - Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL DANIEL GUERRERO BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-var Base64Binary = {
-	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
-
-	/* will return a  Uint8Array type */
-	decodeArrayBuffer: function(input) {
-		var bytes = Math.ceil( (3*input.length) / 4.0);
-		var ab = new ArrayBuffer(bytes);
-		this.decode(input, ab);
-
-		return ab;
-	},
-
-	decode: function(input, arrayBuffer) {
-		//get last chars to see if are valid
-		var lkey1 = this._keyStr.indexOf(input.charAt(input.length-1));		 
-		var lkey2 = this._keyStr.indexOf(input.charAt(input.length-1));		 
-
-		var bytes = Math.ceil( (3*input.length) / 4.0);
-		if (lkey1 == 64) bytes--; //padding chars, so skip
-		if (lkey2 == 64) bytes--; //padding chars, so skip
-
-		var uarray;
-		var chr1, chr2, chr3;
-		var enc1, enc2, enc3, enc4;
-		var i = 0;
-		var j = 0;
-
-		if (arrayBuffer)
-			uarray = new Uint8Array(arrayBuffer);
-		else
-			uarray = new Uint8Array(bytes);
-
-		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-		for (i=0; i<bytes; i+=3) {	
-			//get the 3 octects in 4 ascii chars
-			enc1 = this._keyStr.indexOf(input.charAt(j++));
-			enc2 = this._keyStr.indexOf(input.charAt(j++));
-			enc3 = this._keyStr.indexOf(input.charAt(j++));
-			enc4 = this._keyStr.indexOf(input.charAt(j++));
-
-			chr1 = (enc1 << 2) | (enc2 >> 4);
-			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-			chr3 = ((enc3 & 3) << 6) | enc4;
-
-			uarray[i] = chr1;			
-			if (enc3 != 64) uarray[i+1] = chr2;
-			if (enc4 != 64) uarray[i+2] = chr3;
-		}
-
-		return uarray;	
-	}
-};

+ 0 - 111
dist/midi/inc/shim/WebAudioAPI.js

@@ -1,111 +0,0 @@
-/**
- * @license -------------------------------------------------------------------
- *   module: WebAudioShim - Fix naming issues for WebAudioAPI supports
- *      src: https://github.com/Dinahmoe/webaudioshim
- *   author: Dinahmoe AB
- * -------------------------------------------------------------------
- * Copyright (c) 2012 DinahMoe AB
- * 
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-window.AudioContext = window.AudioContext || window.webkitAudioContext || null;
-window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext || null;
-
-(function (Context) {
-	var isFunction = function (f) {
-		return Object.prototype.toString.call(f) === "[object Function]" ||
-			Object.prototype.toString.call(f) === "[object AudioContextConstructor]";
-	};
-	var contextMethods = [
-		["createGainNode", "createGain"],
-		["createDelayNode", "createDelay"],
-		["createJavaScriptNode", "createScriptProcessor"]
-	];
-	///
-	var proto;
-	var instance;
-	var sourceProto;
-	///
-	if (!isFunction(Context)) {
-		return;
-	}
-	instance = new Context();
-	if (!instance.destination || !instance.sampleRate) {
-		return;
-	}
-	proto = Context.prototype;
-	sourceProto = Object.getPrototypeOf(instance.createBufferSource());
-
-	if (!isFunction(sourceProto.start)) {
-		if (isFunction(sourceProto.noteOn)) {
-			sourceProto.start = function (when, offset, duration) {
-				switch (arguments.length) {
-					case 0:
-						throw new Error("Not enough arguments.");
-					case 1:
-						this.noteOn(when);
-						break;
-					case 2:
-						if (this.buffer) {
-							this.noteGrainOn(when, offset, this.buffer.duration - offset);
-						} else {
-							throw new Error("Missing AudioBuffer");
-						}
-						break;
-					case 3:
-						this.noteGrainOn(when, offset, duration);
-				}
-			};
-		}
-	}
-
-	if (!isFunction(sourceProto.noteOn)) {
-		sourceProto.noteOn = sourceProto.start;
-	}
-
-	if (!isFunction(sourceProto.noteGrainOn)) {
-		sourceProto.noteGrainOn = sourceProto.start;
-	}
-
-	if (!isFunction(sourceProto.stop)) {
-		sourceProto.stop = sourceProto.noteOff;
-	}
-
-	if (!isFunction(sourceProto.noteOff)) {
-		sourceProto.noteOff = sourceProto.stop;
-	}
-
-	contextMethods.forEach(function (names) {
-		var name1;
-		var name2;
-		while (names.length) {
-			name1 = names.pop();
-			if (isFunction(this[name1])) {
-				this[names.pop()] = this[name1];
-			} else {
-				name2 = names.pop();
-				this[name1] = this[name2];
-			}
-		}
-	}, proto);
-})(window.AudioContext);

+ 0 - 421
dist/midi/inc/shim/WebMIDIAPI.js

@@ -1,421 +0,0 @@
-/* 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.
-   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.
-*/
-
-// Initialize the MIDI library.
-(function (global) {
-    'use strict';
-    var midiIO, _requestMIDIAccess, MIDIAccess, _onReady, MIDIPort, MIDIInput, MIDIOutput, _midiProc;
-
-    function Promise() {
-
-    }
-
-    Promise.prototype.then = function(accept, reject) {
-        this.accept = accept; 
-        this.reject = reject;
-    }
-
-    Promise.prototype.succeed = function(access) {
-        if (this.accept)
-            this.accept(access);
-    }
-
-    Promise.prototype.fail = function(error) {
-        if (this.reject)
-            this.reject(error);
-    }
-
-    function _JazzInstance() {
-        this.inputInUse = false;
-        this.outputInUse = false;
-
-        // load the Jazz plugin
-        var o1 = document.createElement("object");
-        o1.id = "_Jazz" + Math.random() + "ie";
-        o1.classid = "CLSID:1ACE1618-1C7D-4561-AEE1-34842AA85E90";
-
-        this.activeX = o1;
-
-        var o2 = document.createElement("object");
-        o2.id = "_Jazz" + Math.random();
-        o2.type="audio/x-jazz";
-        o1.appendChild(o2);
-
-        this.objRef = o2;
-
-        var e = document.createElement("p");
-        e.appendChild(document.createTextNode("This page requires the "));
-
-        var a = document.createElement("a");
-        a.appendChild(document.createTextNode("Jazz plugin"));
-        a.href = "http://jazz-soft.net/";
-
-        e.appendChild(a);
-        e.appendChild(document.createTextNode("."));
-        o2.appendChild(e);
-
-        var insertionPoint = document.getElementById("MIDIPlugin");
-        if (!insertionPoint) {
-            // Create hidden element
-            var insertionPoint = document.createElement("div");
-            insertionPoint.id = "MIDIPlugin";
-            insertionPoint.style.position = "absolute";
-            insertionPoint.style.visibility = "hidden";
-            insertionPoint.style.left = "-9999px";
-            insertionPoint.style.top = "-9999px";
-            document.body.appendChild(insertionPoint);
-        }
-        insertionPoint.appendChild(o1);
-
-        if (this.objRef.isJazz)
-            this._Jazz = this.objRef;
-        else if (this.activeX.isJazz)
-            this._Jazz = this.activeX;
-        else
-            this._Jazz = null;
-        if (this._Jazz) {
-            this._Jazz._jazzTimeZero = this._Jazz.Time();
-            this._Jazz._perfTimeZero = window.performance.now();
-        }
-    }
-
-    _requestMIDIAccess = function _requestMIDIAccess() {
-        var access = new MIDIAccess();
-        return access._promise;
-    };
-
-    // API Methods
-
-    MIDIAccess = function() {
-        this._jazzInstances = new Array();
-        this._jazzInstances.push( new _JazzInstance() );
-        this._promise = new Promise;
-
-        if (this._jazzInstances[0]._Jazz) {
-            this._Jazz = this._jazzInstances[0]._Jazz;
-            window.setTimeout( _onReady.bind(this), 3 );
-        } else {
-            window.setTimeout( _onNotReady.bind(this), 3 );
-        }
-    };
-
-    _onReady = function _onReady() {
-        if (this._promise)
-            this._promise.succeed(this);
-    };
-
-    function _onNotReady() {
-        if (this._promise)
-            this._promise.fail( { code: 1 } );
-    };
-
-    MIDIAccess.prototype.inputs = function(  ) {
-        if (!this._Jazz)
-              return null;
-        var list=this._Jazz.MidiInList();
-        var inputs = new Array( list.length );
-
-        for ( var i=0; i<list.length; i++ ) {
-            inputs[i] = new MIDIInput( this, list[i], i );
-        }
-        return inputs;
-    }
-
-    MIDIAccess.prototype.outputs = function(  ) {
-        if (!this._Jazz)
-            return null;
-        var list=this._Jazz.MidiOutList();
-        var outputs = new Array( list.length );
-
-        for ( var i=0; i<list.length; i++ ) {
-            outputs[i] = new MIDIOutput( this, list[i], i );
-        }
-        return outputs;
-    };
-
-    MIDIInput = function MIDIInput( midiAccess, name, index ) {
-        this._listeners = [];
-        this._midiAccess = midiAccess;
-        this._index = index;
-        this._inLongSysexMessage = false;
-        this._sysexBuffer = new Uint8Array();
-        this.id = "" + index + "." + name;
-        this.manufacturer = "";
-        this.name = name;
-        this.type = "input";
-        this.version = "";
-        this.onmidimessage = null;
-
-        var inputInstance = null;
-        for (var i=0; (i<midiAccess._jazzInstances.length)&&(!inputInstance); i++) {
-            if (!midiAccess._jazzInstances[i].inputInUse)
-                inputInstance=midiAccess._jazzInstances[i];
-        }
-        if (!inputInstance) {
-            inputInstance = new _JazzInstance();
-            midiAccess._jazzInstances.push( inputInstance );
-        }
-        inputInstance.inputInUse = true;
-
-        this._jazzInstance = inputInstance._Jazz;
-        this._input = this._jazzInstance.MidiInOpen( this._index, _midiProc.bind(this) );
-    };
-
-    // Introduced in DOM Level 2:
-    MIDIInput.prototype.addEventListener = function (type, listener, useCapture ) {
-        if (type !== "midimessage")
-            return;
-        for (var i=0; i<this._listeners.length; i++)
-            if (this._listeners[i] == listener)
-                return;
-        this._listeners.push( listener );
-    };
-
-    MIDIInput.prototype.removeEventListener = function (type, listener, useCapture ) {
-        if (type !== "midimessage")
-            return;
-        for (var i=0; i<this._listeners.length; i++)
-            if (this._listeners[i] == listener) {
-                this._listeners.splice( i, 1 );  //remove it
-                return;
-            }
-    };
-
-    MIDIInput.prototype.preventDefault = function() {
-        this._pvtDef = true;
-    };
-
-    MIDIInput.prototype.dispatchEvent = function (evt) {
-        this._pvtDef = false;
-
-        // dispatch to listeners
-        for (var i=0; i<this._listeners.length; i++)
-            if (this._listeners[i].handleEvent)
-                this._listeners[i].handleEvent.bind(this)( evt );
-            else
-                this._listeners[i].bind(this)( evt );
-
-        if (this.onmidimessage)
-            this.onmidimessage( evt );
-
-        return this._pvtDef;
-    };
-
-    MIDIInput.prototype.appendToSysexBuffer = function ( data ) {
-        var oldLength = this._sysexBuffer.length;
-        var tmpBuffer = new Uint8Array( oldLength + data.length );
-        tmpBuffer.set( this._sysexBuffer );
-        tmpBuffer.set( data, oldLength );
-        this._sysexBuffer = tmpBuffer;
-    };
-
-    MIDIInput.prototype.bufferLongSysex = function ( data, initialOffset ) {
-        var j = initialOffset;
-        while (j<data.length) {
-            if (data[j] == 0xF7) {
-                // end of sysex!
-                j++;
-                this.appendToSysexBuffer( data.slice(initialOffset, j) );
-                return j;
-            }
-            j++;
-        }
-        // didn't reach the end; just tack it on.
-        this.appendToSysexBuffer( data.slice(initialOffset, j) );
-        this._inLongSysexMessage = true;
-        return j;
-    };
-
-    _midiProc = function _midiProc( timestamp, data ) {
-        // Have to use createEvent/initEvent because IE10 fails on new CustomEvent.  Thanks, IE!
-        var length = 0;
-        var i,j;
-        var isSysexMessage = false;
-
-        // Jazz sometimes passes us multiple messages at once, so we need to parse them out
-        // and pass them one at a time.
-
-        for (i=0; i<data.length; i+=length) {
-            if (this._inLongSysexMessage) {
-                i = this.bufferLongSysex(data,i);
-                if ( data[i-1] != 0xf7 ) {
-                    // ran off the end without hitting the end of the sysex message
-                    return;
-                }
-                isSysexMessage = true;
-            } else {
-                isSysexMessage = false;
-                switch (data[i] & 0xF0) {
-                    case 0x80:  // note off
-                    case 0x90:  // note on
-                    case 0xA0:  // polyphonic aftertouch
-                    case 0xB0:  // control change
-                    case 0xE0:  // channel mode
-                        length = 3;
-                        break;
-
-                    case 0xC0:  // program change
-                    case 0xD0:  // channel aftertouch
-                        length = 2;
-                        break;
-
-                    case 0xF0:
-                        switch (data[i]) {
-                            case 0xf0:  // variable-length sysex.
-                                i = this.bufferLongSysex(data,i);
-                                if ( data[i-1] != 0xf7 ) {
-                                    // ran off the end without hitting the end of the sysex message
-                                    return;
-                                }
-                                isSysexMessage = true;
-                                break;
-
-                            case 0xF1:  // MTC quarter frame
-                            case 0xF3:  // song select
-                                length = 2;
-                                break;
-
-                            case 0xF2:  // song position pointer
-                                length = 3;
-                                break;
-
-                            default:
-                                length = 1;
-                                break;
-                        }
-                        break;
-                }
-            }
-            var evt = document.createEvent( "Event" );
-            evt.initEvent( "midimessage", false, false );
-            evt.receivedTime = parseFloat( timestamp.toString()) + this._jazzInstance._perfTimeZero;
-            if (isSysexMessage || this._inLongSysexMessage) {
-                evt.data = new Uint8Array( this._sysexBuffer );
-                this._sysexBuffer = new Uint8Array(0);
-                this._inLongSysexMessage = false;
-            } else
-                evt.data = new Uint8Array(data.slice(i, length+i));
-            this.dispatchEvent( evt );
-        }
-    };
-
-    MIDIOutput = function MIDIOutput( midiAccess, name, index ) {
-        this._listeners = [];
-        this._midiAccess = midiAccess;
-        this._index = index;
-        this.id = "" + index + "." + name;
-        this.manufacturer = "";
-        this.name = name;
-        this.type = "output";
-        this.version = "";
-
-        var outputInstance = null;
-        for (var i=0; (i<midiAccess._jazzInstances.length)&&(!outputInstance); i++) {
-            if (!midiAccess._jazzInstances[i].outputInUse)
-                outputInstance=midiAccess._jazzInstances[i];
-        }
-        if (!outputInstance) {
-            outputInstance = new _JazzInstance();
-            midiAccess._jazzInstances.push( outputInstance );
-        }
-        outputInstance.outputInUse = true;
-
-        this._jazzInstance = outputInstance._Jazz;
-        this._jazzInstance.MidiOutOpen(this.name);
-    };
-
-    function _sendLater() {
-        this.jazz.MidiOutLong( this.data );    // handle send as sysex
-    }
-
-    MIDIOutput.prototype.send = function( data, timestamp ) {
-        var delayBeforeSend = 0;
-        if (data.length === 0)
-            return false;
-
-        if (timestamp)
-            delayBeforeSend = Math.floor( timestamp - window.performance.now() );
-
-        if (timestamp && (delayBeforeSend>1)) {
-            var sendObj = new Object();
-            sendObj.jazz = this._jazzInstance;
-            sendObj.data = data;
-
-            window.setTimeout( _sendLater.bind(sendObj), delayBeforeSend );
-        } else {
-            this._jazzInstance.MidiOutLong( data );
-        }
-        return true;
-    };
-
-    //init: create plugin
-    if (!window.navigator.requestMIDIAccess)
-        window.navigator.requestMIDIAccess = _requestMIDIAccess;
-
-}(window));
-
-// Polyfill window.performance.now() if necessary.
-(function (exports) {
-    var perf = {}, props;
-
-    function findAlt() {
-        var prefix = ['moz', 'webkit', 'o', 'ms'],
-        i = prefix.length,
-            //worst case, we use Date.now()
-            props = {
-                value: (function (start) {
-                    return function () {
-                        return Date.now() - start;
-                    };
-                }(Date.now()))
-            };
-
-        //seach for vendor prefixed version
-        for (; i >= 0; i--) {
-            if ((prefix[i] + "Now") in exports.performance) {
-                props.value = function (method) {
-                    return function () {
-                        exports.performance[method]();
-                    }
-                }(prefix[i] + "Now");
-                return props;
-            }
-        }
-
-        //otherwise, try to use connectionStart
-        if ("timing" in exports.performance && "connectStart" in exports.performance.timing) {
-            //this pretty much approximates performance.now() to the millisecond
-            props.value = (function (start) {
-                return function() {
-                    Date.now() - start;
-                };
-            }(exports.performance.timing.connectStart));
-        }
-        return props;
-    }
-
-    //if already defined, bail
-    if (("performance" in exports) && ("now" in exports.performance))
-        return;
-    if (!("performance" in exports))
-        Object.defineProperty(exports, "performance", {
-            get: function () {
-                return perf;
-            }});
-        //otherwise, performance is there, but not "now()"
-
-    props = findAlt();
-    Object.defineProperty(exports.performance, "now", props);
-}(window));

+ 0 - 179
dist/midi/inc/tuna/README.md

@@ -1,179 +0,0 @@
-Latest news
-====
-New effects added: Chorus, Phaser, and Tremolo. <br /> Be sure to follow us at <a href="https://twitter.com/DinahmoeSTHLM">@DinahmoeSTHLM</a> for future updates. Feel free to create your own effects and give us a pull request!
-
-tuna
-====
-
-An audio effects library for the Web Audio API. Created by <a href="http://www.dinahmoe.com">DinahMoe</a>
-
-<img src="https://i.chzbgr.com/completestore/12/9/4/rjttPiC7WE6S4Bi22aYp1A2.jpg" alt="tuna, tuna, tuna"/>
-
-Effect list:
-====
-<ul>
-    <li>Overdrive (6 different algorithms)</li>
-    <li>Filter</li>
-    <li>Cabinet</li>
-    <li>Delay</li>
-    <li>Convolver (Reverb)</li>
-    <li>Compressor</li>
-    <li>WahWah</li>
-    <li>Tremolo</li>
-    <li>Phaser</li>
-    <li>Chorus</li>
-</ul>
-
-Usage
-====
-
-Start by creating a new Tuna object like so:
-
-<pre>
-var context = new webkitAudioContext();
-var tuna = new Tuna(context);
-</pre>
-
-You need to pass the audio context you're using in your application. Tuna will be using it to create its effects.
-
-You create a new tuna node as such:
-
-<pre>
-var chorus = new tuna.Chorus({
-                 rate: 1.5,
-                 feedback: 0.2,
-                 delay: 0.0045,
-                 bypass: 0
-             });
-</pre>
-You can then connect the tuna node to native Web Audio nodes by doing:
-<pre>
-nativeNode.connect(chorus.input);
-chorus.connect(anotherNativeNode);
-</pre>
-or to other tuna nodes by doing:
-<pre>
-tunaNode.connect(chorus.input);
-chorus.connect(anotherTunaNode.input);
-</pre>
-All tuna nodes are connected TO by using the nodes input property, but connecting FROM the tuna node works as it does with ordinary native AudioNodes.
-
-
-The nodes
-====
-
-A basic chorus effect.
-<pre>
-var chorus = new tuna.Chorus({
-                 rate: 1.5,         //0.01 to 8+
-                 feedback: 0.2,     //0 to 1+
-                 delay: 0.0045,     //0 to 1
-                 bypass: 0          //the value 1 starts the effect as bypassed, 0 or 1
-             });
-</pre>
-
-A delay effect with feedback and a highpass filter applied to the delayed signal.
-<pre>
-var delay = new tuna.Delay({
-                feedback: 0.45,    //0 to 1+
-                delayTime: 150,    //how many milliseconds should the wet signal be delayed? 
-                wetLevel: 0.25,    //0 to 1+
-                dryLevel: 1,       //0 to 1+
-                cutoff: 20,        //cutoff frequency of the built in highpass-filter. 20 to 22050
-                bypass: 0
-            });
-</pre>
-
-A basic phaser effect.
-<pre>
-var phaser = new tuna.Phaser({
-                 rate: 1.2,                     //0.01 to 8 is a decent range, but higher values are possible
-                 depth: 0.3,                    //0 to 1
-                 feedback: 0.2,                 //0 to 1+
-                 stereoPhase: 30,               //0 to 180
-                 baseModulationFrequency: 700,  //500 to 1500
-                 bypass: 0
-             });
-</pre>
-
-A basic overdrive effect.
-<pre>
-var overdrive = new tuna.Overdrive({
-                    outputGain: 0.5,         //0 to 1+
-                    drive: 0.7,              //0 to 1
-                    curveAmount: 1,          //0 to 1
-                    algorithmIndex: 0,       //0 to 5, selects one of our drive algorithms
-                    bypass: 0
-                });
-</pre>
-
-A compressor with the option to use automatic makeup gain.
-<pre>
-var compressor = new tuna.Compressor({
-                     threshold: 0.5,    //-100 to 0
-                     makeupGain: 1,     //0 and up
-                     attack: 1,         //0 to 1000
-                     release: 0,        //0 to 3000
-                     ratio: 4,          //1 to 20
-                     knee: 5,           //0 to 40
-                     automakeup: true,  //true/false
-                     bypass: 0
-                 });
-</pre>
-
-A convolver with high- and lowcut. You can find a lot of impulse resonses <a href="http://chromium.googlecode.com/svn/trunk/samples/audio/impulse-responses/">here</a>
-<pre>
-var convolver = new tuna.Convolver({
-                    highCut: 22050,                         //20 to 22050
-                    lowCut: 20,                             //20 to 22050
-                    dryLevel: 1,                            //0 to 1+
-                    wetLevel: 1,                            //0 to 1+
-                    level: 1,                               //0 to 1+, adjusts total output of both wet and dry
-                    impulse: "impulses/impulse_rev.wav",    //the path to your impulse response
-                    bypass: 0
-                });
-</pre>
-
-A basic filter.
-<pre>
-var filter = new tuna.Filter({
-                 frequency: 20,         //20 to 22050
-                 Q: 1,                  //0.001 to 100
-                 gain: 0,               //-40 to 40
-                 bypass: 1,             //0 to 1+
-                 filterType: 0,         //0 to 7, corresponds to the filter types in the native filter node: lowpass, highpass, bandpass, lowshelf, highshelf, peaking, notch, allpass in that order
-                 bypass: 0
-             });
-</pre>
-
-A cabinet/speaker emulator.
-<pre>
-var cabinet = new tuna.Cabinet({
-                  makeupGain: 1,                                 //0 to 20
-                  impulsePath: "impulses/impulse_guitar.wav",    //path to your speaker impulse
-                  bypass: 0
-              });
-</pre>
-
-A basic tremolo.
-<pre>
-var tremolo = new tuna.Tremolo({
-                  intensity: 0.3,    //0 to 1
-                  rate: 0.1,         //0.001 to 8
-                  stereoPhase: 0,    //0 to 180
-                  bypass: 0
-              });
-</pre>
-
-A wahwah with an auto wah option.
-<pre>
-var wahwah = new tuna.WahWah({
-                 automode: true,                //true/false
-                 baseFrequency: 0.5,            //0 to 1
-                 excursionOctaves: 2,           //1 to 6
-                 sweep: 0.2,                    //0 to 1
-                 resonance: 10,                 //1 to 100
-                 sensitivity: 0.5,              //-1 to 1
-                 bypass: 0
-             });
-</pre>

BIN
dist/midi/inc/tuna/impulses/Sweetspot1M.wav


BIN
dist/midi/inc/tuna/impulses/impulse_guitar.wav


BIN
dist/midi/inc/tuna/impulses/impulse_rev.wav


BIN
dist/midi/inc/tuna/impulses/ir_rev_short.wav


+ 0 - 2093
dist/midi/inc/tuna/tuna.js

@@ -1,2093 +0,0 @@
-/*
-    Copyright (c) 2012 DinahMoe AB
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
-    files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
-    modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
-    is furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-    OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    
-    Bitcrusher & Moog Filter by Zach Denton
-*/
-
-// https://developer.mozilla.org/en-US/docs/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
-
-// Originally written by Alessandro Saccoia, Chris Coniglio and Oskar Eriksson
-
-(function (window) {
-    var userContext;
-    var userInstance;
-    var Tuna = function (context) {
-			if (!window.AudioContext) {
-				window.AudioContext = window.webkitAudioContext;
-			}
-            if (!context) {
-                console.log("tuna.js: Missing audio context! Creating a new context for you.");
-                context = window.AudioContext && (new window.AudioContext());
-            }
-            userContext = context;
-            userInstance = this;
-        },
-        version = "0.1",
-        set = "setValueAtTime",
-        linear = "linearRampToValueAtTime",
-        pipe = function (param, val) {
-            param.value = val;
-        },
-        Super = Object.create(null, {
-            activate: {
-                writable: true,
-                value: function (doActivate) {
-                    if (doActivate) {
-                        this.input.disconnect();
-                        this.input.connect(this.activateNode);
-                        if (this.activateCallback) {
-                            this.activateCallback(doActivate);
-                        }
-                    } else {
-                        this.input.disconnect();
-                        this.input.connect(this.output);
-                    }
-                }
-            },
-            bypass: {
-                get: function () {
-                    return this._bypass;
-                },
-                set: function (value) {
-                    if (this._lastBypassValue === value) {
-                        return;
-                    }
-                    this._bypass = value;
-                    this.activate(!value);
-                    this._lastBypassValue = value;
-                }
-            },
-            connect: {
-                value: function (target) {
-                    this.output.connect(target);
-                }
-            },
-            disconnect: {
-                value: function (target) {
-                    this.output.disconnect(target);
-                }
-            },
-            connectInOrder: {
-                value: function (nodeArray) {
-                    var i = nodeArray.length - 1;
-                    while(i--) {
-                        if (!nodeArray[i].connect) {
-                            return console.error("AudioNode.connectInOrder: TypeError: Not an AudioNode.", nodeArray[i]);
-                        }
-                        if (nodeArray[i + 1].input) {
-                            nodeArray[i].connect(nodeArray[i + 1].input);
-                        } else {
-                            nodeArray[i].connect(nodeArray[i + 1]);
-                        }
-                    }
-                }
-            },
-            getDefaults: {
-                value: function () {
-                    var result = {};
-                    for(var key in this.defaults) {
-                        result[key] = this.defaults[key].value;
-                    }
-                    return result;
-                }
-            },
-            getValues: {
-                value: function () {
-                    var result = {};
-                    for(var key in this.defaults) {
-                        result[key] = this[key];
-                    }
-                    return result;
-                }
-            },
-            automate: {
-                value: function (property, value, duration, startTime) {
-                    var start = startTime ? ~~ (startTime / 1000) : userContext.currentTime,
-                        dur = duration ? ~~ (duration / 1000) : 0,
-                        _is = this.defaults[property],
-                        param = this[property],
-                        method;
-
-                    if (param) {
-                        if (_is.automatable) {
-                            if (!duration) {
-                                method = set;
-                            } else {
-                                method = linear;
-                                param.cancelScheduledValues(start);
-                                param.setValueAtTime(param.value, start);
-                            }
-                            param[method](value, dur + start);
-                        } else {
-                            param = value;
-                        }
-                    } else {
-                        console.error("Invalid Property for " + this.name);
-                    }
-                }
-            }
-        }),
-        FLOAT = "float",
-        BOOLEAN = "boolean",
-        STRING = "string",
-        INT = "int";
-
-    function dbToWAVolume(db) {
-        return Math.max(0, Math.round(100 * Math.pow(2, db / 6)) / 100);
-    }
-
-    function fmod(x, y) {
-        // http://kevin.vanzonneveld.net
-        // +   original by: Onno Marsman
-        // +      input by: Brett Zamir (http://brett-zamir.me)
-        // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
-        // *     example 1: fmod(5.7, 1.3);
-        // *     returns 1: 0.5
-        var tmp, tmp2, p = 0,
-            pY = 0,
-            l = 0.0,
-            l2 = 0.0;
-
-        tmp = x.toExponential().match(/^.\.?(.*)e(.+)$/);
-        p = parseInt(tmp[2], 10) - (tmp[1] + '').length;
-        tmp = y.toExponential().match(/^.\.?(.*)e(.+)$/);
-        pY = parseInt(tmp[2], 10) - (tmp[1] + '').length;
-
-        if (pY > p) {
-            p = pY;
-        }
-
-        tmp2 = (x % y);
-
-        if (p < -100 || p > 20) {
-            // toFixed will give an out of bound error so we fix it like this:
-            l = Math.round(Math.log(tmp2) / Math.log(10));
-            l2 = Math.pow(10, l);
-
-            return(tmp2 / l2).toFixed(l - p) * l2;
-        } else {
-            return parseFloat(tmp2.toFixed(-p));
-        }
-    }
-
-    function sign(x) {
-        if (x === 0) {
-            return 1;
-        } else {
-            return Math.abs(x) / x;
-        }
-    }
-
-    function tanh(n) {
-        return(Math.exp(n) - Math.exp(-n)) / (Math.exp(n) + Math.exp(-n));
-    }
-
-    Tuna.toString = Tuna.prototype.toString = function () {
-        return "You are running Tuna version " + version + " by Dinahmoe!";
-    };
-    Tuna.prototype.Filter = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.filter = userContext.createBiquadFilter();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.filter);
-        this.filter.connect(this.output);
-
-        this.frequency = properties.frequency || this.defaults.frequency.value;
-        this.Q = properties.resonance || this.defaults.Q.value;
-        this.filterType = properties.filterType || this.defaults.filterType.value;
-        this.gain = properties.gain || this.defaults.gain.value;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Filter.prototype = Object.create(Super, {
-        name: {
-            value: "Filter"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                frequency: {
-                    value: 800,
-                    min: 20,
-                    max: 22050,
-                    automatable: true
-                },
-                Q: {
-                    value: 1,
-                    min: 0.001,
-                    max: 100,
-                    automatable: true
-                },
-                gain: {
-                    value: 0,
-                    min: -40,
-                    max: 40,
-                    automatable: true
-                },
-                bypass: {
-                    value: true,
-                    automatable: false,
-                    type: BOOLEAN
-                },
-                filterType: {
-                    value: 1,
-                    min: 0,
-                    max: 7,
-                    automatable: false,
-                    type: INT
-                }
-            }
-        },
-        filterType: {
-            enumerable: true,
-            get: function () {
-                return this.filter.type;
-            },
-            set: function (value) {
-                this.filter.type = value;
-            }
-        },
-        Q: {
-            enumerable: true,
-            get: function () {
-                return this.filter.Q;
-            },
-            set: function (value) {
-                this.filter.Q.value = value;
-            }
-        },
-        gain: {
-            enumerable: true,
-            get: function () {
-                return this.filter.gain;
-            },
-            set: function (value) {
-                this.filter.gain.value = value;
-            }
-        },
-        frequency: {
-            enumerable: true,
-            get: function () {
-                return this.filter.frequency;
-            },
-            set: function (value) {
-                this.filter.frequency.value = value;
-            }
-        }
-    });
-    Tuna.prototype.Bitcrusher = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.bufferSize = properties.bufferSize || this.defaults.bufferSize.value;
-
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.processor = userContext.createScriptProcessor(this.bufferSize, 1, 1);
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.processor);
-        this.processor.connect(this.output);
-
-        var phaser = 0, last = 0;
-        this.processor.onaudioprocess = function (e) {
-            var input = e.inputBuffer.getChannelData(0),
-                output = e.outputBuffer.getChannelData(0),
-                step = Math.pow(1/2, this.bits);
-            for(var i = 0; i < input.length; i++) {
-                phaser += this.normfreq;
-                if (phaser >= 1.0) {
-                    phaser -= 1.0;
-                    last = step * Math.floor(input[i] / step + 0.5);
-                }
-                output[i] = last;
-            }
-        };
-
-        this.bits = properties.bits || this.defaults.bits.value;
-        this.normfreq = properties.normfreq || this.defaults.normfreq.value;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Bitcrusher.prototype = Object.create(Super, {
-        name: {
-            value: "Bitcrusher"
-        },
-        defaults: {
-            writable: true,
-            value: {
-                bits: {
-                    value: 4,
-                    min: 1,
-                    max: 16,
-                    automatable: false,
-                    type: INT
-                },
-                bufferSize: {
-                    value: 4096,
-                    min: 256,
-                    max: 16384,
-                    automatable: false,
-                    type: INT
-                },
-                bypass: {
-                    value: false,
-                    automatable: false,
-                    type: BOOLEAN
-                },
-                normfreq: {
-                    value: 0.1,
-                    min: 0.0001,
-                    max: 1.0,
-                    automatable: false,
-                }
-            }
-        },
-        bits: {
-            enumerable: true,
-            get: function () {
-                return this.processor.bits;
-            },
-            set: function (value) {
-                this.processor.bits = value;
-            }
-        },
-        normfreq: {
-            enumerable: true,
-            get: function () {
-                return this.processor.normfreq;
-            },
-            set: function (value) {
-                this.processor.normfreq = value;
-            }
-        }
-    });
-    Tuna.prototype.Cabinet = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.convolver = this.newConvolver(properties.impulsePath || "../impulses/impulse_guitar.wav");
-        this.makeupNode = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.convolver.input);
-        this.convolver.output.connect(this.makeupNode);
-        this.makeupNode.connect(this.output);
-
-        this.makeupGain = properties.makeupGain || this.defaults.makeupGain;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Cabinet.prototype = Object.create(Super, {
-        name: {
-            value: "Cabinet"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                makeupGain: {
-                    value: 1,
-                    min: 0,
-                    max: 20,
-                    automatable: true
-                },
-                bypass: {
-                    value: false,
-                    automatable: false,
-                    type: BOOLEAN
-                }
-            }
-        },
-        makeupGain: {
-            enumerable: true,
-            get: function () {
-                return this.makeupNode.gain;
-            },
-            set: function (value) {
-                this.makeupNode.gain.value = value;
-            }
-        },
-        newConvolver: {
-            value: function (impulsePath) {
-                return new userInstance.Convolver({
-                    impulse: impulsePath,
-                    dryLevel: 0,
-                    wetLevel: 1
-                });
-            }
-        }
-    });
-    Tuna.prototype.Chorus = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.attenuator = this.activateNode = userContext.createGain();
-        this.splitter = userContext.createChannelSplitter(2);
-        this.delayL = userContext.createDelayNode();
-        this.delayR = userContext.createDelayNode();
-        this.feedbackGainNodeLR = userContext.createGain();
-        this.feedbackGainNodeRL = userContext.createGain();
-        this.merger = userContext.createChannelMerger(2);
-        this.output = userContext.createGain();
-
-        this.lfoL = new userInstance.LFO({
-            target: this.delayL.delayTime,
-            callback: pipe
-        });
-        this.lfoR = new userInstance.LFO({
-            target: this.delayR.delayTime,
-            callback: pipe
-        });
-
-        this.input.connect(this.attenuator);
-        this.attenuator.connect(this.output);
-        this.attenuator.connect(this.splitter);
-        this.splitter.connect(this.delayL, 0);
-        this.splitter.connect(this.delayR, 1);
-        this.delayL.connect(this.feedbackGainNodeLR);
-        this.delayR.connect(this.feedbackGainNodeRL);
-        this.feedbackGainNodeLR.connect(this.delayR);
-        this.feedbackGainNodeRL.connect(this.delayL);
-        this.delayL.connect(this.merger, 0, 0);
-        this.delayR.connect(this.merger, 0, 1);
-        this.merger.connect(this.output);
-
-        this.feedback = properties.feedback || this.defaults.feedback.value;
-        this.rate = properties.rate || this.defaults.rate.value;
-        this.delay = properties.delay || this.defaults.delay.value;
-        this.depth = properties.depth || this.defaults.depth.value;
-        this.lfoR.phase = Math.PI / 2;
-        this.attenuator.gain.value = 0.6934; // 1 / (10 ^ (((20 * log10(3)) / 3) / 20))
-        this.lfoL.activate(true);
-        this.lfoR.activate(true);
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Chorus.prototype = Object.create(Super, {
-        name: {
-            value: "Chorus"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                feedback: {
-                    value: 0.4,
-                    min: 0,
-                    max: 0.95,
-                    automatable: false,
-                },
-                delay: {
-                    value: 0.0045,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                depth: {
-                    value: 0.7,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                rate: {
-                    value: 1.5,
-                    min: 0,
-                    max: 8,
-                    automatable: false,
-                },
-                bypass: {
-                    value: true,
-                    automatable: false,
-                    type: BOOLEAN
-                }
-            }
-        },
-        delay: {
-            enumerable: true,
-            get: function () {
-                return this._delay;
-            },
-            set: function (value) {
-                this._delay = 0.0002 * (Math.pow(10, value) * 2);
-                this.lfoL.offset = this._delay;
-                this.lfoR.offset = this._delay;
-                this._depth = this._depth;
-            }
-        },
-        depth: {
-            enumerable: true,
-            get: function () {
-                return this._depth;
-            },
-            set: function (value) {
-                this._depth = value;
-                this.lfoL.oscillation = this._depth * this._delay;
-                this.lfoR.oscillation = this._depth * this._delay;
-            }
-        },
-        feedback: {
-            enumerable: true,
-            get: function () {
-                return this._feedback;
-            },
-            set: function (value) {
-                this._feedback = value;
-                this.feedbackGainNodeLR.gain.value = this._feedback;
-                this.feedbackGainNodeRL.gain.value = this._feedback;
-            }
-        },
-        rate: {
-            enumerable: true,
-            get: function () {
-                return this._rate;
-            },
-            set: function (value) {
-                this._rate = value;
-                this.lfoL.frequency = this._rate;
-                this.lfoR.frequency = this._rate;
-            }
-        }
-    });
-    Tuna.prototype.Compressor = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.compNode = this.activateNode = userContext.createDynamicsCompressor();
-        this.makeupNode = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.compNode.connect(this.makeupNode);
-        this.makeupNode.connect(this.output);
-
-        this.automakeup = properties.automakeup || this.defaults.automakeup.value;
-        this.makeupGain = properties.makeupGain || this.defaults.makeupGain.value;
-        this.threshold = properties.threshold || this.defaults.threshold.value;
-        this.release = properties.release || this.defaults.release.value;
-        this.attack = properties.attack || this.defaults.attack.value;
-        this.ratio = properties.ratio || this.defaults.ratio.value;
-        this.knee = properties.knee || this.defaults.knee.value;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Compressor.prototype = Object.create(Super, {
-        name: {
-            value: "Compressor"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                threshold: {
-                    value: -20,
-                    min: -60,
-                    max: 0,
-                    automatable: true
-                },
-                release: {
-                    value: 250,
-                    min: 10,
-                    max: 2000,
-                    automatable: true
-                },
-                makeupGain: {
-                    value: 1,
-                    min: 1,
-                    max: 100,
-                    automatable: true
-                },
-                attack: {
-                    value: 1,
-                    min: 0,
-                    max: 1000,
-                    automatable: true
-                },
-                ratio: {
-                    value: 4,
-                    min: 1,
-                    max: 50,
-                    automatable: true
-                },
-                knee: {
-                    value: 5,
-                    min: 0,
-                    max: 40,
-                    automatable: true
-                },
-                automakeup: {
-                    value: false,
-                    automatable: false,
-                    type: BOOLEAN
-                },
-                bypass: {
-                    value: true,
-                    automatable: false,
-                    type: BOOLEAN
-                }
-            }
-        },
-        computeMakeup: {
-            value: function () {
-                var magicCoefficient = 4,
-                    // raise me if the output is too hot
-                    c = this.compNode;
-                return -(c.threshold.value - c.threshold.value / c.ratio.value) / magicCoefficient;
-            }
-        },
-        automakeup: {
-            enumerable: true,
-            get: function () {
-                return this._automakeup;
-            },
-            set: function (value) {
-                this._automakeup = value;
-                if (this._automakeup) this.makeupGain = this.computeMakeup();
-            }
-        },
-        threshold: {
-            enumerable: true,
-            get: function () {
-                return this.compNode.threshold;
-            },
-            set: function (value) {
-                this.compNode.threshold.value = value;
-                if (this._automakeup) this.makeupGain = this.computeMakeup();
-            }
-        },
-        ratio: {
-            enumerable: true,
-            get: function () {
-                return this.compNode.ratio;
-            },
-            set: function (value) {
-                this.compNode.ratio.value = value;
-                if (this._automakeup) this.makeupGain = this.computeMakeup();
-            }
-        },
-        knee: {
-            enumerable: true,
-            get: function () {
-                return this.compNode.knee;
-            },
-            set: function (value) {
-                this.compNode.knee.value = value;
-                if (this._automakeup) this.makeupGain = this.computeMakeup();
-            }
-        },
-        attack: {
-            enumerable: true,
-            get: function () {
-                return this.compNode.attack;
-            },
-            set: function (value) {
-                this.compNode.attack.value = value / 1000;
-            }
-        },
-        release: {
-            enumerable: true,
-            get: function () {
-                return this.compNode.release;
-            },
-            set: function (value) {
-                this.compNode.release = value / 1000;
-            }
-        },
-        makeupGain: {
-            enumerable: true,
-            get: function () {
-                return this.makeupNode.gain;
-            },
-            set: function (value) {
-                this.makeupNode.gain.value = dbToWAVolume(value);
-            }
-        }
-    });
-    Tuna.prototype.Convolver = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.convolver = userContext.createConvolver();
-        this.dry = userContext.createGain();
-        this.filterLow = userContext.createBiquadFilter();
-        this.filterHigh = userContext.createBiquadFilter();
-        this.wet = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.filterLow);
-        this.activateNode.connect(this.dry);
-        this.filterLow.connect(this.filterHigh);
-        this.filterHigh.connect(this.convolver);
-        this.convolver.connect(this.wet);
-        this.wet.connect(this.output);
-        this.dry.connect(this.output);
-
-        this.dryLevel = properties.dryLevel || this.defaults.dryLevel.value;
-        this.wetLevel = properties.wetLevel || this.defaults.wetLevel.value;
-        this.highCut = properties.highCut || this.defaults.highCut.value;
-        this.buffer = properties.impulse || "../impulses/ir_rev_short.wav";
-        this.lowCut = properties.lowCut || this.defaults.lowCut.value;
-        this.level = properties.level || this.defaults.level.value;
-        this.filterHigh.type = this.filterHigh.LOWPASS;
-        this.filterLow.type = this.filterHigh.HIGHPASS;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Convolver.prototype = Object.create(Super, {
-        name: {
-            value: "Convolver"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                highCut: {
-                    value: 22050,
-                    min: 20,
-                    max: 22050,
-                    automatable: true
-                },
-                lowCut: {
-                    value: 20,
-                    min: 20,
-                    max: 22050,
-                    automatable: true
-                },
-                dryLevel: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true
-                },
-                wetLevel: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true
-                },
-                level: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true
-                }
-            }
-        },
-        lowCut: {
-            get: function () {
-                return this.filterLow.frequency;
-            },
-            set: function (value) {
-                this.filterLow.frequency.value = value;
-            }
-        },
-        highCut: {
-            get: function () {
-                return this.filterHigh.frequency;
-            },
-            set: function (value) {
-                this.filterHigh.frequency.value = value;
-            }
-        },
-        level: {
-            get: function () {
-                return this.output.gain;
-            },
-            set: function (value) {
-                this.output.gain.value = value;
-            }
-        },
-        dryLevel: {
-            get: function () {
-                return this.dry.gain
-            },
-            set: function (value) {
-                this.dry.gain.value = value;
-            }
-        },
-        wetLevel: {
-            get: function () {
-                return this.wet.gain;
-            },
-            set: function (value) {
-                this.wet.gain.value = value;
-            }
-        },
-        buffer: {
-            enumerable: false,
-            get: function () {
-                return this.convolver.buffer;
-            },
-            set: function (impulse) {
-                var convolver = this.convolver,
-                    xhr = new XMLHttpRequest();
-                if (!impulse) {
-                    console.log("Tuna.Convolver.setBuffer: Missing impulse path!");
-                    return;
-                }
-                xhr.open("GET", impulse, true);
-                xhr.responseType = "arraybuffer";
-                xhr.onreadystatechange = function () {
-                    if (xhr.readyState === 4) {
-                        if (xhr.status < 300 && xhr.status > 199 || xhr.status === 302) {
-                            userContext.decodeAudioData(xhr.response, function (buffer) {
-                                convolver.buffer = buffer;
-                            }, function (e) {
-                                if (e) console.log("Tuna.Convolver.setBuffer: Error decoding data" + e);
-                            });
-                        }
-                    }
-                };
-                xhr.send(null);
-            }
-        }
-    });
-    Tuna.prototype.Delay = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.dry = userContext.createGain();
-        this.wet = userContext.createGain();
-        this.filter = userContext.createBiquadFilter();
-        this.delay = userContext.createDelayNode();
-        this.feedbackNode = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.delay);
-        this.activateNode.connect(this.dry);
-        this.delay.connect(this.filter);
-        this.filter.connect(this.feedbackNode);
-        this.feedbackNode.connect(this.delay);
-        this.feedbackNode.connect(this.wet);
-        this.wet.connect(this.output);
-        this.dry.connect(this.output);
-
-        this.delayTime = properties.delayTime || this.defaults.delayTime.value;
-        this.feedback = properties.feedback || this.defaults.feedback.value;
-        this.wetLevel = properties.wetLevel || this.defaults.wetLevel.value;
-        this.dryLevel = properties.dryLevel || this.defaults.dryLevel.value;
-        this.cutoff = properties.cutoff || this.defaults.cutoff.value;
-        this.filter.type = this.filter.LOWPASS;
-        this.bypass = properties.bypass || false;
-    };
-    
-    Tuna.prototype.Delay.prototype = Object.create(Super, {
-        name: {
-            value: "Delay"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                delayTime: {
-                    value: 100,
-                    min: 20,
-                    max: 1000,
-                    automatable: false,
-                },
-                feedback: {
-                    value: 0.45,
-                    min: 0,
-                    max: 0.9,
-                    automatable: true
-                },
-                cutoff: {
-                    value: 20000,
-                    min: 20,
-                    max: 20000,
-                    automatable: true
-                },
-                wetLevel: {
-                    value: 0.5,
-                    min: 0,
-                    max: 1,
-                    automatable: true
-                },
-                dryLevel: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true
-                }
-            }
-        },
-        delayTime: {
-            enumerable: true,
-            get: function () {
-                return this.delay.delayTime;
-            },
-            set: function (value) {
-                this.delay.delayTime.value = value / 1000;
-            }
-        },
-        wetLevel: {
-            enumerable: true,
-            get: function () {
-                return this.wet.gain;
-            },
-            set: function (value) {
-                this.wet.gain.value = value;
-            }
-        },
-        dryLevel: {
-            enumerable: true,
-            get: function () {
-                return this.dry.gain;
-            },
-            set: function (value) {
-                this.dry.gain.value = value;
-            }
-        },
-        feedback: {
-            enumerable: true,
-            get: function () {
-                return this.feedbackNode.gain;
-            },
-            set: function (value) {
-                this.feedbackNode.gain.value = value;
-            }
-        },
-        cutoff: {
-            enumerable: true,
-            get: function () {
-                return this.filter.frequency;
-            },
-            set: function (value) {
-                this.filter.frequency.value = value;
-            }
-        }
-    });
-    Tuna.prototype.MoogFilter = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.bufferSize = properties.bufferSize || this.defaults.bufferSize.value;
-
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.processor = userContext.createScriptProcessor(this.bufferSize, 1, 1);
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.processor);
-        this.processor.connect(this.output);
-
-        var in1, in2, in3, in4, out1, out2, out3, out4;
-        in1 = in2 = in3 = in4 = out1 = out2 = out3 = out4 = 0.0;
-        this.processor.onaudioprocess = function (e) {
-            var input = e.inputBuffer.getChannelData(0),
-                output = e.outputBuffer.getChannelData(0),
-                f = this.cutoff * 1.16,
-                fb = this.resonance * (1.0 - 0.15 * f * f);
-            for(var i = 0; i < input.length; i++) {
-                input[i] -= out4 * fb;
-                input[i] *= 0.35013 * (f*f)*(f*f);
-                out1 = input[i] + 0.3 * in1 + (1 - f) * out1; // Pole 1
-                in1 = input[i];
-                out2 = out1 + 0.3 * in2 + (1 - f) * out2; // Pole 2
-                in2 = out1;
-                out3 = out2 + 0.3 * in3 + (1 - f) * out3; // Pole 3
-                in3 = out2;
-                out4 = out3 + 0.3 * in4 + (1 - f) * out4; // Pole 4
-                in4 = out3;
-                output[i] = out4;
-            }
-        };
-
-        this.cutoff = properties.cutoff || this.defaults.cutoff.value;
-        this.resonance = properties.resonance || this.defaults.resonance.value;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.MoogFilter.prototype = Object.create(Super, {
-        name: {
-            value: "MoogFilter"
-        },
-        defaults: {
-            writable: true,
-            value: {
-                bufferSize: {
-                    value: 4096,
-                    min: 256,
-                    max: 16384,
-                    automatable: false,
-                    type: INT
-                },
-                bypass: {
-                    value: false,
-                    automatable: false,
-                    type: BOOLEAN
-                },
-                cutoff: {
-                    value: 0.065,
-                    min: 0.0001,
-                    max: 1.0,
-                    automatable: false,
-                },
-                resonance: {
-                    value: 3.5,
-                    min: 0.0,
-                    max: 4.0,
-                    automatable: false,
-                }
-            }
-        },
-        cutoff: {
-            enumerable: true,
-            get: function () {
-                return this.processor.cutoff;
-            },
-            set: function (value) {
-                this.processor.cutoff = value;
-            }
-        },
-        resonance: {
-            enumerable: true,
-            get: function () {
-                return this.processor.resonance;
-            },
-            set: function (value) {
-                this.processor.resonance = value;
-            }
-        }
-    });
-    Tuna.prototype.Overdrive = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.inputDrive = userContext.createGain();
-        this.waveshaper = userContext.createWaveShaper();
-        this.outputDrive = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.inputDrive);
-        this.inputDrive.connect(this.waveshaper);
-        this.waveshaper.connect(this.outputDrive);
-        this.outputDrive.connect(this.output);
-
-        this.ws_table = new Float32Array(this.k_nSamples);
-        this.drive = properties.drive || this.defaults.drive.value;
-        this.outputGain = properties.outputGain || this.defaults.outputGain.value;
-        this.curveAmount = properties.curveAmount || this.defaults.curveAmount.value;
-        this.algorithmIndex = properties.algorithmIndex || this.defaults.algorithmIndex.value;
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Overdrive.prototype = Object.create(Super, {
-        name: {
-            value: "Overdrive"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                drive: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true,
-                    type: FLOAT,
-                    scaled: true
-                },
-                outputGain: {
-                    value: 1,
-                    min: 0,
-                    max: 1,
-                    automatable: true,
-                    type: FLOAT,
-                    scaled: true
-                },
-                curveAmount: {
-                    value: 0.725,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                algorithmIndex: {
-                    value: 0,
-                    min: 0,
-                    max: 5,
-                    automatable: false,
-                    type: INT
-                }
-            }
-        },
-        k_nSamples: {
-            value: 8192
-        },
-        drive: {
-            get: function () {
-                return this.inputDrive.gain;
-            },
-            set: function (value) {
-                this._drive = value;
-            }
-        },
-        curveAmount: {
-            get: function () {
-                return this._curveAmount;
-            },
-            set: function (value) {
-                this._curveAmount = value;
-                if (this._algorithmIndex === undefined) {
-                    this._algorithmIndex = 0;
-                }
-                this.waveshaperAlgorithms[this._algorithmIndex](this._curveAmount, this.k_nSamples, this.ws_table);
-                this.waveshaper.curve = this.ws_table;
-            }
-        },
-        outputGain: {
-            get: function () {
-                return this.outputDrive.gain;
-            },
-            set: function (value) {
-                this._outputGain = dbToWAVolume(value);
-            }
-        },
-        algorithmIndex: {
-            get: function () {
-                return this._algorithmIndex;
-            },
-            set: function (value) {
-                this._algorithmIndex = value>>0;
-                this.curveAmount = this._curveAmount;
-            }
-        },
-        waveshaperAlgorithms: {
-            value: [
-
-            function (amount, n_samples, ws_table) {
-                amount = Math.min(amount, 0.9999);
-                var k = 2 * amount / (1 - amount),
-                    i, x;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    ws_table[i] = (1 + k) * x / (1 + k * Math.abs(x));
-                }
-            }, function (amount, n_samples, ws_table) {
-                var i, x, y;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    y = ((0.5 * Math.pow((x + 1.4), 2)) - 1) * y >= 0 ? 5.8 : 1.2;
-                    ws_table[i] = tanh(y);
-                }
-            }, function (amount, n_samples, ws_table) {
-                var i, x, y, a = 1 - amount;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    y = x < 0 ? -Math.pow(Math.abs(x), a + 0.04) : Math.pow(x, a);
-                    ws_table[i] = tanh(y * 2);
-                }
-            }, function (amount, n_samples, ws_table) {
-                var i, x, y, abx, a = 1 - amount > 0.99 ? 0.99 : 1 - amount;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    abx = Math.abs(x);
-                    if (abx < a) y = abx;
-                    else if (abx > a) y = a + (abx - a) / (1 + Math.pow((abx - a) / (1 - a), 2));
-                    else if (abx > 1) y = abx;
-                    ws_table[i] = sign(x) * y * (1 / ((a + 1) / 2));
-                }
-            }, function (amount, n_samples, ws_table) { // fixed curve, amount doesn't do anything, the distortion is just from the drive
-                var i, x;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    if (x < -0.08905) {
-                        ws_table[i] = (-3 / 4) * (1 - (Math.pow((1 - (Math.abs(x) - 0.032857)), 12)) + (1 / 3) * (Math.abs(x) - 0.032847)) + 0.01;
-                    } else if (x >= -0.08905 && x < 0.320018) {
-                        ws_table[i] = (-6.153 * (x * x)) + 3.9375 * x;
-                    } else {
-                        ws_table[i] = 0.630035;
-                    }
-                }
-            }, function (amount, n_samples, ws_table) {
-                var a = 2 + Math.round(amount * 14),
-                    // we go from 2 to 16 bits, keep in mind for the UI
-                    bits = Math.round(Math.pow(2, a - 1)),
-                    // real number of quantization steps divided by 2
-                    i, x;
-                for(i = 0; i < n_samples; i++) {
-                    x = i * 2 / n_samples - 1;
-                    ws_table[i] = Math.round(x * bits) / bits;
-                }
-            }]
-        }
-    });
-    Tuna.prototype.Phaser = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.splitter = this.activateNode = userContext.createChannelSplitter(2);
-        this.filtersL = [];
-        this.filtersR = [];
-        this.feedbackGainNodeL = userContext.createGain();
-        this.feedbackGainNodeR = userContext.createGain();
-        this.merger = userContext.createChannelMerger(2);
-        this.filteredSignal = userContext.createGain();
-        this.output = userContext.createGain();
-        this.lfoL = new userInstance.LFO({
-            target: this.filtersL,
-            callback: this.callback
-        });
-        this.lfoR = new userInstance.LFO({
-            target: this.filtersR,
-            callback: this.callback
-        });
-
-        var i = this.stage;
-        while(i--) {
-            this.filtersL[i] = userContext.createBiquadFilter();
-            this.filtersR[i] = userContext.createBiquadFilter();
-            this.filtersL[i].type = this.filtersL[i].ALLPASS;
-            this.filtersR[i].type = this.filtersR[i].ALLPASS;
-        }
-        this.input.connect(this.splitter);
-        this.input.connect(this.output);
-        this.splitter.connect(this.filtersL[0], 0, 0);
-        this.splitter.connect(this.filtersR[0], 1, 0);
-        this.connectInOrder(this.filtersL);
-        this.connectInOrder(this.filtersR);
-        this.filtersL[this.stage - 1].connect(this.feedbackGainNodeL);
-        this.filtersL[this.stage - 1].connect(this.merger, 0, 0);
-        this.filtersR[this.stage - 1].connect(this.feedbackGainNodeR);
-        this.filtersR[this.stage - 1].connect(this.merger, 0, 1);
-        this.feedbackGainNodeL.connect(this.filtersL[0]);
-        this.feedbackGainNodeR.connect(this.filtersR[0]);
-        this.merger.connect(this.output);
-
-        this.rate = properties.rate || this.defaults.rate.value;
-        this.baseModulationFrequency = properties.baseModulationFrequency || this.defaults.baseModulationFrequency.value;
-        this.depth = properties.depth || this.defaults.depth.value;
-        this.feedback = properties.feedback || this.defaults.feedback.value;
-        this.stereoPhase = properties.stereoPhase || this.defaults.stereoPhase.value;
-
-        this.lfoL.activate(true);
-        this.lfoR.activate(true);
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Phaser.prototype = Object.create(Super, {
-        name: {
-            value: "Phaser"
-        },
-        stage: {
-            value: 4
-        },
-        defaults: {
-            writable:true,
-            value: {
-                rate: {
-                    value: 0.1,
-                    min: 0,
-                    max: 8,
-                    automatable: false,
-                },
-                depth: {
-                    value: 0.6,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                feedback: {
-                    value: 0.7,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                stereoPhase: {
-                    value: 40,
-                    min: 0,
-                    max: 180,
-                    automatable: false,
-                },
-                baseModulationFrequency: {
-                    value: 700,
-                    min: 500,
-                    max: 1500,
-                    automatable: false,
-                }
-            }
-        },
-        callback: {
-            value: function (filters, value) {
-                for(var stage = 0; stage < 4; stage++) {
-                    filters[stage].frequency.value = value;
-                }
-            }
-        },
-        depth: {
-            get: function () {
-                return this._depth;
-            },
-            set: function (value) {
-                this._depth = value;
-                this.lfoL.oscillation = this._baseModulationFrequency * this._depth;
-                this.lfoR.oscillation = this._baseModulationFrequency * this._depth;
-            }
-        },
-        rate: {
-            get: function () {
-                return this._rate;
-            },
-            set: function (value) {
-                this._rate = value;
-                this.lfoL.frequency = this._rate;
-                this.lfoR.frequency = this._rate;
-            }
-        },
-        baseModulationFrequency: {
-            enumerable: true,
-            get: function () {
-                return this._baseModulationFrequency;
-            },
-            set: function (value) {
-                this._baseModulationFrequency = value;
-                this.lfoL.offset = this._baseModulationFrequency;
-                this.lfoR.offset = this._baseModulationFrequency;
-                this._depth = this._depth;
-            }
-        },
-        feedback: {
-            get: function () {
-                return this._feedback;
-            },
-            set: function (value) {
-                this._feedback = value;
-                this.feedbackGainNodeL.gain.value = this._feedback;
-                this.feedbackGainNodeR.gain.value = this._feedback;
-            }
-        },
-        stereoPhase: {
-            get: function () {
-                return this._stereoPhase;
-            },
-            set: function (value) {
-                this._stereoPhase = value;
-                var newPhase = this.lfoL._phase + this._stereoPhase * Math.PI / 180;
-                newPhase = fmod(newPhase, 2 * Math.PI);
-                this.lfoR._phase = newPhase;
-            }
-        }
-    });
-    Tuna.prototype.Tremolo = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.splitter = this.activateNode = userContext.createChannelSplitter(2), this.amplitudeL = userContext.createGain(), this.amplitudeR = userContext.createGain(), this.merger = userContext.createChannelMerger(2), this.output = userContext.createGain();
-        this.lfoL = new userInstance.LFO({
-            target: this.amplitudeL.gain,
-            callback: pipe
-        });
-        this.lfoR = new userInstance.LFO({
-            target: this.amplitudeR.gain,
-            callback: pipe
-        });
-
-        this.input.connect(this.splitter);
-        this.splitter.connect(this.amplitudeL, 0);
-        this.splitter.connect(this.amplitudeR, 1);
-        this.amplitudeL.connect(this.merger, 0, 0);
-        this.amplitudeR.connect(this.merger, 0, 1);
-        this.merger.connect(this.output);
-
-        this.rate = properties.rate || this.defaults.rate.value;
-        this.intensity = properties.intensity || this.defaults.intensity.value;
-        this.stereoPhase = properties.stereoPhase || this.defaults.stereoPhase.value;
-
-        this.lfoL.offset = 1 - (this.intensity / 2);
-        this.lfoR.offset = 1 - (this.intensity / 2);
-        this.lfoL.phase = this.stereoPhase * Math.PI / 180;
-
-        this.lfoL.activate(true);
-        this.lfoR.activate(true);
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.Tremolo.prototype = Object.create(Super, {
-        name: {
-            value: "Tremolo"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                intensity: {
-                    value: 0.3,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                stereoPhase: {
-                    value: 0,
-                    min: 0,
-                    max: 180,
-                    automatable: false,
-                },
-                rate: {
-                    value: 5,
-                    min: 0.1,
-                    max: 11,
-                    automatable: false,
-                }
-            }
-        },
-        intensity: {
-            enumerable: true,
-            get: function () {
-                return this._intensity;
-            },
-            set: function (value) {
-                this._intensity = value;
-                this.lfoL.offset = 1 - this._intensity / 2;
-                this.lfoR.offset = 1 - this._intensity / 2;
-                this.lfoL.oscillation = this._intensity;
-                this.lfoR.oscillation = this._intensity;
-            }
-        },
-        rate: {
-            enumerable: true,
-            get: function () {
-                return this._rate;
-            },
-            set: function (value) {
-                this._rate = value;
-                this.lfoL.frequency = this._rate;
-                this.lfoR.frequency = this._rate;
-            }
-        },
-        stereoPhase: {
-            enumerable: true,
-            get: function () {
-                return this._rate;
-            },
-            set: function (value) {
-                this._stereoPhase = value;
-                var newPhase = this.lfoL._phase + this._stereoPhase * Math.PI / 180;
-                newPhase = fmod(newPhase, 2 * Math.PI);
-                this.lfoR.phase = newPhase;
-            }
-        }
-    });
-    Tuna.prototype.WahWah = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.envelopeFollower = new userInstance.EnvelopeFollower({
-            target: this,
-            callback: function (context, value) {
-                context.sweep = value;
-            }
-        });
-        this.filterBp = userContext.createBiquadFilter();
-        this.filterPeaking = userContext.createBiquadFilter();
-        this.output = userContext.createGain();
-
-        //Connect AudioNodes
-        this.activateNode.connect(this.filterBp);
-        this.filterBp.connect(this.filterPeaking);
-        this.filterPeaking.connect(this.output);
-
-        //Set Properties
-        this.init();
-        this.automode = properties.enableAutoMode || this.defaults.automode.value;
-        this.resonance = properties.resonance || this.defaults.resonance.value;
-        this.sensitivity = properties.sensitivity || this.defaults.sensitivity.value;
-        this.baseFrequency = properties.baseFrequency || this.defaults.baseFrequency.value;
-        this.excursionOctaves = properties.excursionOctaves || this.defaults.excursionOctaves.value;
-        this.sweep = properties.sweep || this.defaults.sweep.value;
-
-        this.activateNode.gain.value = 2;
-        this.envelopeFollower.activate(true);
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.WahWah.prototype = Object.create(Super, {
-        name: {
-            value: "WahWah"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                automode: {
-                    value: true,
-                    automatable: false,
-                    type: BOOLEAN
-                },
-                baseFrequency: {
-                    value: 0.5,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                excursionOctaves: {
-                    value: 2,
-                    min: 1,
-                    max: 6,
-                    automatable: false,
-                },
-                sweep: {
-                    value: 0.2,
-                    min: 0,
-                    max: 1,
-                    automatable: false,
-                },
-                resonance: {
-                    value: 10,
-                    min: 1,
-                    max: 100,
-                    automatable: false,
-                },
-                sensitivity: {
-                    value: 0.5,
-                    min: -1,
-                    max: 1,
-                    automatable: false,
-                }
-            }
-        },
-        activateCallback: {
-            value: function (value) {
-                this.automode = value;
-            }
-        },
-        automode: {
-            get: function () {
-                return this._automode;
-            },
-            set: function (value) {
-                this._automode = value;
-                if (value) {
-                    this.activateNode.connect(this.envelopeFollower.input);
-                    this.envelopeFollower.activate(true);
-                } else {
-                    this.envelopeFollower.activate(false);
-                    this.activateNode.disconnect();
-                    this.activateNode.connect(this.filterBp);
-                }
-            }
-        },
-        sweep: {
-            enumerable: true,
-            get: function () {
-                return this._sweep.value;
-            },
-            set: function (value) {
-                this._sweep = Math.pow(value > 1 ? 1 : value < 0 ? 0 : value, this._sensitivity);
-                this.filterBp.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-                this.filterPeaking.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-            }
-        },
-        baseFrequency: {
-            enumerable: true,
-            get: function () {
-                return this._baseFrequency;
-            },
-            set: function (value) {
-                this._baseFrequency = 50 * Math.pow(10, value * 2);
-                this._excursionFrequency = Math.min(this.sampleRate / 2, this.baseFrequency * Math.pow(2, this._excursionOctaves));
-                this.filterBp.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-                this.filterPeaking.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-            }
-        },
-        excursionOctaves: {
-            enumerable: true,
-            get: function () {
-                return this._excursionOctaves;
-            },
-            set: function (value) {
-                this._excursionOctaves = value;
-                this._excursionFrequency = Math.min(this.sampleRate / 2, this.baseFrequency * Math.pow(2, this._excursionOctaves));
-                this.filterBp.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-                this.filterPeaking.frequency.value = this._baseFrequency + this._excursionFrequency * this._sweep;
-            }
-        },
-        sensitivity: {
-            enumerable: true,
-            get: function () {
-                return this._sensitivity;
-            },
-            set: function (value) {
-                this._sensitivity = Math.pow(10, value);
-            }
-        },
-        resonance: {
-            enumerable: true,
-            get: function () {
-                return this._resonance;
-            },
-            set: function (value) {
-                this._resonance = value;
-                this.filterPeaking.Q = this._resonance;
-            }
-        },
-        init: {
-            value: function () {
-                this.output.gain.value = 1;
-                this.filterPeaking.type = 5;
-                this.filterBp.type = 2;
-                this.filterPeaking.frequency.value = 100;
-                this.filterPeaking.gain.value = 20;
-                this.filterPeaking.Q.value = 5;
-                this.filterBp.frequency.value = 100;
-                this.filterBp.Q.value = 1;
-                this.sampleRate = userContext.sampleRate;
-            }
-        }
-    });
-    Tuna.prototype.EnvelopeFollower = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.jsNode = this.output = userContext.createScriptProcessor(this.buffersize, 1, 1);
-
-        this.input.connect(this.output);
-
-        this.attackTime = properties.attackTime || this.defaults.attackTime.value;
-        this.releaseTime = properties.releaseTime || this.defaults.releaseTime.value;
-        this._envelope = 0;
-        this.target = properties.target || {};
-        this.callback = properties.callback || function () {};
-    };
-    Tuna.prototype.EnvelopeFollower.prototype = Object.create(Super, {
-        name: {
-            value: "EnvelopeFollower"
-        },
-        defaults: {
-            value: {
-                attackTime: {
-                    value: 0.003,
-                    min: 0,
-                    max: 0.5,
-                    automatable: false,
-                },
-                releaseTime: {
-                    value: 0.5,
-                    min: 0,
-                    max: 0.5,
-                    automatable: false,
-                }
-            }
-        },
-        buffersize: {
-            value: 256
-        },
-        envelope: {
-            value: 0
-        },
-        sampleRate: {
-            value: 44100
-        },
-        attackTime: {
-            enumerable: true,
-            get: function () {
-                return this._attackTime;
-            },
-            set: function (value) {
-                this._attackTime = value;
-                this._attackC = Math.exp(-1 / this._attackTime * this.sampleRate / this.buffersize);
-            }
-        },
-        releaseTime: {
-            enumerable: true,
-            get: function () {
-                return this._releaseTime;
-            },
-            set: function (value) {
-                this._releaseTime = value;
-                this._releaseC = Math.exp(-1 / this._releaseTime * this.sampleRate / this.buffersize);
-            }
-        },
-        callback: {
-            get: function () {
-                return this._callback;
-            },
-            set: function (value) {
-                if (typeof value === "function") {
-                    this._callback = value;
-                } else {
-                    console.error("tuna.js: " + this.name + ": Callback must be a function!");
-                }
-            }
-        },
-        target: {
-            get: function () {
-                return this._target;
-            },
-            set: function (value) {
-                this._target = value;
-            }
-        },
-        activate: {
-            value: function (doActivate) {
-                this.activated = doActivate;
-                if (doActivate) {
-                    this.jsNode.connect(userContext.destination);
-                    this.jsNode.onaudioprocess = this.returnCompute(this);
-                } else {
-                    this.jsNode.disconnect();
-                    this.jsNode.onaudioprocess = null;
-                }
-            }
-        },
-        returnCompute: {
-            value: function (instance) {
-                return function (event) {
-                    instance.compute(event);
-                };
-            }
-        },
-        compute: {
-            value: function (event) {
-                var count = event.inputBuffer.getChannelData(0).length,
-                    channels = event.inputBuffer.numberOfChannels,
-                    current, chan, rms, i;
-                chan = rms = i = 0;
-                if (channels > 1) { //need to mixdown
-                    for(i = 0; i < count; ++i) {
-                        for(; chan < channels; ++chan) {
-                            current = event.inputBuffer.getChannelData(chan)[i];
-                            rms += (current * current) / channels;
-                        }
-                    }
-                } else {
-                    for(i = 0; i < count; ++i) {
-                        current = event.inputBuffer.getChannelData(0)[i];
-                        rms += (current * current);
-                    }
-                }
-                rms = Math.sqrt(rms);
-
-                if (this._envelope < rms) {
-                    this._envelope *= this._attackC;
-                    this._envelope += (1 - this._attackC) * rms;
-                } else {
-                    this._envelope *= this._releaseC;
-                    this._envelope += (1 - this._releaseC) * rms;
-                }
-                this._callback(this._target, this._envelope);
-            }
-        }
-    });
-    
-    // Low-frequency oscillation
-    Tuna.prototype.LFO = function (properties) {
-        //Instantiate AudioNode
-        this.output = userContext.createScriptProcessor(256, 1, 1);
-        this.activateNode = userContext.destination;
-
-        //Set Properties
-        this.frequency = properties.frequency || this.defaults.frequency.value;
-        this.offset = properties.offset || this.defaults.offset.value;
-        this.oscillation = properties.oscillation || this.defaults.oscillation.value;
-        this.phase = properties.phase || this.defaults.phase.value;
-        this.target = properties.target || {};
-        this.output.onaudioprocess = this.callback(properties.callback || function () {});
-        this.bypass = properties.bypass || false;
-    };
-    Tuna.prototype.LFO.prototype = Object.create(Super, {
-        name: {
-            value: "LFO"
-        },
-        bufferSize: {
-            value: 256
-        },
-        sampleRate: {
-            value: 44100
-        },
-        defaults: {
-            value: {
-                frequency: {
-                    value: 1,
-                    min: 0,
-                    max: 20,
-                    automatable: false,
-                },
-                offset: {
-                    value: 0.85,
-                    min: 0,
-                    max: 22049,
-                    automatable: false,
-                },
-                oscillation: {
-                    value: 0.3,
-                    min: -22050,
-                    max: 22050,
-                    automatable: false,
-                },
-                phase: {
-                    value: 0,
-                    min: 0,
-                    max: 2 * Math.PI,
-                    automatable: false,
-                }
-            }
-        },
-        frequency: {
-            get: function () {
-                return this._frequency;
-            },
-            set: function (value) {
-                this._frequency = value;
-                this._phaseInc = 2 * Math.PI * this._frequency * this.bufferSize / this.sampleRate;
-            }
-        },
-        offset: {
-            get: function () {
-                return this._offset;
-            },
-            set: function (value) {
-                this._offset = value;
-            }
-        },
-        oscillation: {
-            get: function () {
-                return this._oscillation;
-            },
-            set: function (value) {
-                this._oscillation = value;
-            }
-        },
-        phase: {
-            get: function () {
-                return this._phase;
-            },
-            set: function (value) {
-                this._phase = value;
-            }
-        },
-        target: {
-            get: function () {
-                return this._target;
-            },
-            set: function (value) {
-                this._target = value;
-            }
-        },
-        activate: {
-            value: function (doActivate) {
-                if (!doActivate) {
-                    this.output.disconnect(userContext.destination);
-                } else {
-                    this.output.connect(userContext.destination);
-                }
-            }
-        },
-        callback: {
-            value: function (callback) {
-                var that = this;
-                return function () {
-                    that._phase += that._phaseInc;
-                    if (that._phase > 2 * Math.PI) {
-                        that._phase = 0;
-                    }
-                    callback(that._target, that._offset + that._oscillation * Math.sin(that._phase));
-                };
-            }
-        }
-    });
-
-	/* Panner 
-	------------------------------------------------*/
-    Tuna.prototype.Panner = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.output = userContext.createGain();
-		this.panner = userContext.createPanner();
-
-        this.activateNode.connect(this.panner);
-		this.panner.connect(this.output);
-
-        this.bypass = properties.bypass || false;
-        this.x = properties.x || 0;
-        this.y = properties.y || 1;
-        this.z = properties.z || 1;
-        this.panningModel = properties.panningModel || 0;
-        this.distanceModel = properties.distanceModel || 0;
-    };
-
-	var PannerPosition = function(type) {
-		return {
-            enumerable: true,
-            get: function () {
-                return this["_" + type];
-            },
-            set: function (value) {
-                this["_" + type] = value;
-				this.panner.setPosition(this._x || 0, this._y || 0, this._z || 0);
-            }
-        }
-	};
-	
-	var PannerModel = function(type) {
-		return {
-            enumerable: true,
-            get: function () {
-                return this["_" + type];
-            },
-            set: function (value) {
-                this["_" + type] = value;
-				this.panner[type] = value;
-            }
-        }
-	};
-	
-	var Clamp = function(value, min, max, automatable) {
-		return {
-			value: value,
-			min: min,
-			max: max,
-			automatable: automatable
-		};
-	};
-	
-    Tuna.prototype.Panner.prototype = Object.create(Super, {
-        name: {
-            value: "Panner"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                x: Clamp(0, -20, 20, false),
-                y: Clamp(0, -20, 20, false),
-                z: Clamp(0, -20, 20, false),
-                distanceModel: Clamp(0, 0, 2, false),
-                panningModel: Clamp(0, 0, 2, false)
-            }
-        },
-        x: PannerPosition("x"),
-        y: PannerPosition("y"),
-        z: PannerPosition("z"),
-        panningModel: PannerModel("panningModel"),
-        distanceModel: PannerModel("distanceModel")
-    });
-
-	/* Volume 
-	------------------------------------------------*/
-    Tuna.prototype.Volume = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.output = userContext.createGain();
-
-        this.activateNode.connect(this.output);
-
-        this.bypass = properties.bypass || false;
-        this.amount = properties.amount || this.defaults.amount.value;
-    };
-
-    Tuna.prototype.Volume.prototype = Object.create(Super, {
-        name: {
-            value: "Volume"
-        },
-        defaults: {
-            writable:true,
-            value: {
-                amount: Clamp(0, 0, 2, false)
-            }
-        },
-        amount: {
-            enumerable: true,
-            get: function () {
-                return this._volume;
-            },
-            set: function (value) {
-                this._volume = value;
-                this.activateNode.gain.value = value;
-            }
-        }
-    });
-
-	/* Frequency 
-	------------------------------------------------*/
-    Tuna.prototype.Frequency = function (properties) {
-        if (!properties) {
-            properties = this.getDefaults();
-        }
-
-		this.trebleFilter = userContext.createBiquadFilter();
-		this.trebleFilter.type = this.trebleFilter.HIGHSHELF;
-		this.trebleFilter.frequency.value = 8000; // 1k+
-		this.trebleFilter.Q.value = 0;
-		this.midtoneFilter = userContext.createBiquadFilter();
-		this.midtoneFilter.type = this.midtoneFilter.PEAKING;
-		this.midtoneFilter.frequency.value = 1000; // 200-1k
-		this.midtoneFilter.Q.value = 0;
-		this.bassFilter = userContext.createBiquadFilter();
-		this.bassFilter.type = this.bassFilter.LOWSHELF;
-		this.bassFilter.frequency.value = 200; // 60-200k
-		this.bassFilter.Q.value = 0;
-		
-        this.input = userContext.createGain();
-        this.activateNode = userContext.createGain();
-        this.output = userContext.createGain();
-
-		this.activateNode.connect(this.bassFilter);
-		this.bassFilter.connect(this.midtoneFilter);
-		this.midtoneFilter.connect(this.trebleFilter);
-        this.trebleFilter.connect(this.output);
-
-        this.bypass = properties.bypass || false;
-        this.volume = properties.volume || false;
-        this.treble = properties.treble || false;
-        this.midtone = properties.midtone || false;
-        this.bass = properties.bass || false;
-    };
-
-    var GainValue = function(type, nodeId) {
-    	return {
-            enumerable: true,
-            get: function () {
-                return this["_" + type];
-            },
-            set: function (value) {
-                this["_" + type] = value;
-                this[nodeId || type + "Filter"].gain.value = value;
-            }
-        };
-    };
-
-    Tuna.prototype.Frequency.prototype = Object.create(Super, {
-        name: {
-            value: "Frequency"
-        },
-        defaults: {
-            writable:true,
-            value: {
-            	volume: Clamp(1, 0, 2, false),
-                treble: Clamp(0, -20, 20, false),
-                midtone: Clamp(0, -20, 20, false),
-                bass: Clamp(0, -20, 20, false)
-            }
-        },
-        volume: GainValue("volume", "activateNode"),
-        treble: GainValue("treble"),
-        midtone: GainValue("midtone"),
-        bass: GainValue("bass")
-    });
-
-    if (typeof define === "function") {
-        define("Tuna", [], function () {
-            return Tuna;
-        });
-    } else {
-        window.Tuna = Tuna;
-    }
-})(this);

+ 0 - 104
dist/midi/index.html

@@ -1,104 +0,0 @@
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-<head>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
-    <title>MIDI.js - Sequencing in Javascript.</title>
-    <!-- midi.js css -->
-    <!-- shim -->
-    <script src="./inc/shim/Base64.js" type="text/javascript"></script>
-    <script src="./inc/shim/Base64binary.js" type="text/javascript"></script>
-    <script src="./inc/shim/WebAudioAPI.js" type="text/javascript"></script>
-    <script src="./inc/shim/WebMIDIAPI.js" type="text/javascript"></script>
-    <!-- jasmid package -->
-    <script src="./inc/jasmid/stream.js"></script>
-    <script src="./inc/jasmid/midifile.js"></script>
-    <script src="./inc/jasmid/replayer.js"></script>
-    <!-- midi.js package -->
-    <script src="./js/midi/audioDetect.js" type="text/javascript"></script>
-    <script src="./js/midi/gm.js" type="text/javascript"></script>
-    <script src="./js/midi/loader.js" type="text/javascript"></script>
-    <script src="./js/midi/plugin.audiotag.js" type="text/javascript"></script>
-    <script src="./js/midi/plugin.webaudio.js" type="text/javascript"></script>
-    <script src="./js/midi/plugin.webmidi.js" type="text/javascript"></script>
-    <script src="./js/midi/player.js" type="text/javascript"></script>
-    <script src="./js/midi/synesthesia.js" type="text/javascript"></script>
-    <!-- utils -->
-    <script src="./js/util/dom_request_xhr.js" type="text/javascript"></script>
-    <script src="./js/util/dom_request_script.js" type="text/javascript"></script>
-</head>
-
-<body>
-    <button id="playBtn">播放</button>
-    <button id="pauseBtn">暂停</button>
-    <button id="stopBtn">跳跃</button>
-    <input type="range" id="skipBtn" value="100" min="45" max="200" />
-    <script type="text/javascript">
-        var midiData = {
-            src: '',
-            timeWarp: 1,
-        }
-        var currentTime = 0
-        var MIDI = window.MIDI
-        MIDI.loadPlugin({
-            soundfontUrl: "./soundfont/",
-            // instrument: ["acoustic_grand_piano", "synth_drum"],
-            onsuccess: function () {
-                console.log(MIDI)
-                window.handleRendered && window.handleRendered()
-                // MIDI.setInstrument(0, MIDI.GM.byName['synth_drum'].number)
-                // MIDI.setInstrument(1, MIDI.GM.byName['acoustic_grand_piano'].number)
-            }
-        });
-
-        // 播放音符
-        function playNote(note, delay) {
-            MIDI.noteOn(0, note, 100, 0);
-            MIDI.noteOff(0, note, delay);
-        }
-
-
-
-        // MIDI.Player.currentTime = 100000
-        // MIDI.Player.timeWarp = 0.6289308176100629
-        // setInterval(() => {
-        //     // console.log(MIDI.Player.currentTime / 1000, MIDI.Player.restart)
-        // }, 100)
-
-        var playBtn = document.getElementById('playBtn')
-        // var pauseBtn = document.getElementById('pauseBtn')
-        // var stopBtn = document.getElementById('stopBtn')
-        // var skipBtn = document.getElementById('skipBtn')
-        playBtn.addEventListener('click', () => {
-            MIDI.noteOn(0, 50, 50, 0);
-            MIDI.noteOff(0, 50, 1);
-            MIDI.noteOn(0, 50, 100, 1);
-            MIDI.noteOff(0, 50, 2);
-            console.log(MIDI)
-        })
-        // pauseBtn.onclick = function () {
-        //     MIDI.Player.pause();
-        // }
-        // stopBtn.onclick = function () {
-        //     MIDI.Player.currentTime = 100000
-        //     MIDI.Player.resume();
-        //     console.log(MIDI)
-        // }
-        // skipBtn.onchange = function (e) {
-        //     var timeWarp = Number(e.target.value) / 100
-        //     // MIDI.Player.stop()
-        //     // const oldCurrent = MIDI.Player.currentTime
-        //     // const ab = MIDI.Player.replayer.getData()
-        //     // console.log(ab)
-        //     MIDI.Player.loadMidiFile(() => {
-        //         MIDI.Player.timeWarp = 1 / timeWarp
-        //         console.log('播放倍数', 1 / timeWarp, Number(e.target.value))
-        //         MIDI.Player.resume();
-        //     })
-
-
-        // }
-    </script>
-</body>
-
-</html>

File diff suppressed because it is too large
+ 0 - 85
dist/midi/js/midi/audioDetect.js


+ 0 - 161
dist/midi/js/midi/gm.js

@@ -1,161 +0,0 @@
-/*
-	----------------------------------------------------------
-	GeneralMIDI
-	----------------------------------------------------------
-*/
-
-(function(root) { 'use strict';
-
-	root.GM = (function(arr) {
-		var clean = function(name) {
-			return name.replace(/[^a-z0-9 ]/gi, '').replace(/[ ]/g, '_').toLowerCase();
-		};
-		var res = {
-			byName: { },
-			byId: { },
-			byCategory: { }
-		};
-		for (var key in arr) {
-			var list = arr[key];
-			for (var n = 0, length = list.length; n < length; n++) {
-				var instrument = list[n];
-				if (!instrument) continue;
-				var num = parseInt(instrument.substr(0, instrument.indexOf(' ')), 10);
-				instrument = instrument.replace(num + ' ', '');
-				res.byId[--num] = 
-				res.byName[clean(instrument)] = 
-				res.byCategory[clean(key)] = {
-					id: clean(instrument),
-					instrument: instrument,
-					number: num,
-					category: key
-				};
-			}
-		}
-		return res;
-	})({
-		'Piano': ['1 Acoustic Grand Piano', '2 Bright Acoustic Piano', '3 Electric Grand Piano', '4 Honky-tonk Piano', '5 Electric Piano 1', '6 Electric Piano 2', '7 Harpsichord', '8 Clavinet'],
-		'Chromatic Percussion': ['9 Celesta', '10 Glockenspiel', '11 Music Box', '12 Vibraphone', '13 Marimba', '14 Xylophone', '15 Tubular Bells', '16 Dulcimer'],
-		'Organ': ['17 Drawbar Organ', '18 Percussive Organ', '19 Rock Organ', '20 Church Organ', '21 Reed Organ', '22 Accordion', '23 Harmonica', '24 Tango Accordion'],
-		'Guitar': ['25 Acoustic Guitar (nylon)', '26 Acoustic Guitar (steel)', '27 Electric Guitar (jazz)', '28 Electric Guitar (clean)', '29 Electric Guitar (muted)', '30 Overdriven Guitar', '31 Distortion Guitar', '32 Guitar Harmonics'],
-		'Bass': ['33 Acoustic Bass', '34 Electric Bass (finger)', '35 Electric Bass (pick)', '36 Fretless Bass', '37 Slap Bass 1', '38 Slap Bass 2', '39 Synth Bass 1', '40 Synth Bass 2'],
-		'Strings': ['41 Violin', '42 Viola', '43 Cello', '44 Contrabass', '45 Tremolo Strings', '46 Pizzicato Strings', '47 Orchestral Harp', '48 Timpani'],
-		'Ensemble': ['49 String Ensemble 1', '50 String Ensemble 2', '51 Synth Strings 1', '52 Synth Strings 2', '53 Choir Aahs', '54 Voice Oohs', '55 Synth Choir', '56 Orchestra Hit'],
-		'Brass': ['57 Trumpet', '58 Trombone', '59 Tuba', '60 Muted Trumpet', '61 French Horn', '62 Brass Section', '63 Synth Brass 1', '64 Synth Brass 2'],
-		'Reed': ['65 Soprano Sax', '66 Alto Sax', '67 Tenor Sax', '68 Baritone Sax', '69 Oboe', '70 English Horn', '71 Bassoon', '72 Clarinet'],
-		'Pipe': ['73 Piccolo', '74 Flute', '75 Recorder', '76 Pan Flute', '77 Blown Bottle', '78 Shakuhachi', '79 Whistle', '80 Ocarina'],
-		'Synth Lead': ['81 Lead 1 (square)', '82 Lead 2 (sawtooth)', '83 Lead 3 (calliope)', '84 Lead 4 (chiff)', '85 Lead 5 (charang)', '86 Lead 6 (voice)', '87 Lead 7 (fifths)', '88 Lead 8 (bass + lead)'],
-		'Synth Pad': ['89 Pad 1 (new age)', '90 Pad 2 (warm)', '91 Pad 3 (polysynth)', '92 Pad 4 (choir)', '93 Pad 5 (bowed)', '94 Pad 6 (metallic)', '95 Pad 7 (halo)', '96 Pad 8 (sweep)'],
-		'Synth Effects': ['97 FX 1 (rain)', '98 FX 2 (soundtrack)', '99 FX 3 (crystal)', '100 FX 4 (atmosphere)', '101 FX 5 (brightness)', '102 FX 6 (goblins)', '103 FX 7 (echoes)', '104 FX 8 (sci-fi)'],
-		'Ethnic': ['105 Sitar', '106 Banjo', '107 Shamisen', '108 Koto', '109 Kalimba', '110 Bagpipe', '111 Fiddle', '112 Shanai'],
-		'Percussive': ['113 Tinkle Bell', '114 Agogo', '115 Steel Drums', '116 Woodblock', '117 Taiko Drum', '118 Melodic Tom', '119 Synth Drum'],
-		'Sound effects': ['120 Reverse Cymbal', '121 Guitar Fret Noise', '122 Breath Noise', '123 Seashore', '124 Bird Tweet', '125 Telephone Ring', '126 Helicopter', '127 Applause', '128 Gunshot']
-	});
-
-	/* get/setInstrument
-	--------------------------------------------------- */
-	root.getInstrument = function(channelId) {
-		var channel = root.channels[channelId];
-		return channel && channel.instrument;
-	};
-
-	root.setInstrument = function(channelId, program, delay) {
-		var channel = root.channels[channelId];
-		if (delay) {
-			return setTimeout(function() {
-				channel.instrument = program;
-			}, delay);
-		} else {
-			channel.instrument = program;
-		}
-	};
-
-	/* get/setMono
-	--------------------------------------------------- */
-	root.getMono = function(channelId) {
-		var channel = root.channels[channelId];
-		return channel && channel.mono;
-	};
-
-	root.setMono = function(channelId, truthy, delay) {
-		var channel = root.channels[channelId];
-		if (delay) {
-			return setTimeout(function() {
-				channel.mono = truthy;
-			}, delay);
-		} else {
-			channel.mono = truthy;
-		}
-	};
-
-	/* get/setOmni
-	--------------------------------------------------- */
-	root.getOmni = function(channelId) {
-		var channel = root.channels[channelId];
-		return channel && channel.omni;
-	};
-
-	root.setOmni = function(channelId, truthy) {
-		var channel = root.channels[channelId];
-		if (delay) {
-			return setTimeout(function() {
-				channel.omni = truthy;	
-			}, delay);
-		} else {
-			channel.omni = truthy;
-		}
-	};
-
-	/* get/setSolo
-	--------------------------------------------------- */
-	root.getSolo = function(channelId) {
-		var channel = root.channels[channelId];
-		return channel && channel.solo;
-	};
-
-	root.setSolo = function(channelId, truthy) {
-		var channel = root.channels[channelId];
-		if (delay) {
-			return setTimeout(function() {
-				channel.solo = truthy;	
-			}, delay);
-		} else {
-			channel.solo = truthy;
-		}
-	};
-
-	/* channels
-	--------------------------------------------------- */
-	root.channels = (function() { // 0 - 15 channels
-		var channels = {};
-		for (var i = 0; i < 16; i++) {
-			channels[i] = { // default values
-				instrument: i,
-				pitchBend: 0,
-				mute: false,
-				mono: false,
-				omni: false,
-				solo: false
-			};
-		}
-		return channels;
-	})();
-
-	/* note conversions
-	--------------------------------------------------- */
-	root.keyToNote = {}; // C8  == 108
-	root.noteToKey = {}; // 108 ==  C8
-
-	(function() {
-		var A0 = 0x15; // first note
-		var C8 = 0x6C; // last note
-		var number2key = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
-		for (var n = A0; n <= C8; n++) {
-			var octave = (n - 12) / 12 >> 0;
-			var name = number2key[n % 12] + octave;
-			root.keyToNote[name] = n;
-			root.noteToKey[n] = name;
-		}
-	})();
-
-})(MIDI);

+ 0 - 199
dist/midi/js/midi/loader.js

@@ -1,199 +0,0 @@
-/*
-	----------------------------------------------------------
-	MIDI.Plugin : 0.3.4 : 2015-03-26
-	----------------------------------------------------------
-	https://github.com/mudcube/MIDI.js
-	----------------------------------------------------------
-	Inspired by javax.sound.midi (albeit a super simple version): 
-		http://docs.oracle.com/javase/6/docs/api/javax/sound/midi/package-summary.html
-	----------------------------------------------------------
-	Technologies
-	----------------------------------------------------------
-		Web MIDI API - no native support yet (jazzplugin)
-		Web Audio API - firefox 25+, chrome 10+, safari 6+, opera 15+
-		HTML5 Audio Tag - ie 9+, firefox 3.5+, chrome 4+, safari 4+, opera 9.5+, ios 4+, android 2.3+
-	----------------------------------------------------------
-*/
-
-if (typeof MIDI === 'undefined') MIDI = {};
-
-MIDI.Soundfont = MIDI.Soundfont || {};
-MIDI.Player = MIDI.Player || {};
-
-(function(root) { 'use strict';
-
-	root.DEBUG = true;
-	root.USE_XHR = true;
-	root.soundfontUrl = './soundfont/';
-
-	/*
-		MIDI.loadPlugin({
-			onsuccess: function() { },
-			onprogress: function(state, percent) { },
-			targetFormat: 'mp3', // optionally can force to use MP3 (for instance on mobile networks)
-			instrument: 'acoustic_grand_piano', // or 1 (default)
-			instruments: [ 'acoustic_grand_piano', 'acoustic_guitar_nylon' ] // or multiple instruments
-		});
-	*/
-
-	root.loadPlugin = function(opts) {
-		if (typeof opts === 'function') {
-			opts = {onsuccess: opts};
-		}
-
-		root.soundfontUrl = opts.soundfontUrl || root.soundfontUrl;
-
-		/// Detect the best type of audio to use
-		root.audioDetect(function(supports) {
-			var hash = window.location.hash;
-			var api = '';
-
-			/// use the most appropriate plugin if not specified
-			if (supports[opts.api]) {
-				api = opts.api;
-			} else if (supports[hash.substr(1)]) {
-				api = hash.substr(1);
-			} else if (supports.webmidi) {
-				api = 'webmidi';
-			} else if (window.AudioContext) { // Chrome
-				api = 'webaudio';
-			} else if (window.Audio) { // Firefox
-				api = 'audiotag';
-			}
-
-			if (connect[api]) {
-				/// use audio/ogg when supported
-				if (opts.targetFormat) {
-					var audioFormat = opts.targetFormat;
-				} else { // use best quality
-					var audioFormat = supports['audio/ogg'] ? 'ogg' : 'mp3';
-				}
-
-				/// load the specified plugin
-				root.__api = api;
-				root.__audioFormat = audioFormat;
-				root.supports = supports;
-				root.loadResource(opts);
-			}
-		});
-	};
-
-	/*
-		root.loadResource({
-			onsuccess: function() { },
-			onprogress: function(state, percent) { },
-			instrument: 'banjo'
-		})
-	*/
-
-	root.loadResource = function(opts) {
-		var instruments = opts.instruments || opts.instrument || 'acoustic_grand_piano';
-		///
-		if (typeof instruments !== 'object') {
-			if (instruments || instruments === 0) {
-				instruments = [instruments];
-			} else {
-				instruments = [];
-			}
-		}
-		/// convert numeric ids into strings
-		for (var i = 0; i < instruments.length; i ++) {
-			var instrument = instruments[i];
-			if (instrument === +instrument) { // is numeric
-				if (root.GM.byId[instrument]) {
-					instruments[i] = root.GM.byId[instrument].id;
-				}
-			}
-		}
-		///
-		opts.format = root.__audioFormat;
-		opts.instruments = instruments;
-		///
-		connect[root.__api](opts);
-	};
-
-	var connect = {
-		webmidi: function(opts) {
-			// cant wait for this to be standardized!
-			root.WebMIDI.connect(opts);
-		},
-		audiotag: function(opts) {
-			// works ok, kinda like a drunken tuna fish, across the board
-			// http://caniuse.com/audio
-			requestQueue(opts, 'AudioTag');
-		},
-		webaudio: function(opts) {
-			// works awesome! safari, chrome and firefox support
-			// http://caniuse.com/web-audio
-			requestQueue(opts, 'WebAudio');
-		}
-	};
-
-	var requestQueue = function(opts, context) {
-		var audioFormat = opts.format;
-		var instruments = opts.instruments;
-		var onprogress = opts.onprogress;
-		var onerror = opts.onerror;
-		///
-		var length = instruments.length;
-		var pending = length;
-		var waitForEnd = function() {
-			if (!--pending) {
-				onprogress && onprogress('load', 1.0);
-				root[context].connect(opts);
-			}
-		};
-		///
-		for (var i = 0; i < length; i ++) {
-			var instrumentId = instruments[i];
-			if (MIDI.Soundfont[instrumentId]) { // already loaded
-				waitForEnd();
-			} else { // needs to be requested
-				sendRequest(instruments[i], audioFormat, function(evt, progress) {
-					var fileProgress = progress / length;
-					var queueProgress = (length - pending) / length;
-					onprogress && onprogress('load', fileProgress + queueProgress, instrumentId);
-				}, function() {
-					waitForEnd();
-				}, onerror);
-			}
-		};
-	};
-
-	var sendRequest = function(instrumentId, audioFormat, onprogress, onsuccess, onerror) {
-		var soundfontPath = root.soundfontUrl + instrumentId + '-' + audioFormat + '.js';
-		if (root.USE_XHR) {
-			root.util.request({
-				url: soundfontPath,
-				format: 'text',
-				onerror: onerror,
-				onprogress: onprogress,
-				onsuccess: function(event, responseText) {
-					var script = document.createElement('script');
-					script.language = 'javascript';
-					script.type = 'text/javascript';
-					script.text = responseText;
-					document.body.appendChild(script);
-					///
-					onsuccess();
-				}
-			});
-		} else {
-			dom.loadScript.add({
-				url: soundfontPath,
-				verify: 'MIDI.Soundfont["' + instrumentId + '"]',
-				onerror: onerror,
-				onsuccess: function() {
-					onsuccess();
-				}
-			});
-		}
-	};
-
-	root.setDefaultPlugin = function(midi) {
-		for (var key in midi) {
-			root[key] = midi[key];
-		}
-	};
-
-})(MIDI);

+ 0 - 380
dist/midi/js/midi/player.js

@@ -1,380 +0,0 @@
-/*
-	----------------------------------------------------------
-	MIDI.Player : 0.3.1 : 2015-03-26
-	----------------------------------------------------------
-	https://github.com/mudcube/MIDI.js
-	----------------------------------------------------------
-*/
-
-if (typeof MIDI === 'undefined') MIDI = {};
-if (typeof MIDI.Player === 'undefined') MIDI.Player = {};
-
-(function() { 'use strict';
-
-var midi = MIDI.Player;
-midi.currentTime = 0;
-midi.endTime = 0; 
-midi.restart = 0; 
-midi.playing = false;
-midi.timeWarp = 1;
-midi.startDelay = 0;
-midi.BPM = 120;
-
-midi.start =
-midi.resume = function(onsuccess) {
-    if (midi.currentTime < -1) {
-    	midi.currentTime = -1;
-    }
-    startAudio(midi.currentTime, null, onsuccess);
-};
-
-midi.pause = function() {
-	var tmp = midi.restart;
-	stopAudio();
-	midi.restart = tmp;
-};
-
-midi.stop = function() {
-	stopAudio();
-	midi.restart = 0;
-	midi.currentTime = 0;
-};
-
-midi.addListener = function(onsuccess) {
-	onMidiEvent = onsuccess;
-};
-
-midi.removeListener = function() {
-	onMidiEvent = undefined;
-};
-
-midi.clearAnimation = function() {
-	if (midi.animationFrameId)  {
-		cancelAnimationFrame(midi.animationFrameId);
-	}
-};
-
-midi.setAnimation = function(callback) {
-	var currentTime = 0;
-	var tOurTime = 0;
-	var tTheirTime = 0;
-	//
-	midi.clearAnimation();
-	///
-	var frame = function() {
-		midi.animationFrameId = requestAnimationFrame(frame);
-		///
-		if (midi.endTime === 0) {
-			return;
-		}
-		if (midi.playing) {
-			currentTime = (tTheirTime === midi.currentTime) ? tOurTime - Date.now() : 0;
-			if (midi.currentTime === 0) {
-				currentTime = 0;
-			} else {
-				currentTime = midi.currentTime - currentTime;
-			}
-			if (tTheirTime !== midi.currentTime) {
-				tOurTime = Date.now();
-				tTheirTime = midi.currentTime;
-			}
-		} else { // paused
-			currentTime = midi.currentTime;
-		}
-		///
-		var endTime = midi.endTime;
-		var percent = currentTime / endTime;
-		var total = currentTime / 1000;
-		var minutes = total / 60;
-		var seconds = total - (minutes * 60);
-		var t1 = minutes * 60 + seconds;
-		var t2 = (endTime / 1000);
-		///
-		if (t2 - t1 < -1.0) {
-			return;
-		} else {
-			callback({
-				now: t1,
-				end: t2,
-				events: noteRegistrar
-			});
-		}
-	};
-	///
-	requestAnimationFrame(frame);
-};
-
-// helpers
-
-midi.loadMidiFile = function(onsuccess, onprogress, onerror) {
-	try {
-		midi.replayer = new Replayer(MidiFile(midi.currentData), midi.timeWarp, null, midi.BPM);
-		midi.data = midi.replayer.getData();
-		midi.endTime = getLength();
-		///
-		MIDI.loadPlugin({
-// 			instruments: midi.getFileInstruments(),
-			onsuccess: onsuccess,
-			onprogress: onprogress,
-			onerror: onerror
-		});
-	} catch(event) {
-		onerror && onerror(event);
-	}
-};
-
-midi.loadFile = function(file, onsuccess, onprogress, onerror) {
-	midi.stop();
-	if (file.indexOf('base64,') !== -1) {
-		var data = window.atob(file.split(',')[1]);
-		midi.currentData = data;
-		midi.loadMidiFile(onsuccess, onprogress, onerror);
-	} else {
-		var fetch = new XMLHttpRequest();
-		fetch.open('GET', file);
-		fetch.overrideMimeType('text/plain; charset=x-user-defined');
-		fetch.onreadystatechange = function() {
-			if (this.readyState === 4) {
-				if (this.status === 200) {
-					var t = this.responseText || '';
-					var ff = [];
-					var mx = t.length;
-					var scc = String.fromCharCode;
-					for (var z = 0; z < mx; z++) {
-						ff[z] = scc(t.charCodeAt(z) & 255);
-					}
-					///
-					var data = ff.join('');
-					midi.currentData = data;
-					midi.loadMidiFile(onsuccess, onprogress, onerror);
-				} else {
-					onerror && onerror('Unable to load MIDI file');
-				}
-			}
-		};
-		fetch.send();
-	}
-};
-
-midi.getFileInstruments = function() {
-	var instruments = {};
-	var programs = {};
-	for (var n = 0; n < midi.data.length; n ++) {
-		var event = midi.data[n][0].event;
-		if (event.type !== 'channel') {
-			continue;
-		}
-		var channel = event.channel;
-		switch(event.subtype) {
-			case 'controller':
-//				console.log(event.channel, MIDI.defineControl[event.controllerType], event.value);
-				break;
-			case 'programChange':
-				programs[channel] = event.programNumber;
-				break;
-			case 'noteOn':
-				var program = programs[channel];
-				var gm = MIDI.GM.byId[isFinite(program) ? program : channel];
-				instruments[gm.id] = true;
-				break;
-		}
-	}
-	var ret = [];
-	for (var key in instruments) {
-		ret.push(key);
-	}
-	return ret;
-};
-
-// Playing the audio
-
-var eventQueue = []; // hold events to be triggered
-var queuedTime; // 
-var startTime = 0; // to measure time elapse
-var noteRegistrar = {}; // get event for requested note
-var onMidiEvent = undefined; // listener
-var scheduleTracking = function(channel, note, currentTime, offset, message, velocity, time) {
-	return setTimeout(function() {
-		var data = {
-			channel: channel,
-			note: note,
-			now: currentTime,
-			end: midi.endTime,
-			message: message,
-			velocity: velocity
-		};
-		//
-		if (message === 128) {
-			delete noteRegistrar[note];
-		} else {
-			noteRegistrar[note] = data;
-		}
-		if (onMidiEvent) {
-			onMidiEvent(data);
-		}
-		midi.currentTime = currentTime;
-		///
-		eventQueue.shift();
-		///
-		if (eventQueue.length < 1000) {
-			startAudio(queuedTime, true);
-		} else if (midi.currentTime === queuedTime && queuedTime < midi.endTime) { // grab next sequence
-			startAudio(queuedTime, true);
-		}
-	}, currentTime - offset);
-};
-
-var getContext = function() {
-	if (MIDI.api === 'webaudio') {
-		return MIDI.WebAudio.getContext();
-	} else {
-		midi.ctx = {currentTime: 0};
-	}
-	return midi.ctx;
-};
-
-var getLength = function() {
-	var data =  midi.data;
-	var length = data.length;
-	var totalTime = 0.5;
-	for (var n = 0; n < length; n++) {
-		totalTime += data[n][1];
-	}
-	return totalTime;
-};
-
-var __now;
-var getNow = function() {
-    if (window.performance && window.performance.now) {
-        return window.performance.now();
-    } else {
-		return Date.now();
-	}
-};
-
-var startAudio = function(currentTime, fromCache, onsuccess) {
-	if (!midi.replayer) {
-		return;
-	}
-	if (!fromCache) {
-		if (typeof currentTime === 'undefined') {
-			currentTime = midi.restart;
-		}
-		///
-		midi.playing && stopAudio();
-		midi.playing = true;
-		midi.data = midi.replayer.getData();
-		midi.endTime = getLength();
-	}
-	///
-	var note;
-	var offset = 0;
-	var messages = 0;
-	var data = midi.data;
-	var ctx = getContext();
-	var length = data.length;
-	//
-	queuedTime = 0.5;
-	///
-	var interval = eventQueue[0] && eventQueue[0].interval || 0;
-	var foffset = currentTime - midi.currentTime;
-	///
-	if (MIDI.api !== 'webaudio') { // set currentTime on ctx
-		var now = getNow();
-		__now = __now || now;
-		ctx.currentTime = (now - __now) / 1000;
-	}
-	///
-	startTime = ctx.currentTime;
-	///
-	for (var n = 0; n < length && messages < 100; n++) {
-		var obj = data[n];
-		if ((queuedTime += obj[1]) <= currentTime) {
-			offset = queuedTime;
-			continue;
-		}
-		///
-		currentTime = queuedTime - offset;
-		///
-		var event = obj[0].event;
-		if (event.type !== 'channel') {
-			continue;
-		}
-		///
-		var channelId = event.channel;
-		var channel = MIDI.channels[channelId];
-		var delay = ctx.currentTime + ((currentTime + foffset + midi.startDelay) / 1000);
-		var queueTime = queuedTime - offset + midi.startDelay;
-		switch (event.subtype) {
-			case 'controller':
-				MIDI.setController(channelId, event.controllerType, event.value, delay);
-				break;
-			case 'programChange':
-				MIDI.programChange(channelId, event.programNumber, delay);
-				break;
-			case 'pitchBend':
-				MIDI.pitchBend(channelId, event.value, delay);
-				break;
-			case 'noteOn':
-				if (channel.mute) break;
-				note = event.noteNumber - (midi.MIDIOffset || 0);
-				eventQueue.push({
-				    event: event,
-				    time: queueTime,
-				    source: MIDI.noteOn(channelId, event.noteNumber, event.velocity, delay),
-				    interval: scheduleTracking(channelId, note, queuedTime + midi.startDelay, offset - foffset, 144, event.velocity)
-				});
-				messages++;
-				break;
-			case 'noteOff':
-				if (channel.mute) break;
-				note = event.noteNumber - (midi.MIDIOffset || 0);
-				eventQueue.push({
-				    event: event,
-				    time: queueTime,
-				    source: MIDI.noteOff(channelId, event.noteNumber, delay),
-				    interval: scheduleTracking(channelId, note, queuedTime, offset - foffset, 128, 0)
-				});
-				break;
-			default:
-				break;
-		}
-	}
-	///
-	onsuccess && onsuccess(eventQueue);
-};
-
-var stopAudio = function() {
-	var ctx = getContext();
-	midi.playing = false;
-	midi.restart += (ctx.currentTime - startTime) * 1000;
-	// stop the audio, and intervals
-	while (eventQueue.length) {
-		var o = eventQueue.pop();
-		window.clearInterval(o.interval);
-		if (!o.source) continue; // is not webaudio
-		if (typeof(o.source) === 'number') {
-			window.clearTimeout(o.source);
-		} else { // webaudio
-			o.source.disconnect(0);
-		}
-	}
-	// run callback to cancel any notes still playing
-	for (var key in noteRegistrar) {
-		var o = noteRegistrar[key]
-		if (noteRegistrar[key].message === 144 && onMidiEvent) {
-			onMidiEvent({
-				channel: o.channel,
-				note: o.note,
-				now: o.now,
-				end: o.end,
-				message: 128,
-				velocity: o.velocity
-			});
-		}
-	}
-	// reset noteRegistrar
-	noteRegistrar = {};
-};
-
-})();

+ 0 - 150
dist/midi/js/midi/plugin.audiotag.js

@@ -1,150 +0,0 @@
-/*
-	----------------------------------------------------------------------
-	AudioTag <audio> - OGG or MPEG Soundbank
-	----------------------------------------------------------------------
-	http://dev.w3.org/html5/spec/Overview.html#the-audio-element
-	----------------------------------------------------------------------
-*/
-
-(function(root) { 'use strict';
-
-	window.Audio && (function() {
-		var midi = root.AudioTag = { api: 'audiotag' };
-		var noteToKey = {};
-		var volume = 127; // floating point 
-		var buffer_nid = -1; // current channel
-		var audioBuffers = []; // the audio channels
-		var notesOn = []; // instrumentId + noteId that is currently playing in each 'channel', for routing noteOff/chordOff calls
-		var notes = {}; // the piano keys
-		for (var nid = 0; nid < 12; nid ++) {
-			audioBuffers[nid] = new Audio();
-		}
-
-		var playChannel = function(channel, note) {
-			if (!root.channels[channel]) return;
-			var instrument = root.channels[channel].instrument;
-			var instrumentId = root.GM.byId[instrument].id;
-			var note = notes[note];
-			if (note) {
-				var instrumentNoteId = instrumentId + '' + note.id;
-				var nid = (buffer_nid + 1) % audioBuffers.length;
-				var audio = audioBuffers[nid];
-				notesOn[ nid ] = instrumentNoteId;
-				if (!root.Soundfont[instrumentId]) {
-					if (root.DEBUG) {
-						console.log('404', instrumentId);
-					}
-					return;
-				}
-				audio.src = root.Soundfont[instrumentId][note.id];
-				audio.volume = volume / 127;
-				audio.play();
-				buffer_nid = nid;
-			}
-		};
-
-		var stopChannel = function(channel, note) {
-			if (!root.channels[channel]) return;
-			var instrument = root.channels[channel].instrument;
-			var instrumentId = root.GM.byId[instrument].id;
-			var note = notes[note];
-			if (note) {
-				var instrumentNoteId = instrumentId + '' + note.id;
-				for (var i = 0, len = audioBuffers.length; i < len; i++) {
-				    var nid = (i + buffer_nid + 1) % len;
-				    var cId = notesOn[nid];
-				    if (cId && cId == instrumentNoteId) {
-				        audioBuffers[nid].pause();
-				        notesOn[nid] = null;
-				        return;
-				    }
-				}
-			}
-		};
-	
-		midi.audioBuffers = audioBuffers;
-		midi.send = function(data, delay) { };
-		midi.setController = function(channel, type, value, delay) { };
-		midi.setVolume = function(channel, n) {
-			volume = n; //- should be channel specific volume
-		};
-
-		midi.programChange = function(channel, program) {
-			root.channels[channel].instrument = program;
-		};
-
-		midi.pitchBend = function(channel, program, delay) { };
-
-		midi.noteOn = function(channel, note, velocity, delay) {
-			var id = noteToKey[note];
-			if (!notes[id]) return;
-			if (delay) {
-				return setTimeout(function() {
-					playChannel(channel, id);
-				}, delay * 1000);
-			} else {
-				playChannel(channel, id);
-			}
-		};
-	
-		midi.noteOff = function(channel, note, delay) {
-// 			var id = noteToKey[note];
-// 			if (!notes[id]) return;
-// 			if (delay) {
-// 				return setTimeout(function() {
-// 					stopChannel(channel, id);
-// 				}, delay * 1000)
-// 			} else {
-// 				stopChannel(channel, id);
-// 			}
-		};
-	
-		midi.chordOn = function(channel, chord, velocity, delay) {
-			for (var idx = 0; idx < chord.length; idx ++) {
-				var n = chord[idx];
-				var id = noteToKey[n];
-				if (!notes[id]) continue;
-				if (delay) {
-					return setTimeout(function() {
-						playChannel(channel, id);
-					}, delay * 1000);
-				} else {
-					playChannel(channel, id);
-				}
-			}
-		};
-	
-		midi.chordOff = function(channel, chord, delay) {
-			for (var idx = 0; idx < chord.length; idx ++) {
-				var n = chord[idx];
-				var id = noteToKey[n];
-				if (!notes[id]) continue;
-				if (delay) {
-					return setTimeout(function() {
-						stopChannel(channel, id);
-					}, delay * 1000);
-				} else {
-					stopChannel(channel, id);
-				}
-			}
-		};
-	
-		midi.stopAllNotes = function() {
-			for (var nid = 0, length = audioBuffers.length; nid < length; nid++) {
-				audioBuffers[nid].pause();
-			}
-		};
-	
-		midi.connect = function(opts) {
-			root.setDefaultPlugin(midi);
-			///
-			for (var key in root.keyToNote) {
-				noteToKey[root.keyToNote[key]] = key;
-				notes[key] = {id: key};
-			}
-			///
-			opts.onsuccess && opts.onsuccess();
-		};
-	})();
-
-})(MIDI);

+ 0 - 326
dist/midi/js/midi/plugin.webaudio.js

@@ -1,326 +0,0 @@
-/*
-	----------------------------------------------------------
-	Web Audio API - OGG or MPEG Soundbank
-	----------------------------------------------------------
-	http://webaudio.github.io/web-audio-api/
-	----------------------------------------------------------
-*/
-
-(function(root) { 'use strict';
-
-	window.AudioContext && (function() {
-		var audioContext = null; // new AudioContext();
-		var useStreamingBuffer = false; // !!audioContext.createMediaElementSource;
-		var midi = root.WebAudio = {api: 'webaudio'};
-		var ctx; // audio context
-		var sources = {};
-		var effects = {};
-		var masterVolume = 127;
-		var audioBuffers = {};
-		///
-		midi.audioBuffers = audioBuffers;
-		midi.send = function(data, delay) { };
-		midi.setController = function(channelId, type, value, delay) { };
-
-		midi.setVolume = function(channelId, volume, delay) {
-			if (delay) {
-				setTimeout(function() {
-					masterVolume = volume;
-				}, delay * 1000);
-			} else {
-				masterVolume = volume;
-			}
-		};
-
-		midi.programChange = function(channelId, program, delay) {
-// 			if (delay) {
-// 				return setTimeout(function() {
-// 					var channel = root.channels[channelId];
-// 					channel.instrument = program;
-// 				}, delay);
-// 			} else {
-				var channel = root.channels[channelId];
-				channel.instrument = program;
-// 			}
-		};
-
-		midi.pitchBend = function(channelId, program, delay) {
-// 			if (delay) {
-// 				setTimeout(function() {
-// 					var channel = root.channels[channelId];
-// 					channel.pitchBend = program;
-// 				}, delay);
-// 			} else {
-				var channel = root.channels[channelId];
-				channel.pitchBend = program;
-// 			}
-		};
-
-		midi.noteOn = function(channelId, noteId, velocity, delay) {
-			delay = delay || 0;
-
-			/// check whether the note exists
-			var channel = root.channels[channelId];
-			var instrument = channel.instrument;
-			var bufferId = instrument + '' + noteId;
-			var buffer = audioBuffers[bufferId];
-			if (!buffer) {
-// 				console.log(MIDI.GM.byId[instrument].id, instrument, channelId);
-				return;
-			}
-
-			/// convert relative delay to absolute delay
-			if (delay < ctx.currentTime) {
-				delay += ctx.currentTime;
-			}
-		
-			/// create audio buffer
-			if (useStreamingBuffer) {
-				var source = ctx.createMediaElementSource(buffer);
-			} else { // XMLHTTP buffer
-				var source = ctx.createBufferSource();
-				source.buffer = buffer;
-			}
-
-			/// add effects to buffer
-			if (effects) {
-				var chain = source;
-				for (var key in effects) {
-					chain.connect(effects[key].input);
-					chain = effects[key];
-				}
-			}
-
-			/// add gain + pitchShift
-			var gain = (velocity / 127) * (masterVolume / 127) * 2 - 1;
-			source.connect(ctx.destination);
-			source.playbackRate.value = 1; // pitch shift 
-			source.gainNode = ctx.createGain(); // gain
-			source.gainNode.connect(ctx.destination);
-			source.gainNode.gain.value = Math.min(1.0, Math.max(-1.0, gain));
-			source.connect(source.gainNode);
-			///
-			if (useStreamingBuffer) {
-				if (delay) {
-					return setTimeout(function() {
-						buffer.currentTime = 0;
-						buffer.play()
-					}, delay * 1000);
-				} else {
-					buffer.currentTime = 0;
-					buffer.play()
-				}
-			} else {
-				source.start(delay || 0);
-			}
-			///
-			sources[channelId + '' + noteId] = source;
-			///
-			return source;
-		};
-
-		midi.noteOff = function(channelId, noteId, delay) {
-			delay = delay || 0;
-
-			/// check whether the note exists
-			var channel = root.channels[channelId];
-			var instrument = channel.instrument;
-			var bufferId = instrument + '' + noteId;
-			var buffer = audioBuffers[bufferId];
-			if (buffer) {
-				if (delay < ctx.currentTime) {
-					delay += ctx.currentTime;
-				}
-				///
-				var source = sources[channelId + '' + noteId];
-				if (source) {
-					if (source.gainNode) {
-						// @Miranet: 'the values of 0.2 and 0.3 could of course be used as 
-						// a 'release' parameter for ADSR like time settings.'
-						// add { 'metadata': { release: 0.3 } } to soundfont files
-						var gain = source.gainNode.gain;
-						gain.linearRampToValueAtTime(gain.value, delay);
-						gain.linearRampToValueAtTime(-1.0, delay + 0.3);
-					}
-					///
-					if (useStreamingBuffer) {
-						if (delay) {
-							setTimeout(function() {
-								buffer.pause();
-							}, delay * 1000);
-						} else {
-							buffer.pause();
-						}
-					} else {
-						if (source.noteOff) {
-							source.noteOff(delay + 0.5);
-						} else {
-							source.stop(delay + 0.5);
-						}
-					}
-					///
-					delete sources[channelId + '' + noteId];
-					///
-					return source;
-				}
-			}
-		};
-
-		midi.chordOn = function(channel, chord, velocity, delay) {
-			var res = {};
-			for (var n = 0, note, len = chord.length; n < len; n++) {
-				res[note = chord[n]] = midi.noteOn(channel, note, velocity, delay);
-			}
-			return res;
-		};
-
-		midi.chordOff = function(channel, chord, delay) {
-			var res = {};
-			for (var n = 0, note, len = chord.length; n < len; n++) {
-				res[note = chord[n]] = midi.noteOff(channel, note, delay);
-			}
-			return res;
-		};
-
-		midi.stopAllNotes = function() {
-			for (var sid in sources) {
-				var delay = 0;
-				if (delay < ctx.currentTime) {
-					delay += ctx.currentTime;
-				}
-				var source = sources[sid];
-				source.gain.linearRampToValueAtTime(1, delay);
-				source.gain.linearRampToValueAtTime(0, delay + 0.3);
-				if (source.noteOff) { // old api
-					source.noteOff(delay + 0.3);
-				} else { // new api
-					source.stop(delay + 0.3);
-				}
-				delete sources[sid];
-			}
-		};
-
-		midi.setEffects = function(list) {
-			if (ctx.tunajs) {
-				for (var n = 0; n < list.length; n ++) {
-					var data = list[n];
-					var effect = new ctx.tunajs[data.type](data);
-					effect.connect(ctx.destination);
-					effects[data.type] = effect;
-				}
-			} else {
-				return console.log('Effects module not installed.');
-			}
-		};
-
-		midi.connect = function(opts) {
-			root.setDefaultPlugin(midi);
-			midi.setContext(ctx || createAudioContext(), opts.onsuccess);
-		};
-	
-		midi.getContext = function() {
-			return ctx;
-		};
-	
-		midi.setContext = function(newCtx, onload, onprogress, onerror) {
-			ctx = newCtx;
-
-			/// tuna.js effects module - https://github.com/Dinahmoe/tuna
-			if (typeof Tuna !== 'undefined' && !ctx.tunajs) {
-				ctx.tunajs = new Tuna(ctx);
-			}
-		
-			/// loading audio files
-			var urls = [];
-			var notes = root.keyToNote;
-			for (var key in notes) urls.push(key);
-			///
-			var waitForEnd = function(instrument) {
-				for (var key in bufferPending) { // has pending items
-					if (bufferPending[key]) return;
-				}
-				///
-				if (onload) { // run onload once
-					onload();
-					onload = null;
-				}
-			};
-			///
-			var requestAudio = function(soundfont, instrumentId, index, key) {
-				var url = soundfont[key];
-				if (url) {
-					bufferPending[instrumentId] ++;
-					loadAudio(url, function(buffer) {
-						buffer.id = key;
-						var noteId = root.keyToNote[key];
-						audioBuffers[instrumentId + '' + noteId] = buffer;
-						///
-						if (-- bufferPending[instrumentId] === 0) {
-							var percent = index / 87;
-// 							console.log(MIDI.GM.byId[instrumentId], 'processing: ', percent);
-							soundfont.isLoaded = true;
-							waitForEnd(instrument);
-						}
-					}, function(err) {
-		// 				console.log(err);
-					});
-				}
-			};
-			///
-			var bufferPending = {};
-			for (var instrument in root.Soundfont) {
-				var soundfont = root.Soundfont[instrument];
-				if (soundfont.isLoaded) {
-					continue;
-				}
-				///
-				var synth = root.GM.byName[instrument];
-				var instrumentId = synth.number;
-				///
-				bufferPending[instrumentId] = 0;
-				///
-				for (var index = 0; index < urls.length; index++) {
-					var key = urls[index];
-					requestAudio(soundfont, instrumentId, index, key);
-				}
-			}
-			///
-			setTimeout(waitForEnd, 1);
-		};
-
-		/* Load audio file: streaming | base64 | arraybuffer
-		---------------------------------------------------------------------- */
-		function loadAudio(url, onload, onerror) {
-			if (useStreamingBuffer) {
-				var audio = new Audio();
-				audio.src = url;
-				audio.controls = false;
-				audio.autoplay = false;
-				audio.preload = false;
-				audio.addEventListener('canplay', function() {
-					onload && onload(audio);
-				});
-				audio.addEventListener('error', function(err) {
-					onerror && onerror(err);
-				});
-				document.body.appendChild(audio);
-			} else if (url.indexOf('data:audio') === 0) { // Base64 string
-				var base64 = url.split(',')[1];
-				var buffer = Base64Binary.decodeArrayBuffer(base64);
-				ctx.decodeAudioData(buffer, onload, onerror);
-			} else { // XMLHTTP buffer
-				var request = new XMLHttpRequest();
-				request.open('GET', url, true);
-				request.responseType = 'arraybuffer';
-				request.onload = function() {
-					ctx.decodeAudioData(request.response, onload, onerror);
-				};
-				request.send();
-			}
-		};
-		
-		function createAudioContext() {
-			return new (window.AudioContext || window.webkitAudioContext)();
-		};
-	})();
-})(MIDI);

Some files were not shown because too many files changed in this diff