liushengqiang 1 year ago
parent
commit
c19debc2e0

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


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


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


+ 18 - 4
dist/index.html

@@ -5,15 +5,29 @@
   <meta charset="UTF-8">
   <link rel="icon" href="./favicon.ico" />
   <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
-  <meta http-equiv="Cache-control" content="no-cache">
+  <meta http-equiv="Cache-control" content="no-cache, must-revalidate">
   <meta http-equiv="Cache" content="no-cache">
+  <meta http-equiv="pragma" CONTENT="no-cache">
+  <meta http-equiv="expires" CONTENT="0">
   <title>制谱</title>
+  <script>
+    window.addEventListener('error', function (event) {
+      if (event.target.tagName === 'SCRIPT' && event.target.src.indexOf('assets/index') > -1) {
+        var total = sessionStorage.getItem('SCRIPT_ERROR')
+        total = Number(total) || 0
+        total = total + 1
+        sessionStorage.setItem('SCRIPT_ERROR', total)
+        if (total > 3) return;
+        window.location.reload()
+      }
+    }, true)
+  </script>
   <script src="//at.alicdn.com/t/c/font_4186350_idu6dqxtfd.js"></script>
   <script src="./flexible.js"></script>
   <script src="./abc2svg/xml2abc.js"></script>
   <script src="./abc2svg/jquery-1.11.1.min.js"></script>
-  <script type="module" crossorigin src="./assets/index-cbda5785.js"></script>
-  <link rel="stylesheet" href="./assets/index-e441ae60.css">
+  <script type="module" crossorigin src="./assets/index-4e52ef91.js"></script>
+  <link rel="stylesheet" href="./assets/index-532dd713.css">
   <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};window.__vite_is_modern_browser=true;</script>
   <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
 </head>
@@ -23,7 +37,7 @@
   
   <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
   <script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-2011adef.js"></script>
-  <script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-f4a487c0.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-b8a45295.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 126 - 0
dist/jianpu/MIDI-1.js

@@ -0,0 +1,126 @@
+//MIDI.js-module to handle the%%MIDI parameters
+abc2svg.MIDI={do_midi:function(parm){function tb40(qs){var i,n1=[2,25,8,31,14,37,20,3,26,9,32,15,38,21,4,27,10,33,16,39],n2=[0,19,36,13,30,7,24,1,18,35,12,29,6,23,0,17],da=21-3*qs
+b=new Float32Array(40)
+for(i=0;i<n1.length;i++)
+b[n1[i]]=(qs*i+da)%12
+for(i=1;i<=n2.length;i++)
+b[n2[i]]=12-(qs*i-da)%12
+return b}
+var n,v,s,maps,o,q,n,qs,a=parm.split(/\s+/),abc=this,cfmt=abc.cfmt(),curvoice=abc.get_curvoice()
+if(curvoice){if(curvoice.ignore)
+return
+if(curvoice.chn==undefined)
+curvoice.chn=curvoice.v<9?curvoice.v:curvoice.v+1}
+switch(a[1]){case"chordname":if(!cfmt.chord)
+cfmt.chord={}
+if(!cfmt.chord.names)
+cfmt.chord.names={}
+cfmt.chord.names[a[2]]=a.slice(3)
+break
+case"chordprog":if(!cfmt.chord)
+cfmt.chord={}
+cfmt.chord.prog=a[2]
+if(a[3]&&a[3].slice(0,7)=="octave=")
+cfmt.chord.trans=Number(a[3].slice(7))
+break
+case"chordvol":v=Number(a[2])
+if(isNaN(v)||v<0||v>127){abc.syntax(1,abc.errs.bad_val,"%%MIDI chordvol")
+break}
+if(!cfmt.chord)
+cfmt.chord={}
+cfmt.chord.vol=v/127
+break
+case"gchordon":case"gchordoff":if(!cfmt.chord)
+cfmt.chord={}
+if(abc.parse.state>=2&&abc.get_curvoice()){s=abc.new_block("midigch")
+s.play=true
+s.on=a[1][7]=='n'}else{cfmt.chord.gchon=a[1][7]=='n'}
+break
+case"channel":v=parseInt(a[2])
+if(isNaN(v)||v<=0||v>16){abc.syntax(1,abc.errs.bad_val,"%%MIDI channel")
+break}
+if(--v!=9){if(abc.parse.state==3){s=abc.new_block("midichn");s.play=true
+s.chn=v}else{abc.set_v_param("channel",v)}
+break}
+abc2svg.MIDI.do_midi.call(abc,"MIDI control 0 1")
+abc2svg.MIDI.do_midi.call(abc,"MIDI control 32 0")
+break
+case"drummap":v=Number(a[3])
+if(isNaN(v)){abc.syntax(1,abc.errs.bad_val,"%%MIDI drummap")
+break}
+n=["C","^C","D","_E","E","F","^F","G","^G","A","_B","B"][v%12]
+while(v<60){n+=','
+v+=12}
+while(v>72){n+="'"
+v-=12}
+this.do_pscom("map MIDIdrum "+a[2]+" play="+n)
+abc.set_v_param("mididrum","MIDIdrum")
+break
+case"program":if(a[3]!=undefined){abc2svg.MIDI.do_midi.call(abc,"MIDI channel "+a[2])
+v=a[3]}else{v=a[2]}
+v=parseInt(v)
+if(isNaN(v)||v<0||v>127){abc.syntax(1,abc.errs.bad_val,"%%MIDI program")
+break}
+if(abc.parse.state==3){s=abc.new_block("midiprog");s.play=true
+s.instr=v}else{abc.set_v_param("instr",v)}
+break
+case"control":n=parseInt(a[2])
+if(isNaN(n)||n<0||n>127){abc.syntax(1,"Bad controller number in %%MIDI")
+break}
+v=parseInt(a[3])
+if(isNaN(v)||v<0||v>127){abc.syntax(1,"Bad controller value in %%MIDI")
+break}
+if(abc.parse.state==3){s=abc.new_block("midictl");s.play=true
+s.ctrl=n;s.val=v}else{abc.set_v_param("midictl",a[2]+' '+a[3])}
+break
+case"temperamentequal":n=parseInt(a[2])
+if(isNaN(n)||n<5||n>255){abc.syntax(1,abc.errs.bad_val,"%%MIDI "+a[1])
+return}
+if(n==53){s=abc.get_glyphs()
+s.acc12_53='<text id="acc12_53" x="-1">&#xe282;</text>'
+s.acc24_53='<text id="acc24_53" x="-1">&#xe282;\
+ <tspan x="0" y="-10" style="font-size:8px">2</tspan></text>'
+s.acc36_53='<text id="acc36_53" x="-1">&#xe262;\
+ <tspan x="0" y="-10" style="font-size:8px">3</tspan></text>'
+s.acc48_53='<text id="acc48_53" x="-1">&#xe262;</text>'
+s.acc60_53='<g id="acc60_53">\n\
+ <text style="font-size:1.2em" x="-1">&#xe282;</text>\n\
+ <path class="stroke" stroke-width="1.6" d="M-2 1.5l7 -3"/>\n\
+</g>'
+s["acc-60_53"]='<text id="acc-60_53" x="-1">&#xe260;</text>'
+s["acc-48_53"]='<g id="acc-48_53">\n\
+ <text x="-1">&#xe260;</text>\n\
+ <path class="stroke" stroke-width="1" d="M-3 -5.5l5 -2"/>\n\
+</g>'
+s["acc-36_53"]='<g id="acc-36_53">\n\
+ <text x="-1">&#xe260;\
+  <tspan x="0" y="-10" style="font-size:8px">3</tspan></text>\n\
+ <path class="stroke" stroke-width="1" d="M-3 -5.5l5 -2"/>\n\
+</g>'
+s["acc-24_53"]='<text id="acc-24_53" x="-2">&#xe280;\
+ <tspan x="0" y="-10" style="font-size:8px">2</tspan></text>'
+s["acc-12_53"]='<text id="acc-12_53" x="-2">&#xe280;</text>'}
+q=7.019550008653874,o=12
+cfmt.nedo=n
+qs=((n*q/o+.5)|0)*o/n
+if(qs<6.85||qs>7.2)
+abc.syntax(0,abc.errs.bad_val,"%%MIDI "+a[1])
+cfmt.temper=tb40(qs)
+break}},set_vp:function(of,a){var i,item,curvoice=this.get_curvoice()
+for(i=0;i<a.length;i++){switch(a[i]){case"channel=":curvoice.chn=a[++i]
+break
+case"instr=":curvoice.instr=a[++i]
+break
+case"midictl=":if(!curvoice.midictl)
+curvoice.midictl=[]
+item=a[++i].split(' ');curvoice.midictl[item[0]]=Number(item[1])
+break
+case"mididrum=":if(!curvoice.map)
+curvoice.map={}
+curvoice.map=a[++i]
+break}}
+of(a)},do_pscom:function(of,text){if(text.slice(0,5)=="MIDI ")
+abc2svg.MIDI.do_midi.call(this,text)
+else
+of(text)},set_hooks:function(abc){abc.do_pscom=abc2svg.MIDI.do_pscom.bind(abc,abc.do_pscom);abc.set_vp=abc2svg.MIDI.set_vp.bind(abc,abc.set_vp)}}
+abc2svg.modules.hooks.push(abc2svg.MIDI.set_hooks);abc2svg.modules.MIDI.loaded=true

File diff suppressed because it is too large
+ 107 - 0
dist/jianpu/abc2svg-1.js


+ 366 - 0
dist/jianpu/abcweb-1.js

