rlo-engine 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -4
- package/dist/Core/AudioMath.d.ts +29 -0
- package/dist/Core/AudioMath.d.ts.map +1 -0
- package/dist/Core/AudioMath.js +64 -0
- package/dist/Core/AudioMath.js.map +1 -0
- package/dist/Core/InstrumentMap.d.ts +36 -0
- package/dist/Core/InstrumentMap.d.ts.map +1 -0
- package/dist/Core/InstrumentMap.js +62 -0
- package/dist/Core/InstrumentMap.js.map +1 -0
- package/dist/Core/RLOCore.d.ts +49 -0
- package/dist/Core/RLOCore.d.ts.map +1 -0
- package/dist/Core/RLOCore.js +188 -0
- package/dist/Core/RLOCore.js.map +1 -0
- package/dist/Core/SequenceBuilder.d.ts +23 -0
- package/dist/Core/SequenceBuilder.d.ts.map +1 -0
- package/dist/Core/SequenceBuilder.js +31 -0
- package/dist/Core/SequenceBuilder.js.map +1 -0
- package/dist/Instruments/Analog/AnalogSynthBase.d.ts +17 -7
- package/dist/Instruments/Analog/AnalogSynthBase.d.ts.map +1 -1
- package/dist/Instruments/Analog/AnalogSynthBase.js +27 -16
- package/dist/Instruments/Analog/AnalogSynthBase.js.map +1 -1
- package/dist/Instruments/Analog/BassSynth.d.ts +12 -5
- package/dist/Instruments/Analog/BassSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/BassSynth.js +17 -10
- package/dist/Instruments/Analog/BassSynth.js.map +1 -1
- package/dist/Instruments/Analog/ChiptuneSynth.d.ts +11 -4
- package/dist/Instruments/Analog/ChiptuneSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/ChiptuneSynth.js +12 -5
- package/dist/Instruments/Analog/ChiptuneSynth.js.map +1 -1
- package/dist/Instruments/Analog/FMSynth.d.ts +11 -4
- package/dist/Instruments/Analog/FMSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/FMSynth.js +14 -7
- package/dist/Instruments/Analog/FMSynth.js.map +1 -1
- package/dist/Instruments/Analog/FormantSynth.d.ts +11 -4
- package/dist/Instruments/Analog/FormantSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/FormantSynth.js +12 -5
- package/dist/Instruments/Analog/FormantSynth.js.map +1 -1
- package/dist/Instruments/Analog/LeadSynth.d.ts +11 -4
- package/dist/Instruments/Analog/LeadSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/LeadSynth.js +14 -7
- package/dist/Instruments/Analog/LeadSynth.js.map +1 -1
- package/dist/Instruments/Analog/OrganSynth.d.ts +11 -4
- package/dist/Instruments/Analog/OrganSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/OrganSynth.js +17 -10
- package/dist/Instruments/Analog/OrganSynth.js.map +1 -1
- package/dist/Instruments/Analog/PadSynth.js +7 -7
- package/dist/Instruments/Analog/PadSynth.js.map +1 -1
- package/dist/Instruments/Analog/ReeseBassSynth.d.ts +11 -4
- package/dist/Instruments/Analog/ReeseBassSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/ReeseBassSynth.js +13 -6
- package/dist/Instruments/Analog/ReeseBassSynth.js.map +1 -1
- package/dist/Instruments/Analog/StringSynth.js +4 -4
- package/dist/Instruments/Analog/StringSynth.js.map +1 -1
- package/dist/Instruments/Analog/WoodwindSynth.d.ts +11 -4
- package/dist/Instruments/Analog/WoodwindSynth.d.ts.map +1 -1
- package/dist/Instruments/Analog/WoodwindSynth.js +19 -12
- package/dist/Instruments/Analog/WoodwindSynth.js.map +1 -1
- package/dist/Instruments/CoreSynthBase.d.ts +31 -24
- package/dist/Instruments/CoreSynthBase.d.ts.map +1 -1
- package/dist/Instruments/CoreSynthBase.js +53 -34
- package/dist/Instruments/CoreSynthBase.js.map +1 -1
- package/dist/Instruments/Decay/AdditiveSynth.d.ts +12 -5
- package/dist/Instruments/Decay/AdditiveSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/AdditiveSynth.js +9 -2
- package/dist/Instruments/Decay/AdditiveSynth.js.map +1 -1
- package/dist/Instruments/Decay/BrassSynth.d.ts +11 -4
- package/dist/Instruments/Decay/BrassSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/BrassSynth.js +22 -15
- package/dist/Instruments/Decay/BrassSynth.js.map +1 -1
- package/dist/Instruments/Decay/ChromaticPercussionSynth.d.ts +12 -5
- package/dist/Instruments/Decay/ChromaticPercussionSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/ChromaticPercussionSynth.js +16 -9
- package/dist/Instruments/Decay/ChromaticPercussionSynth.js.map +1 -1
- package/dist/Instruments/Decay/DecaySynthBase.d.ts +14 -8
- package/dist/Instruments/Decay/DecaySynthBase.d.ts.map +1 -1
- package/dist/Instruments/Decay/DecaySynthBase.js +22 -15
- package/dist/Instruments/Decay/DecaySynthBase.js.map +1 -1
- package/dist/Instruments/Decay/ElectricGuitarSynth.d.ts +12 -5
- package/dist/Instruments/Decay/ElectricGuitarSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/ElectricGuitarSynth.js +19 -12
- package/dist/Instruments/Decay/ElectricGuitarSynth.js.map +1 -1
- package/dist/Instruments/Decay/EthnicSynth.d.ts +12 -5
- package/dist/Instruments/Decay/EthnicSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/EthnicSynth.js +13 -6
- package/dist/Instruments/Decay/EthnicSynth.js.map +1 -1
- package/dist/Instruments/Decay/GuitarSynth.d.ts +12 -5
- package/dist/Instruments/Decay/GuitarSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/GuitarSynth.js +14 -7
- package/dist/Instruments/Decay/GuitarSynth.js.map +1 -1
- package/dist/Instruments/Decay/KarplusSynth.d.ts +7 -0
- package/dist/Instruments/Decay/KarplusSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/KarplusSynth.js +16 -8
- package/dist/Instruments/Decay/KarplusSynth.js.map +1 -1
- package/dist/Instruments/Decay/PianoSynth.d.ts +12 -5
- package/dist/Instruments/Decay/PianoSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/PianoSynth.js +19 -12
- package/dist/Instruments/Decay/PianoSynth.js.map +1 -1
- package/dist/Instruments/Decay/SlapBassSynth.d.ts +12 -5
- package/dist/Instruments/Decay/SlapBassSynth.d.ts.map +1 -1
- package/dist/Instruments/Decay/SlapBassSynth.js +13 -6
- package/dist/Instruments/Decay/SlapBassSynth.js.map +1 -1
- package/dist/Instruments/ISynthInstrument.d.ts +6 -0
- package/dist/Instruments/ISynthInstrument.d.ts.map +1 -1
- package/dist/Instruments/Speciality/DrumSynth.d.ts +7 -0
- package/dist/Instruments/Speciality/DrumSynth.d.ts.map +1 -1
- package/dist/Instruments/Speciality/DrumSynth.js +30 -21
- package/dist/Instruments/Speciality/DrumSynth.js.map +1 -1
- package/dist/Instruments/Speciality/SoundEffectsSynth.d.ts +7 -0
- package/dist/Instruments/Speciality/SoundEffectsSynth.d.ts.map +1 -1
- package/dist/Instruments/Speciality/SoundEffectsSynth.js +20 -12
- package/dist/Instruments/Speciality/SoundEffectsSynth.js.map +1 -1
- package/dist/Instruments/Synthesizer.d.ts +5 -0
- package/dist/Instruments/Synthesizer.d.ts.map +1 -1
- package/dist/Instruments/Synthesizer.js +7 -1
- package/dist/Instruments/Synthesizer.js.map +1 -1
- package/dist/Players/RLOGameEngine.d.ts +35 -0
- package/dist/Players/RLOGameEngine.d.ts.map +1 -0
- package/dist/Players/RLOGameEngine.js +98 -0
- package/dist/Players/RLOGameEngine.js.map +1 -0
- package/dist/Players/RLOMusicPlayer.d.ts +35 -0
- package/dist/Players/RLOMusicPlayer.d.ts.map +1 -0
- package/dist/Players/RLOMusicPlayer.js +167 -0
- package/dist/Players/RLOMusicPlayer.js.map +1 -0
- package/dist/RLO-Transpiler.d.ts +37 -15
- package/dist/RLO-Transpiler.d.ts.map +1 -1
- package/dist/RLO-Transpiler.js +139 -117
- package/dist/RLO-Transpiler.js.map +1 -1
- package/dist/compiler.d.ts +50 -31
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +165 -230
- package/dist/compiler.js.map +1 -1
- package/dist/crush.d.ts +1 -5
- package/dist/crush.d.ts.map +1 -1
- package/dist/crush.js +10 -3
- package/dist/crush.js.map +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/midi-parser.d.ts +14 -0
- package/dist/midi-parser.d.ts.map +1 -1
- package/dist/midi-parser.js +21 -0
- package/dist/midi-parser.js.map +1 -1
- package/dist/rlo-engine.min.js +441 -439
- package/dist/rlo-engine.min.js.map +1 -1
- package/dist/rlo-engine.min.umd.js +1 -1
- package/dist/rlo-engine.min.umd.js.map +1 -1
- package/dist/types.d.ts +21 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/dist/vite.config.d.ts.map +1 -1
- package/dist/vite.config.js +16 -3
- package/dist/vite.config.js.map +1 -1
- package/dist/vite.config.js13k.d.ts.map +1 -1
- package/dist/vite.config.js13k.js +1 -0
- package/dist/vite.config.js13k.js.map +1 -1
- package/package.json +1 -1
- package/dist/Instruments/InstrumentFactory.d.ts +0 -2
- package/dist/Instruments/InstrumentFactory.d.ts.map +0 -1
- package/dist/Instruments/InstrumentFactory.js +0 -4
- package/dist/Instruments/InstrumentFactory.js.map +0 -1
- package/dist/RLO-Player.d.ts +0 -298
- package/dist/RLO-Player.d.ts.map +0 -1
- package/dist/RLO-Player.js +0 -724
- package/dist/RLO-Player.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rlo-engine.min.umd.js","sources":["../Instruments/Synthesizer.ts","../AudioEffects.ts","../RLO-Transpiler.ts","../RLO-Player.ts","../Instruments/CoreSynthBase.ts","../Instruments/Decay/DecaySynthBase.ts","../Instruments/Decay/PianoSynth.ts","../Instruments/Decay/ChromaticPercussionSynth.ts","../Instruments/Analog/AnalogSynthBase.ts","../Instruments/Analog/OrganSynth.ts","../Instruments/Decay/GuitarSynth.ts","../Instruments/Decay/ElectricGuitarSynth.ts","../Instruments/Analog/BassSynth.ts","../Instruments/Analog/StringSynth.ts","../Instruments/Decay/BrassSynth.ts","../Instruments/Analog/WoodwindSynth.ts","../Instruments/Analog/LeadSynth.ts","../Instruments/Analog/PadSynth.ts","../Instruments/Speciality/SoundEffectsSynth.ts","../Instruments/Decay/EthnicSynth.ts","../Instruments/Speciality/DrumSynth.ts","../Instruments/Analog/ChiptuneSynth.ts","../index.ts","../Instruments/Decay/AdditiveSynth.ts","../Instruments/Analog/FMSynth.ts","../Instruments/Analog/FormantSynth.ts","../Instruments/Decay/KarplusSynth.ts","../Instruments/Analog/ReeseBassSynth.ts","../Instruments/Decay/SlapBassSynth.ts"],"sourcesContent":["import { ISynthInstrument } from \"./ISynthInstrument.js\";\r\n\r\n/**\r\n * Handles routing and synthesis of different instrument types.\r\n */\r\nexport class Synthesizer {\r\n private _ctx: AudioContext;\r\n private _masterGain: GainNode;\r\n private _instruments: ISynthInstrument[];\r\n\r\n constructor(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n instruments: ISynthInstrument[],\r\n ) {\r\n this._ctx = ctx;\r\n this._masterGain = masterGain;\r\n this._instruments = instruments;\r\n }\r\n\r\n /**\r\n * Routes the note to the correct instrument synthesis method.\r\n */\r\n public _playNote(\r\n instrumentId: number,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n /** Key Tracking: High frequency waveforms carry significantly more perceived energy.\r\n * Gently rolling off the velocity of high notes prevents them from piercing the mix and distorting.\r\n * We also apply a 0.6 global headroom multiplier to prevent 30+ note crescendos from clipping. */\r\n const keyTrackVel = velocity * 0.6 * Math.min(1, 1600 / freq);\r\n\r\n const instrument = this._instruments[instrumentId] || this._instruments[0];\r\n\r\n if ((globalThis as any).DEBUG_MIDI) {\r\n console.log(\r\n `[MIDI Debug] Instr ID: ${instrumentId} | Class: ${instrument?.constructor.name || \"Unknown\"} | Freq: ${freq.toFixed(2)}Hz | Vel: ${velocity.toFixed(2)} | Dur: ${duration.toFixed(2)}s | Time: ${time.toFixed(2)}s`,\r\n );\r\n }\r\n\r\n if (instrument) {\r\n instrument._playNote(\r\n this._ctx,\r\n this._masterGain,\r\n time,\r\n freq,\r\n duration,\r\n keyTrackVel,\r\n );\r\n }\r\n }\r\n}\r\n","export type ReverbMode = \"concert\" | \"studio\";\r\n\r\n/**\r\n * Utility class for generating programmatic audio effects.\r\n */\r\nexport class AudioEffects {\r\n private static _cachedConcert: AudioBuffer | null = null;\r\n private static _cachedStudio: AudioBuffer | null = null;\r\n\r\n /**\r\n * Generates a mathematical impulse response for a Convolution Reverb node.\r\n * @param {AudioContext} ctx - The active AudioContext.\r\n * @param {ReverbMode} mode - The type of acoustic space to simulate.\r\n * @returns {AudioBuffer} The synthesized reverb impulse buffer.\r\n */\r\n public static _generateReverb(\r\n ctx: AudioContext,\r\n mode: ReverbMode = \"studio\",\r\n ): AudioBuffer {\r\n if (mode === \"concert\" && this._cachedConcert) return this._cachedConcert;\r\n if (mode === \"studio\" && this._cachedStudio) return this._cachedStudio;\r\n\r\n const isStudio = mode === \"studio\";\r\n const length =\r\n ctx.sampleRate *\r\n (isStudio ? 0.2 : 1.5); /** 0.2s for Studio, 1.5s for Concert */\r\n const decay = isStudio ? 8 : 4; /** Exponential decay factor */\r\n\r\n const impulse = ctx.createBuffer(2, length, ctx.sampleRate);\r\n for (let i = 0; i < 2; i++) {\r\n const channel = impulse.getChannelData(i);\r\n let lastOut = 0;\r\n for (let j = 0; j < length; j++) {\r\n /** Simple lowpass filter to absorb harsh high frequencies in the tail */\r\n const noise = Math.random() * 2 - 1;\r\n lastOut = lastOut + 0.3 * (noise - lastOut);\r\n /** True exponential acoustic decay multiplied by a linear fade to ensure 0 at the tail */\r\n channel[j] =\r\n lastOut * Math.exp(-decay * (j / length)) * (1 - j / length);\r\n }\r\n }\r\n\r\n // Cache the newly generated impulse\r\n return isStudio\r\n ? (this._cachedStudio = impulse)\r\n : (this._cachedConcert = impulse);\r\n }\r\n}\r\n","import { RloData } from \"./types.js\";\r\n\r\ndeclare const __ENABLE_TRANSPILER__: boolean;\r\nconst hasTranspiler =\r\n typeof __ENABLE_TRANSPILER__ !== \"undefined\" ? __ENABLE_TRANSPILER__ : true;\r\n\r\n/**\r\n * Universal translator for handling RLO data formats.\r\n * Converts between Human AoS (Array of Structures), Intermediate SoA (Structure of Arrays),\r\n * and highly compressed binary buffers.\r\n */\r\nexport class RLOTranspiler {\r\n /** Converts standard interleaved JSON into Delta-Timed Structure of Arrays */\r\n static _encodeToSoA(humanJson: RloData, fullRangeFreq: boolean = false) {\r\n if (!hasTranspiler) return null as unknown as typeof soa;\r\n const N = humanJson.notes.length / 5;\r\n const f = fullRangeFreq ? new Float32Array(N) : new Uint8Array(N);\r\n const t = new Uint16Array(N);\r\n const d = new Uint16Array(N);\r\n const v = new Uint8Array(N);\r\n const i = new Uint8Array(N);\r\n\r\n let lastRoundedTime = 0;\r\n for (let n = 0, ptr = 0; n < N; n++, ptr += 5) {\r\n const time = humanJson.notes[ptr + 1];\r\n const freq = humanJson.notes[ptr];\r\n if (fullRangeFreq) {\r\n f[n] = freq;\r\n } else {\r\n // Map the frequency in Hz back down to a 1-byte 0-255 index\r\n f[n] =\r\n freq > 0\r\n ? Math.max(\r\n 0,\r\n Math.min(255, Math.round(12 * Math.log2(freq / 440) + 69)),\r\n )\r\n : 0;\r\n }\r\n\r\n const roundedTime = Math.max(0, Math.round(time * 1000));\r\n t[n] = Math.min(65535, roundedTime - lastRoundedTime); // Clamp to Uint16 max to prevent wraparound\r\n d[n] = Math.min(\r\n 65535,\r\n Math.max(0, Math.round(humanJson.notes[ptr + 2] * 1000)),\r\n );\r\n v[n] = Math.max(\r\n 0,\r\n Math.min(255, Math.round(humanJson.notes[ptr + 3] * 255)),\r\n );\r\n i[n] = humanJson.notes[ptr + 4];\r\n lastRoundedTime += t[n]; // Add the clamped delta to accurately track absolute encoded time\r\n }\r\n\r\n const soa = {\r\n durationSecs: humanJson.durationSecs,\r\n f,\r\n t,\r\n d,\r\n v,\r\n i,\r\n };\r\n return soa;\r\n }\r\n\r\n /** Tightly packs the Delta-Timed SoA into a memory-aligned ArrayBuffer */\r\n static _encodeToBinary(\r\n humanJson: RloData,\r\n fullRangeFreq: boolean = false,\r\n ): ArrayBuffer {\r\n if (!hasTranspiler) return new ArrayBuffer(0);\r\n const isLittleEndian = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\r\n const soa = this._encodeToSoA(humanJson, fullRangeFreq);\r\n const N = soa.f.length;\r\n\r\n // Arrays: Time(2*N) + Dur(2*N) + Freq(1*N or 4*N) + Vel(1*N) + Inst(1*N)\r\n const bytesPerNote = fullRangeFreq ? 10 : 7;\r\n const buffer = new ArrayBuffer(12 + bytesPerNote * N);\r\n const view = new DataView(buffer);\r\n\r\n view.setUint8(0, 82);\r\n view.setUint8(1, 76);\r\n view.setUint8(2, 79);\r\n view.setUint8(3, fullRangeFreq ? 70 : 50); // 'RLOF' for Float32, 'RLO2' for Uint8\r\n view.setFloat32(4, soa.durationSecs, true);\r\n view.setUint32(8, N, true);\r\n\r\n if (isLittleEndian) {\r\n new Uint16Array(buffer, 12, N).set(soa.t);\r\n new Uint16Array(buffer, 12 + 2 * N, N).set(soa.d);\r\n if (fullRangeFreq) {\r\n new Float32Array(buffer, 12 + 4 * N, N).set(soa.f as Float32Array);\r\n }\r\n } else {\r\n // Explicitly write multi-byte values as Little-Endian using DataView\r\n // to ensure cross-platform compatibility (avoiding native endianness issues of TypedArrays)\r\n for (let n = 0; n < N; n++) {\r\n view.setUint16(12 + n * 2, soa.t[n], true);\r\n view.setUint16(12 + 2 * N + n * 2, soa.d[n], true);\r\n if (fullRangeFreq) {\r\n view.setFloat32(12 + 4 * N + n * 4, (soa.f as Float32Array)[n], true);\r\n }\r\n }\r\n }\r\n\r\n if (fullRangeFreq) {\r\n new Uint8Array(buffer, 12 + 8 * N, N).set(soa.v);\r\n new Uint8Array(buffer, 12 + 9 * N, N).set(soa.i);\r\n } else {\r\n new Uint8Array(buffer, 12 + 4 * N, N).set(soa.f as Uint8Array);\r\n new Uint8Array(buffer, 12 + 5 * N, N).set(soa.v);\r\n new Uint8Array(buffer, 12 + 6 * N, N).set(soa.i);\r\n }\r\n\r\n return buffer;\r\n }\r\n\r\n /** Reconstructs a high-speed runtime object directly from the binary buffer */\r\n static _decodeBinary(buffer: ArrayBuffer): RloData {\r\n if (!hasTranspiler) return { durationSecs: 0, notes: [] };\r\n const view = new DataView(buffer);\r\n const magic = String.fromCharCode(\r\n view.getUint8(0),\r\n view.getUint8(1),\r\n view.getUint8(2),\r\n view.getUint8(3),\r\n );\r\n if (magic !== \"RLO2\" && magic !== \"RLOF\")\r\n throw new Error(\"Invalid RLO Binary format. Please recompile tracks.\");\r\n const isFullRange = magic === \"RLOF\";\r\n\r\n const durationSecs = view.getFloat32(4, true);\r\n const N = view.getUint32(8, true);\r\n\r\n // Single-byte arrays are endian-agnostic\r\n const f8 = isFullRange ? null : new Uint8Array(buffer, 12 + 4 * N, N);\r\n const v = new Uint8Array(buffer, 12 + (isFullRange ? 8 : 5) * N, N);\r\n const i = new Uint8Array(buffer, 12 + (isFullRange ? 9 : 6) * N, N);\r\n\r\n const notes: number[] = new Array(N * 5);\r\n let currentTime = 0;\r\n\r\n for (let n = 0, ptr = 0; n < N; n++, ptr += 5) {\r\n // Read multi-byte values explicitly as Little-Endian\r\n const tn = view.getUint16(12 + n * 2, true);\r\n const dn = view.getUint16(12 + 2 * N + n * 2, true);\r\n const fn = isFullRange\r\n ? view.getFloat32(12 + 4 * N + n * 4, true)\r\n : f8![n];\r\n\r\n currentTime += tn / 1000;\r\n notes[ptr] = isFullRange\r\n ? fn\r\n : fn > 0\r\n ? 440 * Math.pow(2, (fn - 69) / 12)\r\n : 0;\r\n notes[ptr + 1] = currentTime;\r\n notes[ptr + 2] = dn / 1000;\r\n notes[ptr + 3] = v[n] / 255;\r\n notes[ptr + 4] = i[n];\r\n }\r\n\r\n return { durationSecs, notes };\r\n }\r\n}\r\n","import { RloData } from \"./types.js\";\r\nimport { Synthesizer } from \"./Instruments/Synthesizer.js\";\r\nimport { AudioEffects, ReverbMode } from \"./AudioEffects.js\";\r\nimport { RLOTranspiler } from \"./RLO-Transpiler.js\"; // Corrected import path\r\nimport { ISynthInstrument } from \"./Instruments/ISynthInstrument.js\";\r\n\r\nexport { RLOTranspiler };\r\nexport type { ISynthInstrument };\r\n\r\n/**\r\n * A dummy synthesizer that does absolutely nothing.\r\n * Useful for completely muting specific MIDI IDs in an instrument map.\r\n */\r\nexport const SilentSynth: ISynthInstrument = {\r\n _playNote: () => {},\r\n};\r\n\r\n/** Configuration options for playing sequences/music. */\r\nexport interface PlaySequenceOptions {\r\n loop?: boolean;\r\n fadeInTime?: number;\r\n playbackRate?: number;\r\n volume?: number;\r\n}\r\n\r\n/** Configuration options for playing single Sound Effects. */\r\nexport interface SFXOptions {\r\n velocity?: number;\r\n timeOffset?: number;\r\n}\r\n\r\n/** Configuration for a standard ADSR volume envelope. */\r\nexport interface ADSREnvelope {\r\n attack?: number;\r\n decay?: number;\r\n sustain?: number;\r\n release?: number;\r\n peak?: number;\r\n}\r\n\r\n/**\r\n * Syntactic sugar for applying a standard ADSR envelope to a Web Audio GainNode.\r\n * @param gainParam The AudioParam (e.g., gainNode.gain) to animate.\r\n * @param now The physical start time of the sound.\r\n * @param duration The total held duration of the note.\r\n * @param opts ADSR configuration object.\r\n */\r\nexport function applyEnvelope(\r\n gainParam: AudioParam,\r\n now: number,\r\n duration: number,\r\n opts: ADSREnvelope,\r\n): void {\r\n const a = opts.attack ?? 0.05;\r\n const d = opts.decay ?? 0.1;\r\n const s = opts.sustain ?? 0.8;\r\n const r = opts.release ?? 0.1;\r\n const peak = opts.peak ?? 1.0;\r\n\r\n gainParam.setValueAtTime(0, now);\r\n const realDur = Math.max(0, duration);\r\n\r\n if (realDur <= a) {\r\n const partialPeak = peak * (realDur / (a || 1));\r\n gainParam.linearRampToValueAtTime(partialPeak, now + realDur * 0.5);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n } else if (realDur <= a + d) {\r\n gainParam.linearRampToValueAtTime(peak, now + a);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n } else {\r\n gainParam.linearRampToValueAtTime(peak, now + a);\r\n gainParam.linearRampToValueAtTime(peak * s, now + a + d);\r\n const releaseStart = Math.max(now + a + d, now + realDur - r);\r\n gainParam.setValueAtTime(peak * s, releaseStart);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n }\r\n}\r\n\r\n/** Flag injected by build tools to enable or disable string note parsing. */\r\ndeclare const __ENABLE_NOTE_PARSER__: boolean;\r\nconst hasNoteParser =\r\n typeof __ENABLE_NOTE_PARSER__ !== \"undefined\" ? __ENABLE_NOTE_PARSER__ : true;\r\n\r\n/**\r\n * Converts a musical note string (e.g., 'C4', 'F#5') to its frequency in Hz.\r\n * If a number is provided, it is returned as-is.\r\n */\r\nexport function Note(pitch: string | number): number {\r\n if (typeof pitch === \"number\") return pitch;\r\n if (!hasNoteParser) return 0;\r\n const match = pitch.match(/^([a-gA-G])([#b]?)(\\d)$/);\r\n if (!match) return 0;\r\n const offsets: Record<string, number> = {\r\n C: -9,\r\n D: -7,\r\n E: -5,\r\n F: -4,\r\n G: -2,\r\n A: 0,\r\n B: 2,\r\n };\r\n const [, note, accidental, octave] = match;\r\n let semitone = offsets[note.toUpperCase()];\r\n if (accidental === \"#\") semitone++;\r\n if (accidental === \"b\") semitone--;\r\n semitone += (parseInt(octave, 10) - 4) * 12;\r\n return Number((440 * Math.pow(2, semitone / 12)).toFixed(2));\r\n}\r\n\r\n/** A fluent, chainable builder for creating RloData sequences procedurally. */\r\nexport class RLOSequenceBuilder {\r\n private _notes: number[] = [];\r\n private _duration: number = 0;\r\n\r\n public addNote(opts: {\r\n instrument: number;\r\n pitch: string | number;\r\n duration: number;\r\n time?: number;\r\n velocity?: number;\r\n }): this {\r\n const time = opts.time !== undefined ? opts.time : this._duration;\r\n const freq = Note(opts.pitch);\r\n const vel = opts.velocity ?? 1.0;\r\n this._notes.push(freq, time, opts.duration, vel, opts.instrument);\r\n this._duration = Math.max(this._duration, time + opts.duration);\r\n return this;\r\n }\r\n public setDuration(secs: number): this {\r\n this._duration = secs;\r\n return this;\r\n }\r\n public compile(): RloData {\r\n return { durationSecs: this._duration, notes: this._notes };\r\n }\r\n}\r\n\r\n/** Flag injected by build tools (e.g., Vite) to enable or disable the transpiler (dead-code elimination). */\r\ndeclare const __ENABLE_TRANSPILER__: boolean;\r\nconst hasTranspiler =\r\n typeof __ENABLE_TRANSPILER__ !== \"undefined\" ? __ENABLE_TRANSPILER__ : true;\r\n\r\n/** Flag injected by build tools to enable or disable the RLOMusicPlayer features. */\r\ndeclare const __ENABLE_MUSIC_PLAYER__: boolean;\r\nconst hasMusicPlayer =\r\n typeof __ENABLE_MUSIC_PLAYER__ !== \"undefined\"\r\n ? __ENABLE_MUSIC_PLAYER__\r\n : true;\r\n\r\n/** Flag injected by build tools to enable or disable the RLOGameEngine features. */\r\ndeclare const __ENABLE_GAME_ENGINE__: boolean;\r\nconst hasGameEngine =\r\n typeof __ENABLE_GAME_ENGINE__ !== \"undefined\" ? __ENABLE_GAME_ENGINE__ : true;\r\n\r\n/** Flag injected by build tools to enable or disable the Web Worker metronome for background playback. */\r\ndeclare const __ENABLE_WORKER_METRONOME__: boolean;\r\nconst hasWorkerMetronome =\r\n typeof __ENABLE_WORKER_METRONOME__ !== \"undefined\"\r\n ? __ENABLE_WORKER_METRONOME__\r\n : false;\r\n\r\n/**\r\n * A \"dumb\" mapping mechanism for strict JS13K size-coding.\r\n * Bypasses the closest-match algorithm and explicitly assigns synths to individual IDs.\r\n * @param assignments An array of synthesizer modules and the exact MIDI IDs they should respond to.\r\n * @returns A fully populated array of 129 elements, with unassigned slots remaining null.\r\n */\r\nexport function createDirectMap(\r\n assignments: { synth: ISynthInstrument; ids: number[] }[],\r\n): ISynthInstrument[] {\r\n const mapArray = new Array(129).fill(null);\r\n assignments.forEach((a) => {\r\n a.ids.forEach((id) => (mapArray[id] = a.synth));\r\n });\r\n return mapArray;\r\n}\r\n\r\n/**\r\n * Mathematically maps instruments by MIDI ID, auto-falling back to the closest available synthesizer.\r\n * @param modules An array of synthesizer module configurations to map.\r\n * @returns A fully populated array of 129 synthesizer instruments.\r\n */\r\nexport function createInstrumentMap(\r\n modules: { synth: ISynthInstrument; start: number; end: number }[],\r\n): ISynthInstrument[] {\r\n const mapArray = new Array(129).fill(null);\r\n modules.forEach((m) => {\r\n for (let i = m.start; i <= m.end; i++) mapArray[i] = m.synth;\r\n });\r\n\r\n for (let i = 0; i < 129; i++) {\r\n if (mapArray[i] === null) {\r\n let closest = null;\r\n let minDiff = Infinity;\r\n for (let j = 0; j < 129; j++) {\r\n if (mapArray[j] !== null) {\r\n const diff = Math.abs(i - j);\r\n if (diff < minDiff) {\r\n minDiff = diff;\r\n closest = mapArray[j];\r\n }\r\n }\r\n }\r\n mapArray[i] = closest;\r\n }\r\n }\r\n return mapArray;\r\n}\r\n\r\n/**\r\n * Creates a new instrument map by merging custom synth overrides into an existing base map.\r\n * @param baseMap The base instrument map array.\r\n * @param overrides An array of synthesizer module configurations to override in the base map.\r\n * @returns A new array of synthesizer instruments with the overrides applied.\r\n */\r\nexport function extendInstrumentMap(\r\n baseMap: ISynthInstrument[],\r\n overrides: { synth: ISynthInstrument; start: number; end: number }[],\r\n): ISynthInstrument[] {\r\n const newMap = [...baseMap];\r\n overrides.forEach((m) => {\r\n for (let i = m.start; i <= m.end; i++) newMap[i] = m.synth;\r\n });\r\n return newMap;\r\n}\r\n\r\n/**\r\n * RLOCore: The bare-metal procedural sequencer.\r\n * Zero networking, zero master effects. Just pure math to audio waves.\r\n */\r\nexport class RLOCore {\r\n /** The Web Audio API context used for all audio operations. */\r\n protected _ctx: AudioContext;\r\n /** Indicates whether a sequence is currently playing. */\r\n protected _isPlaying: boolean = false;\r\n /** Stores the timer ID for the standard JavaScript timeout metronome. */\r\n protected _timer: ReturnType<typeof setTimeout> | null = null;\r\n /** Stores the Web Worker instance for accurate background metronome timing. */\r\n protected _workerTimer: Worker | null = null;\r\n /** Incremental ID to keep track of the current playback sequence and prevent overlapping schedules. */\r\n protected _sequenceId: number = 0;\r\n /** The current track playback time in seconds. */\r\n protected _trkT: number = 0;\r\n /** The total duration of the currently playing track in seconds. */\r\n protected _trkD: number = 0; // _currentTrackDuration\r\n /** Array of active audio nodes that need to be cleaned up when playback stops. */\r\n protected _activeNodes: AudioNode[] = [];\r\n /** The current global volume level (0.0 to 1.0). */\r\n protected _volume: number = 0.5;\r\n /** The target time to seek to on the next scheduling tick. */\r\n protected _seekTarget: number | null = null;\r\n\r\n /** The playback speed multiplier (1.0 is normal speed). */\r\n public playbackRate: number = 1.0;\r\n\r\n /** Array of synthesizers mapped to their corresponding MIDI instrument IDs. */\r\n protected _instrumentMap: ISynthInstrument[];\r\n /** The object URL for the Web Worker script, used for cleanup. */\r\n protected _workerUrl: string | null = null;\r\n\r\n /**\r\n * Initializes a new RLOCore instance.\r\n * @param audioContext The Web Audio API context.\r\n * @param instrumentMap The instrument routing map to use for synthesis.\r\n */\r\n constructor(\r\n audioContext: AudioContext,\r\n instrumentMap: ISynthInstrument[] = [],\r\n ) {\r\n this._ctx = audioContext;\r\n this._instrumentMap = instrumentMap;\r\n\r\n if (hasWorkerMetronome) {\r\n const blob = new Blob(\r\n [\r\n `\r\n let timerID = null;\r\n self.onmessage = function(e) {\r\n if (e.data === 'start') {\r\n if (timerID) clearInterval(timerID);\r\n timerID = setInterval(() => self.postMessage('tick'), 50);\r\n } else if (e.data === 'stop' && timerID) {\r\n clearInterval(timerID); timerID = null;\r\n }\r\n };\r\n `,\r\n ],\r\n { type: \"application/javascript\" },\r\n );\r\n this._workerUrl = URL.createObjectURL(blob);\r\n this._workerTimer = new Worker(this._workerUrl);\r\n }\r\n }\r\n\r\n /** Gets the current time of the audio context. */\r\n protected get _now(): number {\r\n return this._ctx.currentTime;\r\n }\r\n\r\n /**\r\n * Sets the global playback volume.\r\n * @param vol The volume level (0.0 to 1.0).\r\n */\r\n public setVolume(vol: number): void {\r\n this._volume = vol;\r\n }\r\n\r\n /**\r\n * Seeks the currently playing track to the specified time in seconds.\r\n * @param timeInSeconds The target time in seconds.\r\n */\r\n public seek(timeInSeconds: number): void {\r\n if (this._trkD > 0) {\r\n this._seekTarget = Math.max(0, timeInSeconds) % this._trkD;\r\n }\r\n }\r\n\r\n /** Stops playback and clears all scheduled audio nodes and timers. */\r\n public stop(): void {\r\n this._isPlaying = false;\r\n this._sequenceId++;\r\n if (this._timer) clearTimeout(this._timer);\r\n if (this._workerTimer) this._workerTimer.postMessage(\"stop\");\r\n\r\n const nodesToClean = this._activeNodes;\r\n this._activeNodes = [];\r\n\r\n nodesToClean.forEach((node) => {\r\n try {\r\n node.disconnect();\r\n } catch (e) {}\r\n });\r\n }\r\n\r\n /** Destroys the core engine, releasing memory and background workers. */\r\n public dispose(): void {\r\n this.stop();\r\n if (this._workerTimer) {\r\n this._workerTimer.terminate();\r\n this._workerTimer = null;\r\n }\r\n if (this._workerUrl) {\r\n URL.revokeObjectURL(this._workerUrl);\r\n this._workerUrl = null;\r\n }\r\n }\r\n\r\n /** Creates and returns a new GainNode. */\r\n protected _gain(): GainNode {\r\n return this._ctx.createGain();\r\n }\r\n\r\n /**\r\n * Applies a linear fade to an AudioParam over a specified duration.\r\n * @param gain The AudioParam to fade.\r\n * @param target The target value.\r\n * @param time The duration of the fade in seconds.\r\n */\r\n protected _fade(gain: AudioParam, target: number, time: number): void {\r\n gain.setValueAtTime(time > 0 ? 0 : target, this._now);\r\n if (time > 0) gain.linearRampToValueAtTime(target, this._now + time);\r\n }\r\n\r\n /** Creates a pre-configured DynamicsCompressorNode for mastering. */\r\n protected _comp(ctx: AudioContext = this._ctx): DynamicsCompressorNode {\r\n const c = ctx.createDynamicsCompressor();\r\n c.threshold.value = -24;\r\n c.knee.value = 12;\r\n c.ratio.value = 8;\r\n c.attack.value = 0.001;\r\n c.release.value = 0.25;\r\n return c;\r\n }\r\n\r\n /**\r\n * Sets up the master audio routing graph for this core.\r\n * @param fadeInTime Optional fade-in duration in seconds.\r\n * @returns An object containing the destination AudioNode.\r\n */\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n const gain = this._gain();\r\n this._fade(gain.gain, this._volume, fadeInTime);\r\n gain.connect(this._ctx.destination);\r\n this._activeNodes.push(gain);\r\n return { destination: gain };\r\n }\r\n\r\n /**\r\n * Plays a compiled RLO sequence.\r\n * @param track The compiled RloData to play.\r\n * @param loopOrOpts Whether the track should loop, or an Options Object.\r\n * @param fadeInTime Optional fade-in duration in seconds (default 0).\r\n */\r\n public playSequence(\r\n track: RloData,\r\n loopOrOpts: boolean | PlaySequenceOptions = true,\r\n oldFadeInTime: number = 0,\r\n ): void {\r\n let loop = true;\r\n let fadeInTime = oldFadeInTime;\r\n if (typeof loopOrOpts === \"object\") {\r\n loop = loopOrOpts.loop ?? true;\r\n fadeInTime = loopOrOpts.fadeInTime ?? 0;\r\n if (loopOrOpts.playbackRate !== undefined)\r\n this.playbackRate = loopOrOpts.playbackRate;\r\n if (loopOrOpts.volume !== undefined) this.setVolume(loopOrOpts.volume);\r\n } else {\r\n loop = loopOrOpts;\r\n }\r\n\r\n this.stop();\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n this._isPlaying = true;\r\n const currentSequenceId = ++this._sequenceId;\r\n this._trkD = track.durationSecs;\r\n\r\n const { destination } = this._createRouting(fadeInTime);\r\n const synthesizer = new Synthesizer(\r\n this._ctx,\r\n destination as GainNode,\r\n this._instrumentMap,\r\n );\r\n\r\n const lookaheadTime = 0.5;\r\n this._trkT = -0.05 * this.playbackRate;\r\n let lastScheduleTime = this._now;\r\n let loopOffsetSecs = 0;\r\n let notePtr = 0;\r\n const notes = track.notes;\r\n const len = notes.length;\r\n\r\n const schedule = () => {\r\n if (!this._isPlaying || this._sequenceId !== currentSequenceId) return;\r\n const currentPhysicalTime = this._now;\r\n const deltaPhysical = currentPhysicalTime - lastScheduleTime;\r\n lastScheduleTime = currentPhysicalTime;\r\n\r\n if (this._seekTarget !== null) {\r\n this._trkT = this._seekTarget;\r\n loopOffsetSecs = 0;\r\n notePtr = 0;\r\n while (notePtr < len && notes[notePtr + 1] < this._seekTarget) {\r\n notePtr += 5;\r\n }\r\n this._seekTarget = null;\r\n } else {\r\n this._trkT += deltaPhysical * this.playbackRate;\r\n }\r\n\r\n const loopDurationSecs = track.durationSecs;\r\n\r\n while (notePtr < len) {\r\n const freq = notes[notePtr];\r\n const noteTime = notes[notePtr + 1];\r\n const noteDur = notes[notePtr + 2];\r\n const velocity = notes[notePtr + 3];\r\n const instrumentId = notes[notePtr + 4];\r\n\r\n const noteTrackTime = loopOffsetSecs + noteTime;\r\n\r\n if (noteTrackTime < this._trkT + lookaheadTime * this.playbackRate) {\r\n const notePhysicalTime =\r\n currentPhysicalTime +\r\n Math.max(0, (noteTrackTime - this._trkT) / this.playbackRate);\r\n synthesizer._playNote(\r\n instrumentId,\r\n notePhysicalTime,\r\n freq,\r\n noteDur / this.playbackRate,\r\n velocity,\r\n );\r\n notePtr += 5;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n if (notePtr >= len) {\r\n if (loop) {\r\n notePtr = 0;\r\n loopOffsetSecs += loopDurationSecs;\r\n schedule();\r\n } else {\r\n if (this._workerTimer) this._workerTimer.postMessage(\"stop\");\r\n }\r\n return;\r\n }\r\n if (!this._workerTimer) {\r\n this._timer = setTimeout(schedule, 50);\r\n }\r\n };\r\n if (this._workerTimer) {\r\n this._workerTimer.onmessage = () => schedule();\r\n this._workerTimer.postMessage(\"start\");\r\n }\r\n schedule();\r\n }\r\n}\r\n\r\n/**\r\n * RLOMusicPlayer: The standard music player.\r\n * Includes network fetching, gzip decoding, convolution reverb, compression, and UI playback controls.\r\n */\r\nexport class RLOMusicPlayer extends RLOCore {\r\n /** The master volume control node. */\r\n private _masterGain: GainNode | null = null;\r\n /** The convolver node used for reverb effects. */\r\n private _reverb: ConvolverNode | null = null;\r\n /** The gain node controlling the wet/dry mix of the reverb effect. */\r\n private _fxGain: GainNode | null = null;\r\n /** A cache of recently loaded tracks to prevent redundant network requests. */\r\n private _trackCache: Map<string, RloData> = new Map();\r\n /** Event handler for pausing/resuming audio when the document visibility changes. */\r\n private _visibilityHandler!: () => void;\r\n /** The maximum number of tracks to store in the cache. */\r\n private _maxCacheSize: number = 20;\r\n /** The current acoustic space simulation mode. */\r\n private _reverbMode: ReverbMode = \"concert\";\r\n\r\n /**\r\n * Initializes a new RLOMusicPlayer instance with advanced effects and network capabilities.\r\n * @param audioContext The Web Audio API context.\r\n * @param instrumentMap Optional custom instrument map.\r\n */\r\n constructor(\r\n audioContext: AudioContext,\r\n instrumentMap: ISynthInstrument[] = [],\r\n ) {\r\n super(audioContext, instrumentMap);\r\n if (!hasMusicPlayer) return;\r\n\r\n AudioEffects._generateReverb(this._ctx, \"concert\");\r\n AudioEffects._generateReverb(this._ctx, \"studio\");\r\n\r\n this._visibilityHandler = () => {\r\n if (document.hidden) {\r\n this._ctx.suspend();\r\n } else if (this._isPlaying) {\r\n this._ctx.resume();\r\n }\r\n };\r\n\r\n // Only pause the AudioContext on tab hide if we AREN'T explicitly running in the background\r\n if (typeof document !== \"undefined\" && !hasWorkerMetronome) {\r\n document.addEventListener(\"visibilitychange\", this._visibilityHandler);\r\n }\r\n }\r\n\r\n /**\r\n * Changes the acoustic space simulation for the reverb effect.\r\n * @param mode 'concert' (large hall) or 'studio' (small room).\r\n */\r\n public setReverbMode(mode: ReverbMode): void {\r\n if (!hasMusicPlayer) return;\r\n this._reverbMode = mode;\r\n if (this._reverb && this._fxGain) {\r\n this._reverb.buffer = AudioEffects._generateReverb(this._ctx, mode);\r\n this._fxGain.gain.setTargetAtTime(\r\n mode === \"studio\" ? 0.05 : 0.2,\r\n this._now,\r\n 0.1,\r\n );\r\n }\r\n }\r\n\r\n /** Disposes the player, clearing caches and removing event listeners. */\r\n public dispose(): void {\r\n if (!hasMusicPlayer) return super.dispose();\r\n super.dispose();\r\n\r\n if (typeof document !== \"undefined\" && !hasWorkerMetronome) {\r\n document.removeEventListener(\"visibilitychange\", this._visibilityHandler);\r\n }\r\n this._trackCache.clear();\r\n }\r\n\r\n /**\r\n * Sets the playback volume, smoothly ramping to the target value.\r\n * @param vol The volume level (0.0 to 1.0).\r\n */\r\n public setVolume(vol: number): void {\r\n super.setVolume(vol);\r\n if (!hasMusicPlayer) return;\r\n if (this._masterGain) {\r\n this._masterGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n }\r\n\r\n /** Returns the current playback time of the track in seconds. */\r\n public getCurrentTime(): number {\r\n if (!hasMusicPlayer) return 0;\r\n if (this._trkD === 0 || !this._isPlaying) return 0;\r\n return Math.max(0, this._trkT) % this._trkD;\r\n }\r\n\r\n /** Returns the total duration of the currently loaded track in seconds. */\r\n public getTotalDuration(): number {\r\n if (!hasMusicPlayer) return 0;\r\n return this._trkD;\r\n }\r\n\r\n /**\r\n * Overrides the core routing to include reverb, filtering, and mastering compression.\r\n * @param fadeInTime Optional fade-in duration in seconds.\r\n * @returns An object containing the destination AudioNode.\r\n */\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n if (!hasMusicPlayer) return super._createRouting(fadeInTime);\r\n this._reverb = this._ctx.createConvolver();\r\n this._reverb.buffer = AudioEffects._generateReverb(\r\n this._ctx,\r\n this._reverbMode,\r\n );\r\n this._masterGain = this._gain();\r\n this._activeNodes.push(this._reverb, this._masterGain);\r\n\r\n this._fade(this._masterGain.gain, this._volume, fadeInTime);\r\n\r\n this._fxGain = this._gain();\r\n this._fxGain.gain.value = this._reverbMode === \"studio\" ? 0.05 : 0.2;\r\n this._activeNodes.push(this._fxGain);\r\n\r\n const masterFilter = this._ctx.createBiquadFilter();\r\n masterFilter.type = \"lowpass\";\r\n masterFilter.frequency.value = Math.min(this._ctx.sampleRate / 2 - 1, 6500);\r\n this._activeNodes.push(masterFilter);\r\n\r\n const compressor = this._comp();\r\n this._activeNodes.push(compressor);\r\n\r\n this._masterGain\r\n .connect(masterFilter)\r\n .connect(compressor)\r\n .connect(this._ctx.destination);\r\n this._masterGain\r\n .connect(this._reverb)\r\n .connect(this._fxGain)\r\n .connect(masterFilter);\r\n\r\n return { destination: this._masterGain };\r\n }\r\n\r\n /**\r\n * Loads and plays a track from a URL, a JSON object, or an existing RloData object.\r\n * @param trackUrlOrData The URL to fetch, or the raw track data.\r\n * @param fadeInOrOpts Optional fade-in duration in seconds, or an Options Object.\r\n * @param oldLoop Whether to loop the track (default true).\r\n */\r\n public async play(\r\n trackUrlOrData: string | RloData,\r\n fadeInOrOpts: number | PlaySequenceOptions = 0,\r\n oldLoop: boolean = true,\r\n ): Promise<void> {\r\n if (!hasMusicPlayer) return;\r\n let track: RloData;\r\n\r\n let fadeInTime = 0;\r\n let optionsObj: PlaySequenceOptions = {};\r\n if (typeof fadeInOrOpts === \"object\") {\r\n fadeInTime = fadeInOrOpts.fadeInTime ?? 0;\r\n optionsObj = fadeInOrOpts;\r\n } else {\r\n fadeInTime = fadeInOrOpts;\r\n optionsObj = { fadeInTime, loop: oldLoop };\r\n }\r\n\r\n if (typeof trackUrlOrData === \"string\") {\r\n if (this._trackCache.has(trackUrlOrData)) {\r\n track = this._trackCache.get(trackUrlOrData)!;\r\n } else {\r\n const response = await fetch(trackUrlOrData);\r\n\r\n if (!hasTranspiler || trackUrlOrData.toLowerCase().endsWith(\".json\")) {\r\n const text = await response.text();\r\n track = JSON.parse(text);\r\n } else {\r\n const rawBuffer = await response.arrayBuffer();\r\n const view = new DataView(rawBuffer);\r\n // Check for 'RLO' magic bytes to see if the browser natively decompressed it\r\n const isDecompressed =\r\n view.byteLength >= 3 &&\r\n view.getUint8(0) === 82 &&\r\n view.getUint8(1) === 76 &&\r\n view.getUint8(2) === 79;\r\n\r\n if (isDecompressed) {\r\n track = RLOTranspiler._decodeBinary(rawBuffer);\r\n } else {\r\n const ds = new (window as any).DecompressionStream(\"gzip\");\r\n const writer = ds.writable.getWriter();\r\n writer.write(rawBuffer);\r\n writer.close();\r\n track = RLOTranspiler._decodeBinary(\r\n await new Response(ds.readable).arrayBuffer(),\r\n );\r\n }\r\n }\r\n this._trackCache.set(trackUrlOrData, track);\r\n\r\n if (this._trackCache.size > this._maxCacheSize) {\r\n const firstKey = this._trackCache.keys().next().value;\r\n if (firstKey) this._trackCache.delete(firstKey);\r\n }\r\n }\r\n } else {\r\n track = trackUrlOrData;\r\n }\r\n\r\n this.playSequence(track, optionsObj);\r\n }\r\n\r\n /** Stops playback and gently resets the master gain nodes. */\r\n public stop(): void {\r\n if (!hasMusicPlayer) return super.stop();\r\n if (this._masterGain) {\r\n const now = this._now;\r\n this._masterGain.gain.cancelScheduledValues(now);\r\n this._masterGain.gain.setValueAtTime(0, now);\r\n\r\n this._masterGain = null;\r\n this._fxGain = null;\r\n this._reverb = null;\r\n }\r\n super.stop();\r\n }\r\n}\r\n\r\n/**\r\n * RLOGameEngine: Built for instant action.\r\n * Features a persistent master routing bus so SFX can play over background music\r\n * without interrupting each other or causing clipping.\r\n */\r\nexport class RLOGameEngine extends RLOCore {\r\n /** The persistent master routing bus volume node. */\r\n private _masterGain!: GainNode;\r\n /** The dedicated routing bus for Sound Effects. */\r\n private _sfxGain!: GainNode;\r\n /** The dedicated routing bus for Background Music. */\r\n private _musicGain!: GainNode;\r\n /** A separate synthesizer instance strictly for playing non-blocking sound effects. */\r\n private _sfxSynthesizer!: Synthesizer;\r\n\r\n /**\r\n * Initializes a new RLOGameEngine instance tailored for dynamic real-time audio.\r\n * @param audioContext The Web Audio API context.\r\n * @param instrumentMap Optional custom instrument map.\r\n */\r\n constructor(\r\n audioContext: AudioContext,\r\n instrumentMap: ISynthInstrument[] = [],\r\n ) {\r\n super(audioContext, instrumentMap);\r\n if (!hasGameEngine) return;\r\n\r\n this._masterGain = this._gain();\r\n this._masterGain.gain.value = this._volume;\r\n\r\n const compressor = this._comp();\r\n\r\n this._masterGain.connect(compressor).connect(this._ctx.destination);\r\n\r\n this._musicGain = this._gain();\r\n this._musicGain.connect(this._masterGain);\r\n\r\n this._sfxGain = this._gain();\r\n this._sfxGain.connect(this._masterGain);\r\n this._sfxSynthesizer = new Synthesizer(\r\n this._ctx,\r\n this._sfxGain,\r\n this._instrumentMap,\r\n );\r\n }\r\n\r\n /**\r\n * Smoothly changes the master volume for all game audio.\r\n * @param vol The volume level (0.0 to 1.0).\r\n */\r\n public setVolume(vol: number): void {\r\n super.setVolume(vol);\r\n if (!hasGameEngine) return;\r\n this._masterGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n /**\r\n * Smoothly changes the volume strictly for the background music routing bus.\r\n * @param vol The volume level (0.0 to 1.0).\r\n */\r\n public setMusicVolume(vol: number): void {\r\n if (!hasGameEngine) return;\r\n this._musicGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n /**\r\n * Smoothly changes the volume strictly for the sound effects routing bus.\r\n * @param vol The volume level (0.0 to 1.0).\r\n */\r\n public setSFXVolume(vol: number): void {\r\n if (!hasGameEngine) return;\r\n this._sfxGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n /**\r\n * Overrides the core routing to tap into the persistent master game bus.\r\n * @param fadeInTime Optional fade-in duration in seconds.\r\n * @returns An object containing the destination AudioNode.\r\n */\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n if (!hasGameEngine) return super._createRouting(fadeInTime);\r\n const musicGain = this._gain();\r\n musicGain.connect(this._musicGain);\r\n this._activeNodes.push(musicGain);\r\n\r\n this._fade(musicGain.gain, 1, fadeInTime);\r\n\r\n return { destination: musicGain };\r\n }\r\n\r\n /**\r\n * Plays a fire-and-forget sound effect dynamically at runtime.\r\n * @param instrumentId The General MIDI ID of the instrument to use (e.g., 128 for percussion).\r\n * @param freqOrNote The frequency in Hz, or a Note String (e.g. 'E4').\r\n * @param duration The duration of the sound effect in seconds.\r\n * @param velocityOrOpts The velocity (0.0 to 1.0), or an Options Object.\r\n * @param oldTimeOffset Optional delay in seconds before the sound effect plays.\r\n */\r\n public playSFX(\r\n instrumentId: number,\r\n freqOrNote: number | string,\r\n duration: number,\r\n velocityOrOpts: number | SFXOptions = 1.0,\r\n oldTimeOffset: number = 0,\r\n ) {\r\n if (!hasGameEngine) return;\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n let velocity = 1.0;\r\n let timeOffset = oldTimeOffset;\r\n if (typeof velocityOrOpts === \"object\") {\r\n velocity = velocityOrOpts.velocity ?? 1.0;\r\n timeOffset = velocityOrOpts.timeOffset ?? 0;\r\n } else {\r\n velocity = velocityOrOpts;\r\n }\r\n this._sfxSynthesizer._playNote(\r\n instrumentId,\r\n this._now + timeOffset,\r\n Note(freqOrNote),\r\n duration,\r\n velocity,\r\n );\r\n }\r\n\r\n /**\r\n * Plays an entire compiled RLO sequence as a fire-and-forget sound effect.\r\n * Note: This bypasses the sequencer and schedules all notes instantly. Ideal for short, complex jingles.\r\n * @param track The compiled RloData to play.\r\n * @param timeOffset Optional delay in seconds before the sequence starts.\r\n */\r\n public playSFXSequence(track: RloData, timeOffset: number = 0): void {\r\n if (!hasGameEngine) return;\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n const start = this._now + timeOffset;\r\n const n = track.notes;\r\n const len = n.length;\r\n\r\n for (let i = 0; i < len; i += 5) {\r\n this._sfxSynthesizer._playNote(\r\n n[i + 4],\r\n start + n[i + 1],\r\n n[i],\r\n n[i + 2],\r\n n[i + 3],\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Plays a background music track, routing it through the master game bus.\r\n * @param track The compiled RloData to play.\r\n * @param loopOrOpts Whether the track should loop indefinitely (default true), or an Options Object.\r\n * @param fadeInTime Optional fade-in duration in seconds (default 0).\r\n */\r\n public playMusic(\r\n track: RloData,\r\n loopOrOpts: boolean | PlaySequenceOptions = true,\r\n oldFadeInTime: number = 0,\r\n ): void {\r\n if (!hasGameEngine) return;\r\n let opts: boolean | PlaySequenceOptions = loopOrOpts;\r\n if (typeof loopOrOpts === \"object\" && loopOrOpts.volume !== undefined) {\r\n this.setMusicVolume(loopOrOpts.volume);\r\n opts = { ...loopOrOpts };\r\n delete (opts as PlaySequenceOptions).volume;\r\n }\r\n this.playSequence(track, opts, oldFadeInTime);\r\n }\r\n\r\n /** Stops the currently playing background music. SFX will continue to function. */\r\n public stopMusic(): void {\r\n super.stop();\r\n }\r\n}\r\n","import { ISynthInstrument } from \"./ISynthInstrument.js\";\r\n\r\ndeclare const __ENABLE_STRICT_GC__: boolean;\r\nconst hasStrictGC =\r\n typeof __ENABLE_STRICT_GC__ !== \"undefined\" ? __ENABLE_STRICT_GC__ : true;\r\n\r\nexport const enum Osc {\r\n Sine = 0,\r\n Square = 1,\r\n Sawtooth = 2,\r\n Triangle = 3,\r\n}\r\nexport const enum Filter {\r\n Lowpass = 0,\r\n Highpass = 1,\r\n Bandpass = 2,\r\n}\r\n\r\nexport abstract class CoreSynthBase implements ISynthInstrument {\r\n public abstract _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void;\r\n\r\n public _osc(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n dest?: AudioNode | AudioParam,\r\n ): OscillatorNode {\r\n const o = ctx.createOscillator();\r\n o.type = [\"sine\", \"square\", \"sawtooth\", \"triangle\"][type] as OscillatorType;\r\n if (freq) o.frequency.value = Math.min(22000, freq);\r\n if (dest) o.connect(dest as any);\r\n return o;\r\n }\r\n public _gain(\r\n ctx: AudioContext,\r\n val: number,\r\n dest?: AudioNode | AudioParam,\r\n ): GainNode {\r\n const g = ctx.createGain();\r\n g.gain.value = val;\r\n if (dest) g.connect(dest as any);\r\n return g;\r\n }\r\n public _filter(ctx: AudioContext, type: Filter): BiquadFilterNode {\r\n const f = ctx.createBiquadFilter();\r\n f.type = [\"lowpass\", \"highpass\", \"bandpass\"][type] as BiquadFilterType;\r\n return f;\r\n }\r\n public _pan(\r\n ctx: AudioContext,\r\n val: number,\r\n dest?: AudioNode,\r\n ): StereoPannerNode {\r\n const p = ctx.createStereoPanner();\r\n p.pan.value = val;\r\n if (dest) p.connect(dest);\r\n return p;\r\n }\r\n public _on(t: number, s: number, ...n: AudioScheduledSourceNode[]): void {\r\n n.forEach((x) => {\r\n x.start(t);\r\n x.stop(s);\r\n });\r\n }\r\n public _set(p: AudioParam, v: number, t: number): void {\r\n p.setValueAtTime(Math.min(22000, v), t);\r\n }\r\n public _lin(p: AudioParam, v: number, t: number): void {\r\n p.linearRampToValueAtTime(Math.min(22000, v), t);\r\n }\r\n public _exp(p: AudioParam, v: number, t: number): void {\r\n p.exponentialRampToValueAtTime(Math.min(22000, v), t);\r\n }\r\n\r\n public _transient(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n dest: AudioNode,\r\n time: number,\r\n peak: number,\r\n dur: number,\r\n atk: number = 0,\r\n ): void {\r\n const g = this._gain(ctx, 0, dest);\r\n this._set(g.gain, atk > 0 ? 0 : peak, time);\r\n if (atk > 0) this._lin(g.gain, peak, time + atk);\r\n this._exp(g.gain, 0.001, time + dur);\r\n this._on(time, time + dur, this._osc(ctx, type, freq, g));\r\n }\r\n public _filterSweep(\r\n ctx: AudioContext,\r\n type: Filter,\r\n f1: number,\r\n f2: number,\r\n t1: number,\r\n dur: number,\r\n ): BiquadFilterNode {\r\n const f = this._filter(ctx, type);\r\n this._set(f.frequency, f1, t1);\r\n this._exp(f.frequency, f2, t1 + dur);\r\n return f;\r\n }\r\n public _stereoOsc(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n detune: number,\r\n pan: number,\r\n dest: AudioNode,\r\n ): [OscillatorNode, OscillatorNode] {\r\n return [\r\n this._osc(ctx, type, freq, this._pan(ctx, -pan, dest)),\r\n this._osc(ctx, type, freq * detune, this._pan(ctx, pan, dest)),\r\n ];\r\n }\r\n public _lfo(\r\n ctx: AudioContext,\r\n freq: number,\r\n depth: number,\r\n time: number,\r\n fadeIn: number,\r\n stopTime: number,\r\n dest: AudioNode | AudioParam,\r\n delay: number = 0,\r\n ): GainNode {\r\n const g = this._gain(ctx, 0, dest);\r\n this._set(g.gain, 0, time);\r\n if (delay > 0) this._set(g.gain, 0, time + delay);\r\n this._lin(g.gain, depth, time + delay + fadeIn);\r\n this._on(time, stopTime, this._osc(ctx, Osc.Sine, freq, g));\r\n return g;\r\n }\r\n\r\n public _gc(\r\n ctx: AudioContext,\r\n time: number,\r\n stopTime: number,\r\n ...nodes: AudioNode[]\r\n ): void {\r\n if (hasStrictGC) {\r\n const gcOsc = ctx.createOscillator();\r\n gcOsc.onended = () => {\r\n nodes.forEach((n) => {\r\n try {\r\n n.disconnect();\r\n } catch (e) {}\r\n });\r\n };\r\n gcOsc.start(time);\r\n gcOsc.stop(stopTime);\r\n }\r\n }\r\n}\r\n","import { CoreSynthBase } from \"../CoreSynthBase.js\";\r\n\r\nexport type DecayCfg = { v: number; a: number; d: number; m: number };\r\n\r\n/**\r\n * Abstract base class for plucked, struck, and decaying synthesizers.\r\n * Handles GainNode creation, Nyquist safety limits, and decay volume envelopes.\r\n */\r\nexport abstract class DecaySynthBase extends CoreSynthBase {\r\n protected _c: DecayCfg = { v: 0.5, a: 0.02, d: 0.2, m: 4.0 };\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = ctx.createGain();\r\n\r\n const c = this._cfg();\r\n const peakVol = Math.max(0.001, velocity * c.v);\r\n\r\n /** Physical strings/mallets stop vibrating quickly. Protects against stuck MIDI notes. */\r\n const safeDuration = Math.max(0.02, Math.min(duration, c.m));\r\n\r\n this._set(gain.gain, 0, time);\r\n this._lin(gain.gain, peakVol, time + c.a);\r\n\r\n this._applyDecay(gain.gain, peakVol, time, c.a, safeDuration, c.d);\r\n\r\n /** Pad the oscillator stop time slightly past the volume decay to prevent digital clicking */\r\n const stopTime = time + safeDuration + c.d + 0.1;\r\n\r\n const output = this._setupSynthesis(\r\n ctx,\r\n masterGain,\r\n gain,\r\n time,\r\n freq,\r\n velocity,\r\n safeDuration,\r\n stopTime,\r\n );\r\n\r\n const finalNode = output || gain;\r\n finalNode.connect(masterGain);\r\n this._gc(ctx, time, stopTime + 2.0, finalNode);\r\n }\r\n\r\n protected _cfg(): DecayCfg {\r\n return this._c;\r\n }\r\n\r\n /** Override this for complex envelopes (like electric guitar compression) */\r\n protected _applyDecay(\r\n gainParam: AudioParam,\r\n peakVol: number,\r\n time: number,\r\n attack: number,\r\n safeDuration: number,\r\n decayTail: number,\r\n ): void {\r\n this._exp(gainParam, 0.001, time + safeDuration + decayTail);\r\n }\r\n\r\n /**\r\n * Set up the specific oscillators and filters for this instrument.\r\n */\r\n protected abstract _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void;\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Piano and similar percussive-melodic instruments.\r\n */\r\nexport class PianoSynth extends DecaySynthBase {\r\n protected _c = { v: 0.8, a: 0.015, d: 0.1, m: 5.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Key-tracking the filter ensures high notes aren't artificially muffled or phase-distorted. Capped at Nyquist. */\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n freq + 800 + velocity * 1000,\r\n freq + 200,\r\n time,\r\n Math.min(safeDuration, 1.0),\r\n );\r\n const osc1 = this._osc(ctx, Osc.Triangle, freq, gain);\r\n\r\n /** Slight inharmonicity stretching, strictly capped below Nyquist to prevent digital aliasing */\r\n const overtoneGain = this._gain(ctx, 0);\r\n const osc2 = this._osc(ctx, Osc.Sine, freq * 2.003, overtoneGain);\r\n const osc3 = this._osc(ctx, Osc.Sine, freq * 3.007, overtoneGain);\r\n\r\n /** Dynamically pan lower keys to the left ear, and higher keys to the right ear */\r\n const panner = this._pan(\r\n ctx,\r\n Math.max(-0.8, Math.min(0.8, (freq - 261.6) / 800)),\r\n );\r\n\r\n /** Sympathetic string resonance: metallic clangs decay much faster than the fundamental */\r\n this._set(overtoneGain.gain, 0, time);\r\n this._lin(overtoneGain.gain, Math.max(0.001, velocity * 0.15), time + 0.01);\r\n this._exp(overtoneGain.gain, 0.001, time + Math.min(safeDuration, 0.5));\r\n overtoneGain.connect(panner);\r\n\r\n /** Mechanical Hammer Thump: the physical impact of the wooden hammer on the strings */\r\n this._transient(\r\n ctx,\r\n Osc.Sine,\r\n 60,\r\n panner,\r\n time,\r\n Math.max(0.001, velocity * 0.4),\r\n 0.05,\r\n 0.005,\r\n );\r\n\r\n gain.connect(panner).connect(filter);\r\n\r\n this._on(time, stopTime, osc1, osc2, osc3);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Chromatic Percussion (Bells, Marimba, Vibraphone).\r\n * Characterized by a pure tone with a very fast attack and immediate decay.\r\n */\r\nexport class ChromaticPercussionSynth extends DecaySynthBase {\r\n protected _c = { v: 0.7, a: 0.005, d: 0.5, m: 6.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Sine, 0, gain);\r\n this._set(osc.frequency, freq * 1.1, time);\r\n this._exp(osc.frequency, freq, time + 0.02);\r\n\r\n const overtoneGain = this._gain(ctx, 0, masterGain);\r\n this._set(overtoneGain.gain, Math.max(0.001, velocity * 0.25), time);\r\n this._exp(overtoneGain.gain, 0.001, time + safeDuration);\r\n const overtone = this._osc(ctx, Osc.Sine, freq * 2.76, overtoneGain);\r\n\r\n overtoneGain.connect(masterGain);\r\n\r\n this._on(time, stopTime, osc, overtone);\r\n }\r\n}\r\n","import { CoreSynthBase } from \"../CoreSynthBase.js\";\r\n\r\nexport type AnalogCfg = { v: number; a: number; r: number };\r\n\r\n/**\r\n * Abstract base class for sustained analog synthesizers.\r\n * Handles GainNode creation, Nyquist safety limits, and ADSR volume envelopes.\r\n */\r\nexport abstract class AnalogSynthBase extends CoreSynthBase {\r\n protected _c: AnalogCfg = { v: 0.5, a: 0.05, r: 0.1 };\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = ctx.createGain();\r\n\r\n const c = this._cfg(duration);\r\n const peakVol = Math.max(0.001, velocity * c.v);\r\n\r\n this._set(gain.gain, 0, time);\r\n this._lin(gain.gain, peakVol, time + c.a);\r\n\r\n const sustainTime = Math.max(c.a, duration);\r\n this._set(gain.gain, peakVol, time + sustainTime);\r\n this._lin(gain.gain, 0.001, time + sustainTime + c.r);\r\n\r\n const stopTime = time + sustainTime + c.r;\r\n\r\n const output = this._setupSynthesis(\r\n ctx,\r\n gain,\r\n time,\r\n freq,\r\n velocity,\r\n sustainTime,\r\n c.r,\r\n stopTime,\r\n );\r\n\r\n const finalNode = output || gain;\r\n finalNode.connect(masterGain);\r\n this._gc(ctx, time, stopTime + 0.1, finalNode);\r\n }\r\n\r\n protected _cfg(d: number): AnalogCfg {\r\n return this._c;\r\n }\r\n\r\n /**\r\n * Set up the specific oscillators and filters for this instrument.\r\n * You must start() and stop() your own oscillators.\r\n * @returns The final audio node in the chain to connect to the master mix. If omitted, the base envelope gain is used.\r\n */\r\n protected abstract _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void;\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Organs using additive sine waves.\r\n */\r\nexport class OrganSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.4, a: 0.01, r: 0.05 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc1 = this._osc(ctx, Osc.Sine, freq, gain);\r\n const gain2 = this._gain(ctx, 0.5, gain);\r\n const osc2 = this._osc(ctx, Osc.Sine, freq * 2, gain2);\r\n const gain3 = this._gain(ctx, 0.25, gain);\r\n const osc3 = this._osc(ctx, Osc.Sine, freq * 3, gain3);\r\n\r\n const rotaryNode = this._gain(ctx, 0.7);\r\n this._lfo(ctx, 6.5, 0.3, time, 0, stopTime, rotaryNode.gain);\r\n\r\n gain.connect(rotaryNode);\r\n\r\n this._transient(\r\n ctx,\r\n Osc.Square,\r\n 4000,\r\n rotaryNode,\r\n time,\r\n Math.max(0.001, velocity * 0.1),\r\n 0.015,\r\n );\r\n\r\n this._on(time, stopTime, osc1, osc2, osc3);\r\n\r\n return rotaryNode;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Acoustic Guitars using a plucked sawtooth.\r\n */\r\nexport class GuitarSynth extends DecaySynthBase {\r\n protected _c = { v: 0.6, a: 0.02, d: 0.2, m: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Bright attack that quickly muffles as the acoustic string loses kinetic energy */\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n 2000 + velocity * 1000,\r\n 200,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const osc = this._osc(ctx, Osc.Sawtooth, 0, gain);\r\n this._set(osc.frequency, freq * 1.02, time);\r\n this._exp(osc.frequency, freq, time + 0.05);\r\n\r\n gain.connect(filter);\r\n\r\n /** Plectrum Pluck: the sharp, plastic click of a pick striking a steel string */\r\n this._transient(\r\n ctx,\r\n Osc.Square,\r\n 3500,\r\n masterGain,\r\n time,\r\n Math.max(0.001, velocity * 0.25),\r\n 0.015,\r\n );\r\n\r\n this._on(time, stopTime, osc);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Electric and Distorted Guitars.\r\n */\r\nexport class ElectricGuitarSynth extends DecaySynthBase {\r\n protected _c = { v: 0.5, a: 0.02, d: 0.2, m: 4.0 };\r\n\r\n protected _applyDecay(\r\n gainParam: AudioParam,\r\n peakVol: number,\r\n time: number,\r\n attack: number,\r\n safeDuration: number,\r\n decayTail: number,\r\n ): void {\r\n /** Compressed sustain mimicking an electric guitar amp */\r\n this._exp(\r\n gainParam,\r\n Math.max(0.001, peakVol * 0.4),\r\n time + Math.min(0.5, safeDuration),\r\n );\r\n this._exp(gainParam, 0.001, time + safeDuration + decayTail);\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n 2500 + velocity * 1500,\r\n 600,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const [osc, osc2] = this._stereoOsc(ctx, Osc.Sawtooth, 0, 1, 0, gain);\r\n this._set(osc.frequency, freq * 1.02, time);\r\n this._exp(osc.frequency, freq, time + 0.05);\r\n this._set(osc2.frequency, freq * 1.022, time);\r\n this._exp(osc2.frequency, freq * 1.002, time + 0.05);\r\n\r\n const vibrato = this._lfo(\r\n ctx,\r\n 5.0,\r\n freq * 0.015,\r\n time,\r\n 0.2,\r\n stopTime,\r\n osc.frequency,\r\n 0.4,\r\n );\r\n vibrato.connect(osc2.frequency);\r\n\r\n gain.connect(filter);\r\n\r\n /** Heavy plectrum attack */\r\n this._transient(\r\n ctx,\r\n Osc.Square,\r\n 3500,\r\n masterGain,\r\n time,\r\n Math.max(0.001, velocity * 0.25),\r\n 0.015,\r\n );\r\n\r\n this._on(time, stopTime, osc, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"../Decay/DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for deep Bass instruments using sawtooth waves.\r\n */\r\nexport class BassSynth extends DecaySynthBase {\r\n protected _c = { v: 0.8, a: 0.05, d: 0.1, m: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Deep envelope sweep for punchy, muffled bass attack. Capped safely below Nyquist. */\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n 300 + velocity * 500,\r\n 100,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const osc = this._osc(ctx, Osc.Sawtooth, 0, gain);\r\n this._set(osc.frequency, freq * 0.92, time);\r\n this._exp(osc.frequency, freq, time + 0.04);\r\n\r\n const subGain = this._gain(ctx, 0.6, gain);\r\n const subOsc = this._osc(ctx, Osc.Sine, 0, subGain);\r\n this._set(subOsc.frequency, (freq / 2) * 0.92, time);\r\n this._exp(subOsc.frequency, freq / 2, time + 0.04);\r\n\r\n gain.connect(filter);\r\n\r\n this._on(time, stopTime, osc, subOsc);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for String and Pad instruments using detuned oscillators.\r\n */\r\nexport class StringSynth extends AnalogSynthBase {\r\n protected _cfg(d: number): { v: number; a: number; r: number } {\r\n return { v: 0.3, a: d < 0.4 ? 0.05 : 0.2, r: d < 0.4 ? 0.1 : 0.5 };\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const [osc1, osc2] = this._stereoOsc(\r\n ctx,\r\n Osc.Sawtooth,\r\n freq,\r\n 1.005,\r\n 0.6,\r\n gain,\r\n );\r\n\r\n const lfo = this._lfo(\r\n ctx,\r\n 4.5,\r\n freq * 0.012,\r\n time,\r\n 0.3,\r\n stopTime,\r\n osc1.frequency,\r\n );\r\n lfo.connect(osc2.frequency);\r\n\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n freq + 1200 + velocity * 1000,\r\n freq + 800,\r\n time,\r\n sustainTime + releaseTime,\r\n );\r\n\r\n gain.connect(filter);\r\n\r\n this._on(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"../Analog/AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Brass and Wind instruments with a slow filter envelope.\r\n */\r\nexport class BrassSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.5, a: 0.1, r: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Square, 0, gain);\r\n this._set(osc.frequency, freq * 0.95, time);\r\n this._exp(osc.frequency, freq, time + 0.05);\r\n\r\n const blareGain = this._gain(ctx, 0, gain);\r\n this._set(blareGain.gain, 0, time);\r\n this._lin(blareGain.gain, Math.max(0.001, velocity * 0.25), time + 0.05);\r\n this._exp(blareGain.gain, 0.001, time + 0.2);\r\n const blare = this._osc(ctx, Osc.Sawtooth, freq * 2, blareGain);\r\n\r\n const filter = this._filter(ctx, Filter.Lowpass);\r\n this._set(filter.frequency, freq + 400, time);\r\n this._lin(filter.frequency, freq + 1500 + velocity * 1000, time + 0.1);\r\n this._exp(filter.frequency, freq + 400, time + sustainTime + releaseTime);\r\n\r\n gain.connect(filter);\r\n this._on(time, stopTime, osc);\r\n this._on(time, time + 0.2, blare);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Woodwinds and Pipes (Flute, Piccolo, Recorder, Ocarina).\r\n * Characterized by a pure, hollow, and breathy tone using sine and triangle waves.\r\n */\r\nexport class WoodwindSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.7, a: 0.05, r: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Flutes are mostly a fundamental sine wave with a tiny bit of triangle for the \"chiff\" sound */\r\n const osc1 = this._osc(ctx, Osc.Sine, freq, gain);\r\n\r\n /** Triangle is mixed much lower just to provide a bit of upper harmonic texture */\r\n const triGain = this._gain(ctx, 0, gain);\r\n /** Breath transient: louder at attack, decaying to a whisper during sustain */\r\n this._set(triGain.gain, 0.3, time);\r\n this._exp(triGain.gain, 0.05, time + 0.2);\r\n const osc2 = this._osc(ctx, Osc.Triangle, freq, triGain);\r\n\r\n /** Lowpass filter to keep it extremely smooth and remove any digital sharpness */\r\n const filter = this._filter(ctx, Filter.Lowpass);\r\n this._set(filter.frequency, freq + 800, time);\r\n\r\n /** Diaphragm vibrato: blooms slowly after the initial breath attack */\r\n const vibrato = this._lfo(\r\n ctx,\r\n 5.5,\r\n freq * 0.015,\r\n time,\r\n 0.4,\r\n stopTime,\r\n osc1.frequency,\r\n );\r\n vibrato.connect(osc2.frequency);\r\n\r\n /** True Amplitude Modulation (Tremolo) pipelined from the diaphragm vibrato */\r\n const tremoloNode = this._gain(ctx, 1.0);\r\n const tremoloDepth = this._gain(ctx, 0.15, tremoloNode.gain);\r\n vibrato.connect(tremoloDepth);\r\n\r\n gain.connect(tremoloNode).connect(filter);\r\n\r\n this._on(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Synth Leads featuring an LFO Vibrato.\r\n */\r\nexport class LeadSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.4, a: 0.05, r: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Sawtooth, 0);\r\n this._set(osc.frequency, freq, time);\r\n\r\n this._lfo(ctx, 5, freq * 0.02, time, 0.2, stopTime, osc.frequency);\r\n\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n freq,\r\n freq * 3,\r\n time,\r\n 0.05,\r\n );\r\n this._exp(filter.frequency, freq * 1.5, time + sustainTime);\r\n filter.Q.value = 3; /** Squelchy resonance */\r\n\r\n osc.connect(filter).connect(gain);\r\n\r\n this._on(time, stopTime, osc);\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Synth Pads (Warm, Choir, Halo, Bowed).\r\n * Characterized by slow attacks, slow releases, and evolving filter sweeps.\r\n */\r\nexport class PadSynth extends AnalogSynthBase {\r\n protected _cfg(d: number): { v: number; a: number; r: number } {\r\n return { v: 0.4, a: d < 0.4 ? 0.05 : 0.3, r: d < 0.4 ? 0.1 : 0.8 };\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const [osc1, osc2] = this._stereoOsc(\r\n ctx,\r\n Osc.Triangle,\r\n freq,\r\n 1.01,\r\n 0.7,\r\n gain,\r\n );\r\n\r\n const filter = this._filter(ctx, Filter.Lowpass);\r\n this._set(filter.frequency, freq + 400, time);\r\n this._lin(\r\n filter.frequency,\r\n freq + 1000 + velocity * 500,\r\n time + sustainTime,\r\n );\r\n\r\n this._lfo(ctx, 0.5, 10, time, 0, stopTime, osc2.frequency);\r\n this._lfo(ctx, 0.1, 400, time, 0, stopTime, filter.frequency);\r\n\r\n gain.connect(filter);\r\n\r\n this._on(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { CoreSynthBase, Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Sound Effects and Sci-Fi Synths.\r\n * Features extreme frequency sweeping over the duration of the note.\r\n */\r\nexport class SoundEffectsSynth extends CoreSynthBase {\r\n /**\r\n * Plays an automated sweeping sci-fi sound effect.\r\n */\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = this._gain(ctx, 0);\r\n const osc = this._osc(ctx, Osc.Sawtooth, 0, gain);\r\n\r\n /** Extreme pitch dive from fundamental down one full octave over the note's duration */\r\n this._set(osc.frequency, freq, time);\r\n this._exp(\r\n osc.frequency,\r\n Math.max(1, freq / 2),\r\n time + Math.max(0.05, duration),\r\n );\r\n\r\n /** Sci-Fi \"Laser Wobble\": fast sine-wave amplitude modulation (avoids scratchy clicking of square wave) */\r\n const stutterNode = this._gain(ctx, 0.5, masterGain);\r\n this._lfo(ctx, 15, 0.5, time, 0, time + duration + 0.2, stutterNode.gain);\r\n\r\n gain.connect(stutterNode);\r\n\r\n this._set(gain.gain, 0, time);\r\n this._lin(gain.gain, Math.max(0.001, velocity * 0.5), time + 0.05);\r\n this._exp(gain.gain, 0.001, time + duration + 0.2);\r\n\r\n this._on(time, time + duration + 0.2, osc);\r\n\r\n this._gc(ctx, time, time + duration + 0.3, gain, stutterNode);\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Ethnic instruments (Sitar, Shamisen, Koto).\r\n * Uses a bandpass filter over a square wave to emulate a hollow, plucked resonator.\r\n */\r\nexport class EthnicSynth extends DecaySynthBase {\r\n protected _c = { v: 0.6, a: 0.02, d: 0.1, m: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Square, 0, gain);\r\n this._set(osc.frequency, freq * 1.05, time);\r\n this._exp(osc.frequency, freq, time + 0.08);\r\n\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Bandpass,\r\n freq * 2.5,\r\n freq,\r\n time,\r\n safeDuration,\r\n );\r\n filter.Q.value = 2;\r\n\r\n filter.connect(gain);\r\n\r\n this._on(time, stopTime, osc);\r\n }\r\n}\r\n","import { CoreSynthBase, Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Percussion and Drum kits.\r\n */\r\nexport class DrumSynth extends CoreSynthBase {\r\n /** Cached white noise buffer to prevent massive memory allocations and GC spikes. */\r\n private static _cachedNoiseBuffer: AudioBuffer | null = null;\r\n\r\n private static _getNoiseBuffer(ctx: AudioContext): AudioBuffer {\r\n if (\r\n !DrumSynth._cachedNoiseBuffer ||\r\n DrumSynth._cachedNoiseBuffer.sampleRate !== ctx.sampleRate\r\n ) {\r\n const bufferSize = ctx.sampleRate * 1.0;\r\n const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);\r\n const data = buffer.getChannelData(0);\r\n for (let i = 0; i < bufferSize; i++) data[i] = Math.random() * 2 - 1;\r\n DrumSynth._cachedNoiseBuffer = buffer;\r\n }\r\n return DrumSynth._cachedNoiseBuffer;\r\n }\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n /** Standard MIDI maps specific frequencies to specific drum kit pieces */\r\n if (freq < 70) {\r\n const gain = this._gain(ctx, 0, masterGain);\r\n const osc = this._osc(ctx, Osc.Sine, 0, gain);\r\n\r\n this._set(osc.frequency, 150, time);\r\n this._exp(osc.frequency, 30, time + 0.1);\r\n this._set(gain.gain, Math.max(0.001, velocity * 1.5), time);\r\n this._exp(gain.gain, 0.001, time + 0.5);\r\n\r\n this._on(time, time + 0.5, osc);\r\n\r\n this._gc(ctx, time, time + 0.6, gain);\r\n } else {\r\n /** HI-HAT / SNARE (White Noise generation) */\r\n const isSnare = freq < 90;\r\n\r\n const noise = ctx.createBufferSource();\r\n noise.buffer = DrumSynth._getNoiseBuffer(ctx);\r\n const gain = this._gain(ctx, 0, masterGain);\r\n const filter = this._filter(\r\n ctx,\r\n isSnare ? Filter.Bandpass : Filter.Highpass,\r\n );\r\n const panner = this._pan(ctx, isSnare ? 0 : Math.random() * 0.6 - 0.3);\r\n\r\n filter.frequency.value = isSnare ? 1500 : 5000;\r\n\r\n this._set(gain.gain, Math.max(0.001, velocity), time);\r\n this._exp(gain.gain, 0.001, time + (isSnare ? 0.2 : 0.05));\r\n\r\n noise.connect(filter).connect(gain).connect(panner);\r\n this._on(time, time + (isSnare ? 0.2 : 0.05), noise);\r\n\r\n /** Add an extra body thwack tone if it is a snare */\r\n if (isSnare) {\r\n const snareOsc = this._osc(ctx, Osc.Triangle, 0, gain);\r\n /** Snare drum head tension: quick pitch drop when the stick hits the skin */\r\n this._set(snareOsc.frequency, 300, time);\r\n this._exp(snareOsc.frequency, 100, time + 0.1);\r\n this._on(time, time + 0.2, snareOsc);\r\n } else {\r\n /** 808 Cymbal Metallic Ring: TR-808 hi-hats contain high-pitched ringing square waves */\r\n this._transient(\r\n ctx,\r\n Osc.Square,\r\n 7000,\r\n panner,\r\n time,\r\n Math.max(0.001, velocity * 0.2),\r\n 0.05,\r\n );\r\n }\r\n\r\n this._gc(ctx, time, time + 0.4, filter, gain, panner);\r\n }\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for 8-bit Chiptune sounds.\r\n * Uses a raw square wave with a rapid pitch-drop \"blip\" attack.\r\n */\r\nexport class ChiptuneSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.4, a: 0.005, r: 0.05 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Square, 0, gain);\r\n\r\n /** Classic tracker \"blip\" attack: starts one octave higher for a fraction of a second */\r\n this._set(osc.frequency, freq * 2, time);\r\n this._set(osc.frequency, freq, time + 0.02);\r\n\r\n this._on(time, stopTime, osc);\r\n }\r\n}\r\n","// AUTO-GENERATED BY VITE CONFIG\nimport { RLOCore as BaseCore, RLOMusicPlayer as BaseMusicPlayer, RLOGameEngine as BaseGameEngine, RLOTranspiler, createInstrumentMap, extendInstrumentMap, createDirectMap, SilentSynth, type ISynthInstrument } from './RLO-Player.js';\nimport { PianoSynth } from './Instruments/Decay/PianoSynth.js';\nimport { ChromaticPercussionSynth } from './Instruments/Decay/ChromaticPercussionSynth.js';\nimport { OrganSynth } from './Instruments/Analog/OrganSynth.js';\nimport { GuitarSynth } from './Instruments/Decay/GuitarSynth.js';\nimport { ElectricGuitarSynth } from './Instruments/Decay/ElectricGuitarSynth.js';\nimport { BassSynth } from './Instruments/Analog/BassSynth.js';\nimport { StringSynth } from './Instruments/Analog/StringSynth.js';\nimport { BrassSynth } from './Instruments/Decay/BrassSynth.js';\nimport { WoodwindSynth } from './Instruments/Analog/WoodwindSynth.js';\nimport { LeadSynth } from './Instruments/Analog/LeadSynth.js';\nimport { PadSynth } from './Instruments/Analog/PadSynth.js';\nimport { SoundEffectsSynth } from './Instruments/Speciality/SoundEffectsSynth.js';\nimport { EthnicSynth } from './Instruments/Decay/EthnicSynth.js';\nimport { DrumSynth } from './Instruments/Speciality/DrumSynth.js';\nimport { FMSynth } from './Instruments/Analog/FMSynth.js';\nimport { AdditiveSynth } from './Instruments/Decay/AdditiveSynth.js';\nimport { KarplusSynth } from './Instruments/Decay/KarplusSynth.js';\nimport { ReeseBassSynth } from './Instruments/Analog/ReeseBassSynth.js';\nimport { FormantSynth } from './Instruments/Analog/FormantSynth.js';\nimport { ChiptuneSynth } from './Instruments/Analog/ChiptuneSynth.js';\nimport { SlapBassSynth } from './Instruments/Decay/SlapBassSynth.js';\n\n// Export all synthesizers (including optional ones) for NPM users\nexport { PianoSynth, ChromaticPercussionSynth, OrganSynth, GuitarSynth, ElectricGuitarSynth, BassSynth, StringSynth, BrassSynth, WoodwindSynth, LeadSynth, PadSynth, SoundEffectsSynth, EthnicSynth, DrumSynth, FMSynth, AdditiveSynth, KarplusSynth, ReeseBassSynth, FormantSynth, ChiptuneSynth, SlapBassSynth };\n\nconst defaultMapModules = [\n { synth: new PianoSynth(), start: 0, end: 7 },\n { synth: new ChromaticPercussionSynth(), start: 8, end: 15 },\n { synth: new OrganSynth(), start: 16, end: 23 },\n { synth: new GuitarSynth(), start: 24, end: 26 },\n { synth: new ElectricGuitarSynth(), start: 27, end: 31 },\n { synth: new BassSynth(), start: 32, end: 39 },\n { synth: new StringSynth(), start: 40, end: 55 },\n { synth: new BrassSynth(), start: 56, end: 71 },\n { synth: new WoodwindSynth(), start: 72, end: 79 },\n { synth: new LeadSynth(), start: 83, end: 87 },\n { synth: new PadSynth(), start: 88, end: 95 },\n { synth: new SoundEffectsSynth(), start: 96, end: 103 },\n { synth: new SoundEffectsSynth(), start: 120, end: 127 },\n { synth: new EthnicSynth(), start: 104, end: 111 },\n { synth: new DrumSynth(), start: 112, end: 119 },\n { synth: new DrumSynth(), start: 128, end: 128 },\n];\nconst defaultMap = createInstrumentMap(defaultMapModules);\n\nconst retroMap = createInstrumentMap([\n { synth: new ChiptuneSynth(), start: 0, end: 127 },\n { synth: new DrumSynth(), start: 128, end: 128 }\n]);\n\nexport { RLOTranspiler, createInstrumentMap, extendInstrumentMap, createDirectMap, SilentSynth, defaultMap as MasterInstrumentMap, defaultMap as StandardInstrumentMap, retroMap as RetroInstrumentMap };\nexport class RLOCore extends BaseCore { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\nexport class RLOMusicPlayer extends BaseMusicPlayer { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\nexport class RLOGameEngine extends BaseGameEngine { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\n","import { DecaySynthBase, DecayCfg } from \"./DecaySynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Inharmonic Additive bells/glass.\r\n * Stacks sine waves at non-integer multiples to create metallic, clanging overtones.\r\n */\r\nexport class AdditiveSynth extends DecaySynthBase {\r\n protected _c = { v: 0.6, a: 0.005, d: 0.5, m: 5.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const ratios = [1.0, 2.76, 5.4, 8.9, 13.3];\r\n const decays = [1.0, 0.6, 0.4, 0.2, 0.1]; // Higher frequencies die out much faster\r\n\r\n ratios.forEach((ratio, i) => {\r\n const hFreq = freq * ratio;\r\n if (hFreq < 22000) {\r\n const peak = Math.max(0.001, velocity * (1 / (i + 1.5)));\r\n const dur = Math.max(0.1, safeDuration * decays[i]);\r\n this._transient(ctx, Osc.Sine, hFreq, gain, time, peak, dur, 0.005);\r\n }\r\n });\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for FM (Frequency Modulation).\r\n * Modulates a carrier sine wave with another sine wave to create glassy,\r\n * metallic overtones common in 1980s Electric Pianos and Bells.\r\n */\r\nexport class FMSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.6, a: 0.01, r: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const carrier = this._osc(ctx, Osc.Sine, freq, gain);\r\n\r\n const modFreq = freq * 2; // 2:1 harmonic ratio for bell/epiano overtones\r\n const modDepth = modFreq * 4; // Modulation index (brightness)\r\n\r\n const modGain = this._gain(ctx, 0, carrier.frequency);\r\n this._set(modGain.gain, modDepth * velocity, time);\r\n this._exp(modGain.gain, 0.01, time + sustainTime); // Decay the harshness over time for a plucked feel\r\n\r\n const modulator = this._osc(ctx, Osc.Sine, modFreq, modGain);\r\n\r\n this._on(time, stopTime, carrier, modulator);\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Formant Choirs (Human Vox).\r\n * Uses parallel bandpass filters locked to specific \"vowel\" resonant frequencies.\r\n */\r\nexport class FormantSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.8, a: 0.1, r: 0.4 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._osc(ctx, Osc.Sawtooth, freq);\r\n this._lfo(ctx, 5, freq * 0.015, time, 0.2, stopTime, osc.frequency);\r\n\r\n // Typical 'Ah' vowel formants: 730Hz, 1090Hz, 2440Hz\r\n [730, 1090, 2440].forEach((f) => {\r\n if (f < 22000) {\r\n const filter = this._filter(ctx, Filter.Bandpass);\r\n filter.frequency.value = f;\r\n filter.Q.value = 12; // High resonance to isolate the formant\r\n osc.connect(filter).connect(gain);\r\n }\r\n });\r\n\r\n this._on(time, stopTime, osc);\r\n }\r\n}\r\n","import { CoreSynthBase, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Karplus-Strong physical modeling.\r\n * Uses a noise burst fed into a tuned delay line with a feedback filter\r\n * to accurately simulate the physics of plucked strings (Acoustic Guitar, Harp).\r\n */\r\nexport class KarplusSynth extends CoreSynthBase {\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const delayTime = 1 / freq;\r\n\r\n // 1. The Plectrum (A microscopic burst of white noise)\r\n const burstBuffer = ctx.createBuffer(\r\n 1,\r\n Math.max(1, ctx.sampleRate * delayTime),\r\n ctx.sampleRate,\r\n );\r\n const data = burstBuffer.getChannelData(0);\r\n for (let i = 0; i < data.length; i++)\r\n data[i] = (Math.random() * 2 - 1) * velocity;\r\n\r\n const burst = ctx.createBufferSource();\r\n burst.buffer = burstBuffer;\r\n\r\n // 2. The String (A delay node exactly the length of the frequency)\r\n const delay = ctx.createDelay(delayTime);\r\n delay.delayTime.value = delayTime;\r\n\r\n // 3. The Body Damping (Lowpass filter inside the feedback loop to absorb high frequencies)\r\n const filter = this._filter(ctx, Filter.Lowpass);\r\n filter.frequency.value = Math.min(22000, freq * 6);\r\n\r\n // 4. The Tension (Feedback gain)\r\n const feedback = this._gain(ctx, 0.98); // Higher value = longer ring time\r\n\r\n burst.connect(delay).connect(filter).connect(feedback).connect(delay);\r\n\r\n const output = this._gain(ctx, 0, masterGain);\r\n this._set(output.gain, 1, time);\r\n this._exp(output.gain, 0.001, time + duration);\r\n\r\n delay.connect(output);\r\n this._on(time, time + duration, burst);\r\n\r\n this._gc(ctx, time, time + duration + 3.0, output, delay, filter, feedback);\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Reese/Wobble Bass.\r\n * Uses heavily detuned sawtooths and an LFO-driven lowpass filter.\r\n */\r\nexport class ReeseBassSynth extends AnalogSynthBase {\r\n protected _c = { v: 0.7, a: 0.05, r: 0.2 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const filter = this._filter(ctx, Filter.Lowpass);\r\n this._set(filter.frequency, freq * 2, time);\r\n\r\n // Wobble LFO: syncs roughly to tempo (e.g. 1/8th notes ~4-8 Hz)\r\n this._lfo(ctx, 6, freq * 3, time, 0, stopTime, filter.frequency);\r\n\r\n // Deep, phasing detune\r\n const [osc1, osc2] = this._stereoOsc(\r\n ctx,\r\n Osc.Sawtooth,\r\n freq / 2,\r\n 1.015,\r\n 0.4,\r\n filter,\r\n );\r\n filter.connect(gain);\r\n this._on(time, stopTime, osc1, osc2);\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc, Filter } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for 80s Slap Bass (DX7/Seinfeld style).\r\n * Characterized by a very snappy filter envelope and a metallic transient \"pop\".\r\n */\r\nexport class SlapBassSynth extends DecaySynthBase {\r\n protected _c = { v: 0.9, a: 0.005, d: 0.15, m: 3.0 }; // Ultra-fast attack for the slap\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** The \"Pop\" - An aggressive lowpass filter sweep that opens bright and snaps shut */\r\n const filter = this._filterSweep(\r\n ctx,\r\n Filter.Lowpass,\r\n freq * 8 + velocity * 3000, // Very bright on hard velocities\r\n freq + 100, // Quickly muffles down to the fundamental\r\n time,\r\n 0.1, // Snap duration\r\n );\r\n filter.Q.value = 3; // Adds a \"quack\" resonance to the slap\r\n\r\n /** The Body - Sawtooth for rich harmonics */\r\n const osc = this._osc(ctx, Osc.Sawtooth, freq, gain);\r\n\r\n /** The Sub - Deep sine wave an octave down to anchor the low end */\r\n const subOsc = this._osc(ctx, Osc.Sine, freq / 2, gain);\r\n\r\n /** The \"Thumb Slap\" - A quick, inharmonic metallic burst simulating the string hitting the fretboard */\r\n this._transient(\r\n ctx,\r\n Osc.Square,\r\n freq * 3.5,\r\n filter,\r\n time,\r\n Math.max(0.001, velocity * 0.4),\r\n 0.04,\r\n );\r\n\r\n gain.connect(filter);\r\n this._on(time, stopTime, osc, subOsc);\r\n\r\n return filter;\r\n }\r\n}\r\n"],"names":["Synthesizer","constructor","ctx","masterGain","instruments","this","_ctx","_masterGain","_instruments","_playNote","instrumentId","time","freq","duration","velocity","keyTrackVel","Math","min","instrument","globalThis","DEBUG_MIDI","_AudioEffects","_generateReverb","mode","_cachedConcert","_cachedStudio","isStudio","length","sampleRate","decay","impulse","createBuffer","i","channel","getChannelData","lastOut","j","random","exp","AudioEffects","RLOTranspiler","_encodeToSoA","humanJson","fullRangeFreq","N","notes","f","Float32Array","Uint8Array","t","Uint16Array","d","v","lastRoundedTime","n","ptr","max","round","log2","roundedTime","durationSecs","_encodeToBinary","isLittleEndian","buffer","soa","ArrayBuffer","view","DataView","setUint8","setFloat32","setUint32","set","setUint16","_decodeBinary","magic","String","fromCharCode","getUint8","Error","isFullRange","getFloat32","getUint32","f8","Array","currentTime","tn","getUint16","dn","fn","pow","createInstrumentMap","modules","mapArray","fill","forEach","m","start","end","synth","closest","minDiff","Infinity","diff","abs","RLOCore$1","audioContext","instrumentMap","_isPlaying","_timer","_workerTimer","_sequenceId","_trkT","_trkD","_activeNodes","_volume","_seekTarget","playbackRate","_workerUrl","_instrumentMap","_now","setVolume","vol","seek","timeInSeconds","stop","clearTimeout","postMessage","nodesToClean","node","disconnect","e","dispose","terminate","URL","revokeObjectURL","_gain","createGain","_fade","gain","target","setValueAtTime","linearRampToValueAtTime","_comp","c","createDynamicsCompressor","threshold","value","knee","ratio","attack","release","_createRouting","fadeInTime","connect","destination","push","playSequence","track","loopOrOpts","oldFadeInTime","loop","volume","state","resume","currentSequenceId","synthesizer","lastScheduleTime","loopOffsetSecs","notePtr","len","schedule","currentPhysicalTime","deltaPhysical","loopDurationSecs","noteTime","noteDur","noteTrackTime","notePhysicalTime","setTimeout","onmessage","RLOCore","super","_reverb","_fxGain","_trackCache","Map","_maxCacheSize","_reverbMode","_visibilityHandler","document","hidden","suspend","addEventListener","setReverbMode","setTargetAtTime","removeEventListener","clear","getCurrentTime","getTotalDuration","createConvolver","masterFilter","createBiquadFilter","type","frequency","compressor","play","trackUrlOrData","fadeInOrOpts","oldLoop","optionsObj","has","get","response","fetch","toLowerCase","endsWith","text","JSON","parse","rawBuffer","arrayBuffer","byteLength","ds","window","DecompressionStream","writer","writable","getWriter","write","close","Response","readable","size","firstKey","keys","next","delete","now","cancelScheduledValues","_musicGain","_sfxGain","_sfxSynthesizer","setMusicVolume","setSFXVolume","musicGain","playSFX","freqOrNote","velocityOrOpts","oldTimeOffset","timeOffset","pitch","match","note","accidental","octave","semitone","C","D","E","F","G","A","B","toUpperCase","parseInt","toFixed","Note","playSFXSequence","playMusic","opts","stopMusic","Osc","Filter","CoreSynthBase","_osc","dest","o","createOscillator","val","g","_filter","_pan","p","createStereoPanner","pan","_on","s","x","_set","_lin","_exp","exponentialRampToValueAtTime","_transient","peak","dur","atk","_filterSweep","f1","f2","t1","_stereoOsc","detune","_lfo","depth","fadeIn","stopTime","delay","_gc","nodes","gcOsc","onended","DecaySynthBase","arguments","_c","a","_cfg","peakVol","safeDuration","_applyDecay","finalNode","_setupSynthesis","gainParam","decayTail","PianoSynth","filter","Lowpass","osc1","Triangle","overtoneGain","osc2","Sine","osc3","panner","ChromaticPercussionSynth","osc","overtone","AnalogSynthBase","r","sustainTime","OrganSynth","releaseTime","gain2","gain3","rotaryNode","Square","GuitarSynth","Sawtooth","ElectricGuitarSynth","BassSynth","subGain","subOsc","StringSynth","BrassSynth","blareGain","blare","WoodwindSynth","triGain","vibrato","tremoloNode","tremoloDepth","LeadSynth","Q","PadSynth","SoundEffectsSynth","stutterNode","EthnicSynth","Bandpass","_DrumSynth","_getNoiseBuffer","_cachedNoiseBuffer","bufferSize","data","isSnare","noise","createBufferSource","Highpass","snareOsc","DrumSynth","ChiptuneSynth","defaultMap","retroMap","decays","hFreq","carrier","modFreq","modDepth","modGain","modulator","delayTime","burstBuffer","burst","createDelay","feedback","output","BaseCore","customMap","BaseGameEngine","BaseMusicPlayer","assignments","ids","id","baseMap","overrides","newMap"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rlo-engine.min.umd.js","sources":["../RLO-Transpiler.ts","../Instruments/Synthesizer.ts","../Core/RLOCore.ts","../AudioEffects.ts","../Players/RLOMusicPlayer.ts","../Players/RLOGameEngine.ts","../Core/AudioMath.ts","../Core/InstrumentMap.ts","../Instruments/CoreSynthBase.ts","../Instruments/Decay/DecaySynthBase.ts","../Instruments/Decay/PianoSynth.ts","../Instruments/Decay/ChromaticPercussionSynth.ts","../Instruments/Analog/AnalogSynthBase.ts","../Instruments/Analog/OrganSynth.ts","../Instruments/Decay/GuitarSynth.ts","../Instruments/Decay/ElectricGuitarSynth.ts","../Instruments/Analog/BassSynth.ts","../Instruments/Analog/StringSynth.ts","../Instruments/Decay/BrassSynth.ts","../Instruments/Analog/WoodwindSynth.ts","../Instruments/Analog/LeadSynth.ts","../Instruments/Analog/PadSynth.ts","../Instruments/Speciality/SoundEffectsSynth.ts","../Instruments/Decay/EthnicSynth.ts","../Instruments/Speciality/DrumSynth.ts","../Instruments/Analog/ChiptuneSynth.ts","../index.ts","../Instruments/Decay/AdditiveSynth.ts","../Instruments/Analog/FMSynth.ts","../Instruments/Analog/FormantSynth.ts","../Instruments/Decay/KarplusSynth.ts","../Instruments/Analog/ReeseBassSynth.ts","../Instruments/Decay/SlapBassSynth.ts"],"sourcesContent":["import { RloData } from \"./types.js\";\r\n\r\ndeclare const __ENABLE_TRANSPILER__: boolean;\r\nconst hasTranspiler =\r\n typeof __ENABLE_TRANSPILER__ !== \"undefined\" ? __ENABLE_TRANSPILER__ : true;\r\n\r\n/**\r\n * Universal translator for handling RLO data formats.\r\n * Converts between Human AoS (Array of Structures), Intermediate SoA (Structure of Arrays),\r\n * and highly compressed binary buffers.\r\n * \r\n * @reason Why Structure of Arrays (SoA) and Delta-Time?\r\n * By decoupling a note into flat typed arrays (time, duration, frequency, velocity, instrument)\r\n * we allow gzip/deflate algorithms to identify massive byte repetition. For example, if a \r\n * hi-hat plays on the exact same instrument ID and velocity for 50 notes, SoA groups those 50\r\n * identical bytes contiguously in memory, allowing gzip to compress them down to literally 1 or 2 bytes.\r\n * Converting absolute time to delta-time serves the same purpose: instead of constantly increasing \r\n * time signatures, rhythmic music will yield contiguous identical delta-time bytes which gzip dominates.\r\n */\r\n/** \r\n * Converts standard interleaved JSON into Delta-Timed Structure of Arrays.\r\n * @param humanJson The flat-packed JSON array.\r\n * @param fullRangeFreq If true, writes raw 32-bit floats. If false, aggressively quantizes to 8-bit MIDI scale.\r\n */\r\nexport function encodeToSoA(humanJson: RloData, fullRangeFreq: boolean = false) {\r\n if (!hasTranspiler) return null as unknown as typeof soa;\r\n const N = humanJson.notes.length / 5;\r\n const f = fullRangeFreq ? new Float32Array(N) : new Uint8Array(N);\r\n const t = new Uint16Array(N);\r\n const d = new Uint16Array(N);\r\n const v = new Uint8Array(N);\r\n const i = new Uint8Array(N);\r\n\r\n let lastRoundedTime = 0;\r\n for (let n = 0, ptr = 0; n < N; n++, ptr += 5) {\r\n const time = humanJson.notes[ptr + 1];\r\n const freq = humanJson.notes[ptr];\r\n if (fullRangeFreq) {\r\n f[n] = freq;\r\n } else {\r\n // Map the frequency in Hz back down to a 1-byte 0-255 index\r\n f[n] =\r\n freq > 0\r\n ? Math.max(\r\n 0,\r\n Math.min(255, Math.round(12 * Math.log2(freq / 440) + 69)),\r\n )\r\n : 0;\r\n }\r\n\r\n const roundedTime = Math.max(0, Math.round(time * 1000));\r\n t[n] = Math.min(65535, roundedTime - lastRoundedTime); // Clamp to Uint16 max to prevent wraparound\r\n d[n] = Math.min(\r\n 65535,\r\n Math.max(0, Math.round(humanJson.notes[ptr + 2] * 1000)),\r\n );\r\n v[n] = Math.max(\r\n 0,\r\n Math.min(255, Math.round(humanJson.notes[ptr + 3] * 255)),\r\n );\r\n i[n] = humanJson.notes[ptr + 4];\r\n lastRoundedTime += t[n]; // Add the clamped delta to accurately track absolute encoded time\r\n }\r\n\r\n const soa = {\r\n durationSecs: humanJson.durationSecs,\r\n f,\r\n t,\r\n d,\r\n v,\r\n i,\r\n };\r\n return soa;\r\n }\r\n\r\n/** \r\n * Tightly packs the Delta-Timed SoA into a memory-aligned ArrayBuffer.\r\n * \r\n * @reason We explicitly manage endianness via DataView for the 16-bit and 32-bit arrays\r\n * to ensure that a `.rlo` file compiled on an x86 machine (Little Endian) plays flawlessly\r\n * on an ARM or obscure Big-Endian web client. \r\n */\r\nexport function encodeToBinary(\r\n humanJson: RloData,\r\n fullRangeFreq: boolean = false,\r\n): ArrayBuffer {\r\n if (!hasTranspiler) return new ArrayBuffer(0);\r\n const isLittleEndian = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\r\n const soa = encodeToSoA(humanJson, fullRangeFreq);\r\n const N = soa.f.length;\r\n\r\n // Arrays: Time(2*N) + Dur(2*N) + Freq(1*N or 4*N) + Vel(1*N) + Inst(1*N)\r\n const bytesPerNote = fullRangeFreq ? 10 : 7;\r\n const buffer = new ArrayBuffer(12 + bytesPerNote * N);\r\n const view = new DataView(buffer);\r\n\r\n view.setUint8(0, 82);\r\n view.setUint8(1, 76);\r\n view.setUint8(2, 79);\r\n view.setUint8(3, fullRangeFreq ? 70 : 50); // 'RLOF' for Float32, 'RLO2' for Uint8\r\n view.setFloat32(4, soa.durationSecs, true);\r\n view.setUint32(8, N, true);\r\n\r\n if (isLittleEndian) {\r\n new Uint16Array(buffer, 12, N).set(soa.t);\r\n new Uint16Array(buffer, 12 + 2 * N, N).set(soa.d);\r\n if (fullRangeFreq) {\r\n new Float32Array(buffer, 12 + 4 * N, N).set(soa.f as Float32Array);\r\n }\r\n } else {\r\n // Explicitly write multi-byte values as Little-Endian using DataView\r\n // to ensure cross-platform compatibility (avoiding native endianness issues of TypedArrays)\r\n for (let n = 0; n < N; n++) {\r\n view.setUint16(12 + n * 2, soa.t[n], true);\r\n view.setUint16(12 + 2 * N + n * 2, soa.d[n], true);\r\n if (fullRangeFreq) {\r\n view.setFloat32(12 + 4 * N + n * 4, (soa.f as Float32Array)[n], true);\r\n }\r\n }\r\n }\r\n\r\n if (fullRangeFreq) {\r\n new Uint8Array(buffer, 12 + 8 * N, N).set(soa.v);\r\n new Uint8Array(buffer, 12 + 9 * N, N).set(soa.i);\r\n } else {\r\n new Uint8Array(buffer, 12 + 4 * N, N).set(soa.f as Uint8Array);\r\n new Uint8Array(buffer, 12 + 5 * N, N).set(soa.v);\r\n new Uint8Array(buffer, 12 + 6 * N, N).set(soa.i);\r\n }\r\n\r\n return buffer;\r\n }\r\n\r\n/** \r\n * Reconstructs a high-speed runtime object directly from the binary buffer.\r\n * \r\n * @reason During decode, we pre-allocate the exact flat array size `new Array(N * 5)`.\r\n * This guarantees that the V8 engine allocates contiguous memory without dynamic resizing overhead.\r\n * It reconstructs absolute time by accumulating the delta-time ticks to prevent floating-point drift.\r\n */\r\nexport function decodeBinary(buffer: ArrayBuffer): RloData {\r\n if (!hasTranspiler) return { durationSecs: 0, notes: new Float32Array(0) };\r\n const view = new DataView(buffer);\r\n const magic = String.fromCharCode(\r\n view.getUint8(0),\r\n view.getUint8(1),\r\n view.getUint8(2),\r\n view.getUint8(3),\r\n );\r\n if (magic !== \"RLO2\" && magic !== \"RLOF\")\r\n throw new Error(\"Invalid RLO Binary format. Please recompile tracks.\");\r\n const isFullRange = magic === \"RLOF\";\r\n\r\n const durationSecs = view.getFloat32(4, true);\r\n const N = view.getUint32(8, true);\r\n\r\n // Single-byte arrays are endian-agnostic\r\n const f8 = isFullRange ? null : new Uint8Array(buffer, 12 + 4 * N, N);\r\n const v = new Uint8Array(buffer, 12 + (isFullRange ? 8 : 5) * N, N);\r\n const i = new Uint8Array(buffer, 12 + (isFullRange ? 9 : 6) * N, N);\r\n\r\n const notes = new Float32Array(N * 5);\r\n let currentTime = 0;\r\n\r\n for (let n = 0, ptr = 0; n < N; n++, ptr += 5) {\r\n // Read multi-byte values explicitly as Little-Endian\r\n const tn = view.getUint16(12 + n * 2, true);\r\n const dn = view.getUint16(12 + 2 * N + n * 2, true);\r\n const fn = isFullRange\r\n ? view.getFloat32(12 + 4 * N + n * 4, true)\r\n : f8![n];\r\n\r\n currentTime += tn / 1000;\r\n notes[ptr] = isFullRange\r\n ? fn\r\n : fn > 0\r\n ? 440 * Math.pow(2, (fn - 69) / 12)\r\n : 0;\r\n notes[ptr + 1] = currentTime;\r\n notes[ptr + 2] = dn / 1000;\r\n notes[ptr + 3] = v[n] / 255;\r\n notes[ptr + 4] = i[n];\r\n }\r\n\r\n return { durationSecs, notes };\r\n}\r\n","import { ISynthInstrument } from \"./ISynthInstrument.js\";\r\n\r\ndeclare const __ENABLE_MIDI_DEBUG__: boolean;\r\nconst hasMidiDebug = typeof __ENABLE_MIDI_DEBUG__ !== \"undefined\" ? __ENABLE_MIDI_DEBUG__ : false;\r\n\r\n/**\r\n * Handles routing and synthesis of different instrument types.\r\n * \r\n * @reason Separation of Concerns:\r\n * The `RLOCore` is strictly responsible for timing and track decoding.\r\n * This class is strictly responsible for mapping Instrument IDs to their specific\r\n * synthesis classes, applying Key Tracking math, and managing the polyphonic fan-out.\r\n */\r\nexport class Synthesizer {\r\n private _ctx: AudioContext;\r\n private _masterGain: GainNode;\r\n private _instruments: ISynthInstrument[];\r\n\r\n constructor(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n instruments: ISynthInstrument[],\r\n ) {\r\n this._ctx = ctx;\r\n this._masterGain = masterGain;\r\n this._instruments = instruments;\r\n }\r\n\r\n /**\r\n * Routes the note to the correct instrument synthesis method.\r\n */\r\n public _playNote(\r\n instrumentId: number,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n /** Key Tracking: High frequency waveforms carry significantly more perceived energy.\r\n * Gently rolling off the velocity of high notes prevents them from piercing the mix and distorting.\r\n * We also apply a 0.6 global headroom multiplier to prevent 30+ note crescendos from clipping. */\r\n const keyTrackVel = velocity * 0.6 * Math.min(1, 1600 / freq);\r\n\r\n const instrument = this._instruments[instrumentId] || this._instruments[0];\r\n\r\n if (hasMidiDebug) {\r\n console.log(\r\n `[MIDI Debug] Instr ID: ${instrumentId} | Class: ${instrument?.constructor.name || \"Unknown\"} | Freq: ${freq.toFixed(2)}Hz | Vel: ${velocity.toFixed(2)} | Dur: ${duration.toFixed(2)}s | Time: ${time.toFixed(2)}s`,\r\n );\r\n }\r\n\r\n if (instrument) {\r\n instrument._playNote(\r\n this._ctx,\r\n this._masterGain,\r\n time,\r\n freq,\r\n duration,\r\n keyTrackVel,\r\n );\r\n }\r\n }\r\n}\r\n","import { RloData } from \"../types.js\";\r\nimport { ISynthInstrument } from \"../Instruments/ISynthInstrument.js\";\r\nimport { Synthesizer } from \"../Instruments/Synthesizer.js\";\r\n\r\n/**\r\n * Options for playing a compiled RLO sequence.\r\n */\r\nexport interface PlaySequenceOptions {\r\n loop?: boolean;\r\n fadeInTime?: number;\r\n playbackRate?: number;\r\n volume?: number;\r\n}\r\n\r\ndeclare const __ENABLE_WORKER_METRONOME__: boolean;\r\nconst hasWorkerMetronome = typeof __ENABLE_WORKER_METRONOME__ !== \"undefined\" ? __ENABLE_WORKER_METRONOME__ : false;\r\n\r\n/**\r\n * Base Engine Core responsible for the precise scheduling and timing of Web Audio nodes.\r\n * \r\n * @reason Why we use a Worker for the metronome:\r\n * In modern browsers, `setTimeout` or `setInterval` on the main thread is throttled \r\n * to ~1000ms if the user switches browser tabs (to save battery). \r\n * By offloading the timing loop to a Web Worker, we guarantee that background tabs\r\n * continue to schedule audio nodes perfectly at 50ms intervals without skipping a beat.\r\n */\r\nexport class RLOCore {\r\n protected _ctx: AudioContext;\r\n protected _isPlaying: boolean = false;\r\n protected _timer: ReturnType<typeof setTimeout> | null = null;\r\n protected _workerTimer: Worker | null = null;\r\n protected _sequenceId: number = 0;\r\n protected _trkT: number = 0;\r\n protected _trkD: number = 0;\r\n protected _activeNodes: AudioNode[] = [];\r\n protected _volume: number = 0.5;\r\n protected _seekTarget: number | null = null;\r\n\r\n public playbackRate: number = 1.0;\r\n\r\n protected _instrumentMap: ISynthInstrument[];\r\n protected _workerUrl: string | null = null;\r\n\r\n constructor(audioContext: AudioContext, instrumentMap: ISynthInstrument[] = []) {\r\n this._ctx = audioContext;\r\n this._instrumentMap = instrumentMap;\r\n\r\n if (hasWorkerMetronome) {\r\n const blob = new Blob(\r\n [\r\n \"let t=null;self.onmessage=e=>{let d=e.data;if(d=='start'){if(t)clearInterval(t);t=setInterval(()=>self.postMessage('tick'),50)}else if(d=='stop'&&t){clearInterval(t);t=null}};\"\r\n ],\r\n { type: \"application/javascript\" },\r\n );\r\n this._workerUrl = URL.createObjectURL(blob);\r\n this._workerTimer = new Worker(this._workerUrl);\r\n }\r\n }\r\n\r\n protected get _now(): number {\r\n return this._ctx.currentTime;\r\n }\r\n\r\n public setVolume(vol: number): void {\r\n this._volume = vol;\r\n }\r\n\r\n public seek(timeInSeconds: number): void {\r\n if (this._trkD > 0) {\r\n this._seekTarget = Math.max(0, timeInSeconds) % this._trkD;\r\n }\r\n }\r\n\r\n public stop(): void {\r\n this._isPlaying = false;\r\n this._sequenceId++;\r\n if (this._timer) clearTimeout(this._timer);\r\n if (hasWorkerMetronome && this._workerTimer) this._workerTimer.postMessage(\"stop\");\r\n\r\n const nodesToClean = this._activeNodes;\r\n this._activeNodes = [];\r\n\r\n while (nodesToClean.length) {\r\n try { nodesToClean.pop()!.disconnect(); } catch (e) {}\r\n }\r\n }\r\n\r\n public dispose(): void {\r\n this.stop();\r\n if (hasWorkerMetronome && this._workerTimer) {\r\n this._workerTimer.terminate();\r\n this._workerTimer = null;\r\n }\r\n if (hasWorkerMetronome && this._workerUrl) {\r\n URL.revokeObjectURL(this._workerUrl);\r\n this._workerUrl = null;\r\n }\r\n }\r\n\r\n protected _createGain(): GainNode {\r\n return this._ctx.createGain();\r\n }\r\n\r\n protected _applyLinearFade(gain: AudioParam, target: number, time: number): void {\r\n gain.setValueAtTime(time > 0 ? 0 : target, this._now);\r\n if (time > 0) gain.linearRampToValueAtTime(target, this._now + time);\r\n }\r\n\r\n protected _createCompressor(ctx: AudioContext = this._ctx): DynamicsCompressorNode {\r\n const c = ctx.createDynamicsCompressor();\r\n c.threshold.value = -24;\r\n c.knee.value = 12;\r\n c.ratio.value = 8;\r\n c.attack.value = 0.001;\r\n c.release.value = 0.25;\r\n return c;\r\n }\r\n\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n const gain = this._createGain();\r\n this._applyLinearFade(gain.gain, this._volume, fadeInTime);\r\n gain.connect(this._ctx.destination);\r\n this._activeNodes.push(gain);\r\n return { destination: gain };\r\n }\r\n\r\n public playSequence(track: RloData, loopOrOpts: boolean | PlaySequenceOptions = true, oldFadeInTime: number = 0): void {\r\n let loop = true;\r\n let fadeInTime = oldFadeInTime;\r\n if (typeof loopOrOpts === \"object\") {\r\n loop = loopOrOpts.loop ?? true;\r\n fadeInTime = loopOrOpts.fadeInTime ?? 0;\r\n this.playbackRate = loopOrOpts.playbackRate ?? this.playbackRate;\r\n if (loopOrOpts.volume !== undefined) this.setVolume(loopOrOpts.volume);\r\n } else {\r\n loop = loopOrOpts;\r\n }\r\n\r\n this.stop();\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n this._isPlaying = true;\r\n const currentSequenceId = ++this._sequenceId;\r\n this._trkD = track.durationSecs;\r\n\r\n const { destination } = this._createRouting(fadeInTime);\r\n const synthesizer = new Synthesizer(\r\n this._ctx,\r\n destination as GainNode,\r\n this._instrumentMap,\r\n );\r\n\r\n const lookaheadTime = 0.5;\r\n this._trkT = -0.05 * this.playbackRate;\r\n let lastScheduleTime = this._now;\r\n let loopOffsetSecs = 0;\r\n let notePtr = 0;\r\n const notes = track.notes;\r\n const len = notes.length;\r\n\r\n const schedule = () => {\r\n if (!this._isPlaying || this._sequenceId !== currentSequenceId) return;\r\n if (len === 0) return; // Prevent infinite loop on empty tracks\r\n\r\n const currentPhysicalTime = this._now;\r\n const deltaPhysical = currentPhysicalTime - lastScheduleTime;\r\n lastScheduleTime = currentPhysicalTime;\r\n\r\n if (this._seekTarget !== null) {\r\n this._trkT = this._seekTarget;\r\n loopOffsetSecs = 0;\r\n notePtr = 0;\r\n while (notePtr < len && notes[notePtr + 1] < this._seekTarget) {\r\n notePtr += 5;\r\n }\r\n this._seekTarget = null;\r\n \r\n // Duck the volume briefly to hide the 0.5s lookahead buffer overlap\r\n const duckGain = destination as GainNode;\r\n if (duckGain.gain) {\r\n duckGain.gain.cancelScheduledValues(currentPhysicalTime);\r\n duckGain.gain.setValueAtTime(0.001, currentPhysicalTime);\r\n duckGain.gain.exponentialRampToValueAtTime(this._volume, currentPhysicalTime + 0.5);\r\n }\r\n } else {\r\n this._trkT += deltaPhysical * this.playbackRate;\r\n }\r\n\r\n const loopDurationSecs = track.durationSecs;\r\n\r\n while (notePtr < len) {\r\n const noteTrackTime = loopOffsetSecs + notes[notePtr + 1];\r\n\r\n if (noteTrackTime >= this._trkT + lookaheadTime * this.playbackRate) break;\r\n\r\n // The \"Lag Chord\" drop threshold:\r\n // If a thread freeze occurred, drop notes that are more than 150ms in the past\r\n if (this._trkT - noteTrackTime <= 0.15 * this.playbackRate) {\r\n const notePhysicalTime = currentPhysicalTime + Math.max(0, (noteTrackTime - this._trkT) / this.playbackRate);\r\n synthesizer._playNote(notes[notePtr + 4], notePhysicalTime, notes[notePtr], notes[notePtr + 2] / this.playbackRate, notes[notePtr + 3]);\r\n }\r\n notePtr += 5;\r\n }\r\n\r\n if (notePtr >= len) {\r\n if (loop) {\r\n notePtr = 0;\r\n loopOffsetSecs += loopDurationSecs;\r\n schedule();\r\n } else {\r\n if (hasWorkerMetronome && this._workerTimer) this._workerTimer.postMessage(\"stop\");\r\n }\r\n return;\r\n }\r\n if (!hasWorkerMetronome || !this._workerTimer) {\r\n this._timer = setTimeout(schedule, 50);\r\n }\r\n };\r\n if (hasWorkerMetronome && this._workerTimer) {\r\n this._workerTimer.onmessage = () => schedule();\r\n this._workerTimer.postMessage(\"start\");\r\n }\r\n schedule();\r\n }\r\n}\r\n","export type ReverbMode = \"concert\" | \"studio\";\r\n\r\n/**\r\n * Utility class for generating programmatic audio effects.\r\n */\r\nexport class AudioEffects {\r\n private static _cachedConcert: AudioBuffer | null = null;\r\n private static _cachedStudio: AudioBuffer | null = null;\r\n\r\n /**\r\n * Generates a mathematical impulse response for a Convolution Reverb node.\r\n * @param {AudioContext} ctx - The active AudioContext.\r\n * @param {ReverbMode} mode - The type of acoustic space to simulate.\r\n * @returns {AudioBuffer} The synthesized reverb impulse buffer.\r\n */\r\n public static _generateReverb(\r\n ctx: AudioContext,\r\n mode: ReverbMode = \"studio\",\r\n ): AudioBuffer {\r\n if (mode === \"concert\" && this._cachedConcert) return this._cachedConcert;\r\n if (mode === \"studio\" && this._cachedStudio) return this._cachedStudio;\r\n\r\n const isStudio = mode === \"studio\";\r\n const length =\r\n ctx.sampleRate *\r\n (isStudio ? 0.2 : 1.5); /** 0.2s for Studio, 1.5s for Concert */\r\n const decay = isStudio ? 8 : 4; /** Exponential decay factor */\r\n\r\n const impulse = ctx.createBuffer(2, length, ctx.sampleRate);\r\n for (let i = 0; i < 2; i++) {\r\n const channel = impulse.getChannelData(i);\r\n let lastOut = 0;\r\n for (let j = 0; j < length; j++) {\r\n /** Simple lowpass filter to absorb harsh high frequencies in the tail */\r\n const noise = Math.random() * 2 - 1;\r\n lastOut = lastOut + 0.3 * (noise - lastOut);\r\n /** True exponential acoustic decay multiplied by a linear fade to ensure 0 at the tail */\r\n channel[j] =\r\n lastOut * Math.exp(-decay * (j / length)) * (1 - j / length);\r\n }\r\n }\r\n\r\n // Cache the newly generated impulse\r\n return isStudio\r\n ? (this._cachedStudio = impulse)\r\n : (this._cachedConcert = impulse);\r\n }\r\n}\r\n","import { RLOCore, PlaySequenceOptions } from \"../Core/RLOCore.js\";\r\nimport { RloData } from \"../types.js\";\r\nimport { ISynthInstrument } from \"../Instruments/ISynthInstrument.js\";\r\nimport { AudioEffects, ReverbMode } from \"../AudioEffects.js\";\r\nimport { decodeBinary } from \"../RLO-Transpiler.js\";\r\n\r\ndeclare const __ENABLE_MUSIC_PLAYER__: boolean;\r\nconst hasMusicPlayer = typeof __ENABLE_MUSIC_PLAYER__ !== \"undefined\" ? __ENABLE_MUSIC_PLAYER__ : true;\r\n\r\ndeclare const __ENABLE_WORKER_METRONOME__: boolean;\r\nconst hasWorkerMetronome = typeof __ENABLE_WORKER_METRONOME__ !== \"undefined\" ? __ENABLE_WORKER_METRONOME__ : false;\r\n\r\ndeclare const window: any;\r\ndeclare const document: any;\r\n\r\n/**\r\n * A specialized extension of `RLOCore` designed for standalone music playback.\r\n * \r\n * @reason Architecture Separation:\r\n * The base `RLOCore` is extremely lightweight and purely handles scheduling logic.\r\n * `RLOMusicPlayer` adds heavy features like Convolution Reverb routing, URL fetching,\r\n * binary decompression streams, and track caching. By separating these into a derived class,\r\n * JS13k game developers who just want to play simple 1-channel blips don't have to bundle\r\n * the gzip DecompressionStream or Convolution Reverb code.\r\n */\r\nexport class RLOMusicPlayer extends RLOCore {\r\n private _masterGainNode: GainNode | null = null;\r\n private _reverbNode: ConvolverNode | null = null;\r\n private _fxGainNode: GainNode | null = null;\r\n private _trackCacheMap: Map<string, RloData> = new Map();\r\n private _visibilityEventHandler!: () => void;\r\n private _maxCacheSizeLimit: number = 20;\r\n private _currentReverbMode: ReverbMode = \"concert\";\r\n\r\n constructor(audioContext: AudioContext, instrumentMap: ISynthInstrument[] = []) {\r\n super(audioContext, instrumentMap);\r\n if (!hasMusicPlayer) return;\r\n\r\n AudioEffects._generateReverb(this._ctx, \"concert\");\r\n AudioEffects._generateReverb(this._ctx, \"studio\");\r\n\r\n this._visibilityEventHandler = () => {\r\n if (document.hidden) {\r\n this._ctx.suspend();\r\n } else if (this._isPlaying) {\r\n this._ctx.resume();\r\n }\r\n };\r\n\r\n if (typeof document !== \"undefined\" && !hasWorkerMetronome) {\r\n document.addEventListener(\"visibilitychange\", this._visibilityEventHandler);\r\n }\r\n }\r\n\r\n public setReverbMode(mode: ReverbMode): void {\r\n if (!hasMusicPlayer) return;\r\n this._currentReverbMode = mode;\r\n if (this._reverbNode && this._fxGainNode) {\r\n this._reverbNode.buffer = AudioEffects._generateReverb(this._ctx, mode);\r\n this._fxGainNode.gain.setTargetAtTime(mode === \"studio\" ? 0.05 : 0.2, this._now, 0.1);\r\n }\r\n }\r\n\r\n public dispose(): void {\r\n if (!hasMusicPlayer) return super.dispose();\r\n super.dispose();\r\n if (typeof document !== \"undefined\" && !hasWorkerMetronome) {\r\n document.removeEventListener(\"visibilitychange\", this._visibilityEventHandler);\r\n }\r\n this._trackCacheMap.clear();\r\n }\r\n\r\n public setVolume(vol: number): void {\r\n super.setVolume(vol);\r\n if (!hasMusicPlayer) return;\r\n if (this._masterGainNode) {\r\n this._masterGainNode.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n }\r\n\r\n public getCurrentTime(): number {\r\n if (!hasMusicPlayer) return 0;\r\n if (this._trkD === 0 || !this._isPlaying) return 0;\r\n return Math.max(0, this._trkT) % this._trkD;\r\n }\r\n\r\n public getTotalDuration(): number {\r\n if (!hasMusicPlayer) return 0;\r\n return this._trkD;\r\n }\r\n\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n if (!hasMusicPlayer) return super._createRouting(fadeInTime);\r\n this._reverbNode = this._ctx.createConvolver();\r\n this._reverbNode.buffer = AudioEffects._generateReverb(this._ctx, this._currentReverbMode);\r\n this._masterGainNode = this._createGain();\r\n this._activeNodes.push(this._reverbNode, this._masterGainNode);\r\n\r\n this._applyLinearFade(this._masterGainNode.gain, this._volume, fadeInTime);\r\n\r\n this._fxGainNode = this._createGain();\r\n this._fxGainNode.gain.value = this._currentReverbMode === \"studio\" ? 0.05 : 0.2;\r\n this._activeNodes.push(this._fxGainNode);\r\n\r\n const masterFilter = this._ctx.createBiquadFilter();\r\n masterFilter.type = \"lowpass\";\r\n masterFilter.frequency.value = Math.min(this._ctx.sampleRate / 2 - 1, 6500);\r\n this._activeNodes.push(masterFilter);\r\n\r\n const compressor = this._createCompressor();\r\n this._activeNodes.push(compressor);\r\n\r\n this._masterGainNode.connect(masterFilter).connect(compressor).connect(this._ctx.destination);\r\n this._masterGainNode.connect(this._reverbNode).connect(this._fxGainNode).connect(masterFilter);\r\n\r\n return { destination: this._masterGainNode };\r\n }\r\n\r\n public async play(trackUrlOrData: string | RloData, fadeInOrOpts: number | PlaySequenceOptions = 0, oldLoop: boolean = true): Promise<void> {\r\n if (!hasMusicPlayer) return;\r\n let track: RloData;\r\n let fadeInTime = 0;\r\n let optionsObj: PlaySequenceOptions = {};\r\n if (typeof fadeInOrOpts === \"object\") {\r\n fadeInTime = fadeInOrOpts.fadeInTime ?? 0;\r\n optionsObj = fadeInOrOpts;\r\n } else {\r\n fadeInTime = fadeInOrOpts;\r\n optionsObj = { fadeInTime, loop: oldLoop };\r\n }\r\n\r\n if (typeof trackUrlOrData === \"string\") {\r\n if (this._trackCacheMap.has(trackUrlOrData)) {\r\n track = this._trackCacheMap.get(trackUrlOrData)!;\r\n } else {\r\n const response = await fetch(trackUrlOrData);\r\n const hasTranspiler = typeof (window as any).__ENABLE_TRANSPILER__ !== \"undefined\" ? (window as any).__ENABLE_TRANSPILER__ : true;\r\n\r\n if (!hasTranspiler || trackUrlOrData.toLowerCase().endsWith(\".json\")) {\r\n const text = await response.text();\r\n track = JSON.parse(text);\r\n } else {\r\n const rawBuffer = await response.arrayBuffer();\r\n const view = new DataView(rawBuffer);\r\n const isDecompressed = view.byteLength >= 3 && view.getUint8(0) === 82 && view.getUint8(1) === 76 && view.getUint8(2) === 79;\r\n\r\n if (isDecompressed) {\r\n track = decodeBinary(rawBuffer);\r\n } else {\r\n const ds = new (window as any).DecompressionStream(\"gzip\");\r\n const writer = ds.writable.getWriter();\r\n writer.write(rawBuffer);\r\n writer.close();\r\n track = decodeBinary(await new Response(ds.readable).arrayBuffer());\r\n }\r\n }\r\n this._trackCacheMap.set(trackUrlOrData, track);\r\n if (this._trackCacheMap.size > this._maxCacheSizeLimit) {\r\n const firstKey = this._trackCacheMap.keys().next().value;\r\n if (firstKey) this._trackCacheMap.delete(firstKey);\r\n }\r\n }\r\n } else {\r\n track = trackUrlOrData;\r\n }\r\n this.playSequence(track, optionsObj);\r\n }\r\n\r\n public stop(): void {\r\n if (!hasMusicPlayer) return super.stop();\r\n if (this._masterGainNode) {\r\n const now = this._now;\r\n this._masterGainNode.gain.cancelScheduledValues(now);\r\n this._masterGainNode.gain.setValueAtTime(0, now);\r\n this._masterGainNode = null;\r\n this._fxGainNode = null;\r\n this._reverbNode = null;\r\n }\r\n super.stop();\r\n }\r\n}\r\n","import { RLOCore, PlaySequenceOptions } from \"../Core/RLOCore.js\";\r\nimport { Note } from \"../Core/AudioMath.js\";\r\nimport { RloData } from \"../types.js\";\r\nimport { ISynthInstrument } from \"../Instruments/ISynthInstrument.js\";\r\nimport { Synthesizer } from \"../Instruments/Synthesizer.js\";\r\n\r\ndeclare const __ENABLE_GAME_ENGINE__: boolean;\r\nconst hasGameEngine = typeof __ENABLE_GAME_ENGINE__ !== \"undefined\" ? __ENABLE_GAME_ENGINE__ : true;\r\n\r\nexport interface SFXOptions {\r\n velocity?: number;\r\n timeOffset?: number;\r\n}\r\n\r\n/**\r\n * Advanced audio engine designed specifically for video games (like JS13k entries).\r\n * \r\n * @reason Architectural Separation:\r\n * This class completely isolates the Music bus from the SFX (Sound Effects) bus.\r\n * Games require distinct volume sliders for Music vs SFX. By instantiating a dedicated\r\n * internal `Synthesizer` explicitly for SFX, we can route all UI clicks, explosions, \r\n * and jump sounds through the `_sfxRoutingGain` without disrupting the background \r\n * music's master volume or looping sequence logic.\r\n */\r\nexport class RLOGameEngine extends RLOCore {\r\n private _gameMasterGain!: GainNode;\r\n private _sfxRoutingGain!: GainNode;\r\n private _musicRoutingGain!: GainNode;\r\n private _sfxInternalSynthesizer!: Synthesizer;\r\n\r\n constructor(audioContext: AudioContext, instrumentMap: ISynthInstrument[] = []) {\r\n super(audioContext, instrumentMap);\r\n if (!hasGameEngine) return;\r\n\r\n this._gameMasterGain = this._createGain();\r\n this._gameMasterGain.gain.value = this._volume;\r\n\r\n const compressor = this._createCompressor();\r\n\r\n this._gameMasterGain.connect(compressor).connect(this._ctx.destination);\r\n\r\n this._musicRoutingGain = this._createGain();\r\n this._musicRoutingGain.connect(this._gameMasterGain);\r\n\r\n this._sfxRoutingGain = this._createGain();\r\n this._sfxRoutingGain.connect(this._gameMasterGain);\r\n this._sfxInternalSynthesizer = new Synthesizer(this._ctx, this._sfxRoutingGain, this._instrumentMap);\r\n }\r\n\r\n public setVolume(vol: number): void {\r\n super.setVolume(vol);\r\n if (!hasGameEngine) return;\r\n this._gameMasterGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n public setMusicVolume(vol: number): void {\r\n if (!hasGameEngine) return;\r\n this._musicRoutingGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n public setSFXVolume(vol: number): void {\r\n if (!hasGameEngine) return;\r\n this._sfxRoutingGain.gain.setTargetAtTime(vol, this._now, 0.1);\r\n }\r\n\r\n protected _createRouting(fadeInTime: number = 0): { destination: AudioNode } {\r\n if (!hasGameEngine) return super._createRouting(fadeInTime);\r\n const musicGain = this._createGain();\r\n musicGain.connect(this._musicRoutingGain);\r\n this._activeNodes.push(musicGain);\r\n\r\n this._applyLinearFade(musicGain.gain, 1, fadeInTime);\r\n\r\n return { destination: musicGain };\r\n }\r\n\r\n public playSFX(instrumentId: number, freqOrNote: number | string, duration: number, velocityOrOpts: number | SFXOptions = 1.0, oldTimeOffset: number = 0) {\r\n if (!hasGameEngine) return;\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n let velocity = 1.0;\r\n let timeOffset = oldTimeOffset;\r\n if (typeof velocityOrOpts === \"object\") {\r\n velocity = velocityOrOpts.velocity ?? 1.0;\r\n timeOffset = velocityOrOpts.timeOffset ?? 0;\r\n } else {\r\n velocity = velocityOrOpts;\r\n }\r\n this._sfxInternalSynthesizer._playNote(instrumentId, this._now + timeOffset, Note(freqOrNote), duration, velocity);\r\n }\r\n\r\n public playSFXSequence(track: RloData, timeOffset: number = 0): void {\r\n if (!hasGameEngine) return;\r\n if (this._ctx.state === \"suspended\") this._ctx.resume();\r\n\r\n const start = this._now + timeOffset;\r\n const n = track.notes;\r\n const len = n.length;\r\n\r\n for (let i = 0; i < len; i += 5) {\r\n this._sfxInternalSynthesizer._playNote(n[i + 4], start + n[i + 1], n[i], n[i + 2], n[i + 3]);\r\n }\r\n }\r\n\r\n public playMusic(track: RloData, loopOrOpts: boolean | PlaySequenceOptions = true, oldFadeInTime: number = 0): void {\r\n if (!hasGameEngine) return;\r\n let opts: boolean | PlaySequenceOptions = loopOrOpts;\r\n if (typeof loopOrOpts === \"object\" && loopOrOpts.volume !== undefined) {\r\n this.setMusicVolume(loopOrOpts.volume);\r\n opts = { ...loopOrOpts };\r\n delete (opts as PlaySequenceOptions).volume;\r\n }\r\n this.playSequence(track, opts, oldFadeInTime);\r\n }\r\n\r\n public stopMusic(): void {\r\n super.stop();\r\n }\r\n}\r\n","export interface ADSREnvelope {\r\n attack?: number;\r\n decay?: number;\r\n sustain?: number;\r\n release?: number;\r\n peak?: number;\r\n}\r\n\r\n/**\r\n * Mathematically applies an Attack-Decay-Sustain-Release (ADSR) volume envelope to an AudioParam.\r\n * \r\n * @reason Why we use explicit `setValueAtTime` and `linearRampToValueAtTime`:\r\n * Web Audio nodes often suffer from clicking/popping if values jump instantaneously.\r\n * By using linear ramps, we ensure smooth zero-crossing transitions. Furthermore, \r\n * the logic elegantly handles edge-cases where the note duration is shorter than \r\n * the Attack or Decay phase by dynamically calculating partial peaks and \r\n * preemptively jumping to the Release phase, preventing sustained hanging notes.\r\n */\r\nexport function applyEnvelope(\r\n gainParam: AudioParam,\r\n now: number,\r\n duration: number,\r\n opts: ADSREnvelope,\r\n): void {\r\n const a = opts.attack ?? 0.05;\r\n const d = opts.decay ?? 0.1;\r\n const s = opts.sustain ?? 0.8;\r\n const r = opts.release ?? 0.1;\r\n const peak = opts.peak ?? 1.0;\r\n\r\n gainParam.setValueAtTime(0, now);\r\n const realDur = Math.max(0, duration);\r\n\r\n if (realDur <= a) {\r\n const partialPeak = peak * (realDur / (a || 1));\r\n gainParam.linearRampToValueAtTime(partialPeak, now + realDur * 0.5);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n } else if (realDur <= a + d) {\r\n gainParam.linearRampToValueAtTime(peak, now + a);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n } else {\r\n gainParam.linearRampToValueAtTime(peak, now + a);\r\n gainParam.linearRampToValueAtTime(peak * s, now + a + d);\r\n const releaseStart = Math.max(now + a + d, now + realDur - r);\r\n gainParam.setValueAtTime(peak * s, releaseStart);\r\n gainParam.linearRampToValueAtTime(0, now + realDur);\r\n }\r\n}\r\n\r\ndeclare const __ENABLE_NOTE_PARSER__: boolean;\r\nconst hasNoteParser = typeof __ENABLE_NOTE_PARSER__ !== \"undefined\" ? __ENABLE_NOTE_PARSER__ : true;\r\n\r\n/**\r\n * Converts a scientific pitch notation string (e.g., \"C4\", \"F#3\") to frequency in Hz.\r\n * \r\n * @reason Why this is included but conditionally compiled:\r\n * This parser is highly convenient for developers writing sequences manually via the API,\r\n * allowing `Note(\"C4\")` instead of `261.63`. However, the transpiler strips string notes \r\n * during binary compilation, so we wrap this in `__ENABLE_NOTE_PARSER__` to allow Rollup \r\n * to entirely remove the Regex from the JS13K build if unused.\r\n */\r\nexport function Note(pitch: string | number): number {\r\n if (typeof pitch === \"number\") return pitch;\r\n if (!hasNoteParser) return 0;\r\n const match = pitch.match(/^([a-gA-G])([#b]?)(\\d)$/);\r\n if (!match) return 0;\r\n const offsets: Record<string, number> = { C: -9, D: -7, E: -5, F: -4, G: -2, A: 0, B: 2 };\r\n const [, note, accidental, octave] = match;\r\n let semitone = offsets[note.toUpperCase()];\r\n if (accidental === \"#\") semitone++;\r\n if (accidental === \"b\") semitone--;\r\n semitone += (parseInt(octave, 10) - 4) * 12;\r\n return Number((440 * Math.pow(2, semitone / 12)).toFixed(2));\r\n}\r\n","import { ISynthInstrument } from \"../Instruments/ISynthInstrument.js\";\r\n\r\n/**\r\n * Helper synth that produces zero sound, used as a fallback or placeholder.\r\n */\r\nexport const SilentSynth: ISynthInstrument = {\r\n _playNote: () => {},\r\n};\r\n\r\n/**\r\n * Creates a raw mapping between explicit MIDI Program IDs (0-128) and Synthesizer instances.\r\n * \r\n * @reason Used primarily by the `crush` JS13k build where only 2 or 3 synths are bundled,\r\n * avoiding the need for complex fuzzy-matching loops.\r\n */\r\nexport function createDirectMap(assignments: { synth: ISynthInstrument; ids: number[] }[]): ISynthInstrument[] {\r\n const mapArray = new Array(129).fill(null);\r\n assignments.forEach((a) => {\r\n a.ids.forEach((id) => (mapArray[id] = a.synth));\r\n });\r\n return mapArray;\r\n}\r\n\r\n/**\r\n * Populates a 128-slot Array mapping MIDI Program IDs to Synthesizer instances.\r\n * \r\n * @reason The NPM library comes with 16 default synths. Standard MIDI files might\r\n * request Program ID 44 (Contrabass), but we only have `StringSynth` mapped to 40-55.\r\n * This function uses a fuzzy \"closest neighbor\" algorithm to automatically fill\r\n * any missing gaps (e.g. mapping ID 44 to the nearest available synth ID). This guarantees\r\n * that imported MIDI files will always produce sound, even if the user hasn't explicitly\r\n * instantiated all 128 GM instruments.\r\n */\r\nexport function createInstrumentMap(modules: { synth: ISynthInstrument; start: number; end: number }[]): ISynthInstrument[] {\r\n const mapArray = new Array(129).fill(null);\r\n modules.forEach((m) => {\r\n for (let i = m.start; i <= m.end; i++) mapArray[i] = m.synth;\r\n });\r\n\r\n for (let i = 0; i < 129; i++) {\r\n if (mapArray[i] === null) {\r\n let closest = null;\r\n let minDiff = Infinity;\r\n for (let j = 0; j < 129; j++) {\r\n if (mapArray[j] !== null) {\r\n const diff = Math.abs(i - j);\r\n if (diff < minDiff) {\r\n minDiff = diff;\r\n closest = mapArray[j];\r\n }\r\n }\r\n }\r\n mapArray[i] = closest;\r\n }\r\n }\r\n return mapArray;\r\n}\r\n\r\nexport function extendInstrumentMap(baseMap: ISynthInstrument[], overrides: { synth: ISynthInstrument; start: number; end: number }[]): ISynthInstrument[] {\r\n const newMap = [...baseMap];\r\n overrides.forEach((m) => {\r\n for (let i = m.start; i <= m.end; i++) newMap[i] = m.synth;\r\n });\r\n return newMap;\r\n}\r\n","import { ISynthInstrument } from \"./ISynthInstrument.js\";\r\n\r\ndeclare const __ENABLE_STRICT_GC__: boolean;\r\nexport const hasStrictGC =\r\n typeof __ENABLE_STRICT_GC__ !== \"undefined\" ? __ENABLE_STRICT_GC__ : true;\r\n\r\nexport type Osc = \"sine\" | \"square\" | \"sawtooth\" | \"triangle\";\r\nexport type Filter = \"lowpass\" | \"highpass\" | \"bandpass\";\r\n\r\nexport abstract class CoreSynthBase implements ISynthInstrument {\r\n public abstract _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void;\r\n\r\n public _createOscillator(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n dest?: AudioNode | AudioParam,\r\n ): OscillatorNode {\r\n const o = ctx.createOscillator();\r\n o.type = type;\r\n if (freq) o.frequency.value = Math.min(22000, freq);\r\n if (dest) o.connect(dest as any);\r\n return o;\r\n }\r\n public _createGain(\r\n ctx: AudioContext,\r\n val: number,\r\n dest?: AudioNode | AudioParam,\r\n ): GainNode {\r\n const g = ctx.createGain();\r\n g.gain.value = val;\r\n if (dest) g.connect(dest as any);\r\n return g;\r\n }\r\n public _createFilter(ctx: AudioContext, type: Filter): BiquadFilterNode {\r\n const f = ctx.createBiquadFilter();\r\n f.type = type;\r\n return f;\r\n }\r\n public _createStereoPanner(\r\n ctx: AudioContext,\r\n val: number,\r\n dest?: AudioNode,\r\n ): StereoPannerNode {\r\n const p = ctx.createStereoPanner();\r\n p.pan.value = val;\r\n if (dest) p.connect(dest);\r\n return p;\r\n }\r\n public _scheduleNodeStartStop(t: number, s: number, ...n: AudioScheduledSourceNode[]): void {\r\n n.forEach((x) => {\r\n x.start(t);\r\n x.stop(s);\r\n });\r\n }\r\n public _setValueAtTime(p: AudioParam, v: number, t: number): void {\r\n p.setValueAtTime(Math.min(22000, v), t);\r\n }\r\n public _linearRampToValue(p: AudioParam, v: number, t: number): void {\r\n p.linearRampToValueAtTime(Math.min(22000, v), t);\r\n }\r\n public _exponentialRampToValue(p: AudioParam, v: number, t: number): void {\r\n p.exponentialRampToValueAtTime(Math.min(22000, v), t);\r\n }\r\n\r\n public _createTransient(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n dest: AudioNode,\r\n time: number,\r\n peak: number,\r\n dur: number,\r\n atk: number = 0,\r\n ): void {\r\n const g = this._createGain(ctx, 0, dest);\r\n this._setValueAtTime(g.gain, atk > 0 ? 0 : peak, time);\r\n if (atk > 0) this._linearRampToValue(g.gain, peak, time + atk);\r\n this._exponentialRampToValue(g.gain, 0.001, time + dur);\r\n this._scheduleNodeStartStop(time, time + dur, this._createOscillator(ctx, type, freq, g));\r\n }\r\n public _createFilterSweep(\r\n ctx: AudioContext,\r\n type: Filter,\r\n f1: number,\r\n f2: number,\r\n t1: number,\r\n dur: number,\r\n ): BiquadFilterNode {\r\n const f = this._createFilter(ctx, type);\r\n this._setValueAtTime(f.frequency, f1, t1);\r\n this._exponentialRampToValue(f.frequency, f2, t1 + dur);\r\n return f;\r\n }\r\n public _createStereoOscillator(\r\n ctx: AudioContext,\r\n type: Osc,\r\n freq: number,\r\n detune: number,\r\n pan: number,\r\n dest: AudioNode,\r\n ): [OscillatorNode, OscillatorNode] {\r\n return [\r\n this._createOscillator(ctx, type, freq, this._createStereoPanner(ctx, -pan, dest)),\r\n this._createOscillator(ctx, type, freq * detune, this._createStereoPanner(ctx, pan, dest)),\r\n ];\r\n }\r\n public _createLFO(\r\n ctx: AudioContext,\r\n freq: number,\r\n depth: number,\r\n time: number,\r\n fadeIn: number,\r\n stopTime: number,\r\n dest: AudioNode | AudioParam,\r\n delay: number = 0,\r\n ): GainNode {\r\n const g = this._createGain(ctx, 0, dest);\r\n this._setValueAtTime(g.gain, 0, time);\r\n if (delay > 0) this._setValueAtTime(g.gain, 0, time + delay);\r\n this._linearRampToValue(g.gain, depth, time + delay + fadeIn);\r\n this._scheduleNodeStartStop(time, stopTime, this._createOscillator(ctx, \"sine\", freq, g));\r\n return g;\r\n }\r\n\r\n /**\r\n * Schedules a delayed garbage collection using a native C++ audio thread.\r\n * \r\n * @reason Why we use a dummy OscillatorNode instead of setTimeout:\r\n * The JS event loop is inherently jittery and subject to GC pauses and tab throttling.\r\n * By scheduling a silent OscillatorNode with a precise `.stop(stopTime)`, we leverage\r\n * the Web Audio API's C++ audio thread to trigger the `onended` callback precisely at the sample\r\n * boundary. This guarantees that `disconnect()` is called on exhausted nodes exactly when\r\n * they finish decaying, preventing memory leaks (stray disconnected nodes) without any JS timing overhead.\r\n * \r\n * @param ctx The AudioContext.\r\n * @param time The start time of the GC lifecycle.\r\n * @param stopTime The exact time when the audio nodes should be completely unlinked from the graph.\r\n * @param nodes The nodes to disconnect.\r\n */\r\n public _scheduleNodeDisposal(\r\n ctx: AudioContext,\r\n time: number,\r\n stopTime: number,\r\n ...nodes: AudioNode[]\r\n ): void {\r\n if (hasStrictGC) {\r\n const gcOsc = this._createOscillator(ctx, \"sine\", 0);\r\n gcOsc.onended = () => {\r\n nodes.forEach((n) => {\r\n try {\r\n if (n && typeof n.disconnect === \"function\") {\r\n n.disconnect();\r\n }\r\n } catch (e) {\r\n // Safe swallow: Node may have been externally disconnected by Game Engine routing.\r\n }\r\n });\r\n };\r\n gcOsc.start(time);\r\n gcOsc.stop(stopTime);\r\n }\r\n }\r\n}","import { CoreSynthBase, hasStrictGC } from \"../CoreSynthBase.js\";\r\n\r\nexport type DecayCfg = { _peakVelocity: number; _attackTimeSeconds: number; _decayTimeSeconds: number; _maxDurationSeconds: number };\r\n\r\n/**\r\n * Abstract base class for plucked, struck, and decaying synthesizers (e.g. Pianos, Guitars, Marimbas).\r\n * \r\n * @reason Physics Simulation:\r\n * Unlike Analog instruments that hold their peak volume as long as a key is pressed,\r\n * physical instruments like Guitars or Pianos immediately begin decaying the moment they are struck.\r\n * This class abstracts the mathematical envelope necessary to simulate that physical decay, \r\n * including a hard `maxDurationSeconds` limit to prevent infinite resonance loops from \r\n * leaking memory if a MIDI file passes a malformed 60-second note duration.\r\n */\r\nexport abstract class DecaySynthBase extends CoreSynthBase {\r\n protected _envelopeConfig: DecayCfg = { _peakVelocity: 0.5, _attackTimeSeconds: 0.02, _decayTimeSeconds: 0.2, _maxDurationSeconds: 4.0 };\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = ctx.createGain();\r\n\r\n const c = this._getEnvelopeConfig();\r\n const peakVol = Math.max(0.001, velocity * c._peakVelocity);\r\n\r\n /** Physical strings/mallets stop vibrating quickly. Protects against stuck MIDI notes. */\r\n const safeDuration = Math.max(0.02, Math.min(duration, c._maxDurationSeconds));\r\n\r\n this._setValueAtTime(gain.gain, 0, time);\r\n this._linearRampToValue(gain.gain, peakVol, time + c._attackTimeSeconds);\r\n\r\n this._applyDecay(gain.gain, peakVol, time, c._attackTimeSeconds, safeDuration, c._decayTimeSeconds);\r\n\r\n /** Pad the oscillator stop time slightly past the volume decay to prevent digital clicking */\r\n const stopTime = time + safeDuration + c._decayTimeSeconds + 0.1;\r\n\r\n const output = this._setupSynthesis(\r\n ctx,\r\n masterGain,\r\n gain,\r\n time,\r\n freq,\r\n velocity,\r\n safeDuration,\r\n stopTime,\r\n );\r\n\r\n const finalNode = output || gain;\r\n finalNode.connect(masterGain);\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, stopTime + 2.0, finalNode);\r\n }\r\n\r\n protected _getEnvelopeConfig(): DecayCfg {\r\n return this._envelopeConfig;\r\n }\r\n\r\n /** Override this for complex envelopes (like electric guitar compression) */\r\n protected _applyDecay(\r\n gainParam: AudioParam,\r\n peakVol: number,\r\n time: number,\r\n attack: number,\r\n safeDuration: number,\r\n decayTail: number,\r\n ): void {\r\n this._exponentialRampToValue(gainParam, 0.001, time + safeDuration + decayTail);\r\n }\r\n\r\n /**\r\n * Set up the specific oscillators and filters for this instrument.\r\n */\r\n protected abstract _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void;\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Piano and similar percussive-melodic instruments.\r\n */\r\n/**\r\n * Simulates a piano using a complex decay envelope, subtle detuning for string realism, and a lowpass filter that closes over time.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class PianoSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.8, _attackTimeSeconds: 0.015, _decayTimeSeconds: 0.1, _maxDurationSeconds: 5.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Key-tracking the filter ensures high notes aren't artificially muffled or phase-distorted. Capped at Nyquist. */\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n freq + 800 + velocity * 1000,\r\n freq + 200,\r\n time,\r\n Math.min(safeDuration, 1.0),\r\n );\r\n const osc1 = this._createOscillator(ctx, \"triangle\", freq, gain);\r\n\r\n /** Slight inharmonicity stretching, strictly capped below Nyquist to prevent digital aliasing */\r\n const overtoneGain = this._createGain(ctx, 0);\r\n const osc2 = this._createOscillator(ctx, \"sine\", freq * 2.003, overtoneGain);\r\n const osc3 = this._createOscillator(ctx, \"sine\", freq * 3.007, overtoneGain);\r\n\r\n /** Dynamically pan lower keys to the left ear, and higher keys to the right ear */\r\n const panner = this._createStereoPanner(\r\n ctx,\r\n Math.max(-0.8, Math.min(0.8, (freq - 261.6) / 800)),\r\n );\r\n\r\n /** Sympathetic string resonance: metallic clangs decay much faster than the fundamental */\r\n this._setValueAtTime(overtoneGain.gain, 0, time);\r\n this._linearRampToValue(overtoneGain.gain, Math.max(0.001, velocity * 0.15), time + 0.01);\r\n this._exponentialRampToValue(overtoneGain.gain, 0.001, time + Math.min(safeDuration, 0.5));\r\n overtoneGain.connect(panner);\r\n\r\n /** Mechanical Hammer Thump: the physical impact of the wooden hammer on the strings */\r\n this._createTransient(\r\n ctx,\r\n \"sine\",\r\n 60,\r\n panner,\r\n time,\r\n Math.max(0.001, velocity * 0.4),\r\n 0.05,\r\n 0.005,\r\n );\r\n\r\n gain.connect(panner).connect(filter);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2, osc3);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Chromatic Percussion (Bells, Marimba, Vibraphone).\r\n * Characterized by a pure tone with a very fast attack and immediate decay.\r\n */\r\n/**\r\n * Emulates struck melodic instruments like a Glockenspiel or Marimba using rapid decay envelopes and metallic overtones.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class ChromaticPercussionSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.7, _attackTimeSeconds: 0.005, _decayTimeSeconds: 0.5, _maxDurationSeconds: 6.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"sine\", 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 1.1, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.02);\r\n\r\n const overtoneGain = this._createGain(ctx, 0, masterGain);\r\n this._setValueAtTime(overtoneGain.gain, Math.max(0.001, velocity * 0.25), time);\r\n this._exponentialRampToValue(overtoneGain.gain, 0.001, time + safeDuration);\r\n const overtone = this._createOscillator(ctx, \"sine\", freq * 2.76, overtoneGain);\r\n\r\n overtoneGain.connect(masterGain);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc, overtone);\r\n }\r\n}\r\n","import { CoreSynthBase, hasStrictGC } from \"../CoreSynthBase.js\";\r\n\r\nexport type AnalogCfg = { _peakVelocity: number; _attackTimeSeconds: number; _releaseTimeSeconds: number; _maxDurationSeconds?: number };\r\n\r\n/**\r\n * Synthesizer instrument implementation.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n * \r\n * @reason Separation of Sustained vs Decaying Physics:\r\n * Synthesizers like an Organ will sustain at peak volume infinitely as long as the key is held,\r\n * whereas a Piano will physically decay to silence even if the key remains held down. \r\n * This base class encapsulates the mathematical ADSR envelope logic specifically for \r\n * infinite-sustain physics, ensuring derived classes only need to define the timbre (Oscillators/Filters).\r\n */\r\nexport abstract class AnalogSynthBase extends CoreSynthBase {\r\n protected _envelopeConfig: AnalogCfg = { _peakVelocity: 0.5, _attackTimeSeconds: 0.05, _releaseTimeSeconds: 0.1, _maxDurationSeconds: 10.0 };\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = ctx.createGain();\r\n\r\n const c = this._getEnvelopeConfig(duration);\r\n const peakVol = Math.max(0.001, velocity * c._peakVelocity);\r\n const safeDuration = c._maxDurationSeconds ? Math.min(duration, c._maxDurationSeconds) : duration;\r\n\r\n this._setValueAtTime(gain.gain, 0, time);\r\n this._linearRampToValue(gain.gain, peakVol, time + c._attackTimeSeconds);\r\n\r\n const sustainTime = Math.max(c._attackTimeSeconds, safeDuration);\r\n this._setValueAtTime(gain.gain, peakVol, time + sustainTime);\r\n this._linearRampToValue(gain.gain, 0.001, time + sustainTime + c._releaseTimeSeconds);\r\n\r\n const stopTime = time + sustainTime + c._releaseTimeSeconds;\r\n\r\n const output = this._setupSynthesis(\r\n ctx,\r\n gain,\r\n time,\r\n freq,\r\n velocity,\r\n sustainTime,\r\n c._releaseTimeSeconds,\r\n stopTime,\r\n );\r\n\r\n const finalNode = output || gain;\r\n finalNode.connect(masterGain);\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, stopTime + 0.1, finalNode);\r\n }\r\n\r\n protected _getEnvelopeConfig(_decayTimeSeconds: number): AnalogCfg {\r\n return this._envelopeConfig;\r\n }\r\n\r\n /**\r\n * Set up the specific oscillators and filters for this instrument.\r\n * You must start() and stop() your own oscillators.\r\n * @returns The final audio node in the chain to connect to the master mix. If omitted, the base envelope gain is used.\r\n */\r\n protected abstract _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void;\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Organs using additive sine waves.\r\n */\r\n/**\r\n * Simulates a tonewheel organ (like a Hammond B3) by using additive synthesis of sine waves at harmonic intervals.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class OrganSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.4, _attackTimeSeconds: 0.01, _releaseTimeSeconds: 0.05 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc1 = this._createOscillator(ctx, \"sine\", freq, gain);\r\n const gain2 = this._createGain(ctx, 0.5, gain);\r\n const osc2 = this._createOscillator(ctx, \"sine\", freq * 2, gain2);\r\n const gain3 = this._createGain(ctx, 0.25, gain);\r\n const osc3 = this._createOscillator(ctx, \"sine\", freq * 3, gain3);\r\n\r\n const rotaryNode = this._createGain(ctx, 0.7);\r\n this._createLFO(ctx, 6.5, 0.3, time, 0, stopTime, rotaryNode.gain);\r\n\r\n gain.connect(rotaryNode);\r\n\r\n this._createTransient(\r\n ctx,\r\n \"square\",\r\n 4000,\r\n rotaryNode,\r\n time,\r\n Math.max(0.001, velocity * 0.1),\r\n 0.015,\r\n );\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2, osc3);\r\n\r\n return rotaryNode;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Acoustic Guitars using a plucked sawtooth.\r\n */\r\n/**\r\n * Simulates an acoustic guitar pluck using the Karplus-Strong algorithm or filtered sawtooth impulses.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class GuitarSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.6, _attackTimeSeconds: 0.02, _decayTimeSeconds: 0.2, _maxDurationSeconds: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Bright attack that quickly muffles as the acoustic string loses kinetic energy */\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n 2000 + velocity * 1000,\r\n 200,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const osc = this._createOscillator(ctx, \"sawtooth\", 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 1.02, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.05);\r\n\r\n gain.connect(filter);\r\n\r\n /** Plectrum Pluck: the sharp, plastic click of a pick striking a steel string */\r\n this._createTransient(\r\n ctx,\r\n \"square\",\r\n 3500,\r\n masterGain,\r\n time,\r\n Math.max(0.001, velocity * 0.25),\r\n 0.015,\r\n );\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Electric and Distorted Guitars.\r\n */\r\n/**\r\n * Simulates a distorted electric guitar using a sawtooth wave run through heavy overdrive and bandpass filtering.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class ElectricGuitarSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.5, _attackTimeSeconds: 0.02, _decayTimeSeconds: 0.2, _maxDurationSeconds: 4.0 };\r\n\r\n protected _applyDecay(\r\n gainParam: AudioParam,\r\n peakVol: number,\r\n time: number,\r\n attack: number,\r\n safeDuration: number,\r\n decayTail: number,\r\n ): void {\r\n /** Compressed sustain mimicking an electric guitar amp */\r\n this._exponentialRampToValue(\r\n gainParam,\r\n Math.max(0.001, peakVol * 0.4),\r\n time + Math.min(0.5, safeDuration),\r\n );\r\n this._exponentialRampToValue(gainParam, 0.001, time + safeDuration + decayTail);\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n 2500 + velocity * 1500,\r\n 600,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const [osc, osc2] = this._createStereoOscillator(ctx, \"sawtooth\", 0, 1, 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 1.02, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.05);\r\n this._setValueAtTime(osc2.frequency, freq * 1.022, time);\r\n this._exponentialRampToValue(osc2.frequency, freq * 1.002, time + 0.05);\r\n\r\n const vibrato = this._createLFO(\r\n ctx,\r\n 5.0,\r\n freq * 0.015,\r\n time,\r\n 0.2,\r\n stopTime,\r\n osc.frequency,\r\n 0.4,\r\n );\r\n vibrato.connect(osc2.frequency);\r\n\r\n gain.connect(filter);\r\n\r\n /** Heavy plectrum attack */\r\n this._createTransient(\r\n ctx,\r\n \"square\",\r\n 3500,\r\n masterGain,\r\n time,\r\n Math.max(0.001, velocity * 0.25),\r\n 0.015,\r\n );\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { DecaySynthBase } from \"../Decay/DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for deep Bass instruments using sawtooth waves.\r\n */\r\n/**\r\n * Synthesizes a deep, resonant bass tone using a lowpass-filtered sawtooth wave. Perfect for foundational low-end frequencies.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class BassSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.8, _attackTimeSeconds: 0.05, _decayTimeSeconds: 0.1, _maxDurationSeconds: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Deep envelope sweep for punchy, muffled bass attack. Capped safely below Nyquist. */\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n 300 + velocity * 500,\r\n 100,\r\n time,\r\n safeDuration,\r\n );\r\n\r\n const osc = this._createOscillator(ctx, \"sawtooth\", 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 0.92, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.04);\r\n\r\n const subGain = this._createGain(ctx, 0.6, gain);\r\n const subOsc = this._createOscillator(ctx, \"sine\", 0, subGain);\r\n this._setValueAtTime(subOsc.frequency, (freq / 2) * 0.92, time);\r\n this._exponentialRampToValue(subOsc.frequency, freq / 2, time + 0.04);\r\n\r\n gain.connect(filter);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc, subOsc);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for String and Pad instruments using detuned oscillators.\r\n */\r\nexport class StringSynth extends AnalogSynthBase {\r\n protected _cfg(d: number): { v: number; a: number; r: number } {\r\n return { v: 0.3, a: d < 0.4 ? 0.05 : 0.2, r: d < 0.4 ? 0.1 : 0.5 };\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const [osc1, osc2] = this._createStereoOscillator(\r\n ctx,\r\n \"sawtooth\",\r\n freq,\r\n 1.005,\r\n 0.6,\r\n gain,\r\n );\r\n\r\n const lfo = this._createLFO(\r\n ctx,\r\n 4.5,\r\n freq * 0.012,\r\n time,\r\n 0.3,\r\n stopTime,\r\n osc1.frequency,\r\n );\r\n lfo.connect(osc2.frequency);\r\n\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n freq + 1200 + velocity * 1000,\r\n freq + 800,\r\n time,\r\n sustainTime + releaseTime,\r\n );\r\n\r\n gain.connect(filter);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"../Analog/AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Brass and Wind instruments with a slow filter envelope.\r\n */\r\n/**\r\n * Simulates a brass instrument (e.g. Trumpet/Trombone) using a sawtooth wave and an envelope-driven lowpass filter to mimic breath pressure.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class BrassSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.5, _attackTimeSeconds: 0.1, _releaseTimeSeconds: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"square\", 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 0.95, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.05);\r\n\r\n const blareGain = this._createGain(ctx, 0, gain);\r\n this._setValueAtTime(blareGain.gain, 0, time);\r\n this._linearRampToValue(blareGain.gain, Math.max(0.001, velocity * 0.25), time + 0.05);\r\n this._exponentialRampToValue(blareGain.gain, 0.001, time + 0.2);\r\n const blare = this._createOscillator(ctx, \"sawtooth\", freq * 2, blareGain);\r\n\r\n const filter = this._createFilter(ctx, \"lowpass\");\r\n this._setValueAtTime(filter.frequency, freq + 400, time);\r\n this._linearRampToValue(filter.frequency, freq + 1500 + velocity * 1000, time + 0.1);\r\n this._exponentialRampToValue(filter.frequency, freq + 400, time + sustainTime + releaseTime);\r\n\r\n gain.connect(filter);\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n this._scheduleNodeStartStop(time, time + 0.2, blare);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Woodwinds and Pipes (Flute, Piccolo, Recorder, Ocarina).\r\n * Characterized by a pure, hollow, and breathy tone using sine and triangle waves.\r\n */\r\n/**\r\n * Emulates a flute or clarinet using a pure sine or triangle wave with gentle vibrato and a breathy noise layer.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class WoodwindSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.7, _attackTimeSeconds: 0.05, _releaseTimeSeconds: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** Flutes are mostly a fundamental sine wave with a tiny bit of triangle for the \"chiff\" sound */\r\n const osc1 = this._createOscillator(ctx, \"sine\", freq, gain);\r\n\r\n /** Triangle is mixed much lower just to provide a bit of upper harmonic texture */\r\n const triGain = this._createGain(ctx, 0, gain);\r\n /** Breath transient: louder at attack, decaying to a whisper during sustain */\r\n this._setValueAtTime(triGain.gain, 0.3, time);\r\n this._exponentialRampToValue(triGain.gain, 0.05, time + 0.2);\r\n const osc2 = this._createOscillator(ctx, \"triangle\", freq, triGain);\r\n\r\n /** Lowpass filter to keep it extremely smooth and remove any digital sharpness */\r\n const filter = this._createFilter(ctx, \"lowpass\");\r\n this._setValueAtTime(filter.frequency, freq + 800, time);\r\n\r\n /** Diaphragm vibrato: blooms slowly after the initial breath attack */\r\n const vibrato = this._createLFO(\r\n ctx,\r\n 5.5,\r\n freq * 0.015,\r\n time,\r\n 0.4,\r\n stopTime,\r\n osc1.frequency,\r\n );\r\n vibrato.connect(osc2.frequency);\r\n\r\n /** True Amplitude Modulation (Tremolo) pipelined from the diaphragm vibrato */\r\n const tremoloNode = this._createGain(ctx, 1.0);\r\n const tremoloDepth = this._createGain(ctx, 0.15, tremoloNode.gain);\r\n vibrato.connect(tremoloDepth);\r\n\r\n gain.connect(tremoloNode).connect(filter);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Synth Leads featuring an LFO Vibrato.\r\n */\r\n/**\r\n * Produces a bright, cutting tone using layered oscillators and detuning to stand out in a mix as the primary melody.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class LeadSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.4, _attackTimeSeconds: 0.05, _releaseTimeSeconds: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"sawtooth\", 0);\r\n this._setValueAtTime(osc.frequency, freq, time);\r\n\r\n this._createLFO(ctx, 5, freq * 0.02, time, 0.2, stopTime, osc.frequency);\r\n\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n freq,\r\n freq * 3,\r\n time,\r\n 0.05,\r\n );\r\n this._exponentialRampToValue(filter.frequency, freq * 1.5, time + sustainTime);\r\n filter.Q.value = 3; /** Squelchy resonance */\r\n\r\n osc.connect(filter).connect(gain);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n }\r\n}\r\n","import { AnalogSynthBase } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Synth Pads (Warm, Choir, Halo, Bowed).\r\n * Characterized by slow attacks, slow releases, and evolving filter sweeps.\r\n */\r\nexport class PadSynth extends AnalogSynthBase {\r\n protected _cfg(d: number): { v: number; a: number; r: number } {\r\n return { v: 0.4, a: d < 0.4 ? 0.05 : 0.3, r: d < 0.4 ? 0.1 : 0.8 };\r\n }\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const [osc1, osc2] = this._createStereoOscillator(\r\n ctx,\r\n \"triangle\",\r\n freq,\r\n 1.01,\r\n 0.7,\r\n gain,\r\n );\r\n\r\n const filter = this._createFilter(ctx, \"lowpass\");\r\n this._setValueAtTime(filter.frequency, freq + 400, time);\r\n this._linearRampToValue(\r\n filter.frequency,\r\n freq + 1000 + velocity * 500,\r\n time + sustainTime,\r\n );\r\n\r\n this._createLFO(ctx, 0.5, 10, time, 0, stopTime, osc2.frequency);\r\n this._createLFO(ctx, 0.1, 400, time, 0, stopTime, filter.frequency);\r\n\r\n gain.connect(filter);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2);\r\n\r\n return filter;\r\n }\r\n}\r\n","import { CoreSynthBase, hasStrictGC } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Sound Effects and Sci-Fi Synths.\r\n * Features extreme frequency sweeping over the duration of the note.\r\n */\r\n/**\r\n * Synthesizes various game-related sound effects (lasers, explosions, jumps) using noise bursts and rapid pitch sweeps.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class SoundEffectsSynth extends CoreSynthBase {\r\n /**\r\n * Plays an automated sweeping sci-fi sound effect.\r\n */\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const gain = this._createGain(ctx, 0);\r\n const osc = this._createOscillator(ctx, \"sawtooth\", 0, gain);\r\n\r\n /** Extreme pitch dive from fundamental down one full octave over the note's duration */\r\n this._setValueAtTime(osc.frequency, freq, time);\r\n this._exponentialRampToValue(\r\n osc.frequency,\r\n Math.max(1, freq / 2),\r\n time + Math.max(0.05, duration),\r\n );\r\n\r\n /** Sci-Fi \"Laser Wobble\": fast sine-wave amplitude modulation (avoids scratchy clicking of square wave) */\r\n const stutterNode = this._createGain(ctx, 0.5, masterGain);\r\n this._createLFO(ctx, 15, 0.5, time, 0, time + duration + 0.2, stutterNode.gain);\r\n\r\n gain.connect(stutterNode);\r\n\r\n this._setValueAtTime(gain.gain, 0, time);\r\n this._linearRampToValue(gain.gain, Math.max(0.001, velocity * 0.5), time + 0.05);\r\n this._exponentialRampToValue(gain.gain, 0.001, time + duration + 0.2);\r\n\r\n this._scheduleNodeStartStop(time, time + duration + 0.2, osc);\r\n\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, time + duration + 0.3, gain, stutterNode);\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Ethnic instruments (Sitar, Shamisen, Koto).\r\n * Uses a bandpass filter over a square wave to emulate a hollow, plucked resonator.\r\n */\r\n/**\r\n * A generalized plucked/struck string synthesizer meant to emulate instruments like a Sitar or Koto.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class EthnicSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.6, _attackTimeSeconds: 0.02, _decayTimeSeconds: 0.1, _maxDurationSeconds: 4.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"square\", 0, gain);\r\n this._setValueAtTime(osc.frequency, freq * 1.05, time);\r\n this._exponentialRampToValue(osc.frequency, freq, time + 0.08);\r\n\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"bandpass\",\r\n freq * 2.5,\r\n freq,\r\n time,\r\n safeDuration,\r\n );\r\n filter.Q.value = 2;\r\n\r\n filter.connect(gain);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n }\r\n}\r\n","import { CoreSynthBase, hasStrictGC } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Percussion and Drum kits.\r\n */\r\n/**\r\n * A specialized routing class that uses note frequency as a trigger map to synthesize distinct drum kit pieces (Kick, Snare, Hi-Hat, etc.).\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class DrumSynth extends CoreSynthBase {\r\n /** Cached white noise buffer to prevent massive memory allocations and GC spikes. */\r\n private static _cachedNoiseBuffer: AudioBuffer | null = null;\r\n\r\n private static _getNoiseBuffer(ctx: AudioContext): AudioBuffer {\r\n if (\r\n !DrumSynth._cachedNoiseBuffer ||\r\n DrumSynth._cachedNoiseBuffer.sampleRate !== ctx.sampleRate\r\n ) {\r\n const bufferSize = ctx.sampleRate * 1.0;\r\n const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);\r\n const data = buffer.getChannelData(0);\r\n for (let i = 0; i < bufferSize; i++) data[i] = Math.random() * 2 - 1;\r\n DrumSynth._cachedNoiseBuffer = buffer;\r\n }\r\n return DrumSynth._cachedNoiseBuffer;\r\n }\r\n\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n /** Standard MIDI maps specific frequencies to specific drum kit pieces */\r\n if (freq < 70) {\r\n const gain = this._createGain(ctx, 0, masterGain);\r\n const osc = this._createOscillator(ctx, \"sine\", 0, gain);\r\n\r\n this._setValueAtTime(osc.frequency, 150, time);\r\n this._exponentialRampToValue(osc.frequency, 30, time + 0.1);\r\n this._setValueAtTime(gain.gain, Math.max(0.001, velocity * 1.5), time);\r\n this._exponentialRampToValue(gain.gain, 0.001, time + 0.5);\r\n\r\n this._scheduleNodeStartStop(time, time + 0.5, osc);\r\n\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, time + 0.6, gain);\r\n } else {\r\n /** HI-HAT / SNARE (White Noise generation) */\r\n const isSnare = freq < 90;\r\n\r\n const noise = ctx.createBufferSource();\r\n noise.buffer = DrumSynth._getNoiseBuffer(ctx);\r\n const gain = this._createGain(ctx, 0, masterGain);\r\n const filter = this._createFilter(\r\n ctx,\r\n isSnare ? \"bandpass\" : \"highpass\",\r\n );\r\n const panner = this._createStereoPanner(ctx, isSnare ? 0 : Math.random() * 0.6 - 0.3);\r\n\r\n filter.frequency.value = isSnare ? 1500 : 5000;\r\n\r\n this._setValueAtTime(gain.gain, Math.max(0.001, velocity), time);\r\n this._exponentialRampToValue(gain.gain, 0.001, time + (isSnare ? 0.2 : 0.05));\r\n\r\n noise.connect(filter).connect(gain).connect(panner);\r\n this._scheduleNodeStartStop(time, time + (isSnare ? 0.2 : 0.05), noise);\r\n\r\n /** Add an extra body thwack tone if it is a snare */\r\n if (isSnare) {\r\n const snareOsc = this._createOscillator(ctx, \"triangle\", 0, gain);\r\n /** Snare drum head tension: quick pitch drop when the stick hits the skin */\r\n this._setValueAtTime(snareOsc.frequency, 300, time);\r\n this._exponentialRampToValue(snareOsc.frequency, 100, time + 0.1);\r\n this._scheduleNodeStartStop(time, time + 0.2, snareOsc);\r\n } else {\r\n /** 808 Cymbal Metallic Ring: TR-808 hi-hats contain high-pitched ringing square waves */\r\n this._createTransient(\r\n ctx,\r\n \"square\",\r\n 7000,\r\n panner,\r\n time,\r\n Math.max(0.001, velocity * 0.2),\r\n 0.05,\r\n );\r\n }\r\n\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, time + 0.4, filter, gain, panner);\r\n }\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for 8-bit Chiptune sounds.\r\n * Uses a raw square wave with a rapid pitch-drop \"blip\" attack.\r\n */\r\n/**\r\n * Generates retro 8-bit style square waves, ideal for recreating classic video game soundtracks.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class ChiptuneSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.4, _attackTimeSeconds: 0.005, _releaseTimeSeconds: 0.05 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"square\", 0, gain);\r\n\r\n /** Classic tracker \"blip\" attack: starts one octave higher for a fraction of a second */\r\n this._setValueAtTime(osc.frequency, freq * 2, time);\r\n this._setValueAtTime(osc.frequency, freq, time + 0.02);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n }\r\n}\r\n","/**\n * @fileoverview AUTO-GENERATED BY VITE CONFIG\n * \n * @reason Central Registry & Export Hub.\n * This file is automatically generated by `vite.config.ts` to ensure that \n * the `MasterInstrumentMap` correctly initializes all 16 default GM synthesizers \n * at the correct index ranges. It acts as the primary NPM package entry point.\n */\nimport { decodeBinary, encodeToBinary, encodeToSoA } from './RLO-Transpiler.js';\nimport { RLOCore as BaseCore } from './Core/RLOCore.js';\nimport { RLOMusicPlayer as BaseMusicPlayer } from './Players/RLOMusicPlayer.js';\nimport { RLOGameEngine as BaseGameEngine } from './Players/RLOGameEngine.js';\nimport { createInstrumentMap, extendInstrumentMap, createDirectMap, SilentSynth } from './Core/InstrumentMap.js';\nimport type { ISynthInstrument } from './Instruments/ISynthInstrument.js';\nimport { PianoSynth } from './Instruments/Decay/PianoSynth.js';\nimport { ChromaticPercussionSynth } from './Instruments/Decay/ChromaticPercussionSynth.js';\nimport { OrganSynth } from './Instruments/Analog/OrganSynth.js';\nimport { GuitarSynth } from './Instruments/Decay/GuitarSynth.js';\nimport { ElectricGuitarSynth } from './Instruments/Decay/ElectricGuitarSynth.js';\nimport { BassSynth } from './Instruments/Analog/BassSynth.js';\nimport { StringSynth } from './Instruments/Analog/StringSynth.js';\nimport { BrassSynth } from './Instruments/Decay/BrassSynth.js';\nimport { WoodwindSynth } from './Instruments/Analog/WoodwindSynth.js';\nimport { LeadSynth } from './Instruments/Analog/LeadSynth.js';\nimport { PadSynth } from './Instruments/Analog/PadSynth.js';\nimport { SoundEffectsSynth } from './Instruments/Speciality/SoundEffectsSynth.js';\nimport { EthnicSynth } from './Instruments/Decay/EthnicSynth.js';\nimport { DrumSynth } from './Instruments/Speciality/DrumSynth.js';\nimport { FMSynth } from './Instruments/Analog/FMSynth.js';\nimport { AdditiveSynth } from './Instruments/Decay/AdditiveSynth.js';\nimport { KarplusSynth } from './Instruments/Decay/KarplusSynth.js';\nimport { ReeseBassSynth } from './Instruments/Analog/ReeseBassSynth.js';\nimport { FormantSynth } from './Instruments/Analog/FormantSynth.js';\nimport { ChiptuneSynth } from './Instruments/Analog/ChiptuneSynth.js';\nimport { SlapBassSynth } from './Instruments/Decay/SlapBassSynth.js';\n\n// Export all synthesizers (including optional ones) for NPM users\nexport { PianoSynth, ChromaticPercussionSynth, OrganSynth, GuitarSynth, ElectricGuitarSynth, BassSynth, StringSynth, BrassSynth, WoodwindSynth, LeadSynth, PadSynth, SoundEffectsSynth, EthnicSynth, DrumSynth, FMSynth, AdditiveSynth, KarplusSynth, ReeseBassSynth, FormantSynth, ChiptuneSynth, SlapBassSynth };\n\nconst defaultMapModules = [\n { synth: new PianoSynth(), start: 0, end: 7 },\n { synth: new ChromaticPercussionSynth(), start: 8, end: 15 },\n { synth: new OrganSynth(), start: 16, end: 23 },\n { synth: new GuitarSynth(), start: 24, end: 26 },\n { synth: new ElectricGuitarSynth(), start: 27, end: 31 },\n { synth: new BassSynth(), start: 32, end: 39 },\n { synth: new StringSynth(), start: 40, end: 55 },\n { synth: new BrassSynth(), start: 56, end: 71 },\n { synth: new WoodwindSynth(), start: 72, end: 79 },\n { synth: new LeadSynth(), start: 83, end: 87 },\n { synth: new PadSynth(), start: 88, end: 95 },\n { synth: new SoundEffectsSynth(), start: 96, end: 103 },\n { synth: new SoundEffectsSynth(), start: 120, end: 127 },\n { synth: new EthnicSynth(), start: 104, end: 111 },\n { synth: new DrumSynth(), start: 112, end: 119 },\n { synth: new DrumSynth(), start: 128, end: 128 },\n];\nconst defaultMap = createInstrumentMap(defaultMapModules);\n\nconst retroMap = createInstrumentMap([\n { synth: new ChiptuneSynth(), start: 0, end: 127 },\n { synth: new DrumSynth(), start: 128, end: 128 }\n]);\n\nexport { decodeBinary, encodeToBinary, encodeToSoA, createInstrumentMap, extendInstrumentMap, createDirectMap, SilentSynth, defaultMap as MasterInstrumentMap, defaultMap as StandardInstrumentMap, retroMap as RetroInstrumentMap };\nexport class RLOCore extends BaseCore { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\nexport class RLOMusicPlayer extends BaseMusicPlayer { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\nexport class RLOGameEngine extends BaseGameEngine { constructor(ctx: AudioContext, customMap?: ISynthInstrument[]) { super(ctx, customMap || defaultMap); } }\n","import { DecaySynthBase, DecayCfg } from \"./DecaySynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Inharmonic Additive bells/glass.\r\n * Stacks sine waves at non-integer multiples to create metallic, clanging overtones.\r\n */\r\n/**\r\n * Creates complex timbres by summing together multiple sine waves at mathematically calculated harmonic ratios.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class AdditiveSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.6, _attackTimeSeconds: 0.005, _decayTimeSeconds: 0.5, _maxDurationSeconds: 5.0 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const ratios = [1.0, 2.76, 5.4, 8.9, 13.3];\r\n const decays = [1.0, 0.6, 0.4, 0.2, 0.1]; // Higher frequencies die out much faster\r\n\r\n ratios.forEach((ratio, i) => {\r\n const hFreq = freq * ratio;\r\n if (hFreq < 22000) {\r\n const peak = Math.max(0.001, velocity * (1 / (i + 1.5)));\r\n const dur = Math.max(0.1, safeDuration * decays[i]);\r\n this._createTransient(ctx, \"sine\", hFreq, gain, time, peak, dur, 0.005);\r\n }\r\n });\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport { Osc } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for FM (Frequency Modulation).\r\n * Modulates a carrier sine wave with another sine wave to create glassy,\r\n * metallic overtones common in 1980s Electric Pianos and Bells.\r\n */\r\n/**\r\n * Uses Frequency Modulation (FM) to create complex metallic or bell-like timbres by modulating the phase of one oscillator with another.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class FMSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.6, _attackTimeSeconds: 0.01, _releaseTimeSeconds: 0.1 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const carrier = this._createOscillator(ctx, \"sine\", freq, gain);\r\n\r\n const modFreq = freq * 2; // 2:1 harmonic ratio for bell/epiano overtones\r\n const modDepth = modFreq * 4; // Modulation index (brightness)\r\n\r\n const modGain = this._createGain(ctx, 0, carrier.frequency);\r\n this._setValueAtTime(modGain.gain, modDepth * velocity, time);\r\n this._exponentialRampToValue(modGain.gain, 0.01, time + sustainTime); // Decay the harshness over time for a plucked feel\r\n\r\n const modulator = this._createOscillator(ctx, \"sine\", modFreq, modGain);\r\n\r\n this._scheduleNodeStartStop(time, stopTime, carrier, modulator);\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Formant Choirs (Human Vox).\r\n * Uses parallel bandpass filters locked to specific \"vowel\" resonant frequencies.\r\n */\r\n/**\r\n * Mimics human vowel sounds (a, e, i, o, u) using parallel bandpass filters (formants) tuned to specific vocal tract resonant frequencies.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class FormantSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.8, _attackTimeSeconds: 0.1, _releaseTimeSeconds: 0.4 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const osc = this._createOscillator(ctx, \"sawtooth\", freq);\r\n this._createLFO(ctx, 5, freq * 0.015, time, 0.2, stopTime, osc.frequency);\r\n\r\n // Typical 'Ah' vowel formants: 730Hz, 1090Hz, 2440Hz\r\n [730, 1090, 2440].forEach((f) => {\r\n if (f < 22000) {\r\n const filter = this._createFilter(ctx, \"bandpass\");\r\n filter.frequency.value = f;\r\n filter.Q.value = 12; // High resonance to isolate the formant\r\n osc.connect(filter).connect(gain);\r\n }\r\n });\r\n\r\n this._scheduleNodeStartStop(time, stopTime, osc);\r\n }\r\n}\r\n","import { CoreSynthBase, Filter, hasStrictGC } from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Karplus-Strong physical modeling.\r\n * Uses a noise burst fed into a tuned delay line with a feedback filter\r\n * to accurately simulate the physics of plucked strings (Acoustic Guitar, Harp).\r\n */\r\n/**\r\n * Implements the Karplus-Strong string synthesis algorithm using a short noise burst fed through a tightly tuned feedback delay line.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class KarplusSynth extends CoreSynthBase {\r\n public _playNote(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n time: number,\r\n freq: number,\r\n duration: number,\r\n velocity: number,\r\n ): void {\r\n const delayTime = 1 / freq;\r\n\r\n // 1. The Plectrum (A microscopic burst of white noise)\r\n const burstBuffer = ctx.createBuffer(\r\n 1,\r\n Math.max(1, ctx.sampleRate * delayTime),\r\n ctx.sampleRate,\r\n );\r\n const data = burstBuffer.getChannelData(0);\r\n for (let i = 0; i < data.length; i++)\r\n data[i] = (Math.random() * 2 - 1) * velocity;\r\n\r\n const burst = ctx.createBufferSource();\r\n burst.buffer = burstBuffer;\r\n\r\n // 2. The String (A delay node exactly the length of the frequency)\r\n const delay = ctx.createDelay(delayTime);\r\n delay.delayTime.value = delayTime;\r\n\r\n // 3. The Body Damping (Lowpass filter inside the feedback loop to absorb high frequencies)\r\n const filter = this._createFilter(ctx, \"lowpass\");\r\n filter.frequency.value = Math.min(22000, freq * 6);\r\n\r\n // 4. The Tension (Feedback gain)\r\n const feedback = this._createGain(ctx, 0.98); // Higher value = longer ring time\r\n\r\n burst.connect(delay).connect(filter).connect(feedback).connect(delay);\r\n\r\n const output = this._createGain(ctx, 0, masterGain);\r\n this._setValueAtTime(output.gain, 1, time);\r\n this._exponentialRampToValue(output.gain, 0.001, time + duration);\r\n\r\n delay.connect(output);\r\n this._scheduleNodeStartStop(time, time + duration, burst);\r\n\r\n if (hasStrictGC) this._scheduleNodeDisposal(ctx, time, time + duration + 3.0, output, delay, filter, feedback);\r\n }\r\n}\r\n","import { AnalogSynthBase, AnalogCfg } from \"./AnalogSynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for Reese/Wobble Bass.\r\n * Uses heavily detuned sawtooths and an LFO-driven lowpass filter.\r\n */\r\n/**\r\n * A staple of Drum & Bass music, this uses two heavily detuned sawtooth waves to create a thick, phasing, and wide bass tone.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class ReeseBassSynth extends AnalogSynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.7, _attackTimeSeconds: 0.05, _releaseTimeSeconds: 0.2 };\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n sustainTime: number,\r\n releaseTime: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n const filter = this._createFilter(ctx, \"lowpass\");\r\n this._setValueAtTime(filter.frequency, freq * 2, time);\r\n\r\n // Wobble LFO: syncs roughly to tempo (e.g. 1/8th notes ~4-8 Hz)\r\n this._createLFO(ctx, 6, freq * 3, time, 0, stopTime, filter.frequency);\r\n\r\n // Deep, phasing detune\r\n const [osc1, osc2] = this._createStereoOscillator(\r\n ctx,\r\n \"sawtooth\",\r\n freq / 2,\r\n 1.015,\r\n 0.4,\r\n filter,\r\n );\r\n filter.connect(gain);\r\n this._scheduleNodeStartStop(time, stopTime, osc1, osc2);\r\n }\r\n}\r\n","import { DecaySynthBase } from \"./DecaySynthBase.js\";\r\nimport {} from \"../CoreSynthBase.js\";\r\n\r\n/**\r\n * Synthesizer strategy for 80s Slap Bass (DX7/Seinfeld style).\r\n * Characterized by a very snappy filter envelope and a metallic transient \"pop\".\r\n */\r\n/**\r\n * Emulates a slapped bass guitar with a sharp, percussive attack phase and a rapidly decaying low-pass filter.\r\n * \r\n * @reason Acoustic Design:\r\n * Encapsulates the specific Web Audio node routing and ADSR parameters\r\n * required to physically model this instrument within the 13KB limit.\r\n */\r\nexport class SlapBassSynth extends DecaySynthBase {\r\n protected _envelopeConfig = { _peakVelocity: 0.9, _attackTimeSeconds: 0.005, _decayTimeSeconds: 0.15, _maxDurationSeconds: 3.0 }; // Ultra-fast attack for the slap\r\n\r\n protected _setupSynthesis(\r\n ctx: AudioContext,\r\n masterGain: GainNode,\r\n gain: GainNode,\r\n time: number,\r\n freq: number,\r\n velocity: number,\r\n safeDuration: number,\r\n stopTime: number,\r\n ): AudioNode | void {\r\n /** The \"Pop\" - An aggressive lowpass filter sweep that opens bright and snaps shut */\r\n const filter = this._createFilterSweep(\r\n ctx,\r\n \"lowpass\",\r\n freq * 8 + velocity * 3000, // Very bright on hard velocities\r\n freq + 100, // Quickly muffles down to the fundamental\r\n time,\r\n 0.1, // Snap duration\r\n );\r\n filter.Q.value = 3; // Adds a \"quack\" resonance to the slap\r\n\r\n /** The Body - Sawtooth for rich harmonics */\r\n const osc = this._createOscillator(ctx, \"sawtooth\", freq, gain);\r\n\r\n /** The Sub - Deep sine wave an octave down to anchor the low end */\r\n const subOsc = this._createOscillator(ctx, \"sine\", freq / 2, gain);\r\n\r\n /** The \"Thumb Slap\" - A quick, inharmonic metallic burst simulating the string hitting the fretboard */\r\n this._createTransient(\r\n ctx,\r\n \"square\",\r\n freq * 3.5,\r\n filter,\r\n time,\r\n Math.max(0.001, velocity * 0.4),\r\n 0.04,\r\n );\r\n\r\n gain.connect(filter);\r\n this._scheduleNodeStartStop(time, stopTime, osc, subOsc);\r\n\r\n return filter;\r\n }\r\n}\r\n"],"names":["encodeToSoA","humanJson","fullRangeFreq","N","notes","length","f","Float32Array","Uint8Array","t","Uint16Array","d","v","i","lastRoundedTime","n","ptr","time","freq","Math","max","min","round","log2","roundedTime","durationSecs","decodeBinary","buffer","view","DataView","magic","String","fromCharCode","getUint8","Error","isFullRange","getFloat32","getUint32","f8","currentTime","tn","getUint16","dn","fn","pow","Synthesizer","constructor","ctx","masterGain","instruments","this","_ctx","_masterGain","_instruments","_playNote","instrumentId","duration","velocity","keyTrackVel","instrument","RLOCore$1","audioContext","instrumentMap","_isPlaying","_timer","_workerTimer","_sequenceId","_trkT","_trkD","_activeNodes","_volume","_seekTarget","playbackRate","_workerUrl","_instrumentMap","_now","setVolume","vol","seek","timeInSeconds","stop","clearTimeout","nodesToClean","pop","disconnect","e","dispose","_createGain","createGain","_applyLinearFade","gain","target","setValueAtTime","linearRampToValueAtTime","_createCompressor","c","createDynamicsCompressor","threshold","value","knee","ratio","attack","release","_createRouting","fadeInTime","connect","destination","push","playSequence","track","loopOrOpts","oldFadeInTime","loop","volume","state","resume","currentSequenceId","synthesizer","lastScheduleTime","loopOffsetSecs","notePtr","len","schedule","currentPhysicalTime","deltaPhysical","duckGain","cancelScheduledValues","exponentialRampToValueAtTime","loopDurationSecs","noteTrackTime","notePhysicalTime","setTimeout","_AudioEffects","_generateReverb","mode","_cachedConcert","_cachedStudio","isStudio","sampleRate","decay","impulse","createBuffer","channel","getChannelData","lastOut","j","random","exp","AudioEffects","RLOCore","super","_masterGainNode","_reverbNode","_fxGainNode","_trackCacheMap","Map","_maxCacheSizeLimit","_currentReverbMode","_visibilityEventHandler","document","hidden","suspend","addEventListener","setReverbMode","setTargetAtTime","removeEventListener","clear","getCurrentTime","getTotalDuration","createConvolver","masterFilter","createBiquadFilter","type","frequency","compressor","play","trackUrlOrData","fadeInOrOpts","oldLoop","optionsObj","has","get","response","fetch","window","__ENABLE_TRANSPILER__","toLowerCase","endsWith","text","JSON","parse","rawBuffer","arrayBuffer","byteLength","ds","DecompressionStream","writer","writable","getWriter","write","close","Response","readable","set","size","firstKey","keys","next","delete","now","_gameMasterGain","_musicRoutingGain","_sfxRoutingGain","_sfxInternalSynthesizer","setMusicVolume","setSFXVolume","musicGain","playSFX","freqOrNote","velocityOrOpts","oldTimeOffset","timeOffset","pitch","match","note","accidental","octave","semitone","C","D","E","F","G","A","B","toUpperCase","parseInt","toFixed","Note","playSFXSequence","start","playMusic","opts","stopMusic","createInstrumentMap","modules","mapArray","Array","fill","forEach","m","end","synth","closest","minDiff","Infinity","diff","abs","CoreSynthBase","_createOscillator","dest","o","createOscillator","val","g","_createFilter","_createStereoPanner","p","createStereoPanner","pan","_scheduleNodeStartStop","s","x","_setValueAtTime","_linearRampToValue","_exponentialRampToValue","_createTransient","peak","dur","atk","_createFilterSweep","f1","f2","t1","_createStereoOscillator","detune","_createLFO","depth","fadeIn","stopTime","delay","_scheduleNodeDisposal","nodes","gcOsc","onended","DecaySynthBase","arguments","_envelopeConfig","_peakVelocity","_attackTimeSeconds","_decayTimeSeconds","_maxDurationSeconds","_getEnvelopeConfig","peakVol","safeDuration","_applyDecay","finalNode","_setupSynthesis","gainParam","decayTail","PianoSynth","filter","osc1","overtoneGain","osc2","osc3","panner","ChromaticPercussionSynth","osc","overtone","AnalogSynthBase","_releaseTimeSeconds","sustainTime","OrganSynth","releaseTime","gain2","gain3","rotaryNode","GuitarSynth","ElectricGuitarSynth","BassSynth","subGain","subOsc","StringSynth","_cfg","a","r","BrassSynth","blareGain","blare","WoodwindSynth","triGain","vibrato","tremoloNode","tremoloDepth","LeadSynth","Q","PadSynth","SoundEffectsSynth","stutterNode","EthnicSynth","_DrumSynth","_getNoiseBuffer","_cachedNoiseBuffer","bufferSize","data","isSnare","noise","createBufferSource","snareOsc","DrumSynth","ChiptuneSynth","defaultMap","retroMap","decays","hFreq","carrier","modFreq","modDepth","modGain","modulator","delayTime","burstBuffer","burst","createDelay","feedback","output","BaseCore","customMap","BaseGameEngine","BaseMusicPlayer","assignments","ids","id","isLittleEndian","soa","ArrayBuffer","setUint8","setFloat32","setUint32","setUint16","baseMap","overrides","newMap"],"mappings":"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"}
|