UNPKG

shimi

Version:

A JS framework for building complex MIDI applications

1 lines 112 kB
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.shimi=e():t.shimi=e()}(this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Arpeggiator:()=>Arpeggiator,Arpeggio:()=>Arpeggio,ArpeggioNote:()=>ArpeggioNote,ButtonEvent:()=>ButtonEvent,ButtonEventData:()=>ButtonEventData,ButtonInput:()=>ButtonInput,ChannelPressureMessage:()=>ChannelPressureMessage,Chord:()=>u,ChordFinder:()=>ChordFinder,ChordProgression:()=>ChordProgression,ChordProgressionChord:()=>ChordProgressionChord,ChordProgressionPlayer:()=>ChordProgressionPlayer,Clip:()=>Clip,ClipBend:()=>ClipBend,ClipCC:()=>ClipCC,ClipNote:()=>ClipNote,ClipPlayer:()=>ClipPlayer,ClipRecorder:()=>ClipRecorder,ClipRecorderEvent:()=>ClipRecorderEvent,ClipRecorderEventData:()=>ClipRecorderEventData,Clock:()=>i,ClockChildFinishedEvent:()=>ClockChildFinishedEvent,ClockChildFinishedEventData:()=>ClockChildFinishedEventData,ContinueMessage:()=>ContinueMessage,ControlChangeMessage:()=>ControlChangeMessage,Cue:()=>Cue,Drums:()=>Drums,EventSubscriber:()=>EventSubscriber,Flexinome:()=>Flexinome,Gamepads:()=>Gamepads,Keyboard:()=>Keyboard,Metronome:()=>Metronome,MidiAccess:()=>MidiAccess,MidiAccessPortEvent:()=>MidiAccessPortEvent,MidiAccessPortEventData:()=>MidiAccessPortEventData,MidiBus:()=>MidiBus,MidiIn:()=>MidiIn,MidiInEvent:()=>MidiInEvent,MidiInEventData:()=>MidiInEventData,MidiMessageBase:()=>MidiMessageBase,MidiOut:()=>MidiOut,MiscController:()=>MiscController,Note:()=>Note,NoteOffMessage:()=>NoteOffMessage,NoteOnMessage:()=>NoteOnMessage,NotePressureMessage:()=>NotePressureMessage,PS4Controller:()=>PS4Controller,PitchBendMessage:()=>PitchBendMessage,PitchFitter:()=>PitchFitter,ProgramChangeMessage:()=>ProgramChangeMessage,PropertyTracker:()=>PropertyTracker,Repeat:()=>Repeat,Scale:()=>Scale,ScaleTemplate:()=>g,SliderEvent:()=>SliderEvent,SliderEventData:()=>SliderEventData,SliderInput:()=>SliderInput,SongPositionMessage:()=>SongPositionMessage,StartMessage:()=>StartMessage,StopMessage:()=>StopMessage,TickMessage:()=>TickMessage,TickReceiver:()=>TickReceiver,TickSender:()=>TickSender,TimeSig:()=>TimeSig,TimeSigDivision:()=>TimeSigDivision,ToneJSMidiOut:()=>ToneJSMidiOut,Tween:()=>Tween,WebAudioMidiOut:()=>WebAudioMidiOut,WebAudioMidiOutChannel:()=>WebAudioMidiOutChannel,pitch:()=>r});class ClockUpdateSource{get useWebWorker(){return this._useWebWorker}get msPerTick(){return this._msPerTick}get callback(){return this._callback}get running(){return this._running}constructor(t,e=5){if(this._useWebWorker=!0,this._running=!1,this._webWorker=null,this._timer=null,!t)throw new Error("ClockUpdateSource must take a callback function");this._msPerTick=e,this._callback=t}start(){return!this.running&&(this._running=!0,this._startRunning(),!0)}stop(){return!!this.running&&(this._running=!1,this._stopRunning(),!0)}_startRunning(){if(this.useWebWorker)try{this._startWebWorker()}catch(t){this._useWebWorker=!1,this._startRunning()}else this._setInterval()}_startWebWorker(){const t=new Blob([`\n let timeoutTime = ${this.msPerTick};\n \n function tick() {\n setTimeout(tick, timeoutTime);\n self.postMessage('tick');\n }\n tick();\n `],{type:"text/javascript"}),e=URL.createObjectURL(t),i=new Worker(e);i.onmessage=this.callback,this._webWorker=i}_setInterval(){this._timer=setInterval(this.callback,this.msPerTick)}_stopRunning(){this._timer&&clearInterval(this._timer),this._webWorker&&(this._webWorker.terminate(),this._webWorker.onmessage=null)}}class ShimiEventData{constructor(t){this.cancel=!1,this.source=t}}class ShimiEvent{constructor(){this._handlers=[]}get handlers(){return this._handlers}add(t){if(!t)throw new Error("Invalid handler value");if("function"==typeof t){const e=new ShimiHandler(t);return this.handlers.push(e),e}return this.handlers.push(t),t}remove(t){this._handlers=this._handlers.filter((e=>!t(e)))}trigger(t){for(const e of this.handlers){if(null==t?void 0:t.cancel)break;e.on&&e.logic(t)}}}class ShimiHandler{get logic(){return this._logic}get ref(){return this._ref}set ref(t){this._ref=t}get on(){return this._on}set on(t){this._on=t}constructor(t,e){this._on=!0,this._logic=t,this.ref=e}withRef(t){return this.ref=t,this}}class Clock{get typeName(){return"shimi.Clock"}get msPerTick(){return this._updateSource.msPerTick}get children(){return this._children}get running(){return this._updateSource.running}constructor(t=5){this._children=[],this._updateSource=null,this._onUpdateSourceTick=()=>this.updateChildren(),this._updateSource=new ClockUpdateSource(this._onUpdateSourceTick,t)}start(){return!!this._updateSource.start()&&(this._lastUpdateTime=(new Date).getTime(),!0)}stop(){return!!this._updateSource.stop()&&(this._lastUpdateTime=null,!0)}addChild(t){return this._children.push(t),t}stopChildren(t){for(const e of this._children)t(e)&&e.finish()}updateChildren(){const t=(new Date).getTime(),e=t-this._lastUpdateTime;this._lastUpdateTime=t;for(const t of this._children)t.isFinished||t.update(e);this._children=this._children.filter((t=>!t.isFinished))}}Clock.default=null;const i=Clock;class ClockChildFinishedEventData extends ShimiEventData{constructor(t){super(t)}}class ClockChildFinishedEvent extends ShimiEvent{}class PropertyTracker{constructor(t){this.value=t,this.oldValue=t}get isDirty(){return this.value!==this.oldValue}accept(){this.oldValue=this.value}undo(){this.value=this.oldValue}}class Arpeggiator{get typeName(){return"shimi.Arpeggiator"}get arpeggio(){return this._arpeggio}set arpeggio(t){this._arpeggio=t}get chord(){return this._chord}set chord(t){this._chord=t,this._endAllNotes()}get channel(){return this._channel}set channel(t){this._channel=t}get ref(){return this._ref}set ref(t){this._ref=t}get metronome(){return this._metronome}set metronome(t){this._metronome=t}get midiOut(){return this._midiOut}set midiOut(t){this._midiOut=t}get speed(){return this._speed}set speed(t){this._speed=t}get beat(){return this._beatTracker.value}set beat(t){this._beatTracker.value=t}get beatTracker(){return this._beatTracker}get running(){return this._running}set running(t){this._running=t}get noteModifier(){return this._noteModifier}set noteModifier(t){this._noteModifier=t}get isFinished(){return this._isFinished}get finished(){return this._finished}constructor(t,e,s){this._channel=0,this._speed=1,this._beatTracker=new PropertyTracker(0),this._running=!0,this._isFinished=!1,this._finished=new ClockChildFinishedEvent,this._notes=[],this.arpeggio=t,this.metronome=e,this.midiOut=s,i.default&&i.default.addChild(this)}update(t){if(!(this.running&&this.arpeggio&&this.metronome&&this.midiOut))return;const e=(this.metronome.totalBeat-this.metronome.totalBeatTracker.oldValue)*this.speed;if(0==e)return;this.beatTracker.accept(),this.beatTracker.value=(this.beatTracker.value+e)%this.arpeggio.duration;const i=this.beatTracker.oldValue,s=this.beatTracker.value;i>s&&this._endAllNotes();for(const t of this._notes){const e=t.arpNote;!e.contains(s)||s<i?t.stop():"number"!=typeof e.velocity&&(t.velocity=e.velocity.update((s-e.start)/e.duration))}if(this._notes=this._notes.filter((t=>t.on)),this.chord)for(const t of this.arpeggio.getNotesStartingInRange(i,s)){const e=t.createNote(this.chord,this.channel,(s-t.start)/t.duration);e&&(e.arpNote=t,this.noteModifier&&this.noteModifier(e),this._notes.push(e),this.midiOut.addNote(e))}}finish(){this._isFinished=!0,this._endAllNotes(),this.finished.trigger(new ClockChildFinishedEventData(this))}withRef(t){return this._ref=t,this}_endAllNotes(){for(const t of this._notes)t.stop();this._notes=[]}}class Range{get start(){return this._start}set start(t){this._start=t}get duration(){return this._duration}set duration(t){if(t<0)throw new Error("Cannot set duration to negative value");this._duration=t}get end(){return this._start+this._duration}set end(t){this.duration=t-this._start}constructor(t,e){this.start=t,this.duration=e}getPercent(t){return 0==this.duration?0:(t-this.start)/this.duration}contains(t){return t>=this.start&&t<=this.end}}function s(t,e){return(t%e+e)%e}function n(t,e,i){const s=i(t),n=i(e);return s<n?-1:s>n?1:0}function r(t){const e=a(t);let i=-1;if(e.parseEndIndex<t.length&&(i=Number(t.substring(e.parseEndIndex))),Number.isNaN(i))throw new Error(t+" is not a valid pitch name");return e.pitch+12*(i+1)}function a(t){let e={C:0,D:2,E:4,F:5,G:7,A:9,B:11}[t[0]];if(null==e)throw new Error(t+" is not a valid pitch name");let i=1;for(;i<t.length;i++){const s=t[i];if("♮"!=s)if("b"==s||"♭"==s)e--;else if("#"==s||"♯"==s)e++;else if("x"==s)e+=2;else if(s=="𝄪"[0]&&t.length>i+1&&t[i+1]=="𝄪"[1])e+=2,i++;else{if(!(s=="𝄫"[0]&&t.length>i+1&&t[i+1]=="𝄫"[1]))break;e-=2,i++}}return{pitch:s(e,12),parseEndIndex:i}}function h(t,e){if(!e)throw Error("scale must be provided");if(7!=e.length)throw Error("scale provided must have length 7");let i=0,s=0;for(;i<t.length;i++){const e=t[i];if("b"==e||"♭"==e)s-=1;else{if("#"!=e&&"♯"!=e)break;s+=1}}if(i>1)throw Error("Expected at most one accidental symbol");let n=i;const r=["i","I","v","V"];for(;i<t.length;i++){const e=t[i];if(!r.includes(e))break}let a=t.substring(n,i),h=!0;if(a==a.toLowerCase())h=!1;else if(a!=a.toUpperCase())throw Error("Invalid mixed casing of roman numerals");a=a.toUpperCase();let o=0;switch(a){case"I":o=1;break;case"II":o=2;break;case"III":o=3;break;case"IV":o=4;break;case"V":o=5;break;case"VI":o=6;break;case"VII":o=7;break;default:throw Error("Unrecognised roman numerals")}let u=e.getPitchByDegree(o)+s;switch(o){case 1:u=Math.max(e.root,Math.min(u,e.root+1));break;case 2:u=Math.max(e.root+1,Math.min(u,e.root+2));break;case 3:u=Math.max(e.root+3,Math.min(u,e.root+4));break;case 4:u=Math.max(e.root+5,Math.min(u,e.root+6));break;case 5:u=Math.max(e.root+6,Math.min(u,e.root+8));break;case 6:u=Math.max(e.root+8,Math.min(u,e.root+9));break;case 7:u=Math.max(e.root+10,Math.min(u,e.root+11))}return{pitch:u,isMajor:h,parseEndIndex:i}}function o(t){return"string"==typeof t&&(t=r(t)),440*Math.pow(2,(t-69)/12)}class Note{get typeName(){return"shimi.Note"}get pitch(){return this._pitch}set pitch(t){this._pitch=t}get velocity(){return this.velocityTracker.value}set velocity(t){this.velocityTracker.value=Math.round(t)}get on(){return this.onTracker.value}set on(t){this.onTracker.value=t}get channel(){return this._channel}set channel(t){this._channel=t}constructor(t,e,i,s){this._pitch="string"==typeof t?r(t):t,this.velocityTracker=new PropertyTracker(Math.round(e)),this.onTracker=new PropertyTracker(!1),this.on=!0,this._channel=i,this.ref=s}start(){return!this.on&&(this.on=!0,!0)}stop(){return!!this.on&&(this.on=!1,!0)}}class ArpeggioNote extends Range{get typeName(){return"shimi.ArpeggioNote"}get pitch(){return this._pitch}set pitch(t){this._pitch=t}get velocity(){return this._velocity}set velocity(t){this._velocity=t}get channel(){return this._channel}set channel(t){this._channel=t}constructor(t,e,i,s,n=null){super(t,e),this._channel=null,this.pitch=i,this.velocity=s,this.channel=n}createNote(t,e,i){var s;if(!t)return null;const n=this.pitch(t);return null==n||n<0||n>127?null:new Note(n,"number"==typeof this.velocity?this.velocity:this.velocity.update(i),null!==(s=this.channel)&&void 0!==s?s:e)}}class Arpeggio extends Range{get typeName(){return"shimi.Arpeggio"}constructor(t){super(0,t),this.notes=[]}addNote(t,e,i,s,n=null){"number"==typeof t&&(t=[t]);for(const r of t)this.notes.push(new ArpeggioNote(r,e,i,s,n));return this}getNotesStartingInRange(t,e){return t<=e?this.notes.filter((i=>i.start>=t&&i.start<e)):this.notes.filter((i=>i.start>=t||i.start<e))}getNotesEndingInRange(t,e){return t<=e?this.notes.filter((i=>i.end>=t&&i.end<e)):this.notes.filter((i=>i.end>=t||i.end<e))}}class ButtonEventData extends ShimiEventData{constructor(t){super(t)}}class ButtonEvent extends ShimiEvent{}class ButtonInput{get typeName(){return"shimi.ButtonInput"}get value(){return this.valueTracker.value}get isPressed(){return 0!=this.valueTracker.value}get name(){return this._name}get activeMs(){return this._activeMs}constructor(t){this._activeMs=0,this.pressed=new ButtonEvent,this.released=new ButtonEvent,this.changed=new ButtonEvent,this.valueTracker=new PropertyTracker(0),this._name=t}update(t){this.isPressed&&(this._activeMs+=t),this.valueTracker.isDirty&&(this.isPressed?0==this.valueTracker.oldValue?this.pressed.trigger(new ButtonEventData(this)):this.changed.trigger(new ButtonEventData(this)):(this.released.trigger(new ButtonEventData(this)),this._activeMs=0)),this.valueTracker.accept()}}class FitPitchOptions{constructor(t){this.maxMovement=2,this.preferRoot=!0,this.preferredDirection="DOWN",this.precision="TIGHT",this.scale=null,this.avoid=[],t&&(Object.assign(this,t),null!=this.avoid&&null!=this.avoid||(this.avoid=[]))}}class Chord{get typeName(){return"shimi.Chord"}get pitches(){return this._pitches}get root(){return this._root}set root(t){this.setRoot(t)}get bass(){return Math.min(...this._pitches)}get name(){return null==this._name&&null!=Chord.nameGenerator&&(this._name=Chord.nameGenerator(this)),this._name}set name(t){this._name=t}constructor(){this._pitches=[],this._root=null,this._name=null}addPitch(t){if("string"==typeof t&&(t=r(t)),!this._pitches.find((e=>e==t))){this._name=null;for(let e=0;e<this._pitches.length;e++)if(this._pitches[e]>t)return this._pitches.splice(e,0,t),this;this._pitches.push(t)}return this}addPitches(t){for(const e of t)this.addPitch(e);return this}removePitches(t){const e=this._pitches.length;return this._pitches=this._pitches.filter((e=>!t(e))),this._pitches.length<e&&(this._name=null),this.root&&!this._pitches.find((t=>t==this.root))&&(this.root=null),this}setRoot(t){return"string"==typeof t&&(t=r(t)),this._root!=t&&(null==t||null==t?this._root=null:(this._root=t,this.addPitch(t)),this._name=null),this}getPitchByIndex(t){t=Math.round(t);const e=Math.floor(t/this.pitches.length);return t-=e*this.pitches.length,this.pitches[t]+12*e}getPitchByDegree(t,e){var i,s,n,r,a,h,o,u,c,l;if(null==this.root)throw Error("Cannot call getPitchByDegree without root being set");if(1==(t=Math.round(t)))return this.root;const d=(t,e)=>{var i,s,n;return null!==(n=null!==(s=null!==(i=this.pitches.find((e=>e==t)))&&void 0!==i?i:this.pitches.find((t=>t==e)))&&void 0!==s?s:this.contains(t)?t:null)&&void 0!==n?n:this.contains(e)?e:null};if(2==t){let t=d(this.root+2,this.root+1);if(null==t){if(this.getPitchByDegree(3,e)==this.root+4)return this.root+2;t=null!==(i=null==e?void 0:e.fitPitch(this.root+2,{preferredDirection:"DOWN",maxMovement:1}))&&void 0!==i?i:this.root+2}return t}if(3==t)return null!==(n=null!==(s=d(this.root+4,this.root+3))&&void 0!==s?s:null==e?void 0:e.fitPitch(this.root+4,{preferredDirection:"DOWN",maxMovement:1}))&&void 0!==n?n:this.root+4;if(4==t)return this.getPitchByDegree(5,e)==this.root+6?this.root+5:null!==(a=null!==(r=d(this.root+5,this.root+6))&&void 0!==r?r:null==e?void 0:e.fitPitch(this.root+5,{preferredDirection:"UP",maxMovement:1}))&&void 0!==a?a:this.root+5;if(5==t)return null!==(o=null!==(h=d(this.root+7,this.root+6))&&void 0!==h?h:null==e?void 0:e.fitPitch(this.root+7,{preferredDirection:"DOWN",maxMovement:1}))&&void 0!==o?o:this.root+7;if(6==t){let t=d(this.root+9,this.root+8);if(null==t){if(this.getPitchByDegree(7,e)-this.getPitchByDegree(5,e)==4)return this.getPitchByDegree(5,e)+2;t=null!==(u=null==e?void 0:e.fitPitch(this.root+9,{preferredDirection:"DOWN",maxMovement:1}))&&void 0!==u?u:this.root+9}return t}if(7==t)return null!==(l=null!==(c=d(this.root+10,this.root+11))&&void 0!==c?c:null==e?void 0:e.fitPitch(this.root+10,{preferredDirection:"UP",maxMovement:1}))&&void 0!==l?l:this.root+10;const p=Math.floor((t-1)/7),g=new Chord;return g._pitches=this._pitches.slice(),g.setRoot(this.root+12*p),g.getPitchByDegree(t-7*p,e)}contains(t){return"string"==typeof t&&(t=r(t)),t=s(t,12),null!=this.pitches.find((e=>s(e,12)==t))}transpose(t){null!=this.root&&(this.root=this.root+t);for(let e=0;e<this.pitches.length;e++)this.pitches[e]=this.pitches[e]+t;this._name=null}duplicate(){const t=new Chord;return t._pitches=this.pitches.slice(),t._root=this.root,t._name=this.name,t}addDegrees(t,e=null){if(null==this.root)throw new Error("You cannot add degrees to the chord before its root has been set");for(let i of t){let t=!1;i<0&&(t=!0,i=Math.abs(i)),i--;let s=this.root;i>=7&&(s+=12*Math.floor(i/7));let n={main:0,fallback:0};switch(i%7){case 1:n={main:2,fallback:1};break;case 2:n={main:4,fallback:3};break;case 3:n={main:5,fallback:6};break;case 4:n={main:7,fallback:6};break;case 5:n={main:9,fallback:8};break;case 6:n={main:11,fallback:10}}t?s+=n.fallback:null==e||e.contains(s+n.main)||!e.contains(s+n.fallback)?s+=n.main:s+=n.fallback,this.addPitch(s)}return this}near(t,e=!1){"string"==typeof t&&(t=r(t));const i=this.pitches.reduce(((t,e)=>t+e),0)/this.pitches.length;let s=Math.round((t-i)/6);if(s%2==1&&(s=s<0?s+1:s-1),s/=2,0!=s)for(let t=0;t<this.pitches.length;t++)this.pitches[t]+=12*s;if(e){for(let e=0;e<this.pitches.length;e++)t-this.pitches[e]>6?this.pitches[e]+=12:this.pitches[e]-t>6&&(this.pitches[e]-=12);this._pitches=this.pitches.sort(((t,e)=>n(t,e,(t=>t))))}return this}fitPitch(t,e,i){"string"==typeof t&&(t=r(t));const n=new FitPitchOptions(e);let a=t=>this._isTightFit(t,n);"MEDIUM"==n.precision&&(a=t=>this._isMediumFit(t,n)),"LOOSE"==n.precision&&(a=t=>this._isLooseFit(t,n));let h=1;"DOWN"==n.preferredDirection?h=-1:"RANDOM"==n.preferredDirection&&(h=Math.random()>=.5?1:-1);let o=t,u=t;for(t%1!=0&&(o=h>0?Math.ceil(t):Math.floor(t),u=h>0?Math.floor(t):Math.ceil(t));;){const e=Math.abs(o-t)<=n.maxMovement,i=Math.abs(u-t)<=n.maxMovement;if(!e&&!i)break;const r=e&&!n.avoid.includes(o),c=i&&!n.avoid.includes(u),l=r?a(o):0,d=c?a(u):0;if(l+d>0){if(l>d)return o;if(d>l)return u;if(n.preferRoot){if(r&&s(o,12)==s(this.root,12))return o;if(c&&s(u,12)==s(this.root,12))return u}return Math.abs(o-t)<=Math.abs(u-t)?o:u}o+=h,u-=h}return i?this.fitPitch(t,i):Math.round(t)}_isTightFit(t,e){return this.contains(t)?1:0}_isMediumFit(t,e){if(this.contains(t))return 1;const i=e.scale;return i&&!i.contains(t)||this.contains(t+1)||this.contains(t-1)?0:.5}_isLooseFit(t,e){if(this.contains(t))return 1;const i=e.scale;return i?i.contains(t)?.5:0:.5}}Chord.nameGenerator=null;const u=Chord;function c(t,e){e||(e=t=>Number(t));let i=0;for(const s of t)i+=e(s);return i}function l(t){const e=[];for(let i=0;i<t.length;i++)t.indexOf(t[i])==i&&e.push(t[i]);return e}function d(t,e){if(!t||0==t.length)return null;let i=[];for(const s of t){const t=e(s),r=i.find((e=>e.value===t));return r?r.count++:i.push({value:t,count:1}),i.sort(((t,e)=>n(t,e,(t=>t.count)))),i.pop().value}}class ChordLookupData{constructor(t,e,i,s,n,r){this.shapeName="",this.name="",this.inverseName="",this.pitchMap=0,this.preference=0,this.intervals=[],this.root=0,this.shapeName=t,this.name=i,this.inverseName=s,this.pitchMap=this._getPitchMap(r,e),this.preference=n,this.intervals=e,this.root=r}_getPitchMap(t,e){const i=l(e.map((e=>s(t+e,12))));let n=0;for(let t of i)n+=Math.pow(2,t);return n}}class ChordLookupResult{constructor(){this.shapeName="",this.name="",this.root=0,this.bass=0,this.pitches=[],this.pitchesAdded=[],this.pitchesRemoved=[]}}class ChordFinder{get typeName(){return"shimi.ChordFinder"}addChordLookup(t,e,i,s,n){if(!e||0==e.length)throw new Error("No intervals specified in chord lookup");if(null==e.find((t=>0==t)))throw new Error("Chord lookup intervals parameter must contain 0");if(this.lookupData.find((e=>e.shapeName==t)))throw new Error("Attempted to add duplicate chord lookup");for(let r=0;r<12;r++)this.lookupData.push(new ChordLookupData(t,e,i,s,n,r));return this}removeChordLookup(t){return this.lookupData=this.lookupData.filter((e=>e.shapeName!=t)),this}replaceChordLookup(t,e,i,s,n){return this.removeChordLookup(t),this.addChordLookup(t,e,i,s,n),this}withDefaultChordLookups(){return this.addChordLookup("M",[0,4,7],"{r}","{r}/{b}",10),this.addChordLookup("m",[0,3,7],"{r}m","{r}m/{b}",9),this.addChordLookup("M7",[0,4,7,11],"{r}M7","{r}M7/{b}",8),this.addChordLookup("7",[0,4,7,10],"{r}7","{r}7/{b}",8),this.addChordLookup("m7",[0,3,7,10],"{r}m7","{r}m7/{b}",8),this.addChordLookup("dim",[0,3,6],"{r}dim","{r}dim/{b}",7),this.addChordLookup("aug",[0,4,8],"{r}aug","{r}aug/{b}",7),this.addChordLookup("5",[0,7],"{r}5","{r}5",6),this.addChordLookup("sus2",[0,2,7],"{r}sus2","{r}sus2/{b}",6),this.addChordLookup("sus4",[0,5,7],"{r}sus4","{r}sus4/{b}",6),this.addChordLookup("dim7",[0,3,6,9],"{r}dim7","{r}dim7/{b}",5),this.addChordLookup("m7♭5",[0,3,6,10],"{r}m7♭5","{r}m7♭5/{b}",5),this.addChordLookup("M9",[0,4,7,11,14],"{r}M9","{r}M9/{b}",4),this.addChordLookup("9",[0,4,7,10,14],"{r}9","{r}9/{b}",4),this.addChordLookup("m9",[0,3,7,10,14],"{r}m9","{r}m9/{b}",4),this.addChordLookup("add9",[0,4,7,14],"{r}add9","{r}add9/{b}",4),this.addChordLookup("madd9",[0,3,7,14],"{r}madd9","{r}madd9/{b}",4),this.addChordLookup("M11",[0,4,7,11,14,17],"{r}M11","{r}M11/{b}",3),this.addChordLookup("11",[0,4,7,10,14,17],"{r}11","{r}11/{b}",3),this.addChordLookup("m11",[0,3,7,10,14,17],"{r}m11","{r}m11/{b}",3),this.addChordLookup("add11",[0,4,7,17],"{r}add11","{r}add11/{b}",3),this.addChordLookup("madd11",[0,3,7,17],"{r}madd11","{r}madd11/{b}",3),this.addChordLookup("mM7",[0,3,7,11],"{r}mM7","{r}mM7/{b}",2),this.addChordLookup("7♯5",[0,4,8,10],"{r}7♯5","{r}7♯5/{b}",2),this.addChordLookup("7♯9",[0,4,7,10,15],"{r}7♯9","{r}7♯9/{b}",2),this}constructor(){this.lookupData=[]}findChord(t,e=null,i=null,r=null){if(0==t.length)return null;if(null!=e&&null==t.find((t=>t==e)))throw new Error("The root is not contained in the passed in pitches");1==t.length&&null==e&&(e=t[0]);const a=this._getAllPotentialChords(t,e,i,r),h=this._getPitchMap(t);let o=null;for(const t of a){const e=this._getPitchMapDistance(t.pitchMap,h);(null==o||e<o.distance||e==o.distance&&t.preference>o.chord.preference)&&(o={distance:e,chord:t})}if(null==o)return null;const u=new ChordLookupResult;u.shapeName=o.chord.shapeName;const c=[];for(const e of t)if((o.chord.pitchMap|Math.pow(2,s(e,12)))==o.chord.pitchMap){u.pitches.push(e);for(let t of o.chord.intervals)if(s(o.chord.root+t,12)==s(e,12)){c.push({interval:t,pitch:e});break}}else u.pitchesRemoved.push(e);for(const t of o.chord.intervals)if(!u.pitches.find((e=>s(e,12)==s(o.chord.root+t,12)))){const e=[];for(const i of c){const s=t-i.interval;e.push(i.pitch+s)}const i=d(e,(t=>t));u.pitches.push(i),u.pitchesAdded.push(i)}return u.pitches.sort(((t,e)=>n(t,e,(t=>t)))),u.bass=u.pitches[0],u.root=u.pitches.find((t=>s(t,12)==s(o.chord.root,12))),u.name=u.bass==u.root?o.chord.name:o.chord.inverseName,u}_getAllPotentialChords(t,e=null,i=null,n=null){const r=this._getPitchMap(t);let a=this.lookupData;return null!=e&&(e=s(e,12),a=a.filter((t=>t.root==e))),null!=i&&(a=a.filter((t=>i.find((e=>e==t.shapeName))))),null!=n&&(a=a.filter((t=>{const e=this._getPitchMap(n.pitches);return 0==((t.pitchMap|r)-r|e)-e}))),a}_getPitchMap(t){const e=l(t.map((t=>s(t,12))));let i=0;for(let t of e)i+=Math.pow(2,t);return i}_getPitchMapDistance(t,e){let i=t^e,s=0;for(;0!=i;)i&=i-1,s++;return s}findChordByName(t,e){let i=0,s="",n=null;try{const e=a(t);i=e.pitch,s=t.substring(e.parseEndIndex)}catch(r){if(!e)throw r;{const r=h(t,e);i=r.pitch,s=t.substring(r.parseEndIndex),n=r.isMajor,n||s.startsWith("m")||(s="m"+s),t=e.getPitchName(i)+s}}for(const r of this.lookupData.filter((t=>t.root==i))){if(null!=n){if(n&&!r.intervals.includes(4))continue;if(!n&&!r.intervals.includes(3))continue}else if(s.length>0&&!s.startsWith(r.shapeName))continue;const i=this._tryLookupMatchToChordName(r,t,e);if(i)return i}return null}_tryLookupMatchToChordName(t,e,i){const s=new ChordLookupResult;s.shapeName=t.shapeName;let o=this._getRegexStringFromLookupDataName(t.name),u=new RegExp(o).exec(e);if(u)s.name=t.name;else{if(o=this._getRegexStringFromLookupDataName(t.inverseName),u=new RegExp(o).exec(e),!u)return null;s.name=t.inverseName}if(s.root=r(u.groups.r)+12,null!=u.groups.b?s.bass=function(t,e){try{const e=a(t);return{pitch:e.pitch,isMajor:null,parseEndIndex:e.parseEndIndex}}catch(i){return h(t,e)}}(u.groups.b,i).pitch:s.bass=s.root,s.pitches=t.intervals.map((t=>t+s.root)),s.bass!=s.root){const t=s.pitches.findIndex((t=>t%12==s.bass));t<0?s.pitches.push(s.bass):s.pitches[t]=s.bass}return s.pitches=s.pitches.sort(((t,e)=>n(t,e,(t=>t)))),s}_getRegexStringFromLookupDataName(t){let e=t;for(;;){const i=e.indexOf("{"),s=e.indexOf("}");if(i<0&&s<0)break;if(i<0!=s<0||s<i)throw new Error(`'${t}' contains unmatched braces`);const n=e.slice(i+1,s);e=e.slice(0,i)+`(?<${n}>(?:[A-G](?:♮|b|#|♭|♯|x|𝄪|𝄫)*)|(?:(?:b|#|♭|♯)?(?:i|I|v|V)+))`+e.slice(s+1)}return"^"+e+"$"}newChord(t,e){const i=this.findChordByName(t,e);if(null==i)return null;const s=(new u).addPitches(i.pitches).setRoot(i.root);return null==u.nameGenerator&&(s.name=t),s}}class ChordProgressionChord extends Range{get typeName(){return"shimi.ChordProgressionChord"}get chord(){return this._chord}set chord(t){this._chord=t}constructor(t,e,i){super(t,e),this._chord=i}}class ChordProgression extends Range{get typeName(){return"shimi.ChordProgression"}constructor(t){super(0,t),this.chords=[]}addChord(t,e,i){const s=new ChordProgressionChord(t,e,i);let n=!1;for(const t of this.chords)if(t.start>=s.start&&t.end<=s.end)t.duration=0,n=!0;else if(t.end>s.start&&t.end<s.end)t.end=s.start;else if(t.start<s.end&&t.start>s.start){const e=t.end;t.start=s.end,t.end=e}return n&&this.removeChords((t=>0==t.duration)),this.chords.push(s),this}removeChords(t){this.chords=this.chords.filter((e=>!t(e)))}getChordsInRange(t,e){const i=[];for(const s of this.chords)if(t<=e){Math.max(t,s.start)<Math.min(e,s.end)&&i.push(s)}else(s.start<e||s.end>t)&&i.push(s);return i}getChordAt(t){return t=s(t,this.duration),this.chords.find((e=>e.start<=t&&e.end>t))}}class ChordEventData extends ShimiEventData{get chord(){return this._chord}constructor(t,e){super(t),this._chord=e}}class ChordEvent extends ShimiEvent{}class ChordProgressionPlayer{get typeName(){return"shimi.ChordProgressionPlayer"}get chordProgression(){return this._chordProgression}set chordProgression(t){this._chordProgression!==t&&(this._chordProgression=t)}get metronome(){return this._metronome}set metronome(t){this._metronome=t}get speed(){return this._speed}set speed(t){this._speed=t}get startBeat(){return this._startBeat}set startBeat(t){this._startBeat=t}get beatCount(){return this._beatCount}set beatCount(t){this._beatCount=t}get beatsPassed(){return this._beatsPassed}get ref(){return this._ref}set ref(t){this._ref=t}get isFinished(){return this._isFinished}get finished(){return this._finished}get currentChord(){return this._currentChord}get chordChanged(){return this._chordChanged}constructor(t,e){this._speed=1,this._startBeat=0,this._beatCount=null,this._beatsPassed=0,this._isFinished=!1,this._finished=new ClockChildFinishedEvent,this._chordChanged=new ChordEvent,this.chordProgression=t,this.metronome=e,i.default&&i.default.addChild(this)}update(t){const e=(this.metronome.totalBeat-this.metronome.totalBeatTracker.oldValue)*this.speed;if(0==e)return;const i=this.beatsPassed+e,s=(this.startBeat+i)%this.chordProgression.duration;if(this._beatsPassed+=e,"number"==typeof this.beatCount&&this.beatsPassed>=this.beatCount)return void this.finish();const n=this.chordProgression.getChordAt(s);n!==this.currentChord&&(this._currentChord=n,this.chordChanged.trigger(new ChordEventData(this,null==n?void 0:n.chord)))}finish(){this._isFinished=!0,this.finished.trigger(new ClockChildFinishedEventData(this))}withRef(t){return this._ref=t,this}}class LinearTween{get typeName(){return"shimi.LinearTween"}get from(){return this._from}get to(){return this._to}constructor(t,e){this._from=t,this._to=e}update(t){return this.from+this.tweenEquation(t)*(this.to-this.from)}tweenEquation(t){return t}then(t,e=1){return new MultiTween(this).then(t,e)}toJSON(){return{type:"Linear",from:this.from,to:this.to}}}class MultiTween{get typeName(){return"shimi.MultiTween"}constructor(t,e=1){this._children=[],this._children.push({tween:t,weight:e})}get from(){return this._children[0].tween.from}get to(){return this._children[this._children.length-1].tween.to}update(t){const e=c(this._children,(t=>t.weight))*t;let i=0;for(const t of this._children){if(i<=e&&i+t.weight>=e){const s=(e-i)/t.weight;return t.tween.update(s)}i+=t.weight}}then(t,e=1){return this._children.push({tween:t,weight:e}),this}toJSON(){return{type:"Multi",children:this._children.map((t=>{const e=t.tween.toJSON();return e.weight=t.weight,e}))}}}class SineInOutTween extends LinearTween{get typeName(){return"shimi.SineInOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){return-(Math.cos(Math.PI*t)-1)/2}toJSON(){return{type:"SineInOut",from:this.from,to:this.to}}}class SineInTween extends LinearTween{get typeName(){return"shimi.SineInTween"}constructor(t,e){super(t,e)}tweenEquation(t){return 1-Math.cos(t*Math.PI/2)}toJSON(){return{type:"SineIn",from:this.from,to:this.to}}}class SineOutTween extends LinearTween{get typeName(){return"shimi.SineOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){return Math.sin(t*Math.PI/2)}toJSON(){return{type:"SineOut",from:this.from,to:this.to}}}class StepsTween extends LinearTween{get typeName(){return"shimi.StepsTween"}get steps(){return this._steps}set steps(t){this._steps=t}constructor(t,e,i){super(t,e),this.steps=i}tweenEquation(t){return t=Math.min(t,.999),Math.floor(t*(this.steps+1))/this.steps}toJSON(){return{type:"Steps",from:this.from,to:this.to,steps:this.steps}}}class QuadraticInOutTween extends LinearTween{get typeName(){return"shimi.QuadraticInOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){if(t<.5)return 2*t*t;{const e=1-t;return 1-2*e*e}}toJSON(){return{type:"QuadraticInOut",from:this.from,to:this.to}}}class QuadraticInTween extends LinearTween{get typeName(){return"shimi.QuadraticInTween"}constructor(t,e){super(t,e)}tweenEquation(t){return t*t}toJSON(){return{type:"QuadraticIn",from:this.from,to:this.to}}}class QuadraticOutTween extends LinearTween{get typeName(){return"shimi.QuadraticOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){const e=1-t;return 1-e*e}toJSON(){return{type:"QuadraticOut",from:this.from,to:this.to}}}class CubicInOutTween extends LinearTween{get typeName(){return"shimi.CubicInOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){return t<.5?(t*=2,Math.pow(t,3)/2):(t=2*(1-t),1-Math.pow(t,3)/2)}toJSON(){return{type:"CubicInOut",from:this.from,to:this.to}}}class CubicInTween extends LinearTween{get typeName(){return"shimi.CubicInTween"}constructor(t,e){super(t,e)}tweenEquation(t){return Math.pow(t,3)}toJSON(){return{type:"CubicIn",from:this.from,to:this.to}}}class CubicOutTween extends LinearTween{get typeName(){return"shimi.CubicOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){const e=1-t;return 1-Math.pow(e,3)}toJSON(){return{type:"CubicOut",from:this.from,to:this.to}}}class QuarticInOutTween extends LinearTween{get typeName(){return"shimi.QuarticInOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){return t<.5?(t*=2,Math.pow(t,4)/2):(t=2*(1-t),1-Math.pow(t,4)/2)}toJSON(){return{type:"QuarticInOut",from:this.from,to:this.to}}}class QuarticInTween extends LinearTween{get typeName(){return"shimi.QuarticInTween"}constructor(t,e){super(t,e)}tweenEquation(t){return Math.pow(t,4)}toJSON(){return{type:"QuarticIn",from:this.from,to:this.to}}}class QuarticOutTween extends LinearTween{get typeName(){return"shimi.QuarticOutTween"}constructor(t,e){super(t,e)}tweenEquation(t){const e=1-t;return 1-Math.pow(e,4)}toJSON(){return{type:"QuarticOut",from:this.from,to:this.to}}}class Tween{static multi(t,e=1){return new MultiTween(t,e)}static linear(t,e){return new LinearTween(t,e)}static sineInOut(t,e){return new SineInOutTween(t,e)}static sineIn(t,e){return new SineInTween(t,e)}static sineOut(t,e){return new SineOutTween(t,e)}static steps(t,e,i){return new StepsTween(t,e,i)}static quadraticInOut(t,e){return new QuadraticInOutTween(t,e)}static quadraticIn(t,e){return new QuadraticInTween(t,e)}static quadraticOut(t,e){return new QuadraticOutTween(t,e)}static cubicInOut(t,e){return new CubicInOutTween(t,e)}static cubicIn(t,e){return new CubicInTween(t,e)}static cubicOut(t,e){return new CubicOutTween(t,e)}static quarticInOut(t,e){return new QuarticInOutTween(t,e)}static quarticIn(t,e){return new QuarticInTween(t,e)}static quarticOut(t,e){return new QuarticOutTween(t,e)}static load(t){const e=t.type;if("Multi"==e){const e=t.children.map((t=>({tween:Tween.load(t),weight:t.weight}))),i=new MultiTween(e[0].tween,e[0].weight);for(let t=1;t<e.length;t++)i.then(e[t].tween,e[t].weight);return i}const i=t.from,s=t.to;switch(e){case"Linear":return Tween.linear(i,s);case"SineInOut":return Tween.sineInOut(i,s);case"SineIn":return Tween.sineIn(i,s);case"SineOut":return Tween.sineOut(i,s);case"Steps":return Tween.steps(i,s,t.steps);case"QuadraticInOut":return Tween.quadraticInOut(i,s);case"QuadraticIn":return Tween.quadraticIn(i,s);case"QuadraticOut":return Tween.quadraticOut(i,s);case"CubicInOut":return Tween.cubicInOut(i,s);case"CubicIn":return Tween.cubicIn(i,s);case"CubicOut":return Tween.cubicOut(i,s);case"QuarticInOut":return Tween.quarticInOut(i,s);case"QuarticIn":return Tween.quarticIn(i,s);case"QuarticOut":return Tween.quarticOut(i,s)}throw new Error("Unrecognised tween type: "+e)}}class ClipNote extends Range{get typeName(){return"shimi.ClipNote"}get pitch(){return this._pitch}set pitch(t){this._pitch=t}get velocity(){return this._velocity}set velocity(t){this._velocity=t}get channel(){return this._channel}set channel(t){this._channel=t}constructor(t,e,i,s,n=null,a=null){super(t,e),this._channel=null,this.pitch="string"==typeof i?r(i):i,this.velocity=s,this.channel=n,this.ref=a}createNote(t,e){var i;return new Note(this.pitch,"number"==typeof this.velocity?this.velocity:this.velocity.update(e),null!==(i=this.channel)&&void 0!==i?i:t,this.ref)}duplicate(){return new ClipNote(this.start,this.duration,this.pitch,this.velocity,this.channel,this.ref)}toJSON(){const t={start:this.start,duration:this.duration,pitch:this.pitch,velocity:this.velocity};return this.channel&&(t.channel=this.channel),this.ref&&(t.ref=this.ref),t}static load(t){const e="number"==typeof t.velocity?t.velocity:Tween.load(t.velocity);return new ClipNote(t.start,t.duration,t.pitch,e,t.channel,t.ref)}}class ClipCC extends Range{get typeName(){return"shimi.ClipCC"}get controller(){return this._controller}set controller(t){this._controller=t}get value(){return this._value}set value(t){this._value=t}get channel(){return this._channel}set channel(t){this._channel=t}constructor(t,e,i,s,n=null){super(t,e),this._channel=null,this.controller=i,this.value=s,this.channel=n}duplicate(){return new ClipCC(this.start,this.duration,this.controller,this.value,this.channel)}toJSON(){const t={start:this.start,duration:this.duration,controller:this.controller,value:this.value};return this.channel&&(t.channel=this.channel),t}static load(t){const e="number"==typeof t.value?t.value:Tween.load(t.value);return new ClipCC(t.start,t.duration,t.controller,e,t.channel)}}class ClipBend extends Range{get typeName(){return"shimi.ClipBend"}get percent(){return this._percent}set percent(t){this._percent=t}get channel(){return this._channel}set channel(t){this._channel=t}constructor(t,e,i,s=null){super(t,e),this._channel=null,this.percent=i,this.channel=s}duplicate(){return new ClipBend(this.start,this.duration,this.percent,this.channel)}toJSON(){const t={start:this.start,duration:this.duration,percent:this.percent};return this.channel&&(t.channel=this.channel),t}static load(t){const e="number"==typeof t.percent?t.percent:Tween.load(t.percent);return new ClipBend(t.start,t.duration,e,t.channel)}}class Clip extends Range{get typeName(){return"shimi.Clip"}constructor(t){super(0,t),this.notes=[],this.controlChanges=[],this.bends=[]}addNote(t,e,i,s,n=null,r=null){"number"==typeof t&&(t=[t]),"number"!=typeof i&&"string"!=typeof i||(i=[i]);for(const a of t)for(const t of i)this.notes.push(new ClipNote(a,e,t,s,n,r));return this}addCC(t,e,i,s,n=null){"number"==typeof t&&(t=[t]);for(const r of t)this.controlChanges.push(new ClipCC(r,e,i,s,n));return this}addBend(t,e,i,s=null){"number"==typeof t&&(t=[t]);for(const n of t)this.bends.push(new ClipBend(n,e,i,s));return this}duplicate(){const t=new Clip(this.duration);return t.notes.push(...this.notes.map((t=>t.duplicate()))),t.controlChanges.push(...this.controlChanges.map((t=>t.duplicate()))),t.bends.push(...this.bends.map((t=>t.duplicate()))),t}quantize(t,e=1){if(!t||0==t.length)throw new Error("You must provide a rhythm to quantize notes to");if(null!=t.find((t=>t<=0)))throw new Error("Quantize rhythm must contain only positive non-zero values");e=Math.min(1,Math.max(0,e));const i=c(t,(t=>t));for(const s of this.notes){let n=Math.floor(s.start/i)*i,r=n;for(const e of t)n+=e,Math.abs(n-s.start)<Math.abs(r-s.start)&&(r=n);r%=this.duration,s.start+=e*(r-s.start)}return this}transpose(t){for(const e of this.notes)e.pitch+=t;return this}invert(t){for(const e of this.notes)e.pitch=2*t-e.pitch;return this}reverse(){for(const t of this.notes)t.start=this.end-t.end;for(const t of this.controlChanges)t.start=this.end-t.end;for(const t of this.bends)t.start=this.end-t.end;return this}getNotesStartingInRange(t,e){return this._getChildrenStartingInRange(this.notes,t,e)}getNotesEndingInRange(t,e){return this._getChildrenEndingInRange(this.notes,t,e)}getControlChangesIntersectingRange(t,e){return this._getChildrenIntersectingRange(this.controlChanges,t,e)}getBendsIntersectingRange(t,e){return this._getChildrenIntersectingRange(this.bends,t,e)}_getChildrenStartingInRange(t,e,i){return e<=i?t.filter((t=>t.start>=e&&t.start<i)):t.filter((t=>t.start>=e||t.start<i))}_getChildrenEndingInRange(t,e,i){return e<=i?t.filter((t=>t.end>=e&&t.end<i)):t.filter((t=>t.end>=e||t.end<i))}_getChildrenIntersectingRange(t,e,i){return e<=i?t.filter((t=>Math.min(i,t.end)>=Math.max(e,t.start))):t.filter((t=>t.end>=e||t.start<=i))}toJSON(){return{start:this.start,duration:this.duration,notes:this.notes,controlChanges:this.controlChanges,bends:this.bends}}static load(t){const e=new Clip(t.duration);return e.start=t.start,e.notes.push(...t.notes.map((t=>ClipNote.load(t)))),e.controlChanges.push(...t.controlChanges.map((t=>ClipCC.load(t)))),e.bends.push(...t.bends.map((t=>ClipBend.load(t)))),e}}class MidiMessageBase{validateIntInRange(t,e,i,s){if((t=Math.round(t))<e)throw new Error(s+" cannot be less than "+e);if(t>i)throw new Error(s+" cannot be greater than "+i);return t}}class NoteOffMessage extends MidiMessageBase{get typeName(){return"shimi.NoteOffMessage"}constructor(t,e,i){super(),this.pitch=0,this.velocity=0,this.channel=0,this.pitch="string"==typeof t?r(t):t,this.velocity=e,this.channel=i}toArray(){return[128+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.pitch,0,127,"pitch"),this.validateIntInRange(this.velocity,0,127,"velocity")]}duplicate(){return new NoteOffMessage(this.pitch,this.velocity,this.channel)}}class NoteOnMessage extends MidiMessageBase{get typeName(){return"shimi.NoteOnMessage"}constructor(t,e,i){super(),this.pitch=0,this.velocity=0,this.channel=0,this.pitch="string"==typeof t?r(t):t,this.velocity=e,this.channel=i}toArray(){return[144+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.pitch,0,127,"pitch"),this.validateIntInRange(this.velocity,0,127,"velocity")]}duplicate(){return new NoteOnMessage(this.pitch,this.velocity,this.channel)}}class NotePressureMessage extends MidiMessageBase{get typeName(){return"shimi.NotePressureMessage"}constructor(t,e,i){super(),this.pitch=0,this.velocity=0,this.channel=0,this.pitch="string"==typeof t?r(t):t,this.velocity=e,this.channel=i}toArray(){return[160+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.pitch,0,127,"pitch"),this.validateIntInRange(this.velocity,0,127,"velocity")]}duplicate(){return new NotePressureMessage(this.pitch,this.velocity,this.channel)}}class ControlChangeMessage extends MidiMessageBase{get typeName(){return"shimi.ControlChangeMessage"}constructor(t,e,i){super(),this.controller=0,this.value=0,this.channel=0,this.controller=t,this.value=e,this.channel=i}toArray(){return[176+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.controller,0,127,"controller"),this.validateIntInRange(this.value,0,127,"value")]}duplicate(){return new ControlChangeMessage(this.controller,this.value,this.channel)}}class ProgramChangeMessage extends MidiMessageBase{get typeName(){return"shimi.ProgramChangeMessage"}constructor(t,e){super(),this.program=0,this.channel=0,this.program=t,this.channel=e}toArray(){return[192+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.program,0,127,"program")]}duplicate(){return new ProgramChangeMessage(this.program,this.channel)}}class ChannelPressureMessage extends MidiMessageBase{get typeName(){return"shimi.ChannelPressureMessage"}constructor(t,e){super(),this.value=t,this.channel=e}toArray(){return[208+this.validateIntInRange(this.channel,0,15,"channel"),this.validateIntInRange(this.value,0,127,"value")]}duplicate(){return new ChannelPressureMessage(this.value,this.channel)}}class PitchBendMessage extends MidiMessageBase{get typeName(){return"shimi.PitchBendMessage"}constructor(t,e){super(),this.percent=t,this.channel=e}toArray(){if(this.percent<-1)throw new Error("percent cannot be less than -1");if(this.percent>1)throw new Error("percent cannot be greater than 1");const t=Math.min(16383,this.validateIntInRange(8192*this.percent+8192,0,16384,"bend"));return[224+this.validateIntInRange(this.channel,0,15,"channel"),t%128,Math.floor(t/128)]}duplicate(){return new PitchBendMessage(this.percent,this.channel)}static calculatePercent(t,e){let i=128*e+t;return i>=16383&&i<16384&&(i=16384),(i-8192)/8192}}class TickMessage{get typeName(){return"shimi.TickMessage"}constructor(){}toArray(){return[248]}duplicate(){return new TickMessage}}class SongPositionMessage{get typeName(){return"shimi.SongPositionMessage"}constructor(t){this.value=t}toArray(){if(this.value<0)throw new Error("value cannot be less than 0");if(this.value>16383)throw new Error("value cannot be greater than 16383");return[242,this.value%128,Math.floor(this.value/128)]}duplicate(){return new SongPositionMessage(this.value)}}class StartMessage{get typeName(){return"shimi.StartMessage"}constructor(){}toArray(){return[250]}duplicate(){return new StartMessage}}class ContinueMessage{get typeName(){return"shimi.ContinueMessage"}constructor(){}toArray(){return[251]}duplicate(){return new ContinueMessage}}class StopMessage{get typeName(){return"shimi.StopMessage"}constructor(){}toArray(){return[252]}duplicate(){return new StopMessage}}class ClipPlayer{get typeName(){return"shimi.ClipPlayer"}get clip(){return this._clip}set clip(t){this._clip!==t&&(this._endAllNotes(),this._clip=t)}get channel(){return this._channel}set channel(t){this._channel=t}get ref(){return this._ref}set ref(t){this._ref=t}get metronome(){return this._metronome}set metronome(t){this._metronome=t}get midiOut(){return this._midiOut}set midiOut(t){this._midiOut=t}get speed(){return this._speed}set speed(t){this._speed=t}get startBeat(){return this._startBeat}set startBeat(t){this._startBeat=t}get beatCount(){return this._beatCount}set beatCount(t){this._beatCount=t}get running(){return this._running}set running(t){this._running=t}get noteModifier(){return this._noteModifier}set noteModifier(t){this._noteModifier=t}get beatsPassed(){return this._beatsPassed}get isFinished(){return this._isFinished}get finished(){return this._finished}get muteNotes(){return this._muteNotes}set muteNotes(t){this._muteNotes=t,this._muteNotes&&this._endAllNotes()}get muteCCs(){return this._muteCCs}set muteCCs(t){this._muteCCs=t}get muteBends(){return this._muteBends}set muteBends(t){this._muteBends=t}get muteAll(){return this.muteNotes&&this.muteCCs&&this.muteBends}set muteAll(t){this.muteNotes=t,this.muteCCs=t,this.muteBends=t}constructor(t,e,s){this._channel=0,this._speed=1,this._startBeat=0,this._beatCount=null,this._running=!0,this._beatsPassed=0,this._isFinished=!1,this._finished=new ClockChildFinishedEvent,this._muteNotes=!1,this._muteCCs=!1,this._muteBends=!1,this._notes=[],this.clip=t,this.metronome=e,this.midiOut=s,i.default&&i.default.addChild(this)}start(){this.running=!0}pause(){this.running=!1}stop(){this.running=!1,this._beatsPassed=0}update(t){var e,i;if(!(this.running&&this.clip&&this.metronome&&this.midiOut))return;const s=(this.metronome.totalBeat-this.metronome.totalBeatTracker.oldValue)*this.speed;if(0==s)return;const n=this.beatsPassed,r=this.beatsPassed+s,a=(this.startBeat+n)%this.clip.duration,h=(this.startBeat+r)%this.clip.duration;if(a>h&&this._endAllNotes(),this._beatsPassed+=s,"number"==typeof this.beatCount&&this.beatsPassed>=this.beatCount)this.finish();else{for(const t of this._notes){const e=t.clipNote;e.contains(h)&&this.clip.notes.find((t=>t===e))?"number"!=typeof e.velocity&&(t.velocity=e.velocity.update((h-e.start)/e.duration)):t.stop()}if(this._notes=this._notes.filter((t=>t.on)),!this.muteNotes)for(const t of this.clip.getNotesStartingInRange(a,h)){const e=t.createNote(this.channel,(h-t.start)/t.duration);e.clipNote=t,this.noteModifier&&this.noteModifier(e),this._notes.push(e),this.midiOut.addNote(e)}if(!this.muteCCs)for(const t of this.clip.getControlChangesIntersectingRange(a,h)){const i="function"==typeof t.value;h>t.end&&t.start<a&&!i||this.midiOut.sendMessage(new ControlChangeMessage(t.controller,"number"==typeof t.value?t.value:t.value.update(Math.min(1,(h-t.start)/t.duration)),null!==(e=t.channel)&&void 0!==e?e:this.channel))}if(!this.muteBends)for(const t of this.clip.getBendsIntersectingRange(a,h)){const e="function"==typeof t.percent;h>t.end&&t.start<a&&!e||this.midiOut.sendMessage(new PitchBendMessage("number"==typeof t.percent?t.percent:t.percent.update(Math.min(1,(h-t.start)/t.duration)),null!==(i=t.channel)&&void 0!==i?i:this.channel))}}}finish(){this._isFinished=!0,this._endAllNotes(),this.finished.trigger(new ClockChildFinishedEventData(this))}withRef(t){return this._ref=t,this}_endAllNotes(){for(const t of this._notes)t.stop();this._notes=[]}}class ClipRecorderEventData extends ShimiEventData{get clip(){return this._clip}constructor(t,e){super(t),this._clip=e}}class ClipRecorderEvent extends ShimiEvent{}class ClipRecorder{get typeName(){return"shimi.ClipRecorder"}get metronome(){return this._metronome}set metronome(t){this._metronome=t}get midiIn(){return this._midiIn}set midiIn(t){this._midiIn!=t&&(this._removeMidiInSubscriptions(),this._midiIn=t,this._addMidiInSubscriptions())}_addMidiInSubscriptions(){this._midiIn&&!this.isFinished&&(this._midiIn.noteOn.add(this._onNoteOn),this._midiIn.noteOff.add(this._onNoteOff),this._midiIn.controlChange.add(this._onControlChange),this._midiIn.pitchBend.add(this._onPitchBend))}_removeMidiInSubscriptions(){this._midiIn&&(this._midiIn.noteOn.remove((t=>t.logic==this._onNoteOn)),this._midiIn.noteOff.remove((t=>t.logic==this._onNoteOff)),this._midiIn.controlChange.remove((t=>t.logic==this._onControlChange)),this._midiIn.pitchBend.remove((t=>t.logic==this._onPitchBend)))}get beatCount(){return this._beatCount}set beatCount(t){this._beatCount=t,this._clip.duration=null==t?0:t}get beatsPassed(){return this._beatsPassed}get newClip(){return this._newClip}constructor(t,e){this._beatCount=4,this._beatsPassed=0,this._clip=new Clip(4),this._newClip=new ClipRecorderEvent,this._inProgressNotes=[],this._onNoteOn=t=>{const e=t.message;this._inProgressNotes.push(new ClipNote(this._getClipPosition(this.beatsPassed),0,e.pitch,e.velocity,e.channel))},this._onNoteOff=t=>{const e=t.message,i=this._inProgressNotes.find((t=>t.pitch==e.pitch&&t.channel==e.channel));i&&(i.end=this._getClipPosition(this.beatsPassed),this._clip.notes.push(i),this._inProgressNotes=this._inProgressNotes.filter((t=>t.pitch!=e.pitch||t.channel!=e.channel)))},this._onControlChange=t=>{const e=t.message;this._clip.controlChanges.push(new ClipCC(this._getClipPosition(this.beatsPassed),0,e.controller,e.value,e.channel))},this._onPitchBend=t=>{const e=t.message;this._clip.bends.push(new ClipBend(this._getClipPosition(this.beatsPassed),0,e.percent,e.channel))},this._isFinished=!1,this._finished=new ClockChildFinishedEvent,this.metronome=t,this.midiIn=e,i.default&&i.default.addChild(this)}_getClipPosition(t){return null==this.beatCount?t:t%this._clip.duration}get ref(){return this._ref}set ref(t){this._ref=t}update(t){if(this.isFinished||!this.midiIn||!this.metronome)return;const e=this.metronome.totalBeat-this.metronome.totalBeatTracker.oldValue;if(0==e)return;const i=this.beatsPassed,s=this.beatsPassed+e;this._getClipPosition(i),this._getClipPosition(s);this._beatsPassed+=e,null!=this.beatCount&&this.beatsPassed>=this.beatCount&&this.finish()}get isFinished(){return this._isFinished}get finished(){return this._finished}finish(){this._isFinished=!0,this._removeMidiInSubscriptions(),null==this.beatCount&&(this._clip.duration=this.beatsPassed);for(const t of this._inProgressNotes)t.end=this._clip.duration,this._clip.notes.push(t);this._inProgressNotes=[],this.newClip.trigger(new ClipRecorderEventData(this,this._clip)),this.finished.trigger(new ClockChildFinishedEventData(this))}withRef(t){return this._ref=t,this}}class CueBase{get ref(){return this._ref}set ref(t){this._ref=t}get isFinished(){return this._isFinished}get finished(){return this._finished}get action(){return this._action}constructor(t){this._isFinished=!1,this._finished=n