@@ -0,0 +1,366 @@
+// abc2svg - ABC to SVG translator
+// @source: https://chiselapp.com/user/moinejf/repository/abc2svg
+// Copyright (C) 2014-2023 Jean-Francois Moine - LGPL3+
+//abcweb-1.js file to include in html pages
+window.onerror = function (msg, url, line) {
+    if (typeof msg == 'string')
+        alert("window error: " + msg + "\nURL: " + url + "\nLine: " + line)
+    else if (typeof msg == 'object')
+        alert("window error: " + msg.type + ' ' + msg.target.src)
+    else
+        alert("window error: " + msg)
+    return false
+}
+var user, abcplay
+if (typeof abc2svg == "undefined")
+    var abc2svg = {}
+abc2svg.mu = ""
+abc2svg.abc_end = function () { }
+abc2svg.jsdir = document.currentScript ? document.currentScript.src.match(/.*\//) : (function () {
+    var s_a = document.getElementsByTagName('script')
+    for (var k = 0; k < s_a.length; k++) {
+        if (s_a[k].src.indexOf("abcweb") >= 0)
+            return s_a[k].src.match(/.*\//) || ''
+    }
+    return ""
+})()
+abc2svg.loadjs = function (fn, relay, onerror) {
+    var s = document.createElement('script')
+    if (/:\/\//.test(fn))
+        s.src = fn
+    else
+        s.src = abc2svg.jsdir + fn
+    s.onload = relay
+    s.onerror = function () {
+        if (onerror)
+            onerror(fn)
+        else
+            alert('error loading ' + fn)
+    }
+    document.head.appendChild(s)
+}
+function dom_loaded() {
+    var abc, src, outb, err, a_inc = {}, tune_lst = [], html, busy, playing, playconf = { onend: function () { playing = 0 } }
+    function visible() {
+        var mu, r, wh = window.innerHeight || document.documentElement.clientHeight
+        while (1) {
+            mu = abc2svg.alldiv[0]
+            if (!mu)
+                break
+            r = mu.d.getBoundingClientRect()
+            if (r.top > wh)
+                break
+            musgen(mu)
+            abc2svg.alldiv.shift()
+        }
+        if (abc2svg.alldiv.length) {
+            if (!abc2svg.onscroll) {
+                abc2svg.onscroll = visible
+                window.addEventListener("scroll", visible)
+            }
+        } else { window.removeEventListener("scroll", visible) }
+    }
+    function get_p(e) {
+        var i, j, k, r, o = '', sh = document.styleSheets, s = e.style
+        c = e.getAttribute("class")
+        if (c) {
+            c = '.' + c
+            for (i = 0; i < sh.length; i++) {
+                r = sh[i].rules
+                for (j = 0; j < r.length; j++) {
+                    if (r[j].selectorText == c)
+                        break
+                }
+                if (j < r.length)
+                    break
+            }
+            if (i < sh.length) {
+                r = r[j]
+                for (i = 0; i < r.style.length; i++) {
+                    k = r.style[i]
+                    if (k[0] == '-' && k[1] == '-')
+                        o += '%%' + k.slice(2) + ' '
+                            + r.style.getPropertyValue(k)
+                            + '\n'
+                }
+            }
+        }
+        for (i = 0; i < s.length; i++) {
+            k = s[i]
+            if (k[0] == '-' && k[1] == '-')
+                o += '%%' + k.slice(2) + ' '
+                    + s.getPropertyValue(k)
+                    + '\n'
+        }
+        return o
+    }
+    function move_music(src) {
+        var re, res, i, j, k, t, re_stop = /\n<|\n%.begin[^\s]+/g, ss = 0, out = ""
+        if (/<[^>]* class="[^"]*abc[^"]*/.test(src))
+            re = '<[^>]* class="[^"]*abc[^"]*'
+        else
+            re = '%abc-\\d|X:\\s*\\d'
+        re = new RegExp('(^|\n)(' + re + ')', 'g')
+        while (1) {
+            res = re.exec(src)
+            if (!res)
+                break
+            i = re.lastIndex - res[0].length
+            if (i > ss) {
+                out += src.slice(ss, i)
+                html = 1
+            }
+            t = res[2]
+            if (t[0] == '<') {
+                i = src.indexOf('>', i) + 1
+                j = res[2].indexOf(' ')
+                t = res[2].slice(1, j)
+                j = src.indexOf('</' + t + '>', i)
+                ss = j + t.length + 4
+            } else {
+                re_stop.lastIndex = i
+                while (1) {
+                    res = re_stop.exec(src)
+                    if (!res || res[0] == "\n<")
+                        break
+                    k = src.indexOf(res[0].replace("begin", "end"), re_stop.lastIndex)
+                    if (k < 0)
+                        break
+                    re_stop.lastIndex = k
+                }
+                if (!res || k < 0)
+                    j = src.length
+                else
+                    j = re_stop.lastIndex - 1
+                ss = j
+            }
+            out += '<script type="text/vnd.abc">\n'
+                + src.slice(i, j)
+                + '</script>\n'
+            re.lastIndex = ss
+        }
+        out += src.slice(ss)
+        if (abc2svg.page && html)
+            out += '\
+<pre class="nop" style="background:#ff8080">\
+Printing may be bad because the file contains pure HTML and %%pageheight\
+</pre>\n'
+        document.body.innerHTML = out
+    }
+    function save_music() {
+        var i, k, div, c, s, sa
+        abc2svg.music = [{ t: "", n: "mus0" }]
+        k = location.search
+        if (k) {
+            k = k.substr(1).split("&")
+            for (i = 0; i < k.length; i++)
+                abc2svg.music[0].t += "%%"
+                    + decodeURIComponent(k[i].replace('=', ' '))
+                    + '\n'
+        }
+        while (1) {
+            sa = document.getElementsByTagName('script')
+            for (i = 0; i < sa.length; i++) {
+                s = sa[i]
+                if (s.type == 'text/vnd.abc')
+                    break
+            }
+            if (i >= sa.length)
+                break
+            c = get_p(s)
+            div = document.createElement('div')
+            if (s.text.indexOf('\nX:') < 0) {
+                abc2svg.music[0].t += c + s.innerHTML
+                if (!abc2svg.music[0].d)
+                    abc2svg.music[0].d = div
+            } else { abc2svg.music.push({ n: "mus" + abc2svg.music.length, t: c + s.innerHTML, d: div }) }
+            s.parentNode.replaceChild(div, s)
+        }
+    }
+    function musgen(mu) {
+        var t = mu.t
+        if (busy) {
+            mu.w = 1
+            return
+        }
+        busy = 1
+        function render() {
+            var i, j, e
+            outb = err = ""
+            abc.tosvg(mu.n, t)
+            abc2svg.abc_end()
+            if (mu.d) {
+                if (err)
+                    outb += '<pre class="nop" style="background:#ff8080">'
+                        + err + "</pre>\n"
+                if (abc.cfmt().with_source && outb)
+                    outb = '<pre class="source">'
+                        + clean_txt(t)
+                        + '</pre>\n\
+<div class="source">\n'
+                        + outb
+                        + '</div>\n'
+                mu.d.innerHTML = outb
+                mu.d.addEventListener('click', abc2svg.playseq)
+                e = mu.d.getElementsByTagName('svg')
+                for (i = 0; i < e.length; i++) {
+                    j = e[i].getAttribute('class')
+                    if (!j)
+                        continue
+                    j = j.match(/tune(\d+)/)
+                    if (!j)
+                        continue
+                    j = j[1]
+                    tune_lst[j] = null
+                }
+            }
+            mu.w = busy = 0
+            for (i = 1; i < abc2svg.music.length; i++) {
+                if (abc2svg.music[i].w) {
+                    musgen(abc2svg.music[i])
+                    break
+                }
+            }
+        }
+        function include() {
+            var i, j, fn, r, k = 0
+            while (1) {
+                i = t.indexOf('%%abc-include ', k)
+                if (i < 0) {
+                    render()
+                    return
+                }
+                i += 14
+                j = t.indexOf('\n', i)
+                fn = t.slice(i, j).trim()
+                if (!a_inc[fn])
+                    break
+                k = j
+            }
+            r = new XMLHttpRequest()
+            r.open('GET', fn, true)
+            r.onload = function () {
+                if (r.status === 200) {
+                    a_inc[fn] = r.responseText
+                    if (abc2svg.modules.load(a_inc[fn], include))
+                        include()
+                } else {
+                    a_inc[fn] = '%\n'
+                    alert('Error getting ' + fn + '\n' + r.statusText)
+                    include()
+                }
+            }
+            r.onerror = function () {
+                a_inc[fn] = '%\n'
+                alert('Error getting ' + fn + '\n' + r.statusText)
+                include()
+            }
+            r.send()
+        }
+        if (abc2svg.modules.load(t, include))
+            include()
+    }
+    abc2svg.musgen = musgen
+    user = { read_file: function (fn) { return a_inc[fn] }, errmsg: function (msg, l, c) { err += clean_txt(msg) + '\n' }, img_out: function (p) { outb += p } }
+    function clean_txt(txt) {
+        return txt.replace(/<|>|&.*?;|&/g, function (c) {
+            switch (c) {
+                case '<': return "&lt;"
+                case '>': return "&gt;"
+                case '&': return "&amp;"
+            }
+            return c
+        })
+    }
+    abc2svg.playseq = function (evt) {
+        if (playing) {
+            abcplay.stop()
+            return
+        }
+        var i, j, svg = evt.target, e = svg
+        while (svg.tagName != 'svg') {
+            svg = svg.parentNode
+            if (!svg)
+                return
+        }
+        i = svg.getAttribute('class')
+        if (!i)
+            return
+        i = i.match(/tune(\d+)/)
+        if (!i)
+            return
+        i = i[1]
+        if (!abcplay) {
+            if (typeof AbcPlay == "undefined") {
+                abc2svg.playseq = function () { }
+                return
+            }
+            if (abc.cfmt().soundfont)
+                playconf.sfu = abc.cfmt().soundfont
+            abcplay = AbcPlay(playconf)
+        }
+        if (!tune_lst[i]) {
+            tune_lst[i] = abc.tunes[i]
+            abcplay.add(tune_lst[i][0], tune_lst[i][1], tune_lst[i][3])
+        }
+        s = tune_lst[i][0]
+        i = e.getAttribute('class')
+        if (i)
+            i = i.match(/abcr _(\d+)_/)
+        if (i) {
+            i = i[1]
+            while (s && s.istart != i)
+                s = s.ts_next
+            if (!s) {
+                alert("play bug: no such symbol in the tune")
+                return
+            }
+        }
+        while (s && !s.fname)
+            s = s.ts_next
+        for (i = 1; i < abc2svg.music.length; i++) {
+            if (abc2svg.music[i].n == s.fname)
+                break
+        }
+        abc2svg.mu = abc2svg.music[i]
+        playing = 1
+        abcplay.play(s, null)
+    }
+    src = document.body.innerHTML
+    if (!abc2svg.Abc) {
+        abc2svg.loadjs("abc2svg-1.js", dom_loaded)
+        return
+    }
+    if (src.indexOf('type="text/vnd.abc"') < 0)
+        move_music(src)
+    save_music()
+    abc = new abc2svg.Abc(user)
+    if (typeof follow == "function")
+        follow(abc, user, playconf)
+    if (abc2svg.music[0].t)
+        musgen(abc2svg.music[0])
+    abc2svg.alldiv = []
+    for (var i = 1; i < abc2svg.music.length; i++)
+        abc2svg.alldiv.push(abc2svg.music[i])
+    visible()
+}
+abc2svg.get_music = function (d) {
+    var i, mu
+    for (var i = 1; i < abc2svg.music.length; i++) {
+        mu = abc2svg.music[i]
+        if (mu.d == d)
+            return mu.t
+    }
+}
+abc2svg.set_music = function (d, t) {
+    var i, mu
+    for (var i = 1; i < abc2svg.music.length; i++) {
+        mu = abc2svg.music[i]
+        if (mu.d == d) {
+            mu.t = t
+            abc2svg.musgen(mu)
+            break
+        }
+    }
+}
+window.addEventListener("load", dom_loaded, { once: true })

BIN
dist/jianpu/favicon.ico


+ 400 - 0
dist/jianpu/font.js

@@ -0,0 +1,400 @@
+// abc2svg music font
+var musicfont = 'url("data:application/octet-stream;base64,\
+AAEAAAAOAIAAAwBgRkZUTY1L868AAFgoAAAAHEdERUYAFQAUAABYDAAAABxPUy8yWMFdCgAAAWgA\
+AABWY21hcFz/TQsAAAQIAAADemN2dCAAIgKIAAAHhAAAAARnYXNw//8AAwAAWAQAAAAIZ2x5Zg27\
+S/YAAAiwAABGeGhlYWQTZto6AAAA7AAAADZoaGVhCWn/GwAAASQAAAAkaG10eNlp+7kAAAHAAAAC\
+SGxvY2HP4L6kAAAHiAAAASZtYXhwANkBFgAAAUgAAAAgbmFtZdbpNH4AAE8oAAADJHBvc3SIfxKM\
+AABSTAAABbUAAQAAAAEAAF56eDVfDzz1AAsEAAAAAADRlyIXAAAAAN4tda//OPzvBUsEiAAAAAgA\
+AgAAAAAAAAABAAAEiPzvAFwEJf84/XQFSwABAAAAAAAAAAAAAAAAAAAAkgABAAAAkgDlAAUAAAAA\
+AAIAAAABAAEAAABAAC4AAAAAAAEBgAGQAAUACAKZAswAAACPApkCzAAAAesAMwEJAAACAAUDAAAA\
+AAAAAAAAARAAAAAAAAAAAAAAAFBmRWQAQAAA7LcDOP84AFwEiAMRAAAAAQAAAAAAAAF2ACIAAAAA\
+AVUAAAGQAAACWAAAAFcAAAAjAAAAJQAAACT//wBkAAAEIwAABCUAAAHg/9wDXgB6AwsAAALSAAAC\
+v/+6AdYAAAMLAAADDgAAAyf/yADIAAABaP//Aa4AAAEiAAABkAAAAXwAAAGQAAABkAAAAYEAAAGQ\
+AAABkAAAAYEAAAGZAAkBmAAJAfQAAAEEABQBBAAKAmsAJAISAAABwgAAAUkAAAFAAAABSv/+ASwA\
+AAIwAAABSgAAAUoAAABkAAABQAAAAUAAAAFAAAABQAAAAGQAAAE2AAAA5gAAATYAAAE7AAABOwAA\
+ATsAAAE7AAABOwAAATsAAAE7AAABOwAAATsAAAE7AAABDQAAAMgAAAD/AAABCwAUAW4AAACMAAAA\
+jAAAAQ0AMgFu//UAqQAAAToAAAFA//0AUAAAAVQAAABkAAABGAAAAlgAAAC2AAABkAAEAIIAAACC\
+AAABLAAAASwAAADuAAAA/wAAAUkAAAGPAAAB2AAAAdgAAAIz//ADIP/hAXv/tAG4/9sBFv9+ARP/\
+2wDcAAAA6P/kAr//tAIz/7QCv/+0Ayv/2wFf/9sCaf9+AV//fgJp/34BXwAAAf0ABQG1AAABtQAA\
+AkQADQJEAA0BGAAAATYAAAEs//8BLAAAAPoAAADIAAABGP84APoAAADIAAAEDQAAAhwADAH0AAAB\
+9AAAAfQAAAH0AAAB9AAAAfQAAAB4AAAALQAAAhwAAAD6AAAA+v/oAcIAAAFIAAABQAAAAgoAAAIK\
+AAAAZAAAAAAAAwAAAAMAAAAcAAEAAAAAAnQAAwABAAAAHAAEAlgAAACSAIAABgASAAAAIOAA4DDg\
+OeBD4EjgUOBc4GLgaeB+4IzgleCk4Kngs+EB4bnhu+Hn4fLh9OH34fnh/OIA4kniZOJr4oPkoOSi\
+5KTkqOSs5MDkzuTR5OrlAeUl5S3lMeU55WflaeVt5YLl0OXi5hDmEuYU5hjmJOYw5lDmVekS6RXp\
+GOkg6SXpXeoC6qTso+yl7Kfsqey3//8AAAAAACDgAOAw4DjgQ+BF4FDgXOBi4GngeuCA4JTgoOCp\
+4LPhAeG54bvh5+Hy4fTh9+H54fzh/uJA4mDiauKA5KDkouSk5KjkrOTA5M7k0eTh5QDlIOUp5S/l\
+OeVm5WnlbOWC5dDl4uYQ5hLmFOYY5iTmMOZQ5lXpEOkU6RjpIOkl6V3qAuqk7KLspeyn7Knst///\
+AAP/5CAFH9Yfzx/GH8Ufvh+zH64fqB+YH5cfkB+GH4IfeR8sHnUedB5JHj8ePh48HjseOR44Hfkd\
+4x3eHcobrhutG6wbqRumG5MbhhuEG3UbYBtCGz8bPhs3GwsbChsIGvQapxqWGmkaaBpnGmQaWRpO\
+Gi8aKxdxF3AXbhdnF2MXLBaIFecT6hPpE+gT5xPaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAQYAAAMAAAAAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAABAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiAogAAAAqACoAKgA2\
+AD4AbgB6AIYAkgCwASQBgAHwAjICvgNQA7ADxARgBPIFSgWKBiQGRgZaBqwG/AccB2IHogfcCCgI\
+aAiuCQgJHAlCCWgJmgm2CdgKBAoaCjQKagp4CoQKkAqiCr4K4AruCwILFAskC3ALgAuaC7QL7Awk\
+DHIMvg0kDYYOBA58DqIOvA7sDxYPbg+ID6IPyBAiEEIQgBCoELwQyBDWEOYRDhE0EWwReBGEEZAR\
+nBG+EeQSGhJoEsgTPBNiE5AT5BRYFKwU7BUwFYYWpBd+GBQYxhmOGiYa/hwYHQwdTh2SHdwd9h4a\
+Hi4eQh5yHoIelB6wHsYe6h8aH/ggtCDcIPohLCFqIZwh3iHwIf4iGiI0IloifCKqIsQi7iMqIzwA\
+AAACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8\
+sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAABAAAAAAGRAZAAAwAAMREhEQGRAZD+cAABAAAA\
+AAAAAAAAAAAAMQAAAQAAAAAAVwQDACAAABE1NjU0JyY1NDcGFRQXFhUUBxYVFAcGFRQXJjU0NzY1\
+NDUjElc/FSVNTSUVP1cSIwIDAhhDNmA5NGY6MksiOWFNYRgYZkxgOSVKMjpmNDlgNkgAAQAAAAAA\
+IwPoAAMAABEzESMjIwPo/BgAAQAAAfQAJQPoAAMAABEzESMlJQPo/gwAAf//A2QAJARgAAMAABEz\
+ByMkASQEYPwAAgAAAUAAZAKeAAcADwAAEiImNDYyFhQCIiY0NjIWFEcqHR0qHR0qHR0qHQI6HSod\
+HSr+6R0qHR0qAAAABQAAAAAEJAGuAC8ANwA/AEcAUwAAITUzHgEzMjY1NCcuBDU0NjMyFhc3Mxcj\
+LgEjIgYVFB4DFx4BFRQGIyInByAiJjQ2MhYUBCImNDYyFhQBETMyNjQmIwM1MxEjNTMyFhUUIwJO\
+HhVPMik7lBkaKhYRWT0kJxkeHgceD0owHzkQIhkyCE5NW09FLiMBmyodHSod/eoqHR0qHf6JKDxG\
+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\
+Q1SGKUl4RAMNBCldQ1SGKUl4RAMNBCldQ1QAAAAFAAD9VQE8AhIAJAAyAEAATgBcAAAZATMeBhUU\
+BxYVFAcWFRQHFhUUBxYVFAc2NTQuAyM1HgMXNDY1NC4DJx4DFzQ2NTQuAyceAxc0NjU0LgMnHgMX\
+NDY1NC4DHgYnMzs4LhwSEhISEhISEx4FKT5IQBYJRE1WFQEpPkhBFglETVYVASk+SEEWCURNVhUB\
+KT5IQRYJRE1WFQEpPkhB/rsDVxs5Mzc6PUglLCsnLSwrJy0sKyctLCspKzY5GSE3ZEU0GKskVENd\
+KQMNBDdlRTMZqyRUQ10pBAwEN2VFMxmrJFRDXSkDDgM3ZUUzGaskVENdKQQMBDdlRTMZAAAFAAD9\
+vAE8AnkAIwAwAD0ASgBXAAAZATMyPgI1NCcWFRQHFhUUBxYVFAcWFRQHFhUUDgUHNTI+AjU0JjUO\
+AycyPgI1NCY1DgMnMj4CNTQmNQ4DJzI+AjU0JjUOAx4cVVc9BR4TEhISEhISEhwuODszJwYdVVc9\
+ARVWTUQJHVVXPQEVVk1ECR1VVz0BFVZNRAkdVVc9ARVWTUT9vANXKUh3RCEZOTYrKSssLScrLC0n\
+KywtJyssJUg9OjczORuqKUl4RAMNBCldQ1SGKUl4RAMNBCldQ1SGKUl4RAMNBCldQ1SGKUl4RAMN\
+BCldQ1QAAAACAAD/ZADhAbAACgAWAAA3IgYdATY3NjU0JjcyFhUUBwYjETMRNmcUKyImKx0HIzlL\
+UkQoI3omE7kPODsvGyYmMiNJTFICTP68NAAAAgAA/oYAxQF6AAMADAAAFzc1BxEVNxEjNQcRNxyQ\
+kKkZrAFlLZYtAUnoNP3A4jMCQwEAAAIAAP6YAP8BaAADAB8AADcVNzUDIzUHNTc1BzU3NTMVNzUz\
+FTcVBxU3FQcVIzUHU1paHjU1NTUeWh01NTU1HVpGpxun/jejD1wPpw9aD6ifHKujD1wPpw9aD6if\
+HAAAAAEAFP+EAQsAegAeAAAXNSYnBzAVIzUzNycwIzUzFRYXNzA1MxUjBgcXMDMVwygMM0g5MzM5\
+SCESNEg5IRM0OXw7Jg0zO0oyMkg5IhEzOUciETRIAAQAAP9qAWwBsAAOABwAKwA6AAA3DgEdATI3\
+Njc2NTQnJiM3MhYVFAcGBwYjETMRNhcOAR0BMjc2NzY1NCcmIzcyFhUUBwYHDgEjETMRNk4RHg4e\
+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\
+IyImNTQ2MzIWFRQHMj8BBiMiJjU0NjMyFhUUBzI/ASIOASMiJjU0NjMyFhUUBzI3NjIXAScTBiMi\
+JjU0NjMyFhUUBzI/AQYjIiY1NDYzMhYVFAcyNwE/KCErNycbHCkXQQs2KB8rNycbHCkXPws0ASAc\
+Eys3JxscKRdILgEWA/5qLVUoISs3JxscKRdBCzooISs3JxscKRdBCzQMKCggIB8ZHRsixAwoKCAg\
+HxkdGyLHCQQpKB8gHhkdG00CAvqADAEkDCgoICAfGR0bIsgMKCggIB8ZHRsiAAP/8P8GAiYA+gAH\
+AA8AEwAANiImNDYyFhQAIiY0NjIWFAUBMwFQMiMjMiMBiDIjIzIj/dIBuH7+R0sjMiMjMv7PIzIj\
+IzJaAfT+DAAE/+H/BgMHAPoABwAPABMAFwAANiImNDYyFhQAIiY0NjIWFAUBMwEzATMBQTIjIzIj\
+AncyIyMyI/zjAbh7/kd5Abh7/kdLIzIjIzL+zyMyIyMyWgH0/gwB9P4MAAL/tP+IAXwBGAARADsA\
+ADcWMzI2NzY1NCcmIyIGBwYVFBciJwczMhQrASI0OwETNjU0IyIOAwcGJjc2NzYzMhYXPgEzMhYV\
+FAbFAgUSMg4NDwIEEjULDycqGS00CwvhCwtLaAYLCAwPCxkKBRsFMQ8XJSMkBx0mIx4tWSgBNSQg\
+JiUFATMcJyQpLiB6Hh4BHRIMDwcUEiwQCA8JWBAZExoeDzQwSWsAAAH/2//2Ab4BGABTAAA3BgcG\
+KwEiPwE2JiMiBgcGJjc+AzMyFzYzMhc+ATMyFhUUDwEGFRQzMjc+BTc2FgcOAiMiJjU0PwE2NTQj\
+Ig8BBgcnBiY/ATY1NCMiB1AHCAQENQ0NQgQGCA0WJAUVBBQQIh8SNwskJC0JCykTGSQFLwQIAQQF\
+CwcMAw0BBhUGEhctHxUZBTQBFRsIQQgPJg0IBEMBFRsIFREDARqnDQ8aOQgMCSUaMBIoKCgQGCMa\
+Cw99CwkOAgMJBg8FEgEJDQsfHxoWEw0NiAIEDhSrFgEBAQ8IqwIEDhQAAAAB/37/YAFeAbgAQQAA\
+ByImNTQ2MzIWFRQHBhUUMzI+BzcjIjU0OwE+ATMyFhUUBiMiJjU0NzY0IyIOBwczMhQrAQ4BMiAw\
+FxMSFxIKGQsQDwsNCg4NFAo1ExFBFGk0IDAXExIXEgoZBwwKBwgFBgMGATYTEz8hdqAmIBoiFA8O\
+CwcNDgYREyUkPDdVJxUTS18mIBoiFA8OCwYcBQsKFA0aDR4GKMXBAAAB/9sAAAETARMAKgAANz4B\
+JiMiBg8BBgcGKwEiPwE2JiMiBgcGJjc+ATMyFhc2MzIWFRQjIiY1NNAFAwMFFCQJPwcIBAQ1DQ1C\
+BAYIDhciBRUEITgiGx0EHyQaICsPG+cDBwQsGJwRAwEaow0PGjUIDAk8QBoNJx4ZNxYNFAAAAAEA\
+AAAAANwBGAAxAAAzIiY1NDYyFhUUBxYzMjY1NC4CJyY1NDYzMhYVFAYjIiY1NDcmIyIGFRQeAhcW\
+FRRQHjIVGhcQDBMWIQkLGAY6Ny0iNhYQDRYHDxEPGRESHgUwKxsQFhAMEhAQFhILDwcNBCUwIygk\
+GBAYFA4DDhMRDQkTDBEDICtVAAAB/+T//ADnAQ8APAAAJwYuAT8BIgYjIiYOAQcGJyY3PgE3HgEz\
+MjYzMhcWFA8BBhUUMzI2MzIXFjc2JyI1NDYzMhUUBisBLgEjIgoGCwEFsAUfDAMUDB8FDwQDCAwL\
+AQ4vFSIrBAgFCweeAgIBDQYaIw0IBQckEg0mKB4dGCUIDgMECA0GwQYGAjIFDQsJEh4wAgEGCwEB\
+EQenBgIDAxoKDg0DHQ4VNx4vAxgABf+0/4gFSwEYABEAIwC2AMgA2gAAJRYzMjY3NjU0JyYjIgYH\
+BhUUBRYzMjY3NjU0JyYjIgYHBhUUFyInBzMyFCsBIjQ7ARM2NTQjIg4DBwYmNzY3NjMyFhc+ATMy\
+Fz4BMzIWFz4BMzIXPgEzMhYXPgEzMhc+ATMyFhc+ATMyFhUUBiMiJwczMhQrASI0OwETNjU0IyIG\
+BxUUBiMiJwczMhQrASI0OwETNjU0IyIGBxUUBiMiJwczMhQrASI0OwETNjU0IyIGBxUUBiUWMzI2\
+NzY1NCcmIyIGBwYVFAUWMzI2NzY1NCcmIyIGBwYVFAIKAwQSMg4NDwMDEzQLD/7LAwQSMg4NDwMD\
+EzQLDxMWGS00CwvhCwtLaAYLCAwPCxkKBRsFMQ8XJSMkBx0mIy8TEiIbIyQHHSYjLxMSIhsjJAcd\
+JiMvExIiGyMkBx0mIx4ta0kWGS00CwvhCwtLaAYLDhQUa0kWGS00CwvhCwtLaAYLDhQUa0kWGS00\
+CwvhCwtLaAYLDhQUawODAwQSMg4NDwMDEzQLD/7LAwQSMg4NDwMDEzQLDygBNSQhJSQGATMcJiUo\
+BwE1JCElJAYBMxwmJSgvIHoeHgEdEA4PBxQSLBAIDwlYEBkTGh4PMhwWExoeDzIcFhMaHg8yHBYT\
+Gh4PNDBHbSB6Hh4BHRAODxgjAUdtIHoeHgEdEA4PGCMBR20geh4eAR0QDg8YIwFHbSgBNSQhJSQG\
+ATMcJiUoBwE1JCElJAYBMxwmJSgAAAAE/7T/iAQGARgAbwCBAJMApQAAISInBzMyFCsBIjQ7ARM2\
+NTQjIgYHFRQGIyInBzMyFCsBIjQ7ARM2NTQjIgYHFRQGIyInBzMyFCsBIjQ7ARM2NTQjIg4DBwYm\
+NzY3NjMyFhc+ATMyFz4BMzIWFz4BMzIXPgEzMhYXPgEzMhYVFAYnFjMyNjc2NTQnJiMiBgcGFRQF\
+FjMyNjc2NTQnJiMiBgcGFRQFFjMyNjc2NTQnJiMiBgcGFRQDUhYZLTQLC+ELC0toBgsOFBRrSRYZ\
+LTQLC+ELC0toBgsOFBRrSRYZLTQLC+ELC0toBgsIDA8LGQoFGwUxDxclIyQHHSYjLxMSIhsjJAcd\
+JiMvExIiGyMkBx0mIx4ta0wDBBIyDg0PAwMTNAsP/ssDBBIyDg0PAwMTNAsP/ssDBBIyDg0PAwMT\
+NAsPIHoeHgEdEA4PGCMBR20geh4eAR0QDg8YIwFHbSB6Hh4BHRAODwcUEiwQCA8JWBAZExoeDzIc\
+FhMaHg8yHBYTGh4PNDBHbSgBNSQhJSQGATMcJiUoBwE1JCElJAYBMxwmJSgHATUkISUkBgEzHCYl\
+KAAAA/+0/4gCwQEYAEwAXgBwAAAzIicHMzIUKwEiNDsBEzY1NCMiDgMHBiY3Njc2MzIWFz4BMzIX\
+PgEzMhYXPgEzMhYVFAYjIicHMzIUKwEiNDsBEzY1NCMiBgcVFAYnFjMyNjc2NTQnJiMiBgcGFRQF\
+FjMyNjc2NTQnJiMiBgcGFRTIFhktNAsL4QsLS2gGCwgMDwsZCgUbBTEPFyUjJAcdJiMvExIiGyMk\
+Bx0mIx4ta0kWGS00CwvhCwtLaAYLDhQUa0wDBBIyDg0PAwMTNAsPAVUDBBIyDg0PAwMTNAsPIHoe\
+HgEdEA4PBxQSLBAIDwlYEBkTGh4PMhwWExoeDzQwR20geh4eAR0QDg8YIwFHbSgBNSQhJSQGATMc\
+JiUoBwE1JCElJAYBMxwmJSgAAv/b/4gDKwEYAHIAhAAAJTY3NjMyFhc+ATMyFhUUBiMiJwczMhQr\
+ASI0OwETNjU0IyIOAwcOASMiJjU0PwE2NTQjIg8BBgcnBiY/ATY1NCMiDwEGBwYrASI/ATYmIyIG\
+BwYmNz4DMzIXNjMyFz4BMzIWFRQPAQYVFDMyNz4BFxYzMjY3NjU0JyYjIgYHBhUUAa0xFBgiIyQH\
+HSYjHi1rSRYZLTQLC+ELC0toBgsHDxIOGAgaPC0VGQU0ARUbCEEIDyYNCARDARUbCEQHCAQENQ0N\
+QgQGCA0WJAUVBBQQIh8SNwskJC0JCykTGSQFLwQIAgMPJdEDBBIyDg0PAwMTNAsPd2wYHRMaHg80\
+MEdtIHoeHgEdEA4PDR8bNRA2OBUUDA6IAwMOFKsWAQEBDwirAwMOFKwRAwEapw0PGjkIDAklGjAS\
+KCgoEBgjGg0NfQsJDgIINTkBNSQhJSQGATMcJiUoAAAC/9v/YAMZAbgAUwCZAAA3BgcGKwEiPwE2\
+JiMiBgcGJjc+AzMyFzYzMhc+ATMyFhUUDwEGFRQzMjc+BTc2FgcOAiMiJjU0PwE2NTQjIg8BBgcn\
+BiY/ATY1NCMiBxMiJjU0NjMyFhUUBwYVFDMyPgc3IyImNTQ2OwE+ATMyFhUUBiMiJjU0NzY0IyIO\
+BwczMhYUBisBDgFQBwgEBDUNDUIEBggNFiQFFQQUECIfEjcLJCQtCQspExkkBS8ECAIDBQsHDAMN\
+AQYVBhIXLR8VGQU0ARUbCEEIDyYNCARDARUbCPUgMBcTEhcSChkLEA8LDQoODRQKNQkKCQhBFGk0\
+IDAXExIXEgoZBwwKBwgFBgMGATYJCwsJPyF2FREDARqnDQ8aOQgMCSUaMBIoKCgQGCMaDQ19CwkO\
+AgMJBg8FEgEJDQsfHxoVFAwOiAMDDhSrFgEBAQ8IqwMDDhT+nyYgGiIUDw4LBw0OBhETJSQ8N1Un\
+DAkIC0tfJiAaIhQPDgsGHAULChQNGg0eBgwQDMXBAAAAAf9+/2ACaQG4AHgAACUjDgEjIiY1NDYz\
+MhYVFAcGFRQzMj4HNyMiJjU0NjsBPgEzMhYVFAYjIiY1NDc2NCMiBwYHFz4BMzIWFRQGIyImNTQ3\
+NjQjIg4HBzMyFhQGKwEOASMiJjU0NjMyFhUUBwYVFDMyPgcBX5shdl8gMBcTEhcSChkLEA8LDQoO\
+DRQKNQkKCQhBFGk0IDAXExIXEgoZJhcDAZsUaTQgMBcTEhcSChkHDAoHCAUGAwYBNgkLCwk/IXZf\
+IDAXExIXEgoZCxAPCw0KDw0U5sXBJiAaIhQPDgsHDQ4GERMlJDw3VScMCQgLS18mIBoiFA8OCwYc\
+cwwGAUtfJiAaIhQPDgsGHAULChQNGg0eBgwQDMXBJiAaIhQPDgsHDQ4GERMlJDw3VQAAAAH/fv9g\
+A3QBuACuAAATMz4BMzIWFRQGIyImNTQ3NjQjIgcGBxc+ATMyFhUUBiMiJjU0NzY0IyIOBwczMhYU\
+BisBDgEjIiY1NDYzMhYVFAcGFRQzMj4HNyMOASMiJjU0NjMyFhUUBwYVFDMyPgc3Iw4BIyImNTQ2\
+MzIWFRQHBhUUMzI+BzcjIiY1NDY7AT4BMzIWFRQGIyImNTQ3NjQjIg4CBwbMnBRpNCAwFxMSFxIK\
+GSYXAwGbFGk0IDAXExIXEgoZBwwKBwgFBgMGATYJCgoJPyF2XyAwFxMSFxIKGQsQDwsNCg8NFAqb\
+IXZfIDAXExIXEgoZCxAPCw0KDg0VCpshdl8gMBcTEhcSChkLEA8LDQoODRQKNQkKCQhBFGk0IDAX\
+ExIXEgoZDhUOCAYCAQ5LXyYgGiIUDw4LBhxzDAYBS18mIBoiFA8OCwYcBQsKFA0aDR4GDBAMxcEm\
+IBoiFA8OCwcNDgYREyUkPDdVJ8XBJiAaIhQPDgsHDQ4GERMlJDs4VSfFwSYgGiIUDw4LBw0OBhET\
+JSQ8N1UnDAkIC0tfJiAaIhQPDgsGHBMnIhsKAAH/fv9gBIABuADkAAABFz4BMzIWFRQGIyImNTQ3\
+NjQjIgcGBxc+ATMyFhUUBiMiJjU0NzY0IyIOBwczMhYUBisBDgEjIiY1NDYzMhYVFAcGFRQzMj4H\
+NyMOASMiJjU0NjMyFhUUBwYVFDMyPgc3Iw4BIyImNTQ2MzIWFRQHBhUUMzI+BzcjDgEjIiY1NDYz\
+MhYVFAcGFRQzMj4HNyMiJjU0NjsBPgEzMhYVFAYjIiY1NDc2NCMiBwYHFz4BMzIWFRQGIyImNTQ3\
+NjQjIg4HAdicFGk0IDAXExIXEgoZJhcDAZsUaTQgMBcTEhcSChkHDAoHCAUGAwYBNgkKCgk/IXZf\
+IDAXExIXEgoZCxAPCw0KDw0UCpshdl8gMBcTEhcSChkLEA8LDQoODRQKmyF2XyAwFxMSFxIKGQsQ\
+DwsNCg8NFAqbIXZfIDAXExIXEgoZCxAPCw0KDg0UCjUJCgkIQRRpNCAwFxMSFxIKGSYXAwGbFGk0\
+IDAXExIXEgoZBwwKBwgFBgMGAQ8BS18mIBoiFA8OCwYccwwGAUtfJiAaIhQPDgsGHAULChQNGg0e\
+BgwQDMXBJiAaIhQPDgsHDQ4GERMlJDw3VSfFwSYgGiIUDw4LBw0OBhETJSM8N1YnxcEmIBoiFA8O\
+CwcNDgYREyUkPDdVJ8XBJiAaIhQPDgsHDQ4GERMlJDw3VScMCQgLS18mIBoiFA8OCwYccwwGAUtf\
+JiAaIhQPDgsGHAUKCxMOGQ4dAAAAAAMAAP9gAt8BuAA2AHIAuwAAMyImNTQ2MzIWFRQHFjMyNjU0\
+LgMnLgI1NDYzMhYVFAYjIiY1NDcmIyIGFRQeAhceARUUJQYuAT8BJiMiBiMiDgEHBicmNz4BNxYz\
+MjYzMhcWFA8BBhUUHgEXFj4BJy4BNTQ2MzIVFAYjIiMuASMiBSImNTQ2MzIWFRQHDgEeARUUFjI+\
+BzcjIiY1NDY7AT4BMzIWFRQGIyImNTQ3NjQjIg4HBzMyFhQGKwEOAVAeMhIMDhcMBhgWIQMMBRcD\
+FBgUNy0iNhYQDRYFEA4PGRESHgUbFwEmBgsBBa4KFAYcBgUQEgUQBQMHCwwBLR4gKAcJDQsHmgQa\
+Kg0FCQUCAyQUDCYrIAMDFzUJE/60IDAXExIXEgQBAQIGFhAPCw0KDg0UCjUJCgkIQRRpNCAwFxMS\
+FxIKGQcMCgcIBQYDBgE2CQoKCT8hdisbEBYNCxgMEhYSCQwNBA4CDRIeDyMtJBgQGBQOCAgUEQ0J\
+EwwRAxIfFVoDBAgNBr8FARgfBA0LCBMeLgQDCAIBEQejBgQHAwcLAwQNBggIFAsTNx4qAg2yJiAa\
+IhQPDgsCBQQGAwgGBhETJSQ8N1UnDAkIC0tfJiAaIhQPDgsGHAULChQNGg0eBgwQDMXBAAAAAgAF\
+//sB/AGaAAkALAAAAQ8BBhUUMzI2NwcOASMiJjU0PwEjNTM/AQc3MhU2MzIWFRQGIiY1NDcGDwEj\
+ATZ/OQIUGEQSDCkyHyIiAzdpcxZZJpgZIDUYHRggFgk3EEJIAQkHuAgDFRcPKBkUJBoLC7MgSi54\
+Ci0pHBUSGxEOEhMPJ9gAAQAA//0BtQDUAC8AACUyNTQnBiImNT4BMzIWFRQHBiMiLwEmIyIVFBc2\
+MzIWFRQGByInJjU0NzYzFh8BFgFwLRoQHBQBFwkkLSkXHiYeohoRLhkQDw0VFA0dGBwoFiIqF6Ic\
+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\
+eVkyPHpYMR8eBi45OCUyEgG5/m9GaTgnRWocAU7vNVxHTnVJSHJBSe8AAAAAAgAA/3kCCwKoAB8A\
+KAAAJTURMx4EFRQHFhUUBzY1NCYjERQGIyImNTQ2MzITHgEXNDY1NCYBIh4JMDg2IxUWIgV2OHlZ\
+Mjx6WDE9DoUbAXZr5gFXJEc7QlgzJTIwJC5BGSFfnv7WRmk4J0VqAXY7ojUDDgNfnwAAAQAA/84A\
+ZAAyAAcAABYiJjQ2MhYURyodHSodMh0qHR0qAAAAAAAOAK4AAQAAAAAAAACDAQgAAQAAAAAAAQAH\
+AZwAAQAAAAAAAgAHAbQAAQAAAAAAAwAjAgQAAQAAAAAABAAHAjgAAQAAAAAABQAJAlQAAQAAAAAA\
+BgAHAm4AAwABBAkAAAEGAAAAAwABBAkAAQAOAYwAAwABBAkAAgAOAaQAAwABBAkAAwBGAbwAAwAB\
+BAkABAAOAigAAwABBAkABQASAkAAAwABBAkABgAOAl4AQwBvAHAAeQByAGkAZwBoAHQAIABcADIA\
+NQAxACAAMgAwADEAOAAtADIAMAAxADkAIABKAGUAYQBuAC0ARgByAGEAbgBjAG8AaQBzACAATQBv\
+AGkAbgBlAC4AIABUAGgAaQBzACAAZgBvAG4AdAAgAGkAcwAgAGwAaQBjAGUAbgBzAGUAZAAgAHUA\
+bgBkAGUAcgAgAHQAaABlACAAUwBJAEwAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBz\
+AGUAIABcACgAaAB0AHQAcAA6AC8ALwBzAGMAcgBpAHAAdABzAC4AcwBpAGwALgBvAHIAZwAvAE8A\
+RgBMAFwAKQAuAABDb3B5cmlnaHQgXDI1MSAyMDE4LTIwMTkgSmVhbi1GcmFuY29pcyBNb2luZS4g\
+VGhpcyBmb250IGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBTSUwgT3BlbiBGb250IExpY2Vuc2UgXCho\
+dHRwOi8vc2NyaXB0cy5zaWwub3JnL09GTFwpLgAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAUgBl\
+AGcAdQBsAGEAcgAAUmVndWxhcgAARgBvAG4AdABGAG8AcgBnAGUAIAAyAC4AMAAgADoAIABhAGIA\
+YwAyAHMAdgBnACAAOgAgADEAMgAtADIALQAyADAAMgAyAABGb250Rm9yZ2UgMi4wIDogYWJjMnN2\
+ZyA6IDEyLTItMjAyMgAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAVgBlAHIAcwBpAG8AbgAgACAA\
+AFZlcnNpb24gIAAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA\
+AAAAAAAAAAAAAACSAAAAAQACAQIAAwEDAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMB\
+FAEVARYBFwEYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BLwEw\
+ATEBMgEzATQBNQE2ATcBOAE5AToBOwE8AT0BPgE/AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwB\
+TQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFp\
+AWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8BgAGBAYIBgwGEAYUB\
+hgGHAYgBiQGKAYsBjAGNAY4BjwYubm9kZWYHdW5pRTAwMAd1bmlFMDMwB3VuaUUwMzgHdW5pRTAz\
+OQd1bmlFMDQzB3VuaUUwNDUHdW5pRTA0Ngd1bmlFMDQ3B3VuaUUwNDgHdW5pRTA1MAd1bmlFMDVD\
+B3VuaUUwNjIHdW5pRTA2OQd1bmlFMDdBB3VuaUUwN0IHdW5pRTA3Qwd1bmlFMDdEB3VuaUUwN0UH\
+dW5pRTA4MAd1bmlFMDgxB3VuaUUwODIHdW5pRTA4Mwd1bmlFMDg0B3VuaUUwODUHdW5pRTA4Ngd1\
+bmlFMDg3B3VuaUUwODgHdW5pRTA4OQd1bmlFMDhBB3VuaUUwOEIHdW5pRTA4Qwd1bmlFMDk0B3Vu\
+aUUwOTUHdW5pRTBBMAd1bmlFMEExB3VuaUUwQTIHdW5pRTBBMwd1bmlFMEE0B3VuaUUwQTkHdW5p\
+RTBCMwd1bmlFMTAxB3VuaUUxQjkHdW5pRTFCQgd1bmlFMUU3B3VuaUUxRjIHdW5pRTFGNAd1bmlF\
+MUY3B3VuaUUxRjkHdW5pRTFGQwd1bmlFMUZFB3VuaUUxRkYHdW5pRTIwMAd1bmlFMjQwB3VuaUUy\
+NDEHdW5pRTI0Mgd1bmlFMjQzB3VuaUUyNDQHdW5pRTI0NQd1bmlFMjQ2B3VuaUUyNDcHdW5pRTI0\
+OAd1bmlFMjQ5B3VuaUUyNjAHdW5pRTI2MQd1bmlFMjYyB3VuaUUyNjMHdW5pRTI2NAd1bmlFMjZh\
+B3VuaUUyNmIHdW5pRTI4MAd1bmlFMjgxB3VuaUUyODIHdW5pRTI4Mwd1bmlFNEEwB3VuaUU0QTIH\
+dW5pRTRBNAd1bmlFNEE4B3VuaUU0QUMHdW5pRTRDMAd1bmlFNENFB3VuaUU0RDEHdW5pRTRFMQd1\
+bmlFNEUyB3VuaUU0RTMHdW5pRTRFNAd1bmlFNEU1B3VuaUU0RTYHdW5pRTRFNwd1bmlFNEU4B3Vu\
+aUU0RTkHdW5pRTRFQQd1bmlFNTAwB3VuaUU1MDEHdW5pRTUyMAd1bmlFNTIxB3VuaUU1MjIHdW5p\
+RTUyMwd1bmlFNTI0B3VuaUU1MjUHdW5pRTUyOQd1bmlFNTJBB3VuaUU1MkIHdW5pRTUyQwd1bmlF\
+NTJEB3VuaUU1MkYHdW5pRTUzMAd1bmlFNTMxB3VuaUU1MzkHdW5pRTU2Ngd1bmlFNTY3B3VuaUU1\
+NjkHdW5pRTU2Qwd1bmlFNTZEB3VuaUU1ODIHdW5pRTVEMAd1bmlFNUUyB3VuaUU2MTAHdW5pRTYx\
+Mgd1bmlFNjE0B3VuaUU2MTgHdW5pRTYyNAd1bmlFNjMwB3VuaUU2NTAHdW5pRTY1NQd1bmlFOTEw\
+B3VuaUU5MTEHdW5pRTkxMgd1bmlFOTE0B3VuaUU5MTUHdW5pRTkxOAd1bmlFOTIwB3VuaUU5MjUH\
+dW5pRTk1RAd1bmlFQTAyB3VuaUVBQTQHdW5pRUNBMgd1bmlFQ0EzB3VuaUVDQTUHdW5pRUNBNwd1\
+bmlFQ0E5B3VuaUVDQjcAAAAAAAAB//8AAgABAAAAAAAAAAwAFAAEAAAAAgAAAAEAAAABAAAAAAAB\
+AAAAAN2HW+gAAAAA0ZciFwAAAADeLXWv\
+") format("truetype")'

+ 35 - 0
dist/jianpu/index.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <title>简谱</title>
+
+  <!-- <script src="./snd-1.js"></script> -->
+  <style>
+    svg text[text-anchor="end"]+text[text-anchor="end"]{
+      display: none;
+    }
+  </style>
+</head>
+
+<body>
+  <noscript>
+    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+        Please enable it to continue.</strong>
+  </noscript>
+  <script id="abcData" type="text/vnd.abc" style="display: none;">
+  </script>
+  <script>
+    const abc = location.search.split('c=')[1]
+    const abcData = document.getElementById('abcData');
+    abcData.innerHTML = decodeURIComponent(abc)
+    console.log("🚀 ~ abcData:", abcData)
+  </script>
+
+  <script src="./abcweb-1.js"></script>
+</body>
+
+</html>

+ 251 - 0
dist/jianpu/jianpu-1.js

@@ -0,0 +1,251 @@
+// abc2svg - ABC to SVG translator
+// @source: https://chiselapp.com/user/moinejf/repository/abc2svg
+// Copyright (C) 2014-2023 Jean-Francois Moine - LGPL3+
+//jianpu.js-module to output jiănpŭ(简谱)music sheets
+if(typeof abc2svg=="undefined")
+var abc2svg={}
+abc2svg.jianpu={k_tb:["Cb","Gb","Db","Ab","Eb","Bb","F","C","G","D","A","E","B","F#","C#"],cde2fcg:new Int8Array([0,2,4,-1,1,3,5]),cgd2cde:new Int8Array([0,-4,-1,-5,-2,-6,-3,0,-4,-1,-5,-2,-6,-3,0]),acc2:new Int8Array([-2,-1,3,1,2]),acc_tb:["\ue264","\ue260",,"\ue262","\ue263","\ue261"],calc_beam:function(of,bm,s1){if(!s1.p_v.jianpu)
+return of(bm,s1)},output_music:function(of){var p_v,v,C=abc2svg.C,abc=this,cur_sy=abc.get_cur_sy(),voice_tb=abc.get_voice_tb()
+function ov_def(v){var s1,tim,s=p_v.sym
+while(s){s1=s.ts_prev
+if(!s.invis&&s.dur&&s1.v!=v&&s1.st==s.st&&s1.time==s.time){while(1){if(!s1.prev||s1.prev.bar_type)
+break
+s1=s1.prev}
+while(!s1.bar_type){s1.dy=14
+s1.notes[0].pit=30
+if(s1.type==C.REST)
+s1.combine=-1
+s1=s1.next}
+while(1){s.dy=-14
+s.notes[0].pit=20
+if(!s.next||s.next.bar_type||s.next.time>=s1.time)
+break
+s=s.next}}
+s=s.next}}
+function set_head(){var v,p_v,mt,s2,sk,s,tsfirst=abc.get_tsfirst()
+for(v=0;v<voice_tb.length;v++){p_v=voice_tb[v]
+if(p_v.jianpu)
+break}
+if(v>=voice_tb.length)
+return
+mt=p_v.meter.a_meter[0]
+sk=p_v.key
+s2=p_v.sym
+s={type:C.BLOCK,subtype:"text",time:s2.time,dur:0,v:0,p_v:p_v,st:0,fmt:s2.fmt,seqst:true,text:(sk.k_mode+1)+"="+
+(abc2svg.jianpu.k_tb[sk.k_sf+7+
+abc2svg.jianpu.cde2fcg[sk.k_mode]]),font:abc.get_font("text")}
+if(mt)
+s.text+=' '+(mt.bot?(mt.top+'/'+mt.bot):mt.top)
+s2=tsfirst
+s.next=s2.next
+if(s.next)
+s.next.prev=s
+s.prev=s2
+s2.next=s
+s.ts_next=s2.ts_next
+s.ts_next.ts_prev=s
+s.ts_prev=s2
+s2.ts_next=s}
+function slice(s){var n,s2,s3,jn=s.type==C.REST?0:8
+if(s.dur>=C.BLEN)
+n=3
+else if(s.dur==C.BLEN/2)
+n=1
+else
+n=2
+s.notes[0].dur=s.dur=s.dur_orig=C.BLEN/4
+delete s.fmr
+while(--n>=0){s2={type:C.REST,v:s.v,p_v:s.p_v,st:s.st,dur:C.BLEN/4,dur_orig:C.BLEN/4,fmt:s.fmt,stem:0,multi:0,nhd:0,notes:[{dur:s.dur,pit:s.notes[0].pit,jn:jn}],xmx:0,noplay:true,time:s.time+C.BLEN/4,prev:s,next:s.next}
+s.next=s2
+if(s2.next)
+s2.next.prev=s2
+if(!s.ts_next){s.ts_next=s2
+if(s.soln)
+s.soln=false
+s2.ts_prev=s
+s2.seqst=true}else{for(s3=s.ts_next;s3;s3=s3.ts_next){if(s3.time<s2.time)
+continue
+if(s3.time>s2.time){s2.seqst=true
+s3=s3.ts_prev}
+s2.ts_next=s3.ts_next
+s2.ts_prev=s3
+if(s2.ts_next)
+s2.ts_next.ts_prev=s2
+s3.ts_next=s2
+break}}
+s=s2}}
+function set_note(s,sf){var i,m,note,p,pit,a,nn,delta=abc2svg.jianpu.cgd2cde[sf+7]-2
+s.stem=-1
+s.stemless=true
+if(s.sls){for(i=0;i<s.sls.length;i++)
+s.sls[i].ty=C.SL_ABOVE}
+for(m=0;m<=s.nhd;m++){note=s.notes[m]
+p=note.pit
+pit=p+delta
+note.jn=((pit+77)%7)+1
+note.pit=25
+note.jo=(pit/7)|0
+a=note.acc
+if(a){nn=abc2svg.jianpu.cde2fcg[(p+5+16*7)%7]-sf
+if(a!=3)
+nn+=a*7
+nn=((((nn+1+21)/7)|0)+2-3+32*5)%5
+note.acc=abc2svg.jianpu.acc2[nn]}
+if(note.sls){for(i=0;i<note.sls.length;i++)
+note.sls[i].ty=C.SL_ABOVE}
+if(note.tie_ty)
+note.tie_ty=C.SL_ABOVE}
+if(s.dur>=C.BLEN/2&&!s.invis)
+slice(s)
+if(s.a_dd){for(i=0;i<s.a_dd.length;i++){if(s.a_dd[i].glyph=="stc"){abc.deco_put("gstc",s)
+s.a_dd[i]=s.a_dd.pop()}}}}
+function set_sym(p_v){var s,g,sf=p_v.key.k_sf
+delete p_v.key.k_a_acc
+s=p_v.clef
+s.invis=true
+s.clef_type='t'
+s.clef_line=2
+for(s=p_v.sym;s;s=s.next){s.st=p_v.st
+switch(s.type){case C.CLEF:s.invis=true
+s.clef_type='t'
+s.clef_line=2
+default:continue
+case C.KEY:sf=s.k_sf
+s.a_gch=[{type:'@',font:abc.get_font("annotation"),wh:[10,10],x:-5,y:26,text:(s.k_mode+1)+"="+
+(abc2svg.jianpu.k_tb[sf+7+
+abc2svg.jianpu.cde2fcg[s.k_mode]])}]
+continue
+case C.REST:if(s.notes[0].jn)
+continue
+s.notes[0].jn=0
+if(s.dur>=C.BLEN/2&&!s.invis)
+slice(s)
+continue
+case C.NOTE:set_note(s,sf)
+break
+case C.GRACE:for(g=s.extra;g;g=g.next)
+set_note(g,sf)
+break}}}
+set_head()
+for(v=0;v<voice_tb.length;v++){p_v=voice_tb[v]
+if(p_v.jianpu){set_sym(p_v)
+if(p_v.second)
+ov_def(v)}}
+of()},draw_symbols:function(of,p_voice){var s,s2,nl,y,C=abc2svg.C,abc=this,dot="\ue1e7",staff_tb=abc.get_staff_tb(),out_svg=abc.out_svg,out_sxsy=abc.out_sxsy,xypath=abc.xypath
+if(!p_voice.jianpu){of(p_voice)
+return}
+function draw_dur(s1,x,y,s2,n,nl){var s,s3,sc=s1.grace?.5:1
+xypath(x-3,y+5)
+out_svg('h'+((s2.x-s1.x)/sc+8).toFixed(1)+'"/>\n')
+y-=2.5
+while(++n<=nl){s=s1
+while(1){if(s.nflags&&s.nflags>=n){s3=s
+while(s!=s2){if(s.next.beam_br1||(s.next.beam_br2&&n>2)||(s.next.nflags&&s.next.nflags<n))
+break
+s=s.next}
+draw_dur(s3,s3.x,y,s,n,nl)}
+if(s==s2)
+break
+s=s.next}}}
+function out_mus(x,y,p){out_svg('<text x="')
+out_sxsy(x,'" y="',y)
+out_svg('">'+p+'</text>\n')}
+function out_txt(x,y,p){out_svg('<text class="fj" x="')
+out_sxsy(x,'" y="',y)
+out_svg('">'+p+'</text>\n')}
+function draw_hd(s,x,y){var m,note,ym
+for(m=0;m<=s.nhd;m++){note=s.notes[m]
+out_txt(x-3.5,y+8,"01234567-"[note.jn])
+if(note.acc)
+out_mus(x-12,y+12,abc2svg.jianpu.acc_tb[note.acc+2])
+if(note.jo>2){out_mus(x-1,y+22,dot)
+if(note.jo>3){y+=3
+out_mus(x-1,y+22,dot)}}else if(note.jo<2){ym=y+4
+if(m==0&&s.nflags>0)
+ym-=2.5*s.nflags
+out_mus(x-1,ym,dot)
+if(note.jo<1){ym-=3
+out_mus(x-1,ym,dot)}}
+y+=20}}
+function draw_note(s){var sc=1,x=s.x,y=staff_tb[s.st].y
+if(s.dy)
+y+=s.dy
+if(s.grace){out_svg('<g transform="translate(')
+out_sxsy(x,',',y+15)
+out_svg(') scale(.5)">\n')
+abc.stv_g().g++
+x=0
+y=0
+sc=.5}
+draw_hd(s,x,y)
+if(s.nflags>=0&&s.dots)
+out_mus(x+8*sc,y+13*sc,dot)
+if(s.grace){out_svg('</g>\n')
+abc.stv_g().g--}}
+for(s=p_voice.sym;s;s=s.next){if(s.invis)
+continue
+switch(s.type){case C.METER:abc.draw_meter(s)
+break
+case C.NOTE:case C.REST:draw_note(s)
+break
+case C.GRACE:for(g=s.extra;g;g=g.next)
+draw_note(g)
+break}}
+for(s=p_voice.sym;s;s=s.next){if(s.invis)
+continue
+switch(s.type){case C.NOTE:case C.REST:nl=s.nflags
+if(nl<=0)
+continue
+y=staff_tb[s.st].y
+s2=s
+while(s.next&&s.next.nflags>0){s=s.next
+if(s.nflags>nl)
+nl=s.nflags
+if(s.beam_end)
+break}
+if(s.dy)
+y+=s.dy
+draw_dur(s2,s2.x,y,s,1,nl)
+break}}},set_fmt:function(of,cmd,param){if(cmd=="jianpu"){this.set_v_param("jianpu",param)
+return}
+of(cmd,param)},set_pitch:function(of,last_s){of(last_s)
+if(!last_s)
+return
+var C=abc2svg.C
+for(var s=this.get_tsfirst();s;s=s.ts_next){if(!s.p_v.jianpu)
+continue
+switch(s.type){case C.KEY:if(s.prev.type==C.CLEF||s.v!=0)
+s.a_gch=null
+break
+case C.NOTE:s.ymx=20*s.nhd+22
+if(s.notes[s.nhd].jo>2){s.ymx+=3
+if(s.notes[s.nhd].jo>3)
+s.ymx+=2}
+s.ymn=0
+break}}},set_vp:function(of,a){var i,p_v=this.get_curvoice()
+for(i=0;i<a.length;i++){if(a[i]=="jianpu="){p_v.jianpu=this.get_bool(a[++i])
+if(p_v.jianpu)
+this.set_vp(["staffsep=","20","sysstaffsep=","14","stafflines=","...","tuplets=","0 1 0 1"])
+break}}
+of(a)},set_width:function(of,s){of(s)
+if(!s.p_v||!s.p_v.jianpu)
+return
+var w,m,note,C=abc2svg.C
+switch(s.type){case C.CLEF:case C.KEY:s.wl=s.wr=.1
+break
+case C.NOTE:for(m=0;m<=s.nhd;m++){note=s.notes[m]
+if(note.acc&&s.wl<14)
+s.wl=14}
+break}},set_hooks:function(abc){abc.calculate_beam=abc2svg.jianpu.calc_beam.bind(abc,abc.calculate_beam)
+abc.draw_symbols=abc2svg.jianpu.draw_symbols.bind(abc,abc.draw_symbols)
+abc.output_music=abc2svg.jianpu.output_music.bind(abc,abc.output_music)
+abc.set_format=abc2svg.jianpu.set_fmt.bind(abc,abc.set_format)
+abc.set_pitch=abc2svg.jianpu.set_pitch.bind(abc,abc.set_pitch)
+abc.set_vp=abc2svg.jianpu.set_vp.bind(abc,abc.set_vp)
+abc.set_width=abc2svg.jianpu.set_width.bind(abc,abc.set_width)
+abc.get_glyphs().gstc='<circle id="gstc" cx="0" cy="-3" r="2"/>'
+abc.get_decos().gstc="0 gstc 5 1 1"
+abc.add_style("\n.fj{font:15px sans-serif}")}}
+if(!abc2svg.mhooks)
+abc2svg.mhooks={}
+abc2svg.mhooks.jianpu=abc2svg.jianpu.set_hooks

+ 408 - 0
dist/jianpu/play-1.js

@@ -0,0 +1,408 @@
+//snd-1.js-file to include in html pages with abc2svg-1.js for playing
+function AbcPlay(i_conf){var conf=i_conf,init={},audio=ToAudio(),audio5,midi5,current,abcplay={clear:audio.clear,add:audio.add,set_sfu:function(v){if(v==undefined)
+return conf.sfu
+conf.sfu=v},set_speed:function(v){if(v==undefined)
+return conf.speed
+conf.new_speed=v},set_vol:function(v){if(v==undefined)
+return conf.gain;conf.gain=v
+if(current&&current.set_vol)
+current.set_vol(v)},play:play,stop:vf}
+function vf(){}
+function play(istart,i_iend,a_e){init.istart=istart;init.i_iend=i_iend;init.a_e=a_e
+if(midi5)
+midi5.get_outputs(play2)
+else
+play2()}
+function play2(out){var o
+if(!out)
+out=[]
+o=audio5.get_outputs()
+if(o)
+Array.prototype.push.apply(out,o)
+if(out.length==0){if(conf.onend)
+conf.onend()
+return}
+if(out.length==1){o=0}else{o=-1
+var pr="Use"
+for(var i=0;i<out.length;i++)
+pr+="\n "+i+": "+out[i]
+var res=window.prompt(pr,'0')
+if(res){o=Number(res)
+if(isNaN(o)||o<0||o>=out.length)
+o=-1}
+if(!res||o<0){if(conf.onend)
+conf.onend()
+return}}
+current=out[o]=='sf2'?audio5:midi5;abcplay.play=current.play;abcplay.stop=current.stop
+if(current.set_output)
+current.set_output(out[o]);if(abc2svg.pwait){if(typeof abc2svg.pwait=="boolean"){abc2svg.pwait=function(){abcplay.play(init.istart,init.i_iend,init.a_e)}}
+return}
+abcplay.play(init.istart,init.i_iend,init.a_e)}
+conf.gain=0.7;conf.speed=1;(function(){var v
+try{if(!localStorage)
+return}catch(e){return}
+if(!conf.sfu){v=localStorage.getItem("sfu")
+if(v)
+conf.sfu=v}
+v=localStorage.getItem("volume")
+if(v)
+conf.gain=Number(v)})()
+if(typeof Midi5=="function")
+midi5=Midi5(conf)
+if(typeof Audio5=="function")
+audio5=Audio5(conf);return abcplay}
+if(typeof module=='object'&&typeof exports=='object')
+exports.AbcPlay=AbcPlay
+function ToAudio(){var C=abc2svg.C,a_e,p_time,abc_time,play_factor
+return{clear:function(){var a_pe=a_e;a_e=null
+return a_pe},add:function(start,voice_tb){var i,n,dt,d,v,rep_st_s,rep_en_s,rep_nx_s,rep_st_fac,instr=[],s=start
+function set_voices(){var v,p_v,s,mi
+a_e.push(new Float32Array([0,0,-1,121,0,1,0]))
+for(v=0;v<voice_tb.length;v++){p_v=voice_tb[v];mi=p_v.instr||0
+if(p_v.midictl){for(s=p_v.sym;s;s=s.next)
+if(s.dur)
+break
+if(!s)
+continue
+p_v.midictl.forEach(function(val,i){a_e.push(new Float32Array([s.istart,0,-1,i,val,1,v]))})}
+instr[v]=mi}}
+function do_tie(s,b40,d){var i,note,v=s.v,end_time=s.time+s.dur
+for(s=s.ts_next;;s=s.ts_next){if(!s)
+return d
+if(s==rep_en_s){s=rep_nx_s
+while(s&&s.v!=v)
+s=s.ts_next
+if(!s)
+return d
+end_time=s.time}
+if(s.time!=end_time)
+return d
+if(s.type==C.NOTE&&s.v==v)
+break}
+i=s.notes.length
+while(--i>=0){note=s.notes[i]
+if(note.b40==b40){note.ti2=true
+d+=s.dur/play_factor;return note.tie_ty?do_tie(s,b40,d):d}}
+return d}
+function gen_grace(s){var g,i,n,t,d,s2,next=s.next
+if(s.sappo){d=C.BLEN/16}else if((!next||next.type!=C.NOTE)&&s.prev&&s.prev.type==C.NOTE){d=s.prev.dur/2}else{next.ts_prev.ts_next=next.ts_next;next.ts_next.ts_prev=next.ts_prev;for(s2=next.ts_next;s2;s2=s2.ts_next){if(s2.time!=next.time){next.ts_next=s2
+next.ts_prev=s2.ts_prev;next.ts_prev.ts_next=next;s2.ts_prev=next
+break}}
+d=next.dur/12
+if(d&(d-1)==0)
+d=next.dur/2
+else
+d=next.dur/3;next.time+=d;next.dur-=d}
+n=0
+for(g=s.extra;g;g=g.next)
+if(g.type==C.NOTE)
+n++;d/=n*play_factor;t=p_time
+for(g=s.extra;g;g=g.next){if(g.type!=C.NOTE)
+continue
+gen_notes(g,t,d);t+=d}}
+function gen_notes(s,t,d){for(var i=0;i<=s.nhd;i++){var note=s.notes[i]
+if(note.ti2)
+continue
+a_e.push(new Float32Array([s.istart,t,instr[s.v],note.midi,note.tie_ty?do_tie(s,note.b40,d):d,1,s.v]))}}
+if(!a_e){a_e=[]
+abc_time=p_time=0;play_factor=C.BLEN/4*120/60}else if(s.time<abc_time){abc_time=s.time}
+set_voices()
+while(s){if(s.tempo){d=0;n=s.tempo_notes.length
+for(i=0;i<n;i++)
+d+=s.tempo_notes[i];play_factor=d*s.tempo/60}
+dt=s.time-abc_time
+if(dt>0){p_time+=dt/play_factor;abc_time=s.time}
+switch(s.type){case C.BAR:if(!s.seqst)
+break
+if(s==rep_en_s){s=rep_nx_s
+abc_time=s.time}else if(s.bar_type[0]==':'){rep_nx_s=s
+if(!rep_en_s)
+rep_en_s=s
+if(rep_st_s){s=rep_st_s
+play_factor=rep_st_fac}else{s=start;set_voices()}
+abc_time=s.time
+break}
+if(s.bar_type[s.bar_type.length-1]==':'){rep_st_s=s;rep_en_s=null
+rep_st_fac=play_factor}else if(s.text&&s.text[0]=='1'){rep_en_s=s}
+break
+case C.GRACE:if(s.time==0&&abc_time==0){dt=0
+if(s.sappo)
+dt=C.BLEN/16
+else if(!s.next||s.next.type!=C.NOTE)
+dt=d/2;abc_time-=dt}
+gen_grace(s)
+break
+case C.REST:case C.NOTE:d=s.dur
+if(s.next&&s.next.type==C.GRACE){dt=0
+if(s.next.sappo)
+dt=C.BLEN/16
+else if(!s.next.next||s.next.next.type!=C.NOTE)
+dt=d/2;s.next.time-=dt;d-=dt}
+d/=play_factor
+if(s.type==C.NOTE)
+gen_notes(s,p_time,d)
+else
+a_e.push(new Float32Array([s.istart,p_time,0,0,d,0,s.v]))
+break
+case C.BLOCK:switch(s.subtype){case"midictl":a_e.push(new Float32Array([s.istart,p_time,-1,s.ctrl,s.val,1,s.v]))
+break
+case"midiprog":instr[s.v]=s.instr
+break}
+break}
+s=s.ts_next}}}}
+if(typeof module=='object'&&typeof exports=='object')
+exports.ToAudio=ToAudio
+var abcsf2=[]
+function Audio5(i_conf){var conf=i_conf,onend=function(){},onnote=function(){},errmsg,ac,gain,params=[],rates=[],w_instr=0,evt_idx,iend,stime,timouts=[]
+function js_instr_load(instr,done,fail){abc2svg.loadjs(conf.sfu+'/'+instr+'.js',function(){done(b64dcod(abcsf2[instr]))},fail)}
+if(!conf.instr_load)
+conf.instr_load=js_instr_load
+var b64d=[]
+function init_b64d(){var b64l='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',l=b64l.length
+for(var i=0;i<l;i++)
+b64d[b64l[i]]=i
+b64d['=']=0}
+function b64dcod(s){var i,t,dl,a,l=s.length,j=0
+dl=l*3/4
+if(s[l-1]=='='){if(s[l-2]=='=')
+dl--;dl--;l-=4}
+a=new Uint8Array(dl)
+for(i=0;i<l;i+=4){t=(b64d[s[i]]<<18)+
+(b64d[s[i+1]]<<12)+
+(b64d[s[i+2]]<<6)+
+b64d[s[i+3]];a[j++]=(t>>16)&0xff;a[j++]=(t>>8)&0xff;a[j++]=t&0xff}
+if(l!=s.length){t=(b64d[s[i]]<<18)+
+(b64d[s[i+1]]<<12)+
+(b64d[s[i+2]]<<6)+
+b64d[s[i+3]];a[j++]=(t>>16)&0xff
+if(j<dl)
+a[j++]=(t>>8)&0xff}
+return a}
+function sample_cp(b,s){var i,n,a=b.getChannelData(0)
+for(i=0;i<s.length;i++)
+a[i]=s[i]/196608}
+function sf2_create(parser,instr){var i,sid,gen,parm,sampleRate,sample,j,infos=[],instrument=parser.instrument,zone=parser.instrumentZone
+i=instrument[0].instrumentBagIndex
+j=instrument[1]?instrument[1].instrumentBagIndex:zone.length
+while(i<j){infos.push({generator:parser.createInstrumentGenerator_(zone,i).generator})
+i++}
+rates[instr]=[]
+for(i=0;i<infos.length;i++){gen=infos[i].generator;if(!gen.sampleID)
+continue
+sid=gen.sampleID.amount;sampleRate=parser.sampleHeader[sid].sampleRate;sample=parser.sample[sid];parm={attack:Math.pow(2,(gen.attackVolEnv?gen.attackVolEnv.amount:-12000)/1200),hold:Math.pow(2,(gen.holdVolEnv?gen.holdVolEnv.amount:-12000)/1200),decay:Math.pow(2,(gen.decayVolEnv?gen.decayVolEnv.amount:-12000)/1200)/3,sustain:gen.sustainVolEnv?(gen.sustainVolEnv.amount/1000):0,buffer:ac.createBuffer(1,sample.length,sampleRate)}
+parm.hold+=parm.attack;parm.decay+=parm.hold;if(parm.sustain>=.4)
+parm.sustain=0.01
+else
+parm.sustain=1-parm.sustain/.4
+sample_cp(parm.buffer,sample)
+if(gen.sampleModes&&(gen.sampleModes.amount&1)){parm.loopStart=parser.sampleHeader[sid].startLoop/sampleRate;parm.loopEnd=parser.sampleHeader[sid].endLoop/sampleRate}
+var scale=(gen.scaleTuning?gen.scaleTuning.amount:100)/100,tune=(gen.coarseTune?gen.coarseTune.amount:0)+
+(gen.fineTune?gen.fineTune.amount:0)/100+
+parser.sampleHeader[sid].pitchCorrection/100-
+(gen.overridingRootKey?gen.overridingRootKey.amount:parser.sampleHeader[sid].originalPitch)
+for(j=gen.keyRange.lo;j<=gen.keyRange.hi;j++){rates[instr][j]=Math.pow(Math.pow(2,1/12),(j+tune)*scale);params[instr][j]=parm}}}
+function load_instr(instr,a_e){w_instr++;conf.instr_load(instr,function(sf2_bin){var parser=new sf2.Parser(sf2_bin);parser.parse();sf2_create(parser,instr);if(--w_instr==0)
+play_start(a_e)},function(){errmsg('could not find the instrument '+
+((instr/128)|0).toString()+'-'+
+(instr%128).toString());if(--w_instr==0)
+play_start(a_e)})}
+function load_res(a_e){var i,e,instr,v,bk=[]
+for(i=evt_idx;i<iend;i++){e=a_e[i]
+if(!e)
+break
+instr=e[2]
+v=e[6]
+if(bk[v]==undefined)
+bk[v]=0
+if(instr<0){switch(e[3]){case 0:bk[v]=(bk[v]&0x3fff)|(e[4]<<14)
+break
+case 32:bk[v]=(bk[v]&0x1fc07f)|(e[4]<<7)
+break
+case 121:bk=[]
+break}}else{if(bk[v]){instr&=0x7f
+instr|=bk[v]
+e[2]=instr}
+if(!params[instr]){params[instr]=[];load_instr(instr,a_e)}}}}
+function note_run(e,t,d){var g,st,instr=e[2],key=e[3]|0,parm=params[instr][key],o=ac.createBufferSource();if(!parm)
+return
+o.buffer=parm.buffer
+if(parm.loopStart){o.loop=true;o.loopStart=parm.loopStart;o.loopEnd=parm.loopEnd}
+if(o.detune){var dt=(e[3]*100)%100
+if(dt)
+o.detune.value=dt}
+o.playbackRate.value=rates[instr][key];g=ac.createGain();if(parm.hold<0.002){g.gain.setValueAtTime(1,t)}else{if(parm.attack<0.002){g.gain.setValueAtTime(1,t)}else{g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(1,t+parm.attack)}
+g.gain.setValueAtTime(1,t+parm.hold)}
+g.gain.exponentialRampToValueAtTime(parm.sustain,t+parm.decay);o.connect(g);g.connect(gain);o.start(t);o.stop(t+d)}
+function play_next(a_e){var t,e,e2,maxt,st,d;if(a_e)
+e=a_e[evt_idx]
+if(!e||evt_idx>=iend){onend()
+return}
+if(conf.new_speed){stime=ac.currentTime-
+(ac.currentTime-stime)*conf.speed/conf.new_speed;conf.speed=conf.new_speed;conf.new_speed=0}
+timouts=[];t=e[1]/conf.speed;maxt=t+3
+while(1){d=e[4]/conf.speed
+if(e[2]>=0){if(e[5]!=0)
+note_run(e,t+stime,d)
+var i=e[0];st=(t+stime-ac.currentTime)*1000;timouts.push(setTimeout(onnote,st,i,true));setTimeout(onnote,st+d*1000,i,false)}
+e=a_e[++evt_idx]
+if(!e||evt_idx>=iend){setTimeout(onend,(t+stime-ac.currentTime+d)*1000)
+return}
+t=e[1]/conf.speed
+if(t>maxt)
+break}
+timouts.push(setTimeout(play_next,(t+stime-ac.currentTime)*1000-300,a_e))}
+function play_start(a_e){if(iend==0){onend()
+return}
+if(w_instr!=0)
+return
+gain.connect(ac.destination);stime=ac.currentTime+.2
+-a_e[evt_idx][1]*conf.speed;play_next(a_e)}
+init_b64d();if(!conf.sfu)
+conf.sfu="Scc1t2"
+return{get_outputs:function(){return(window.AudioContext||window.webkitAudioContext)?['sf2']:null},play:function(istart,i_iend,a_e){if(!a_e||istart>=a_e.length){onend()
+return}
+if(conf.onend)
+onend=conf.onend
+if(conf.onnote)
+onnote=conf.onnote
+errmsg=conf.errmsg||alert
+function play_unlock(){var buf=ac.createBuffer(1,1,22050),src=ac.createBufferSource();src.buffer=buf;src.connect(ac.destination);src.noteOn(0)}
+if(!gain){ac=conf.ac
+if(!ac){conf.ac=ac=new(window.AudioContext||window.webkitAudioContext);if(/iPad|iPhone|iPod/.test(navigator.userAgent))
+play_unlock()}
+gain=ac.createGain();gain.gain.value=conf.gain}
+iend=i_iend;evt_idx=istart;load_res(a_e);play_start(a_e)},stop:function(){iend=0
+timouts.forEach(function(id){clearTimeout(id)})
+play_next()
+if(gain){gain.disconnect();gain=null}},set_vol:function(v){if(gain)
+gain.gain.value=v}}}
+(function(root,factory){if(typeof exports==="object"){root.sf2=exports;factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],function(exports){root.sf2=exports;return(root.sf2,factory(exports))})}else{root.sf2={};factory(root.sf2)}}(this,function(sf2){"use strict";sf2.Parser=function(input,options){options=options||{};this.input=input;this.parserOptions=options.parserOptions};sf2.Parser.prototype.parse=function(){var parser=new sf2.Riff.Parser(this.input,this.parserOptions),chunk;parser.parse();if(parser.chunkList.length!==1)
+throw new Error('wrong chunk length');chunk=parser.getChunk(0);if(chunk===null)
+throw new Error('chunk not found');this.parseRiffChunk(chunk);this.input=null};sf2.Parser.prototype.parseRiffChunk=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='RIFF')
+throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='sfbk')
+throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.getNumberOfChunks()!==3)
+throw new Error('invalid sfbk structure');this.parseInfoList(parser.getChunk(0));this.parseSdtaList(parser.getChunk(1));this.parsePdtaList(parser.getChunk(2))};sf2.Parser.prototype.parseInfoList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
+throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='INFO')
+throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse()};sf2.Parser.prototype.parseSdtaList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
+throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='sdta')
+throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.chunkList.length!==1)
+throw new Error('TODO');this.samplingData=parser.getChunk(0)};sf2.Parser.prototype.parsePdtaList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
+throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='pdta')
+throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.getNumberOfChunks()!==9)
+throw new Error('invalid pdta chunk');this.parsePhdr((parser.getChunk(0)));this.parsePbag((parser.getChunk(1)));this.parsePmod((parser.getChunk(2)));this.parsePgen((parser.getChunk(3)));this.parseInst((parser.getChunk(4)));this.parseIbag((parser.getChunk(5)));this.parseImod((parser.getChunk(6)));this.parseIgen((parser.getChunk(7)));this.parseShdr((parser.getChunk(8)))};sf2.Parser.prototype.parsePhdr=function(chunk){var data=this.input,ip=chunk.offset,presetHeader=this.presetHeader=[],size=chunk.offset+chunk.size;if(chunk.type!=='phdr')
+throw new Error('invalid chunk type:'+chunk.type);while(ip<size){presetHeader.push({presetName:String.fromCharCode.apply(null,data.subarray(ip,ip+=20)),preset:data[ip++]|(data[ip++]<<8),bank:data[ip++]|(data[ip++]<<8),presetBagIndex:data[ip++]|(data[ip++]<<8),library:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0,genre:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0,morphology:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0})}};sf2.Parser.prototype.parsePbag=function(chunk){var data=this.input,ip=chunk.offset,presetZone=this.presetZone=[],size=chunk.offset+chunk.size;if(chunk.type!=='pbag')
+throw new Error('invalid chunk type:'+chunk.type);while(ip<size){presetZone.push({presetGeneratorIndex:data[ip++]|(data[ip++]<<8),presetModulatorIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parsePmod=function(chunk){if(chunk.type!=='pmod')
+throw new Error('invalid chunk type:'+chunk.type);this.presetZoneModulator=this.parseModulator(chunk)};sf2.Parser.prototype.parsePgen=function(chunk){if(chunk.type!=='pgen')
+throw new Error('invalid chunk type:'+chunk.type);this.presetZoneGenerator=this.parseGenerator(chunk)};sf2.Parser.prototype.parseInst=function(chunk){var data=this.input,ip=chunk.offset,instrument=this.instrument=[],size=chunk.offset+chunk.size;if(chunk.type!=='inst')
+throw new Error('invalid chunk type:'+chunk.type);while(ip<size){instrument.push({instrumentName:String.fromCharCode.apply(null,data.subarray(ip,ip+=20)),instrumentBagIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parseIbag=function(chunk){var data=this.input,ip=chunk.offset,instrumentZone=this.instrumentZone=[],size=chunk.offset+chunk.size;if(chunk.type!=='ibag')
+throw new Error('invalid chunk type:'+chunk.type);while(ip<size){instrumentZone.push({instrumentGeneratorIndex:data[ip++]|(data[ip++]<<8),instrumentModulatorIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parseImod=function(chunk){if(chunk.type!=='imod')
+throw new Error('invalid chunk type:'+chunk.type);this.instrumentZoneModulator=this.parseModulator(chunk)};sf2.Parser.prototype.parseIgen=function(chunk){if(chunk.type!=='igen')
+throw new Error('invalid chunk type:'+chunk.type);this.instrumentZoneGenerator=this.parseGenerator(chunk)};sf2.Parser.prototype.parseShdr=function(chunk){var data=this.input,ip=chunk.offset,samples=this.sample=[],sampleHeader=this.sampleHeader=[],size=chunk.offset+chunk.size,sampleName,start,end,startLoop,endLoop,sampleRate,originalPitch,pitchCorrection,sampleLink,sampleType;if(chunk.type!=='shdr')
+throw new Error('invalid chunk type:'+chunk.type);while(ip<size){sampleName=String.fromCharCode.apply(null,data.subarray(ip,ip+=20));start=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);end=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);startLoop=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);endLoop=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);sampleRate=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);originalPitch=data[ip++];pitchCorrection=(data[ip++]<<24)>>24;sampleLink=data[ip++]|(data[ip++]<<8);sampleType=data[ip++]|(data[ip++]<<8);var sample=new Int16Array(new Uint8Array(data.subarray(this.samplingData.offset+start*2,this.samplingData.offset+end*2)).buffer);startLoop-=start;endLoop-=start;if(sampleRate>0){var adjust=this.adjustSampleData(sample,sampleRate);sample=adjust.sample;sampleRate*=adjust.multiply;startLoop*=adjust.multiply;endLoop*=adjust.multiply}
+samples.push(sample);sampleHeader.push({sampleName:sampleName,startLoop:startLoop,endLoop:endLoop,sampleRate:sampleRate,originalPitch:originalPitch,pitchCorrection:pitchCorrection,sampleLink:sampleLink,sampleType:sampleType})}};sf2.Parser.prototype.adjustSampleData=function(sample,sampleRate){var newSample,i,il,j,multiply=1;while(sampleRate<22050){newSample=new Int16Array(sample.length*2);for(i=j=0,il=sample.length;i<il;++i){newSample[j++]=sample[i];newSample[j++]=sample[i]}
+sample=newSample;multiply*=2;sampleRate*=2}
+return{sample:sample,multiply:multiply}};sf2.Parser.prototype.parseModulator=function(chunk){var data=this.input,ip=chunk.offset,size=chunk.offset+chunk.size,code,key,output=[];while(ip<size){ip+=2;code=data[ip++]|(data[ip++]<<8);key=sf2.Parser.GeneratorEnumeratorTable[code];if(key===undefined){output.push({type:key,value:{code:code,amount:data[ip]|(data[ip+1]<<8)<<16>>16,lo:data[ip++],hi:data[ip++]}})}else{switch(key){case'keyRange':case'velRange':case'keynum':case'velocity':output.push({type:key,value:{lo:data[ip++],hi:data[ip++]}});break;default:output.push({type:key,value:{amount:data[ip++]|(data[ip++]<<8)<<16>>16}});break}}
+ip+=2;ip+=2}
+return output};sf2.Parser.prototype.parseGenerator=function(chunk){var data=this.input,ip=chunk.offset,size=chunk.offset+chunk.size,code,key,output=[];while(ip<size){code=data[ip++]|(data[ip++]<<8);key=sf2.Parser.GeneratorEnumeratorTable[code];if(key===undefined){output.push({type:key,value:{code:code,amount:data[ip]|(data[ip+1]<<8)<<16>>16,lo:data[ip++],hi:data[ip++]}});continue}
+switch(key){case'keynum':case'keyRange':case'velRange':case'velocity':output.push({type:key,value:{lo:data[ip++],hi:data[ip++]}});break;default:output.push({type:key,value:{amount:data[ip++]|(data[ip++]<<8)<<16>>16}});break}}
+return output};sf2.Parser.prototype.getPresets=function(){var preset=this.presetHeader,zone=this.presetZone,output=[],bagIndex,bagIndexEnd,zoneInfo,presetGenerator,presetModulator,i,il,j,jl
+for(i=0,il=preset.length;i<il;++i){j=preset[i].presetBagIndex
+jl=preset[i+1]?preset[i+1].presetBagIndex:zone.length
+zoneInfo=[];for(;j<jl;++j){presetGenerator=this.createPresetGenerator_(zone,j);presetModulator=this.createPresetModulator_(zone,j);zoneInfo.push({generator:presetGenerator.generator,modulator:presetModulator.modulator,})}
+output.push({info:zoneInfo,header:preset[i],})}
+return output};sf2.Parser.prototype.createInstrumentGenerator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].instrumentGeneratorIndex,zone[index+1]?zone[index+1].instrumentGeneratorIndex:this.instrumentZoneGenerator.length,this.instrumentZoneGenerator);return{generator:modgen.modgen,}};sf2.Parser.prototype.createInstrumentModulator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetModulatorIndex,zone[index+1]?zone[index+1].instrumentModulatorIndex:this.instrumentZoneModulator.length,this.instrumentZoneModulator);return{modulator:modgen.modgen}};sf2.Parser.prototype.createPresetGenerator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetGeneratorIndex,zone[index+1]?zone[index+1].presetGeneratorIndex:this.presetZoneGenerator.length,this.presetZoneGenerator);return{generator:modgen.modgen,}};sf2.Parser.prototype.createPresetModulator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetModulatorIndex,zone[index+1]?zone[index+1].presetModulatorIndex:this.presetZoneModulator.length,this.presetZoneModulator);return{modulator:modgen.modgen,}};sf2.Parser.prototype.createBagModGen_=function(zone,indexStart,indexEnd,zoneModGen){var modgen={unknown:[],'keyRange':{hi:127,lo:0}};var info,i,il;for(i=indexStart,il=indexEnd;i<il;++i){info=zoneModGen[i];if(info.type==='unknown')
+modgen.unknown.push(info.value);else
+modgen[info.type]=info.value}
+return{modgen:modgen}};sf2.Parser.GeneratorEnumeratorTable=['startAddrsOffset','endAddrsOffset','startloopAddrsOffset','endloopAddrsOffset','startAddrsCoarseOffset','modLfoToPitch','vibLfoToPitch','modEnvToPitch','initialFilterFc','initialFilterQ','modLfoToFilterFc','modEnvToFilterFc','endAddrsCoarseOffset','modLfoToVolume',undefined,'chorusEffectsSend','reverbEffectsSend','pan',undefined,undefined,undefined,'delayModLFO','freqModLFO','delayVibLFO','freqVibLFO','delayModEnv','attackModEnv','holdModEnv','decayModEnv','sustainModEnv','releaseModEnv','keynumToModEnvHold','keynumToModEnvDecay','delayVolEnv','attackVolEnv','holdVolEnv','decayVolEnv','sustainVolEnv','releaseVolEnv','keynumToVolEnvHold','keynumToVolEnvDecay','instrument',undefined,'keyRange','velRange','startloopAddrsCoarseOffset','keynum','velocity','initialAttenuation',undefined,'endloopAddrsCoarseOffset','coarseTune','fineTune','sampleID','sampleModes',undefined,'scaleTuning','exclusiveClass','overridingRootKey'];sf2.Riff={};sf2.Riff.Parser=function(input,options){options=options||{};this.input=input;this.ip=options.index||0;this.length=options.length||input.length-this.ip;this.offset=this.ip;this.padding=options.padding!==undefined?options.padding:true;this.bigEndian=options.bigEndian!==undefined?options.bigEndian:false};sf2.Riff.Chunk=function(type,size,offset){this.type=type;this.size=size;this.offset=offset};sf2.Riff.Parser.prototype.parse=function(){var length=this.length+this.offset;this.chunkList=[];while(this.ip<length)
+this.parseChunk()};sf2.Riff.Parser.prototype.parseChunk=function(){var input=this.input,ip=this.ip,size;this.chunkList.push(new sf2.Riff.Chunk(String.fromCharCode(input[ip++],input[ip++],input[ip++],input[ip++]),(size=this.bigEndian?((input[ip++]<<24)|(input[ip++]<<16)|(input[ip++]<<8)|(input[ip++])):((input[ip++])|(input[ip++]<<8)|(input[ip++]<<16)|(input[ip++]<<24))),ip));ip+=size;if(this.padding&&((ip-this.offset)&1)===1)
+ip++;this.ip=ip};sf2.Riff.Parser.prototype.getChunk=function(index){var chunk=this.chunkList[index];if(chunk===undefined)
+return null;return chunk};sf2.Riff.Parser.prototype.getNumberOfChunks=function(){return this.chunkList.length};return sf2}));function Midi5(i_conf){var conf=i_conf,onend=function(){},onnote=function(){},rf,op,v_i=[],bk=[],evt_idx,iend,stime,timouts=[]
+function note_run(e,t,d){var k=e[3]|0,i=e[2],c=e[6]&0x0f,a=(e[3]*100)%100
+if(bk[c]==128)
+c=9
+if(i!=v_i[c]){if(v_i[c]==undefined)
+op.send(new Uint8Array([0xb0+c,121,0]));v_i[c]=i
+op.send(new Uint8Array([0xc0+c,i&0x7f]))}
+if(a&&Midi5.ma.sysexEnabled){op.send(new Uint8Array([0xf0,0x7f,0x7f,0x08,0x02,i&0x7f,0x01,k,k,a/.78125,0,0xf7]),t)}
+op.send(new Uint8Array([0x90+c,k,127]),t);op.send(new Uint8Array([0x80+c,k,0]),t+d-20)}
+function play_next(a_e){var t,e,e2,maxt,st,d,c
+if(a_e)
+e=a_e[evt_idx]
+if(!op||evt_idx>=iend||!e){onend()
+return}
+if(conf.new_speed){stime=window-performance.now()-
+(window.performance.now()-stime)*conf.speed/conf.new_speed;conf.speed=conf.new_speed;conf.new_speed=0}
+timouts=[];t=e[1]/conf.speed*1000;maxt=t+3000
+while(1){d=e[4]/conf.speed*1000
+if(e[2]>=0){if(e[5]!=0)
+note_run(e,t+stime,d)
+st=t+stime-window.performance.now();timouts.push(setTimeout(onnote,st,e[0],true));setTimeout(onnote,st+d,e[0],false)}else{c=e[6]&0x0f
+op.send(new Uint8Array([0xb0+c,e[3],e[4]]),t+stime)
+if(bk[c]==undefined)
+bk[c]=0
+switch(e[3]){case 0:bk[c]=(bk[c]&0x7f)|(e[4]<<7)
+break
+case 32:bk[c]=(bk[c]&0x3f80)|e[4]
+break
+case 121:bk=[]
+break}}
+e=a_e[++evt_idx]
+if(!e||evt_idx>=iend){setTimeout(onend,t+stime-window.performance.now()+d)
+return}
+t=e[1]/conf.speed*1000
+if(t>maxt)
+break}
+timouts.push(setTimeout(play_next,(t+stime-window.performance.now())
+-300,a_e))}
+function send_outputs(access){var o,os,out=[];Midi5.ma=access;if(access&&access.outputs.size>0){os=access.outputs.values()
+while(1){o=os.next()
+if(!o||o.done)
+break
+out.push(o.value.name)}}
+rf(out)}
+return{get_outputs:function(f){if(!navigator.requestMIDIAccess){f()
+return}
+rf=f;navigator.requestMIDIAccess({sysex:true}).then(send_outputs,function(msg){navigator.requestMIDIAccess().then(send_outputs,function(msg){rf()})})},set_output:function(name){var o,os
+if(!Midi5.ma)
+return
+os=Midi5.ma.outputs.values()
+while(1){o=os.next()
+if(!o||o.done)
+break
+if(o.value.name==name){op=o.value
+break}}},play:function(istart,i_iend,a_e){if(!a_e||istart>=a_e.length){onend()
+return}
+if(conf.onend)
+onend=conf.onend
+if(conf.onnote)
+onnote=conf.onnote;iend=i_iend;evt_idx=istart;if(0){op.send(new Uint8Array([0xf0,0x7f,0x7f,0x08,0x02,0x00,0x01,0x69,0x69,0x00,0,0xf7]),t)}
+v_i=[];stime=window.performance.now()+200
+-a_e[evt_idx][1]*conf.speed*1000;play_next(a_e)},stop:function(){iend=0
+timouts.forEach(function(id){clearTimeout(id)})
+play_next()
+if(op&&op.clear)
+op.clear()}}}
+function follow(abc,user,playconf){var keep_types={note:true,rest:true}
+user.anno_stop=function(type,start,stop,x,y,w,h){if(!keep_types[type])
+return
+abc.out_svg('<rect class="abcr _'+start+'_" x="');abc.out_sxsy(x,'" y="',y);abc.out_svg('" width="'+w.toFixed(2)+'" height="'+abc.sh(h).toFixed(2)+'"/>\n')}
+playconf.onnote=function(i,on){var b,x,y,elts=document.getElementsByClassName('_'+i+'_')
+if(elts&&elts[0]){elts[0].style.fillOpacity=on?0.4:0
+if(on&&!window.no_scroll){b=elts[0].getBoundingClientRect()
+if(b.top<0)
+y=window.scrollY+b.top-
+window.innerHeight/2
+else if(b.bottom>window.innerHeight)
+y=window.scrollY+b.bottom+
+window.innerHeight/2
+if(b.left<0)
+x=window.scrollX+b.left-
+window.innerWidth/2
+else if(b.right>window.innerWidth)
+x=window.scrollX+b.right+
+window.innerWidth/2
+if(x!=undefined||y!=undefined)
+window.scrollTo(x||0,y||0)}}}}
+(function(){var sty=document.createElement("style")
+sty.innerHTML=".abcr {fill: #d00000; fill-opacity: 0; z-index: 15}"
+document.head.appendChild(sty)})()

