audio-mixer-engine 0.5.2 → 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.
@@ -1 +1 @@
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 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(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,q=s;if(t<n){const d=n-t;r=n,q=Math.max(0,s-d)}if(q<=0)return a;const l=Math.max(0,(r-n)*1e3),o=setTimeout(()=>{this.noteOn(e,i),this.scheduledEvents.delete(`${a}_on`)},l),h=l+q*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,l=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,l],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,l),setTimeout(()=>{n.noteOff&&n.noteOff(a,r)},100)):setTimeout(()=>{n.noteOn&&n.noteOn(a,r,l),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,q]=a.split("=");r&&q!==void 0&&(e[r]=q)}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,q={format:s,ticksPerBeat:r,tracks:[],duration:0};let l=8+i;for(let o=0;o<n;o++)if(e[l]===77&&e[l+1]===84&&e[l+2]===114&&e[l+3]===107){const h=this._bytesToNumber(e.slice(l+4,l+8)),u=e.slice(l+8,l+8+h),d=this._parseTrack(u);q.tracks.push(d),l+=8+h}else throw new Error(`Invalid track header at position ${l}`);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 l=t[i++],o=this._readVariableLengthValue(t,i);i+=o.bytesRead;const h=t.slice(i,i+o.value);switch(i+=o.value,l){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((q&240)===144){const l=q&15,o=t[i++],h=t[i++];h>0?e.notes.push({type:"noteOn",noteNumber:o,velocity:h,tick:s,channel:l}):e.notes.push({type:"noteOff",noteNumber:o,tick:s,channel:l})}else if((q&240)===128){const l=q&15,o=t[i++];t[i++],e.notes.push({type:"noteOff",noteNumber:o,tick:s,channel:l})}else if(q===240||q===247){const l=this._readVariableLengthValue(t,i);i+=l.bytesRead+l.value}else if((q&240)===176){const l=q&15,o=t[i++],h=t[i++];e.events.push({type:"controller",controllerNumber:o,value:h,channel:l,tick:s})}else if((q&240)===192){const l=q&15,o=t[i++];e.events.push({type:"programChange",programNumber:o,channel:l,tick:s})}else if((q&240)===208){const l=q&15,o=t[i++];e.events.push({type:"channelAftertouch",pressure:o,channel:l,tick:s})}else if((q&240)===224){const l=q&15,o=t[i++],u=(t[i++]<<7|o)-8192;e.events.push({type:"pitchBend",value:u,channel:l,tick:s})}else if((q&240)===160){const l=q&15,o=t[i++],h=t[i++];e.events.push({type:"noteAftertouch",noteNumber:o,pressure:h,channel:l,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.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},q=0,l=0;for(;q<s;){for(;l<a.length&&a[l].tick<=q;)r=a[l],l++;let o;o=q+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=q+m*d,y=this._ticksToTime(A,t);u.push(y)}n.push({sig:[r.numerator,r.denominator],beats:u}),q=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 l=t.tracks.findIndex(o=>o.name===n.trackName);l!==-1&&(a=t.tracks[l],r=l)}if(!a)continue;const q=this._extractPartDataFromTrack(a,r,t,i);n.instrument!==void 0&&n.instrument!==null&&(q.defaultInstrument=this._resolveInstrument(n.instrument)),e[s]=q}else t.tracks.forEach((s,n)=>{if(!s.notes.length)return;let a=null;if(s.name){const l=s.name.toLowerCase();for(const o of this.partNames)if(o.length===1){if(l===o){a=o;break}}else if(l.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,q=2;for(;e[r];)r=`${a} ${q}`,q++;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 q=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),l=q.length>0?q[0].programNumber:0;return{notes:n,lyrics:r,trackIndex:e,programChanges:q,defaultInstrument:l}}_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(q=>{q.events.forEach(l=>{l.type==="tempo"&&s.push(l)})}),s.sort((q,l)=>q.tick-l.tick);let n=0,a=0,r=120;for(const q of s){if(q.tick>t)break;if(q.tick>a){const o=(q.tick-a)/i*(60/r);n+=o,a=q.tick}r=q.bpm}if(t>a){const l=(t-a)/i*(60/r);n+=l}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 q=s[r],l=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=l;u<=o;u++)this._shouldPlayBar(a,u,h)&&i.push({barNumber:u,repeat:q,sectionIndex:n.section,voltaTime:h})}return i}generateBarOrderFromLegacyBars(t,e){const i=[];let s=1,n=0;for(const a of t){a.from!==void 0&&(s=a.from===-1?0:a.from,n=0);const r=a.repeat||1;let q=a.beats;for(;q>0;){const o=this._getBeatsPerBar(s,e)-n;q>=o?(i.push({barNumber:s,repeat:r,sectionIndex:0,voltaTime:1}),q-=o,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 q=t[a],l=q.barNumber;if(s[l]===void 0){const d=r[n];if(!d||!d.sig)throw new Error(`Invalid MIDI bar structure at index ${n}`);s[l]=d.sig[0]}const o=s[l];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,q,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 l={time:a[r-1],repeat:e.repeat,bar:e.barNumber,beat:r,timeSig:s};t.push(l)}}_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 q=a.programChanges;for(;r<q.length&&q[r].time<e;)r++;for(;r<q.length&&q[r].time<=i;){const l=q[r];n.setInstrument(l.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 l=q[r];if(l.endTime-l.startTime>=.01){const o=this.playbackStartTime+l.startTime/this.playbackSpeed,h=(l.endTime-l.startTime)/this.playbackSpeed;n.playNote(o,l.pitch,l.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 q=[];for(const l of a){const o=n[l];if(!o)continue;const h=this.midiPlayer.getPartChannel(l);if(!h)continue;const u=this.midiPlayer.getPartOutput(l);u&&u.gain.value===0||(h.playPreviewNote(o.pitch,{startTime:r,duration:i,velocity:s,instrument:t.instrument}),q.push({partName:l,pitch:o.pitch,startTime:r}),r+=e)}return{parts:q,totalDuration:q.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 q=this.midiPlayer&&this.midiPlayer.playbackSpeed||1,l=n/q,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*l,beatSequence:this._generateBeatSequence(d,l,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 l=Math.max(q,this.audioEngine.audioContext.currentTime+.001),o=a.isDownbeat||a.beat===1;this._scheduleTickAtTime(l,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,q=this.audioEngine.audioContext.currentTime+Math.max(a,.005),l=Math.max(r,q),o=n.beat===1;this._scheduleTickAtTime(l,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;
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;
@@ -56,8 +56,8 @@ class g {
56
56
  a.gain.value = i, n.connect(a);
57
57
  const r = this.getMetronomeOutput();
58
58
  r ? a.connect(r) : a.connect(this.audioContext.destination);
59
- const q = Math.max(t, this.audioContext.currentTime);
60
- n.start(q);
59
+ const l = Math.max(t, this.audioContext.currentTime);
60
+ n.start(l);
61
61
  } catch (s) {
62
62
  console.warn("Buffer metronome playback failed:", s);
63
63
  }
@@ -182,16 +182,16 @@ class y {
182
182
  playNote(t, e, i, s) {
183
183
  this._validateActive();
184
184
  const n = this.engine.audioContext.currentTime, a = `${this.partId}_${t}_${e}_${Date.now()}`;
185
- let r = t, q = s;
185
+ let r = t, l = s;
186
186
  if (t < n) {
187
187
  const c = n - t;
188
- r = n, q = Math.max(0, s - c);
188
+ r = n, l = Math.max(0, s - c);
189
189
  }
190
- if (q <= 0)
190
+ if (l <= 0)
191
191
  return a;
192
- const l = Math.max(0, (r - n) * 1e3), o = setTimeout(() => {
192
+ const q = Math.max(0, (r - n) * 1e3), o = setTimeout(() => {
193
193
  this.noteOn(e, i), this.scheduledEvents.delete(`${a}_on`);
194
- }, l), h = l + q * 1e3, u = setTimeout(() => {
194
+ }, q), h = q + l * 1e3, u = setTimeout(() => {
195
195
  this.noteOff(e), this.scheduledEvents.delete(`${a}_off`);
196
196
  }, h);
197
197
  return this.scheduledEvents.set(`${a}_on`, o), this.scheduledEvents.set(`${a}_off`, u), a;
@@ -786,12 +786,12 @@ class M extends g {
786
786
  const s = this.getMetronomeChannel(), n = this._getSynthesizer();
787
787
  if (!s || !n)
788
788
  return super.playMetronomeTick(t, e, i);
789
- const a = 15, r = e ? 86 : 60, l = Math.round(Math.min(127, Math.max(0, i * (e ? 127 : 100)))), o = this.audioContext.currentTime, h = Math.max(t, o), u = h - o;
789
+ 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;
790
790
  n.post ? (n.post({
791
791
  channelNumber: a,
792
792
  type: "midiMessage",
793
793
  data: {
794
- messageData: [144 | a, r, l],
794
+ messageData: [144 | a, r, q],
795
795
  channelOffset: 0,
796
796
  force: !1,
797
797
  options: {
@@ -811,10 +811,10 @@ class M extends g {
811
811
  // Precise tick duration!
812
812
  }
813
813
  }
814
- })) : u <= 0.01 ? (n.noteOn && n.noteOn(a, r, l), setTimeout(() => {
814
+ })) : u <= 0.01 ? (n.noteOn && n.noteOn(a, r, q), setTimeout(() => {
815
815
  n.noteOff && n.noteOff(a, r);
816
816
  }, 100)) : setTimeout(() => {
817
- n.noteOn && n.noteOn(a, r, l), setTimeout(() => {
817
+ n.noteOn && n.noteOn(a, r, q), setTimeout(() => {
818
818
  n.noteOff && n.noteOff(a, r);
819
819
  }, 100);
820
820
  }, u * 1e3);
@@ -919,8 +919,8 @@ class P {
919
919
  return e;
920
920
  const n = t.substring(i + 1).split("&");
921
921
  for (const a of n) {
922
- const [r, q] = a.split("=");
923
- r && q !== void 0 && (e[r] = q);
922
+ const [r, l] = a.split("=");
923
+ r && l !== void 0 && (e[r] = l);
924
924
  }
925
925
  return e;
926
926
  }
@@ -932,20 +932,20 @@ class P {
932
932
  const e = new Uint8Array(t);
933
933
  if (!(e[0] === 77 && e[1] === 84 && e[2] === 104 && e[3] === 100))
934
934
  throw new Error("Not a valid MIDI file");
935
- 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 = {
935
+ 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 = {
936
936
  format: s,
937
937
  ticksPerBeat: r,
938
938
  tracks: [],
939
939
  duration: 0
940
940
  };
941
- let l = 8 + i;
941
+ let q = 8 + i;
942
942
  for (let o = 0; o < n; o++)
943
- if (e[l] === 77 && e[l + 1] === 84 && e[l + 2] === 114 && e[l + 3] === 107) {
944
- const h = this._bytesToNumber(e.slice(l + 4, l + 8)), u = e.slice(l + 8, l + 8 + h), c = this._parseTrack(u);
945
- q.tracks.push(c), l += 8 + h;
943
+ if (e[q] === 77 && e[q + 1] === 84 && e[q + 2] === 114 && e[q + 3] === 107) {
944
+ const h = this._bytesToNumber(e.slice(q + 4, q + 8)), u = e.slice(q + 8, q + 8 + h), c = this._parseTrack(u);
945
+ l.tracks.push(c), q += 8 + h;
946
946
  } else
947
- throw new Error(`Invalid track header at position ${l}`);
948
- return q;
947
+ throw new Error(`Invalid track header at position ${q}`);
948
+ return l;
949
949
  }
950
950
  /**
951
951
  * Parse a single MIDI track
@@ -966,18 +966,18 @@ class P {
966
966
  r = t[i++], a = a << 7 | r & 127;
967
967
  while (r & 128);
968
968
  s += a, r = t[i++];
969
- let q = r;
969
+ let l = r;
970
970
  if ((r & 128) === 0) {
971
971
  if (n === null)
972
972
  throw new Error("Running status byte encountered before status byte");
973
- q = n, i--;
973
+ l = n, i--;
974
974
  } else
975
- n = q;
976
- if (q === 255) {
977
- const l = t[i++], o = this._readVariableLengthValue(t, i);
975
+ n = l;
976
+ if (l === 255) {
977
+ const q = t[i++], o = this._readVariableLengthValue(t, i);
978
978
  i += o.bytesRead;
979
979
  const h = t.slice(i, i + o.value);
980
- switch (i += o.value, l) {
980
+ switch (i += o.value, q) {
981
981
  case 3:
982
982
  e.name = this._bytesToString(h);
983
983
  break;
@@ -1014,75 +1014,75 @@ class P {
1014
1014
  e.duration = s;
1015
1015
  break;
1016
1016
  }
1017
- } else if ((q & 240) === 144) {
1018
- const l = q & 15, o = t[i++], h = t[i++];
1017
+ } else if ((l & 240) === 144) {
1018
+ const q = l & 15, o = t[i++], h = t[i++];
1019
1019
  h > 0 ? e.notes.push({
1020
1020
  type: "noteOn",
1021
1021
  noteNumber: o,
1022
1022
  velocity: h,
1023
1023
  tick: s,
1024
- channel: l
1024
+ channel: q
1025
1025
  }) : e.notes.push({
1026
1026
  type: "noteOff",
1027
1027
  noteNumber: o,
1028
1028
  tick: s,
1029
- channel: l
1029
+ channel: q
1030
1030
  });
1031
- } else if ((q & 240) === 128) {
1032
- const l = q & 15, o = t[i++];
1031
+ } else if ((l & 240) === 128) {
1032
+ const q = l & 15, o = t[i++];
1033
1033
  t[i++], e.notes.push({
1034
1034
  type: "noteOff",
1035
1035
  noteNumber: o,
1036
1036
  tick: s,
1037
- channel: l
1037
+ channel: q
1038
1038
  });
1039
- } else if (q === 240 || q === 247) {
1040
- const l = this._readVariableLengthValue(t, i);
1041
- i += l.bytesRead + l.value;
1042
- } else if ((q & 240) === 176) {
1043
- const l = q & 15, o = t[i++], h = t[i++];
1039
+ } else if (l === 240 || l === 247) {
1040
+ const q = this._readVariableLengthValue(t, i);
1041
+ i += q.bytesRead + q.value;
1042
+ } else if ((l & 240) === 176) {
1043
+ const q = l & 15, o = t[i++], h = t[i++];
1044
1044
  e.events.push({
1045
1045
  type: "controller",
1046
1046
  controllerNumber: o,
1047
1047
  value: h,
1048
- channel: l,
1048
+ channel: q,
1049
1049
  tick: s
1050
1050
  });
1051
- } else if ((q & 240) === 192) {
1052
- const l = q & 15, o = t[i++];
1051
+ } else if ((l & 240) === 192) {
1052
+ const q = l & 15, o = t[i++];
1053
1053
  e.events.push({
1054
1054
  type: "programChange",
1055
1055
  programNumber: o,
1056
- channel: l,
1056
+ channel: q,
1057
1057
  tick: s
1058
1058
  });
1059
- } else if ((q & 240) === 208) {
1060
- const l = q & 15, o = t[i++];
1059
+ } else if ((l & 240) === 208) {
1060
+ const q = l & 15, o = t[i++];
1061
1061
  e.events.push({
1062
1062
  type: "channelAftertouch",
1063
1063
  pressure: o,
1064
- channel: l,
1064
+ channel: q,
1065
1065
  tick: s
1066
1066
  });
1067
- } else if ((q & 240) === 224) {
1068
- const l = q & 15, o = t[i++], u = (t[i++] << 7 | o) - 8192;
1067
+ } else if ((l & 240) === 224) {
1068
+ const q = l & 15, o = t[i++], u = (t[i++] << 7 | o) - 8192;
1069
1069
  e.events.push({
1070
1070
  type: "pitchBend",
1071
1071
  value: u,
1072
- channel: l,
1072
+ channel: q,
1073
1073
  tick: s
1074
1074
  });
1075
- } else if ((q & 240) === 160) {
1076
- const l = q & 15, o = t[i++], h = t[i++];
1075
+ } else if ((l & 240) === 160) {
1076
+ const q = l & 15, o = t[i++], h = t[i++];
1077
1077
  e.events.push({
1078
1078
  type: "noteAftertouch",
1079
1079
  noteNumber: o,
1080
1080
  pressure: h,
1081
- channel: l,
1081
+ channel: q,
1082
1082
  tick: s
1083
1083
  });
1084
1084
  } else
1085
- console.warn(`Unknown event type: ${q.toString(16)} at position ${i - 1}`), i++;
1085
+ console.warn(`Unknown event type: ${l.toString(16)} at position ${i - 1}`), i++;
1086
1086
  }
1087
1087
  return e;
1088
1088
  }
@@ -1136,21 +1136,21 @@ class P {
1136
1136
  });
1137
1137
  }), s === 0 && (s = e * 8);
1138
1138
  const n = [], a = i.filter((o) => o.type === "timeSignature").sort((o, h) => o.tick - h.tick);
1139
- let r = { numerator: 4, denominator: 4 }, q = 0, l = 0;
1140
- for (; q < s; ) {
1141
- for (; l < a.length && a[l].tick <= q; )
1142
- r = a[l], l++;
1139
+ let r = { numerator: 4, denominator: 4 }, l = 0, q = 0;
1140
+ for (; l < s; ) {
1141
+ for (; q < a.length && a[q].tick <= l; )
1142
+ r = a[q], q++;
1143
1143
  let o;
1144
- o = q + e * 4 * r.numerator / r.denominator;
1144
+ o = l + e * 4 * r.numerator / r.denominator;
1145
1145
  const h = r.numerator, u = [], c = e * (4 / r.denominator);
1146
1146
  for (let m = 0; m < h; m++) {
1147
- const A = q + m * c, f = this._ticksToTime(A, t);
1147
+ const A = l + m * c, f = this._ticksToTime(A, t);
1148
1148
  u.push(f);
1149
1149
  }
1150
1150
  n.push({
1151
1151
  sig: [r.numerator, r.denominator],
1152
1152
  beats: u
1153
- }), q = o;
1153
+ }), l = o;
1154
1154
  }
1155
1155
  this.parsedData.barStructure = n;
1156
1156
  }
@@ -1168,35 +1168,35 @@ class P {
1168
1168
  if (n.trackIndex !== void 0 && n.trackIndex !== null)
1169
1169
  r = n.trackIndex, r >= 0 && r < t.tracks.length && (a = t.tracks[r]);
1170
1170
  else if (n.trackName) {
1171
- const l = t.tracks.findIndex((o) => o.name === n.trackName);
1172
- l !== -1 && (a = t.tracks[l], r = l);
1171
+ const q = t.tracks.findIndex((o) => o.name === n.trackName);
1172
+ q !== -1 && (a = t.tracks[q], r = q);
1173
1173
  }
1174
1174
  if (!a)
1175
1175
  continue;
1176
- const q = this._extractPartDataFromTrack(a, r, t, i);
1177
- n.instrument !== void 0 && n.instrument !== null && (q.defaultInstrument = this._resolveInstrument(n.instrument)), e[s] = q;
1176
+ const l = this._extractPartDataFromTrack(a, r, t, i);
1177
+ n.instrument !== void 0 && n.instrument !== null && (l.defaultInstrument = this._resolveInstrument(n.instrument)), e[s] = l;
1178
1178
  }
1179
1179
  else
1180
1180
  t.tracks.forEach((s, n) => {
1181
1181
  if (!s.notes.length) return;
1182
1182
  let a = null;
1183
1183
  if (s.name) {
1184
- const l = s.name.toLowerCase();
1184
+ const q = s.name.toLowerCase();
1185
1185
  for (const o of this.partNames)
1186
1186
  if (o.length === 1) {
1187
- if (l === o) {
1187
+ if (q === o) {
1188
1188
  a = o;
1189
1189
  break;
1190
1190
  }
1191
- } else if (l.includes(o)) {
1191
+ } else if (q.includes(o)) {
1192
1192
  a = o;
1193
1193
  break;
1194
1194
  }
1195
1195
  }
1196
1196
  a || (a = s.name || `Track ${n + 1}`), a === "s" && (a = "soprano"), a === "a" && (a = "alto"), a === "t" && (a = "tenor"), a === "b" && (a = "bass");
1197
- let r = a, q = 2;
1197
+ let r = a, l = 2;
1198
1198
  for (; e[r]; )
1199
- r = `${a} ${q}`, q++;
1199
+ r = `${a} ${l}`, l++;
1200
1200
  a = r, e[a] = this._extractPartDataFromTrack(s, n, t, i);
1201
1201
  });
1202
1202
  this.parsedData.parts = e;
@@ -1235,17 +1235,17 @@ class P {
1235
1235
  // Time in quarter notes
1236
1236
  }));
1237
1237
  n.sort((o, h) => o.startTick - h.startTick);
1238
- const q = t.events.filter((o) => o.type === "programChange").map((o) => ({
1238
+ const l = t.events.filter((o) => o.type === "programChange").map((o) => ({
1239
1239
  programNumber: o.programNumber,
1240
1240
  tick: o.tick,
1241
1241
  time: this._ticksToTime(o.tick, i)
1242
- })).sort((o, h) => o.tick - h.tick), l = q.length > 0 ? q[0].programNumber : 0;
1242
+ })).sort((o, h) => o.tick - h.tick), q = l.length > 0 ? l[0].programNumber : 0;
1243
1243
  return {
1244
1244
  notes: n,
1245
1245
  lyrics: r,
1246
1246
  trackIndex: e,
1247
- programChanges: q,
1248
- defaultInstrument: l
1247
+ programChanges: l,
1248
+ defaultInstrument: q
1249
1249
  };
1250
1250
  }
1251
1251
  /**
@@ -1315,23 +1315,23 @@ class P {
1315
1315
  */
1316
1316
  _ticksToTime(t, e) {
1317
1317
  const i = e.ticksPerBeat || 480, s = [];
1318
- e.tracks.forEach((q) => {
1319
- q.events.forEach((l) => {
1320
- l.type === "tempo" && s.push(l);
1318
+ e.tracks.forEach((l) => {
1319
+ l.events.forEach((q) => {
1320
+ q.type === "tempo" && s.push(q);
1321
1321
  });
1322
- }), s.sort((q, l) => q.tick - l.tick);
1322
+ }), s.sort((l, q) => l.tick - q.tick);
1323
1323
  let n = 0, a = 0, r = 120;
1324
- for (const q of s) {
1325
- if (q.tick > t) break;
1326
- if (q.tick > a) {
1327
- const o = (q.tick - a) / i * (60 / r);
1328
- n += o, a = q.tick;
1324
+ for (const l of s) {
1325
+ if (l.tick > t) break;
1326
+ if (l.tick > a) {
1327
+ const o = (l.tick - a) / i * (60 / r);
1328
+ n += o, a = l.tick;
1329
1329
  }
1330
- r = q.bpm;
1330
+ r = l.bpm;
1331
1331
  }
1332
1332
  if (t > a) {
1333
- const l = (t - a) / i * (60 / r);
1334
- n += l;
1333
+ const q = (t - a) / i * (60 / r);
1334
+ n += q;
1335
1335
  }
1336
1336
  return n;
1337
1337
  }
@@ -1367,11 +1367,11 @@ class E {
1367
1367
  throw new Error(`Invalid section index: ${n.section}`);
1368
1368
  const r = n.section;
1369
1369
  s[r] || (s[r] = 0), s[r]++;
1370
- const q = s[r], l = n.from !== void 0 ? n.from : this._getSectionStartBar(t, n.section), o = n.to !== void 0 ? n.to : a.to, h = n.as || 1;
1371
- for (let u = l; u <= o; u++)
1370
+ 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;
1371
+ for (let u = q; u <= o; u++)
1372
1372
  this._shouldPlayBar(a, u, h) && i.push({
1373
1373
  barNumber: u,
1374
- repeat: q,
1374
+ repeat: l,
1375
1375
  sectionIndex: n.section,
1376
1376
  voltaTime: h
1377
1377
  });
@@ -1386,21 +1386,21 @@ class E {
1386
1386
  */
1387
1387
  generateBarOrderFromLegacyBars(t, e) {
1388
1388
  const i = [];
1389
- let s = 1, n = 0;
1390
- for (const a of t) {
1391
- a.from !== void 0 && (s = a.from === -1 ? 0 : a.from, n = 0);
1392
- const r = a.repeat || 1;
1393
- let q = a.beats;
1389
+ let s = 1, n = 0, a;
1390
+ for (const r of t) {
1391
+ r.from !== void 0 && (s = r.from === -1 ? 0 : r.from, n = 0), r.timeSig !== void 0 && (a = r.timeSig);
1392
+ const l = r.repeat || 1;
1393
+ let q = r.beats;
1394
1394
  for (; q > 0; ) {
1395
- const o = this._getBeatsPerBar(s, e) - n;
1396
- q >= o ? (i.push({
1395
+ const h = (a !== void 0 ? a : this._getBeatsPerBar(s, e)) - n;
1396
+ q >= h ? (i.push({
1397
1397
  barNumber: s,
1398
- repeat: r,
1398
+ repeat: l,
1399
1399
  sectionIndex: 0,
1400
1400
  // Legacy format doesn't have sections
1401
1401
  voltaTime: 1
1402
1402
  // Legacy format doesn't have voltas
1403
- }), q -= o, n = 0, s === 0 ? s = 1 : s++) : (n += q, q = 0);
1403
+ }), q -= h, n = 0, s === 0 ? s = 1 : s++) : (n += q, q = 0);
1404
1404
  }
1405
1405
  }
1406
1406
  return n > 0 && i.push({
@@ -1452,14 +1452,14 @@ class E {
1452
1452
  let n = 0, a = 0;
1453
1453
  const r = [...e];
1454
1454
  for (; a < t.length && n < r.length; ) {
1455
- const q = t[a], l = q.barNumber;
1456
- if (s[l] === void 0) {
1455
+ const l = t[a], q = l.barNumber;
1456
+ if (s[q] === void 0) {
1457
1457
  const c = r[n];
1458
1458
  if (!c || !c.sig)
1459
1459
  throw new Error(`Invalid MIDI bar structure at index ${n}`);
1460
- s[l] = c.sig[0];
1460
+ s[q] = c.sig[0];
1461
1461
  }
1462
- const o = s[l];
1462
+ const o = s[q];
1463
1463
  let h = r[n], u = h.sig[0];
1464
1464
  for (; u < o && n + 1 < r.length; ) {
1465
1465
  const c = r[n + 1], m = [
@@ -1486,7 +1486,7 @@ class E {
1486
1486
  };
1487
1487
  r[n] = b, r.splice(n + 1, 0, T), h = b;
1488
1488
  }
1489
- this._generateBeatsForBar(i, q, h, o), n++, a++;
1489
+ this._generateBeatsForBar(i, l, h, o), n++, a++;
1490
1490
  }
1491
1491
  if (a < t.length)
1492
1492
  throw new Error(`Ran out of MIDI bars before completing score. Score bar ${a}/${t.length}, MIDI bar ${n}/${r.length}`);
@@ -1502,14 +1502,14 @@ class E {
1502
1502
  throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(i)}`);
1503
1503
  const a = n.slice(0, s);
1504
1504
  for (let r = 1; r <= s; r++) {
1505
- const l = {
1505
+ const q = {
1506
1506
  time: a[r - 1],
1507
1507
  repeat: e.repeat,
1508
1508
  bar: e.barNumber,
1509
1509
  beat: r,
1510
1510
  timeSig: s
1511
1511
  };
1512
- t.push(l);
1512
+ t.push(q);
1513
1513
  }
1514
1514
  }
1515
1515
  /**
@@ -1807,25 +1807,25 @@ class p {
1807
1807
  if (a) {
1808
1808
  if (a.programChanges && a.programChanges.length > 0) {
1809
1809
  let r = this.partProgramPointers.get(s) || 0;
1810
- const q = a.programChanges;
1811
- for (; r < q.length && q[r].time < e; )
1810
+ const l = a.programChanges;
1811
+ for (; r < l.length && l[r].time < e; )
1812
1812
  r++;
1813
- for (; r < q.length && q[r].time <= i; ) {
1814
- const l = q[r];
1815
- n.setInstrument(l.programNumber), r++;
1813
+ for (; r < l.length && l[r].time <= i; ) {
1814
+ const q = l[r];
1815
+ n.setInstrument(q.programNumber), r++;
1816
1816
  }
1817
1817
  this.partProgramPointers.set(s, r);
1818
1818
  }
1819
1819
  if (a.notes) {
1820
1820
  let r = this.partNotePointers.get(s) || 0;
1821
- const q = a.notes;
1822
- for (; r < q.length && q[r].endTime < e; )
1821
+ const l = a.notes;
1822
+ for (; r < l.length && l[r].endTime < e; )
1823
1823
  r++;
1824
- for (; r < q.length && q[r].startTime <= i; ) {
1825
- const l = q[r];
1826
- if (l.endTime - l.startTime >= 0.01) {
1827
- const o = this.playbackStartTime + l.startTime / this.playbackSpeed, h = (l.endTime - l.startTime) / this.playbackSpeed;
1828
- n.playNote(o, l.pitch, l.velocity, h);
1824
+ for (; r < l.length && l[r].startTime <= i; ) {
1825
+ const q = l[r];
1826
+ if (q.endTime - q.startTime >= 0.01) {
1827
+ const o = this.playbackStartTime + q.startTime / this.playbackSpeed, h = (q.endTime - q.startTime) / this.playbackSpeed;
1828
+ n.playNote(o, q.pitch, q.velocity, h);
1829
1829
  }
1830
1830
  r++;
1831
1831
  }
@@ -2292,27 +2292,27 @@ class B {
2292
2292
  throw new Error("No MIDI data loaded");
2293
2293
  const e = t.delayBetweenParts ?? 0.3, i = t.duration ?? 0.5, s = t.velocity ?? 100, n = this.midiPlayer.getAllNextNotes(), a = t.partOrder ?? this.getPartNames();
2294
2294
  let r = this.audioEngine.audioContext.currentTime + 0.01;
2295
- const q = [];
2296
- for (const l of a) {
2297
- const o = n[l];
2295
+ const l = [];
2296
+ for (const q of a) {
2297
+ const o = n[q];
2298
2298
  if (!o) continue;
2299
- const h = this.midiPlayer.getPartChannel(l);
2299
+ const h = this.midiPlayer.getPartChannel(q);
2300
2300
  if (!h) continue;
2301
- const u = this.midiPlayer.getPartOutput(l);
2301
+ const u = this.midiPlayer.getPartOutput(q);
2302
2302
  u && u.gain.value === 0 || (h.playPreviewNote(o.pitch, {
2303
2303
  startTime: r,
2304
2304
  duration: i,
2305
2305
  velocity: s,
2306
2306
  instrument: t.instrument
2307
- }), q.push({
2308
- partName: l,
2307
+ }), l.push({
2308
+ partName: q,
2309
2309
  pitch: o.pitch,
2310
2310
  startTime: r
2311
2311
  }), r += e);
2312
2312
  }
2313
2313
  return {
2314
- parts: q,
2315
- totalDuration: q.length * e
2314
+ parts: l,
2315
+ totalDuration: l.length * e
2316
2316
  };
2317
2317
  }
2318
2318
  // ========================================
@@ -2427,11 +2427,11 @@ class B {
2427
2427
  for (; t[s].time > e; ) s--;
2428
2428
  const a = t[s], r = t[s + 1];
2429
2429
  r ? n = r.time - a.time : s > 0 && (n = a.time - t[s - 1].time);
2430
- const q = this.midiPlayer && this.midiPlayer.playbackSpeed || 1, l = n / q, o = a.timeSig === 1, h = o && r ? r.timeSig : a.timeSig, u = o ? h - 1 : a.beat > 1 ? a.beat - 1 : 0, c = i * h + u;
2430
+ 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, c = i * h + u;
2431
2431
  return {
2432
2432
  totalBeats: c,
2433
- duration: c * l,
2434
- beatSequence: this._generateBeatSequence(c, l, h),
2433
+ duration: c * q,
2434
+ beatSequence: this._generateBeatSequence(c, q, h),
2435
2435
  beatsPerBar: h,
2436
2436
  startBeat: a
2437
2437
  };
@@ -2573,12 +2573,12 @@ class B {
2573
2573
  return;
2574
2574
  const i = this.midiPlayer.getCurrentTime(), s = 0.1;
2575
2575
  for (let n = this.nextBeatIndex; n < e.length; n++) {
2576
- const a = e[n], r = this.midiPlayer.playbackSpeed || 1, q = t + (a.time - i) / r;
2577
- if (q > this.audioEngine.audioContext.currentTime + s)
2576
+ const a = e[n], r = this.midiPlayer.playbackSpeed || 1, l = t + (a.time - i) / r;
2577
+ if (l > this.audioEngine.audioContext.currentTime + s)
2578
2578
  break;
2579
- if (q >= this.audioEngine.audioContext.currentTime - 0.01) {
2580
- const l = Math.max(q, this.audioEngine.audioContext.currentTime + 1e-3), o = a.isDownbeat || a.beat === 1;
2581
- this._scheduleTickAtTime(l, o), this.nextBeatIndex = n + 1;
2579
+ if (l >= this.audioEngine.audioContext.currentTime - 0.01) {
2580
+ const q = Math.max(l, this.audioEngine.audioContext.currentTime + 1e-3), o = a.isDownbeat || a.beat === 1;
2581
+ this._scheduleTickAtTime(q, o), this.nextBeatIndex = n + 1;
2582
2582
  }
2583
2583
  }
2584
2584
  }
@@ -2599,8 +2599,8 @@ class B {
2599
2599
  if (n.time > s)
2600
2600
  break;
2601
2601
  if (a >= -0.025 && a <= 0.15) {
2602
- const r = this.audioEngine.audioContext.currentTime + 5e-3, q = this.audioEngine.audioContext.currentTime + Math.max(a, 5e-3), l = Math.max(r, q), o = n.beat === 1;
2603
- this._scheduleTickAtTime(l, o);
2602
+ const r = this.audioEngine.audioContext.currentTime + 5e-3, l = this.audioEngine.audioContext.currentTime + Math.max(a, 5e-3), q = Math.max(r, l), o = n.beat === 1;
2603
+ this._scheduleTickAtTime(q, o);
2604
2604
  }
2605
2605
  this.nextBeatIndex++;
2606
2606
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "audio-mixer-engine",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Audio engine library for audio mixer applications with MIDI parsing, playback, and synthesis",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -95,6 +95,7 @@ class BeatMapper {
95
95
  const barOrder = [];
96
96
  let currentBar = 1; // Start at bar 1 by default
97
97
  let beatsInCurrentBar = 0; // Track accumulated beats in current bar
98
+ let currentTimeSig = undefined; // Track time signature from metadata
98
99
 
99
100
  for (const barEntry of bars) {
100
101
  // Handle 'from' field - jump to a specific bar
@@ -104,6 +105,11 @@ class BeatMapper {
104
105
  beatsInCurrentBar = 0; // Reset when jumping to a new bar
105
106
  }
106
107
 
108
+ // Update time signature if specified in this entry
109
+ if (barEntry.timeSig !== undefined) {
110
+ currentTimeSig = barEntry.timeSig;
111
+ }
112
+
107
113
  // Get repeat number (default to 1 if not specified)
108
114
  const repeat = barEntry.repeat || 1;
109
115
 
@@ -111,7 +117,10 @@ class BeatMapper {
111
117
  let remainingBeats = barEntry.beats;
112
118
 
113
119
  while (remainingBeats > 0) {
114
- const beatsPerBar = this._getBeatsPerBar(currentBar, midiBarStructure);
120
+ // Use time signature from metadata if available, otherwise get from MIDI
121
+ const beatsPerBar = currentTimeSig !== undefined
122
+ ? currentTimeSig
123
+ : this._getBeatsPerBar(currentBar, midiBarStructure);
115
124
  const beatsNeeded = beatsPerBar - beatsInCurrentBar;
116
125
 
117
126
  if (remainingBeats >= beatsNeeded) {