audio-mixer-engine 0.5.1 → 0.5.3

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/README.md CHANGED
@@ -757,6 +757,33 @@ player.setBar(9); // Jump to Chorus
757
757
  player.setBar(1, 1); // Jump to Verse, second time through
758
758
  ```
759
759
 
760
+ ## Metadata and Score Configuration
761
+
762
+ The library supports comprehensive metadata to override MIDI file information and configure playback behavior. See [METADATA.md](./METADATA.md) for the complete metadata specification including:
763
+
764
+ - **Score metadata overrides**: Title, composer, arranger, copyright
765
+ - **Part configuration**: Custom part names, track mapping, instrument overrides
766
+ - **Playback modifiers**: Semitone shift, playback speed adjustment
767
+ - **Structure metadata**: Non-linear playback with sections and repeats (see also [BEATMAPPING.md](./BEATMAPPING.md))
768
+
769
+ ```javascript
770
+ // Example: Load with metadata overrides
771
+ const metadata = {
772
+ title: "Amazing Grace",
773
+ composer: "John Newton",
774
+ semitoneShift: -2, // Transpose down 2 semitones
775
+ playbackSpeed: 0.8, // Slow to 80% speed
776
+ parts: {
777
+ "soprano": { trackIndex: 0, instrument: 52 },
778
+ "alto": { trackIndex: 1, instrument: 52 }
779
+ },
780
+ sections: [...], // Structure for non-linear playback
781
+ order: [...]
782
+ };
783
+
784
+ await playbackManager.load(midiBuffer, metadata);
785
+ ```
786
+
760
787
  ## Use Cases
761
788
 
762
789
  This library is specifically designed for:
@@ -1 +1 @@
1
- "use strict";var P=Object.create;var T=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var O=(d,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of E(t))!B.call(d,s)&&s!==e&&T(d,s,{get:()=>t[s],enumerable:!(i=M(t,s))||i.enumerable});return d};var N=(d,t,e)=>(e=d!=null?P(S(d)):{},O(t||!d||!d.__esModule?T(e,"default",{value:d,enumerable:!0}):e,d));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D="data:audio/mpeg;base64,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",z="data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//tkxPIADij5M+wwzYmAm6X9hJmwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//s0xPaAClDTI6OxLwCwkeLoEJkoqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAAB/gAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";class g{constructor(t,e={}){if(new.target===g)throw new Error("AudioEngine is abstract and cannot be instantiated directly");this.audioContext=t,this.options=e,this.isInitialized=!1,this.channels=new WeakMap,this.activeChannels=new Set}async initialize(t){throw new Error("initialize() must be implemented by subclass")}createChannel(t,e={}){throw new Error("createChannel() must be implemented by subclass")}allSoundsOff(){throw new Error("allSoundsOff() must be implemented by subclass")}async playMetronomeTick(t,e,i){try{await this._ensureMetronomeBuffersLoaded();const s=e?this.accentTickBuffer:this.regularTickBuffer;if(!s){console.warn("Metronome buffer not available");return}const n=this.audioContext.createBufferSource();n.buffer=s;const a=this.audioContext.createGain();a.gain.value=i,n.connect(a);const r=this.getMetronomeOutput();r?a.connect(r):a.connect(this.audioContext.destination);const q=Math.max(t,this.audioContext.currentTime);n.start(q)}catch(s){console.warn("Buffer metronome playback failed:",s)}}getMetronomeOutput(){return this._metronomeOutput||(this._metronomeOutput=this.audioContext.createGain(),this._metronomeOutput.gain.value=1,this._metronomeOutput.connect(this.audioContext.destination)),this._metronomeOutput}async _ensureMetronomeBuffersLoaded(){if(!(this.regularTickBuffer&&this.accentTickBuffer)){try{if(typeof fetch<"u"){const[t,e]=await Promise.all([fetch(D),fetch(z)]),[i,s]=await Promise.all([t.arrayBuffer(),e.arrayBuffer()]),[n,a]=await Promise.all([this.audioContext.decodeAudioData(i),this.audioContext.decodeAudioData(s)]);this.regularTickBuffer=n,this.accentTickBuffer=a;return}}catch(t){console.warn("Failed to load metronome sounds:",t)}this.regularTickBuffer=this.audioContext.createBuffer(2,1024,this.audioContext.sampleRate),this.accentTickBuffer=this.audioContext.createBuffer(2,1024,this.audioContext.sampleRate)}}getActiveChannels(){return Array.from(this.activeChannels)}destroy(){this.allSoundsOff(),this._metronomeOutput&&(this._metronomeOutput.disconnect(),this._metronomeOutput=null),this.regularTickBuffer=null,this.accentTickBuffer=null,this.activeChannels.clear(),this.isInitialized=!1}_validateInitialized(){if(!this.isInitialized)throw new Error("AudioEngine not initialized. Call initialize() first.")}_registerChannel(t){this.activeChannels.add(t)}_unregisterChannel(t){this.activeChannels.delete(t),this.channels.delete(t)}}class y{constructor(t,e,i={}){if(new.target===y)throw new Error("ChannelHandle is abstract and cannot be instantiated directly");this.engine=t,this.partId=e,this.options={initialVolume:1,...i},this.isDestroyed=!1,this.noteRefCounts=new Map,this.scheduledEvents=new Map,this.activeNotes=new Set}getOutputNode(){throw new Error("getOutputNode() must be implemented by subclass")}noteOn(t,e){this._validateActive();const i=this.noteRefCounts.get(t)||0;this.noteRefCounts.set(t,i+1),this._actualNoteOn(t,e),i===0&&this.activeNotes.add(t)}noteOff(t){this._validateActive();const e=this.noteRefCounts.get(t)||0;if(e<=0)return;const i=e-1;this.noteRefCounts.set(t,i),i===0&&(this._actualNoteOff(t),this.activeNotes.delete(t),this.noteRefCounts.delete(t))}playNote(t,e,i,s){this._validateActive();const n=this.engine.audioContext.currentTime,a=`${this.partId}_${t}_${e}_${Date.now()}`;let r=t,q=s;if(t<n){const m=n-t;r=n,q=Math.max(0,s-m)}if(q<=0)return a;const o=Math.max(0,(r-n)*1e3),l=setTimeout(()=>{this.noteOn(e,i),this.scheduledEvents.delete(`${a}_on`)},o),h=o+q*1e3,c=setTimeout(()=>{this.noteOff(e),this.scheduledEvents.delete(`${a}_off`)},h);return this.scheduledEvents.set(`${a}_on`,l),this.scheduledEvents.set(`${a}_off`,c),a}playPreviewNote(t,e={}){this._validateActive();const i=e.startTime??this.engine.audioContext.currentTime+.01,s=e.duration??.5,n=e.velocity??100;let a=null;e.instrument!==void 0&&(a=this.getInstrument(),this.setInstrument(e.instrument)),this.playNote(i,t,n,s),a!==null&&setTimeout(()=>{this.isDestroyed||this.setInstrument(a)},(s+.1)*1e3)}allNotesOff(){this._validateActive(),this.scheduledEvents.forEach(t=>{clearTimeout(t)}),this.scheduledEvents.clear(),this.activeNotes.forEach(t=>{this._actualNoteOff(t)}),this.noteRefCounts.clear(),this.activeNotes.clear()}_actualNoteOn(t,e){throw new Error("_actualNoteOn() must be implemented by subclass")}_actualNoteOff(t){throw new Error("_actualNoteOff() must be implemented by subclass")}async setInstrument(t){throw new Error("setInstrument() must be implemented by subclass")}getInstrument(){throw new Error("getInstrument() must be implemented by subclass")}setVolume(t){throw new Error("setVolume() must be implemented by subclass")}getVolume(){throw new Error("getVolume() must be implemented by subclass")}getPartId(){return this.partId}isActive(){return!this.isDestroyed&&this.engine.isInitialized&&this.engine.activeChannels.has(this)}destroy(){if(!this.isDestroyed){this.allNotesOff();const t=this.getOutputNode();t&&t.disconnect(),this.noteRefCounts.clear(),this.scheduledEvents.clear(),this.activeNotes.clear(),this.engine._unregisterChannel(this),this.isDestroyed=!0}}_validateActive(){if(this.isDestroyed)throw new Error("Channel has been destroyed");if(!this.engine.isInitialized)throw new Error("AudioEngine is not initialized")}}const I={piano:0,bright_piano:1,electric_grand:2,honky_tonk:3,electric_piano_1:4,electric_piano_2:5,harpsichord:6,clavinet:7,celesta:8,glockenspiel:9,music_box:10,vibraphone:11,marimba:12,xylophone:13,tubular_bells:14,dulcimer:15,drawbar_organ:16,percussive_organ:17,rock_organ:18,church_organ:19,reed_organ:20,accordion:21,harmonica:22,tango_accordion:23,organ:19,nylon_guitar:24,steel_guitar:25,electric_guitar_jazz:26,electric_guitar_clean:27,electric_guitar_muted:28,overdriven_guitar:29,distortion_guitar:30,guitar_harmonics:31,guitar:24,acoustic_bass:32,electric_bass_finger:33,electric_bass_pick:34,fretless_bass:35,slap_bass_1:36,slap_bass_2:37,synth_bass_1:38,synth_bass_2:39,bass:32,violin:40,viola:41,cello:42,contrabass:43,tremolo_strings:44,pizzicato_strings:45,orchestral_harp:46,timpani:47,strings:48,strings_ensemble:48,slow_strings:49,synth_strings_1:50,synth_strings_2:51,choir_aahs:52,voice_oohs:53,synth_voice:54,orchestra_hit:55,trumpet:56,trombone:57,tuba:58,muted_trumpet:59,french_horn:60,brass_section:61,synth_brass_1:62,synth_brass_2:63,soprano_sax:64,alto_sax:65,tenor_sax:66,baritone_sax:67,oboe:68,english_horn:69,bassoon:70,clarinet:71,saxophone:64,piccolo:72,flute:73,recorder:74,pan_flute:75,blown_bottle:76,shakuhachi:77,whistle:78,ocarina:79,lead_1_square:80,lead_2_sawtooth:81,lead_3_calliope:82,lead_4_chiff:83,lead_5_charang:84,lead_6_voice:85,lead_7_fifths:86,lead_8_bass:87,pad_1_new_age:88,pad_2_warm:89,pad_3_polysynth:90,pad_4_choir:91,pad_5_bowed:92,pad_6_metallic:93,pad_7_halo:94,pad_8_sweep:95,fx_1_rain:96,fx_2_soundtrack:97,fx_3_crystal:98,fx_4_atmosphere:99,fx_5_brightness:100,fx_6_goblins:101,fx_7_echoes:102,fx_8_sci_fi:103,sitar:104,banjo:105,shamisen:106,koto:107,kalimba:108,bag_pipe:109,fiddle:110,shanai:111,tinkle_bell:112,agogo:113,steel_drums:114,woodblock:115,taiko_drum:116,melodic_tom:117,synth_drum:118,reverse_cymbal:119,guitar_fret_noise:120,breath_noise:121,seashore:122,bird_tweet:123,telephone_ring:124,helicopter:125,applause:126,gunshot:127},L=Object.entries(I).reduce((d,[t,e])=>(d[e]=t,d),{});class _{static getInstrumentProgram(t){if(typeof t=="number")return t;const e=I[t.toLowerCase()];return e!==void 0?e:0}static getProgramName(t){return L[t]||`Program ${t}`}static generateNoteId(t,e,i){return`${t}_${e}_${Math.round(i)}`}}class C extends y{constructor(t,e,i,s={}){super(t,e,s),this.midiChannel=i,this.currentVolume=s.initialVolume||1,this.currentInstrument=s.instrument||"piano",this.outputGain=null,this._setupOutputNode(),this.setVolume(this.currentVolume),s.instrument&&this.setInstrument(s.instrument)}getOutputNode(){return this.outputGain}_actualNoteOn(t,e){const i=this.engine._getSynthesizer();if(i&&i.noteOn){const s=Math.round(e*this.currentVolume);i.noteOn(this.midiChannel,t,s)}}_actualNoteOff(t){const e=this.engine._getSynthesizer();e&&e.noteOff&&e.noteOff(this.midiChannel,t)}async setInstrument(t){this._validateActive();const e=_.getInstrumentProgram(t);this.currentInstrument=t;const i=this.engine._getSynthesizer();i&&i.programChange?i.programChange(this.midiChannel,e):console.warn("Cannot set instrument: synthesizer not available or no programChange method")}getInstrument(){return this.currentInstrument}setVolume(t){this._validateActive(),t=Math.max(0,Math.min(1,t)),this.currentVolume=t;const e=Math.round(t*127),i=this.engine._getSynthesizer();i&&i.controllerChange&&i.controllerChange(this.midiChannel,7,e)}getVolume(){return this.currentVolume}getMidiChannel(){return this.midiChannel}getActiveNoteCount(){return this.activeNotes.size}playNote(t,e,i,s){this._validateActive();const n=`${this.partId}_${t}_${e}_${Date.now()}`,a=this.engine._getSynthesizer();if(a&&a.post){const r=Math.round(i*this.currentVolume);a.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[144|this.midiChannel,e,r],channelOffset:0,force:!1,options:{time:t}}}),a.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[128|this.midiChannel,e,0],channelOffset:0,force:!1,options:{time:t+s}}})}else return super.playNote(t,e,i,s);return n}allNotesOff(){this._validateActive();const t=this.engine._getSynthesizer();t&&t.post?t.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[176|this.midiChannel,123,0],channelOffset:0,force:!1,options:{time:this.engine.audioContext.currentTime}}}):super.allNotesOff()}destroy(){if(!this.isDestroyed){const t=this.engine._getIndividualOutput(this.midiChannel);this.outputGain&&this.outputGain!==t&&this.outputGain.disconnect(),this.outputGain=null}super.destroy()}_setupOutputNode(){const t=this.engine._getIndividualOutput(this.midiChannel);t?this.outputGain=t:(console.warn(`No individual output available for MIDI channel ${this.midiChannel}, using fallback`),this.outputGain=this.engine.audioContext.createGain(),this.outputGain.gain.value=this.currentVolume)}}class U extends g{constructor(t,e={}){super(t,e),this.synthesizer=null,this.soundfont=null,this.channelCounter=0,this.partToMidiChannel=new Map,this.midiChannelToPart=new Map,this.individualOutputs=[]}async initialize(t){const{WorkletSynthesizer:e}=await import("spessasynth_lib");let i;if(typeof t=="string")i=await this._loadSoundfontFromPath(t);else if(t instanceof ArrayBuffer)i=t;else throw new Error("Invalid soundfont data type. Expected string path or ArrayBuffer.");await this._loadAudioWorkletSafely(),this._setupIndividualOutputs(),this.dummyTarget=this.audioContext.createGain(),await new Promise(s=>setTimeout(s,50)),this.synthesizer=new e(this.audioContext),await this.synthesizer.soundBankManager.addSoundBank(i,"main"),await this.synthesizer.isReady,this._connectIndividualOutputs(),this._initializeMetronomeChannel(),this.isInitialized=!0}createChannel(t,e={}){if(this._validateInitialized(),this.partToMidiChannel.has(t))throw new Error(`Channel for part '${t}' already exists`);const i=this.channelCounter;if(i>=15)throw new Error("Maximum number of musical part channels (15) exceeded. Channel 15 is reserved for metronome.");this.channelCounter++,this.partToMidiChannel.set(t,i),this.midiChannelToPart.set(i,t);const s=new C(this,t,i,e);return this._registerChannel(s),e.instrument&&s.setInstrument(e.instrument),s}allSoundsOff(){this.synthesizer&&this.midiChannelToPart.forEach((t,e)=>{this.synthesizer.controllerChange&&this.synthesizer.controllerChange(e,120,0)})}clearAllChannels(){this.allSoundsOff(),this.partToMidiChannel.clear(),this.midiChannelToPart.clear(),this.channelCounter=0}destroy(){this.allSoundsOff(),this.synthesizer&&typeof this.synthesizer.disconnect=="function"&&this.synthesizer.disconnect(),this.individualOutputs.forEach(t=>{t&&t.disconnect&&t.disconnect()}),this.individualOutputs=[],this.dummyTarget&&(this.dummyTarget.disconnect(),this.dummyTarget=null),this.partToMidiChannel.clear(),this.midiChannelToPart.clear(),this.channelCounter=0,super.destroy(),this.synthesizer=null,this.soundfont=null}getMidiChannelForPart(t){return this.partToMidiChannel.has(t)?this.partToMidiChannel.get(t):null}_getSynthesizer(){return this.synthesizer}_getIndividualOutput(t){return t>=0&&t<this.individualOutputs.length?this.individualOutputs[t]:null}getMetronomeChannel(){const t=this._getIndividualOutput(15);return console.log("Metronome channel 15 output:",t?"Available":"NULL",`(total outputs: ${this.individualOutputs.length})`),t}_setupIndividualOutputs(){this.individualOutputs=[];for(let t=0;t<16;t++){const e=this.audioContext.createGain();e.gain.value=1,this.individualOutputs.push(e)}}_connectIndividualOutputs(){try{this.synthesizer&&this.synthesizer.connectIndividualOutputs?this.synthesizer.connectIndividualOutputs(this.individualOutputs):(console.warn("Synthesizer does not support individual outputs, using master output only"),this.synthesizer&&this.synthesizer.connect&&this.audioContext.destination&&this.synthesizer.connect(this.audioContext.destination))}catch(t){console.warn("Failed to connect individual outputs:",t.message),console.warn("Falling back to master output routing")}}async _loadSoundfontFromPath(t){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load soundfont: ${e.status} ${e.statusText}`);return await e.arrayBuffer()}async _loadAudioWorkletSafely(){const t="/node_modules/spessasynth_lib/dist/spessasynth_processor.min.js";for(let i=1;i<=5;i++)try{await this.audioContext.audioWorklet.addModule(t);return}catch(s){if(console.warn(`AudioWorklet loading failed (attempt ${i}/5):`,s.message),i===5)throw new Error(`AudioWorklet failed after 5 attempts: ${s.message}`);const n=i*500;await new Promise(a=>setTimeout(a,n))}}_initializeMetronomeChannel(){try{const t=this._getSynthesizer();if(!t){console.warn("Cannot initialize metronome channel: synthesizer not available");return}const e=15;t.programChange&&(t.programChange(e,115),console.log("Metronome channel 15 initialized with woodblock instrument (115)")),t.controllerChange&&t.controllerChange(e,7,127)}catch(t){console.warn("Failed to initialize metronome channel:",t)}}async playMetronomeTick(t,e,i){try{const s=this.getMetronomeChannel(),n=this._getSynthesizer();if(!s||!n)return super.playMetronomeTick(t,e,i);const a=15,r=e?86:60,o=Math.round(Math.min(127,Math.max(0,i*(e?127:100)))),l=this.audioContext.currentTime,h=Math.max(t,l),c=h-l;n.post?(n.post({channelNumber:a,type:"midiMessage",data:{messageData:[144|a,r,o],channelOffset:0,force:!1,options:{time:h}}}),n.post({channelNumber:a,type:"midiMessage",data:{messageData:[128|a,r,0],channelOffset:0,force:!1,options:{time:h+.1}}})):c<=.01?(n.noteOn&&n.noteOn(a,r,o),setTimeout(()=>{n.noteOff&&n.noteOff(a,r)},100)):setTimeout(()=>{n.noteOn&&n.noteOn(a,r,o),setTimeout(()=>{n.noteOff&&n.noteOff(a,r)},100)},c*1e3)}catch(s){return console.warn("MIDI metronome failed, falling back to buffers:",s),super.playMetronomeTick(t,e,i)}}getMetronomeOutput(){return!this.individualOutputs||this.individualOutputs.length<16?null:this.individualOutputs[15]}}class k{constructor(){this.partNames=["soprano","alto","tenor","bass","treble","mezzo","baritone","s","a","t","b","satb"],this.parsedData={parts:{},barStructure:[],metadata:{}}}async parse(t){try{const e=await this._parseMidiBuffer(t);return this._extractMetadata(e),this._extractBarStructure(e),this._extractParts(e),this.parsedData}catch(e){throw console.error("Error parsing MIDI file:",e),e}}async _parseMidiBuffer(t){const e=new Uint8Array(t);if(!(e[0]===77&&e[1]===84&&e[2]===104&&e[3]===100))throw new Error("Not a valid MIDI file");const i=this._bytesToNumber(e.slice(4,8)),s=this._bytesToNumber(e.slice(8,10)),n=this._bytesToNumber(e.slice(10,12)),a=this._bytesToNumber(e.slice(12,14)),r=a&32768?null:a,q={format:s,ticksPerBeat:r,tracks:[],duration:0};let o=8+i;for(let l=0;l<n;l++)if(e[o]===77&&e[o+1]===84&&e[o+2]===114&&e[o+3]===107){const h=this._bytesToNumber(e.slice(o+4,o+8)),c=e.slice(o+8,o+8+h),m=this._parseTrack(c);q.tracks.push(m),o+=8+h}else throw new Error(`Invalid track header at position ${o}`);return q}_parseTrack(t){const e={notes:[],name:null,lyrics:[],events:[],duration:0};let i=0,s=0,n=null;for(;i<t.length;){let a=0,r=0;do r=t[i++],a=a<<7|r&127;while(r&128);s+=a,r=t[i++];let q=r;if((r&128)===0){if(n===null)throw new Error("Running status byte encountered before status byte");q=n,i--}else n=q;if(q===255){const o=t[i++],l=this._readVariableLengthValue(t,i);i+=l.bytesRead;const h=t.slice(i,i+l.value);switch(i+=l.value,o){case 3:e.name=this._bytesToString(h);break;case 1:e.events.push({type:"text",text:this._bytesToString(h),tick:s});break;case 5:e.lyrics.push({text:this._bytesToString(h),tick:s});break;case 81:const c=this._bytesToNumber(h),m=Math.round(6e7/c);e.events.push({type:"tempo",bpm:m,tick:s});break;case 88:e.events.push({type:"timeSignature",numerator:h[0],denominator:Math.pow(2,h[1]),tick:s});break;case 47:e.duration=s;break}}else if((q&240)===144){const o=q&15,l=t[i++],h=t[i++];h>0?e.notes.push({type:"noteOn",noteNumber:l,velocity:h,tick:s,channel:o}):e.notes.push({type:"noteOff",noteNumber:l,tick:s,channel:o})}else if((q&240)===128){const o=q&15,l=t[i++];t[i++],e.notes.push({type:"noteOff",noteNumber:l,tick:s,channel:o})}else if(q===240||q===247){const o=this._readVariableLengthValue(t,i);i+=o.bytesRead+o.value}else if((q&240)===176){const o=q&15,l=t[i++],h=t[i++];e.events.push({type:"controller",controllerNumber:l,value:h,channel:o,tick:s})}else if((q&240)===192){const o=q&15,l=t[i++];e.events.push({type:"programChange",programNumber:l,channel:o,tick:s})}else if((q&240)===208){const o=q&15,l=t[i++];e.events.push({type:"channelAftertouch",pressure:l,channel:o,tick:s})}else if((q&240)===224){const o=q&15,l=t[i++],c=(t[i++]<<7|l)-8192;e.events.push({type:"pitchBend",value:c,channel:o,tick:s})}else if((q&240)===160){const o=q&15,l=t[i++],h=t[i++];e.events.push({type:"noteAftertouch",noteNumber:l,pressure:h,channel:o,tick:s})}else console.warn(`Unknown event type: ${q.toString(16)} at position ${i-1}`),i++}return e}_extractMetadata(t){const e={title:null,composer:null,partNames:[],format:t.format,ticksPerBeat:t.ticksPerBeat};t.tracks.forEach((i,s)=>{if(i.name&&!e.title&&(e.title=i.name),i.events.filter(n=>n.type==="text").forEach(n=>{const a=n.text.toLowerCase();(a.includes("compos")||a.includes("by"))&&!e.composer&&(e.composer=n.text)}),i.name){const n=i.name.toLowerCase();for(const a of this.partNames)if(n.includes(a)){e.partNames.push({index:s,name:i.name});break}}}),this.parsedData.metadata=e}_extractBarStructure(t){const e=t.ticksPerBeat||480,i=[];t.tracks.forEach(l=>{l.events.forEach(h=>{(h.type==="timeSignature"||h.type==="tempo")&&i.push(h)})}),i.sort((l,h)=>l.tick-h.tick);let s=0;t.tracks.forEach(l=>{l.notes&&l.notes.forEach(h=>{h.type==="noteOff"&&h.tick>s&&(s=h.tick)})}),s===0&&(s=e*8);const n=[],a=i.filter(l=>l.type==="timeSignature").sort((l,h)=>l.tick-h.tick);let r={numerator:4,denominator:4},q=0,o=0;for(;q<s;){for(;o<a.length&&a[o].tick<=q;)r=a[o],o++;let l;l=q+e*4*r.numerator/r.denominator,i.filter(u=>u.type==="tempo"&&u.tick>=q&&u.tick<l);const h=r.numerator,c=[],m=e*(4/r.denominator);for(let u=0;u<h;u++){const A=q+u*m,f=this._ticksToTime(A,t);c.push(f)}n.push({sig:[r.numerator,r.denominator],beats:c}),q=l}this.parsedData.barStructure=n}_extractParts(t){const e={},i=t.ticksPerBeat;t.tracks.forEach((s,n)=>{if(!s.notes.length)return;let a=null;if(s.name){const u=s.name.toLowerCase();for(const A of this.partNames)if(A.length===1){if(u===A){a=A;break}}else if(u.includes(A)){a=A;break}}a||(a=s.name||`Track ${n+1}`),a==="s"&&(a="soprano"),a==="a"&&(a="alto"),a==="t"&&(a="tenor"),a==="b"&&(a="bass");let r=a,q=2;for(;e[r];)r=`${a} ${q}`,q++;a=r;const o=[],l={};s.notes.forEach(u=>{if(u.type==="noteOn")l[u.noteNumber]={tick:u.tick,velocity:u.velocity};else if(u.type==="noteOff"&&l[u.noteNumber]){const A=l[u.noteNumber],f=u.tick-A.tick;o.push({pitch:u.noteNumber,name:this._midiNoteToName(u.noteNumber),startTick:A.tick,endTick:u.tick,duration:f,startTime:this._ticksToTime(A.tick,t),endTime:this._ticksToTime(u.tick,t),velocity:A.velocity}),delete l[u.noteNumber]}});const h=s.lyrics.map(u=>({text:u.text,tick:u.tick,time:u.tick/i}));o.sort((u,A)=>u.startTick-A.startTick);const c=s.events.filter(u=>u.type==="programChange").map(u=>({programNumber:u.programNumber,tick:u.tick,time:this._ticksToTime(u.tick,t)})).sort((u,A)=>u.tick-A.tick),m=c.length>0?c[0].programNumber:0;e[a]={notes:o,lyrics:h,trackIndex:n,programChanges:c,defaultInstrument:m}}),this.parsedData.parts=e}_midiNoteToName(t){const e=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],i=Math.floor(t/12)-1;return`${e[t%12]}${i}`}_bytesToNumber(t){let e=0;for(let i=0;i<t.length;i++)e=e<<8|t[i];return e}_bytesToString(t){return new TextDecoder().decode(t)}_readVariableLengthValue(t,e){let i=0,s,n=0;do s=t[e+n++],i=i<<7|s&127;while(s&128);return{value:i,bytesRead:n}}_ticksToTime(t,e){const i=e.ticksPerBeat||480,s=[];e.tracks.forEach(q=>{q.events.forEach(o=>{o.type==="tempo"&&s.push(o)})}),s.sort((q,o)=>q.tick-o.tick);let n=0,a=0,r=120;for(const q of s){if(q.tick>t)break;if(q.tick>a){const l=(q.tick-a)/i*(60/r);n+=l,a=q.tick}r=q.bpm}if(t>a){const o=(t-a)/i*(60/r);n+=o}return n}}class x{constructor(){this.barOrder=[],this.beatTable=[]}mapBeats(t,e){try{return this.barOrder=this.generateBarOrder(e.sections,e.order),this.beatTable=this.generateBeatTable(this.barOrder,t.barStructure),this.beatTable}catch(i){throw console.error("Error mapping beats:",i),i}}generateBarOrder(t,e){const i=[],s={};for(const n of e){const a=t[n.section];if(!a)throw new Error(`Invalid section index: ${n.section}`);const r=n.section;s[r]||(s[r]=0),s[r]++;const q=s[r],o=n.from!==void 0?n.from:this._getSectionStartBar(t,n.section),l=n.to!==void 0?n.to:a.to,h=n.as||1;for(let c=o;c<=l;c++)this._shouldPlayBar(a,c,h)&&i.push({barNumber:c,repeat:q,sectionIndex:n.section,voltaTime:h})}return i}generateBeatTable(t,e){const i=[],s={};let n=0,a=0;const r=[...e];for(;a<t.length&&n<r.length;){const q=t[a],o=q.barNumber;if(s[o]===void 0){const m=r[n];if(!m||!m.sig)throw new Error(`Invalid MIDI bar structure at index ${n}`);s[o]=m.sig[0]}const l=s[o];let h=r[n],c=h.sig[0];for(;c<l&&n+1<r.length;){const m=r[n+1],u=[h.sig[0]+m.sig[0],h.sig[1]],A=[...h.beats||[],...m.beats||[]];h={sig:u,beats:A},r[n]=h,r.splice(n+1,1),c=u[0]}if(c>l){const m=l,u=c-l,A=h.beats?h.beats.slice(0,m):[],f=h.beats?h.beats.slice(m):[],b={sig:[m,h.sig[1]],beats:A},w={sig:[u,h.sig[1]],beats:f};r[n]=b,r.splice(n+1,0,w),h=b}this._generateBeatsForBar(i,q,h,l),n++,a++}if(a<t.length)throw new Error(`Ran out of MIDI bars before completing score. Score bar ${a}/${t.length}, MIDI bar ${n}/${r.length}`);return i}_generateBeatsForBar(t,e,i,s){const{beats:n}=i;if(!n||!Array.isArray(n))throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(i)}`);const a=n.slice(0,s);for(let r=1;r<=s;r++){const o={time:a[r-1],repeat:e.repeat,bar:e.barNumber,beat:r,timeSig:s};t.push(o)}}_getSectionStartBar(t,e){return t[e].pickup!==void 0?0:e===0?1:t[e-1].to+1}_shouldPlayBar(t,e,i){if(!t.voltas)return!0;const s=t.voltas.indexOf(e);return s===-1?!0:s+1===i}}function v(d){return{all:d=d||new Map,on:function(t,e){var i=d.get(t);i?i.push(e):d.set(t,[e])},off:function(t,e){var i=d.get(t);i&&(e?i.splice(i.indexOf(e)>>>0,1):d.set(t,[]))},emit:function(t,e){var i=d.get(t);i&&i.slice().map(function(s){s(e)}),(i=d.get("*"))&&i.slice().map(function(s){s(t,e)})}}}class p{constructor(t,e,i=null,s=null){if(!t||!t.isInitialized)throw new Error("Initialized AudioEngine is required");if(!e)throw new Error("Parsed MIDI data is required");this.audioEngine=t,this.instrumentMap=i||{},this.parsedData=e,this._isPlaying=!1,this._currentTime=0,this._totalDuration=0,this.playbackSpeed=1,this.partChannels=new Map,this.partOutputs=new Map,this.playbackStartTime=0,this.lookAheadTime=.05,this.scheduleInterval=null,this.partNotePointers=new Map,this.partProgramPointers=new Map,this.eventBus=v(),this.beatMapper=new x,this.beats=[],this._setupPartChannels(),this._calculateTotalDuration(),this._resetNotePointers(),this._resetProgramPointers();const n=s||this._createDefaultStructureMetadata();this.beats=this.beatMapper.mapBeats(e,n)}play(){this._isPlaying||(this._isPlaying=!0,this.playbackStartTime=this.audioEngine.audioContext.currentTime-this._currentTime/this.playbackSpeed,this._resetNotePointers(),this._resetProgramPointers(),this._schedulePlayback(),this._startTimeUpdateLoop())}playAt(t){this._isPlaying||(this._isPlaying=!0,this.playbackStartTime=t-this._currentTime/this.playbackSpeed,this._resetNotePointers(),this._resetProgramPointers(),this._schedulePlayback(),this._startTimeUpdateLoop())}pause(){this._isPlaying&&(this._isPlaying=!1,this._stopScheduling(),this._stopTimeUpdateLoop())}stop(){this._isPlaying=!1,this._currentTime=0,this._stopScheduling(),this._stopTimeUpdateLoop(),this._resetNotePointers(),this._resetProgramPointers()}skipToTime(t){t=Math.max(0,Math.min(t,this._totalDuration));const e=this._isPlaying;e&&this.pause(),this._currentTime=t,this._resetNotePointers(),this._resetProgramPointers(),e&&this.play()}setPlaybackSpeed(t,e=!0){if(t<=0)throw new Error("Playback speed must be greater than 0");const i=e&&this._isPlaying;i&&this.pause();const s=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed;this.playbackSpeed=t,i?this.play():this.playbackStartTime=this.audioEngine.audioContext.currentTime-s/this.playbackSpeed}setBar(t,e=0){const i=this.getTimeFromBar(t,e);i!==null&&(this.skipToTime(i),this._emitEvent("barChanged",{bar:t,beat:1,repeat:e,time:i}))}getTimeFromBar(t,e=0){e||(e=1);const i=this.beats.find(s=>s.bar===t&&s.beat===1&&s.repeat===e);return i?i.time:null}getBeatFromTime(t){if(!this.beats.length)return null;let e=null;for(let i=this.beats.length-1;i>=0;i--)if(this.beats[i].time<=t){e=this.beats[i];break}return e}allSoundsOff(){this.audioEngine.allSoundsOff()}getPartOutput(t){return this.partOutputs.get(t)||null}getPartChannel(t){return this.partChannels.get(t)||null}getAllNextNotes(t){const e=t??this.getCurrentTime(),i={};for(const[s,n]of Object.entries(this.parsedData.parts)){const a=n.notes.find(r=>r.startTime>=e);i[s]=a?{pitch:a.pitch,startTime:a.startTime}:null}return i}getCurrentTime(){if(this._isPlaying){const t=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed;this._currentTime=Math.min(t,this._totalDuration)}return this._currentTime}getTotalDuration(){return this._totalDuration}isPlaying(){return this._isPlaying}on(t,e){this.eventBus.on(t,e)}off(t,e){this.eventBus.off(t,e)}_setupPartChannels(){Object.keys(this.parsedData.parts).forEach(t=>{const e=this.parsedData.parts[t],i=this.instrumentMap[t]||{},s=i.instrument!==void 0?i.instrument:e.defaultInstrument!==void 0?e.defaultInstrument:0;try{const n=this.audioEngine.createChannel(t,{instrument:s,initialVolume:i.volume||1});this.partChannels.set(t,n);const a=this.audioEngine.audioContext.createGain();a.gain.value=1;const r=n.getOutputNode();r&&r.connect(a),this.partOutputs.set(t,a)}catch(n){console.error(`Failed to create channel for part '${t}':`,n),this._emitEvent("error",n)}})}_calculateTotalDuration(){let t=0;Object.values(this.parsedData.parts).forEach(e=>{e.notes.forEach(i=>{i.endTime>t&&(t=i.endTime)})}),this._totalDuration=t}_schedulePlayback(){this._stopScheduling(),this._startScheduleLoop()}_startScheduleLoop(){this.scheduleInterval||(this.scheduleInterval=setInterval(()=>{if(!this._isPlaying)return;const e=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed,i=e+this.lookAheadTime;for(const[s,n]of this.partChannels){const a=this.parsedData.parts[s];if(a){if(a.programChanges&&a.programChanges.length>0){let r=this.partProgramPointers.get(s)||0;const q=a.programChanges;for(;r<q.length&&q[r].time<e;)r++;for(;r<q.length&&q[r].time<=i;){const o=q[r];n.setInstrument(o.programNumber),r++}this.partProgramPointers.set(s,r)}if(a.notes){let r=this.partNotePointers.get(s)||0;const q=a.notes;for(;r<q.length&&q[r].endTime<e;)r++;for(;r<q.length&&q[r].startTime<=i;){const o=q[r];if(o.endTime-o.startTime>=.01){const l=this.playbackStartTime+o.startTime/this.playbackSpeed,h=(o.endTime-o.startTime)/this.playbackSpeed;n.playNote(l,o.pitch,o.velocity,h)}r++}this.partNotePointers.set(s,r)}}}},50))}_resetNotePointers(){const t=this._currentTime;for(const[e]of this.partChannels){const i=this.parsedData.parts[e];if(!i||!i.notes)continue;let s=0;for(;s<i.notes.length&&i.notes[s].endTime<t;)s++;this.partNotePointers.set(e,s)}}_resetProgramPointers(){const t=this._currentTime;for(const[e,i]of this.partChannels){const s=this.parsedData.parts[e];if(!s||!s.programChanges){this.partProgramPointers.set(e,0);continue}let n=0,a=s.defaultInstrument;for(;n<s.programChanges.length&&s.programChanges[n].time<=t;)a=s.programChanges[n].programNumber,n++;i.setInstrument(a),this.partProgramPointers.set(e,n)}}_stopScheduling(){this.scheduleInterval&&(clearInterval(this.scheduleInterval),this.scheduleInterval=null),this.partChannels.forEach(t=>{t.isActive()&&t.allNotesOff()})}_startTimeUpdateLoop(){this.timeUpdateInterval=setInterval(()=>{const t=this.getCurrentTime();this._emitEvent("timeupdate",{currentTime:t});const e=this.getBeatFromTime(t);e&&this._emitEvent("beatChanged",e),t>=this._totalDuration+.05&&(this.stop(),this._emitEvent("ended",{finalTime:t}))},100)}_stopTimeUpdateLoop(){this.timeUpdateInterval&&(clearInterval(this.timeUpdateInterval),this.timeUpdateInterval=null)}_emitEvent(t,e){(this.eventBus.all.get(t)||[]).forEach(s=>{try{s(e)}catch(n){console.error(`Error in ${t} event listener:`,n)}})}_createDefaultStructureMetadata(){return{sections:[{from:1,to:this.parsedData.barStructure.length}],order:[{section:0}]}}destroy(){this.stop(),this.partChannels.forEach(t=>{t.destroy()}),this.partChannels.clear(),this.partOutputs.forEach(t=>{t.disconnect()}),this.partOutputs.clear(),this.partNotePointers.clear(),this.partProgramPointers.clear(),this.eventBus.all.clear()}}class F{constructor(t,e={}){if(!t)throw new Error("AudioEngine is required");this.audioEngine=t,this.midiPlayer=null,this.eventBus=v(),this._parser=new k,this._partOutputsMap=new Map,this.metronomeConfig={enabled:!1,tickInstrument:115,accentInstrument:116,volume:.7,...e.metronome},this.leadInConfig={enabled:!1,bars:1,...e.leadIn},this.startupConfig={delayMs:25,...e.startup},this.state="reset",this.frozenTime=0,this.leadInData=null,this.leadInStartTime=null,this.leadInProgress=null,this.leadInInterval=null,this.timeUpdateInterval=null,this.metronomeScheduleInterval=null,this.nextBeatIndex=0,this._validateConfig()}async load(t,e=null,i=null){this.reset();let s;if(t instanceof p)s=t;else if(t instanceof ArrayBuffer){const n=await this._parser.parse(t);let a=null;typeof e=="string"?a=JSON.parse(e):e&&typeof e=="object"&&(a=e);const r=i||this._createDefaultInstrumentMap(n.parts);s=new p(this.audioEngine,n,r,a)}else if(t&&typeof t=="object"&&t.parts){let n=null;typeof e=="string"?n=JSON.parse(e):e&&typeof e=="object"&&(n=e);const a=i||this._createDefaultInstrumentMap(t.parts);s=new p(this.audioEngine,t,a,n)}else throw new Error("Invalid input type. Expected MidiPlayer, parsed MIDI data, or ArrayBuffer");this._setMidiPlayer(s)}reset(){this.stop(),this.midiPlayer&&(this.midiPlayer.destroy(),this.midiPlayer=null),this.audioEngine.clearAllChannels(),this._partOutputsMap.clear(),this.frozenTime=0,this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this.nextBeatIndex=0,this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this.state="reset"}getPartOutputs(){return this._partOutputsMap.entries()}getPartNames(){return Array.from(this._partOutputsMap.keys())}async play(t={}){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");if(!(this.state==="playing"||this.state==="lead-in"))try{const e=t.leadIn!==void 0?t.leadIn:this.leadInConfig.enabled,i=t.metronome!==void 0?t.metronome:this.metronomeConfig.enabled;this.frozenTime===0&&(this.frozenTime=this.midiPlayer.getCurrentTime()),e?await this._startLeadIn(i):await this._startMidiPlayback(i)}catch(e){throw this.state="stopped",this._emitEvent("error",e),e}}pause(){if(!this.midiPlayer||this.state==="stopped"||this.state==="paused")return;const t=this.state;this.state="paused",t==="lead-in"?this._pauseLeadIn():t==="playing"&&(this.midiPlayer.pause(),this._stopMetronome()),this._stopTimeUpdateLoop(),this._emitEvent("playbackPaused",{})}resume(){!this.midiPlayer||this.state!=="paused"||(this.leadInData&&this.leadInProgress!==null&&this.leadInProgress<1?this._resumeLeadIn():(this.state="playing",this._resetMetronomeBeatTracking(),this.midiPlayer.play(),this._startMetronomeIfEnabled(),this._startTimeUpdateLoop(),this._emitEvent("playbackStarted",{})))}stop(){if(this.state==="stopped")return;const t=this.state==="playing";this.state="stopped",this.frozenTime=0,this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this._resetMetronomeBeatTracking(),t&&this.midiPlayer.stop(),this._emitEvent("playbackStopped",{})}skipToTime(t){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");this.frozenTime=t,this.state!=="lead-in"&&(this.midiPlayer.skipToTime(t),this.state==="playing"&&this.metronomeConfig.enabled&&this._resetMetronomeBeatTracking())}setBar(t,e=0){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");if(this.state==="lead-in"){const i=this.midiPlayer.getTimeFromBar(t,e);i!==null&&(this.frozenTime=i);return}if(this.midiPlayer.setBar(t,e),this.state==="stopped"){const i=this.midiPlayer.getTimeFromBar(t,e);i!==null&&(this.frozenTime=i)}this.state==="playing"&&this.metronomeConfig.enabled&&this._resetMetronomeBeatTracking()}getCurrentTime(){return this.state==="lead-in"||this.state==="paused"&&this.leadInProgress!==null?this.frozenTime:this.midiPlayer?this.midiPlayer.getCurrentTime():0}getLeadInProgress(){return this.leadInProgress}setMetronomeEnabled(t){const e=this.metronomeConfig.enabled;this.metronomeConfig.enabled=t,this.state==="playing"&&(t&&!e?this._startMetronome():!t&&e&&this._stopMetronome()),this._emitEvent("metronomeEnabledChanged",{enabled:t})}setMetronomeSettings(t){if(t.volume!==void 0&&(t.volume<0||t.volume>1))throw new Error("Metronome volume must be between 0.0 and 1.0");if(Object.assign(this.metronomeConfig,t),t.volume!==void 0){const e=this.audioEngine.getMetronomeOutput();e&&e.gain&&(e.gain.value=t.volume)}this._emitEvent("metronomeSettingsChanged",{...t})}setLeadInEnabled(t){this.leadInConfig.enabled=t,this._emitEvent("leadInSettingsChanged",{enabled:t,bars:this.leadInConfig.bars})}setLeadInBars(t){if(t<1)throw new Error("Lead-in bars must be at least 1");this.leadInConfig.bars=t,this._emitEvent("leadInSettingsChanged",{enabled:this.leadInConfig.enabled,bars:t})}setPlaybackSpeed(t,e=!0){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");this.midiPlayer.setPlaybackSpeed(t,e)}getMetronomeSettings(){return{...this.metronomeConfig}}isMetronomeEnabled(){return this.metronomeConfig.enabled}getLeadInSettings(){return{enabled:this.leadInConfig.enabled,bars:this.leadInConfig.bars}}getStartupSettings(){return{...this.startupConfig}}setStartupDelay(t){if(typeof t!="number"||t<0||t>1e3)throw new Error("Startup delay must be a number between 0 and 1000 milliseconds");this.startupConfig.delayMs=t,this._emitEvent("startupSettingsChanged",{delayMs:t})}getState(){return this.state}isInLeadIn(){return this.state==="lead-in"}isPlaying(){return this.state==="playing"||this.state==="lead-in"}getMetronomeOutput(){return this.audioEngine.getMetronomeOutput()}getPartOutput(t){return this.midiPlayer?this.midiPlayer.getPartOutput(t):null}allSoundsOff(){this.midiPlayer&&this.midiPlayer.allSoundsOff()}previewNextNotes(t={}){if(!this.midiPlayer)throw new Error("No MIDI data loaded");const e=t.delayBetweenParts??.3,i=t.duration??.5,s=t.velocity??100,n=this.midiPlayer.getAllNextNotes(),a=t.partOrder??this.getPartNames();let r=this.audioEngine.audioContext.currentTime+.01;const q=[];for(const o of a){const l=n[o];if(!l)continue;const h=this.midiPlayer.getPartChannel(o);if(!h)continue;const c=this.midiPlayer.getPartOutput(o);c&&c.gain.value===0||(h.playPreviewNote(l.pitch,{startTime:r,duration:i,velocity:s,instrument:t.instrument}),q.push({partName:o,pitch:l.pitch,startTime:r}),r+=e)}return{parts:q,totalDuration:q.length*e}}getTotalDuration(){return this.midiPlayer?this.midiPlayer.getTotalDuration():0}on(t,e){this.eventBus.on(t,e)}off(t,e){this.eventBus.off(t,e)}_setupEventDelegation(){this.midiPlayer.on("timeupdate",t=>{this.state==="playing"&&this._emitEvent("timeupdate",{...t,effectiveTime:t.currentTime,leadInProgress:null})}),this.midiPlayer.on("beatChanged",t=>{this.state==="playing"&&this._emitEvent("beatChanged",{...t,isLeadIn:!1})}),this.midiPlayer.on("barChanged",t=>{this.state==="playing"&&this._emitEvent("barChanged",t)}),this.midiPlayer.on("ended",t=>{this.state==="playing"&&(this.state="stopped",this._stopMetronome(),this._stopTimeUpdateLoop(),this._emitEvent("playbackEnded",t))}),this.midiPlayer.on("error",t=>{this._emitEvent("error",t)})}_validateConfig(){if(this.metronomeConfig.volume<0||this.metronomeConfig.volume>1)throw new Error("Metronome volume must be between 0.0 and 1.0");if(this.leadInConfig.bars<1)throw new Error("Lead-in bars must be at least 1")}async _startLeadIn(t){this.state="lead-in";const e=this.startupConfig.delayMs/1e3;this.leadInStartTime=this.audioEngine.audioContext.currentTime+e,this.leadInProgress=0,this.leadInData=this._calculateLeadInBeats(),this._emitEvent("leadInStarted",{totalBeats:this.leadInData.totalBeats,duration:this.leadInData.duration,bars:this.leadInConfig.bars,startupDelayMs:this.startupConfig.delayMs}),setTimeout(()=>{this.state==="lead-in"&&this._startLeadInScheduling(t)},this.startupConfig.delayMs),this._startTimeUpdateLoop()}_calculateLeadInBeats(){if(!this.midiPlayer)return{totalBeats:4,duration:2,beatSequence:[],beatsPerBar:4,startBeat:{bar:1,beat:1,timeSig:4}};const t=this.midiPlayer.beats,e=this.frozenTime,i=this.leadInConfig.bars;let s=t.length-1,n=.5;for(;t[s].time>e;)s--;const a=t[s],r=t[s+1];r?n=r.time-a.time:s>0&&(n=a.time-t[s-1].time);const q=this.midiPlayer&&this.midiPlayer.playbackSpeed||1,o=n/q,l=a.timeSig===1,h=l&&r?r.timeSig:a.timeSig,c=l?h-1:a.beat>1?a.beat-1:0,m=i*h+c;return{totalBeats:m,duration:m*o,beatSequence:this._generateBeatSequence(m,o,h),beatsPerBar:h,startBeat:a}}_generateBeatSequence(t,e,i){const s=[];for(let n=0;n<t;n++){const a=n%i+1;s.push({beat:a,isAccent:a===1,time:n*e,absoluteTime:this.leadInStartTime+n*e})}return s}_startLeadInScheduling(t){this.leadInBeatIndex=0,this.leadInScheduledBeats=new Set;const e=this.leadInData.beatSequence,i=10;this.leadInStartTime=this.audioEngine.audioContext.currentTime,this.leadInInterval=setInterval(()=>{const s=this.audioEngine.audioContext.currentTime-this.leadInStartTime;for(this.leadInProgress=Math.min(1,s/this.leadInData.duration);this.leadInBeatIndex<e.length;){const n=e[this.leadInBeatIndex],a=n.time-s;if(a>.05)break;if(!this.leadInScheduledBeats.has(this.leadInBeatIndex)&&a>=-.05&&a<=.05){const r=a<=0?this.audioEngine.audioContext.currentTime+.01:this.audioEngine.audioContext.currentTime+a;this._scheduleTickAtTime(r,n.isAccent),this._emitEvent("beatChanged",{bar:Math.floor(this.leadInBeatIndex/this.leadInData.beatsPerBar)+1,beat:n.beat,repeat:1,time:this.frozenTime,isLeadIn:!0}),this.leadInScheduledBeats.add(this.leadInBeatIndex)}this.leadInBeatIndex++}this.leadInProgress>=1&&this._completeLeadIn(t)},i)}_completeLeadIn(t){const e=this.leadInStartTime+this.leadInData.duration;this._stopLeadIn(),this._emitEvent("leadInEnded",{}),this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this._startMidiPlaybackAt(e,t,!0)}async _startMidiPlaybackAt(t,e,i=!0){this.state="playing",i&&this._emitEvent("playbackStarted",{startupDelayMs:0,scheduledStartTime:t}),this.midiPlayer.playAt(t),e&&this._startMetronomeAt(t),this.timeUpdateInterval||this._startTimeUpdateLoop()}async _startMidiPlayback(t,e=!0,i=!1){this.state="playing",this._resetMetronomeBeatTracking(),e&&this._emitEvent("playbackStarted",{startupDelayMs:i?0:this.startupConfig.delayMs});const s=()=>{if(this.state==="playing")try{this.midiPlayer.play(),t&&this._startMetronome()}catch(n){this.state="stopped",this._emitEvent("error",n)}};i?s():setTimeout(s,this.startupConfig.delayMs),this.timeUpdateInterval||this._startTimeUpdateLoop()}_startMetronome(){!this.metronomeConfig.enabled||this.state!=="playing"||(this._scheduleMetronomeTicks(),this.metronomeScheduleInterval=setInterval(()=>{this._scheduleMetronomeTicks()},50))}_startMetronomeAt(t){this.metronomeConfig.enabled&&(this.metronomeScheduledStartTime=t,this._resetMetronomeBeatTracking(),this._scheduleMetronomeTicksAt(t),this.metronomeScheduleInterval=setInterval(()=>{this._scheduleMetronomeTicks()},50))}_startMetronomeIfEnabled(){this.metronomeConfig.enabled&&this._startMetronome()}_scheduleMetronomeTicksAt(t){if(!this.metronomeConfig.enabled||!this.midiPlayer)return;const e=this.midiPlayer.beats;if(!e||e.length===0)return;const i=this.midiPlayer.getCurrentTime(),s=.1;for(let n=this.nextBeatIndex;n<e.length;n++){const a=e[n],r=this.midiPlayer.playbackSpeed||1,q=t+(a.time-i)/r;if(q>this.audioEngine.audioContext.currentTime+s)break;if(q>=this.audioEngine.audioContext.currentTime-.01){const o=Math.max(q,this.audioEngine.audioContext.currentTime+.001),l=a.isDownbeat||a.beat===1;this._scheduleTickAtTime(o,l),this.nextBeatIndex=n+1}}}_scheduleMetronomeTicks(){if(!this.metronomeConfig.enabled||!this.midiPlayer)return;const t=this.midiPlayer.getCurrentTime(),e=this.midiPlayer.beats;if(!e||e.length===0)return;for(;this.nextBeatIndex<e.length&&e[this.nextBeatIndex].time<t-.025;)this.nextBeatIndex++;const s=t+.15;for(;this.nextBeatIndex<e.length;){const n=e[this.nextBeatIndex],a=n.time-t;if(n.time>s)break;if(a>=-.025&&a<=.15){const r=this.audioEngine.audioContext.currentTime+.005,q=this.audioEngine.audioContext.currentTime+Math.max(a,.005),o=Math.max(r,q),l=n.beat===1;this._scheduleTickAtTime(o,l)}this.nextBeatIndex++}}async _scheduleTickAtTime(t,e){try{await this.audioEngine.playMetronomeTick(t,e,this.metronomeConfig.volume)}catch(i){console.warn("Failed to schedule metronome tick:",i)}}_resetMetronomeBeatTracking(){if(!this.midiPlayer){this.nextBeatIndex=0;return}const t=this.getCurrentTime(),e=this.midiPlayer.beats;if(!e||e.length===0){this.nextBeatIndex=0;return}for(this.nextBeatIndex=0;this.nextBeatIndex<e.length&&e[this.nextBeatIndex].time<t-.01;)this.nextBeatIndex++}_stopMetronome(){this.metronomeScheduleInterval&&(clearInterval(this.metronomeScheduleInterval),this.metronomeScheduleInterval=null)}_stopLeadIn(){this.leadInInterval&&(clearInterval(this.leadInInterval),this.leadInInterval=null)}_pauseLeadIn(){this._stopLeadIn()}_resumeLeadIn(){if(!this.leadInData||this.leadInProgress===null)return;this.state="lead-in";const t=this.audioEngine.audioContext.currentTime,e=this.leadInProgress*this.leadInData.duration;this.leadInStartTime=t-e,this._startLeadInScheduling(this.metronomeConfig.enabled),this._startTimeUpdateLoop()}_startTimeUpdateLoop(){this.timeUpdateInterval||(this.timeUpdateInterval=setInterval(()=>{this.state==="lead-in"?this._emitEvent("timeupdate",{currentTime:this.frozenTime,effectiveTime:this.frozenTime,leadInProgress:this.leadInProgress||0}):this.state},100))}_stopTimeUpdateLoop(){this.timeUpdateInterval&&(clearInterval(this.timeUpdateInterval),this.timeUpdateInterval=null)}_emitEvent(t,e){(this.eventBus.all.get(t)||[]).forEach(s=>{try{s(e)}catch(n){console.error(`Error in ${t} event listener:`,n)}})}destroy(){this.stop(),this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this.eventBus.all.clear()}_setMidiPlayer(t){this.midiPlayer=t,this.audioEngine=t.audioEngine,this._partOutputsMap.clear(),Object.keys(this.midiPlayer.parsedData.parts).forEach(e=>{const i=this.midiPlayer.getPartOutput(e);i&&this._partOutputsMap.set(e,i)}),this._setupEventDelegation(),this.state="ready"}_createDefaultInstrumentMap(t){const e={},i={soprano:{instrument:"choir_aahs",volume:1},alto:{instrument:"choir_aahs",volume:1},tenor:{instrument:"choir_aahs",volume:1},bass:{instrument:"choir_aahs",volume:1},piano:{instrument:"piano",volume:.8},organ:{instrument:"church_organ",volume:.7},strings:{instrument:"string_ensemble_1",volume:.6},flute:{instrument:"flute",volume:.8},trumpet:{instrument:"trumpet",volume:.7}};return Object.keys(t).forEach(s=>{const n=s.toLowerCase(),a=i[n]||i.piano;e[s]={instrument:a.instrument,volume:a.volume}}),e}}exports.AudioEngine=g;exports.AudioEngineUtils=_;exports.BeatMapper=x;exports.ChannelHandle=y;exports.MidiParser=k;exports.MidiPlayer=p;exports.PlaybackManager=F;exports.SpessaSynthAudioEngine=U;exports.SpessaSynthChannelHandle=C;
1
+ "use strict";var P=Object.create;var _=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var O=(c,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of M(t))!S.call(c,s)&&s!==e&&_(c,s,{get:()=>t[s],enumerable:!(i=E(t,s))||i.enumerable});return c};var D=(c,t,e)=>(e=c!=null?P(B(c)):{},O(t||!c||!c.__esModule?_(e,"default",{value:c,enumerable:!0}):e,c));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N="data:audio/mpeg;base64,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",z="data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//tkxPIADij5M+wwzYmAm6X9hJmwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//s0xPaAClDTI6OxLwCwkeLoEJkoqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAAB/gAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";class p{constructor(t,e={}){if(new.target===p)throw new Error("AudioEngine is abstract and cannot be instantiated directly");this.audioContext=t,this.options=e,this.isInitialized=!1,this.channels=new WeakMap,this.activeChannels=new Set}async initialize(t){throw new Error("initialize() must be implemented by subclass")}createChannel(t,e={}){throw new Error("createChannel() must be implemented by subclass")}allSoundsOff(){throw new Error("allSoundsOff() must be implemented by subclass")}async playMetronomeTick(t,e,i){try{await this._ensureMetronomeBuffersLoaded();const s=e?this.accentTickBuffer:this.regularTickBuffer;if(!s){console.warn("Metronome buffer not available");return}const n=this.audioContext.createBufferSource();n.buffer=s;const a=this.audioContext.createGain();a.gain.value=i,n.connect(a);const r=this.getMetronomeOutput();r?a.connect(r):a.connect(this.audioContext.destination);const l=Math.max(t,this.audioContext.currentTime);n.start(l)}catch(s){console.warn("Buffer metronome playback failed:",s)}}getMetronomeOutput(){return this._metronomeOutput||(this._metronomeOutput=this.audioContext.createGain(),this._metronomeOutput.gain.value=1,this._metronomeOutput.connect(this.audioContext.destination)),this._metronomeOutput}async _ensureMetronomeBuffersLoaded(){if(!(this.regularTickBuffer&&this.accentTickBuffer)){try{if(typeof fetch<"u"){const[t,e]=await Promise.all([fetch(N),fetch(z)]),[i,s]=await Promise.all([t.arrayBuffer(),e.arrayBuffer()]),[n,a]=await Promise.all([this.audioContext.decodeAudioData(i),this.audioContext.decodeAudioData(s)]);this.regularTickBuffer=n,this.accentTickBuffer=a;return}}catch(t){console.warn("Failed to load metronome sounds:",t)}this.regularTickBuffer=this.audioContext.createBuffer(2,1024,this.audioContext.sampleRate),this.accentTickBuffer=this.audioContext.createBuffer(2,1024,this.audioContext.sampleRate)}}getActiveChannels(){return Array.from(this.activeChannels)}destroy(){this.allSoundsOff(),this._metronomeOutput&&(this._metronomeOutput.disconnect(),this._metronomeOutput=null),this.regularTickBuffer=null,this.accentTickBuffer=null,this.activeChannels.clear(),this.isInitialized=!1}_validateInitialized(){if(!this.isInitialized)throw new Error("AudioEngine not initialized. Call initialize() first.")}_registerChannel(t){this.activeChannels.add(t)}_unregisterChannel(t){this.activeChannels.delete(t),this.channels.delete(t)}}class g{constructor(t,e,i={}){if(new.target===g)throw new Error("ChannelHandle is abstract and cannot be instantiated directly");this.engine=t,this.partId=e,this.options={initialVolume:1,...i},this.isDestroyed=!1,this.noteRefCounts=new Map,this.scheduledEvents=new Map,this.activeNotes=new Set}getOutputNode(){throw new Error("getOutputNode() must be implemented by subclass")}noteOn(t,e){this._validateActive();const i=this.noteRefCounts.get(t)||0;this.noteRefCounts.set(t,i+1),this._actualNoteOn(t,e),i===0&&this.activeNotes.add(t)}noteOff(t){this._validateActive();const e=this.noteRefCounts.get(t)||0;if(e<=0)return;const i=e-1;this.noteRefCounts.set(t,i),i===0&&(this._actualNoteOff(t),this.activeNotes.delete(t),this.noteRefCounts.delete(t))}playNote(t,e,i,s){this._validateActive();const n=this.engine.audioContext.currentTime,a=`${this.partId}_${t}_${e}_${Date.now()}`;let r=t,l=s;if(t<n){const d=n-t;r=n,l=Math.max(0,s-d)}if(l<=0)return a;const q=Math.max(0,(r-n)*1e3),o=setTimeout(()=>{this.noteOn(e,i),this.scheduledEvents.delete(`${a}_on`)},q),h=q+l*1e3,u=setTimeout(()=>{this.noteOff(e),this.scheduledEvents.delete(`${a}_off`)},h);return this.scheduledEvents.set(`${a}_on`,o),this.scheduledEvents.set(`${a}_off`,u),a}playPreviewNote(t,e={}){this._validateActive();const i=e.startTime??this.engine.audioContext.currentTime+.01,s=e.duration??.5,n=e.velocity??100;let a=null;e.instrument!==void 0&&(a=this.getInstrument(),this.setInstrument(e.instrument)),this.playNote(i,t,n,s),a!==null&&setTimeout(()=>{this.isDestroyed||this.setInstrument(a)},(s+.1)*1e3)}allNotesOff(){this._validateActive(),this.scheduledEvents.forEach(t=>{clearTimeout(t)}),this.scheduledEvents.clear(),this.activeNotes.forEach(t=>{this._actualNoteOff(t)}),this.noteRefCounts.clear(),this.activeNotes.clear()}_actualNoteOn(t,e){throw new Error("_actualNoteOn() must be implemented by subclass")}_actualNoteOff(t){throw new Error("_actualNoteOff() must be implemented by subclass")}async setInstrument(t){throw new Error("setInstrument() must be implemented by subclass")}getInstrument(){throw new Error("getInstrument() must be implemented by subclass")}setVolume(t){throw new Error("setVolume() must be implemented by subclass")}getVolume(){throw new Error("getVolume() must be implemented by subclass")}getPartId(){return this.partId}isActive(){return!this.isDestroyed&&this.engine.isInitialized&&this.engine.activeChannels.has(this)}destroy(){if(!this.isDestroyed){this.allNotesOff();const t=this.getOutputNode();t&&t.disconnect(),this.noteRefCounts.clear(),this.scheduledEvents.clear(),this.activeNotes.clear(),this.engine._unregisterChannel(this),this.isDestroyed=!0}}_validateActive(){if(this.isDestroyed)throw new Error("Channel has been destroyed");if(!this.engine.isInitialized)throw new Error("AudioEngine is not initialized")}}const I={piano:0,bright_piano:1,electric_grand:2,honky_tonk:3,electric_piano_1:4,electric_piano_2:5,harpsichord:6,clavinet:7,celesta:8,glockenspiel:9,music_box:10,vibraphone:11,marimba:12,xylophone:13,tubular_bells:14,dulcimer:15,drawbar_organ:16,percussive_organ:17,rock_organ:18,church_organ:19,reed_organ:20,accordion:21,harmonica:22,tango_accordion:23,organ:19,nylon_guitar:24,steel_guitar:25,electric_guitar_jazz:26,electric_guitar_clean:27,electric_guitar_muted:28,overdriven_guitar:29,distortion_guitar:30,guitar_harmonics:31,guitar:24,acoustic_bass:32,electric_bass_finger:33,electric_bass_pick:34,fretless_bass:35,slap_bass_1:36,slap_bass_2:37,synth_bass_1:38,synth_bass_2:39,bass:32,violin:40,viola:41,cello:42,contrabass:43,tremolo_strings:44,pizzicato_strings:45,orchestral_harp:46,timpani:47,strings:48,strings_ensemble:48,slow_strings:49,synth_strings_1:50,synth_strings_2:51,choir_aahs:52,voice_oohs:53,synth_voice:54,orchestra_hit:55,trumpet:56,trombone:57,tuba:58,muted_trumpet:59,french_horn:60,brass_section:61,synth_brass_1:62,synth_brass_2:63,soprano_sax:64,alto_sax:65,tenor_sax:66,baritone_sax:67,oboe:68,english_horn:69,bassoon:70,clarinet:71,saxophone:64,piccolo:72,flute:73,recorder:74,pan_flute:75,blown_bottle:76,shakuhachi:77,whistle:78,ocarina:79,lead_1_square:80,lead_2_sawtooth:81,lead_3_calliope:82,lead_4_chiff:83,lead_5_charang:84,lead_6_voice:85,lead_7_fifths:86,lead_8_bass:87,pad_1_new_age:88,pad_2_warm:89,pad_3_polysynth:90,pad_4_choir:91,pad_5_bowed:92,pad_6_metallic:93,pad_7_halo:94,pad_8_sweep:95,fx_1_rain:96,fx_2_soundtrack:97,fx_3_crystal:98,fx_4_atmosphere:99,fx_5_brightness:100,fx_6_goblins:101,fx_7_echoes:102,fx_8_sci_fi:103,sitar:104,banjo:105,shamisen:106,koto:107,kalimba:108,bag_pipe:109,fiddle:110,shanai:111,tinkle_bell:112,agogo:113,steel_drums:114,woodblock:115,taiko_drum:116,melodic_tom:117,synth_drum:118,reverse_cymbal:119,guitar_fret_noise:120,breath_noise:121,seashore:122,bird_tweet:123,telephone_ring:124,helicopter:125,applause:126,gunshot:127},L=Object.entries(I).reduce((c,[t,e])=>(c[e]=t,c),{});class T{static getInstrumentProgram(t){if(typeof t=="number")return t;const e=I[t.toLowerCase()];return e!==void 0?e:0}static getProgramName(t){return L[t]||`Program ${t}`}static generateNoteId(t,e,i){return`${t}_${e}_${Math.round(i)}`}}class k extends g{constructor(t,e,i,s={}){super(t,e,s),this.midiChannel=i,this.currentVolume=s.initialVolume||1,this.currentInstrument=s.instrument||"piano",this.outputGain=null,this._setupOutputNode(),this.setVolume(this.currentVolume),s.instrument&&this.setInstrument(s.instrument)}getOutputNode(){return this.outputGain}_actualNoteOn(t,e){const i=this.engine._getSynthesizer();if(i&&i.noteOn){const s=Math.round(e*this.currentVolume);i.noteOn(this.midiChannel,t,s)}}_actualNoteOff(t){const e=this.engine._getSynthesizer();e&&e.noteOff&&e.noteOff(this.midiChannel,t)}async setInstrument(t){this._validateActive();const e=T.getInstrumentProgram(t);this.currentInstrument=t;const i=this.engine._getSynthesizer();i&&i.programChange?i.programChange(this.midiChannel,e):console.warn("Cannot set instrument: synthesizer not available or no programChange method")}getInstrument(){return this.currentInstrument}setVolume(t){this._validateActive(),t=Math.max(0,Math.min(1,t)),this.currentVolume=t;const e=Math.round(t*127),i=this.engine._getSynthesizer();i&&i.controllerChange&&i.controllerChange(this.midiChannel,7,e)}getVolume(){return this.currentVolume}getMidiChannel(){return this.midiChannel}getActiveNoteCount(){return this.activeNotes.size}playNote(t,e,i,s){this._validateActive();const n=`${this.partId}_${t}_${e}_${Date.now()}`,a=this.engine._getSynthesizer();if(a&&a.post){const r=Math.round(i*this.currentVolume);a.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[144|this.midiChannel,e,r],channelOffset:0,force:!1,options:{time:t}}}),a.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[128|this.midiChannel,e,0],channelOffset:0,force:!1,options:{time:t+s}}})}else return super.playNote(t,e,i,s);return n}allNotesOff(){this._validateActive();const t=this.engine._getSynthesizer();t&&t.post?t.post({channelNumber:this.midiChannel,type:"midiMessage",data:{messageData:[176|this.midiChannel,123,0],channelOffset:0,force:!1,options:{time:this.engine.audioContext.currentTime}}}):super.allNotesOff()}destroy(){if(!this.isDestroyed){const t=this.engine._getIndividualOutput(this.midiChannel);this.outputGain&&this.outputGain!==t&&this.outputGain.disconnect(),this.outputGain=null}super.destroy()}_setupOutputNode(){const t=this.engine._getIndividualOutput(this.midiChannel);t?this.outputGain=t:(console.warn(`No individual output available for MIDI channel ${this.midiChannel}, using fallback`),this.outputGain=this.engine.audioContext.createGain(),this.outputGain.gain.value=this.currentVolume)}}class U extends p{constructor(t,e={}){super(t,e),this.synthesizer=null,this.soundfont=null,this.channelCounter=0,this.partToMidiChannel=new Map,this.midiChannelToPart=new Map,this.individualOutputs=[]}async initialize(t){const{WorkletSynthesizer:e}=await import("spessasynth_lib");let i;if(typeof t=="string")i=await this._loadSoundfontFromPath(t);else if(t instanceof ArrayBuffer)i=t;else throw new Error("Invalid soundfont data type. Expected string path or ArrayBuffer.");await this._loadAudioWorkletSafely(),this._setupIndividualOutputs(),this.dummyTarget=this.audioContext.createGain(),await new Promise(s=>setTimeout(s,50)),this.synthesizer=new e(this.audioContext),await this.synthesizer.soundBankManager.addSoundBank(i,"main"),await this.synthesizer.isReady,this._connectIndividualOutputs(),this._initializeMetronomeChannel(),this.isInitialized=!0}createChannel(t,e={}){if(this._validateInitialized(),this.partToMidiChannel.has(t))throw new Error(`Channel for part '${t}' already exists`);const i=this.channelCounter;if(i>=15)throw new Error("Maximum number of musical part channels (15) exceeded. Channel 15 is reserved for metronome.");this.channelCounter++,this.partToMidiChannel.set(t,i),this.midiChannelToPart.set(i,t);const s=new k(this,t,i,e);return this._registerChannel(s),e.instrument&&s.setInstrument(e.instrument),s}allSoundsOff(){this.synthesizer&&this.midiChannelToPart.forEach((t,e)=>{this.synthesizer.controllerChange&&this.synthesizer.controllerChange(e,120,0)})}clearAllChannels(){this.allSoundsOff(),this.partToMidiChannel.clear(),this.midiChannelToPart.clear(),this.channelCounter=0}destroy(){this.allSoundsOff(),this.synthesizer&&typeof this.synthesizer.disconnect=="function"&&this.synthesizer.disconnect(),this.individualOutputs.forEach(t=>{t&&t.disconnect&&t.disconnect()}),this.individualOutputs=[],this.dummyTarget&&(this.dummyTarget.disconnect(),this.dummyTarget=null),this.partToMidiChannel.clear(),this.midiChannelToPart.clear(),this.channelCounter=0,super.destroy(),this.synthesizer=null,this.soundfont=null}getMidiChannelForPart(t){return this.partToMidiChannel.has(t)?this.partToMidiChannel.get(t):null}_getSynthesizer(){return this.synthesizer}_getIndividualOutput(t){return t>=0&&t<this.individualOutputs.length?this.individualOutputs[t]:null}getMetronomeChannel(){const t=this._getIndividualOutput(15);return console.log("Metronome channel 15 output:",t?"Available":"NULL",`(total outputs: ${this.individualOutputs.length})`),t}_setupIndividualOutputs(){this.individualOutputs=[];for(let t=0;t<16;t++){const e=this.audioContext.createGain();e.gain.value=1,this.individualOutputs.push(e)}}_connectIndividualOutputs(){try{this.synthesizer&&this.synthesizer.connectIndividualOutputs?this.synthesizer.connectIndividualOutputs(this.individualOutputs):(console.warn("Synthesizer does not support individual outputs, using master output only"),this.synthesizer&&this.synthesizer.connect&&this.audioContext.destination&&this.synthesizer.connect(this.audioContext.destination))}catch(t){console.warn("Failed to connect individual outputs:",t.message),console.warn("Falling back to master output routing")}}async _loadSoundfontFromPath(t){const e=await fetch(t);if(!e.ok)throw new Error(`Failed to load soundfont: ${e.status} ${e.statusText}`);return await e.arrayBuffer()}async _loadAudioWorkletSafely(){const t="/node_modules/spessasynth_lib/dist/spessasynth_processor.min.js";for(let i=1;i<=5;i++)try{await this.audioContext.audioWorklet.addModule(t);return}catch(s){if(console.warn(`AudioWorklet loading failed (attempt ${i}/5):`,s.message),i===5)throw new Error(`AudioWorklet failed after 5 attempts: ${s.message}`);const n=i*500;await new Promise(a=>setTimeout(a,n))}}_initializeMetronomeChannel(){try{const t=this._getSynthesizer();if(!t){console.warn("Cannot initialize metronome channel: synthesizer not available");return}const e=15;t.programChange&&(t.programChange(e,115),console.log("Metronome channel 15 initialized with woodblock instrument (115)")),t.controllerChange&&t.controllerChange(e,7,127)}catch(t){console.warn("Failed to initialize metronome channel:",t)}}async playMetronomeTick(t,e,i){try{const s=this.getMetronomeChannel(),n=this._getSynthesizer();if(!s||!n)return super.playMetronomeTick(t,e,i);const a=15,r=e?86:60,q=Math.round(Math.min(127,Math.max(0,i*(e?127:100)))),o=this.audioContext.currentTime,h=Math.max(t,o),u=h-o;n.post?(n.post({channelNumber:a,type:"midiMessage",data:{messageData:[144|a,r,q],channelOffset:0,force:!1,options:{time:h}}}),n.post({channelNumber:a,type:"midiMessage",data:{messageData:[128|a,r,0],channelOffset:0,force:!1,options:{time:h+.1}}})):u<=.01?(n.noteOn&&n.noteOn(a,r,q),setTimeout(()=>{n.noteOff&&n.noteOff(a,r)},100)):setTimeout(()=>{n.noteOn&&n.noteOn(a,r,q),setTimeout(()=>{n.noteOff&&n.noteOff(a,r)},100)},u*1e3)}catch(s){return console.warn("MIDI metronome failed, falling back to buffers:",s),super.playMetronomeTick(t,e,i)}}getMetronomeOutput(){return!this.individualOutputs||this.individualOutputs.length<16?null:this.individualOutputs[15]}}class C{constructor(){this.partNames=["soprano","alto","tenor","bass","treble","mezzo","baritone","s","a","t","b","satb"],this.parsedData={parts:{},barStructure:[],metadata:{}}}async parse(t,e=null){try{const i=await this._parseMidiBuffer(t);return this.metadataOverrides=e||{},this._normalizeLegacyMetadata(),this._extractMetadata(i),this._extractBarStructure(i),this._extractParts(i),this.parsedData.structureMetadata=this.metadataOverrides,this.parsedData}catch(i){throw console.error("Error parsing MIDI file:",i),i}}_normalizeLegacyMetadata(){if(!this.metadataOverrides||Object.keys(this.metadataOverrides).length===0)return;const t=this.metadataOverrides;if(t.scores&&Array.isArray(t.scores)&&t.scores.length>0){const e=t.scores[0];e.parts&&(t.parts=this._convertLegacyParts(e.parts)),e.bars&&(t.bars=e.bars),delete t.scores}else t.parts&&Array.isArray(t.parts)&&(t.parts=this._convertLegacyParts(t.parts));delete t.type,delete t.version,delete t.subtitle}_convertLegacyParts(t){const e={};for(const i of t){if(!i.name||!i.url)continue;const s=i.name.toLowerCase(),n=this._parseUrlParams(i.url),a={};if(n.track!==void 0&&(a.trackIndex=parseInt(n.track,10)),n.prog!==void 0){const r=parseInt(n.prog,10);r!==0&&(a.instrument=r)}a.trackIndex!==void 0&&(e[s]=a)}return e}_parseUrlParams(t){const e={},i=t.indexOf("?");if(i===-1)return e;const n=t.substring(i+1).split("&");for(const a of n){const[r,l]=a.split("=");r&&l!==void 0&&(e[r]=l)}return e}async _parseMidiBuffer(t){const e=new Uint8Array(t);if(!(e[0]===77&&e[1]===84&&e[2]===104&&e[3]===100))throw new Error("Not a valid MIDI file");const i=this._bytesToNumber(e.slice(4,8)),s=this._bytesToNumber(e.slice(8,10)),n=this._bytesToNumber(e.slice(10,12)),a=this._bytesToNumber(e.slice(12,14)),r=a&32768?null:a,l={format:s,ticksPerBeat:r,tracks:[],duration:0};let q=8+i;for(let o=0;o<n;o++)if(e[q]===77&&e[q+1]===84&&e[q+2]===114&&e[q+3]===107){const h=this._bytesToNumber(e.slice(q+4,q+8)),u=e.slice(q+8,q+8+h),d=this._parseTrack(u);l.tracks.push(d),q+=8+h}else throw new Error(`Invalid track header at position ${q}`);return l}_parseTrack(t){const e={notes:[],name:null,lyrics:[],events:[],duration:0};let i=0,s=0,n=null;for(;i<t.length;){let a=0,r=0;do r=t[i++],a=a<<7|r&127;while(r&128);s+=a,r=t[i++];let l=r;if((r&128)===0){if(n===null)throw new Error("Running status byte encountered before status byte");l=n,i--}else n=l;if(l===255){const q=t[i++],o=this._readVariableLengthValue(t,i);i+=o.bytesRead;const h=t.slice(i,i+o.value);switch(i+=o.value,q){case 3:e.name=this._bytesToString(h);break;case 1:e.events.push({type:"text",text:this._bytesToString(h),tick:s});break;case 5:e.lyrics.push({text:this._bytesToString(h),tick:s});break;case 81:const u=this._bytesToNumber(h),d=Math.round(6e7/u);e.events.push({type:"tempo",bpm:d,tick:s});break;case 88:e.events.push({type:"timeSignature",numerator:h[0],denominator:Math.pow(2,h[1]),tick:s});break;case 47:e.duration=s;break}}else if((l&240)===144){const q=l&15,o=t[i++],h=t[i++];h>0?e.notes.push({type:"noteOn",noteNumber:o,velocity:h,tick:s,channel:q}):e.notes.push({type:"noteOff",noteNumber:o,tick:s,channel:q})}else if((l&240)===128){const q=l&15,o=t[i++];t[i++],e.notes.push({type:"noteOff",noteNumber:o,tick:s,channel:q})}else if(l===240||l===247){const q=this._readVariableLengthValue(t,i);i+=q.bytesRead+q.value}else if((l&240)===176){const q=l&15,o=t[i++],h=t[i++];e.events.push({type:"controller",controllerNumber:o,value:h,channel:q,tick:s})}else if((l&240)===192){const q=l&15,o=t[i++];e.events.push({type:"programChange",programNumber:o,channel:q,tick:s})}else if((l&240)===208){const q=l&15,o=t[i++];e.events.push({type:"channelAftertouch",pressure:o,channel:q,tick:s})}else if((l&240)===224){const q=l&15,o=t[i++],u=(t[i++]<<7|o)-8192;e.events.push({type:"pitchBend",value:u,channel:q,tick:s})}else if((l&240)===160){const q=l&15,o=t[i++],h=t[i++];e.events.push({type:"noteAftertouch",noteNumber:o,pressure:h,channel:q,tick:s})}else console.warn(`Unknown event type: ${l.toString(16)} at position ${i-1}`),i++}return e}_extractMetadata(t){const e={title:null,composer:null,partNames:[],format:t.format,ticksPerBeat:t.ticksPerBeat};t.tracks.forEach((i,s)=>{if(i.name&&!e.title&&(e.title=i.name),i.events.filter(n=>n.type==="text").forEach(n=>{const a=n.text.toLowerCase();(a.includes("compos")||a.includes("by"))&&!e.composer&&(e.composer=n.text)}),i.name){const n=i.name.toLowerCase();for(const a of this.partNames)if(n.includes(a)){e.partNames.push({index:s,name:i.name});break}}}),this.metadataOverrides.title!==void 0&&(e.title=this.metadataOverrides.title),this.metadataOverrides.composer!==void 0&&(e.composer=this.metadataOverrides.composer),this.metadataOverrides.arranger!==void 0&&(e.arranger=this.metadataOverrides.arranger),this.metadataOverrides.copyright!==void 0&&(e.copyright=this.metadataOverrides.copyright),this.parsedData.metadata=e}_extractBarStructure(t){const e=t.ticksPerBeat||480,i=[];t.tracks.forEach(o=>{o.events.forEach(h=>{(h.type==="timeSignature"||h.type==="tempo")&&i.push(h)})}),i.sort((o,h)=>o.tick-h.tick);let s=0;t.tracks.forEach(o=>{o.notes&&o.notes.forEach(h=>{h.type==="noteOff"&&h.tick>s&&(s=h.tick)})}),s===0&&(s=e*8);const n=[],a=i.filter(o=>o.type==="timeSignature").sort((o,h)=>o.tick-h.tick);let r={numerator:4,denominator:4},l=0,q=0;for(;l<s;){for(;q<a.length&&a[q].tick<=l;)r=a[q],q++;let o;o=l+e*4*r.numerator/r.denominator;const h=r.numerator,u=[],d=e*(4/r.denominator);for(let m=0;m<h;m++){const A=l+m*d,y=this._ticksToTime(A,t);u.push(y)}n.push({sig:[r.numerator,r.denominator],beats:u}),l=o}this.parsedData.barStructure=n}_extractParts(t){const e={},i=t.ticksPerBeat;if(this.metadataOverrides.parts)for(const[s,n]of Object.entries(this.metadataOverrides.parts)){if(!n.trackIndex&&n.trackIndex!==0&&!n.trackName)continue;let a=null,r=null;if(n.trackIndex!==void 0&&n.trackIndex!==null)r=n.trackIndex,r>=0&&r<t.tracks.length&&(a=t.tracks[r]);else if(n.trackName){const q=t.tracks.findIndex(o=>o.name===n.trackName);q!==-1&&(a=t.tracks[q],r=q)}if(!a)continue;const l=this._extractPartDataFromTrack(a,r,t,i);n.instrument!==void 0&&n.instrument!==null&&(l.defaultInstrument=this._resolveInstrument(n.instrument)),e[s]=l}else t.tracks.forEach((s,n)=>{if(!s.notes.length)return;let a=null;if(s.name){const q=s.name.toLowerCase();for(const o of this.partNames)if(o.length===1){if(q===o){a=o;break}}else if(q.includes(o)){a=o;break}}a||(a=s.name||`Track ${n+1}`),a==="s"&&(a="soprano"),a==="a"&&(a="alto"),a==="t"&&(a="tenor"),a==="b"&&(a="bass");let r=a,l=2;for(;e[r];)r=`${a} ${l}`,l++;a=r,e[a]=this._extractPartDataFromTrack(s,n,t,i)});this.parsedData.parts=e}_extractPartDataFromTrack(t,e,i,s){const n=[],a={};t.notes.forEach(o=>{if(o.type==="noteOn")a[o.noteNumber]={tick:o.tick,velocity:o.velocity};else if(o.type==="noteOff"&&a[o.noteNumber]){const h=a[o.noteNumber],u=o.tick-h.tick;n.push({pitch:o.noteNumber,name:this._midiNoteToName(o.noteNumber),startTick:h.tick,endTick:o.tick,duration:u,startTime:this._ticksToTime(h.tick,i),endTime:this._ticksToTime(o.tick,i),velocity:h.velocity}),delete a[o.noteNumber]}});const r=t.lyrics.map(o=>({text:o.text,tick:o.tick,time:o.tick/s}));n.sort((o,h)=>o.startTick-h.startTick);const l=t.events.filter(o=>o.type==="programChange").map(o=>({programNumber:o.programNumber,tick:o.tick,time:this._ticksToTime(o.tick,i)})).sort((o,h)=>o.tick-h.tick),q=l.length>0?l[0].programNumber:0;return{notes:n,lyrics:r,trackIndex:e,programChanges:l,defaultInstrument:q}}_resolveInstrument(t){if(typeof t=="number")return t;if(typeof t=="string"){const e={choir_aahs:52,piano:0,acoustic_grand_piano:0,bright_acoustic_piano:1,electric_grand_piano:2,strings:48,string_ensemble_1:48,violin:40,viola:41,cello:42,contrabass:43},i=t.toLowerCase().replace(/ /g,"_");return e[i]!==void 0?e[i]:0}return 0}_midiNoteToName(t){const e=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],i=Math.floor(t/12)-1;return`${e[t%12]}${i}`}_bytesToNumber(t){let e=0;for(let i=0;i<t.length;i++)e=e<<8|t[i];return e}_bytesToString(t){return new TextDecoder().decode(t)}_readVariableLengthValue(t,e){let i=0,s,n=0;do s=t[e+n++],i=i<<7|s&127;while(s&128);return{value:i,bytesRead:n}}_ticksToTime(t,e){const i=e.ticksPerBeat||480,s=[];e.tracks.forEach(l=>{l.events.forEach(q=>{q.type==="tempo"&&s.push(q)})}),s.sort((l,q)=>l.tick-q.tick);let n=0,a=0,r=120;for(const l of s){if(l.tick>t)break;if(l.tick>a){const o=(l.tick-a)/i*(60/r);n+=o,a=l.tick}r=l.bpm}if(t>a){const q=(t-a)/i*(60/r);n+=q}return n}}class v{constructor(){this.barOrder=[],this.beatTable=[]}mapBeats(t,e){try{return e.bars&&!e.sections?this.barOrder=this.generateBarOrderFromLegacyBars(e.bars,t.barStructure):e.sections&&e.order?this.barOrder=this.generateBarOrder(e.sections,e.order):this.barOrder=this.generateLinearBarOrder(t.barStructure),this.beatTable=this.generateBeatTable(this.barOrder,t.barStructure),this.beatTable}catch(i){throw console.error("Error mapping beats:",i),i}}generateBarOrder(t,e){const i=[],s={};for(const n of e){const a=t[n.section];if(!a)throw new Error(`Invalid section index: ${n.section}`);const r=n.section;s[r]||(s[r]=0),s[r]++;const l=s[r],q=n.from!==void 0?n.from:this._getSectionStartBar(t,n.section),o=n.to!==void 0?n.to:a.to,h=n.as||1;for(let u=q;u<=o;u++)this._shouldPlayBar(a,u,h)&&i.push({barNumber:u,repeat:l,sectionIndex:n.section,voltaTime:h})}return i}generateBarOrderFromLegacyBars(t,e){const i=[];let s=1,n=0,a;for(const r of t){r.from!==void 0&&(s=r.from===-1?0:r.from,n=0),r.timeSig!==void 0&&(a=r.timeSig);const l=r.repeat||1;let q=r.beats;for(;q>0;){const h=(a!==void 0?a:this._getBeatsPerBar(s,e))-n;q>=h?(i.push({barNumber:s,repeat:l,sectionIndex:0,voltaTime:1}),q-=h,n=0,s===0?s=1:s++):(n+=q,q=0)}}return n>0&&i.push({barNumber:s,repeat:1,sectionIndex:0,voltaTime:1}),i}generateLinearBarOrder(t){const e=[];for(let i=0;i<t.length;i++)e.push({barNumber:i+1,repeat:1,sectionIndex:0,voltaTime:1});return e}_getBeatsPerBar(t,e){const i=e.length>0&&e[0].sig&&e[0].sig[0]<=2;let s;if(i?s=t:s=t-1,s<0||s>=e.length)return 4;const n=e[s];return n.sig?n.sig[0]:4}generateBeatTable(t,e){const i=[],s={};let n=0,a=0;const r=[...e];for(;a<t.length&&n<r.length;){const l=t[a],q=l.barNumber;if(s[q]===void 0){const d=r[n];if(!d||!d.sig)throw new Error(`Invalid MIDI bar structure at index ${n}`);s[q]=d.sig[0]}const o=s[q];let h=r[n],u=h.sig[0];for(;u<o&&n+1<r.length;){const d=r[n+1],m=[h.sig[0]+d.sig[0],h.sig[1]],A=[...h.beats||[],...d.beats||[]];h={sig:m,beats:A},r[n]=h,r.splice(n+1,1),u=m[0]}if(u>o){const d=o,m=u-o,A=h.beats?h.beats.slice(0,d):[],y=h.beats?h.beats.slice(d):[],b={sig:[d,h.sig[1]],beats:A},w={sig:[m,h.sig[1]],beats:y};r[n]=b,r.splice(n+1,0,w),h=b}this._generateBeatsForBar(i,l,h,o),n++,a++}if(a<t.length)throw new Error(`Ran out of MIDI bars before completing score. Score bar ${a}/${t.length}, MIDI bar ${n}/${r.length}`);return i}_generateBeatsForBar(t,e,i,s){const{beats:n}=i;if(!n||!Array.isArray(n))throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(i)}`);const a=n.slice(0,s);for(let r=1;r<=s;r++){const q={time:a[r-1],repeat:e.repeat,bar:e.barNumber,beat:r,timeSig:s};t.push(q)}}_getSectionStartBar(t,e){return t[e].pickup!==void 0?0:e===0?1:t[e-1].to+1}_shouldPlayBar(t,e,i){if(!t.voltas)return!0;const s=t.voltas.indexOf(e);return s===-1?!0:s+1===i}}function x(c){return{all:c=c||new Map,on:function(t,e){var i=c.get(t);i?i.push(e):c.set(t,[e])},off:function(t,e){var i=c.get(t);i&&(e?i.splice(i.indexOf(e)>>>0,1):c.set(t,[]))},emit:function(t,e){var i=c.get(t);i&&i.slice().map(function(s){s(e)}),(i=c.get("*"))&&i.slice().map(function(s){s(t,e)})}}}class f{constructor(t=null,e,i=null,s=null){if(!e)throw new Error("Parsed MIDI data is required");this.audioEngine=t,this._audioEngineReady=!!(t&&t.isInitialized),this.instrumentMap=i||{},this.parsedData=e,this._isPlaying=!1,this._currentTime=0,this._totalDuration=0,this.playbackSpeed=1,this.partChannels=new Map,this.partOutputs=new Map,this.playbackStartTime=0,this.lookAheadTime=.05,this.scheduleInterval=null,this.partNotePointers=new Map,this.partProgramPointers=new Map,this.eventBus=x(),this.beatMapper=new v,this.beats=[],this._calculateTotalDuration();const n=s||this._createDefaultStructureMetadata();this.beats=this.beatMapper.mapBeats(e,n),this._audioEngineReady&&(this._setupPartChannels(),this._resetNotePointers(),this._resetProgramPointers())}setAudioEngine(t){if(!t||!t.isInitialized)throw new Error("An initialized AudioEngine is required");this.audioEngine=t,this._audioEngineReady=!0,this._setupPartChannels(),this._resetNotePointers(),this._resetProgramPointers()}isAudioEngineReady(){return this._audioEngineReady}play(){if(!this._audioEngineReady)throw new Error("Audio engine not ready. Call setAudioEngine() first.");this._isPlaying||(this._isPlaying=!0,this.playbackStartTime=this.audioEngine.audioContext.currentTime-this._currentTime/this.playbackSpeed,this._resetNotePointers(),this._resetProgramPointers(),this._schedulePlayback(),this._startTimeUpdateLoop())}playAt(t){if(!this._audioEngineReady)throw new Error("Audio engine not ready. Call setAudioEngine() first.");this._isPlaying||(this._isPlaying=!0,this.playbackStartTime=t-this._currentTime/this.playbackSpeed,this._resetNotePointers(),this._resetProgramPointers(),this._schedulePlayback(),this._startTimeUpdateLoop())}pause(){this._isPlaying&&(this._isPlaying=!1,this._stopScheduling(),this._stopTimeUpdateLoop())}stop(){this._isPlaying=!1,this._currentTime=0,this._stopScheduling(),this._stopTimeUpdateLoop(),this._resetNotePointers(),this._resetProgramPointers()}skipToTime(t){t=Math.max(0,Math.min(t,this._totalDuration));const e=this._isPlaying;e&&this.pause(),this._currentTime=t,this._resetNotePointers(),this._resetProgramPointers(),e&&this.play()}setPlaybackSpeed(t,e=!0){if(t<=0)throw new Error("Playback speed must be greater than 0");const i=e&&this._isPlaying;i&&this.pause();const s=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed;this.playbackSpeed=t,i?this.play():this.playbackStartTime=this.audioEngine.audioContext.currentTime-s/this.playbackSpeed}setBar(t,e=0){const i=this.getTimeFromBar(t,e);i!==null&&(this.skipToTime(i),this._emitEvent("barChanged",{bar:t,beat:1,repeat:e,time:i}))}getTimeFromBar(t,e=0){e||(e=1);const i=this.beats.find(s=>s.bar===t&&s.beat===1&&s.repeat===e);return i?i.time:null}getBeatFromTime(t){if(!this.beats.length)return null;let e=null;for(let i=this.beats.length-1;i>=0;i--)if(this.beats[i].time<=t){e=this.beats[i];break}return e}allSoundsOff(){this._audioEngineReady&&this.audioEngine.allSoundsOff()}getPartOutput(t){return this.partOutputs.get(t)||null}getPartChannel(t){return this.partChannels.get(t)||null}getAllNextNotes(t){const e=t??this.getCurrentTime(),i={};for(const[s,n]of Object.entries(this.parsedData.parts)){const a=n.notes.find(r=>r.startTime>=e);i[s]=a?{pitch:a.pitch,startTime:a.startTime}:null}return i}getCurrentTime(){if(this._isPlaying){const t=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed;this._currentTime=Math.min(t,this._totalDuration)}return this._currentTime}getTotalDuration(){return this._totalDuration}isPlaying(){return this._isPlaying}on(t,e){this.eventBus.on(t,e)}off(t,e){this.eventBus.off(t,e)}_setupPartChannels(){Object.keys(this.parsedData.parts).forEach(t=>{const e=this.parsedData.parts[t],i=this.instrumentMap[t]||{},s=i.instrument!==void 0?i.instrument:e.defaultInstrument!==void 0?e.defaultInstrument:0;try{const n=this.audioEngine.createChannel(t,{instrument:s,initialVolume:i.volume||1});this.partChannels.set(t,n);const a=this.audioEngine.audioContext.createGain();a.gain.value=1;const r=n.getOutputNode();r&&r.connect(a),this.partOutputs.set(t,a)}catch(n){console.error(`Failed to create channel for part '${t}':`,n),this._emitEvent("error",n)}})}_calculateTotalDuration(){let t=0;Object.values(this.parsedData.parts).forEach(e=>{e.notes.forEach(i=>{i.endTime>t&&(t=i.endTime)})}),this._totalDuration=t}_schedulePlayback(){this._stopScheduling(),this._startScheduleLoop()}_startScheduleLoop(){this.scheduleInterval||(this.scheduleInterval=setInterval(()=>{if(!this._isPlaying)return;const e=(this.audioEngine.audioContext.currentTime-this.playbackStartTime)*this.playbackSpeed,i=e+this.lookAheadTime;for(const[s,n]of this.partChannels){const a=this.parsedData.parts[s];if(a){if(a.programChanges&&a.programChanges.length>0){let r=this.partProgramPointers.get(s)||0;const l=a.programChanges;for(;r<l.length&&l[r].time<e;)r++;for(;r<l.length&&l[r].time<=i;){const q=l[r];n.setInstrument(q.programNumber),r++}this.partProgramPointers.set(s,r)}if(a.notes){let r=this.partNotePointers.get(s)||0;const l=a.notes;for(;r<l.length&&l[r].endTime<e;)r++;for(;r<l.length&&l[r].startTime<=i;){const q=l[r];if(q.endTime-q.startTime>=.01){const o=this.playbackStartTime+q.startTime/this.playbackSpeed,h=(q.endTime-q.startTime)/this.playbackSpeed;n.playNote(o,q.pitch,q.velocity,h)}r++}this.partNotePointers.set(s,r)}}}},50))}_resetNotePointers(){const t=this._currentTime;for(const[e]of this.partChannels){const i=this.parsedData.parts[e];if(!i||!i.notes)continue;let s=0;for(;s<i.notes.length&&i.notes[s].endTime<t;)s++;this.partNotePointers.set(e,s)}}_resetProgramPointers(){const t=this._currentTime;for(const[e,i]of this.partChannels){const s=this.parsedData.parts[e];if(!s||!s.programChanges){this.partProgramPointers.set(e,0);continue}let n=0,a=s.defaultInstrument;for(;n<s.programChanges.length&&s.programChanges[n].time<=t;)a=s.programChanges[n].programNumber,n++;i.setInstrument(a),this.partProgramPointers.set(e,n)}}_stopScheduling(){this.scheduleInterval&&(clearInterval(this.scheduleInterval),this.scheduleInterval=null),this.partChannels.forEach(t=>{t.isActive()&&t.allNotesOff()})}_startTimeUpdateLoop(){this.timeUpdateInterval=setInterval(()=>{const t=this.getCurrentTime();this._emitEvent("timeupdate",{currentTime:t});const e=this.getBeatFromTime(t);e&&this._emitEvent("beatChanged",e),t>=this._totalDuration+.05&&(this.stop(),this._emitEvent("ended",{finalTime:t}))},100)}_stopTimeUpdateLoop(){this.timeUpdateInterval&&(clearInterval(this.timeUpdateInterval),this.timeUpdateInterval=null)}_emitEvent(t,e){(this.eventBus.all.get(t)||[]).forEach(s=>{try{s(e)}catch(n){console.error(`Error in ${t} event listener:`,n)}})}_createDefaultStructureMetadata(){return{sections:[{from:1,to:this.parsedData.barStructure.length}],order:[{section:0}]}}destroy(){this.stop(),this.partChannels.forEach(t=>{t.destroy()}),this.partChannels.clear(),this.partOutputs.forEach(t=>{t.disconnect()}),this.partOutputs.clear(),this.partNotePointers.clear(),this.partProgramPointers.clear(),this.eventBus.all.clear()}}class F{constructor(t=null,e={}){t instanceof f?(this.audioEngine=t.audioEngine,this.midiPlayer=t,this.parsedData=t.parsedData,this._audioEngineReady=!!(this.audioEngine&&this.audioEngine.isInitialized)):(this.audioEngine=t,this._audioEngineReady=!!(t&&t.isInitialized),this.midiPlayer=null,this.parsedData=null),this.eventBus=x(),this._parser=new C,this._partOutputsMap=new Map,this.instrumentMap=null,this.metronomeConfig={enabled:!1,tickInstrument:115,accentInstrument:116,volume:.7,...e.metronome},this.leadInConfig={enabled:!1,bars:1,...e.leadIn},this.startupConfig={delayMs:25,...e.startup},this.state="reset",this.frozenTime=0,this.leadInData=null,this.leadInStartTime=null,this.leadInProgress=null,this.leadInInterval=null,this.timeUpdateInterval=null,this.metronomeScheduleInterval=null,this.nextBeatIndex=0,this._validateConfig(),this.midiPlayer&&this._completeMidiPlayerSetup()}setAudioEngine(t){if(!t||!t.isInitialized)throw new Error("An initialized AudioEngine is required");this.audioEngine=t,this._audioEngineReady=!0,this.parsedData&&!this.midiPlayer&&this._setupPlayerWithAudio()}isAudioEngineReady(){return this._audioEngineReady}async load(t,e=null,i=null){if(this.reset(),t instanceof f)this.parsedData=t.parsedData,this.instrumentMap=i,this._audioEngineReady&&this._setMidiPlayer(t);else if(t instanceof ArrayBuffer)this.parsedData=await this._parser.parse(t,e),this.instrumentMap=i||this._createDefaultInstrumentMap(this.parsedData.parts),this._audioEngineReady&&this._setupPlayerWithAudio();else if(t&&typeof t=="object"&&t.parts)this.parsedData=t,this.instrumentMap=i||this._createDefaultInstrumentMap(t.parts),this._audioEngineReady&&this._setupPlayerWithAudio();else throw new Error("Invalid input type. Expected MidiPlayer, parsed MIDI data, or ArrayBuffer")}reset(){this.stop(),this.midiPlayer&&(this.midiPlayer.destroy(),this.midiPlayer=null),this.parsedData=null,this.instrumentMap=null,this._audioEngineReady&&this.audioEngine.clearAllChannels(),this._partOutputsMap.clear(),this.frozenTime=0,this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this.nextBeatIndex=0,this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this.state="reset"}getPartOutputs(){return this._partOutputsMap.entries()}getPartNames(){return Array.from(this._partOutputsMap.keys())}async play(t={}){if(!this._audioEngineReady)throw new Error("Audio engine not ready. Call setAudioEngine() after user interaction.");if(this.parsedData&&!this.midiPlayer&&this._setupPlayerWithAudio(),!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");if(!(this.state==="playing"||this.state==="lead-in"))try{const e=t.leadIn!==void 0?t.leadIn:this.leadInConfig.enabled,i=t.metronome!==void 0?t.metronome:this.metronomeConfig.enabled;this.frozenTime===0&&(this.frozenTime=this.midiPlayer.getCurrentTime()),e?await this._startLeadIn(i):await this._startMidiPlayback(i)}catch(e){throw this.state="stopped",this._emitEvent("error",e),e}}pause(){if(!this.midiPlayer||this.state==="stopped"||this.state==="paused")return;const t=this.state;this.state="paused",t==="lead-in"?this._pauseLeadIn():t==="playing"&&(this.midiPlayer.pause(),this._stopMetronome()),this._stopTimeUpdateLoop(),this._emitEvent("playbackPaused",{})}resume(){!this.midiPlayer||this.state!=="paused"||(this.leadInData&&this.leadInProgress!==null&&this.leadInProgress<1?this._resumeLeadIn():(this.state="playing",this._resetMetronomeBeatTracking(),this.midiPlayer.play(),this._startMetronomeIfEnabled(),this._startTimeUpdateLoop(),this._emitEvent("playbackStarted",{})))}stop(){if(this.state==="stopped")return;const t=this.state==="playing";this.state="stopped",this.frozenTime=0,this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this._resetMetronomeBeatTracking(),t&&this.midiPlayer.stop(),this._emitEvent("playbackStopped",{})}skipToTime(t){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");this.frozenTime=t,this.state!=="lead-in"&&(this.midiPlayer.skipToTime(t),this.state==="playing"&&this.metronomeConfig.enabled&&this._resetMetronomeBeatTracking())}setBar(t,e=0){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");if(this.state==="lead-in"){const i=this.midiPlayer.getTimeFromBar(t,e);i!==null&&(this.frozenTime=i);return}if(this.midiPlayer.setBar(t,e),this.state==="stopped"){const i=this.midiPlayer.getTimeFromBar(t,e);i!==null&&(this.frozenTime=i)}this.state==="playing"&&this.metronomeConfig.enabled&&this._resetMetronomeBeatTracking()}getCurrentTime(){return this.state==="lead-in"||this.state==="paused"&&this.leadInProgress!==null?this.frozenTime:this.midiPlayer?this.midiPlayer.getCurrentTime():0}getLeadInProgress(){return this.leadInProgress}setMetronomeEnabled(t){const e=this.metronomeConfig.enabled;this.metronomeConfig.enabled=t,this.state==="playing"&&(t&&!e?this._startMetronome():!t&&e&&this._stopMetronome()),this._emitEvent("metronomeEnabledChanged",{enabled:t})}setMetronomeSettings(t){if(t.volume!==void 0&&(t.volume<0||t.volume>1))throw new Error("Metronome volume must be between 0.0 and 1.0");if(Object.assign(this.metronomeConfig,t),t.volume!==void 0){const e=this.audioEngine.getMetronomeOutput();e&&e.gain&&(e.gain.value=t.volume)}this._emitEvent("metronomeSettingsChanged",{...t})}setLeadInEnabled(t){this.leadInConfig.enabled=t,this._emitEvent("leadInSettingsChanged",{enabled:t,bars:this.leadInConfig.bars})}setLeadInBars(t){if(t<1)throw new Error("Lead-in bars must be at least 1");this.leadInConfig.bars=t,this._emitEvent("leadInSettingsChanged",{enabled:this.leadInConfig.enabled,bars:t})}setPlaybackSpeed(t,e=!0){if(!this.midiPlayer)throw new Error("No MIDI data loaded. Call load() first.");this.midiPlayer.setPlaybackSpeed(t,e)}getMetronomeSettings(){return{...this.metronomeConfig}}isMetronomeEnabled(){return this.metronomeConfig.enabled}getLeadInSettings(){return{enabled:this.leadInConfig.enabled,bars:this.leadInConfig.bars}}getStartupSettings(){return{...this.startupConfig}}setStartupDelay(t){if(typeof t!="number"||t<0||t>1e3)throw new Error("Startup delay must be a number between 0 and 1000 milliseconds");this.startupConfig.delayMs=t,this._emitEvent("startupSettingsChanged",{delayMs:t})}getState(){return this.state}isInLeadIn(){return this.state==="lead-in"}isPlaying(){return this.state==="playing"||this.state==="lead-in"}getMetronomeOutput(){return this.audioEngine.getMetronomeOutput()}getPartOutput(t){return this.midiPlayer?this.midiPlayer.getPartOutput(t):null}allSoundsOff(){this.midiPlayer&&this.midiPlayer.allSoundsOff()}previewNextNotes(t={}){if(!this.midiPlayer)throw new Error("No MIDI data loaded");const e=t.delayBetweenParts??.3,i=t.duration??.5,s=t.velocity??100,n=this.midiPlayer.getAllNextNotes(),a=t.partOrder??this.getPartNames();let r=this.audioEngine.audioContext.currentTime+.01;const l=[];for(const q of a){const o=n[q];if(!o)continue;const h=this.midiPlayer.getPartChannel(q);if(!h)continue;const u=this.midiPlayer.getPartOutput(q);u&&u.gain.value===0||(h.playPreviewNote(o.pitch,{startTime:r,duration:i,velocity:s,instrument:t.instrument}),l.push({partName:q,pitch:o.pitch,startTime:r}),r+=e)}return{parts:l,totalDuration:l.length*e}}getTotalDuration(){if(this.midiPlayer)return this.midiPlayer.getTotalDuration();if(this.parsedData&&this.parsedData.parts){let t=0;return Object.values(this.parsedData.parts).forEach(e=>{e.notes&&e.notes.forEach(i=>{i.endTime>t&&(t=i.endTime)})}),t}return 0}on(t,e){this.eventBus.on(t,e)}off(t,e){this.eventBus.off(t,e)}_setupEventDelegation(){this.midiPlayer.on("timeupdate",t=>{this.state==="playing"&&this._emitEvent("timeupdate",{...t,effectiveTime:t.currentTime,leadInProgress:null})}),this.midiPlayer.on("beatChanged",t=>{this.state==="playing"&&this._emitEvent("beatChanged",{...t,isLeadIn:!1})}),this.midiPlayer.on("barChanged",t=>{this.state==="playing"&&this._emitEvent("barChanged",t)}),this.midiPlayer.on("ended",t=>{this.state==="playing"&&(this.state="stopped",this._stopMetronome(),this._stopTimeUpdateLoop(),this._emitEvent("playbackEnded",t))}),this.midiPlayer.on("error",t=>{this._emitEvent("error",t)})}_validateConfig(){if(this.metronomeConfig.volume<0||this.metronomeConfig.volume>1)throw new Error("Metronome volume must be between 0.0 and 1.0");if(this.leadInConfig.bars<1)throw new Error("Lead-in bars must be at least 1")}async _startLeadIn(t){this.state="lead-in";const e=this.startupConfig.delayMs/1e3;this.leadInStartTime=this.audioEngine.audioContext.currentTime+e,this.leadInProgress=0,this.leadInData=this._calculateLeadInBeats(),this._emitEvent("leadInStarted",{totalBeats:this.leadInData.totalBeats,duration:this.leadInData.duration,bars:this.leadInConfig.bars,startupDelayMs:this.startupConfig.delayMs}),setTimeout(()=>{this.state==="lead-in"&&this._startLeadInScheduling(t)},this.startupConfig.delayMs),this._startTimeUpdateLoop()}_calculateLeadInBeats(){if(!this.midiPlayer)return{totalBeats:4,duration:2,beatSequence:[],beatsPerBar:4,startBeat:{bar:1,beat:1,timeSig:4}};const t=this.midiPlayer.beats,e=this.frozenTime,i=this.leadInConfig.bars;let s=t.length-1,n=.5;for(;t[s].time>e;)s--;const a=t[s],r=t[s+1];r?n=r.time-a.time:s>0&&(n=a.time-t[s-1].time);const l=this.midiPlayer&&this.midiPlayer.playbackSpeed||1,q=n/l,o=a.timeSig===1,h=o&&r?r.timeSig:a.timeSig,u=o?h-1:a.beat>1?a.beat-1:0,d=i*h+u;return{totalBeats:d,duration:d*q,beatSequence:this._generateBeatSequence(d,q,h),beatsPerBar:h,startBeat:a}}_generateBeatSequence(t,e,i){const s=[];for(let n=0;n<t;n++){const a=n%i+1;s.push({beat:a,isAccent:a===1,time:n*e,absoluteTime:this.leadInStartTime+n*e})}return s}_startLeadInScheduling(t){this.leadInBeatIndex=0,this.leadInScheduledBeats=new Set;const e=this.leadInData.beatSequence,i=10;this.leadInStartTime=this.audioEngine.audioContext.currentTime,this.leadInInterval=setInterval(()=>{const s=this.audioEngine.audioContext.currentTime-this.leadInStartTime;for(this.leadInProgress=Math.min(1,s/this.leadInData.duration);this.leadInBeatIndex<e.length;){const n=e[this.leadInBeatIndex],a=n.time-s;if(a>.05)break;if(!this.leadInScheduledBeats.has(this.leadInBeatIndex)&&a>=-.05&&a<=.05){const r=a<=0?this.audioEngine.audioContext.currentTime+.01:this.audioEngine.audioContext.currentTime+a;this._scheduleTickAtTime(r,n.isAccent),this._emitEvent("beatChanged",{bar:Math.floor(this.leadInBeatIndex/this.leadInData.beatsPerBar)+1,beat:n.beat,repeat:1,time:this.frozenTime,isLeadIn:!0}),this.leadInScheduledBeats.add(this.leadInBeatIndex)}this.leadInBeatIndex++}this.leadInProgress>=1&&this._completeLeadIn(t)},i)}_completeLeadIn(t){const e=this.leadInStartTime+this.leadInData.duration;this._stopLeadIn(),this._emitEvent("leadInEnded",{}),this.leadInData=null,this.leadInProgress=null,this.leadInStartTime=null,this._startMidiPlaybackAt(e,t,!0)}async _startMidiPlaybackAt(t,e,i=!0){this.state="playing",i&&this._emitEvent("playbackStarted",{startupDelayMs:0,scheduledStartTime:t}),this.midiPlayer.playAt(t),e&&this._startMetronomeAt(t),this.timeUpdateInterval||this._startTimeUpdateLoop()}async _startMidiPlayback(t,e=!0,i=!1){this.state="playing",this._resetMetronomeBeatTracking(),e&&this._emitEvent("playbackStarted",{startupDelayMs:i?0:this.startupConfig.delayMs});const s=()=>{if(this.state==="playing")try{this.midiPlayer.play(),t&&this._startMetronome()}catch(n){this.state="stopped",this._emitEvent("error",n)}};i?s():setTimeout(s,this.startupConfig.delayMs),this.timeUpdateInterval||this._startTimeUpdateLoop()}_startMetronome(){!this.metronomeConfig.enabled||this.state!=="playing"||(this._scheduleMetronomeTicks(),this.metronomeScheduleInterval=setInterval(()=>{this._scheduleMetronomeTicks()},50))}_startMetronomeAt(t){this.metronomeConfig.enabled&&(this.metronomeScheduledStartTime=t,this._resetMetronomeBeatTracking(),this._scheduleMetronomeTicksAt(t),this.metronomeScheduleInterval=setInterval(()=>{this._scheduleMetronomeTicks()},50))}_startMetronomeIfEnabled(){this.metronomeConfig.enabled&&this._startMetronome()}_scheduleMetronomeTicksAt(t){if(!this.metronomeConfig.enabled||!this.midiPlayer)return;const e=this.midiPlayer.beats;if(!e||e.length===0)return;const i=this.midiPlayer.getCurrentTime(),s=.1;for(let n=this.nextBeatIndex;n<e.length;n++){const a=e[n],r=this.midiPlayer.playbackSpeed||1,l=t+(a.time-i)/r;if(l>this.audioEngine.audioContext.currentTime+s)break;if(l>=this.audioEngine.audioContext.currentTime-.01){const q=Math.max(l,this.audioEngine.audioContext.currentTime+.001),o=a.isDownbeat||a.beat===1;this._scheduleTickAtTime(q,o),this.nextBeatIndex=n+1}}}_scheduleMetronomeTicks(){if(!this.metronomeConfig.enabled||!this.midiPlayer)return;const t=this.midiPlayer.getCurrentTime(),e=this.midiPlayer.beats;if(!e||e.length===0)return;for(;this.nextBeatIndex<e.length&&e[this.nextBeatIndex].time<t-.025;)this.nextBeatIndex++;const s=t+.15;for(;this.nextBeatIndex<e.length;){const n=e[this.nextBeatIndex],a=n.time-t;if(n.time>s)break;if(a>=-.025&&a<=.15){const r=this.audioEngine.audioContext.currentTime+.005,l=this.audioEngine.audioContext.currentTime+Math.max(a,.005),q=Math.max(r,l),o=n.beat===1;this._scheduleTickAtTime(q,o)}this.nextBeatIndex++}}async _scheduleTickAtTime(t,e){try{await this.audioEngine.playMetronomeTick(t,e,this.metronomeConfig.volume)}catch(i){console.warn("Failed to schedule metronome tick:",i)}}_resetMetronomeBeatTracking(){if(!this.midiPlayer){this.nextBeatIndex=0;return}const t=this.getCurrentTime(),e=this.midiPlayer.beats;if(!e||e.length===0){this.nextBeatIndex=0;return}for(this.nextBeatIndex=0;this.nextBeatIndex<e.length&&e[this.nextBeatIndex].time<t-.01;)this.nextBeatIndex++}_stopMetronome(){this.metronomeScheduleInterval&&(clearInterval(this.metronomeScheduleInterval),this.metronomeScheduleInterval=null)}_stopLeadIn(){this.leadInInterval&&(clearInterval(this.leadInInterval),this.leadInInterval=null)}_pauseLeadIn(){this._stopLeadIn()}_resumeLeadIn(){if(!this.leadInData||this.leadInProgress===null)return;this.state="lead-in";const t=this.audioEngine.audioContext.currentTime,e=this.leadInProgress*this.leadInData.duration;this.leadInStartTime=t-e,this._startLeadInScheduling(this.metronomeConfig.enabled),this._startTimeUpdateLoop()}_startTimeUpdateLoop(){this.timeUpdateInterval||(this.timeUpdateInterval=setInterval(()=>{this.state==="lead-in"?this._emitEvent("timeupdate",{currentTime:this.frozenTime,effectiveTime:this.frozenTime,leadInProgress:this.leadInProgress||0}):this.state},100))}_stopTimeUpdateLoop(){this.timeUpdateInterval&&(clearInterval(this.timeUpdateInterval),this.timeUpdateInterval=null)}_emitEvent(t,e){(this.eventBus.all.get(t)||[]).forEach(s=>{try{s(e)}catch(n){console.error(`Error in ${t} event listener:`,n)}})}destroy(){this.stop(),this._stopLeadIn(),this._stopMetronome(),this._stopTimeUpdateLoop(),this.eventBus.all.clear()}_setupPlayerWithAudio(){if(!this._audioEngineReady)throw new Error("Audio engine not ready");if(!this.parsedData)throw new Error("No parsed MIDI data available");const t=this.parsedData.structureMetadata||null,e=new f(this.audioEngine,this.parsedData,this.instrumentMap,t);this._setMidiPlayer(e)}_setMidiPlayer(t){this.midiPlayer=t,this.audioEngine=t.audioEngine,this._audioEngineReady=!0,this._completeMidiPlayerSetup()}_completeMidiPlayerSetup(){this._partOutputsMap.clear(),Object.keys(this.midiPlayer.parsedData.parts).forEach(t=>{const e=this.midiPlayer.getPartOutput(t);e&&this._partOutputsMap.set(t,e)}),this._setupEventDelegation(),this.state="ready"}_createDefaultInstrumentMap(t){const e={},i={soprano:{instrument:"choir_aahs",volume:1},alto:{instrument:"choir_aahs",volume:1},tenor:{instrument:"choir_aahs",volume:1},bass:{instrument:"choir_aahs",volume:1},piano:{instrument:"piano",volume:.8},organ:{instrument:"church_organ",volume:.7},strings:{instrument:"string_ensemble_1",volume:.6},flute:{instrument:"flute",volume:.8},trumpet:{instrument:"trumpet",volume:.7}};return Object.keys(t).forEach(s=>{const n=s.toLowerCase(),a=i[n]||i.piano;e[s]={instrument:a.instrument,volume:a.volume}}),e}}exports.AudioEngine=p;exports.AudioEngineUtils=T;exports.BeatMapper=v;exports.ChannelHandle=g;exports.MidiParser=C;exports.MidiPlayer=f;exports.PlaybackManager=F;exports.SpessaSynthAudioEngine=U;exports.SpessaSynthChannelHandle=k;