+ 1292 - 0
dist/jianpu/snd-1.js

@@ -0,0 +1,1292 @@
+// abc2svg - ABC to SVG translator
+// @source: https://chiselapp.com/user/moinejf/repository/abc2svg
+// Copyright (C) 2014-2023 Jean-Francois Moine - LGPL3+
+//snd-1.js-file to include in html pages with abc2svg-1.js for playing
+function AbcPlay(i_conf) {
+    var conf = i_conf, init = {}, audio = ToAudio(), audio5, midi5, current, abcplay = {
+        clear: audio.clear, add: audio.add, set_sfu: function (v) {
+            if (v == undefined)
+                return conf.sfu
+            conf.sfu = v
+        }, set_speed: function (v) {
+            if (v == undefined)
+                return conf.speed
+            conf.new_speed = v
+        }, set_vol: function (v) {
+            if (v == undefined)
+                return conf.gain; conf.gain = v
+            if (current && current.set_vol)
+                current.set_vol(v)
+        }, play: play, stop: vf
+    }
+    function vf() { }
+    function play(istart, i_iend, a_e) {
+        init.istart = istart; init.i_iend = i_iend; init.a_e = a_e
+        if (midi5)
+            midi5.get_outputs(play2)
+        else
+            play2()
+    }
+    function play2(out) {
+        var o
+        if (!out)
+            out = []
+        o = audio5.get_outputs()
+        if (o)
+            Array.prototype.push.apply(out, o)
+        if (out.length == 0) {
+            if (conf.onend)
+                conf.onend()
+            return
+        }
+        if (out.length == 1) { o = 0 } else {
+            o = -1
+            var pr = "Use"
+            for (var i = 0; i < out.length; i++)
+                pr += "\n " + i + ": " + out[i]
+            var res = window.prompt(pr, '0')
+            if (res) {
+                o = Number(res)
+                if (isNaN(o) || o < 0 || o >= out.length)
+                    o = -1
+            }
+            if (!res || o < 0) {
+                if (conf.onend)
+                    conf.onend()
+                return
+            }
+        }
+        current = out[o] == 'sf2' ? audio5 : midi5; abcplay.play = current.play; abcplay.stop = current.stop
+        if (current.set_output)
+            current.set_output(out[o]); abcplay.play(init.istart, init.i_iend, init.a_e)
+    }
+    conf.gain = 0.7; conf.speed = 1; (function () {
+        var v
+        try {
+            if (!localStorage)
+                return
+        } catch (e) { return }
+        if (!conf.sfu) {
+            v = localStorage.getItem("sfu")
+            if (v)
+                conf.sfu = v
+        }
+        v = localStorage.getItem("volume")
+        if (v)
+            conf.gain = Number(v)
+    })()
+    if (typeof Midi5 == "function")
+        midi5 = Midi5(conf)
+    if (typeof Audio5 == "function")
+        audio5 = Audio5(conf); return abcplay
+}
+if (typeof module == 'object' && typeof exports == 'object')
+    exports.AbcPlay = AbcPlay
+if (!abc2svg)
+    var abc2svg = {}
+function ToAudio() {
+    return {
+        add: function (first, voice_tb, cfmt) {
+            var toaud = this, C = abc2svg.C, p_time = 0, abc_time = 0, play_fac = C.BLEN / 4 * 120 / 60, i, n, dt, d, v, s = first, rst = s, rst_fac, rsk = [], b_tim, b_typ
+            function get_beat() {
+                var s = first.p_v.meter
+                if (!s.a_meter[0])
+                    return C.BLEN / 4
+                if (!s.a_meter[0].bot)
+                    return (s.a_meter[1] && s.a_meter[1].top == '|') ? C.BLEN / 2 : C.BLEN / 4
+                if (s.a_meter[0].bot == "8" && s.a_meter[0].top % 3 == 0)
+                    return C.BLEN / 8 * 3
+                return C.BLEN / s.a_meter[0].bot | 0
+            }
+            function def_beats() {
+                var i, s2, s3, tim, last_d, beat = get_beat(), d = first.p_v.meter.wmeasure, nb = d / beat | 0, v = voice_tb.length, p_v = { id: "_beats", v: v, sym: { type: C.BLOCK, v: v, subtype: "midiprog", chn: 9, instr: 16384, ts_prev: first } }, s = { type: C.NOTE, v: v, p_v: p_v, dur: beat, nhd: 0, notes: [{ midi: 37 }] }
+                for (s2 = first; s2; s2 = s2.ts_next) {
+                    if (s2.bar_type && s2.time) {
+                        nb = (2 * d - s2.time) / beat | 0
+                        last_d = beat - s2.time
+                        break
+                    }
+                }
+                s2 = p_v.sym
+                for (s3 = first; s3 && !s3.time; s3 = s3.ts_next) {
+                    if (s3.type == C.TEMPO) {
+                        s3 = Object.create(s3)
+                        s3.v = v
+                        s3.p_v = p_v
+                        s3.prev = s3.ts_prev = s2
+                        s2.next = s2.ts_next = s3
+                        s2 = s3
+                        play_fac = set_tempo(s2)
+                        break
+                    }
+                }
+                voice_tb[v] = p_v
+                p_v.sym.p_v = p_v
+                tim = abc_time = -d
+                first.time = s2.time = tim
+                if (s3)
+                    p_v.sym.time = tim
+                for (i = 0; i < nb; i++) {
+                    s3 = Object.create(s)
+                    s3.time = tim
+                    s3.prev = s2
+                    s2.next = s3
+                    s3.ts_prev = s2
+                    s2.ts_next = s3
+                    s2 = s3
+                    if (last_d && i == nb - 1) { s3.dur = s3.dur_orig = s3.notes[0].dur = last_d }
+                    tim += beat
+                }
+                s2.ts_next = first.ts_next
+                s2.ts_next.ts_prev = s2
+                first.ts_next = p_v.sym
+            }
+            function build_parts(first) {
+                var i, j, c, n, v, s = first, p = s.parts, st = [], r = ""
+                for (i = 0; i < p.length; i++) {
+                    c = p[i]
+                    switch (c) {
+                        case '.': continue
+                        case '(': st.push(r.length)
+                            continue
+                        case ')': j = st.pop()
+                            if (j == undefined)
+                                j = r.length
+                            continue
+                    }
+                    if (c >= 'A' && c <= 'Z') {
+                        j = r.length
+                        r += c
+                        continue
+                    }
+                    n = Number(c)
+                    if (isNaN(n))
+                        break
+                    v = r.slice(j)
+                    if (r.length + v.length * n > 128)
+                        continue
+                    while (--n > 0)
+                        r += v
+                }
+                s.parts = r
+                s.p_s = []
+                while (1) {
+                    if (!s.ts_next) {
+                        s.part1 = first
+                        break
+                    }
+                    s = s.ts_next
+                    if (s.part) {
+                        s.part1 = first
+                        v = s.part.text[0]
+                        for (i = 0; i < first.parts.length; i++) {
+                            if (first.parts[i] == v)
+                                first.p_s[i] = s
+                        }
+                    }
+                }
+            }
+            function gen_grace(s) {
+                var g, i, n, t, d, s2, next = s.next
+                if (s.sappo) { d = C.BLEN / 16 } else if ((!next || next.type != C.NOTE) && s.prev && s.prev.type == C.NOTE) { d = s.prev.dur / 2 } else {
+                    d = next.dur / 12
+                    if (!(d & (d - 1)))
+                        d = next.dur / 2
+                    else
+                        d = next.dur / 3
+                    if (s.p_v.key.k_bagpipe)
+                        d /= 2
+                    next.time += d
+                    next.dur -= d
+                }
+                n = 0
+                for (g = s.extra; g; g = g.next)
+                    n++
+                d /= n * play_fac
+                t = p_time
+                for (g = s.extra; g; g = g.next) {
+                    g.ptim = t
+                    g.pdur = d
+                    t += d
+                }
+            }
+            function set_tempo(s) {
+                var i, d = 0, n = s.tempo_notes.length
+                for (i = 0; i < n; i++)
+                    d += s.tempo_notes[i]
+                return d * s.tempo / 60
+            }
+            function set_variant(s) {
+                var d, n = s.text.match(/[1-8]-[2-9]|[1-9,.]|[^\s]+$/g)
+                while (1) {
+                    d = n.shift()
+                    if (!d)
+                        break
+                    if (d[1] == '-')
+                        for (i = d[0]; i <= d[2]; i++)
+                            rsk[i] = s
+                    else if (d >= '1' && d <= '9')
+                        rsk[Number(d)] = s
+                    else if (d != ',')
+                        rsk.push(s)
+                }
+            }
+            if (cfmt.chord)
+                abc2svg.chord(first, voice_tb, cfmt)
+            if (cfmt.playbeats)
+                def_beats()
+            if (s.parts)
+                build_parts(s)
+            rst_fac = play_fac
+            while (s) {
+                if (s.noplay) {
+                    s = s.ts_next
+                    continue
+                }
+                dt = s.time - abc_time
+                if (dt != 0) {
+                    p_time += dt / play_fac
+                    abc_time = s.time
+                }
+                s.ptim = p_time
+                if (s.part) {
+                    rst = s
+                    rst_fac = play_fac
+                }
+                switch (s.type) {
+                    case C.BAR: if (s.time != b_tim) {
+                        b_tim = s.time
+                        b_typ = 0
+                    }
+                        if (s.text && rsk.length > 1 && s.text[0] != '1') {
+                            if (b_typ & 1)
+                                break
+                            b_typ |= 1
+                            set_variant(s)
+                            play_fac = rst_fac
+                            rst = rsk[0]
+                        }
+                        if (s.bar_type[0] == ':') {
+                            if (b_typ & 2)
+                                break
+                            b_typ |= 2
+                            s.rep_p = rst
+                            if (rst == rsk[0])
+                                s.rep_v = rsk
+                        }
+                        if (s.text) {
+                            if (s.text[0] == '1') {
+                                if (b_typ & 1)
+                                    break
+                                b_typ |= 1
+                                s.rep_s = rsk = [rst]
+                                if (rst.bar_type && rst.bar_type.slice(-1) != ':')
+                                    rst.bar_type += ':'
+                                set_variant(s)
+                                rst_fac = play_fac
+                            }
+                        } else if (s.bar_type.slice(-1) == ':') {
+                            if (b_typ & 4)
+                                break
+                            b_typ |= 4
+                            rst = s
+                            rst_fac = play_fac
+                        } else if (s.rbstop == 2) {
+                            if (b_typ & 8)
+                                break
+                            b_typ |= 8
+                            rst = s
+                            rst_fac = play_fac
+                        }
+                        break
+                    case C.GRACE: if (s.time == 0 && abc_time == 0) {
+                        dt = 0
+                        if (s.sappo)
+                            dt = C.BLEN / 16
+                        else if (!s.next || s.next.type != C.NOTE)
+                            dt = d / 2
+                        abc_time -= dt
+                    }
+                        gen_grace(s)
+                        break
+                    case C.REST: case C.NOTE: d = s.dur
+                        if (s.next && s.next.type == C.GRACE) {
+                            dt = 0
+                            if (s.next.sappo)
+                                dt = C.BLEN / 16
+                            else if (!s.next.next || s.next.next.type != C.NOTE)
+                                dt = d / 2
+                            s.next.time -= dt
+                            d -= dt
+                        }
+                        d /= play_fac
+                        s.pdur = d
+                        v = s.v
+                        break
+                    case C.TEMPO: if (s.tempo)
+                        play_fac = set_tempo(s)
+                        break
+                }
+                s = s.ts_next
+            }
+        }
+    }
+}
+abc2svg.play_next = function (po) {
+    function do_tie(not_s, d) {
+        var i, s = not_s.s, C = abc2svg.C, v = s.v, end_time = s.time + s.dur, repv = po.repv
+        while (1) {
+            s = s.ts_next
+            if (!s || s.time > end_time)
+                break
+            if (s.type == C.BAR) {
+                if (s.rep_p) {
+                    if (!po.repn) {
+                        s = s.rep_p
+                        end_time = s.time
+                    }
+                }
+                if (s.rep_s) {
+                    if (!s.rep_s[repv])
+                        break
+                    s = s.rep_s[repv++]
+                    end_time = s.time
+                }
+                while (s.ts_next && !s.ts_next.dur)
+                    s = s.ts_next
+                continue
+            }
+            if (s.time < end_time || !s.ti2)
+                continue
+            i = s.notes.length
+            while (--i >= 0) {
+                note = s.notes[i]
+                if (note.tie_s == not_s) {
+                    d += s.pdur / po.conf.speed
+                    return note.tie_e ? do_tie(note, d) : d
+                }
+            }
+        }
+        return d
+    }
+    function set_ctrl(po, s2, t) {
+        var i, p_v = s2.p_v, s = { subtype: "midictl", p_v: p_v, v: s2.v }
+        for (i in p_v.midictl) {
+            s.ctrl = Number(i)
+            s.val = p_v.midictl[i]
+            po.midi_ctrl(po, s, t)
+        }
+        for (s = p_v.sym; s != s2; s = s.next) {
+            if (s.subtype == "midictl")
+                po.midi_ctrl(po, s, t)
+            else if (s.subtype == 'midiprog')
+                po.midi_prog(po, s)
+        }
+        i = po.v_c[s2.v]
+        if (i == undefined)
+            po.v_c[s2.v] = i = s2.v < 9 ? s2.v : s2.v + 1
+        if (po.c_i[i] == undefined)
+            po.c_i[i] = 0
+        po.p_v[s2.v] = true
+    }
+    function play_cont(po) {
+        var d, i, st, m, note, g, s2, t, maxt, now, C = abc2svg.C, s = po.s_cur
+        function var_end(s) {
+            var i, s2, s3, a = s.rep_v || s.rep_s
+            ti = 0
+            for (i = 1; i < a.length; i++) {
+                s2 = a[i]
+                if (s2.time > ti) {
+                    ti = s2.time
+                    s3 = s2
+                }
+            }
+            for (s = s3; s != po.s_end; s = s.ts_next) {
+                if (s.time == ti)
+                    continue
+                if (s.rbstop == 2)
+                    break
+            }
+            po.repv = 1
+            return s
+        }
+        if (po.stop) {
+            if (po.onend)
+                po.onend(po.repv)
+            return
+        }
+        while (s.noplay) {
+            s = s.ts_next
+            if (!s || s == po.s_end) {
+                if (po.onend)
+                    po.onend(po.repv)
+                return
+            }
+        }
+        t = po.stim + s.ptim / po.conf.speed
+        now = po.get_time(po)
+        if (po.conf.new_speed) {
+            po.stim = now - (now - po.stim) * po.conf.speed / po.conf.new_speed
+            po.conf.speed = po.conf.new_speed
+            po.conf.new_speed = 0
+            t = po.stim + s.ptim / po.conf.speed
+        }
+        maxt = t + po.tgen
+        po.timouts = []
+        while (1) {
+            if (!po.p_v[s.v])
+                set_ctrl(po, s, t)
+            switch (s.type) {
+                case C.BAR: s2 = null
+                    if (s.rep_p) {
+                        po.repv++
+                        if (!po.repn && (!s.rep_v || po.repv <= s.rep_v.length)) {
+                            s2 = s.rep_p
+                            po.repn = true
+                        } else {
+                            if (s.rep_v)
+                                s2 = var_end(s)
+                            po.repn = false
+                        }
+                    }
+                    if (s.rep_s) {
+                        s2 = s.rep_s[po.repv]
+                        if (s2) {
+                            po.repn = false
+                            if (s2 == s)
+                                s2 = null
+                        } else {
+                            s2 = var_end(s)
+                            if (s2 == po.s_end)
+                                break
+                        }
+                    }
+                    if (s.bar_type.slice(-1) == ':' && s.bar_type[0] != ':')
+                        po.repv = 1
+                    if (s2) {
+                        po.stim += (s.ptim - s2.ptim) / po.conf.speed
+                        s = s2
+                        while (s && !s.dur)
+                            s = s.ts_next
+                        if (!s)
+                            break
+                        t = po.stim + s.ptim / po.conf.speed
+                        break
+                    }
+                    if (!s.part1) {
+                        while (s.ts_next && !s.ts_next.seqst) {
+                            s = s.ts_next
+                            if (s.part1)
+                                break
+                        }
+                        if (!s.part1)
+                            break
+                    }
+                default: if (s.part1 && po.i_p != undefined) {
+                    s2 = s.part1.p_s[++po.i_p]
+                    if (s2) {
+                        po.stim += (s.ptim - s2.ptim) / po.conf.speed
+                        s = s2
+                        t = po.stim + s.ptim / po.conf.speed
+                    } else { s = po.s_end }
+                    po.repv = 1
+                }
+                    break
+            }
+            if (s && s != po.s_end) {
+                switch (s.type) {
+                    case C.BAR: break
+                    case C.BLOCK: if (s.subtype == "midictl")
+                        po.midi_ctrl(po, s, t)
+                    else if (s.subtype == 'midiprog')
+                        po.midi_prog(po, s)
+                        break
+                    case C.GRACE: for (g = s.extra; g; g = g.next) {
+                        d = g.pdur / po.conf.speed
+                        for (m = 0; m <= g.nhd; m++) {
+                            note = g.notes[m]
+                            if (!note.noplay)
+                                po.note_run(po, g, note.midi, t + g.ptim - s.ptim, d)
+                        }
+                    }
+                        break
+                    case C.NOTE: case C.REST: d = s.pdur / po.conf.speed
+                        if (s.type == C.NOTE) {
+                            for (m = 0; m <= s.nhd; m++) {
+                                note = s.notes[m]
+                                if (note.tie_s || note.noplay)
+                                    continue
+                                po.note_run(po, s, note.midi, t, note.tie_e ? do_tie(note, d) : d)
+                            }
+                        }
+                        if (po.onnote && s.istart) {
+                            i = s.istart
+                            st = (t - now) * 1000
+                            po.timouts.push(setTimeout(po.onnote, st, i, true))
+                            if (d > 2)
+                                d -= .1
+                            setTimeout(po.onnote, st + d * 1000, i, false)
+                        }
+                        break
+                }
+            }
+            while (1) {
+                if (!s || s == po.s_end || !s.ts_next) {
+                    if (po.onend)
+                        setTimeout(po.onend, (t - now + d) * 1000, po.repv)
+                    po.s_cur = s
+                    return
+                }
+                s = s.ts_next
+                if (!s.noplay)
+                    break
+            }
+            t = po.stim + s.ptim / po.conf.speed
+            if (t > maxt)
+                break
+        }
+        po.s_cur = s
+        po.timouts.push(setTimeout(play_cont, (t - now) * 1000
+            - 300, po))
+    }
+    function get_part(po) {
+        var s, i, s_p
+        for (s = po.s_cur; s; s = s.ts_prev) {
+            if (s.parts) {
+                po.i_p = -1
+                return
+            }
+            s_p = s.part1
+            if (!s_p || !s_p.p_s)
+                continue
+            for (i = 0; i < s_p.p_s.length; i++) {
+                if (s_p.p_s[i] == s) {
+                    po.i_p = i
+                    return
+                }
+            }
+        }
+    }
+    get_part(po)
+    po.stim = po.get_time(po) + .3
+        - po.s_cur.ptim * po.conf.speed
+    po.p_v = []
+    if (!po.repv)
+        po.repv = 1
+    play_cont(po)
+}
+if (typeof module == 'object' && typeof exports == 'object')
+    exports.ToAudio = ToAudio
+var abcsf2 = []
+function Audio5(i_conf) {
+    var po, conf = i_conf, empty = function () { }, errmsg, ac, gain, model, parser, presets, instr = [], params = [], rates = [], w_instr = 0
+    var b64d = []
+    function init_b64d() {
+        var b64l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', l = b64l.length
+        for (var i = 0; i < l; i++)
+            b64d[b64l[i]] = i
+        b64d['='] = 0
+    }
+    function b64dcod(s) {
+        var i, t, dl, a, l = s.length, j = 0
+        dl = l * 3 / 4
+        if (s[l - 1] == '=') {
+            if (s[l - 2] == '=')
+                dl--
+            dl--
+            l -= 4
+        }
+        a = new Uint8Array(dl)
+        for (i = 0; i < l; i += 4) {
+            t = (b64d[s[i]] << 18) +
+            (b64d[s[i + 1]] << 12) +
+            (b64d[s[i + 2]] << 6) +
+            b64d[s[i + 3]]
+            a[j++] = (t >> 16) & 0xff
+            a[j++] = (t >> 8) & 0xff
+            a[j++] = t & 0xff
+        }
+        if (l != s.length) {
+            t = (b64d[s[i]] << 18) +
+            (b64d[s[i + 1]] << 12) +
+            (b64d[s[i + 2]] << 6) +
+            b64d[s[i + 3]]
+            a[j++] = (t >> 16) & 0xff
+            if (j < dl)
+                a[j++] = (t >> 8) & 0xff
+        }
+        return a
+    }
+    function sample_cp(b, s) {
+        var i, n, a = b.getChannelData(0)
+        for (i = 0; i < s.length; i++)
+            a[i] = s[i] / 196608
+    }
+    function sf2_create(instr, sf2par, sf2pre) {
+        function get_instr(i) {
+            var instrument = sf2par.instrument, zone = sf2par.instrumentZone, j = instrument[i].instrumentBagIndex, jl = instrument[i + 1] ? instrument[i + 1].instrumentBagIndex : zone.length, info = []
+            while (j < jl) {
+                instrumentGenerator = sf2par.createInstrumentGenerator_(zone, j)
+                info.push({ generator: instrumentGenerator.generator, })
+                j++
+            }
+            return { info: info }
+        }
+        var i, j, k, sid, gen, parm, gparm, sample, infos, sampleRate, scale, b = instr >> 7, p = instr % 128, pr = sf2pre
+        rates[instr] = []
+        for (i = 0; i < pr.length; i++) {
+            gen = pr[i].header
+            if (gen.preset == p && gen.bank == b)
+                break
+        }
+        pr = pr[i]
+        if (!pr) {
+            errmsg('unknown instrument ' + b + ':' + p)
+            return
+        }
+        pr = pr.info
+        for (k = 0; k < pr.length; k++) {
+            if (!pr[k].generator.instrument)
+                continue
+            gparm = null
+            infos = get_instr(pr[k].generator.instrument.amount).info
+            for (i = 0; i < infos.length; i++) {
+                gen = infos[i].generator
+                if (!gparm) { parm = gparm = { attack: .001, hold: .001, decay: .001, sustain: 0 } } else {
+                    parm = Object.create(gparm)
+                    if (!gen.sampleID)
+                        gparm = parm
+                }
+                if (gen.attackVolEnv)
+                    parm.attack = Math.pow(2, gen.attackVolEnv.amount / 1200)
+                if (gen.holdVolEnv)
+                    parm.hold = Math.pow(2, gen.holdVolEnv.amount / 1200)
+                if (gen.decayVolEnv)
+                    parm.decay = Math.pow(2, gen.decayVolEnv.amount / 1200) / 3
+                if (gen.sustainVolEnv)
+                    parm.sustain = gen.sustainVolEnv.amount / 1000
+                if (gen.sampleModes && gen.sampleModes.amount & 1)
+                    parm.sm = 1
+                if (!gen.sampleID)
+                    continue
+                sid = gen.sampleID.amount
+                sampleRate = sf2par.sampleHeader[sid].sampleRate
+                sample = sf2par.sample[sid]
+                parm.buffer = ac.createBuffer(1, sample.length, sampleRate)
+                parm.hold += parm.attack
+                parm.decay += parm.hold
+                if (parm.sustain >= .4)
+                    parm.sustain = 0.01
+                else
+                    parm.sustain = 1 - parm.sustain / .4
+                sample_cp(parm.buffer, sample)
+                if (parm.sm) {
+                    parm.loopStart = sf2par.sampleHeader[sid].startLoop / sampleRate
+                    parm.loopEnd = sf2par.sampleHeader[sid].endLoop / sampleRate
+                }
+                scale = (gen.scaleTuning ? gen.scaleTuning.amount : 100) / 100, tune = (gen.coarseTune ? gen.coarseTune.amount : 0) +
+                    (gen.fineTune ? gen.fineTune.amount : 0) / 100 +
+                    sf2par.sampleHeader[sid].pitchCorrection / 100 -
+                    (gen.overridingRootKey ? gen.overridingRootKey.amount : sf2par.sampleHeader[sid].originalPitch)
+                for (j = gen.keyRange.lo; j <= gen.keyRange.hi; j++) {
+                    rates[instr][j] = Math.pow(Math.pow(2, 1 / 12), (j + tune) * scale)
+                    params[instr][j] = parm
+                }
+            }
+        }
+    }
+    function load_instr(instr) {
+        w_instr++
+        abc2svg.loadjs(conf.sfu + '/' + instr + '.js', function () {
+            var sf2par = new sf2.Parser(b64dcod(abcsf2[instr]))
+            sf2par.parse()
+            var sf2pre = sf2par.getPresets()
+            sf2_create(instr, sf2par, sf2pre)
+            if (--w_instr == 0)
+                play_start()
+        }, function () {
+            errmsg('could not find the instrument ' +
+                ((instr / 128) | 0).toString() + '-' +
+                (instr % 128).toString())
+            if (--w_instr == 0)
+                play_start()
+        })
+    }
+    function def_instr(s, f, sf2par, sf2pre) {
+        var i, bk = [], nv = -1, vb = 0
+        s = s.p_v.sym
+        while (s.ts_prev)
+            s = s.ts_prev
+        for (; s; s = s.ts_next) {
+            if (s.v > nv) {
+                nv = s.v
+                bk[nv] = 0
+                if (s.p_v.midictl) {
+                    if (s.p_v.midictl[0])
+                        bk[s.v] = (bk[s.v] & ~0x1fc000)
+                            + (s.p_v.midictl[0] << 14)
+                    if (s.p_v.midictl[32])
+                        bk[s.v] = (bk[s.v] & ~0x3f80)
+                            + (s.p_v.midictl[32] << 7)
+                }
+            }
+            switch (s.subtype) {
+                case "midiprog": break
+                case "midictl": if (s.ctrl != 0 && s.ctrl != 32)
+                    continue
+                    if (bk[s.v] == undefined)
+                        bk[s.v] = 0
+                    if (s.ctrl == 0)
+                        bk[s.v] = (bk[s.v] & ~0x1fc000)
+                            + (s.val << 14)
+                    else
+                        bk[s.v] = (bk[s.v] & ~0x3f80)
+                            + (s.val << 7)
+                default: continue
+            }
+            vb |= 1 << s.v
+            i = s.instr
+            if (i == undefined) {
+                if (s.chn != 9)
+                    continue
+                i = bk[s.v] ? 0 : 128 * 128
+            }
+            if (bk[s.v])
+                i += bk[s.v]
+            if (!params[i]) {
+                params[i] = []
+                f(i, sf2par, sf2pre)
+            }
+        }
+        nv = (2 << nv) - 1
+        if (nv != vb && !params[0]) {
+            params[0] = []
+            f(0, sf2par, sf2pre)
+        }
+    }
+    function load_res(s) {
+        if (abc2svg.sf2 || conf.sfu.slice(-4) == ".sf2" || conf.sfu.slice(-3) == ".js") {
+            if (abc2svg.sf2) {
+                if (!parser) {
+                    parser = new sf2.Parser(b64dcod(abc2svg.sf2))
+                    parser.parse()
+                    presets = parser.getPresets()
+                }
+            } else if (!parser) {
+                w_instr++
+                if (conf.sfu.slice(-3) == ".js") {
+                    abc2svg.loadjs(conf.sfu, function () {
+                        load_res(s)
+                        if (--w_instr == 0)
+                            play_start()
+                    }, function () {
+                        errmsg('could not load the sound file '
+                            + conf.sfu)
+                        if (--w_instr == 0)
+                            play_start()
+                    })
+                    return
+                }
+                var r = new XMLHttpRequest()
+                r.open('GET', conf.sfu, true)
+                r.responseType = "arraybuffer"
+                r.onload = function () {
+                    if (r.status === 200) {
+                        parser = new sf2.Parser(new Uint8Array(r.response))
+                        parser.parse()
+                        presets = parser.getPresets()
+                        load_res(s)
+                        if (--w_instr == 0)
+                            play_start()
+                    } else {
+                        errmsg('could not load the sound file '
+                            + conf.sfu)
+                        if (--w_instr == 0)
+                            play_start()
+                    }
+                }
+                r.onerror = function () {
+                    errmsg('could not load the sound file '
+                        + conf.sfu)
+                    if (--w_instr == 0)
+                        play_start()
+                }
+                r.send()
+                return
+            }
+            def_instr(s, sf2_create, parser, presets)
+        } else { def_instr(s, load_instr) }
+    }
+    function get_time(po) { return po.ac.currentTime }
+    function midi_ctrl(po, s, t) {
+        switch (s.ctrl) {
+            case 0: if (po.v_b[s.v] == undefined)
+                po.v_b[s.v] = 0
+                po.v_b[s.v] = (po.v_b[s.v] & ~0x1fc000)
+                    + (s.val << 14)
+                break
+            case 7: s.p_v.vol = s.val / 127
+                break
+            case 32: if (po.v_b[s.v] == undefined)
+                po.v_b[s.v] = 0
+                po.v_b[s.v] = (po.v_b[s.v] & ~0x3f80)
+                    + (s.val << 7)
+                break
+        }
+    }
+    function midi_prog(po, s) {
+        var i = s.instr
+        po.v_c[s.v] = s.chn
+        if (i == undefined) {
+            if (s.chn != 9)
+                return
+            i = po.v_b[s.v] ? 0 : 128 * 128
+        }
+        if (po.v_b[s.v])
+            i += po.v_b[s.v]
+        po.c_i[s.chn] = i
+    }
+    function note_run(po, s, key, t, d) {
+        var g, st, c = po.v_c[s.v], instr = po.c_i[c], k = key | 0, parm = params[instr][k], o = po.ac.createBufferSource(), v = s.p_v.vol == undefined ? 1 : s.p_v.vol
+        if (!v || !parm)
+            return
+        o.buffer = parm.buffer
+        if (parm.loopStart) {
+            o.loop = true
+            o.loopStart = parm.loopStart
+            o.loopEnd = parm.loopEnd
+        }
+        if (o.detune) {
+            var dt = (key * 100) % 100
+            if (dt)
+                o.detune.value = dt
+        }
+        o.playbackRate.value = po.rates[instr][k]
+        g = po.ac.createGain()
+        if (parm.hold < 0.002) { g.gain.setValueAtTime(v, t) } else {
+            if (parm.attack < 0.002) { g.gain.setValueAtTime(v, t) } else {
+                g.gain.setValueAtTime(0, t)
+                g.gain.linearRampToValueAtTime(v, t + parm.attack)
+            }
+            g.gain.setValueAtTime(v, t + parm.hold)
+        }
+        g.gain.exponentialRampToValueAtTime(parm.sustain * v, t + parm.decay)
+        o.connect(g)
+        g.connect(po.gain)
+        o.start(t)
+        o.stop(t + d)
+    }
+    function play_start() {
+        if (po.stop) {
+            po.onend(repv)
+            return
+        }
+        gain.connect(ac.destination)
+        abc2svg.play_next(po)
+    }
+    init_b64d()
+    if (!conf.sfu)
+        conf.sfu = "Scc1t2"
+    if (navigator.userAgentData && navigator.userAgentData.getHighEntropyValues)
+        navigator.userAgentData.getHighEntropyValues(['model']).then(function (ua) { model = ua.model })
+    else
+        model = navigator.userAgent
+    return {
+        get_outputs: function () { return (window.AudioContext || window.webkitAudioContext) ? ['sf2'] : null }, play: function (i_start, i_end, i_lvl) {
+            errmsg = conf.errmsg || alert
+            function play_unlock() {
+                var buf = ac.createBuffer(1, 1, 22050), src = ac.createBufferSource()
+                src.buffer = buf
+                src.connect(ac.destination)
+                src.start(0)
+            }
+            if (!gain) {
+                ac = conf.ac
+                if (!ac) {
+                    conf.ac = ac = new (window.AudioContext || window.webkitAudioContext)
+                    if (/iPad|iPhone|iPod/.test(model))
+                        play_unlock()
+                }
+                gain = ac.createGain()
+                gain.gain.value = conf.gain
+            }
+            while (i_start.noplay)
+                i_start = i_start.ts_next
+            po = { conf: conf, onend: conf.onend || empty, onnote: conf.onnote || empty, s_end: i_end, s_cur: i_start, repv: i_lvl || 0, tgen: 2, get_time: get_time, midi_ctrl: midi_ctrl, midi_prog: midi_prog, note_run: note_run, timouts: [], v_c: [], c_i: [], v_b: [], ac: ac, gain: gain, rates: rates }
+            w_instr++
+            load_res(i_start)
+            if (--w_instr == 0)
+                play_start()
+        }, stop: function () {
+            po.stop = true
+            po.timouts.forEach(function (id) { clearTimeout(id) })
+            abc2svg.play_next(po)
+            if (gain) {
+                gain.disconnect()
+                gain = null
+            }
+        }, set_vol: function (v) {
+            if (gain)
+                gain.gain.value = v
+        }
+    }
+}
+(function (root, factory) { if (typeof exports === "object") { root.sf2 = exports; factory(exports) } else if (typeof define === "function" && define.amd) { define(["exports"], function (exports) { root.sf2 = exports; return (root.sf2, factory(exports)) }) } else { root.sf2 = {}; factory(root.sf2) } }(this, function (sf2) {
+    "use strict"; sf2.Parser = function (input, options) { options = options || {}; this.input = input; this.parserOptions = options.parserOptions }; sf2.Parser.prototype.parse = function () {
+        var parser = new sf2.Riff.Parser(this.input, this.parserOptions), chunk; parser.parse(); if (parser.chunkList.length !== 1)
+            throw new Error('wrong chunk length'); chunk = parser.getChunk(0); if (chunk === null)
+            throw new Error('chunk not found'); this.parseRiffChunk(chunk); this.input = null
+    }; sf2.Parser.prototype.parseRiffChunk = function (chunk) {
+        var parser, data = this.input, ip = chunk.offset, signature; if (chunk.type !== 'RIFF')
+            throw new Error('invalid chunk type:' + chunk.type); signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]); if (signature !== 'sfbk')
+            throw new Error('invalid signature:' + signature); parser = new sf2.Riff.Parser(data, { 'index': ip, 'length': chunk.size - 4 }); parser.parse(); if (parser.getNumberOfChunks() !== 3)
+            throw new Error('invalid sfbk structure'); this.parseInfoList(parser.getChunk(0)); this.parseSdtaList(parser.getChunk(1)); this.parsePdtaList(parser.getChunk(2))
+    }; sf2.Parser.prototype.parseInfoList = function (chunk) {
+        var parser, data = this.input, ip = chunk.offset, signature; if (chunk.type !== 'LIST')
+            throw new Error('invalid chunk type:' + chunk.type); signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]); if (signature !== 'INFO')
+            throw new Error('invalid signature:' + signature); parser = new sf2.Riff.Parser(data, { 'index': ip, 'length': chunk.size - 4 }); parser.parse()
+    }; sf2.Parser.prototype.parseSdtaList = function (chunk) {
+        var parser, data = this.input, ip = chunk.offset, signature; if (chunk.type !== 'LIST')
+            throw new Error('invalid chunk type:' + chunk.type); signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]); if (signature !== 'sdta')
+            throw new Error('invalid signature:' + signature); parser = new sf2.Riff.Parser(data, { 'index': ip, 'length': chunk.size - 4 }); parser.parse(); if (parser.chunkList.length !== 1)
+            throw new Error('TODO'); this.samplingData = parser.getChunk(0)
+    }; sf2.Parser.prototype.parsePdtaList = function (chunk) {
+        var parser, data = this.input, ip = chunk.offset, signature; if (chunk.type !== 'LIST')
+            throw new Error('invalid chunk type:' + chunk.type); signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]); if (signature !== 'pdta')
+            throw new Error('invalid signature:' + signature); parser = new sf2.Riff.Parser(data, { 'index': ip, 'length': chunk.size - 4 }); parser.parse(); if (parser.getNumberOfChunks() !== 9)
+            throw new Error('invalid pdta chunk'); this.parsePhdr((parser.getChunk(0))); this.parsePbag((parser.getChunk(1))); this.parsePmod((parser.getChunk(2))); this.parsePgen((parser.getChunk(3))); this.parseInst((parser.getChunk(4))); this.parseIbag((parser.getChunk(5))); this.parseImod((parser.getChunk(6))); this.parseIgen((parser.getChunk(7))); this.parseShdr((parser.getChunk(8)))
+    }; sf2.Parser.prototype.parsePhdr = function (chunk) {
+        var data = this.input, ip = chunk.offset, presetHeader = this.presetHeader = [], size = chunk.offset + chunk.size; if (chunk.type !== 'phdr')
+            throw new Error('invalid chunk type:' + chunk.type); while (ip < size) { presetHeader.push({ presetName: String.fromCharCode.apply(null, data.subarray(ip, ip += 20)), preset: data[ip++] | (data[ip++] << 8), bank: data[ip++] | (data[ip++] << 8), presetBagIndex: data[ip++] | (data[ip++] << 8), library: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0, genre: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0, morphology: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0 }) }
+    }; sf2.Parser.prototype.parsePbag = function (chunk) {
+        var data = this.input, ip = chunk.offset, presetZone = this.presetZone = [], size = chunk.offset + chunk.size; if (chunk.type !== 'pbag')
+            throw new Error('invalid chunk type:' + chunk.type); while (ip < size) { presetZone.push({ presetGeneratorIndex: data[ip++] | (data[ip++] << 8), presetModulatorIndex: data[ip++] | (data[ip++] << 8) }) }
+    }; sf2.Parser.prototype.parsePmod = function (chunk) {
+        if (chunk.type !== 'pmod')
+            throw new Error('invalid chunk type:' + chunk.type); this.presetZoneModulator = this.parseModulator(chunk)
+    }; sf2.Parser.prototype.parsePgen = function (chunk) {
+        if (chunk.type !== 'pgen')
+            throw new Error('invalid chunk type:' + chunk.type); this.presetZoneGenerator = this.parseGenerator(chunk)
+    }; sf2.Parser.prototype.parseInst = function (chunk) {
+        var data = this.input, ip = chunk.offset, instrument = this.instrument = [], size = chunk.offset + chunk.size; if (chunk.type !== 'inst')
+            throw new Error('invalid chunk type:' + chunk.type); while (ip < size) { instrument.push({ instrumentName: String.fromCharCode.apply(null, data.subarray(ip, ip += 20)), instrumentBagIndex: data[ip++] | (data[ip++] << 8) }) }
+    }; sf2.Parser.prototype.parseIbag = function (chunk) {
+        var data = this.input, ip = chunk.offset, instrumentZone = this.instrumentZone = [], size = chunk.offset + chunk.size; if (chunk.type !== 'ibag')
+            throw new Error('invalid chunk type:' + chunk.type); while (ip < size) { instrumentZone.push({ instrumentGeneratorIndex: data[ip++] | (data[ip++] << 8), instrumentModulatorIndex: data[ip++] | (data[ip++] << 8) }) }
+    }; sf2.Parser.prototype.parseImod = function (chunk) {
+        if (chunk.type !== 'imod')
+            throw new Error('invalid chunk type:' + chunk.type); this.instrumentZoneModulator = this.parseModulator(chunk)
+    }; sf2.Parser.prototype.parseIgen = function (chunk) {
+        if (chunk.type !== 'igen')
+            throw new Error('invalid chunk type:' + chunk.type); this.instrumentZoneGenerator = this.parseGenerator(chunk)
+    }; sf2.Parser.prototype.parseShdr = function (chunk) {
+        var data = this.input, ip = chunk.offset, samples = this.sample = [], sampleHeader = this.sampleHeader = [], size = chunk.offset + chunk.size, sampleName, start, end, startLoop, endLoop, sampleRate, originalPitch, pitchCorrection, sampleLink, sampleType; if (chunk.type !== 'shdr')
+            throw new Error('invalid chunk type:' + chunk.type); while (ip < size) {
+                sampleName = String.fromCharCode.apply(null, data.subarray(ip, ip += 20)); start = (data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24); end = (data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24); startLoop = (data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24); endLoop = (data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24); sampleRate = (data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24); originalPitch = data[ip++]; pitchCorrection = (data[ip++] << 24) >> 24; sampleLink = data[ip++] | (data[ip++] << 8); sampleType = data[ip++] | (data[ip++] << 8); var sample = new Int16Array(new Uint8Array(data.subarray(this.samplingData.offset + start * 2, this.samplingData.offset + end * 2)).buffer); startLoop -= start; endLoop -= start; if (sampleRate > 0) { var adjust = this.adjustSampleData(sample, sampleRate); sample = adjust.sample; sampleRate *= adjust.multiply; startLoop *= adjust.multiply; endLoop *= adjust.multiply }
+                samples.push(sample); sampleHeader.push({ sampleName: sampleName, startLoop: startLoop, endLoop: endLoop, sampleRate: sampleRate, originalPitch: originalPitch, pitchCorrection: pitchCorrection, sampleLink: sampleLink, sampleType: sampleType })
+            }
+    }; sf2.Parser.prototype.adjustSampleData = function (sample, sampleRate) {
+        var newSample, i, il, j, multiply = 1; while (sampleRate < 22050) {
+            newSample = new Int16Array(sample.length * 2); for (i = j = 0, il = sample.length; i < il; ++i) { newSample[j++] = sample[i]; newSample[j++] = sample[i] }
+            sample = newSample; multiply *= 2; sampleRate *= 2
+        }
+        return { sample: sample, multiply: multiply }
+    }; sf2.Parser.prototype.parseModulator = function (chunk) {
+        var data = this.input, ip = chunk.offset, size = chunk.offset + chunk.size, code, key, output = []; while (ip < size) {
+            ip += 2; code = data[ip++] | (data[ip++] << 8); key = sf2.Parser.GeneratorEnumeratorTable[code]; if (key === undefined) { output.push({ type: key, value: { code: code, amount: data[ip] | (data[ip + 1] << 8) << 16 >> 16, lo: data[ip++], hi: data[ip++] } }) } else { switch (key) { case 'keyRange': case 'velRange': case 'keynum': case 'velocity': output.push({ type: key, value: { lo: data[ip++], hi: data[ip++] } }); break; default: output.push({ type: key, value: { amount: data[ip++] | (data[ip++] << 8) << 16 >> 16 } }); break } }
+            ip += 2; ip += 2
+        }
+        return output
+    }; sf2.Parser.prototype.parseGenerator = function (chunk) {
+        var data = this.input, ip = chunk.offset, size = chunk.offset + chunk.size, code, key, output = []; while (ip < size) {
+            code = data[ip++] | (data[ip++] << 8); key = sf2.Parser.GeneratorEnumeratorTable[code]; if (key === undefined) { output.push({ type: key, value: { code: code, amount: data[ip] | (data[ip + 1] << 8) << 16 >> 16, lo: data[ip++], hi: data[ip++] } }); continue }
+            switch (key) { case 'keynum': case 'keyRange': case 'velRange': case 'velocity': output.push({ type: key, value: { lo: data[ip++], hi: data[ip++] } }); break; default: output.push({ type: key, value: { amount: data[ip++] | (data[ip++] << 8) << 16 >> 16 } }); break }
+        }
+        return output
+    }; sf2.Parser.prototype.getPresets = function () {
+        var preset = this.presetHeader, zone = this.presetZone, output = [], bagIndex, bagIndexEnd, zoneInfo, presetGenerator, presetModulator, i, il, j, jl
+        for (i = 0, il = preset.length; i < il; ++i) {
+            j = preset[i].presetBagIndex
+            jl = preset[i + 1] ? preset[i + 1].presetBagIndex : zone.length
+            zoneInfo = []; for (; j < jl; ++j) { presetGenerator = this.createPresetGenerator_(zone, j); presetModulator = this.createPresetModulator_(zone, j); zoneInfo.push({ generator: presetGenerator.generator, modulator: presetModulator.modulator, }) }
+            output.push({ info: zoneInfo, header: preset[i], })
+        }
+        return output
+    }; sf2.Parser.prototype.createInstrumentGenerator_ = function (zone, index) { var modgen = this.createBagModGen_(zone, zone[index].instrumentGeneratorIndex, zone[index + 1] ? zone[index + 1].instrumentGeneratorIndex : this.instrumentZoneGenerator.length, this.instrumentZoneGenerator); return { generator: modgen.modgen, } }; sf2.Parser.prototype.createInstrumentModulator_ = function (zone, index) { var modgen = this.createBagModGen_(zone, zone[index].presetModulatorIndex, zone[index + 1] ? zone[index + 1].instrumentModulatorIndex : this.instrumentZoneModulator.length, this.instrumentZoneModulator); return { modulator: modgen.modgen } }; sf2.Parser.prototype.createPresetGenerator_ = function (zone, index) { var modgen = this.createBagModGen_(zone, zone[index].presetGeneratorIndex, zone[index + 1] ? zone[index + 1].presetGeneratorIndex : this.presetZoneGenerator.length, this.presetZoneGenerator); return { generator: modgen.modgen, } }; sf2.Parser.prototype.createPresetModulator_ = function (zone, index) { var modgen = this.createBagModGen_(zone, zone[index].presetModulatorIndex, zone[index + 1] ? zone[index + 1].presetModulatorIndex : this.presetZoneModulator.length, this.presetZoneModulator); return { modulator: modgen.modgen, } }; sf2.Parser.prototype.createBagModGen_ = function (zone, indexStart, indexEnd, zoneModGen) {
+        var modgen = { unknown: [], 'keyRange': { hi: 127, lo: 0 } }; var info, i, il; for (i = indexStart, il = indexEnd; i < il; ++i) {
+            info = zoneModGen[i]; if (info.type === 'unknown')
+                modgen.unknown.push(info.value); else
+                modgen[info.type] = info.value
+        }
+        return { modgen: modgen }
+    }; sf2.Parser.GeneratorEnumeratorTable = ['startAddrsOffset', 'endAddrsOffset', 'startloopAddrsOffset', 'endloopAddrsOffset', 'startAddrsCoarseOffset', 'modLfoToPitch', 'vibLfoToPitch', 'modEnvToPitch', 'initialFilterFc', 'initialFilterQ', 'modLfoToFilterFc', 'modEnvToFilterFc', 'endAddrsCoarseOffset', 'modLfoToVolume', undefined, 'chorusEffectsSend', 'reverbEffectsSend', 'pan', undefined, undefined, undefined, 'delayModLFO', 'freqModLFO', 'delayVibLFO', 'freqVibLFO', 'delayModEnv', 'attackModEnv', 'holdModEnv', 'decayModEnv', 'sustainModEnv', 'releaseModEnv', 'keynumToModEnvHold', 'keynumToModEnvDecay', 'delayVolEnv', 'attackVolEnv', 'holdVolEnv', 'decayVolEnv', 'sustainVolEnv', 'releaseVolEnv', 'keynumToVolEnvHold', 'keynumToVolEnvDecay', 'instrument', undefined, 'keyRange', 'velRange', 'startloopAddrsCoarseOffset', 'keynum', 'velocity', 'initialAttenuation', undefined, 'endloopAddrsCoarseOffset', 'coarseTune', 'fineTune', 'sampleID', 'sampleModes', undefined, 'scaleTuning', 'exclusiveClass', 'overridingRootKey']; sf2.Riff = {}; sf2.Riff.Parser = function (input, options) { options = options || {}; this.input = input; this.ip = options.index || 0; this.length = options.length || input.length - this.ip; this.offset = this.ip; this.padding = options.padding !== undefined ? options.padding : true; this.bigEndian = options.bigEndian !== undefined ? options.bigEndian : false }; sf2.Riff.Chunk = function (type, size, offset) { this.type = type; this.size = size; this.offset = offset }; sf2.Riff.Parser.prototype.parse = function () {
+        var length = this.length + this.offset; this.chunkList = []; while (this.ip < length)
+            this.parseChunk()
+    }; sf2.Riff.Parser.prototype.parseChunk = function () {
+        var input = this.input, ip = this.ip, size; this.chunkList.push(new sf2.Riff.Chunk(String.fromCharCode(input[ip++], input[ip++], input[ip++], input[ip++]), (size = this.bigEndian ? ((input[ip++] << 24) | (input[ip++] << 16) | (input[ip++] << 8) | (input[ip++])) : ((input[ip++]) | (input[ip++] << 8) | (input[ip++] << 16) | (input[ip++] << 24))), ip)); ip += size; if (this.padding && ((ip - this.offset) & 1) === 1)
+            ip++; this.ip = ip
+    }; sf2.Riff.Parser.prototype.getChunk = function (index) {
+        var chunk = this.chunkList[index]; if (chunk === undefined)
+            return null; return chunk
+    }; sf2.Riff.Parser.prototype.getNumberOfChunks = function () { return this.chunkList.length }; return sf2
+})); function Midi5(i_conf) {
+    var po, conf = i_conf, empty = function () { }, rf, op
+    function get_time(po) { return window.performance.now() / 1000 }
+    function note_run(po, s, k, t, d) {
+        var j, a = (k * 100) % 100, c = po.v_c[s.v], i = po.c_i[c]
+        k |= 0
+        t *= 1000
+        d *= 1000
+        if (a && Midi5.ma.sysexEnabled) { po.op.send(new Uint8Array([0xf0, 0x7f, 0x7f, 0x08, 0x02, i & 0x7f, 0x01, k, k, a / .78125, 0, 0xf7]), t) }
+        po.op.send(new Uint8Array([0x90 + c, k, 127]), t)
+        po.op.send(new Uint8Array([0x80 + c, k, 0]), t + d - 20)
+    }
+    function midi_ctrl(po, s, t) { po.op.send(new Uint8Array([0xb0 + po.v_c[s.v], s.ctrl, s.val]), t * 1000) }
+    function midi_prog(po, s) {
+        var i, c = s.chn
+        po.v_c[s.v] = c
+        if (po.c_i[c] == undefined) {
+            po.op.send(new Uint8Array([0xb0 + c, 121, 0]))
+            if (0) {
+                if (s.p_v.midictl) {
+                    for (i in s.p_v.midictl)
+                        po.op.send(new Uint8Array([0xb0 + c, i, s.p_v.midictl[i]]))
+                }
+            }
+        }
+        i = s.instr
+        if (i != undefined) {
+            po.c_i[c] = i
+            po.op.send(new Uint8Array([0xc0 + c, i & 0x7f]))
+        }
+    }
+    function send_outputs(access) {
+        var o, os, out = []
+        Midi5.ma = access
+        if (access && access.outputs.size > 0) {
+            os = access.outputs.values()
+            while (1) {
+                o = os.next()
+                if (!o || o.done)
+                    break
+                out.push(o.value.name)
+            }
+        }
+        rf(out)
+    }
+    return {
+        get_outputs: function (f) {
+            if (!navigator.requestMIDIAccess) {
+                f()
+                return
+            }
+            rf = f
+            navigator.requestMIDIAccess({ sysex: true }).then(send_outputs, function (msg) { navigator.requestMIDIAccess().then(send_outputs, function (msg) { rf() }) })
+        }, set_output: function (name) {
+            if (!Midi5.ma)
+                return
+            var o, os = Midi5.ma.outputs.values()
+            while (1) {
+                o = os.next()
+                if (!o || o.done)
+                    break
+                if (o.value.name == name) {
+                    op = o.value
+                    break
+                }
+            }
+        }, play: function (i_start, i_end, i_lvl) {
+            po = { conf: conf, onend: conf.onend || empty, onnote: conf.onnote || empty, s_end: i_end, s_cur: i_start, repv: i_lvl || 0, tgen: 2, get_time: get_time, midi_ctrl: midi_ctrl, midi_prog: midi_prog, note_run: note_run, timouts: [], op: op, v_c: [], c_i: [] }
+            if (0) { op.send(new Uint8Array([0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x00, 0x01, 0x69, 0x69, 0x00, 0, 0xf7]), t) }
+            abc2svg.play_next(po)
+        }, stop: function () {
+            po.stop = true
+            po.timouts.forEach(function (id) { clearTimeout(id) })
+            abc2svg.play_next(po)
+            if (op && op.clear)
+                op.clear()
+        }
+    }
+}
+function follow(abc, user, playconf) {
+    var keep_types = { note: true, rest: true }
+    user.anno_stop = function (type, start, stop, x, y, w, h) {
+        if (!keep_types[type])
+            return
+        abc.out_svg('<rect class="abcr _' + start + '_" x="'); abc.out_sxsy(x, '" y="', y); abc.out_svg('" width="' + w.toFixed(2) + '" height="' + abc.sh(h).toFixed(2) + '"/>\n')
+    }
+    playconf.onnote = function (i, on) {
+        var b, i, e, elts, x = 0, y = 0
+        if (abc2svg.mu)
+            elts = abc2svg.mu.d.getElementsByClassName('_' + i + '_')
+        else
+            elts = document.getElementsByClassName('_' + i + '_')
+        if (!elts || !elts.length)
+            return
+        e = elts[0]
+        e.style.fillOpacity = on ? 0.4 : 0
+        if (on && !window.no_scroll) {
+            b = e.getBoundingClientRect()
+            if (b.top < 0 || b.bottom > window.innerHeight * .8)
+                y = b.top - window.innerHeight * .3
+            if (b.left < 0 || b.right > window.innerWidth * .8)
+                x = b.left - window.innerWidth * .3
+            if (x || y)
+                window.scrollBy({ top: y, left: x, behavior: (x < 0 || y) ? 'instant' : 'smooth' })
+        }
+    }
+}
+(function () {
+    var sty = document.createElement("style")
+    sty.innerHTML = ".abcr {fill: #d00000; fill-opacity: 0; z-index: 15}"
+    document.head.appendChild(sty)
+})()
+abc2svg.ch_names = { '': ["C-E G C+", "E-C G C+", "G-C E G "], m: ["C-e G C+", "e-C G C+", "G-C e G "], '7': ["C-b-E G ", "E-C G b ", "G-E b C+", "b-E G C+"], m7: ["C-b-e G ", "e-C G b ", "G-e b C+", "b-e G C+"], m7b5: ["C-b-e g ", "e-C g b ", "g-e b C+", "b-e g C+"], M7: ["C-B-E G ", "E-C G B ", "G-E B C+", "B-E G C+"], '6': ["C-A-E G ", "E-C A B ", "A-E B C+", "B-E A C+"], m6: ["C-A-e G ", "e-C A B ", "A-e B C+", "B-e A C+"], aug: ["C-E a C+", "E-C a C+", "a-C E a "], aug7: ["C-b-E a ", "E-C a b ", "a-E b C+", "b-E a C+"], dim: ["C-E g C+", "E-C g C+", "g-C E g "], dim7: ["C-e g A ", "e-C g A ", "g-e A C+", "A-C e G "], '9': ["C-b-E G D+", "E-C G b D+", "G-E b C+D+", "b-E G C+D+", "D-G-C E b "], m9: ["C-b-e G D+", "e-C G b D+", "G-e b C+D+", "b-e G C+D+", "D-G-C e b "], maj9: ["C-B-E G D+", "E-C G B D+", "G-E B C+D+", "B-E G C+D+", "D-G-C E B "], M9: ["C-B-E G D+", "E-C G B D+", "G-C E B D+", "B-E G C+D+", "D-G-C E B "], '11': ["C-b-E G D+F+", "E-C G b D+F+", "G-E b C+D+F+", "b-E G C+D+F+", "D-G-C E b F+", "F-D-G-C E b D+"], dim9: ["C-A-e g d+", "e-C g A d+", "g-C e A d+", "A-C e g d+", "D-g-C e A "], sus4: ["C-F G C+", "F-C G C+", "G-C F G "], sus9: ["C-D G C+", "D-C G C+", "G-C D G "], '7sus4': ["C-b-F G ", "F-C G b ", "G-F b C+", "b-C F G "], '7sus9': ["C-b-D G ", "D-C G b ", "G-D b C+", "b-C D G "], '5': ["C-G C+", "G-G C+"] }
+abc2svg.midlet = "CdDeEFgGaAbB"
+abc2svg.letmid = { C: 0, d: 1, D: 2, e: 3, E: 4, F: 5, g: 6, G: 7, a: 8, A: 9, b: 10, B: 11 }
+abc2svg.chord = function (first, voice_tb, cfmt) {
+    var chnm, i, k, vch, s, gchon, C = abc2svg.C, trans = 48 + (cfmt.chord.trans ? cfmt.chord.trans * 12 : 0)
+    function chcr(b, ch) {
+        var i, v, r = []
+        b = abc2svg.midlet[b]
+        i = ch.length
+        while (--i > 0) {
+            if (ch[i][0] == b)
+                break
+        }
+        ch = ch[i]
+        for (i = 0; i < ch.length; i += 2) {
+            v = abc2svg.letmid[ch[i]]
+            switch (ch[i + 1]) {
+                case '+': v += 12; break
+                case '-': v -= 12; break
+            }
+            r.push(v)
+        }
+        return r
+    }
+    function filter(a_cs) {
+        var i, cs, t
+        for (i = 0; i < a_cs.length; i++) {
+            cs = a_cs[i]
+            if (cs.type != 'g')
+                continue
+            t = cs.otext
+            if (t.slice(-1) == ')')
+                t = t.replace(/\(.*/, '')
+            return t.replace(/\(|\)|\[|\]/g, '')
+        }
+    }
+    function gench(sb) {
+        var r, ch, b, m, n, not, a = filter(sb.a_gch), s = { v: vch.v, p_v: vch, type: C.NOTE, time: sb.time, notes: [] }
+        if (!a)
+            return
+        a = a.match(/([A-GN])([#♯b♭]?)([^/]*)\/?(.*)/)
+        if (!a)
+            return
+        r = abc2svg.letmid[a[1]]
+        if (r == undefined) {
+            if (a[1] != "N")
+                return
+            s.type = C.REST
+            ch = [0]
+            r = 0
+        } else {
+            switch (a[2]) {
+                case "#": case "♯": r++; break
+                case "b": case "♭": r--; break
+            }
+            if (!a[3]) { ch = chnm[""] } else {
+                ch = abc2svg.ch_alias[a[3]]
+                if (ch == undefined)
+                    ch = a[3]
+                ch = chnm[ch]
+                if (!ch)
+                    ch = a[3][0] == 'm' ? chnm.m : chnm[""]
+            }
+            if (a[4]) {
+                b = a[4][0].toUpperCase()
+                b = abc2svg.letmid[b]
+                if (b != undefined) {
+                    switch (a[4][1]) {
+                        case "#": case "♯": b++; if (b >= 12) b = 0; break
+                        case "b": case "♭": b--; if (b < 0) b = 11; break
+                    }
+                }
+            }
+        }
+        if (b == undefined)
+            b = 0
+        ch = chcr(b, ch)
+        n = ch.length
+        r += trans
+        if (sb.p_v.tr_snd)
+            r += sb.p_v.tr_snd
+        for (m = 0; m < n; m++) {
+            not = { midi: r + ch[m] }
+            s.notes.push(not)
+        }
+        s.nhd = n - 1
+        s.prev = vch.last_sym
+        vch.last_sym.next = s
+        s.ts_next = sb.ts_next
+        sb.ts_next = s
+        s.ts_prev = sb
+        if (s.ts_next)
+            s.ts_next.ts_prev = s
+        vch.last_sym = s
+    }
+    if (cfmt.chord.names) {
+        chnm = Object.create(abc2svg.ch_names)
+        for (k in cfmt.chord.names) {
+            vch = ""
+            for (i = 0; i < cfmt.chord.names[k].length; i++) {
+                s = cfmt.chord.names[k][i]
+                vch += abc2svg.midlet[s % 12]
+                vch += i == 0 ? "-" : (s >= 12 ? "+" : " ")
+            }
+            chnm[k] = [vch]
+        }
+    } else { chnm = abc2svg.ch_names }
+    k = 0
+    for (i = 0; i < voice_tb.length; i++) {
+        if (k < voice_tb[i].chn)
+            k = voice_tb[i].chn
+    }
+    if (k == 8)
+        k++
+    vch = { v: voice_tb.length, id: "_chord", time: 0, sym: { type: C.BLOCK, subtype: "midiprog", chn: k + 1, instr: cfmt.chord.prog || 0, time: 0, ts_prev: first, ts_next: first.ts_next }, vol: cfmt.chord.vol || .6 }
+    vch.sym.p_v = vch
+    vch.sym.v = vch.v
+    vch.last_sym = vch.sym
+    voice_tb.push(vch)
+    first.ts_next = vch.sym
+    gchon = cfmt.chord.gchon
+    s = first
+    while (1) {
+        if (!s.ts_next) {
+            if (gchon)
+                vch.last_sym.dur = s.time - vch.last_sym.time
+            break
+        }
+        s = s.ts_next
+        if (!s.a_gch) {
+            if (s.subtype == "midigch") {
+                if (gchon && !s.on)
+                    vch.last_sym.dur = s.time - vch.last_sym.time
+                gchon = s.on
+            }
+            continue
+        }
+        if (!gchon)
+            continue
+        for (i = 0; i < s.a_gch.length; i++) {
+            gch = s.a_gch[i]
+            if (gch.type != 'g')
+                continue
+            vch.last_sym.dur = s.time - vch.last_sym.time
+            gench(s)
+            break
+        }
+    }
+}

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