pepperscore 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/LICENSE +26 -12
- package/README.md +97 -8
- package/dist/THIRD_PARTY_NOTICES.txt +1222 -0
- package/dist/assets/{import.worker-D0XfuAHu.js → import.worker-nfqQ5M0Y.js} +2 -2
- package/dist/assets/verovio.worker-DGik-H4a.js +7 -0
- package/dist/audio.d.ts +24 -0
- package/dist/audio.js +198 -0
- package/dist/audio.js.map +1 -0
- package/dist/components/PepperScore.d.ts +89 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2586 -3246
- package/dist/index.js.map +1 -1
- package/dist/lib/chrome.d.ts +5 -2
- package/dist/lib/file-state.d.ts +17 -4
- package/dist/lib/header-controls.d.ts +7 -3
- package/dist/lib/hit-test.d.ts +18 -0
- package/dist/lib/instruments.d.ts +82 -0
- package/dist/lib/metronome.d.ts +33 -0
- package/dist/lib/notation/mei-tab.d.ts +51 -0
- package/dist/lib/notation/mei-view.d.ts +8 -0
- package/dist/lib/playback/timeline.d.ts +4 -1
- package/dist/lib/prefs.d.ts +50 -0
- package/dist/lib/render.d.ts +36 -1
- package/dist/lib/score.d.ts +7 -0
- package/dist/lib/sound-players.d.ts +9 -1
- package/dist/lib/tab/fret-assign.d.ts +53 -0
- package/dist/lib/tab/tab-parts.d.ts +58 -0
- package/dist/lib/verovio-protocol.d.ts +15 -0
- package/dist/lib/verovio-runtime.d.ts +9 -1
- package/dist/runtime-files.d.ts +15 -0
- package/dist/{sf2-player-CRlOJDhD.js → sf2-player-oWC6yrUH.js} +28 -6
- package/dist/sf2-player-oWC6yrUH.js.map +1 -0
- package/dist/sound-players-DdLBBZaR.js +1172 -0
- package/dist/sound-players-DdLBBZaR.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/verovio/LICENSE +858 -0
- package/dist/verovio/verovio-module.mjs +0 -0
- package/dist/verovio/verovio.mjs +397 -0
- package/package.json +6 -1
- package/dist/assets/verovio.worker-DkHQmOsT.js +0 -19034
- package/dist/sf2-player-CRlOJDhD.js.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const e=/<(?:!--[\s\S]*?--|\?[\s\S]*?\?|!\[CDATA\[[\s\S]*?\]\]|!DOCTYPE[^>]*|(\/?)([A-Za-z_][\w.:-]*)((?:\s+[^\s=/>]+(?:\s*=\s*(?:"[^"]*"|'[^']*'))?)*)\s*(\/?))>/g,t=/* @__PURE__ */ new Map;function n(e){let n=t.get(e);return n||(n=RegExp(`\\s${e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`),t.set(e,n)),n}function r(e,t){if(!e.includes(t))return null;let r=n(t).exec(e);return r?r[1]??r[2]??``:null}function i(e,t){return e.replace(n(t),``)}function a(e,t,r){return e.replace(n(t),` ${t}="${r}"`)}const o=e=>e.slice(e.indexOf(`:`)+1),s=e=>r(e,`xml:id`)||``,c=e=>(e||``).split(/\s+/).filter(Boolean),l=e=>e.replace(/^#/,``);function u(t,n){e.lastIndex=0;for(let r=e.exec(t);r;r=e.exec(t))if(r[2]&&n({closing:r[1]===`/`,name:o(r[2]),attributes:r[3]||``,selfClosing:r[4]===`/`,index:r.index,length:r[0].length}))return}function d(e){let t=[],n=[],i=[],a=[],o=[],c=-1,l=!1,d=!1,f=0,p=/* @__PURE__ */ new Set,m=0;return u(e,({closing:e,name:u,attributes:h,selfClosing:g})=>{if(e){a.pop(),u===`staff`&&d?(d=!1,f&&(m=Math.max(m,Math.ceil(f/p.size)))):c>=0&&(u===`staffGrp`&&o.pop(),u===`scoreDef`&&a.length===c&&(c=-1,l=!0));return}if(u===`measure`)t.push(s(h));else if(u===`staff`&&!g)d=!0,f=0,p=/* @__PURE__ */ new Set;else if(u===`verse`&&d)f++,p.add(r(h,`n`)||`1`);else if(u===`scoreDef`&&!l&&c<0)g?l=!0:c=a.length;else if(c>=0){if(u===`staffGrp`)i.push({id:s(h),staves:[]}),g||o.push(i.length-1);else if(u===`staffDef`){let e={n:r(h,`n`)||``,id:s(h)};n.push(e),a.at(-1)===`staffGrp`&&o.length&&i[o.at(-1)].staves.push(e)}}g||a.push(u)}),{measureIds:t,lyricDensity:m,staffDefs:n,groups:i}}const f=/* @__PURE__ */ new Set([`meiHead`,`label`,`labelAbbr`,`sb`,`pb`,`pgHead`,`pgFoot`]);function p(e,t){let n=/* @__PURE__ */ new Set,i=[],a=[],o=0;return u(e,({closing:e,name:l,attributes:u,selfClosing:d})=>{if(e){o?o--:l===`staffGrp`&&a.pop();return}let f=l===`staffGrp`?i.push(0)-1:-1;if(o){let e=s(u);e&&n.add(e),d||o++;return}let p=(l===`staffDef`||l===`staff`)&&t.has(r(u,`n`)||``);if(!p){let e=c(r(u,`staff`));p=e.length>0&&e.every(e=>t.has(e))}if(p){let e=s(u);e&&n.add(e),d||(o=1);return}if(l===`staffDef`)for(let e of a)i[e]++;f>=0&&!d&&a.push(f)}),{removed:n,emptyGroups:new Set(i.flatMap((e,t)=>e?[]:[t]))}}function m(e,t,n=1/0,o=0){let d=new Set(t.hiddenStaves),{removed:m,emptyGroups:h}=d.size?p(e,d):{removed:/* @__PURE__ */ new Set,emptyGroups:/* @__PURE__ */ new Set},g=e=>m.size>0&&c(e).some(e=>m.has(l(e))),_=[],v=[],y=0,b=0,x=0,S=0,C=0,w=-1,T=-1,E=()=>++C>=n,D=t.chordSymbols&&t.harmSize&&t.harmSize!==100?Math.round(t.harmSize):0,O=0;if(u(e,({closing:n,name:u,attributes:p,selfClosing:C,index:k,length:A})=>{b||_.push(e.slice(y,k)),y=k+A;let j=e.slice(k,k+A);if(n){if(b){b--;return}return u===`harm`&&O&&v.at(-1)===`rend`&&(v.pop(),O--,_.push(`</rend>`)),v.pop(),T=-1,_.push(j),u===`measure`&&E()?(w=y,!0):void 0}let M=u===`staffGrp`?x++:-1;if(b){if(d.size){let e=s(p);e&&m.add(e)}C||b++;return}let N=f.has(u)||u===`harm`&&!t.chordSymbols,P=j;if(!N&&d.size){let e=c(r(p,`staff`)),t=e.filter(e=>!d.has(e));N=(u===`staffDef`||u===`staff`)&&d.has(r(p,`n`)||``)||M>=0&&h.has(M)||e.length>0&&!t.length||g(r(p,`startid`))||g(r(p,`endid`)),!N&&t.length!==e.length&&(P=a(P,`staff`,t.join(` `)));let n=r(p,`plist`);if(!N&&n&&g(n)){let e=c(n).filter(e=>!m.has(l(e)));e.length?P=a(P,`plist`,e.join(` `)):N=!0}}if(N){if(d.size){let e=s(p);e&&m.add(e)}C||(b=1);return}if((u===`staffDef`||u===`staffGrp`)&&(P=i(i(P,`label`),`label.abbr`)),u===`measure`&&(t.breakEvery>0&&S>0&&(S+o)%t.breakEvery===0&&(T>=0?_.splice(T,0,`<pb/>`):_.push(`<pb/>`)),S++),(u===`ending`||u===`section`)&&!C?T<0&&(T=_.length):T=-1,_.push(P),!C)v.push(/^<([^\s/>]+)/.exec(j)[1]);else if(u===`measure`&&E())return w=y,!0;if(D&&u===`harm`&&!C){let t=e.indexOf(`</harm>`,y);(t>=0?e.slice(y,t).includes(`<fb`):e.includes(`<fb`,y))||(_.push(`<rend fontsize="${D}%">`),v.push(`rend`),O++)}}),w<0)return _.push(e.slice(y)),_.join(``);for(let e=v.length-1;e>=0;e--)_.push(`</${v[e]}>`);return _.join(``)}const h=[`C`,`D`,`E`,`F`,`G`,`A`,`B`],g={C:0,D:2,E:4,F:5,G:7,A:9,B:11},_=[`Cb`,`Gb`,`Db`,`Ab`,`Eb`,`Bb`,`F`,`C`,`G`,`D`,`A`,`E`,`B`,`F#`,`C#`],v=[`Ab`,`Eb`,`Bb`,`F`,`C`,`G`,`D`,`A`,`E`,`B`,`F#`,`C#`,`G#`,`D#`,`A#`],y=[0,-5,2,-3,4,-1,6,1,-4,3,-2,5],b=[0,7,2,-3,4,-1,6,1,-4,3,-2,5],x=(e,t)=>(e%t+t)%t,S=e=>e>0?`#`.repeat(e):`b`.repeat(-e);function C(e){let t=0;for(let n of e)t+=n===`#`||n===`♯`?1:n===`x`||n===`𝄪`?2:n===`𝄫`?-2:-1;return t}function w(e,t){let n=(t>0?`FCGDAEB`:`BEADGCF`).indexOf(e),r=n<Math.abs(t)?Math.floor((Math.abs(t)-1-n)/7)+1:0;return t>0?r:-r}function T(e,t=`major`){let n=(t===`minor`?v:_)[e+7];if(!n)throw Error(`No key with ${e} fifths`);return{tonic:n,mode:t,fifths:e,scale:h.map(t=>({step:t,alter:w(t,e)}))}}function E(e){let t=e.fifths>0?e.fifths-12:e.fifths<0?e.fifths+12:null;return t===null||Math.abs(t)>7?null:T(t,e.mode)}function D(e,t=`major`,n={}){let r=x(e+(t===`minor`?3:0),12),i=T((n.family===`sharp`?b:y)[r],t);return n.flip?E(i)??i:i}function O(e,t){return{...t,octave:Math.round((e-g[t.step]-t.alter)/12)-1}}const k=(e,t)=>x(g[t.step]+t.alter,12)===x(e,12),A=e=>h.indexOf(e);function j(e,t){let n=x(A(t.step)-A(e),7);return n===1?1:n===6?-1:0}function M(e,t,n={}){let r=x(e,12),i=n.source&&k(r,n.source)?n.source:void 0;if(i&&Math.abs(i.alter)===2&&!n.transposed)return O(e,i);let a=t.scale.find(e=>k(r,e));if(a)return O(e,a);let o=e=>Math.abs(e.alter)<=1&&![`E1`,`B1`,`F-1`,`C-1`].includes(e.step+e.alter);if(t.mode===`minor`){let n=A(t.tonic.charAt(0));for(let i of[5,6]){let a=t.scale[(n+i)%7],o={step:a.step,alter:a.alter+1};if(k(r,o)&&Math.abs(o.alter)<=1)return O(e,o)}}if(i&&o(i)&&n.next!==void 0&&n.next-e>=1&&n.next-e<=2)return O(e,i);let s=Object.entries(g).find(([,e])=>e===r)?.[0];if(s){let r={step:h[(A(s)+1)%7],alter:-1};if((s===`E`||s===`B`)&&t.fifths<=-6&&n.prev!==void 0&&n.next!==void 0){let i=M(n.prev,t),a=M(n.next,t),o=[j(r.step,i),j(r.step,a)];if(o.includes(1)&&o.includes(-1))return O(e,r)}return O(e,{step:s,alter:0})}let c={step:h.find(e=>g[e]===r-1),alter:1},l={step:h.find(e=>g[e]===r+1),alter:-1};return t.fifths>0?O(e,c):t.fifths<0?O(e,l):O(e,r===6?c:l)}function N(e,t){let n=/^([A-G])([#♯b♭x𝄪𝄫]*)(.*)$/s.exec(e);if(!n)return e;let r=/[♯♭]/.test(e),i=(e,n)=>{let i=M(60+g[e]+C(n),t),a=S(i.alter);return i.step+(r?a.replace(/#/g,`♯`).replace(/b/g,`♭`):a)},a=n[3].replace(/\/([A-G])([#♯b♭x𝄪𝄫]*)/g,(e,t,n)=>`/${i(t,n)}`);return i(n[1],n[2])+a}const P=[`C`,`D`,`E`,`F`,`G`,`A`,`B`],F=[0,2,4,5,7,9,11],I=(e,t)=>(e%t+t)%t;function ee(e){let t=/^([+-]?)(dd|d|m|M|P|A|AA)(\d+)$/.exec(e.trim());if(!t)return{diatonic:0,chromatic:0};let n=Number(t[3])-1,r=n%7,i=F[r]+12*Math.floor(n/7),a=(r===0||r===3||r===4?{dd:-2,d:-1,P:0,A:1,AA:2}:{dd:-3,d:-2,m:-1,M:0,A:1,AA:2})[t[2]]??0,o=t[1]===`-`?-1:1;return{diatonic:o*n,chromatic:o*(i+a)}}const te=({diatonic:e,chromatic:t})=>7*t-12*e;function ne(e,t){if(!t.diatonic&&!t.chromatic)return e;let n=P.indexOf(e.step)+t.diatonic,r=P[I(n,7)],i=e.octave+Math.floor(n/7);return{step:r,octave:i,alter:L(e)+t.chromatic-L({step:r,octave:i,alter:0})}}const L=e=>(e.octave+1)*12+F[P.indexOf(e.step)]+e.alter;function re(e){if(e==null)return null;let t=/^\s*(\d+)\s*([sf]?)\s*$/.exec(e);if(!t)return null;let n=Number(t[1]);return t[2]===`f`?-n:n}const R=e=>e>0?`${e}s`:e<0?`${-e}f`:`0`,ie=e=>{let t=e;for(;t>7;)t-=12;for(;t<-7;)t+=12;return t};function ae(e,t,n,r,i){if(t===0){let t=T(ie(e),n);return i?E(t)??t:t}let a=I(7*(e+7*t),12);return D(I(a-(n===`minor`?3:0),12),n,{family:r.profile,flip:i})}function oe(e){let t=[];return e.forEach((n,r)=>{if(n.tiedFrom!==void 0&&t[n.tiedFrom]&&L(t[n.tiedFrom])===n.midi){t.push(t[n.tiedFrom]);return}let i=e=>e&&!e.chord&&!n.chord?e.midi:void 0;t.push(M(n.midi,n.key,{source:n.source,prev:i(e[r-1]),next:i(e[r+1]),transposed:!0}))}),t}const se=(e,t)=>e.scale[P.indexOf(t)]?.alter??0;function ce(e){let t=Array(e.length).fill(!1),n=e.map((e,t)=>t).sort((t,n)=>e[t].onset-e[n].onset||t-n),r=/* @__PURE__ */ new Map;for(let i=0;i<n.length;){let a=i;for(;a<n.length&&Math.abs(e[n[a]].onset-e[n[i]].onset)<1e-6;)a++;let o=[];for(let s of n.slice(i,a)){let{pitch:n,key:i,tieEnd:a,cautionary:c}=e[s],l=`${n.step}${n.octave}`,u=r.get(l)??se(i,n.step);a||(n.alter!==u||c)&&(t[s]=!0,o.push([l,n.alter]))}for(let[e,t]of o)r.set(e,t);i=a}return t}const z=/^([A-G])([#♯b♭x𝄪𝄫]*)/,le=e=>[...e].reduce((e,t)=>e+(t===`#`||t===`♯`?1:t===`x`||t===`𝄪`?2:t===`𝄫`?-2:-1),0);function ue(e,t){let n=(e,n)=>{let r=t.reduce((e,t)=>ne(e,t),{step:e,alter:le(n),octave:4});return r.step+(r.alter>0?`#`.repeat(r.alter):`b`.repeat(-r.alter))},r=z.exec(e);if(!r)return e;let i=e.slice(r[0].length).replace(/\/([A-G])([#♯b♭x𝄪𝄫]*)/g,(e,t,r)=>`/${n(t,r)}`);return n(r[1],r[2])+i}const de=`CDEFGAB`,fe=[0,2,4,5,7,9,11],B={s:1,f:-1,n:0,x:2,ss:2,ff:-2,ts:3,tf:-3,xs:3,sx:3,nf:-1,ns:1,su:1,sd:1,fu:-1,fd:-1,nu:0,nd:0},pe=e=>({1:`s`,[-1]:`f`,0:`n`,2:`x`,[-2]:`ff`})[e]??`n`,me=e=>({1:`s`,[-1]:`f`,0:`n`,2:`ss`,[-2]:`ff`})[e]??`n`;function he(e,t){let n=(t>0?`FCGDAEB`:`BEADGCF`).indexOf(e),r=n<Math.abs(t)?Math.floor((Math.abs(t)-1-n)/7)+1:0;return t>0?r:-r}const ge={maxima:32,long:16,breve:8,1:4,2:2,4:1,8:.5,16:.25,32:.125,64:.0625,128:.03125,256:.015625};function _e(e){return r(e,`grace`)===null?(ge[r(e,`dur`)||``]??0)*(2-1/2**(Number(r(e,`dots`))||0)):0}function ve(e,t,n){let r=RegExp(`\\s${t.replace(`.`,`\\.`)}\\s*=\\s*(?:"[^"]*"|'[^']*')`);return r.test(e)?e.replace(r,` ${t}="${n}"`):e.replace(/\s*(\/?)>$/,` ${t}="${n}"$1>`)}function ye(e,t){return e.replace(RegExp(`\\s${t.replace(`.`,`\\.`)}\\s*=\\s*(?:"[^"]*"|'[^']*')`),``)}const V=[`keysig`,`key.sig`,`key.mode`,`key.pname`,`key.accid`,`key.sig.mixed`],be=e=>V.reduce(ye,e),xe=e=>e.replace(/\s*\/>$/,`>`),Se=e=>`<keySig sig="${R(e.fifths)}"${e.mode===`minor`?` mode="minor"`:``}/>`,Ce=e=>e===`minor`?`minor`:e===`major`?`major`:null,we=/^(?:\s+(?:n|xml:id|keysig|key\.[\w.]+)\s*=\s*(?:"[^"]*"|'[^']*'))*\s*$/;function Te(e,t){return t?!!t.interval||t.concert||t.flip||t.semitones!==0||/\b(?:clef\.)?shape="perc"/.test(e)||Object.values(t.staves).some(e=>e.percussion||(e.keys?.length??0)>1):!1}async function Ee(e,t,n,r=0){return!t||!Te(e,t)?e:De(t.interval?await n(e,{transpose:t.interval,transposeToSoundingPitch:!1}):e,t,r)}function De(e,t,n=0){if(!Te(e,t))return e;let i=te(ee(t.interval)),a=/* @__PURE__ */ new Map;u(e,({closing:e,name:t,attributes:n})=>{if(e||t!==`tie`)return;let i=r(n,`startid`)?.replace(/^#/,``),o=r(n,`endid`)?.replace(/^#/,``);i&&o&&a.set(o,i)});let o=[],s=[],c=[],l=[],d=[],f=[],p=new Set(Object.entries(t.staves).filter(([,e])=>e.percussion).map(([e])=>e)),m=e=>t.staves[e]??{profile:`neutral`,moved:t.semitones!==0},h=e=>!p.has(e)&&(m(e).moved||t.semitones!==0||t.flip||!!t.interval),g=[],_=[],v,y,b,x=0,S=-1,C=``,w=``,T=0,E=[],D=-1,O=0,k=0,A,j,M=()=>E.reduce((e,t)=>e*t,1),P=(e,t,n)=>{let i=re(r(e,t))??(t===`key.sig`?re(r(e,`keysig`)):null);return i===null?null:{fifths:i,mode:Ce(r(e,n))??`major`}};u(e,({closing:t,name:n,attributes:i,selfClosing:u,index:m,length:N})=>{let F=e.slice(m,m+N);if(t){if(_.pop(),b){--x===0&&(b.end=m+N,b=void 0);return}n===`staffDef`&&y?(y.end=m+N,y=void 0):n===`scoreDef`&&v?(v.end=m+N,v=void 0):n===`note`&&A?(A.end=m+N,A=void 0):n===`chord`?(O--,T+=k*M()):n===`tuplet`?E.pop():n===`harm`&&j?(j.textEnd=m,j=void 0):n===`layer`?w=``:n===`staff`&&(C=``);return}if(u||_.push(n),b){u||x++;return}if(j&&(j.nested=!0),n===`scoreDef`){let e={start:m,end:m+N,initial:!o.length,measure:S+1,content:!1,keyRanges:[],tagEdits:[],keys:/* @__PURE__ */ new Map},t=P(i,`key.sig`,`key.mode`);t&&e.keys.set(`*`,t);let n=be(F);n!==F&&e.tagEdits.push({start:m,end:m+N,text:n}),/\s(?!xml:id)[\w.:-]+\s*=/.test(n.replace(/^<[\w:]+/,``).replace(/\sxml:id\s*=\s*"[^"]*"/,``))&&(e.content=!0),o.push(e),u||(v=e);return}if(v&&n===`staffGrp`){if(v.initial)return;we.test(i)||(v.content=!0);return}if(n===`staffDef`){let e=r(i,`n`)||``,t={start:m,end:m+N,n:e,tag:F,selfClosing:u};if(r(i,`clef.shape`)===`perc`&&p.add(e),v){let n=P(i,`key.sig`,`key.mode`);n&&v.keys.set(e,n);let r=be(F);r!==F&&v.tagEdits.push({start:m,end:m+N,text:r}),we.test(i)||(v.content=!0),v.initial&&(s.push(t),e&&!g.includes(e)&&g.push(e))}u||(y=t);return}if(n===`clef`&&y){r(i,`shape`)===`perc`&&p.add(y.n),u&&(y.clefEnd=m+N),v&&(v.content=!0);return}if(n===`keySig`){let e={start:m,end:m+N};u||(b=e,x=1);let t=P(i,`sig`,`mode`);v?(v.keyRanges.push(e),t&&v.keys.set(y?y.n:`*`,t)):C&&f.push(Object.assign(e,{staff:C,measure:S,key:t}));return}if(v){v.content=!0;return}if(n===`measure`){S++,c.push(m);return}if(n===`staff`){C=r(i,`n`)||``;return}if(n===`layer`){w=r(i,`n`)||`1`,T=0,E.length=0,O=0;return}if(!C||!w){n===`harm`&&!u&&(j={textStart:m+N,textEnd:m+N,staff:(r(i,`staff`)||``).split(/\s+/)[0],measure:S,nested:!1},d.push(j));return}if(n===`tuplet`){let e=Number(r(i,`num`))||1,t=Number(r(i,`numbase`))||1;u||E.push(t/e);return}if(n===`chord`){D=T,k=_e(i),u?T+=k*M():O++;return}if(n===`note`){let e=O>0,t=e?D:T;e||(T+=_e(i)*M());let n=(r(i,`pname`)||``).toUpperCase(),o=Number(r(i,`oct`));if(!n||!de.includes(n)||!Number.isFinite(o)||!h(C))return;let s=r(i,`xml:id`)||``,c=r(i,`tie`),d=r(i,`accid`),f=r(i,`accid.ges`);A={start:m,end:m+N,tag:F,selfClosing:u,id:s,staff:C,layer:w,measure:S,onset:t,chord:e,pname:n,oct:o,written:d===null?null:B[d]??null,gestural:f===null?null:B[f]??null,accids:[],tieEnd:a.has(s)||c===`t`||c===`m`,cautionary:!1},l.push(A),u&&(A=void 0);return}if(n===`accid`&&A){let e=r(i,`accid`),t=r(i,`accid.ges`);e!==null&&B[e]!==void 0&&(A.written=B[e]),t!==null&&B[t]!==void 0&&(A.gestural=B[t]),(r(i,`func`)!==null||r(i,`enclose`)!==null)&&(A.cautionary=e!==null),A.accids.push({start:m,end:m+N,attributes:i});return}[`rest`,`space`,`mRest`,`mSpace`,`multiRest`].includes(n)&&O===0&&(T+=(n.startsWith(`m`)?1e3:_e(i))*M())});for(let e of p)g.includes(e)||g.push(e);let F=c.length,I=/* @__PURE__ */ new Map;for(let e of g){if(p.has(e))continue;let t=Array(Math.max(1,F)).fill(void 0),r=m(e).keys;if(r?.length)for(let e=0;e<t.length;e++){let i=[...r].reverse().find(([t])=>t<=e+n)??r[0];t[e]={fifths:i[1],mode:i[2]}}else{let n={fifths:0,mode:`major`},r=/* @__PURE__ */ new Map;for(let n of o){let a=n.keys.get(e)??n.keys.get(`*`);a&&r.set(Math.min(n.measure,t.length-1),{fifths:a.fifths-i,mode:a.mode})}for(let n of f)n.staff===e&&n.key&&r.set(Math.min(n.measure+1,t.length-1),{fifths:n.key.fifths-i,mode:n.key.mode});for(let e=0;e<t.length;e++)n=r.get(e)??n,t[e]=n}I.set(e,t)}let L=/* @__PURE__ */ new Map,R=(e,n)=>{let r=I.get(e)?.[Math.max(0,Math.min(n,F-1))]??{fifths:0,mode:`major`},i=`${e}|${r.fifths}|${r.mode}`,a=L.get(i);return a||(a=ae(r.fifths,t.semitones,r.mode,m(e),t.flip),L.set(i,a)),a},ie=e=>{let t=m(e).shift;return t?{diatonic:t[0],chromatic:t[1]}:void 0},se=(e,t)=>{let n=ie(e);return(I.get(e)?.[Math.max(0,Math.min(t,F-1))]?.fifths??0)+i-(n?te(n):0)},z=/* @__PURE__ */ new Map;for(let e of l){let t=`${e.staff}|${e.measure}`;(z.get(t)??z.set(t,[]).get(t)).push(e)}let le=/* @__PURE__ */ new Map;for(let e of z.values()){let t=/* @__PURE__ */ new Map;for(let n of[...e].sort((e,t)=>e.onset-t.onset)){let e=`${n.pname}${n.oct}`;le.set(n,n.written??n.gestural??t.get(e)??he(n.pname,se(n.staff,n.measure))),n.written!==null&&t.set(e,n.written)}}let ge=/* @__PURE__ */ new Map;for(let e of l){let t=`${e.staff}|${e.layer}`;(ge.get(t)??ge.set(t,[]).get(t)).push(e)}let V=/* @__PURE__ */ new Map,Ee=e=>(e.octave+1)*12+fe[de.indexOf(e.step)]+e.alter;for(let e of ge.values()){let t=new Map(e.map((e,t)=>[e.id,t]));oe(e.map(e=>{let n=ie(e.staff),r={step:e.pname,octave:e.oct,alter:le.get(e)??0},i=n?ne(r,n):r,o=a.get(e.id);return{midi:Ee(i),source:i,key:R(e.staff,e.measure),chord:e.chord,tiedFrom:o===void 0?void 0:t.get(o)}})).forEach((t,n)=>V.set(e[n],t))}let De=new Map(l.map(e=>[e.id,e]));for(let e of l){let t=De.get(a.get(e.id)||``);t&&V.has(t)&&Ee(V.get(t))===Ee(V.get(e))&&V.set(e,V.get(t))}let Oe=/* @__PURE__ */ new Map;for(let e of z.values()){let t=ce(e.map(e=>({pitch:V.get(e),onset:e.onset,key:R(e.staff,e.measure),tieEnd:e.tieEnd,cautionary:e.cautionary})));e.forEach((e,n)=>Oe.set(e,t[n]))}let H=[];for(let e of l){let t=V.get(e),n=Oe.get(e),i=ye(ye(e.tag,`accid`),`accid.ges`);i=ve(ve(i,`pname`,t.step.toLowerCase()),`oct`,String(t.octave)),n||(i=ve(i,`accid.ges`,me(t.alter)));let a=e.accids.find(e=>r(e.attributes,`accid`)!==null)??e.accids[0],o=a?r(a.attributes,`xml:id`):null,s=a&&n?[`func`,`enclose`,`place`].map(e=>[e,r(a.attributes,e)]).filter(([,e])=>e!==null).map(([e,t])=>` ${e}="${t}"`).join(``):``,c=n?`<accid${o?` xml:id="${o}"`:``} accid="${pe(t.alter)}"${s}/>`:``;if(e.selfClosing)H.push({start:e.start,end:e.end,text:c?`${xe(i)}${c}</note>`:i});else{H.push({start:e.start,end:e.start+e.tag.length,text:i+c});for(let t of e.accids)H.push({start:t.start,end:t.end,text:``})}}for(let t of d){if(!h(t.staff)||t.nested||t.textEnd<=t.textStart)continue;let n=e.slice(t.textStart,t.textEnd),[,r,i,a]=/^(\s*)([\s\S]*?)(\s*)$/.exec(n),o=ie(t.staff),s=N(o?ue(i,[o]):i,R(t.staff,Math.max(0,t.measure)));s!==i&&H.push({start:t.textStart,end:t.textEnd,text:r+s+a})}for(let e of f)H.push({start:e.start,end:e.end,text:``});for(let e of o){if(!e.initial&&!e.content){H.push({start:e.start,end:e.end,text:``});continue}H.push(...e.tagEdits);for(let t of e.keyRanges)H.push({start:t.start,end:t.end,text:``})}let U=g.filter(e=>!p.has(e));for(let e of s){if(p.has(e.n)||!U.includes(e.n))continue;let t=Se(R(e.n,0)),n=be(e.tag);if(e.selfClosing){let r=H.findIndex(t=>t.start===e.start&&t.end===e.end);r>=0&&H.splice(r,1),H.push({start:e.start,end:e.end,text:`${xe(n)}${t}</staffDef>`})}else{let n=e.clefEnd??e.start+e.tag.length;H.push({start:n,end:n,text:t})}}for(let e=1;e<F;e++){let t=U.filter(t=>{let n=R(t,e-1),r=R(t,e);return n.fifths!==r.fifths||n.mode!==r.mode});if(!t.length)continue;let n=c[e];H.push({start:n,end:n,text:`<scoreDef><staffGrp>${t.map(t=>`<staffDef n="${t}">${Se(R(t,e))}</staffDef>`).join(``)}</staffGrp></scoreDef>`})}if(!H.length)return e;H.sort((e,t)=>e.start-t.start||e.end-t.end);let ke=[],W=0;for(let t of H)t.start<W||(ke.push(e.slice(W,t.start),t.text),W=t.end);return ke.push(e.slice(W)),ke.join(``)}const Oe=[40,45,50,55,59,64],H=.08,U=1e-9;function ke(e,t={}){let n=t.tuning&&t.tuning.length?t.tuning:Oe,r=Math.max(0,Math.floor(t.capo??0)),i=Math.floor(t.maxFret??22),a=t.octaveFold??!0,o=Math.min(n.length,31),s=Math.max(0,i-r),c=new Int32Array(o);for(let e=0;e<o;e++)c[e]=n[n.length-1-e]+r;let l=Math.max(1,s),u=l+1,d=e=>{for(let t=0;t<o;t++)if(e>=c[t]&&e<=c[t]+s)return!0;return!1},f=e=>{if(Number.isFinite(e)){if(d(e))return 0;if(a)for(let t=1;t<=10;t++){if(d(e+12*t))return 12*t;if(d(e-12*t))return-12*t}}};function p(e,t,n,r){let i=e.length,a=[];if(i===0||i>o)return a;let l=new Int8Array(i),u=new Int8Array(i),d=()=>{let e=99,t=-1,n=0,r=0;for(let a=0;a<i;a++){let i=u[a];r+=l[a],i===0?n++:(i<e&&(e=i),i>t&&(t=i))}let o=t<0,s=1,c=1,d=0;o||(d=t-e,s=Math.max(1,t-3),c=Math.max(1,e),s>c&&(s=c=Math.max(1,e)));let f=i>1?l[i-1]-l[0]+1-i:0,p=-.3*n+.3*Math.max(0,t-12)**2+1*d**1.5+.5*f+.05*r,m=p+H*s;if(a.length===24&&m>=a[23].rank)return;let h={str:l.slice(),fret:u.slice(),open:o,posLo:s,posHi:c,cost:p,rank:m},g=a.length;for(;g>0&&a[g-1].rank>m;)g--;a.splice(g,0,h),a.length>24&&a.pop()},f=(a,p,m,h)=>{if(a===i){d();return}let g=e[a],_=o-(i-a);for(let e=p;e<=_;e++){if(t[a]>=0&&e!==t[a]||r&1<<e)continue;let i=g-c[e];if(i<0||i>s||n[a]>=0&&i!==n[a])continue;let o=m,d=h;i>0&&(i<o&&(o=i),i>d&&(d=i),d-o>(o>=7?5:4))||(l[a]=e,u[a]=i,f(a+1,e+1,o,d))}};return f(0,0,99,-1),a}let m=/* @__PURE__ */ new Map;function h(e,t){let n=String(t);for(let t of e)n+=`,${t.pitch}:${t.fixedT}:${t.fixedFret}`;let r=m.get(n);if(r)return r;let i=e.map((e,t)=>t),a={shapes:[],kept:[]};for(;i.length;){if(i.length<=o){let n=i.map(t=>e[t].pitch),r=i.map(t=>e[t].fixedT),o=i.map(t=>e[t].fixedFret),s=r.some(e=>e>=0),c=i.map(()=>-1),l=[];s&&(l.push([r,o,t]),t&&l.push([r,o,0])),l.push([c,c,t]),t&&l.push([c,c,0]);let u=[];for(let[e,t,r]of l)if(u=p(n,e,t,r),u.length)break;if(u.length){a={shapes:u,kept:i};break}}i=g(e,i)}return m.set(n,a),a}function g(e,t){let n=t.length,r=e=>t.filter((t,n)=>n!==e),i=t=>{let i=t[0],a=1/0;if(t.length>1&&n-1<=o){let o=Array(n-1).fill(-1);for(let n of t){let t=p(r(n).map(t=>e[t].pitch),o,o,0),s=t.length?t[0].rank:1/0;s<a&&(a=s,i=n)}}return r(i)},a=[];for(let r=1;r<n;r++)e[t[r]].pitch===e[t[r-1]].pitch&&a.push(r);if(a.length)return i(a);if(n>2){let r=t.map(t=>(e[t].pitch%12+12)%12),a=[],o=[];for(let e=1;e<n-1;e++)a.push(e),r.some((t,n)=>n!==e&&t===r[e])&&o.push(e);return i(o.length?o:a)}return r(n-1)}let _=e.map(e=>(e.pitches??[]).map(()=>({unplayable:!0}))),v=e.map(e=>{let t=[];return(e.pitches??[]).forEach((n,r)=>{let i=f(n);if(i===void 0)return;let a=n+i,l=-1,u=-1,d=e.fixed?.[r];if(d){let e=Math.floor(d.string)-1,t=d.fret!==void 0&&d.fret!==null&&Number.isFinite(d.fret),n=t?Math.floor(d.fret):a-(c[e]??NaN);e>=0&&e<o&&n>=0&&n<=s&&c[e]+n===a&&(l=e,u=t?n:-1)}t.push({pitch:a,orig:r,shifted:i,fixedT:l,fixedFret:u})}),t.sort((e,t)=>t.pitch-e.pitch||e.orig-t.orig),t.length?t:void 0}),y=new Float64Array(e.length*u),b=new Int32Array(e.length*u),x=new Int32Array(e.length*u),S=new Float64Array(u),C=new Int32Array(u),w=[],T=-1/0,E=0,D=e=>{let t=-1,n=1/0;for(let r=1,i=e*u+1;r<u;r++,i++)y[i]<n&&(n=y[i],t=r);return t},O=t=>{let n=0,r=w.length?D(w.length-1):-1;for(let i=w.length-1;i>=0&&r>=0;i--){let a=w[i];if(a.reach<=t+U)break;if(a.end<=t+U){r=x[i*u+r];continue}let o=a.plan.shapes[b[i*u+r]],s=e[a.event].durations??[];for(let e=0;e<a.plan.kept.length;e++)a.onset+(s[a.notes[a.plan.kept[e]].orig]??0)>t+U&&(n|=1<<o.str[e]);r=x[i*u+r]}return n},k=()=>{if(!w.length)return;let e=D(w.length-1);for(let t=w.length-1;t>=0&&e>=0;t--){let n=w[t],r=n.plan.shapes[b[t*u+e]],i=_[n.event];for(let e=0;e<n.plan.kept.length;e++){let t=n.notes[n.plan.kept[e]],a={string:r.str[e]+1,fret:r.fret[e]};t.shifted&&(a.shifted=t.shifted),i[t.orig]=a}e=x[t*u+e]}w=[]};for(let t=0;t<e.length;t++){let n=v[t];if(!n)continue;let r=e[t],i=Number.isFinite(r.onset)?r.onset:E,a=Math.max(0,i-T);a>=2&&k();let o=h(n,O(i));if(!o.shapes.length)continue;let s=w.length,c=s*u,d=c-u;if(s>0){let e=1+.5*a,t=1.5/e,n=2/e,r=1/0,i=-1;for(let e=1;e<u;e++){S[e]=r,C[e]=i;let t=y[d+e];r+=n,t+n<r&&(r=t+n,i=e)}r=1/0,i=-1;for(let e=u-1;e>=1;e--){let a=S[e],o=C[e];r<a&&(a=r,o=i);let s=y[d+e];r+=n,s+n<r&&(r=s+n,i=e),a+=t,s<=a?(S[e]=s,C[e]=s<1/0?e:-1):(S[e]=a,C[e]=o)}}y.fill(1/0,c,c+u),b.fill(-1,c,c+u),x.fill(-1,c,c+u);let f=o.shapes;for(let e=0;e<f.length;e++){let t=f[e],n=t.open?1:t.posLo,r=t.open?l:t.posHi;for(let i=n;i<=r;i++){let n=t.cost+H*i,r=-1;s>0&&(t.open?(n+=y[d+i],r=i):(n+=S[i],r=C[i])),n<y[c+i]&&(y[c+i]=n,b[c+i]=e,x[c+i]=r)}}let p=r.durations??[],m=0;for(let e of n)m=Math.max(m,p[e.orig]??0);w.push({event:t,plan:o,notes:n,onset:i,end:i+m,reach:Math.max(i+m,w.at(-1)?.reach??-1/0)}),E=i,T=i+m}return k(),_}function W(e,t={}){let n=e.map(()=>({continuation:!1})),r=e.map((e,t)=>t).filter(t=>{let n=e[t];return n.pitch!==null&&Number.isFinite(n.pitch)&&Number.isFinite(n.onset)}).sort((t,n)=>e[t].onset-e[n].onset||t-n),i=/* @__PURE__ */ new Map,a=/* @__PURE__ */ new Map,o=[],s=[],c=e=>e.onset+(Number.isFinite(e.duration)?Math.max(0,e.duration):0);for(let t=0;t<r.length;){let l=e[r[t]].onset,u=t;for(;u<r.length&&Math.abs(e[r[u]].onset-l)<1e-6;)u++;let d=r.slice(t,u);t=u;let f=[];for(let t of d){let r=e[t],o=r.tieStop?a.get(r.pitch):void 0;o&&(i.set(t,o),n[t].continuation=!0,f.push(t),s[o[0]][o[1]]=Math.max(s[o[0]][o[1]],c(r)))}for(let t of f)e[t].tieStart||a.delete(e[t].pitch);for(let t of f)e[t].tieStart&&a.set(e[t].pitch,i.get(t));let p,m=/* @__PURE__ */ new Map;for(let t of d){if(n[t].continuation)continue;let r=e[t],u=r.pitch;p||(p={onset:l,durations:[],pitches:[],fixed:[]},o.push(p),s.push([]));let d=o.length-1,f=m.get(u);f===void 0?(f=p.pitches.length,m.set(u,f),p.pitches.push(u),p.fixed.push(r.fixed),s[d].push(c(r))):(s[d][f]=Math.max(s[d][f],c(r)),p.fixed[f]||(p.fixed[f]=r.fixed)),i.set(t,[d,f]),r.tieStart&&a.set(u,[d,f])}}o.forEach((e,t)=>{e.durations=s[t].map(t=>t-e.onset)});let l=ke(o,t);for(let[e,[t,r]]of i)n[e].result=l[t][r];return n}const Ae={c:0,d:2,e:4,f:5,g:7,a:9,b:11},je={s:1,f:-1,n:0,x:2,ss:2,ff:-2,ts:3,tf:-3,xs:3,sx:3,nf:-1,ns:1,su:1,sd:1,fu:-1,fd:-1,nu:0,nd:0},Me={maxima:32,long:16,breve:8,1:4,2:2,4:1,8:.5,16:.25,32:.125,64:.0625,128:.03125,256:.015625},Ne=/* @__PURE__ */ new Set([`rest`,`space`,`mRest`,`mSpace`,`multiRest`]),Pe=/* @__PURE__ */ new Set([`beam`,`tuplet`]),Fe=/* @__PURE__ */ new Set([`bTrem`,`fTrem`,`ligature`,`choice`,`orig`,`reg`,`sic`,`corr`,`supplied`,`add`,`subst`]),Ie=/* @__PURE__ */ new Set([`harm`,`tempo`,`dir`,`repeatMark`,`fermata`]),Le=/* @__PURE__ */ new Set([`mRpt`,`mRpt2`,`multiRpt`]),Re=/* @__PURE__ */ new Set([...Le,`beatRpt`,`halfmRpt`]),ze=[[`c`],[`c`,`s`],[`d`],[`e`,`f`],[`e`],[`f`],[`f`,`s`],[`g`],[`a`,`f`],[`a`],[`b`,`f`],[`b`]],Be=e=>e.replace(/[&<>"]/g,``),G=(e,t)=>e?` xml:id="${Be(e)}${t}"`:``;function Ve(e,t,n){let i=Number(r(e,`dur.ppq`));if(t&&Number.isFinite(i)&&r(e,`dur.ppq`)!==null)return i/t;let a=Me[r(e,`dur`)||``];return a===void 0?0:a*(2-1/2**(Number(r(e,`dots`))||0))*n.reduce((e,t)=>e*t,1)}const He=(e,t,n)=>{let i=(r(e,`pname`)||``).toLowerCase(),a=Number(r(e,`oct`));if(!(i in Ae)||!Number.isFinite(a)||r(e,`oct`)===null)return null;let o=r(e,`accid.ges`)??t.gestural??r(e,`accid`)??t.written??``;return 12*(a+1)+Ae[i]+(je[o]??0)+n},Ue=e=>typeof e==`number`&&Number.isFinite(e)?Math.max(0,Math.min(24,Math.round(e))):0,We=e=>Array.isArray(e)&&e.length>=1&&e.length<=31&&e.every(e=>Number.isInteger(e)&&e>=0&&e<=127)?e:Oe,Ge=e=>{if(!e.size)return null;let t=Math.max(...e.keys()),n=Array.from({length:t},(n,r)=>e.get(t-r));return n.every(e=>e!==void 0)?n:null};function Ke(e,t){return`<tuning>${[...e].reverse().map((e,n)=>{let r=e+t,[i,a]=ze[(r%12+12)%12];return`<course n="${n+1}" pname="${i}" oct="${Math.floor(r/12)-1}"${a?` accid="${a}"`:``}/>`}).join(``)}</tuning>`}function qe(e,t){let n=new Set(t.generate),i=t.refret??{},a=new Set(t.sounding??[]),o=/* @__PURE__ */ new Set([...n,...Object.keys(i)]),s=new Map([...o].map(e=>[e,[]])),c=/* @__PURE__ */ new Map,l=/* @__PURE__ */ new Set,d=/* @__PURE__ */ new Set,f=/* @__PURE__ */ new Set,p=4,m=4,h=4,g=(e,t)=>{let n=Number(r(e,`${t}count`)),i=Number(r(e,`${t}unit`));n>0&&(m=n),i>0&&(h=i),p=m*4/h},_=0,v=0,y=!1,b=!1,x=null,S=0,C=null,w=0,T=[],E=null,D=!1,O=null,k=0,A=()=>{if(!O)return;let e=c.get(x);if(x in i){let t=Number(r(O.attributes,`tab.course`)),n=Number(r(O.attributes,`tab.fret`)),a=e?.courses?.get(t);O.rec.midi=a!==void 0&&Number.isInteger(n)&&n>=0&&r(O.attributes,`tab.fret`)!==null?a+n+i[x]:null}else O.rec.midi=He(O.attributes,O,e?.semi??0);O=null};return u(e,({closing:e,name:u,attributes:m,selfClosing:j})=>{if(e){if(u===`staffDef`){C?.courses.size&&(C.entry.courses=C.courses),C=null;return}if(u===`measure`){b=!1,_+=v>0&&!y?v:Math.max(v,p);return}if(!x)return;if(k){k--;return}u===`note`?A():u===`chord`||u===`tabGrp`?(E&&!D&&(w+=E.dur),E=null):u===`tuplet`?T.pop():u===`layer`?v=Math.max(v,w):u===`staff`&&--S===0&&(x=null);return}if(u===`scoreDef`){g(m,`meter.`);return}if(u===`meterSig`){g(m,``);return}if(u===`staffDef`){g(m,`meter.`);let e=r(m,`n`)||``;if(o.has(e)){let t=c.get(e),n=Number(r(m,`ppq`)),o=r(m,`trans.semi`),s={ppq:n>0?n:t?.ppq,semi:a.has(e)?0:o===null?t?.semi??0:Number(o)||0,courses:t?.courses};c.set(e,s),e in i&&!j&&(C={entry:s,courses:/* @__PURE__ */ new Map})}return}if(u===`course`&&C){let e=Number(r(m,`n`)),t=He(m,{},0);e>=1&&t!==null&&C.courses.set(e,t);return}if(u===`measure`){b=!0,v=0,y=!1;return}if(u===`tie`&&b){let e=(r(m,`startid`)||``).replace(/^#/,``),t=(r(m,`endid`)||``).replace(/^#/,``);e&&t&&(l.add(e),d.add(t));return}if(u===`staff`&&!x){let e=r(m,`n`)||``;o.has(e)&&!j&&(x=e,S=1);return}if(!x)return;if(k){j||k++;return}if(!j&&u===`staff`){S++;return}let M=s.get(x),N=c.get(x)?.ppq;if(u===`layer`){w=0;return}if(u===`graceGrp`){j||(k=1);return}if(u===`tuplet`){let e=Number(r(m,`num`))||1,t=Number(r(m,`numbase`))||1;j||T.push(t/e);return}if(u===`chord`||u===`tabGrp`){if(D=r(m,`grace`)!==null,D){j||(k=1);return}E={onset:_+w,dur:Ve(m,N,T),notes:[]},M.push(E);let e=r(m,`xml:id`);e&&n.has(x)&&f.add(e),j&&(w+=E.dur,E=null);return}if(u===`note`){if(!E&&r(m,`grace`)!==null){j||(k=1);return}let e=E;e||(e={onset:_+w,dur:Ve(m,N,T),notes:[]},M.push(e),w+=e.dur);let i=r(m,`xml:id`)||``;i&&n.has(x)&&f.add(i);let a=r(m,`tie`)||``,o=Number(r(m,`tab.course`)),s=Number(r(m,`tab.fret`)),c=Number.isInteger(s)&&r(m,`tab.fret`)!==null,l={id:i,midi:null,fixed:t.fixed&&n.has(x)&&Number.isInteger(o)&&o>=1?c?{string:o,fret:s}:{string:o}:void 0,continuation:/[mt]/.test(a),tieStart:/[im]/.test(a),dur:e.dur};e.notes.push(l),O={rec:l,attributes:m,event:e,inChord:!!E},j&&A();return}if(u===`accid`&&O){let e=r(m,`accid`),t=r(m,`accid.ges`);e!==null&&(O.written=e),t!==null&&(O.gestural=t);return}(Ne.has(u)||Re.has(u))&&(u===`mRest`||u===`mSpace`||u===`multiRest`||Le.has(u)?y=!0:w+=u===`halfmRpt`?p/2:u===`beatRpt`?4/h:Ve(m,N,T))}),{staves:s,tieStarts:l,tieEnds:d,info:c,ids:f}}function Je(e,t,n,r,i,a){let o=/* @__PURE__ */ new Map,s=We(i.tuning),c=Ue(i.capo);for(let[l,u]of e){let e=[],d=[];for(let r of u)for(let i of r.notes)e.push(i),d.push({onset:r.onset,duration:i.dur,pitch:i.midi,tieStart:i.tieStart||t.has(i.id),tieStop:i.continuation||n.has(i.id),fixed:a?.get(i.id)??i.fixed});let f=l in(i.refret??{})&&r.get(l)?.courses?Ge(r.get(l).courses):null;W(d,f?{tuning:f,capo:0}:{tuning:s,capo:c}).forEach(({result:t,continuation:n},r)=>{let i=e[r];if(i.continuation=n,t){if(n){i.held=t;return}o.set(i.id,t),a&&i.id&&`string`in t&&!a.has(i.id)&&a.set(i.id,{string:t.string,fret:t.fret})}})}return o}const Ye=e=>[`dur`,`dots`,`dur.ppq`].map(t=>{let n=r(e,t);return n===null?``:` ${t}="${n}"`}).join(``),Xe=(e,t)=>t&&`string`in t?`<note${G(e,``)} tab.course="${t.string}" tab.fret="${t.fret}"/>`:``,Ze=e=>e&&`string`in e?`<note tab.course="${e.string}" tab.fret="${e.fret}" visible="false"/>`:``,K=(e,t,n)=>{let r=RegExp(`(\\s${t.replace(`.`,`\\.`)}\\s*=\\s*)(?:"[^"]*"|'[^']*')`);return r.test(e)?e.replace(r,`$1"${n}"`):e.replace(/\s*(\/?)>$/,` ${t}="${n}"$1>`)};function Qe(e,t,n){let i=new Set(t.generate),a=t.refret??{},o=t.retarget,s=Object.keys(o).length>0;if(!i.size&&!s&&!Object.keys(a).length)return e;let c=i.size||Object.keys(a).length,{staves:l,tieStarts:d,tieEnds:f,info:p,ids:m}=c?qe(e,t):{staves:/* @__PURE__ */ new Map,tieStarts:/* @__PURE__ */ new Set,tieEnds:/* @__PURE__ */ new Set,info:/* @__PURE__ */ new Map,ids:/* @__PURE__ */ new Set},h=c?Je(l,d,f,p,t,n):/* @__PURE__ */ new Map,g=/* @__PURE__ */ new Map;for(let e of l.values())for(let t of e)for(let e of t.notes)e.continuation&&g.set(e.id,e.held);let _=We(t.tuning),v=Ke(_,Ue(t.capo)),y=new Set([...i].map(e=>String(100+Number(e)))),b=[],x=0,S=-1,C=!1,w=0,T=null,E=null,D=0,O=0,k=null,A=-1,j=(e,t,n)=>{let r=p.get(e)?.ppq;return`<staffDef${G(t,`-tab`)} n="${100+Number(e)}" lines="${_.length}" notationtype="tab.guitar" keysig="0"${r?` ppq="${r}"`:``}><clef shape="TAB" line="${_.length-1}"/>${v}${n}</staffDef>`};return u(e,({closing:t,name:n,attributes:c,selfClosing:l,index:u,length:d})=>{b.push(e.slice(x,u)),x=u+d;let f=e.slice(u,u+d);if(t?w--:l||w++,!t&&Ie.has(n)&&s){let e=r(c,`staff`);if(e!==null){let t=e.split(/\s+/).filter(Boolean).map(e=>o[e]??e).join(` `);if(t!==e){f=K(f,`staff`,t);let e=r(c,`startid`)?.replace(/^#/,``)??``;e&&m.has(e)&&t.split(` `).every(e=>y.has(e))&&(f=K(f,`startid`,`#${e}-tab`))}}}if(A<0&&n===`staff`&&!t&&!l&&(r(c,`n`)||``)in a)A=w;else if(A>=0&&t&&n===`staff`&&w===A-1)A=-1;else if(A>=0&&n===`note`&&!t){let e=r(c,`xml:id`)||``,t=g.has(e)?g.get(e):h.get(e);t&&`string`in t?f=K(K(f,`tab.course`,String(t.string)),`tab.fret`,String(t.fret)):t&&(f=K(f,`visible`,`false`))}if(b.push(f),n===`scoreDef`&&!t&&!C&&S<0){l?C=!0:S=w;return}if(n===`scoreDef`&&t&&S>=0&&w===S-1){S=-1,C=!0;return}if(S>=0){if(n===`staffDef`&&!t){let e=r(c,`n`)||``;if(!i.has(e))return;let t=r(c,`xml:id`)||``;if(l){b.push(j(e,t,``));return}T={n:e,id:t,meterSig:``,depth:w};return}if(T&&n===`meterSig`&&!t){T.meterSig=f.replace(/\sxml:id\s*=\s*"[^"]*"/,``).replace(/\s*\/?>$/,`/>`);return}T&&n===`staffDef`&&t&&w===T.depth-1&&(b.push(j(T.n,T.id,T.meterSig)),T=null);return}if(!E){if(n===`staff`&&!t&&!l&&i.has(r(c,`n`)||``)){let e=r(c,`n`);E=[`<staff${G(r(c,`xml:id`)||``,`-tab`)} n="${100+Number(e)}">`],D=w,O=0,k=null}return}if(t&&n===`staff`&&w===D-1){E.push(`</staff>`),b.push(E.join(``)),E=null;return}if(O){t?O--:l||O++;return}let p=r(c,`xml:id`)||``;if(t){n===`layer`||Pe.has(n)?E.push(`</${n}>`):n===`chord`&&k&&(k.frets||E.push(Ze(k.held)),E.push(`</tabGrp>`),k=null);return}if(n===`layer`||Pe.has(n)){let e=[`n`,`num`,`numbase`,`num.visible`,`bracket.visible`,`num.format`,`bracket.place`,`num.place`].map(e=>{let t=r(c,e);return t===null?``:` ${e}="${t}"`}).join(``);E.push(`<${n}${G(p,`-tab`)}${e}${l?`/>`:`>`}`);return}if(!Fe.has(n)){if(n===`chord`){if(r(c,`grace`)!==null){l||(O=1);return}E.push(`<tabGrp${G(p,`-tab`)}${Ye(c)}><tabDurSym/>`),l?E.push(`</tabGrp>`):k={frets:0};return}if(n===`note`){if(l||(O=1),k){if(g.has(p)){k.held||(k.held=g.get(p));return}let e=Xe(p?`${p}-tab`:``,h.get(p));e&&k.frets++,E.push(e);return}if(r(c,`grace`)!==null)return;E.push(`<tabGrp${G(p,`-tab`)}${Ye(c)}><tabDurSym/>${g.has(p)?Ze(g.get(p)):Xe(p?`${p}-tabn`:``,h.get(p))}</tabGrp>`);return}if(Ne.has(n)||Re.has(n)){l||(O=1);let e=Re.has(n)?c.replace(/\s+xml:id\s*=\s*(?:"[^"]*"|'[^']*')/,``).trimEnd():Ye(c);E.push(`<${n}${G(p,`-tab`)}${e}/>`);return}l||(O=1)}}),b.push(e.slice(x)),b.join(``)}const $e=e=>`reader-m${e+1}`,et=`(?:[^>"']|"[^"]*"|'[^']*')*`,q=RegExp(`<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<\\?[\\s\\S]*?\\?>|<(/?)(part|measure|attributes|lyric|slur|wedge|octave-shift|pedal|bracket|dashes|tuplet|glissando|slide|ending|beam)(?=[\\s/>])(${et})>`,`g`),tt=/* @__PURE__ */ new Map;function J(e,t){if(!e.includes(t))return;let n=tt.get(t);n||tt.set(t,n=RegExp(`\\s${t}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`));let r=n.exec(e);return r?r[1]??r[2]:void 0}const nt=/* @__PURE__ */ new Set([`start`,`up`,`down`,`crescendo`,`diminuendo`]);function rt(e){let t=/<score-partwise[\s>]/.exec(e),n=e.indexOf(`</part-list>`);if(!t||n<0)return;let r=[],i=[],a=/* @__PURE__ */ new Map,o=``,s,c=-1,l=-1,u=0,d=/* @__PURE__ */ new Set,f=0,p=-1;q.lastIndex=n;for(let t=q.exec(e);t;t=q.exec(e)){let n=t[2];if(!n)continue;let m=t[1]===`/`,h=t[3]||``,g=h.endsWith(`/`);if(n===`part`){if(m){if(!s||c>=0)return;s=void 0,p=t.index+t[0].length}else{if(s||g)return;r.length||(o=e.slice(0,t.index)),s={open:t[0],measures:[],attributes:[]},r.push(s),l=-1}continue}if(!s)continue;if(n===`measure`){if(m){if(c<0)return;s.measures.push(c,t.index+t[0].length),c=-1,u&&(f=Math.max(f,Math.ceil(u/Math.max(1,d.size))))}else{if(c>=0)return;l++,u=0,d=/* @__PURE__ */ new Set,g?s.measures.push(t.index,t.index+t[0].length):c=t.index}continue}if(c<0||m)continue;if(n===`attributes`){if(g)continue;let n=e.indexOf(`</attributes>`,t.index);if(n<0)return;let r=n+13;s.attributes.push({measure:l,block:e.slice(t.index,r),leading:!/<note(?=[\s/>])/.test(e.slice(c,t.index))}),q.lastIndex=r;continue}if(n===`lyric`){u++,d.add(J(h,`number`)||`1`);continue}let _;if(n===`beam`){let t=/^\s*(begin|end)\b/.exec(e.slice(q.lastIndex,q.lastIndex+16))?.[1];_=t===`begin`?`open`:t===`end`?`close`:void 0}else{let e=J(h,`type`)||``;_=nt.has(e)?`open`:e===`stop`||n===`ending`&&e===`discontinue`?`close`:void 0}if(!_)continue;let v=`${r.length}:${n}:${n===`ending`?``:J(h,`number`)||`1`}`;if(_===`open`)a.set(v,l);else{let e=a.get(v);e!==void 0&&(a.delete(v),l>e&&i.push({start:e,end:l}))}}if(!r.length||s||c>=0)return;let m=r[0].measures.length/2;if(m)return i.sort((e,t)=>e.start-t.start),{text:e,head:o,tail:e.slice(p),parts:r,measureCount:m,lyricDensity:f,spans:i}}const it=[`divisions`,`key`,`time`,`staves`,`part-symbol`,`instruments`,`clef`,`staff-details`,`transpose`,`for-part`],Y=RegExp(`<(${it.join(`|`)})(?=[\\s/>])(${et})>`,`g`);function at(e,t){let n=/* @__PURE__ */ new Map;for(let{measure:r,block:i}of e.attributes){if(r>=t)break;Y.lastIndex=0;for(let e=Y.exec(i);e;e=Y.exec(i)){let[t,r,a]=e,o=t;if(!a.endsWith(`/`)){let t=i.indexOf(`</${r}>`,Y.lastIndex);if(t<0)continue;o=i.slice(e.index,t+r.length+3),Y.lastIndex=t+r.length+3}let s=J(a,`number`)??(r===`clef`?`1`:void 0);if(s===void 0)for(let e of[...n.keys()])e.startsWith(`${r}#`)&&n.delete(e);n.set(`${r}#${s??``}`,o)}}for(let{measure:r,block:i,leading:a}of e.attributes)if(r===t&&a)for(let[,e]of i.matchAll(/<key(?=[\s/>])((?:[^>"']|"[^"]*"|'[^']*')*)>/g)){let t=J(e,`number`);for(let e of[...n.keys()])e.startsWith(`key#`)&&(t===void 0||e===`key#${t}`||e===`key#`)&&n.delete(e)}if(!n.size)return``;let r=[];for(let e of it)for(let[t,i]of n)t.startsWith(`${e}#`)&&r.push(e===`time`?i.replace(/^<time\b((?:[^>"']|"[^"]*"|'[^']*')*)/,(e,t)=>`<time print-object="no"${t.replace(/\sprint-object\s*=\s*(?:"[^"]*"|'[^']*')/,``)}`):i);return`<attributes>${r.join(``)}</attributes>`}function ot(e,t,n,r){let i=t.measures[n*2],a=t.measures[n*2+1],o=e.text.slice(i,a),s=/^<measure\b(?:[^>"']|"[^"]*"|'[^']*')*>/.exec(o)[0].length,c=o.slice(0,s),l=` id="${$e(n)}"`;return c=/\sid\s*=\s*(?:"[^"]*"|'[^']*')/.test(c)?c.replace(/\sid\s*=\s*(?:"[^"]*"|'[^']*')/,l):c.replace(/\s*(\/?)>$/,`${l}$1>`),c.endsWith(`/>`)?r?`${c.slice(0,-2)}>${r}</measure>`:c:c+r+o.slice(s)}function st(e,t,n){let r=[t>0?e.head.replace(/<credit\b[\s\S]*?<\/credit>/g,``):e.head];for(let i of e.parts){r.push(i.open);let a=Math.min(n,i.measures.length/2);for(let n=t;n<a;n++)r.push(ot(e,i,n,n===t&&t>0?at(i,t):``));r.push(`</part>`)}return r.push(e.tail),r.join(``)}function ct(e,t){let n=t-1;for(let r of e.spans){if(r.start>=t)break;r.end>=t&&(n=Math.min(n,r.start))}return Math.max(0,Math.min(t,16,t-n))}function lt(e,t){let n=t;for(let r of e.spans){if(r.start>=t)break;r.end>=t&&(n=Math.max(n,r.end))}return Math.max(0,Math.min(e.measureCount-t,16,n-t+1))}function ut(e,t,n,r,i){let a=e.measureCount;if(n<=0)return{from:0,to:a,firstSystem:0,endSystem:1,firstPage:1};let o=Math.ceil(a/n),s=Math.max(1,Math.floor(i/Math.max(1,r*n))),c=Math.floor(Math.max(0,Math.min(o-1,t))/s)*s,l=Math.min(o,c+s),u=c*n,d=Math.min(a,l*n),f=ct(e,u),p=d<a?lt(e,d):0,m=u-f,h=f?Math.ceil(u/n)-Math.floor(m/n)+1:1;return{from:m,to:d+p,firstSystem:c,endSystem:l,firstPage:h}}const dt=[`breaks`,`transpose`,`transposeToSoundingPitch`,`xmlIdChecksum`];let ft,pt,mt;function ht(){return pt??=(async()=>{if(!ft)throw Error(`The notation renderer was not told where to load Verovio from.`);let{module:e,toolkit:t}=ft;try{let[n,r]=await Promise.all([import(
|
|
2
|
+
/* @vite-ignore */
|
|
3
|
+
e),import(
|
|
4
|
+
/* @vite-ignore */
|
|
5
|
+
t)]);if(typeof n.default!=`function`||typeof r.VerovioToolkit!=`function`||typeof r.enableLogToBuffer!=`function`)throw Error(`not a compatible Verovio build`);return mt={createModule:n.default,Toolkit:r.VerovioToolkit,enableLogToBuffer:r.enableLogToBuffer}}catch(n){throw pt=void 0,new St(`Could not load Verovio from ${e} and ${t}: ${n instanceof Error?n.message:String(n)}`,void 0)}})()}let X,gt;function _t(){if(X)return X;let e=ht().then(e=>e.createModule()).then(e=>(mt.enableLogToBuffer(1,e),gt=e,e)).catch(t=>{throw X===e&&(X=void 0),t});return X=e}const vt=async()=>{let e=await _t();return new mt.Toolkit(e)};let yt,bt,Z;const Q=/* @__PURE__ */ new Map,xt=[];var St=class extends Error{code;constructor(e,t){super(e),this.code=t}};function Ct(e){for(let e of[yt,bt])try{e?.destroy()}catch{}yt=bt=void 0,Z=void 0,e&&(X=void 0,gt=void 0)}async function wt(e){return e===`main`?yt??=await vt():bt??=await vt()}function Tt(){let e=gt;return e?.HEAPU8?.length??e?.wasmMemory?.buffer.byteLength}function Et(e){let t=Q.get(e);if(!t)throw new St(`The score is no longer loaded in the renderer.`,`missing`);return Q.delete(e),Q.set(e,t),t}function $(e,t,n){if(e.resetOptions(),e.setOptions(n),!e.loadData(t))throw Error(`Verovio could not import this score.`)}const Dt={breaks:`none`,inputFrom:`auto`,xmlIdChecksum:!0};async function Ot(e){let t=await vt();try{return $(t,e,Dt),t.getMEI()}finally{try{xt.push(t.getLog()||``)}catch{}try{t.destroy()}catch{}}}async function kt(e,t,n){let r=`${t}-${n}`,i=e.meis.get(r);if(i!==void 0)return e.meis.delete(r),e.meis.set(r,i),i;for(i=await Ot(st(e.index,t,n)),e.meis.set(r,i);e.meis.size>8;)e.meis.delete(e.meis.keys().next().value);return i}async function At(e,t){let n=await vt();try{return $(n,e,{breaks:`none`,xmlIdChecksum:!0,...t}),n.getMEI()}finally{try{xt.push(n.getLog()||``)}catch{}try{n.destroy()}catch{}}}const jt=(e,t,n=0)=>Ee(e,t,At,n);async function Mt(e,t){if(!t)return e.mei;let n=JSON.stringify(t);return e.spelled?.key!==n&&(e.spelled={key:n,mei:await jt(e.mei,t)}),e.spelled.mei}async function Nt(e,t){let n=await Mt(e,t.spelling);if(!t.tab)return n;let r=JSON.stringify([t.spelling??null,t.tab]);return e.tabbed?.key!==r&&(e.tabbed={key:r,mei:Qe(n,t.tab)}),e.tabbed.mei}async function Pt(e,t,n,r){let i=await Ft(e,t,n,r.spelling);if(!r.tab)return i;let a=JSON.stringify([r.spelling??null,r.tab]),o=e.frets.get(a);if(!o)for(o=/* @__PURE__ */ new Map,e.frets.set(a,o);e.frets.size>4;)e.frets.delete(e.frets.keys().next().value);return Qe(i,r.tab,o)}async function Ft(e,t,n,r){let i=await kt(e,t,n);if(!r||!Te(i,r))return i;let a=`${t}-${n}|${JSON.stringify(r)}`,o=e.spelled.get(a);if(o!==void 0)return e.spelled.delete(a),e.spelled.set(a,o),o;for(o=await jt(i,r,t),e.spelled.set(a,o);e.spelled.size>8;)e.spelled.delete(e.spelled.keys().next().value);return o}const It=(e,t)=>Object.fromEntries(t.map(t=>[t,e[t]??null]));async function Lt(e,t,n,r){let i=JSON.stringify([...e,t,It(n,dt)]),a=JSON.stringify(n),o=await wt(`main`);return Z?.loadKey===i?Z.optionsKey!==a&&(Z=void 0,o.resetOptions(),o.setOptions(n),o.redoLayout(),Z={loadKey:i,optionsKey:a}):(Z=void 0,$(o,await r(),n),Z={loadKey:i,optionsKey:a}),o}function Rt(e,t,n){return Math.min(n,Math.max(t*2,Ht(e,t,t*4)+1))}const zt=/\s(?:endid|tstamp2)\s*=\s*"([^"]*)"/g,Bt=/\sxml:id\s*=\s*"([^"]*)"/,Vt=/<measure\b/g;function Ht(e,t,n){let r=[];Vt.lastIndex=0;for(let t=Vt.exec(e);t&&r.length<=n;t=Vt.exec(e))r.push(t.index);let i=/* @__PURE__ */ new Set,a=0;for(let n=0;n+1<r.length;n++){let o=e.slice(r[n],r[n+1]);if(n<t)for(let[,e]of o.matchAll(zt)){let t=/^(\d+)m\+/.exec(e);t?a=Math.max(a,n+Number(t[1])):i.add(e.replace(/^#/,``))}else if(i.size)for(let e of o.match(/<[^>]*\sxml:id\s*=\s*"[^"]*"[^>]*>/g)||[]){let t=Bt.exec(e)?.[1];t&&i.delete(t)&&(a=Math.max(a,n))}if(n>=t&&!i.size)break}return Math.min(n-1,a)}async function Ut(e,t,n){let r=new TextDecoder().decode(t),i=rt(r),a;if(i&&(n||i.parts.length*i.measureCount>=2400)){let{staffDefs:e,groups:t}=d(await Ot(st(i,0,1)));a={kind:`chunked`,index:i,info:{measureIds:Array.from({length:i.measureCount},(e,t)=>$e(t)),lyricDensity:i.lyricDensity,staffDefs:e,groups:t,chunked:!0},meis:/* @__PURE__ */ new Map,spelled:/* @__PURE__ */ new Map,frets:/* @__PURE__ */ new Map}}else{let e=await wt(`main`);Z=void 0,$(e,r,Dt);let t=e.getMEI();a={kind:`whole`,mei:t,info:d(t)}}for(Q.delete(e),Q.set(e,a);Q.size>12;)Q.delete(Q.keys().next().value);return a.info}function Wt(e,t,n){let r=e.renderToSVG(t),i=/<svg\b[^>]*?\sid="([^"]+)"/.exec(r)?.[1];return!i||!/^[\w-]+$/.test(i)?r:r.replace(RegExp(`(?<=[#"-])${i}(?![\\w-])`,`g`),`${i}-c${n}`)}const Gt=(e,t)=>{let n=new Set(t.hiddenStaves);return Math.max(1,e.staffDefs.filter(e=>!n.has(e.n)).length+(t.tab?.generate.length??0))};async function Kt(e){if(e.kind===`import`)return Ut(e.revision,e.bytes,!!e.chunking?.force);if(e.kind===`release`)return Q.delete(e.revision),null;if(e.simulateOom)throw await new Promise(e=>setTimeout(e,300)),RangeError(`Cannot enlarge memory arrays (simulated).`);let t=Et(e.revision);if(e.kind===`probe`){let n=await wt(`probe`);if(t.kind===`chunked`){let r=t.index.measureCount,i=Math.min(r,e.measures*2),a=e.measures>=r?r:i+lt(t.index,i);return $(n,m(await Pt(t,0,a,e.view),e.view),e.options),{svg:Wt(n,1,e.channel),pageCount:n.getPageCount(),measures:a}}let{info:r}=t,i=await Nt(t,e.view),a=e.measures>=r.measureIds.length?r.measureIds.length:Rt(i,e.measures,r.measureIds.length);return $(n,m(i,e.view,a),e.options),{svg:Wt(n,1,e.channel),pageCount:n.getPageCount(),measures:a}}if(t.kind===`whole`){let n=await Lt([e.revision],e.view,e.options,async()=>m(await Nt(t,e.view),e.view)),r=n.getPageCount();return{pageCount:r,pages:e.pages.filter(e=>e>=1&&e<=r).map(t=>({page:t,svg:Wt(n,t,e.channel)}))}}let n=e.view.breakEvery,r=n>0?Math.ceil(t.index.measureCount/n):1,i=/* @__PURE__ */ new Map;for(let a of e.pages){if(a<1||a>r)continue;let o=ut(t.index,a-1,n,Gt(t.info,e.view),e.chunkBudget),s=`${o.from}-${o.to}`;(i.get(s)??i.set(s,{plan:o,pages:[]}).get(s)).pages.push(a)}let a=[];for(let{plan:n,pages:r}of i.values()){let i=await Lt([e.revision,n.from,n.to],e.view,e.options,async()=>m(await Pt(t,n.from,n.to,e.view),e.view,1/0,n.from)),o=i.getPageCount();for(let t of r){let r=n.firstPage+(t-1-n.firstSystem);if(r>o)throw Error(`A score chunk laid out ${o} pages where ${r} were expected.`);a.push({page:t,svg:Wt(i,r,e.channel)})}}return{pageCount:r,pages:a}}function qt(e){if(e instanceof St)return{message:e.message,code:e.code};let t=e instanceof Error?`${e.name}: ${e.message}`:String(e),n=globalThis.WebAssembly?.Exception;return n&&e instanceof n||/out of memory|OOM|Cannot enlarge memory|allocation failed|RangeError/i.test(t)?{message:`This score is too large for the notation renderer on this device (it ran out of memory).`,code:`oom`}:{message:e instanceof Error?e.message:String(e)}}function Jt(e){let t=xt.splice(0).join(``);try{t+=(yt??bt)?.getLog()||``}catch{}if(!t)return;let n=t.split(`
|
|
6
|
+
`).filter(Boolean),r=n.filter(e=>e.startsWith(`[Error]`)).length;console.warn(`Verovio ${e}: ${n.length} log message${n.length===1?``:`s`} (${r} error${r===1?``:`s`})${n.length>12?`, first 12`:``}:\n${n.slice(0,12).join(`
|
|
7
|
+
`)}`)}const Yt=[],Xt=/* @__PURE__ */ new Map;let Zt=!1;const Qt=e=>self.postMessage(e);async function $t(){let e=Yt.shift();if(!e){Zt=!1;return}if(e.kind!==`import`&&e.kind!==`release`&&e.ticket<(Xt.get(e.channel)??0))Qt({id:e.id,error:`Superseded score render.`,code:`superseded`});else try{let t=await Kt(e);Jt(e.kind),Qt({id:e.id,value:t,heap:Tt()})}catch(t){Jt(e.kind);let{message:n,code:r}=qt(t);r!==`missing`&&Ct(r===`oom`||!(t instanceof Error&&t.message===`Verovio could not import this score.`)),Qt({id:e.id,error:n,code:r,heap:Tt()})}setTimeout(()=>void $t(),0)}self.onmessage=e=>{let t=e.data;if(t.kind===`configure`){ft=t.files;return}(t.kind===`probe`||t.kind===`render`)&&Xt.set(t.channel,Math.max(Xt.get(t.channel)??0,t.ticket)),Yt.push(t),Zt||(Zt=!0,setTimeout(()=>void $t(),0))};
|
package/dist/audio.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pepperscore/audio: the reader's audio engine as a small, framework-free API (no React), so other apps on the page
|
|
3
|
+
* (a piano visualiser, a practice tool) share one AudioContext, one "who is playing" slot and the same sounds.
|
|
4
|
+
*
|
|
5
|
+
* - getSharedAudio(): the page's AudioContext and master compressor (null without Web Audio). resumeAudio(context)
|
|
6
|
+
* resumes it with a bounded wait (call it from a user gesture).
|
|
7
|
+
* - claimPlayback(owner) / releasePlayback(owner): one player at a time. Claiming stops the previous owner (a
|
|
8
|
+
* PepperScore reader, or your own `{ stop() }`); PepperScore claims it when it starts playing.
|
|
9
|
+
* - loadInstrument(program | name | 'drums', options) / loadDrumKit(options): an AudioPlayer through pepperscore's sound
|
|
10
|
+
* resolution (soundSources, the pack's FluidR3 sound, TimGM6mb.sf2; drums from Perfect Drums plus TimGM6mb's kit).
|
|
11
|
+
* - createMetronome({ voice: 'woodblock' | 'drum-machine' | 'click', gain }).
|
|
12
|
+
*
|
|
13
|
+
* Everything not exported here is internal.
|
|
14
|
+
*/
|
|
15
|
+
export { getSharedAudio, resumeAudio, claimPlayback, releasePlayback } from './lib/audio-engine';
|
|
16
|
+
export type { SharedAudio, PlaybackOwner } from './lib/audio-engine';
|
|
17
|
+
export { loadInstrument, loadDrumKit, createMetronome } from './lib/instruments';
|
|
18
|
+
export type { Instrument, InstrumentName, InstrumentPlan, InstrumentOptions, Metronome, MetronomeOptions } from './lib/instruments';
|
|
19
|
+
export { METRONOME_VOICES } from './lib/metronome';
|
|
20
|
+
export type { MetronomeVoice } from './lib/metronome';
|
|
21
|
+
export type { AudioPlayer } from './lib/sound-players';
|
|
22
|
+
export type { SoundSource, SoundPlan } from './lib/sounds';
|
|
23
|
+
export type { SoundPackName } from './lib/assets';
|
|
24
|
+
export { SOUNDS_VERSION, defaultAssetBaseUrl } from './lib/assets';
|
package/dist/audio.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { a as e, c as t, d as n, f as r, g as i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f } from "./sound-players-DdLBBZaR.js";
|
|
2
|
+
//#region src/lib/metronome.ts
|
|
3
|
+
var p = [
|
|
4
|
+
"woodblock",
|
|
5
|
+
"drum-machine",
|
|
6
|
+
"click"
|
|
7
|
+
], m = 112, h = 78, g = (e) => e === "woodblock" ? [76, 77] : e === "drum-machine" ? [36, 42] : [];
|
|
8
|
+
function _(e, t, { accent: n = t === 0, covers: r } = {}) {
|
|
9
|
+
let i = n ? m : h;
|
|
10
|
+
if (e === "woodblock") {
|
|
11
|
+
let e = n ? 76 : 77;
|
|
12
|
+
return r?.(e) ? [{
|
|
13
|
+
kind: "note",
|
|
14
|
+
note: e,
|
|
15
|
+
velocity: i
|
|
16
|
+
}] : [{
|
|
17
|
+
kind: "knock",
|
|
18
|
+
accent: n
|
|
19
|
+
}];
|
|
20
|
+
}
|
|
21
|
+
if (e === "drum-machine") {
|
|
22
|
+
let e = n ? 36 : 42;
|
|
23
|
+
return r?.(e) ? [{
|
|
24
|
+
kind: "note",
|
|
25
|
+
note: e,
|
|
26
|
+
velocity: i
|
|
27
|
+
}] : [{
|
|
28
|
+
kind: "tick",
|
|
29
|
+
accent: n
|
|
30
|
+
}];
|
|
31
|
+
}
|
|
32
|
+
return [{
|
|
33
|
+
kind: "tick",
|
|
34
|
+
accent: n
|
|
35
|
+
}];
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/lib/instruments.ts
|
|
39
|
+
var v = Array.from({ length: 88 }, (e, t) => 21 + t), y = () => typeof document < "u" && document.baseURI || "http://localhost/";
|
|
40
|
+
function b(e) {
|
|
41
|
+
if (e === "drums" || e === "drum-kit") return { drums: !0 };
|
|
42
|
+
let t = typeof e == "number" ? Number.isInteger(e) ? i[e - 1] : void 0 : i.find((t) => t.soundfont === e);
|
|
43
|
+
if (!t) throw Error(`pepperscore/audio: unknown instrument ${JSON.stringify(e)} (use a GM program 1-128, a FluidR3 name or 'drums').`);
|
|
44
|
+
return {
|
|
45
|
+
drums: !1,
|
|
46
|
+
program: t.program,
|
|
47
|
+
name: t.soundfont
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function x(e) {
|
|
51
|
+
if (e.context) return {
|
|
52
|
+
context: e.context,
|
|
53
|
+
destination: e.destination ?? e.context.destination
|
|
54
|
+
};
|
|
55
|
+
let t = r();
|
|
56
|
+
if (!t) throw Error("pepperscore/audio: Web Audio is not available on this device.");
|
|
57
|
+
return {
|
|
58
|
+
context: t.context,
|
|
59
|
+
destination: e.destination ?? t.master
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function S(n, r = {}) {
|
|
63
|
+
let i = b(n), { context: o, destination: c } = x(r), l = a(r.assetBaseUrl, r.soundPack ?? "core"), d = await t(l), p = e(i, {
|
|
64
|
+
sources: r.sources,
|
|
65
|
+
fluidr3: d.fluidr3,
|
|
66
|
+
base: l,
|
|
67
|
+
page: y()
|
|
68
|
+
}), m = o.createGain();
|
|
69
|
+
m.connect(c);
|
|
70
|
+
let h;
|
|
71
|
+
try {
|
|
72
|
+
h = await s(o, p, m);
|
|
73
|
+
} catch (e) {
|
|
74
|
+
throw m.disconnect(), e;
|
|
75
|
+
}
|
|
76
|
+
let g = !1, _ = Promise.resolve(), S = async (e) => {
|
|
77
|
+
if (await Promise.all(h.map((t) => t.loadNotes?.(e))), p.kind === "note-files" && p.drums) {
|
|
78
|
+
let t = _.then(async () => {
|
|
79
|
+
if (g) return;
|
|
80
|
+
let t = h, n = t.length;
|
|
81
|
+
await f(o, t, e, u(l), m), g && t.slice(n).forEach((e) => e.dispose());
|
|
82
|
+
});
|
|
83
|
+
_ = t.catch(() => {}), await t;
|
|
84
|
+
}
|
|
85
|
+
}, C = {
|
|
86
|
+
context: o,
|
|
87
|
+
output: m,
|
|
88
|
+
plan: {
|
|
89
|
+
kind: p.kind,
|
|
90
|
+
sourceId: p.sourceId
|
|
91
|
+
},
|
|
92
|
+
loadNotes: S,
|
|
93
|
+
covers: (e) => h.some((t) => t.covers?.(e) ?? !0),
|
|
94
|
+
start: (e) => {
|
|
95
|
+
let t = [];
|
|
96
|
+
for (let n of h) try {
|
|
97
|
+
t.push(n.start({
|
|
98
|
+
...e,
|
|
99
|
+
destination: e.destination ?? m
|
|
100
|
+
}));
|
|
101
|
+
} catch {}
|
|
102
|
+
return () => t.forEach((e) => e());
|
|
103
|
+
},
|
|
104
|
+
stop: () => h.forEach((e) => e.stop()),
|
|
105
|
+
dispose: () => {
|
|
106
|
+
g = !0, h.forEach((e) => e.dispose()), h = [], m.disconnect();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
try {
|
|
110
|
+
await S(r.notes ?? (i.drums ? [] : v));
|
|
111
|
+
} catch (e) {
|
|
112
|
+
throw C.dispose(), e;
|
|
113
|
+
}
|
|
114
|
+
return C;
|
|
115
|
+
}
|
|
116
|
+
var C = (e = {}) => S("drums", e), w = 1e4, T = {
|
|
117
|
+
knock: {
|
|
118
|
+
frequency: [740, 1040],
|
|
119
|
+
drop: .6,
|
|
120
|
+
decay: .07,
|
|
121
|
+
level: [.5, .7],
|
|
122
|
+
type: "triangle"
|
|
123
|
+
},
|
|
124
|
+
tick: {
|
|
125
|
+
frequency: [1800, 2400],
|
|
126
|
+
drop: 1,
|
|
127
|
+
decay: .025,
|
|
128
|
+
level: [.18, .28],
|
|
129
|
+
type: "sine"
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
async function E(e = {}) {
|
|
133
|
+
let { context: t, destination: n } = x(e), r = t.createGain();
|
|
134
|
+
r.gain.value = Math.max(0, Math.min(1, e.gain ?? .5)), r.connect(n);
|
|
135
|
+
let i = e.voice ?? "woodblock", a = null, o = null, s = !1, c = -Infinity, l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set(), d = () => o ??= C({
|
|
136
|
+
...e,
|
|
137
|
+
context: t,
|
|
138
|
+
destination: r
|
|
139
|
+
}).then((e) => {
|
|
140
|
+
if (s) throw e.dispose(), Error("the metronome was disposed");
|
|
141
|
+
return a = e, e;
|
|
142
|
+
}, (e) => {
|
|
143
|
+
throw o = null, e;
|
|
144
|
+
}), f = async (e) => {
|
|
145
|
+
i = e;
|
|
146
|
+
let t = g(e);
|
|
147
|
+
if (!(!t.length || s || l.has(e))) try {
|
|
148
|
+
await (await d()).loadNotes(t), s || l.add(e);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
if (s) return;
|
|
151
|
+
c = Date.now(), console.warn(`pepperscore/audio: the metronome's drum sounds could not load (${e instanceof Error ? e.message : String(e)}); using synthesized sounds.`);
|
|
152
|
+
}
|
|
153
|
+
}, p = f(i), m = (e, n, i) => {
|
|
154
|
+
let a = T[e], o = +!!n, s = t.createOscillator(), c = t.createGain();
|
|
155
|
+
return s.type = a.type, s.frequency.setValueAtTime(a.frequency[o], i), s.frequency.exponentialRampToValueAtTime(a.frequency[o] * a.drop, i + a.decay), c.gain.setValueAtTime(0, i), c.gain.linearRampToValueAtTime(a.level[o], i + .002), c.gain.exponentialRampToValueAtTime(1e-4, i + a.decay), s.connect(c).connect(r), s.onended = () => {
|
|
156
|
+
u.delete(s), s.disconnect(), c.disconnect();
|
|
157
|
+
}, u.add(s), s.start(i), s.stop(i + a.decay + .01), () => {
|
|
158
|
+
if (u.has(s)) try {
|
|
159
|
+
s.stop();
|
|
160
|
+
} catch {}
|
|
161
|
+
};
|
|
162
|
+
}, h = () => {
|
|
163
|
+
a?.stop();
|
|
164
|
+
for (let e of [...u]) try {
|
|
165
|
+
e.stop();
|
|
166
|
+
} catch {}
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
get voice() {
|
|
170
|
+
return i;
|
|
171
|
+
},
|
|
172
|
+
output: r,
|
|
173
|
+
ready: p,
|
|
174
|
+
setVoice: f,
|
|
175
|
+
tick: ({ time: e, beat: n, accent: r }) => {
|
|
176
|
+
let u = Math.max(e, t.currentTime);
|
|
177
|
+
!s && !o && !l.has(i) && g(i).length && Date.now() - c > w && f(i);
|
|
178
|
+
let d = a && l.has(i) ? a : null, p = _(i, n, {
|
|
179
|
+
accent: r,
|
|
180
|
+
covers: d ? (e) => d.covers(e) : void 0
|
|
181
|
+
}).map((e) => e.kind === "note" ? d.start({
|
|
182
|
+
note: e.note,
|
|
183
|
+
time: u,
|
|
184
|
+
duration: .5,
|
|
185
|
+
velocity: e.velocity
|
|
186
|
+
}) : m(e.kind, e.accent, u));
|
|
187
|
+
return () => p.forEach((e) => e());
|
|
188
|
+
},
|
|
189
|
+
stop: h,
|
|
190
|
+
dispose: () => {
|
|
191
|
+
s = !0, h(), a?.dispose(), a = null, o = null, r.disconnect();
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
export { p as METRONOME_VOICES, c as SOUNDS_VERSION, n as claimPlayback, E as createMetronome, d as defaultAssetBaseUrl, r as getSharedAudio, C as loadDrumKit, S as loadInstrument, l as releasePlayback, o as resumeAudio };
|
|
197
|
+
|
|
198
|
+
//# sourceMappingURL=audio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio.js","names":["planSound","loadPackInfo","claimPlayback","getSharedAudio","programs","resolveAssetBase","resumeAudio","loadPlayers","SOUNDS_VERSION","releasePlayback","fallbackSf2Url","defaultAssetBaseUrl","addDrumFallback","METRONOME_VOICES","ACCENT_VELOCITY","BEAT_VELOCITY","metronomeNotes","voice","metronomeHits","beat","velocity","accent","note","covers","PIANO_RANGE","i","pageBase","instrumentRequest","sound","entry","item","audioTarget","options","shared","loadInstrument","request","base","pack","plan","output","context","destination","players","error","disposed","fallbackQueue","loadNotes","player","notes","step","current","before","instrument","stops","stop","loadDrumKit","RETRY_AFTER_MS","SYNTH","createMetronome","kit","kitLoad","failedAt","loaded","synths","ensureKit","loadedKit","setVoice","next","ready","synth","spec","kind","osc","env","time","at","drums","hit"],"sources":["../src/lib/metronome.ts","../src/lib/instruments.ts"],"sourcesContent":["/**\n * What a metronome beat sounds like, per voice (public through pepperscore/audio's createMetronome). Pure: no Web Audio\n * and no runtime imports (validation/audio-api.mjs runs it in Node).\n * - woodblock: GM hi wood block (76) on beat 1, low wood block (77) on the others, when the drum kit has them; else a\n * soft synthesized knock.\n * - drum-machine: kick (36) on beat 1, closed hi-hat (42) on the others, from the drum kit.\n * - click: a soft, short synthesized tick.\n * Beat 1 (`beat` 0) is accented: a louder note, or a higher, louder synth sound.\n */\nexport type MetronomeVoice = 'woodblock' | 'drum-machine' | 'click';\nexport const METRONOME_VOICES: readonly MetronomeVoice[] = ['woodblock', 'drum-machine', 'click'];\n\nexport type MetronomeHit =\n | { kind: 'note'; note: number; velocity: number }\n | { kind: 'knock' | 'tick'; accent: boolean };\n\nexport const WOODBLOCK_HIGH = 76;\nexport const WOODBLOCK_LOW = 77;\nexport const KICK = 36;\nexport const CLOSED_HAT = 42;\nconst ACCENT_VELOCITY = 112;\nconst BEAT_VELOCITY = 78;\n\n/** Drum notes a voice plays (loaded up front); the synthesized click needs none. */\nexport const metronomeNotes = (voice: MetronomeVoice): number[] =>\n voice === 'woodblock' ? [WOODBLOCK_HIGH, WOODBLOCK_LOW] : voice === 'drum-machine' ? [KICK, CLOSED_HAT] : [];\n\n/**\n * The hits for one beat. `beat` counts from 0 (beat 1 of the bar) and `accent` defaults to `beat === 0`. `kit` says\n * whether the drum kit loaded and which notes it plays; without it, sample voices fall back to synthesized sounds.\n */\nexport function metronomeHits(voice: MetronomeVoice, beat: number, { accent = beat === 0, covers }: { accent?: boolean; covers?: (note: number) => boolean } = {}): MetronomeHit[] {\n const velocity = accent ? ACCENT_VELOCITY : BEAT_VELOCITY;\n if (voice === 'woodblock') {\n const note = accent ? WOODBLOCK_HIGH : WOODBLOCK_LOW;\n return covers?.(note) ? [{ kind: 'note', note, velocity }] : [{ kind: 'knock', accent }];\n }\n if (voice === 'drum-machine') {\n const note = accent ? KICK : CLOSED_HAT;\n return covers?.(note) ? [{ kind: 'note', note, velocity }] : [{ kind: 'tick', accent }];\n }\n return [{ kind: 'tick', accent }];\n}\n","/**\n * Instruments and the metronome for pepperscore/audio (src/audio.ts). Built on the reader's own sound code: the same\n * shared AudioContext (audio-engine), sound resolution (sounds.ts planSound: soundSources, then the pack's FluidR3\n * sound, then TimGM6mb.sf2; drums from Perfect Drums with TimGM6mb's kit for missing notes) and players. Every built-in\n * file is fetched from the asset base, so a page that self-hosts the sounds talks to no other host.\n */\nimport { programs } from './gm-soundfont-manifest.json';\nimport { getSharedAudio } from './audio-engine';\nimport { loadPackInfo, resolveAssetBase, type SoundPackName } from './assets';\nimport { addDrumFallback, loadPlayers, type AudioPlayer } from './sound-players';\nimport { fallbackSf2Url, planSound, type SoundPlan, type SoundRequest, type SoundSource } from './sounds';\nimport { metronomeHits, metronomeNotes, type MetronomeVoice } from './metronome';\n\nexport type InstrumentOptions = {\n /** Root of a pepperscore-sounds-<pack> layout (relative to the page); default: the jsDelivr copy of pepperscore-sounds-<soundPack>. */\n assetBaseUrl?: string;\n /** Picks the default assetBaseUrl. With your own assetBaseUrl, its pack.json decides which FluidR3 sounds exist. */\n soundPack?: SoundPackName;\n /** Your own sounds, claimed per GM program or for the drum kit (the PepperScore `soundSources` prop). */\n sources?: readonly SoundSource[];\n /** Default: the page's shared AudioContext (getSharedAudio). */\n context?: AudioContext;\n /** Where the instrument's output goes. Default: the shared master compressor (or `context.destination` for your own context). */\n destination?: AudioNode;\n /** Notes to load before the promise resolves. Default: 21-108 for an instrument, none for the drum kit. */\n notes?: number[];\n};\n\n/** The public view of an instrument's sound plan. */\nexport type InstrumentPlan = { readonly kind: SoundPlan['kind']; readonly sourceId: string };\n\n/** A loaded sound: an AudioPlayer plus its output gain (volume) and the plan it came from. */\nexport type Instrument = AudioPlayer & {\n readonly context: AudioContext;\n /** The instrument's volume; connected to `destination`. */\n readonly output: GainNode;\n /** Which kind of source plays it and its id (for example `'builtin:fluidr3'`). Read-only; the plan's URLs and presets are internal. */\n readonly plan: InstrumentPlan;\n /** Load (decode) these notes; a note starts silently until it is loaded. Drums load TimGM6mb's kit for notes the kit lacks. */\n loadNotes(notes: number[]): Promise<void>;\n /** Whether a loaded player can sound this note. */\n covers(note: number): boolean;\n};\n\n/** A GM program (1-128), a FluidR3 sound name (`'acoustic_grand_piano'`), or `'drums'` for the GM drum kit (`'drum-kit'`, the score part id, is accepted as an alias). */\nexport type InstrumentName = number | string;\n\nconst PIANO_RANGE = Array.from({ length: 88 }, (_, i) => 21 + i);\nconst pageBase = (): string => (typeof document !== 'undefined' && document.baseURI) || 'http://localhost/';\n\n/** The sound request for a program number, a FluidR3 name or 'drums'/'drum-kit'. */\nexport function instrumentRequest(sound: InstrumentName): SoundRequest {\n if (sound === 'drums' || sound === 'drum-kit') return { drums: true };\n const entry = typeof sound === 'number' ? (Number.isInteger(sound) ? programs[sound - 1] : undefined) : programs.find(item => item.soundfont === sound);\n if (!entry) throw new Error(`pepperscore/audio: unknown instrument ${JSON.stringify(sound)} (use a GM program 1-128, a FluidR3 name or 'drums').`);\n return { drums: false, program: entry.program, name: entry.soundfont };\n}\n\nfunction audioTarget(options: { context?: AudioContext; destination?: AudioNode }): { context: AudioContext; destination: AudioNode } {\n if (options.context) return { context: options.context, destination: options.destination ?? options.context.destination };\n const shared = getSharedAudio();\n if (!shared) throw new Error('pepperscore/audio: Web Audio is not available on this device.');\n return { context: shared.context, destination: options.destination ?? shared.master };\n}\n\n/**\n * Load an instrument through pepperscore's sound resolution. `start()` returns a stop function for that one note;\n * `stop()` stops every sounding note and cancels every scheduled one. A note's `destination` is honoured by sample-pack\n * and note-file sounds; SF2 sounds always play through `output`.\n */\nexport async function loadInstrument(sound: InstrumentName, options: InstrumentOptions = {}): Promise<Instrument> {\n const request = instrumentRequest(sound);\n const { context, destination } = audioTarget(options);\n const base = resolveAssetBase(options.assetBaseUrl, options.soundPack ?? 'core');\n const pack = await loadPackInfo(base);\n const plan = planSound(request, { sources: options.sources, fluidr3: pack.fluidr3, base, page: pageBase() });\n const output = context.createGain();\n output.connect(destination);\n let players: AudioPlayer[];\n try { players = await loadPlayers(context, plan, output); } catch (error) { output.disconnect(); throw error; }\n let disposed = false;\n // The drum kit's TimGM6mb fallback loads one at a time (two overlapping loadNotes calls would each fetch the 6 MB SF2),\n // and a player that arrives after dispose() is released at once instead of leaking into the old player list.\n let fallbackQueue: Promise<void> = Promise.resolve();\n const loadNotes = async (notes: number[]) => {\n await Promise.all(players.map(player => player.loadNotes?.(notes)));\n if (plan.kind === 'note-files' && plan.drums) {\n const step = fallbackQueue.then(async () => {\n if (disposed) return;\n const current = players, before = current.length;\n await addDrumFallback(context, current, notes, fallbackSf2Url(base), output);\n if (disposed) current.slice(before).forEach(player => player.dispose());\n });\n fallbackQueue = step.catch(() => {});\n await step;\n }\n };\n const instrument: Instrument = {\n context, output, plan: { kind: plan.kind, sourceId: plan.sourceId }, loadNotes,\n covers: note => players.some(player => player.covers?.(note) ?? true),\n start: options => {\n const stops: Array<() => void> = [];\n for (const player of players) {\n // A sample-pack player throws for a note it has not loaded; that note is silent rather than an error mid-schedule.\n try { stops.push(player.start({ ...options, destination: options.destination ?? output })); } catch { /* not loaded */ }\n }\n return () => stops.forEach(stop => stop());\n },\n stop: () => players.forEach(player => player.stop()),\n dispose: () => { disposed = true; players.forEach(player => player.dispose()); players = []; output.disconnect(); },\n };\n try { await loadNotes(options.notes ?? (request.drums ? [] : PIANO_RANGE)); } catch (error) { instrument.dispose(); throw error; }\n return instrument;\n}\n\n/** The GM drum kit (`loadInstrument('drums', options)`): Perfect Drums note files, TimGM6mb's kit for notes they lack. */\nexport const loadDrumKit = (options: InstrumentOptions = {}): Promise<Instrument> => loadInstrument('drums', options);\n\nexport type MetronomeOptions = Omit<InstrumentOptions, 'notes'> & {\n /** Default 'woodblock'. */\n voice?: MetronomeVoice;\n /** Output volume, 0-1. Default 0.5 (gentle). */\n gain?: number;\n};\n\nexport type Metronome = {\n readonly voice: MetronomeVoice;\n readonly output: GainNode;\n /**\n * Schedule one beat at `time` (AudioContext seconds). `beat` counts from 0 within the bar; beat 0 is accented unless\n * `accent` says otherwise. Returns a stop function for that beat.\n */\n tick(options: { time: number; beat: number; accent?: boolean }): () => void;\n /**\n * Resolves once the drum kit and the notes of the voice given to `createMetronome` have loaded (or failed: then the\n * synthesized sounds keep playing). `createMetronome` itself does not wait for it.\n */\n readonly ready: Promise<void>;\n /** Switch voice; resolves when the drum kit notes the voice needs have loaded. Until then the voice plays its synthesized sound. A failed load is retried by the next call. */\n setVoice(voice: MetronomeVoice): Promise<void>;\n /** Stop every sounding and scheduled beat. */\n stop(): void;\n dispose(): void;\n};\n\n/** After a failed drum load, ticks retry in the background no sooner than this. */\nconst RETRY_AFTER_MS = 10_000;\n\nconst SYNTH = {\n knock: { frequency: [740, 1040], drop: .6, decay: .07, level: [.5, .7], type: 'triangle' },\n tick: { frequency: [1800, 2400], drop: 1, decay: .025, level: [.18, .28], type: 'sine' },\n} as const;\n\n/**\n * A metronome on the shared AudioContext; drum voices come from the same drum kit loadDrumKit plays. Resolves at once:\n * the drum kit (a few MB for the woodblock's TimGM6mb kit) loads in the background, and beats play the synthesized\n * sound until it arrives (`await metronome.ready` to wait).\n */\nexport async function createMetronome(options: MetronomeOptions = {}): Promise<Metronome> {\n const { context, destination } = audioTarget(options);\n const output = context.createGain();\n output.gain.value = Math.max(0, Math.min(1, options.gain ?? .5));\n output.connect(destination);\n let voice: MetronomeVoice = options.voice ?? 'woodblock';\n let kit: Instrument | null = null;\n let kitLoad: Promise<Instrument> | null = null;\n let disposed = false;\n let failedAt = -Infinity;\n /** Voices whose kit notes are loaded; a voice plays its synthesized sound until then. */\n const loaded = new Set<MetronomeVoice>();\n const synths = new Set<OscillatorNode>();\n // The drum kit loads once however many setVoice calls overlap (they share the in-flight promise), a kit that arrives\n // after dispose() is released, and a failed load is not remembered: the next setVoice (or, after a pause, tick) retries.\n const ensureKit = (): Promise<Instrument> => kitLoad ??= loadDrumKit({ ...options, context, destination: output }).then(\n loadedKit => {\n if (disposed) { loadedKit.dispose(); throw new Error('the metronome was disposed'); }\n kit = loadedKit;\n return loadedKit;\n },\n error => { kitLoad = null; throw error; });\n const setVoice = async (next: MetronomeVoice) => {\n voice = next;\n const notes = metronomeNotes(next);\n if (!notes.length || disposed || loaded.has(next)) return;\n try {\n const drums = await ensureKit();\n await drums.loadNotes(notes);\n if (!disposed) loaded.add(next);\n } catch (error) {\n if (disposed) return;\n // No drum kit at the asset base (or the fetch failed): the sample voices play synthesized sounds, and a later retry is allowed.\n failedAt = Date.now();\n console.warn(`pepperscore/audio: the metronome's drum sounds could not load (${error instanceof Error ? error.message : String(error)}); using synthesized sounds.`);\n }\n };\n const ready = setVoice(voice);\n const synth = (kind: 'knock' | 'tick', accent: boolean, time: number) => {\n const spec = SYNTH[kind], i = accent ? 1 : 0;\n const osc = context.createOscillator(), env = context.createGain();\n osc.type = spec.type;\n osc.frequency.setValueAtTime(spec.frequency[i], time);\n osc.frequency.exponentialRampToValueAtTime(spec.frequency[i] * spec.drop, time + spec.decay);\n env.gain.setValueAtTime(0, time);\n env.gain.linearRampToValueAtTime(spec.level[i], time + .002);\n env.gain.exponentialRampToValueAtTime(.0001, time + spec.decay);\n osc.connect(env).connect(output);\n osc.onended = () => { synths.delete(osc); osc.disconnect(); env.disconnect(); };\n synths.add(osc);\n osc.start(time);\n osc.stop(time + spec.decay + .01);\n return () => { if (synths.has(osc)) try { osc.stop(); } catch { /* ended */ } };\n };\n const stop = () => { kit?.stop(); for (const osc of [...synths]) try { osc.stop(); } catch { /* ended */ } };\n return {\n get voice() { return voice; },\n output,\n ready,\n setVoice,\n tick: ({ time, beat, accent }) => {\n const at = Math.max(time, context.currentTime);\n // A drum voice whose kit failed to load tries again, at most once per RETRY_AFTER_MS, while ticks keep sounding synthesized.\n if (!disposed && !kitLoad && !loaded.has(voice) && metronomeNotes(voice).length && Date.now() - failedAt > RETRY_AFTER_MS) void setVoice(voice);\n const drums = kit && loaded.has(voice) ? kit : null;\n const stops = metronomeHits(voice, beat, { accent, covers: drums ? note => drums.covers(note) : undefined }).map(hit =>\n hit.kind === 'note' ? drums!.start({ note: hit.note, time: at, duration: .5, velocity: hit.velocity }) : synth(hit.kind, hit.accent, at));\n return () => stops.forEach(stop => stop());\n },\n stop,\n dispose: () => { disposed = true; stop(); kit?.dispose(); kit = null; kitLoad = null; output.disconnect(); },\n };\n}\n"],"mappings":"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"}
|
|
@@ -13,6 +13,62 @@ export type PepperScoreReadyInfo = {
|
|
|
13
13
|
}>;
|
|
14
14
|
measures: number;
|
|
15
15
|
};
|
|
16
|
+
/** What a click on the engraving hit (`onElementClick`). */
|
|
17
|
+
export type PepperScoreClickInfo = {
|
|
18
|
+
/** Viewer note id (data-note-id) when a note or rest was hit. */
|
|
19
|
+
noteId?: string;
|
|
20
|
+
/** Source element id (the MusicXML `id` attribute) of the first pitch of that note, when known. */
|
|
21
|
+
sourceId?: string;
|
|
22
|
+
/** Zero-based measure index, when a measure box was hit. */
|
|
23
|
+
measureIndex?: number;
|
|
24
|
+
/** 0..1 position of the click across the measure's width. */
|
|
25
|
+
fraction?: number;
|
|
26
|
+
/** 1-based index of the nearest visible staff in the system. */
|
|
27
|
+
staff?: number;
|
|
28
|
+
/**
|
|
29
|
+
* When no note was hit: the drawn note or rest in the hit measure, on `staff`, whose notehead is nearest the click
|
|
30
|
+
* across the engraving (its viewer id and MusicXML id). Engraved positions are not proportional to time, so this
|
|
31
|
+
* maps a click in staff space to an event better than `fraction`.
|
|
32
|
+
*/
|
|
33
|
+
nearestNoteId?: string;
|
|
34
|
+
nearestSourceId?: string;
|
|
35
|
+
clientX: number;
|
|
36
|
+
clientY: number;
|
|
37
|
+
};
|
|
38
|
+
/** Adds `className` to the drawn notes (`ids`: note or source ids) and measures (`measures`: zero-based indexes); re-applied after every draw. */
|
|
39
|
+
export type PepperScoreHighlight = {
|
|
40
|
+
ids?: string[];
|
|
41
|
+
measures?: number[];
|
|
42
|
+
className: string;
|
|
43
|
+
};
|
|
44
|
+
/** CSS pixels from each edge. */
|
|
45
|
+
export type PepperScoreInsets = {
|
|
46
|
+
top?: number;
|
|
47
|
+
right?: number;
|
|
48
|
+
bottom?: number;
|
|
49
|
+
left?: number;
|
|
50
|
+
};
|
|
51
|
+
/** What `scrollIntoView` reveals: the drawn notes (note or source ids, like `highlights`), else the measure (zero-based). */
|
|
52
|
+
export type PepperScoreScrollTarget = {
|
|
53
|
+
ids?: string[];
|
|
54
|
+
measure?: number;
|
|
55
|
+
};
|
|
56
|
+
export type PepperScoreScrollOptions = {
|
|
57
|
+
/** Keep the target at least this far inside the visible edges (a number for every edge). Default 0. */
|
|
58
|
+
margin?: number | PepperScoreInsets;
|
|
59
|
+
/**
|
|
60
|
+
* When a scroll is needed, go this share (0..1) of the visible extent past the least scroll, in the direction of
|
|
61
|
+
* travel, so what follows is in view too (the target always stays inside the margins). Default 0.
|
|
62
|
+
*/
|
|
63
|
+
lead?: number;
|
|
64
|
+
/** Client coordinates the target must also stay inside, e.g. the space between a host's overlays. */
|
|
65
|
+
bounds?: PepperScoreInsets;
|
|
66
|
+
/**
|
|
67
|
+
* A `performance.now()` time: do nothing if the reader has scrolled, wheeled, touched or pressed on the score
|
|
68
|
+
* since then (or a pointer is still down on it), so a reader's own scrolling or click is never overridden.
|
|
69
|
+
*/
|
|
70
|
+
interactedSince?: number;
|
|
71
|
+
};
|
|
16
72
|
export type PepperScoreHandle = {
|
|
17
73
|
/** Start playback (no-op while playing, when the chrome loads no audio, or with a `clock`). */
|
|
18
74
|
play(): Promise<void>;
|
|
@@ -27,6 +83,17 @@ export type PepperScoreHandle = {
|
|
|
27
83
|
seek(seconds: number): void;
|
|
28
84
|
/** Seconds of the playhead: `clock.now()` with a `clock`, else the self-driven position. */
|
|
29
85
|
currentTime(): number;
|
|
86
|
+
/** Draw the measure's system if needed and scroll the measure into view. */
|
|
87
|
+
scrollToMeasure(index: number): Promise<void>;
|
|
88
|
+
/** `seek` to the start of a measure (its first performed occurrence). */
|
|
89
|
+
seekToMeasure(index: number): void;
|
|
90
|
+
/**
|
|
91
|
+
* Scroll the least distance (plus `lead`) that brings the target `margin` inside the visible edges; nothing moves
|
|
92
|
+
* when it is already there. Horizontally the notes (else the measure) must show; vertically their whole system
|
|
93
|
+
* (or the notes, when the system is taller than the view). Draws the measure's system if needed. Smooth, unless the
|
|
94
|
+
* user prefers reduced motion. Does nothing while playback follows (it owns the view). Resolves `true` when it scrolled.
|
|
95
|
+
*/
|
|
96
|
+
scrollIntoView(target: PepperScoreScrollTarget, options?: PepperScoreScrollOptions): Promise<boolean>;
|
|
30
97
|
};
|
|
31
98
|
export type PepperScoreProps = {
|
|
32
99
|
/** Score sources; the first present wins, in this order. */
|
|
@@ -57,6 +124,14 @@ export type PepperScoreProps = {
|
|
|
57
124
|
persist?: PersistNamespace;
|
|
58
125
|
/** Root of a pepperscore-sounds-<pack> layout; default: the jsDelivr copy of pepperscore-sounds-<soundPack>. */
|
|
59
126
|
assetBaseUrl?: string;
|
|
127
|
+
/**
|
|
128
|
+
* A directory with an interface-compatible Verovio build to engrave with instead of the copy shipped in
|
|
129
|
+
* dist/verovio/, laid out like the verovio npm package's dist/ (`verovio-module.mjs` and `verovio.mjs`), for example
|
|
130
|
+
* `https://cdn.jsdelivr.net/npm/verovio@6.3.0/dist/`. Relative URLs resolve against the page; cross-origin needs CORS.
|
|
131
|
+
* All readers on a page share one Verovio worker: set it before the first score engraves (the latest value wins
|
|
132
|
+
* when the worker next starts).
|
|
133
|
+
*/
|
|
134
|
+
verovioBaseUrl?: string;
|
|
60
135
|
soundPack?: SoundPackName;
|
|
61
136
|
/** Sounds that replace the built-in ones for the programs (or drum kit) they claim; the first claiming entry wins. */
|
|
62
137
|
soundSources?: SoundSource[];
|
|
@@ -77,8 +152,21 @@ export type PepperScoreProps = {
|
|
|
77
152
|
onSeek?(seconds: number): void;
|
|
78
153
|
/** Self-driven playback time, about 10 times a second while playing. */
|
|
79
154
|
onTimeUpdate?(seconds: number): void;
|
|
155
|
+
/** Any click on the engraving (every chrome, with or without a clock): the note, measure and staff it hit. */
|
|
156
|
+
onElementClick?(info: PepperScoreClickInfo): void;
|
|
157
|
+
/** Every draw landed (the first paint, a re-layout, an in-place swap), with `highlights` already applied. */
|
|
158
|
+
onRender?(): void;
|
|
159
|
+
/** Classes to add to notes and measures (for a host's selection or cursor; see the `ps-*` classes in styles.css). */
|
|
160
|
+
highlights?: PepperScoreHighlight[];
|
|
80
161
|
/** Focus the reader on mount so page-turn keys work before any click. */
|
|
81
162
|
autoFocus?: boolean;
|
|
163
|
+
/**
|
|
164
|
+
* How a new `musicXml` or `abc` replaces a score already on screen. `"reveal"` (default): fade out, show the loading
|
|
165
|
+
* overlay, scroll to the top and fade the new score in. `"none"`: keep the current engraving and scroll position until
|
|
166
|
+
* the new one replaces it in place, with no fade or overlay (for a host that edits the score it shows, like the
|
|
167
|
+
* editor). The first paint, other sources and setting changes (mode, font, transposition) always reveal.
|
|
168
|
+
*/
|
|
169
|
+
paintTransition?: 'reveal' | 'none';
|
|
82
170
|
ref?: React.Ref<PepperScoreHandle>;
|
|
83
171
|
};
|
|
84
|
-
export default function PepperScore({ musicXml, file, scoreUrl, abc, chrome: preset, controls, view, height, className, ariaLabel, settings, persist, assetBaseUrl, soundPack, soundSources, onReady, onPlay, onStop, onError, clock, audio: withAudio, onSeek, onTimeUpdate, autoFocus, ref }: PepperScoreProps): import("react").JSX.Element;
|
|
172
|
+
export default function PepperScore({ musicXml, file, scoreUrl, abc, chrome: preset, controls, view, height, className, ariaLabel, settings, persist, assetBaseUrl, verovioBaseUrl, soundPack, soundSources, onReady, onPlay, onStop, onError, clock, audio: withAudio, onSeek, onTimeUpdate, onElementClick, onRender, highlights, autoFocus, paintTransition, ref }: PepperScoreProps): import("react").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import PepperScore from './components/PepperScore';
|
|
|
2
2
|
import type { PepperScoreProps } from './components/PepperScore';
|
|
3
3
|
export { PepperScore };
|
|
4
4
|
export default PepperScore;
|
|
5
|
-
export type { PepperScoreProps, PepperScoreHandle, PepperScoreReadyInfo } from './components/PepperScore';
|
|
5
|
+
export type { PepperScoreProps, PepperScoreHandle, PepperScoreReadyInfo, PepperScoreClickInfo, PepperScoreHighlight, PepperScoreInsets, PepperScoreScrollTarget, PepperScoreScrollOptions } from './components/PepperScore';
|
|
6
6
|
export type { ChromePreset, PepperScoreControls } from './lib/chrome';
|
|
7
|
-
export type { PepperScoreSettings } from './lib/prefs';
|
|
7
|
+
export type { PepperScoreSettings, PepperScoreAnnotationSizes, AnnotationSize } from './lib/prefs';
|
|
8
8
|
export type { ExternalClock, ClockEvent } from './lib/clock';
|
|
9
9
|
export type { SoundSource } from './lib/sounds';
|
|
10
10
|
export type { SoundPackName } from './lib/assets';
|