PageSourceSearch

https://motif-self.vercel.app/assets/v2-D_2Yz88L.js

js motif-self.vercel.app collected 2026-10-03 07:20:17 UTC 43,335 bytes, 13 lines download raw bytes

1var Wt=Object.defineProperty;var zt=(o,t,n)=>t in o?Wt(o,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):o[t]=n;var h=(o,t,n)=>zt(o,typeof t!="symbol"?t+"":t,n);import{c as J,M as Ut}from"./MIDIService-CF3kZgy9.js";/* empty css              */import{a as qt}from"./export-CbG4o32l.js";const $t=[.125,.25,.5,.75];function z(o,t){const n=$t[o],e=64,s=new Float32Array(e),i=new Float32Array(e);s[0]=0,i[0]=0;for(let a=1;a<e;a++){const r=2/(Math.PI*a)*Math.sin(Math.PI*a*n);i[a]=r,s[a]=0}return t.createPeriodicWave(s,i,{disableNormalization:!1})}function _t(o){return[z(0,o),z(1,o),z(2,o),z(3,o)]}const vt=131072,Tt=65536,Ct=2047,Ot=[.5,1,1.5,2,2.5,3,3.5,4];function wt(o){return 440*Math.pow(2,(o-69)/12)}function Ht(o){const t=Math.round(2048-vt/o);return Math.max(0,Math.min(Ct,t))}function Xt(o){return o>=2048?0:vt/(2048-o)}function U(o){const t=wt(o),n=Ht(t);return Xt(n)}function jt(o){const t=Math.round(2048-Tt/o);return Math.max(0,Math.min(Ct,t))}function Qt(o){return o>=2048?0:Tt/(2048-o)}function ht(o){const t=wt(o),n=jt(t);return Qt(n)}function Kt(o,t){const n=Ot[o%8],e=Math.max(0,Math.min(14,t));return 524288/n/Math.pow(2,e+1)}function Yt(o){const t=Math.max(0,Math.min(72,o-24)),n=Math.floor(14-t/72*14);return{divisorCode:Math.floor(t%8),clockShift:n}}class Zt{constructor(t,n,e=!1){h(this,"audioContext");h(this,"dutyWaves");h(this,"currentDuty",2);h(this,"hasSweep");h(this,"outputNode");this.audioContext=t,this.outputNode=n,this.hasSweep=e,this.dutyWaves=_t(t)}setDutyCycle(t){this.currentDuty=t}getDutyCycle(){return this.currentDuty}playNote(t,n,e=100,s){const i=s??this.audioContext.currentTime,a=this.audioContext.createOscillator();a.setPeriodicWave(this.dutyWaves[this.currentDuty]);const r=U(t);a.frequency.setValueAtTime(r,i);const c=this.audioContext.createGain(),l=e/127*.8,d=.005,u=.02;c.gain.setValueAtTime(0,i),c.gain.linearRampToValueAtTime(l,i+d);const m=i+Math.max(d,n-u);c.gain.setValueAtTime(l,m);const f=i+n+u;return c.gain.linearRampToValueAtTime(.001,f),a.connect(c),c.connect(this.outputNode),a.start(i),a.stop(f+.01),a.onended=()=>{try{a.disconnect(),c.disconnect()}catch{}},{oscillator:a,gainNode:c,stopTime:f}}playNoteWithDuty(t,n,e,s,i){const a=i??this.audioContext.currentTime,r=this.audioContext.createOscillator();r.setPeriodicWave(this.dutyWaves[s]);const c=U(t);r.frequency.setValueAtTime(c,a);const l=this.audioContext.createGain(),d=e/127*.8,u=.005,m=.02;l.gain.setValueAtTime(0,a),l.gain.linearRampToValueAtTime(d,a+u);const f=a+Math.max(u,n-m);l.gain.setValueAtTime(d,f);const C=a+n+m;return l.gain.linearRampToValueAtTime(.001,C),r.connect(l),l.connect(this.outputNode),r.start(a),r.stop(C+.01),r.onended=()=>{try{r.disconnect(),l.disconnect()}catch{}},{oscillator:r,gainNode:l,stopTime:C}}canSweep(){return this.hasSweep}playNoteWithSweep(t,n,e,s=100,i){if(!this.hasSweep)return console.warn("PulseChannel: Sweep not available on this channel"),null;const a=i??this.audioContext.currentTime,r=this.audioContext.createOscillator();r.setPeriodicWave(this.dutyWaves[this.currentDuty]);const c=U(t),l=U(n);r.frequency.setValueAtTime(c,a),r.frequency.linearRampToValueAtTime(l,a+e);const d=this.audioContext.createGain(),u=s/127*.8,m=.005,f=.02;d.gain.setValueAtTime(0,a),d.gain.linearRampToValueAtTime(u,a+m);const C=a+Math.max(m,e-f);d.gain.setValueAtTime(u,C);const v=a+e+f;return d.gain.linearRampToValueAtTime(.001,v),r.connect(d),d.connect(this.outputNode),r.start(a),r.stop(v+.01),r.onended=()=>{try{r.disconnect(),d.disconnect()}catch{}},{oscillator:r,gainNode:d,stopTime:v}}}const g=32,w=15,dt={0:0,1:1,2:.5,3:.25};class Jt{constructor(){h(this,"samples");this.samples=new Uint8Array(g),this.samples.fill(8)}quantize(t){const n=Math.max(0,Math.min(1,t));return Math.floor(n*w)}loadFromFloats(t){for(let n=0;n<g;n++){const e=n<t.length?t[n]:.5;this.samples[n]=this.quantize(e)}}loadFromBytes(t){for(let n=0;n<g;n++){const e=n<t.length?t[n]:8;this.samples[n]=Math.max(0,Math.min(w,Math.floor(e)))}}getSamples(){return this.samples}createBuffer(t){const n=t.createBuffer(1,g,t.sampleRate),e=n.getChannelData(0);for(let s=0;s<g;s++)e[s]=this.samples[s]/w*2-1;return n}createExtendedBuffer(t,n=256){const e=g*n,s=t.createBuffer(1,e,t.sampleRate),i=s.getChannelData(0);for(let a=0;a<e;a++){const r=a%g;i[a]=this.samples[r]/w*2-1}return s}}function bt(){const o=new Uint8Array(g);for(let t=0;t<g;t++){const n=t/g;let e;n<.5?e=n*2:e=2-n*2,o[t]=Math.floor(e*w)}return o}function te(){const o=new Uint8Array(g);for(let t=0;t<g;t++)o[t]=Math.floor(t/(g-1)*w);return o}function It(){const o=new Uint8Array(g);for(let t=0;t<g;t++){const n=t/g*Math.PI*2,e=(Math.sin(n)+1)/2;o[t]=Math.floor(e*w)}return o}function ee(){const o=new Uint8Array(g);for(let t=0;t<g;t++)o[t]=t<g/2?w:0;return o}function ne(){return bt()}function se(){return It()}function ie(){const o=new Uint8Array(g);for(let t=0;t<g;t++){const n=t/g,e=n,s=n<.5?n*2:2-n*2,i=e*.6+s*.4;o[t]=Math.floor(i*w)}return o}const mt={triangle:bt,sawtooth:te,sine:It,square:ee,bass:ne,pad:se,lead:ie};function q(o,t,n=16){const e=o.length,s=[];for(let c=0;c<e;c++){const l=typeof o[c]=="number"?o[c]:0;s.push(l/w*2-1)}const i=Math.min(n,32),a=new Float32Array(i),r=new Float32Array(i);a[0]=0,r[0]=0;for(let c=1;c<i;c++){let l=0,d=0;for(let m=0;m<e;m++){const f=2*Math.PI*c*m/e;l+=s[m]*Math.cos(f),d-=s[m]*Math.sin(f)}const u=1/(1+c*.1);a[c]=2*l/e*u,r[c]=2*d/e*u}
1return t.createPeriodicWave(a,r,{disableNormalization:!1})}class ae{constructor(t,n,e="bass"){h(this,"audioContext");h(this,"waveTable");h(this,"periodicWave",null);h(this,"volume",1);h(this,"outputNode");h(this,"currentPreset");this.audioContext=t,this.outputNode=n,this.currentPreset=e,this.waveTable=new Jt,this.loadPreset(e)}loadPreset(t){this.currentPreset=t;const n=mt[t]();this.waveTable.loadFromBytes(Array.from(n)),this.periodicWave=q(this.waveTable.getSamples(),this.audioContext)}loadCustomWaveform(t){this.waveTable.loadFromBytes(t),this.periodicWave=q(this.waveTable.getSamples(),this.audioContext)}setVolume(t){this.volume=t}getVolume(){return this.volume}getPreset(){return this.currentPreset}playNote(t,n,e=100,s){const i=s??this.audioContext.currentTime;this.periodicWave||(this.periodicWave=q(this.waveTable.getSamples(),this.audioContext));const a=this.audioContext.createOscillator();a.setPeriodicWave(this.periodicWave);const r=ht(t);a.frequency.setValueAtTime(r,i);const c=this.audioContext.createGain(),l=e/127*.8,d=dt[this.volume],u=l*d,m=.002,f=.01;c.gain.setValueAtTime(0,i),c.gain.linearRampToValueAtTime(u,i+m);const C=i+Math.max(m,n-f);c.gain.setValueAtTime(u,C);const v=i+n+f;return c.gain.linearRampToValueAtTime(.001,v),a.connect(c),c.connect(this.outputNode),a.start(i),a.stop(v+.01),a.onended=()=>{try{a.disconnect(),c.disconnect()}catch{}},{oscillator:a,gainNode:c,stopTime:v}}playNoteWithPreset(t,n,e,s,i){const a=i??this.audioContext.currentTime,r=mt[s](),c=q(r,this.audioContext),l=this.audioContext.createOscillator();l.setPeriodicWave(c);const d=ht(t);l.frequency.setValueAtTime(d,a);const u=this.audioContext.createGain(),m=e/127*.8,f=dt[this.volume],C=m*f,v=.002,ut=.01;u.gain.setValueAtTime(0,a),u.gain.linearRampToValueAtTime(C,a+v);const Gt=a+Math.max(v,n-ut);u.gain.setValueAtTime(C,Gt);const Z=a+n+ut;return u.gain.linearRampToValueAtTime(.001,Z),l.connect(u),u.connect(this.outputNode),l.start(a),l.stop(Z+.01),l.onended=()=>{try{l.disconnect(),u.disconnect()}catch{}},{oscillator:l,gainNode:u,stopTime:Z}}getWaveformSamples(){return this.waveTable.getSamples()}}const ft=32767;class oe{constructor(t="15bit"){h(this,"lfsr");h(this,"mode");this.mode=t,this.lfsr=ft}clock(){const t=this.lfsr&1,n=this.lfsr&1,e=this.lfsr>>1&1,s=n^e;return this.lfsr>>=1,this.lfsr|=s<<14,this.mode==="7bit"&&(this.lfsr&=-65,this.lfsr|=s<<6),t}reset(){this.lfsr=ft}setMode(t){this.mode=t}getMode(){return this.mode}getValue(){return this.lfsr}generateSequence(t){const n=[];for(let e=0;e<t;e++)n.push(this.clock());return n}}function re(o,t,n,e="15bit"){const s=o.sampleRate,i=Math.ceil(t*s),a=o.createBuffer(1,i,s),r=a.getChannelData(0),c=new oe(e),l=s/n;let d=0,u=0;for(let m=0;m<i;m++)d+=1,d>=l&&(u=c.clock(),d-=l),r[m]=u*2-1;return a}class ce{constructor(t,n,e="15bit"){h(this,"audioContext");h(this,"mode");h(this,"outputNode");h(this,"bufferCache",[]);h(this,"maxCacheSize",8);this.audioContext=t,this.outputNode=n,this.mode=e}setMode(t){this.mode=t}getMode(){return this.mode}getNoiseBuffer(t,n,e){const s=this.bufferCache.find(a=>a.frequency===t&&a.mode===e&&a.duration>=n);if(s)return s.buffer;const i=re(this.audioContext,n+.1,t,e);for(this.bufferCache.push({buffer:i,frequency:t,mode:e,duration:n});this.bufferCache.length>this.maxCacheSize;)this.bufferCache.shift();return i}playNoise(t,n,e=100,s){const i=s??this.audioContext.currentTime,a=this.getNoiseBuffer(n,t,this.mode),r=this.audioContext.createBufferSource();r.buffer=a,r.loop=!1;const c=this.audioContext.createGain(),l=e/127*.3,d=.001,u=.05,m=l*.6,f=.03;c.gain.setValueAtTime(0,i),c.gain.linearRampToValueAtTime(l,i+d),c.gain.linearRampToValueAtTime(m,i+d+u);const C=i+Math.max(d+u,t-f);c.gain.setValueAtTime(m,C);const v=i+t+f;return c.gain.linearRampToValueAtTime(.001,v),r.connect(c),c.connect(this.outputNode),r.start(i),r.stop(v+.01),r.onended=()=>{try{r.disconnect(),c.disconnect()}catch{}},{source:r,gainNode:c,stopTime:v}}playNote(t,n,e=100,s){const{divisorCode:i,clockShift:a}=Yt(t),r=Kt(i,a);return this.playNoise(n,r,e,s)}playKick(t=100,n){const e=n??this.audioContext.currentTime,s=this.getNoiseBuffer(500,.15,"7bit"),i=this.audioContext.createBufferSource();i.buffer=s;const a=this.audioContext.createGain(),r=t/127*.4;return a.gain.setValueAtTime(r,e),a.gain.exponentialRampToValueAtTime(.01,e+.1),i.connect(a),a.connect(this.outputNode),i.start(e),i.stop(e+.15),i.onended=()=>{try{i.disconnect(),a.disconnect()}catch{}},{source:i,gainNode:a,stopTime:e+.15}}playSnare(t=100,n){const e=n??this.audioContext.currentTime,s=this.getNoiseBuffer(2e3,.2,"7bit"),i=this.audioContext.createBufferSource();i.buffer=s;const a=this.audioContext.createGain(),r=t/127*.3;return a.gain.setValueAtTime(0,e),a.gain.linearRampToValueAtTime(r,e+.005),a.gain.exponentialRampToValueAtTime(.01,e+.15),i.connect(a),a.connect(this.outputNode),i.start(e),i.stop(e+.2),i.onended=()=>{try{i.disconnect(),a.disconnect()}catch{}},{source:i,gainNode:a,stopTime:e+.2}}playHihat(t=100,n=!1,e){const s=e??this.audioContext.currentTime,i=n?.3:.08,a=this.getNoiseBuffer(8e3,i,"15bit"),r=this.audioContext.createBufferSource();r.buffer=a;const c=this.audioContext.createGain(),l=t/127*.2;return c.gain.setValueAtTime(l,s),n?c.gain.exponentialRampToValueAtTime(.01,s+.25):c.gain.exponentialRampToValueAtTime(.01,s+.05),r.connect(c),c.connect(this.outputNode),r.start(s),r.stop(s+i),r.onended=()=>{try{r.disconnect(),c.disconnect()}catch{}},{source:r,gainNode:c,stopTime:s+i}}clearCache(){this.bufferCache=[]}}const le={enabled:!0,lowpassFreq:1e4,bitDepth:8,sampleRateReduction:1,saturation:.08,highpassFreq:20};class tt{constructor(t,n={}){h(this,"audioContext");h(this,"config");h(this,"inputGain");h(this,"outputGain");h(this,"highpassFilter");h(this,"lowpassFilter");h(this,"bitCrusher",null);h(this,"waveshaper");h(this,"limiter");h(this,"isInitialized",!1);this.audioContext=t,this.config={...le,...n},this.inputGain=t.createGain(),this.outputGain=t.createGain(),this.highpassFilter=t.createBiquadFilter(),this.highpassFilter.type="highpass",this.highpassFilter.frequency.value=this.config.highpassFreq,this.highpassFilter.Q.value=.7,this.lowpassFilter=t.createBiquadFilter(),this.lowpassFilter.type="lowpass",this.lowpassFilter.frequency.value=this.config.lowpassFreq,this.lowpassFilter.Q.value=.7,this.waveshaper=t.createWaveShaper(),this.waveshaper.curve=this.createSaturationCurve(this.config.saturation),this.waveshaper.oversample="2x",this.limiter=t.createDynamicsCompressor(),this.limiter.threshold.value=-12,this.limiter.knee.value=3,this.limiter.ratio.value=20,this.limiter.attack.value=.001,this.limiter.release.value=.05,this.initializeBasicChain()}initializeBasicChain(){this.inputGain.connect(this.highpassFilter),this.highpassFilter.connect(this.lowpassFilter),this.lowpassFilter.connect(this.waveshaper),this.waveshaper.connect(this.limiter),this.limiter.connect(this.outputGain),this.isInitialized=!0}
1initializeBitCrusher(){if(this.bitCrusher)return;this.lowpassFilter.disconnect();const n=this.audioContext.createScriptProcessor(4096,1,1),e=this.config.bitDepth,s=this.config.sampleRateReduction,i=Math.pow(2,e);let a=0,r=0;n.onaudioprocess=c=>{const l=c.inputBuffer.getChannelData(0),d=c.outputBuffer.getChannelData(0);for(let u=0;u<l.length;u++){if(r++,r>=s){r=0;const m=l[u];a=Math.round(m*i)/i}d[u]=a}},this.bitCrusher=n,this.lowpassFilter.connect(n),n.connect(this.waveshaper)}createSaturationCurve(t){const e=new Float32Array(44100);for(let s=0;s<44100;s++){const i=s*2/44100-1;if(t===0)e[s]=i;else{const a=2*t/(1-t);e[s]=(1+a)*i/(1+a*Math.abs(i))}}return e}getInput(){return this.inputGain}getOutput(){return this.outputGain}setEnabled(t){this.config.enabled=t,this.inputGain.gain.value=t?1:0}setConfig(t){this.config={...this.config,...t},this.highpassFilter.frequency.value=this.config.highpassFreq,this.lowpassFilter.frequency.value=this.config.lowpassFreq,this.waveshaper.curve=this.createSaturationCurve(this.config.saturation)}getConfig(){return{...this.config}}static createPreset(t){return{enabled:!0,lowpassFreq:8e3,bitDepth:8,sampleRateReduction:1,saturation:.05,highpassFreq:30}}}const ue={masterVolume:.7,lookaheadTime:.1,scheduleInterval:25},et={pulse:[{id:"p1",hasSweep:!0,defaultDuty:2},{id:"p2",hasSweep:!0,defaultDuty:2},{id:"p3",hasSweep:!1,defaultDuty:1},{id:"p4",hasSweep:!1,defaultDuty:1}],wave:[{id:"w1",preset:"bass"},{id:"w2",preset:"pad"}],noise:[{id:"n1",mode:"7bit"},{id:"n2",mode:"15bit"}]};class gt{constructor(t,n){h(this,"audioContext");h(this,"config");h(this,"masterGain");h(this,"limiter");h(this,"colorizer");h(this,"pulseChannels",new Map);h(this,"waveChannels",new Map);h(this,"noiseChannels",new Map);h(this,"channelGains",new Map);h(this,"channelStates",new Map);h(this,"scheduledNoteCount",0);h(this,"activeNodes",new Set);this.audioContext=t||new AudioContext,this.config={...ue,...n},this.colorizer=new tt(this.audioContext,tt.createPreset()),this.masterGain=this.audioContext.createGain(),this.masterGain.gain.value=this.config.masterVolume,this.limiter=this.audioContext.createDynamicsCompressor(),this.limiter.threshold.value=-6,this.limiter.knee.value=3,this.limiter.ratio.value=20,this.limiter.attack.value=.001,this.limiter.release.value=.1,this.masterGain.connect(this.limiter),this.limiter.connect(this.audioContext.destination),this.initializeChannels()}initializeChannels(){for(const t of et.pulse){const n=this.createChannelGain(t.id,.12),e=new Zt(this.audioContext,n,t.hasSweep);e.setDutyCycle(t.defaultDuty),this.pulseChannels.set(t.id,e),this.initChannelState(t.id)}for(const t of et.wave){const n=this.createChannelGain(t.id,.15),e=new ae(this.audioContext,n,t.preset);this.waveChannels.set(t.id,e),this.initChannelState(t.id)}for(const t of et.noise){const n=this.createChannelGain(t.id,0),e=new ce(this.audioContext,n,t.mode);this.noiseChannels.set(t.id,e),this.initChannelState(t.id)}}createChannelGain(t,n){const e=this.audioContext.createGain();return e.gain.value=n,e.connect(this.masterGain),this.channelGains.set(t,e),e}initChannelState(t){var n;this.channelStates.set(t,{id:t,isBusy:!1,busyUntil:0,currentGain:((n=this.channelGains.get(t))==null?void 0:n.gain.value)||0})}getAudioContext(){return this.audioContext}async resume(){const t=this.audioContext;if(t.state!=="running"){try{const n=t.createBuffer(1,1,t.sampleRate),e=t.createBufferSource();e.buffer=n,e.connect(t.destination),e.start(0),e.stop(.001)}catch{}if(t.state==="suspended")try{await t.resume()}catch{}t.state!=="running"&&await new Promise(n=>{let e=0;const s=()=>
1{if(t.state==="running"||e>=500){n();return}e+=50,t.resume().catch(()=>{}),setTimeout(s,50)};s()})}}scheduleNote(t){const{channel:n,midiNote:e,startTime:s,duration:i,velocity:a}=t;n.startsWith("p")?this.schedulePulseNote(n,e,i,a,s):n.startsWith("w")?this.scheduleWaveNote(n,e,i,a,s):n.startsWith("n")&&this.scheduleNoiseNote(n,e,i,a,s),this.updateChannelBusy(n,s+i),this.scheduledNoteCount++}schedulePulseNote(t,n,e,s,i){const a=this.pulseChannels.get(t);if(!a)return;const r=a.playNote(n,e,s,i);this.trackNode(r.oscillator,r.stopTime)}scheduleWaveNote(t,n,e,s,i){const a=this.waveChannels.get(t);if(!a)return;const r=a.playNote(n,e,s,i);this.trackNode(r.oscillator,r.stopTime)}scheduleNoiseNote(t,n,e,s,i){const a=this.noiseChannels.get(t);if(!a)return;const r=a.playNote(n,e,s,i);this.trackNode(r.source,r.stopTime)}trackNode(t,n){this.activeNodes.add(t);const e=()=>{this.activeNodes.delete(t)};t.onended=e}updateChannelBusy(t,n){const e=this.channelStates.get(t);e&&(e.isBusy=!0,e.busyUntil=Math.max(e.busyUntil,n))}isChannelFree(t,n){const e=n??this.audioContext.currentTime,s=this.channelStates.get(t);return s?e>=s.busyUntil:!1}findFreePulseChannel(t){const n=t??this.audioContext.currentTime;for(const e of["p1","p2","p3","p4"])if(this.isChannelFree(e,n))return e;return null}findFreeWaveChannel(t){const n=t??this.audioContext.currentTime;for(const e of["w1","w2"])if(this.isChannelFree(e,n))return e;return null}findFreeNoiseChannel(t){const n=t??this.audioContext.currentTime;for(const e of["n1","n2"])if(this.isChannelFree(e,n))return e;return null}setPulseDuty(t,n){const e=this.pulseChannels.get(t);e&&e.setDutyCycle(n)}setWavePreset(t,n){const e=this.waveChannels.get(t);e&&e.loadPreset(n)}setNoiseMode(t,n){const e=this.noiseChannels.get(t);e&&e.setMode(n)}setChannelVolume(t,n){const e=this.channelGains.get(t);e&&(e.gain.value=Math.max(0,Math.min(1,n)))}setMasterVolume(t){this.masterGain.gain.value=Math.max(0,Math.min(1,t)),this.config.masterVolume=t}getMasterVolume(){return this.config.masterVolume}getPulseChannel(t){return this.pulseChannels.get(t)}getWaveChannel(t){return this.waveChannels.get(t)}getNoiseChannel(t){return this.noiseChannels.get(t)}getChannelStates(){return new Map(this.channelStates)}getCurrentTime(){return this.audioContext.currentTime}reset(){for(const t of this.channelStates.keys())this.initChannelState(t);this.scheduledNoteCount=0}stopAll(){const t=this.audioContext.currentTime;for(const n of this.activeNodes)try{n.stop(t)}catch{}this.activeNodes.clear(),this.reset()}getScheduledNoteCount(){return this.scheduledNoteCount}getColorizer(){return this.colorizer}setColorizerPreset(t){this.colorizer.setConfig(tt.createPreset(t))}setColorizerEnabled(t){this.colorizer.setEnabled(t)}initializeBitCrusher(){this.colorizer.initializeBitCrusher()}}class he{analyzeTrack(t,n){const e=t.notes;if(e.length===0)return this.createEmptyAnalysis(n,t.channel);const s=this.calculateNoteRange(e),i=this.calculateNoteDensity(e),a=this.calculateAverageVelocity(e),r=this.calculateAverageDuration(e),c=this.calculateComplexity(e),l=this.detectChords(e),d=t.channel===9||this.detectDrums(e),u=this.detectPercussive(e),m=this.detectRole(e,s,d,i,l,r),f=this.calculatePriority(m,i,a,e.length);return{trackIndex:n,channel:t.channel,isDrums:d,isPercussive:u,noteRange:s,noteDensity:i,complexity:c,hasChords:l,avgVelocity:a,avgDuration:r,noteCount:e.length,role:m,priority:f}}analyzeTracks(t){return t.map((e,s)=>this.analyzeTrack(e,s)).sort((e,s)=>s.priority-e.priority)}createEmptyAnalysis(t,n){return{trackIndex:t,channel:n,isDrums:!1,isPercussive:!1,noteRange:{min:0,max:0,avg:0},noteDensity:0,complexity:0,hasChords:!1,avgVelocity:0,avgDuration:0,noteCount:0,role:"fx",priority:0}}calculateNoteRange(t){if(t.length===0)return{min:0,max:0,avg:0};let n=127,e=0,s=0;for(const i of t)n=Math.min(n,i.midi),e=Math.max(e,i.midi),s+=i.midi;return{min:n,max:e,avg:s/t.length}}calculateNoteDensity(t){if(t.length<2)return 0;const n=t[0].time,s=t[t.length-1].time+t[t.length-1].duration-n;return s<=0?0:t.length/s}calculateAverageVelocity(t){return t.length===0?0:t.reduce((e,s)=>e+s.velocity,0)/t.length}calculateAverageDuration(t){return t.length===0?0:t.reduce((e,s)=>e+s.duration,0)/t.length}calculateComplexity(t){if(t.length<2)return 0;const n=this.calculateNoteRange(t),e=Math.min(1,(n.max-n.min)/36),s=[];for(let c=1;c<t.length;c++)s.push(t[c].time-t[c-1].time);if(s.length===0)return e*.5;const i=s.reduce((c,l)=>c+l,0)/s.length,a=s.reduce((c,l)=>c+Math.pow(l-i,2),0)/s.length,r=Math.min(1,Math.sqrt(a)/i);return e*.6+r*.4}detectChords(t){const e=new Map;for(const i of t){const a=Math.floor(i.time/.01);e.set(a,(e.get(a)||0)+1)}let s=0;for(const i of e.values())i>=2&&s++;return s>e.size*.1}detectDrums(t){if(t.length<4)return!1;const n=this.calculateAverageDuration(t),e=this.calculateNoteRange(t),s=n<.1,i=e.min>=35&&e.max<=81&&e.max-e.min<30,a=new Map;for(const l of t)a.set(l.midi,(a.get(l.midi)||0)+1);const c=a.size<10&&t.length>20;return s&&(i||c)}detectPercussive(t){return this.calculateAverageDuration(t)<.15}detectRole(t,n,e,s,i,a){return e?"drums":n.avg<52||n.max<55?"bass":n.avg>58&&s>2?"lead":s<1.5&&a>.5?"pad":i?"harmony":s>8?"fx":"lead"}calculatePriority(t,n,e,s){let i=50;switch(t){case"drums":i+=30;break;case"bass":i+=25;break;case"lead":i+=20;break;case"harmony":i+=15;break;case"pad":i+=10;break;case"fx":i+=5;break}return i+=Math.min(20,n*2),i+=e/127*10,i+=Math.min(10,Math.log10(s+1)*3),i}}const de={maxTracks:8,arpeggiateHarmony:!0,leadDuty:2,harmonyDuty:1}
1,E={pulse:["p1","p2","p3","p4"],noise:["n1","n2"]};class me{constructor(t={}){h(this,"analyzer");h(this,"config");this.analyzer=new he,this.config={...de,...t}}setConfig(t){this.config={...this.config,...t}}mapTracks(t){const e=this.analyzer.analyzeTracks(t).filter(a=>a.noteCount>0),s=new Set,i=[];for(const a of e){if(i.length>=this.config.maxTracks)break;const r=this.assignChannel(a,s);r&&(i.push(r),s.add(r.channelId))}return i}assignChannel(t,n){const{role:e,hasChords:s}=t;switch(e){case"drums":return this.assignDrums(t,n);case"bass":return this.assignBass(t,n);case"lead":return this.assignLead(t,n);case"harmony":return this.assignHarmony(t,n,s);case"pad":return this.assignPad(t,n);case"fx":return this.assignFX(t,n);default:return this.assignToAnyPulse(t,n)}}assignDrums(t,n){const e=this.findFreeChannel(E.noise,n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,noiseMode:"7bit"}:null}assignBass(t,n){if(!n.has("w1"))return{trackIndex:t.trackIndex,channelId:"w1",shouldArpeggiate:!1,wavePreset:"bass"};if(!n.has("w2"))return{trackIndex:t.trackIndex,channelId:"w2",shouldArpeggiate:!1,wavePreset:"bass"};const e=this.findFreeChannel(E.pulse,n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,dutyCycle:2}:null}assignLead(t,n){for(const s of["p1","p2"])if(!n.has(s))return{trackIndex:t.trackIndex,channelId:s,shouldArpeggiate:!1,dutyCycle:this.config.leadDuty};const e=this.findFreeChannel(["p3","p4"],n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,dutyCycle:this.config.leadDuty}:null}assignHarmony(t,n,e){const s=this.findFreeChannel(["p3","p4","p1","p2"],n);return s?{trackIndex:t.trackIndex,channelId:s,shouldArpeggiate:this.config.arpeggiateHarmony&&e,dutyCycle:this.config.harmonyDuty}:null}assignPad(t,n){if(!n.has("w2"))return{trackIndex:t.trackIndex,channelId:"w2",shouldArpeggiate:!1,wavePreset:"pad"};if(!n.has("w1"))return{trackIndex:t.trackIndex,channelId:"w1",shouldArpeggiate:!1,wavePreset:"pad"};const e=this.findFreeChannel(E.pulse,n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,dutyCycle:2}:null}assignFX(t,n){const e=this.findFreeChannel(E.pulse,n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,dutyCycle:0}:null}assignToAnyPulse(t,n){const e=this.findFreeChannel(E.pulse,n);return e?{trackIndex:t.trackIndex,channelId:e,shouldArpeggiate:!1,dutyCycle:2}:null}findFreeChannel(t,n){for(const e of t)if(!n.has(e))return e;return null}getAnalyzer(){return this.analyzer}analyzeTracks(t){return this.analyzer.analyzeTracks(t)}}const fe={speed:1/32,bpm:120,pattern:"up",minNotes:2};class ge{constructor(t={}){h(this,"config");this.config={...fe,...t}}setConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}getStepDuration(){return 60/this.config.bpm*this.config.speed}arpeggiate(t){if(t.length===0)return[];const n=this.groupIntoChords(t),e=[];for(const s of n)s.notes.length<this.config.minNotes?e.push(...s.notes):e.push(...this.arpeggiateChord(s));return e.sort((s,i)=>s.time-i.time)}groupIntoChords(t){const e=[...t].sort((a,r)=>a.time-r.time),s=[];let i=null;for(const a of e)!i||a.time-i.startTime>.02?(i={startTime:a.time,notes:[a]},s.push(i)):i.notes.push(a);return s}arpeggiateChord(t){const n=this.getStepDuration(),e=this.sortNotesForPattern(t.notes),s=Math.max(...t.notes.map(d=>d.duration)),i=e.length*n,a=Math.max(1,Math.floor(s/i)),r=[];let c=0,l=1;for(let d=0;d<a;d++)for(let u=0;u<e.length;u++){const m=e[c],f=t.startTime+(d*e.length+u)*n;f<t.startTime+s&&r.push({midiNote:m.midiNote,time:f,duration:n*.9,velocity:m.velocity}),this.config.pattern==="updown"?(c+=l,c>=e.length-1?(l=-1,c=e.length-1):c<=0&&(l=1,c=0)):this.config.pattern==="random"?c=Math.floor(Math.random()*e.length):c=(c+1)%e.length}return r}sortNotesForPattern(t){const n=[...t];switch(this.config.pattern){case"up":case"updown":n.sort((e,s)=>e.midiNote-s.midiNote);break;case"down":n.sort((e,s)=>s.midiNote-e.midiNote);break;case"random":for(let e=n.length-1;e>0;e--){const s=Math.floor(Math.random()*(e+1));[n[e],n[s]]=[n[s],n[e]]}break}return n}wouldArpeggiate(t){return this.groupIntoChords(t).some(e=>e.notes.length>=this.config.minNotes)}setBPM(t){this.config.bpm=Math.max(20,Math.min(300,t))}setSpeed(t){this.config.speed=t}setPattern(t){this.config.pattern=t}}const pe={enhanceBass:!0,enhanceDrums:!1,doubleMelody:!0,fillGaps:!0,minGapToFill:.5,targetUtilization:.7,hihatRate:1,bpm:120};class ye{constructor(t={}){h(this,"config");this.config={...pe,...t}}setConfig(t){this.config={...this.config,...t}}setBPM(t){this.config.bpm=t}arrange(t,n,e){const s=t.length;let i=[...t];
1const a=this.groupByChannel(i);if(this.config.enhanceBass){const c=["w1","w2"];for(const l of c)if(a.has(l)){const d=a.get(l),u=this.enhanceBass(d,e);a.set(l,u)}}if(this.config.enhanceDrums){const c=["n1","n2"];for(const l of c){const d=a.get(l)||[],u=this.enhanceDrums(d,e,l);a.set(l,u)}}if(this.config.doubleMelody){const c=["p1","p2","p3","p4"],l=c.filter(u=>a.has(u)&&a.get(u).length>0),d=c.filter(u=>!l.includes(u));if(d.length>0&&l.length>0){const u=this.findLeadChannel(a,l);if(u&&a.get(u)){const m=this.doubleMelody(a.get(u),d[0]);a.set(d[0],m)}}}if(this.config.fillGaps)for(const[c,l]of a){const d=this.fillGaps(l,e,c);a.set(c,d)}i=[];for(const c of a.values())i.push(...c);i.sort((c,l)=>c.startTime-l.startTime);const r=this.calculateUtilization(a,e);return{notes:i,stats:{originalNotes:s,addedNotes:i.length-s,channelUtilization:r}}}groupByChannel(t){const n=new Map;for(const e of t)n.has(e.channel)||n.set(e.channel,[]),n.get(e.channel).push(e);for(const e of n.values())e.sort((s,i)=>s.startTime-i.startTime);return n}enhanceBass(t,n){if(t.length===0)return t;const e=[],s=60/this.config.bpm;for(const i of t){if(e.push(i),i.duration>s*1.5){const a=i.startTime+i.duration/2;e.push({...i,startTime:a,duration:Math.min(s*.5,i.duration/4),velocity:i.velocity*.7})}i.duration>s*2&&Math.random()>.6&&e.push({...i,midiNote:i.midiNote+12,startTime:i.startTime+s,duration:s*.4,velocity:i.velocity*.6})}return e.sort((i,a)=>i.startTime-a.startTime)}enhanceDrums(t,n,e){const s=[...t],i=60/this.config.bpm,a=i/this.config.hihatRate;if(e==="n2")for(let r=0;r<n;r+=a)t.some(l=>Math.abs(l.startTime-r)<a*.3)||s.push({channel:e,midiNote:66,startTime:r,duration:a*.4,velocity:40+Math.random()*15});else if(e==="n1"){const r=this.getKickTimes(t),c=this.getSnareTimes(t);for(let l=0;l<n/i;l++){const d=l*i;(l%4===0||l%4===2)&&(r.some(u=>Math.abs(u-d)<i*.2)||s.push({channel:e,midiNote:36,startTime:d,duration:.15,velocity:100})),(l%4===1||l%4===3)&&(c.some(u=>Math.abs(u-d)<i*.2)||s.push({channel:e,midiNote:48,startTime:d,duration:.1,velocity:90}))}}return s.sort((r,c)=>r.startTime-c.startTime)}getKickTimes(t){return t.filter(n=>n.midiNote<45&&n.velocity>80).map(n=>n.startTime)}getSnareTimes(t){return t.filter(n=>n.midiNote>=45&&n.midiNote<55&&n.velocity>70).map(n=>n.startTime)}doubleMelody(t,n){return t.map(e=>({...e,channel:n,midiNote:e.midiNote+12,velocity:Math.round(e.velocity*.5)}))}findLeadChannel(t,n){let e=null,s=0;for(const i of n){const a=t.get(i);if(!a||a.length===0)continue;const r=a.reduce((d,u)=>d+u.midiNote,0)/a.length,c=a.length,l=r/127*.5+Math.min(1,c/100)*.5;l>s&&(s=l,e=i)}return e}fillGaps(t,n,e){if(t.length===0)return t;const s=[...t],i=this.config.minGapToFill;for(let c=0;c<t.length-1;c++){const l=t[c],d=t[c+1],u=l.startTime+l.duration,m=d.startTime-u;m>i&&s.push({channel:e,midiNote:l.midiNote,startTime:u+.1,duration:Math.min(m-.2,.3),velocity:Math.round(l.velocity*.4)})}const a=t[t.length-1];return n-(a.startTime+a.duration)>i*2&&s.push({channel:e,midiNote:a.midiNote,startTime:a.startTime+a.duration+.1,duration:.3,velocity:Math.round(a.velocity*.3)}),s.sort((c,l)=>c.startTime-l.startTime)}calculateUtilization(t,n){const e={};for(const[s,i]of t){const a=i.reduce((r,c)=>r+c.duration,0);e[s]=Math.min(1,a/n)}return e}}const ve={autoResume:!0,defaultBPM:120,masterVolume:.7,enableArranger:!1,arrangerConfig:{}};class Te{constructor(t={}){h(this,"apu");h(this,"mapper");h(this,"arpeggiator");h(this,"arranger");h(this,"config");h(this,"isPlaying",!1);h(this,"currentPlaybackInfo",null);h(this,"playbackStartTime",0);h(this,"pendingNotes",[]);h(this,"scheduleIndex",0);h(this,"loadedNotes",[]);h(this,"loadedDuration",0);h(this,"loadedAssignments",[]);h(this,"schedulerInterval",null);h(this,"SCHEDULE_AHEAD_TIME",2);h(this,"SCHEDULER_INTERVAL_MS",250);this.config={...ve,...t},this.apu=new gt(void 0,this.config),this.mapper=new me,this.arpeggiator=new ge({bpm:this.config.defaultBPM}),this.arranger=new ye(this.config.arrangerConfig)}getAPU(){return this.apu}async playMIDI(t,n=0){this.config.autoResume&&await this.apu.resume(),this.isPlaying&&this.stop();const e=this.prepare(t);return this.startFromOffset(n),e}prepareMIDI(t){return this.prepare(t)}prepare(t){var c;const n=new J.Midi(t),e=((c=n.header.tempos[0])==null?void 0:c.bpm)||this.config.defaultBPM;this.arpeggiator.setBPM(e),this.arranger.setBPM(e);
1const s=this.convertMIDITracks(n),i=this.mapper.mapTracks(s);let a=this.convertToGBNotes(s,i);this.config.enableArranger&&(a=this.arranger.arrange(a,i,n.duration).notes),this.loadedNotes=a,this.loadedDuration=n.duration,this.loadedAssignments=i;const r={duration:n.duration,assignments:i,noteCount:a.length};return this.currentPlaybackInfo=r,r}playFrom(t){this.loadedNotes.length!==0&&this.startFromOffset(Math.max(0,t))}async renderToBuffer(t=22050,n=30){if(this.loadedNotes.length===0)return null;const e=Math.min(this.loadedDuration,n),s=e+.5;let i=this.loadedNotes.filter(l=>l.startTime<e);const a=1500;if(i.length>a){const l=i.length/a;i=Array.from({length:a},(d,u)=>i[Math.round(u*l)])}const r=new OfflineAudioContext(2,Math.ceil(s*t),t),c=new gt(r,this.config);for(const l of this.loadedAssignments)l.channelId.startsWith("p")&&l.dutyCycle!==void 0?c.setPulseDuty(l.channelId,l.dutyCycle):l.channelId.startsWith("w")&&l.wavePreset?c.setWavePreset(l.channelId,l.wavePreset):l.channelId.startsWith("n")&&l.noiseMode&&c.setNoiseMode(l.channelId,l.noiseMode);for(const l of i)c.scheduleNote(l);return r.startRendering()}startFromOffset(t){this.stopScheduler(),this.apu.stopAll(),this.pendingNotes=this.loadedNotes;let n=0;for(;n<this.pendingNotes.length&&this.pendingNotes[n].startTime<t;)n++;this.scheduleIndex=n;const e=this.apu.getCurrentTime()+.1-t;this.playbackStartTime=e,this.isPlaying=!0,this.scheduleNextBatch(),this.startScheduler();const s=(this.loadedDuration-t+1)*1e3;setTimeout(()=>{this.isPlaying&&this.playbackStartTime===e&&(this.isPlaying=!1)},Math.max(0,s))}convertMIDITracks(t){return t.tracks.map((n,e)=>({channel:n.channel,name:n.name,notes:n.notes.map(s=>({midi:s.midi,time:s.time,duration:s.duration,velocity:Math.round(s.velocity*127)}))}))}convertToGBNotes(t,n){const e=[];for(const s of n){const i=t[s.trackIndex];if(!i||i.notes.length===0)continue;this.applyChannelSettings(s);let a=i.notes.map(r=>({midiNote:r.midi,time:r.time,duration:r.duration,velocity:r.velocity}));s.shouldArpeggiate&&(a=this.arpeggiator.arpeggiate(a));
1for(const r of a)e.push({channel:s.channelId,midiNote:r.midiNote,startTime:r.time,duration:r.duration,velocity:r.velocity})}return e.sort((s,i)=>s.startTime-i.startTime)}applyChannelSettings(t){const{channelId:n,dutyCycle:e,wavePreset:s,noiseMode:i}=t;n.startsWith("p")&&e!==void 0&&this.apu.setPulseDuty(n,e),n.startsWith("w")&&s&&this.apu.setWavePreset(n,s),n.startsWith("n")&&i&&this.apu.setNoiseMode(n,i)}scheduleNextBatch(){if(!this.isPlaying&&this.scheduleIndex>0)return;const e=this.apu.getCurrentTime()-this.playbackStartTime+this.SCHEDULE_AHEAD_TIME;let s=0;for(;this.scheduleIndex<this.pendingNotes.length;){const i=this.pendingNotes[this.scheduleIndex];if(i.startTime>e)break;this.apu.scheduleNote({...i,startTime:this.playbackStartTime+i.startTime}),this.scheduleIndex++,s++}s>0&&console.log(`Scheduled ${s} notes (${this.scheduleIndex}/${this.pendingNotes.length})`)}startScheduler(){this.stopScheduler(),this.schedulerInterval=setInterval(()=>{if(!this.isPlaying){this.stopScheduler();return}this.scheduleNextBatch(),this.scheduleIndex>=this.pendingNotes.length&&this.stopScheduler()},this.SCHEDULER_INTERVAL_MS)}stopScheduler(){this.schedulerInterval&&(clearInterval(this.schedulerInterval),this.schedulerInterval=null)}stop(){this.isPlaying=!1,this.stopScheduler(),this.pendingNotes=[],this.scheduleIndex=0,this.apu.stopAll(),console.log("Playback stopped")}getIsPlaying(){return this.isPlaying}getPlaybackInfo(){return this.currentPlaybackInfo}getElapsedTime(){return this.isPlaying?this.apu.getCurrentTime()-this.playbackStartTime:0}setVolume(t){this.apu.setMasterVolume(t)}getVolume(){return this.apu.getMasterVolume()}async resume(){await this.apu.resume()}setArrangerEnabled(t){this.config.enableArranger=t,console.log(`Arranger ${t?"enabled":"disabled"}`)}isArrangerEnabled(){return this.config.enableArranger??!0}getArranger(){return this.arranger}analyzeMIDI(t){var i;const n=new J.Midi(t),e=this.convertMIDITracks(n),s=this.mapper.mapTracks(e);return{duration:n.duration,trackCount:n.tracks.length,noteCount:n.tracks.reduce((a,r)=>a+r.notes.length,0),bpm:((i=n.header.tempos[0])==null?void 0:i.bpm)||this.config.defaultBPM,assignments:s}}getTrackAnalysis(t){const n=new J.Midi(t),e=this.convertMIDITracks(n);return this.mapper.analyzeTracks(e)}}const y=new Te,ot=new Ut;let A=null,D=[],k=null;const O=document.getElementById("songInput"),it=document.getElementById("searchBtn"),H=document.getElementById("resultsBody"),xt=document.getElementById("resultsSection"),X=document.getElementById("playerSection"),Ce=document.getElementById("status"),Mt=document.getElementById("selectedTitle"),Nt=document.getElementById("selectedMeta"),F=document.getElementById("btn-play"),R=document.getElementById("btn-stop"),j=document.getElementById("v1Tab"),nt=document.getElementById("faqBtnTop"),N=document.getElementById("faqModalBackdrop"),$=document.getElementById("faqCloseBtn"),we=()=>{N.classList.add("open"),$.focus()},rt=()=>{N.classList.remove("open")};nt==null||nt.addEventListener("click",we);$==null||$.addEventListener("click",rt);N==null||N.addEventListener("click",o=>{o.target===N&&rt()});document.addEventListener("keydown",o=>{o.key==="Escape"&&rt()});const K=document.getElementById("progress-row"),kt=document.getElementById("play-progress-fill"),V=document.getElementById("play-seek"),At=document.getElementById("play-current"),St=document.getElementById("play-total");let T=0,I=0,b=!1,L=!1;const be=document.getElementById("iosAudioBanner"),Ie=document.getElementById("enableAudioBtn"),pt=document.getElementById("iosAudioState"),ct=document.getElementById("shareRow"),M=document.getElementById("saveAudioBtn"),_=d
1ocument.getElementById("copyLinkBtn"),xe=document.getElementById("shareToXBtn"),at=document.getElementById("shareFallback"),st=document.getElementById("shareFallbackInput");let S=null,P="";function p(o){Ce.textContent=o}function Q(o){const t=Math.floor(o/60),n=Math.floor(o%60);return`${t}:${n.toString().padStart(2,"0")}`}function Pt(o){return(o||"").split(/\s+/).filter(Boolean).map(t=>/^[A-Z0-9]+$/.test(t)?t:t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join(" ")}function G(o){const t=(o||"").replace(/\.mid$/i,"").replace(/[_.]+/g," ").replace(/\b(midi?)\b/gi,"").replace(/\s+/g," ").trim();return Pt(t||"Unknown")}function Bt(o){const t=String(o||"").toLowerCase();return t==="bitmidi"?"BitMidi":Pt(t)}function Me(){const o=navigator.userAgent||"";return/iPad|iPhone|iPod/.test(o)||/Macintosh/.test(o)&&navigator.maxTouchPoints>1}function Et(){try{return y.getAPU().getAudioContext().state==="running"}catch{return!1}}function B(){be.style.display=Me()&&!Et()?"block":"none"}function W(){F.textContent=b?"Pause":"Play"}function x(o){const t=T>0?Math.max(0,Math.min(100,o/T*100)):0;kt.style.width=`${t}%`,V.value=String(t),At.textContent=Q(o),St.textContent=Q(T)}function Dt(){k&&clearInterval(k),k=setInterval(()=>{const o=y.getElapsedTime();if(T>0&&o>=T){yt();return}if(!y.getIsPlaying()&&b){yt();return}x(o)},150)}function Y(){k&&(clearInterval(k),k=null)}function yt(){Y(),b=!1,I=0,y.stop(),W(),R.disabled=!0,x(T),p("")}async function Ne(){if(await y.resume(),B(),I>0&&L)y.playFrom(I);else{const o=await y.playMIDI(A);L=!0,T=o.duration}b=!0,W(),R.disabled=!1,K.style.display="block",Dt(),p("Playing…")}function ke(){const o=Math.max(0,Math.min(T,y.getElapsedTime()));I=o,y.stop(),b=!1,Y(),W(),x(o),p("Paused.")}function Ft(){Y(),y.stop(),b=!1,L=!1,I=0,T=0,R.disabled=!0,W(),K.style.display="none",kt.style.width="0%",V.value="0",At.textContent="0:00",St.textContent="0:00",ct.style.display="none",at.style.display="none",S=null,P=""}async function lt(){const o=O.value.trim();if(!o){p("Enter a song name to search.");return}p("Searching…"),it.disabled=!0,H.innerHTML="";try{const t=await ot.search(o);if(D=t,!t.length){p("No MIDI files found. Try a different search.");return}Ae(),xt.classList.add("visible"),p("Pick a source. Try another if it sounds rough, some MIDIs map better than others."),B()}catch(t){p(`Search error: ${t&&t.message?t.message:"unknown"}`)}finally{it.disabled=!1}}function Ae(){H.innerHTML="",D.forEach((o,t)=>{const n=document.createElement("tr");
1n.innerHTML=`
2          <td>${G(o.title)}</td>
3          <td class="source-col">${Bt(o.source)}</td>
4          <td class="action-col">
5            <div style="display:flex; gap:10px; justify-content:flex-end; align-items:center;">
6              <button type="button" class="row-use-btn">Use</button>
7            </div>
8          </td>`,n.querySelector("button.row-use-btn").addEventListener("click",e=>{e.stopPropagation(),Rt(t)}),H.appendChild(n)})}async function Rt(o){if(o<0||o>=D.length)return;const t=D[o];H.querySelectorAll("tr").forEach((e,s)=>e.classList.toggle("selected",s===o)),Ft(),p("Loading…"),F.disabled=!0;try{const e=await ot.fetchMIDI(t.midiUrl);if(!e)throw new Error("Failed to fetch MIDI");A=e;const s=y.analyzeMIDI(e);T=s.duration;const i=String(t.midiUrl||"").match(/\/uploads\/(\d+)\.mid/i);S=i&&i[1]?i[1]:null,P=t.title||"",Mt.textContent=G(t.title),Nt.textContent=`Source: ${Bt(t.source)} · ${s.noteCount} notes · ${Q(s.duration)}`,j&&(j.href=`/?song=${encodeURIComponent(t.title||"")}`),X.classList.add("visible"),xt.classList.add("collapsed"),K.style.display="block",x(0),S&&(ct.style.display="flex"),F.disabled=!1,p(""),B();try{X.scrollIntoView({behavior:"smooth",block:"start"})}catch{}}catch(e){p(`Load error: ${e&&e.message?e.message:"unknown"}`)}}F.addEventListener("click",async()=>{if(A)try{b?ke():await Ne()}catch(o){p(`Playback error: ${o&&o.message?o.message:"unknown"}`)}});R.addEventListener("click",()=>{Y(),y.stop(),b=!1,I=0,R.disabled=!0,W(),x(0),p("")});function Lt(){if(T<=0)return;const o=parseFloat(V.value)/100*T;I=o,x(o),b&&(y.playFrom(o),Dt())}V.addEventListener("input",Lt);V.addEventListener("change",Lt);function Vt(){const o=`${window.location.origin}/v2.html`;return S?`${o}?id=${encodeURIComponent(S)}&title=${encodeURIComponent(P||"")}`:o}async function Se(){var n;const o=Vt();let t=!1;try{(n=navigator.clipboard)!=null&&n.writeText&&(await navigator.clipboard.writeText(o),t=!0)}catch{}if(!t)try{const e=document.createElement("textarea");e.value=o,e.style.position="fixed",e.style.left="-9999px",e.setAttribute("readonly",""),document.body.appendChild(e),e.focus(),e.select();try{e.setSelectionRange(0,o.length)}catch{}t=document.execCommand("copy"),document.body.removeChild(e)}catch{}if(t){const e=_.textContent;_.textContent="Copied!",at.style.display="none",setTimeout(()=>{_.textContent=e},1500)}else st.value=o,at.style.display="block",st.focus(),st.select()}function Pe(){const o=Vt(),n=`I made a Game Boy version of ${G(P||"a song")}
9
10Using @b1rdmania's Wario Synth (v2 engine)
11
12Check it out`;window.open(`https://twitter.com/intent/tweet?text=${encodeURIComponent(n)}&url=${encodeURIComponent(o)}`,"_blank")}_.addEventListener("click",()=>void Se());xe.addEventListener("click",Pe);function Be(o){return G(o).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"wario-synth"}function Ee(o,t,n){const e=o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength),s=new Blob([e],{type:n}),i=URL.createObjectURL(s),a=document.createElement("a");a.href=i,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),setTimeout(()=>URL.revokeObjectURL(i),1e3)}M.addEventListener("click",async()=>{if(!A)return;const o=M.textContent;M.disabled=!0,M.textContent="Rendering…",p("Rendering audio…");try{L||(y.prepareMIDI(A),L=!0);const t=await y.renderToBuffer();if(!t)throw new Error("Nothing to render");const n=qt(t);Ee(n,`${Be(P)}-gameboy.wav`,"audio/wav"),p("Saved a 30s clip (.wav).")}catch(t){p(`Export error: ${t&&t.message?t.message:"unknown"}`)}finally{M.disabled=!1,M.textContent=o}});Ie.addEventListener("click",async()=>{pt.textContent="Audio: enabling…";try{await y.resume()}catch{}pt.textContent=Et()?"Audio: running":"Still locked. Tap again.",B()});it.addEventListener("click",lt);O.addEventListener("keypress",o=>{o.key==="Enter"&&lt()});async function De(o,t){Ft(),p(`Loading ${t||o}…`);try{const n=await ot.fetchMIDI(`https://bitmidi.com/uploads/${o}.mid`);if(!n)throw new Error("Failed to fetch MIDI");A=n;const e=y.analyzeMIDI(n);T=e.duration,S=o,P=t||"",Mt.textContent=G(t||`BitMidi ${o}`),Nt.textContent=`Source: BitMidi · ${e.noteCount} notes · ${Q(e.duration)}`,j&&(j.href=`/?song=${encodeURIComponent(t||"")}`),X.classList.add("visible"),K.style.display="block",x(0),ct.style.display="flex",F.disabled=!1,p("Loaded. Press Play."),B();try{X.scrollIntoView({behavior:"smooth",block:"start"})}catch{}return!0}catch(n){return p(`Link load error: ${n&&n.message?n.message:"unknown"}
12`),!1}}async function Fe(){const o=new URLSearchParams(window.location.search),t=o.get("id"),n=o.get("q"),e=o.get("title")||"";t&&/^\d+$/.test(t)?(e&&(O.value=e),await De(t,e)):n&&(O.value=n,await lt(),D.length>0&&await Rt(0))}B();Fe();
13//# sourceMappingURL=v2-D_2Yz88L.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.