@al8b/audio 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants.ts","../../src/devices/beeper.ts","../../src/devices/music.ts","../../src/devices/sound.ts"],"sourcesContent":["/** A4 reference frequency in Hz (concert pitch) */\nexport const A4_FREQUENCY = 440;\n\n/** Ratio between adjacent semitones in equal temperament */\nexport const SEMITONE_RATIO = 2 ** (1 / 12);\n\n/** MIDI note number for A4 */\nexport const A4_MIDI_NOTE = 69;\n","/**\n * Beeper - Procedural sound generation from text sequences\n * Converts music notation strings into beep sequences\n * Example: \"square tempo 120 C4 D4 E4 F4\"\n */\nimport { A4_FREQUENCY, A4_MIDI_NOTE, SEMITONE_RATIO } from \"../constants\";\nexport class Beeper {\n\tprivate audio: any;\n\tprivate notes: Record<string | number, number> = {};\n\tprivate plainNotes: Record<string, number> = {};\n\tprivate currentOctave = 5;\n\tprivate currentDuration = 0.5;\n\tprivate currentVolume = 0.5;\n\tprivate currentSpan = 1;\n\tprivate currentWaveform = \"square\";\n\n\tconstructor(audio: any) {\n\t\tthis.audio = audio;\n\t\tthis.initializeNotes();\n\t}\n\n\t/**\n\t * Initialize note mappings\n\t */\n\tprivate initializeNotes(): void {\n\t\tconst noteNames = [\n\t\t\t[\"C\", \"DO\"],\n\t\t\t[\"C#\", \"DO#\", \"Db\", \"REb\"],\n\t\t\t[\"D\", \"RE\"],\n\t\t\t[\"D#\", \"RE#\", \"Eb\", \"MIb\"],\n\t\t\t[\"E\", \"MI\"],\n\t\t\t[\"F\", \"FA\"],\n\t\t\t[\"F#\", \"FA#\", \"Gb\", \"SOLb\"],\n\t\t\t[\"G\", \"SOL\"],\n\t\t\t[\"G#\", \"SOL#\", \"Ab\", \"LAb\"],\n\t\t\t[\"A\", \"LA\"],\n\t\t\t[\"A#\", \"LA#\", \"Bb\", \"SIb\"],\n\t\t\t[\"B\", \"SI\"],\n\t\t];\n\n\t\tfor (let i = 0; i <= 127; i++) {\n\t\t\tthis.notes[i] = i;\n\t\t\tconst oct = Math.floor(i / 12) - 1;\n\n\t\t\tfor (const n of noteNames[i % 12]) {\n\t\t\t\tthis.notes[n + oct] = i;\n\t\t\t}\n\n\t\t\tif (oct === -1) {\n\t\t\t\tfor (const n of noteNames[i % 12]) {\n\t\t\t\t\tthis.plainNotes[n] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parse and play beep sequence\n\t */\n\tpublic beep(input: string): void {\n\t\tlet status: string = \"normal\";\n\t\tconst sequence: any[] = [];\n\t\tconst loops: any[] = [];\n\t\tlet note: number | undefined;\n\n\t\tconst parsed = input.split(\" \");\n\n\t\tfor (const t of parsed) {\n\t\t\tif (t === \"\") continue;\n\n\t\t\tswitch (status) {\n\t\t\t\tcase \"normal\":\n\t\t\t\t\tif (this.notes[t] !== undefined) {\n\t\t\t\t\t\t// Full note with octave (e.g., \"C4\")\n\t\t\t\t\t\tnote = this.notes[t];\n\t\t\t\t\t\tthis.currentOctave = Math.floor(note / 12);\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),\n\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (this.plainNotes[t] !== undefined) {\n\t\t\t\t\t\t// Note without octave (e.g., \"C\")\n\t\t\t\t\t\tnote = this.plainNotes[t] + this.currentOctave * 12;\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),\n\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if ([\"square\", \"sine\", \"saw\", \"noise\"].includes(t)) {\n\t\t\t\t\t\t// Waveform\n\t\t\t\t\t\tthis.currentWaveform = t;\n\t\t\t\t\t} else if ([\"tempo\", \"duration\", \"volume\", \"span\", \"loop\", \"to\"].includes(t)) {\n\t\t\t\t\t\t// Commands\n\t\t\t\t\t\tstatus = t;\n\t\t\t\t\t} else if (t === \"-\") {\n\t\t\t\t\t\t// Rest/silence\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\t\t\t\tvolume: 0,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (t === \"end\") {\n\t\t\t\t\t\t// End loop\n\t\t\t\t\t\tif (loops.length > 0 && sequence.length > 0) {\n\t\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\t\t\t\t\tvolume: 0,\n\t\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\t\tduration: 0,\n\t\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst lop = loops.splice(loops.length - 1, 1)[0];\n\t\t\t\t\t\t\tsequence[sequence.length - 1].loopto = lop.start;\n\t\t\t\t\t\t\tsequence[sequence.length - 1].repeats = lop.repeats;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"tempo\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst tempo = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(tempo) && tempo > 0) {\n\t\t\t\t\t\tthis.currentDuration = 60 / tempo;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"duration\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst duration = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(duration) && duration > 0) {\n\t\t\t\t\t\tthis.currentDuration = duration / 1000;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"volume\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst volume = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(volume)) {\n\t\t\t\t\t\tthis.currentVolume = volume / 100;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"span\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst span = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(span)) {\n\t\t\t\t\t\tthis.currentSpan = span / 100;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"loop\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tloops.push({\n\t\t\t\t\t\tstart: sequence.length,\n\t\t\t\t\t});\n\t\t\t\t\tconst repeats = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(repeats)) {\n\t\t\t\t\t\tloops[loops.length - 1].repeats = repeats;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"to\":\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tif (note !== undefined) {\n\t\t\t\t\t\tlet n: number | undefined;\n\n\t\t\t\t\t\tif (this.notes[t] !== undefined) {\n\t\t\t\t\t\t\tn = this.notes[t];\n\t\t\t\t\t\t} else if (this.plainNotes[t] !== undefined) {\n\t\t\t\t\t\t\tn = this.plainNotes[t] + this.currentOctave * 12;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (n !== undefined && n !== note) {\n\t\t\t\t\t\t\t// Generate slide from note to n\n\t\t\t\t\t\t\tconst step = n > note ? 1 : -1;\n\t\t\t\t\t\t\tfor (let i = note + step; step > 0 ? i <= n : i >= n; i += step) {\n\t\t\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (i - A4_MIDI_NOTE),\n\t\t\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnote = n;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Close any remaining loops\n\t\tif (loops.length > 0 && sequence.length > 0) {\n\t\t\tconst lop = loops.splice(loops.length - 1, 1)[0];\n\t\t\tsequence.push({\n\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\tvolume: 0,\n\t\t\t\tspan: this.currentSpan,\n\t\t\t\tduration: 0,\n\t\t\t\twaveform: this.currentWaveform,\n\t\t\t});\n\n\t\t\tsequence[sequence.length - 1].loopto = lop.start;\n\t\t\tsequence[sequence.length - 1].repeats = lop.repeats;\n\t\t}\n\n\t\tthis.audio.addBeeps(sequence);\n\t}\n}\n","/**\n * Music - Music streaming and playback using HTML5 Audio\n * L8B Music class for LootiScript\n */\nexport class Music {\n\tpublic ready: number = 1;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tpublic tag: HTMLAudioElement;\n\tpublic playing: boolean = false;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string) {\n\t\tthis.audio = audio;\n\t\tthis.url = url;\n\t\tthis.tag = new Audio(this.url);\n\t\tthis.ready = 1;\n\t}\n\n\t/**\n\t * Play music with volume and loop (HTML5 Audio implementation)\n\t */\n\tpublic play(volume: number = 1, loopit: boolean = false): any {\n\t\tthis.playing = true;\n\t\tthis.tag.loop = !!loopit;\n\t\tthis.tag.volume = Math.max(0, Math.min(1, volume));\n\n\t\tif (this.audio.isStarted()) {\n\t\t\tthis.tag.play();\n\t\t} else {\n\t\t\tthis.audio.addToWakeUpList(this);\n\t\t}\n\n\t\tthis.audio.addPlaying(this);\n\n\t\treturn {\n\t\t\tplay: () => {\n\t\t\t\treturn this.tag.play();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tthis.playing = false;\n\t\t\t\tthis.tag.pause();\n\t\t\t\tthis.audio.removePlaying(this);\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tthis.tag.volume = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tgetPosition: () => {\n\t\t\t\treturn this.tag.currentTime;\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn this.tag.duration;\n\t\t\t},\n\t\t\tsetPosition: (pos: number) => {\n\t\t\t\tthis.tag.pause();\n\t\t\t\tthis.tag.currentTime = Math.max(0, Math.min(this.tag.duration, pos));\n\t\t\t\tif (this.playing) {\n\t\t\t\t\tthis.tag.play();\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Wake up audio (for autoplay policy)\n\t */\n\tpublic wakeUp(): void {\n\t\tif (this.playing) {\n\t\t\tthis.tag.play();\n\t\t}\n\t}\n\n\t/**\n\t * Stop music\n\t */\n\tpublic stop(): void {\n\t\tthis.playing = false;\n\t\tthis.tag.pause();\n\t\tthis.audio.removePlaying(this);\n\t}\n}\n","/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\t\t\terror: `Audio decoding failed: ${String(err)}`,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\terror: `Failed to load sound: ${url}`,\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["A4_FREQUENCY","SEMITONE_RATIO","A4_MIDI_NOTE","Beeper","audio","notes","plainNotes","currentOctave","currentDuration","currentVolume","currentSpan","currentWaveform","initializeNotes","noteNames","i","oct","Math","floor","n","beep","input","status","sequence","loops","note","parsed","split","t","undefined","push","frequency","A4_FREQUENCY","SEMITONE_RATIO","A4_MIDI_NOTE","volume","span","duration","waveform","includes","length","lop","splice","loopto","start","repeats","tempo","Number","parseFloat","isNaN","step","addBeeps","Music","ready","name","url","tag","playing","audio","Audio","play","volume","loopit","loop","Math","max","min","isStarted","addToWakeUpList","addPlaying","stop","pause","removePlaying","setVolume","v","getPosition","currentTime","getDuration","duration","setPosition","pos","wakeUp","APIErrorCode","reportRuntimeError","Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","reportRuntimeError","runtime","listener","APIErrorCode","E7016","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
1
+ {"version":3,"sources":["../../src/constants.ts","../../src/devices/beeper.ts","../../src/devices/music.ts","../../src/devices/sound.ts"],"sourcesContent":["/** A4 reference frequency in Hz (concert pitch) */\nexport const A4_FREQUENCY = 440;\n\n/** Ratio between adjacent semitones in equal temperament */\nexport const SEMITONE_RATIO = 2 ** (1 / 12);\n\n/** MIDI note number for A4 */\nexport const A4_MIDI_NOTE = 69;\n","/**\n * Beeper - Procedural sound generation from text sequences\n * Converts music notation strings into beep sequences\n * Example: \"square tempo 120 C4 D4 E4 F4\"\n */\nimport { A4_FREQUENCY, A4_MIDI_NOTE, SEMITONE_RATIO } from \"../constants\";\nexport class Beeper {\n\tprivate audio: any;\n\tprivate notes: Record<string | number, number> = {};\n\tprivate plainNotes: Record<string, number> = {};\n\tprivate currentOctave = 5;\n\tprivate currentDuration = 0.5;\n\tprivate currentVolume = 0.5;\n\tprivate currentSpan = 1;\n\tprivate currentWaveform = \"square\";\n\n\tconstructor(audio: any) {\n\t\tthis.audio = audio;\n\t\tthis.initializeNotes();\n\t}\n\n\t/**\n\t * Initialize note mappings\n\t */\n\tprivate initializeNotes(): void {\n\t\tconst noteNames = [\n\t\t\t[\"C\", \"DO\"],\n\t\t\t[\"C#\", \"DO#\", \"Db\", \"REb\"],\n\t\t\t[\"D\", \"RE\"],\n\t\t\t[\"D#\", \"RE#\", \"Eb\", \"MIb\"],\n\t\t\t[\"E\", \"MI\"],\n\t\t\t[\"F\", \"FA\"],\n\t\t\t[\"F#\", \"FA#\", \"Gb\", \"SOLb\"],\n\t\t\t[\"G\", \"SOL\"],\n\t\t\t[\"G#\", \"SOL#\", \"Ab\", \"LAb\"],\n\t\t\t[\"A\", \"LA\"],\n\t\t\t[\"A#\", \"LA#\", \"Bb\", \"SIb\"],\n\t\t\t[\"B\", \"SI\"],\n\t\t];\n\n\t\tfor (let i = 0; i <= 127; i++) {\n\t\t\tthis.notes[i] = i;\n\t\t\tconst oct = Math.floor(i / 12) - 1;\n\n\t\t\tfor (const n of noteNames[i % 12]) {\n\t\t\t\tthis.notes[n + oct] = i;\n\t\t\t}\n\n\t\t\tif (oct === -1) {\n\t\t\t\tfor (const n of noteNames[i % 12]) {\n\t\t\t\t\tthis.plainNotes[n] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parse and play beep sequence\n\t */\n\tpublic beep(input: string): void {\n\t\tlet status: string = \"normal\";\n\t\tconst sequence: any[] = [];\n\t\tconst loops: any[] = [];\n\t\tlet note: number | undefined;\n\n\t\tconst parsed = input.split(\" \");\n\n\t\tfor (const t of parsed) {\n\t\t\tif (t === \"\") continue;\n\n\t\t\tswitch (status) {\n\t\t\t\tcase \"normal\":\n\t\t\t\t\tif (this.notes[t] !== undefined) {\n\t\t\t\t\t\t// Full note with octave (e.g., \"C4\")\n\t\t\t\t\t\tnote = this.notes[t];\n\t\t\t\t\t\tthis.currentOctave = Math.floor(note / 12);\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),\n\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (this.plainNotes[t] !== undefined) {\n\t\t\t\t\t\t// Note without octave (e.g., \"C\")\n\t\t\t\t\t\tnote = this.plainNotes[t] + this.currentOctave * 12;\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),\n\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if ([\"square\", \"sine\", \"saw\", \"noise\"].includes(t)) {\n\t\t\t\t\t\t// Waveform\n\t\t\t\t\t\tthis.currentWaveform = t;\n\t\t\t\t\t} else if ([\"tempo\", \"duration\", \"volume\", \"span\", \"loop\", \"to\"].includes(t)) {\n\t\t\t\t\t\t// Commands\n\t\t\t\t\t\tstatus = t;\n\t\t\t\t\t} else if (t === \"-\") {\n\t\t\t\t\t\t// Rest/silence\n\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\t\t\t\tvolume: 0,\n\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (t === \"end\") {\n\t\t\t\t\t\t// End loop\n\t\t\t\t\t\tif (loops.length > 0 && sequence.length > 0) {\n\t\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\t\t\t\t\tvolume: 0,\n\t\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\t\tduration: 0,\n\t\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst lop = loops.splice(loops.length - 1, 1)[0];\n\t\t\t\t\t\t\tsequence[sequence.length - 1].loopto = lop.start;\n\t\t\t\t\t\t\tsequence[sequence.length - 1].repeats = lop.repeats;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"tempo\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst tempo = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(tempo) && tempo > 0) {\n\t\t\t\t\t\tthis.currentDuration = 60 / tempo;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"duration\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst duration = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(duration) && duration > 0) {\n\t\t\t\t\t\tthis.currentDuration = duration / 1000;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"volume\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst volume = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(volume)) {\n\t\t\t\t\t\tthis.currentVolume = volume / 100;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"span\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tconst span = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(span)) {\n\t\t\t\t\t\tthis.currentSpan = span / 100;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"loop\": {\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tloops.push({\n\t\t\t\t\t\tstart: sequence.length,\n\t\t\t\t\t});\n\t\t\t\t\tconst repeats = Number.parseFloat(t);\n\t\t\t\t\tif (!Number.isNaN(repeats)) {\n\t\t\t\t\t\tloops[loops.length - 1].repeats = repeats;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"to\":\n\t\t\t\t\tstatus = \"normal\";\n\t\t\t\t\tif (note !== undefined) {\n\t\t\t\t\t\tlet n: number | undefined;\n\n\t\t\t\t\t\tif (this.notes[t] !== undefined) {\n\t\t\t\t\t\t\tn = this.notes[t];\n\t\t\t\t\t\t} else if (this.plainNotes[t] !== undefined) {\n\t\t\t\t\t\t\tn = this.plainNotes[t] + this.currentOctave * 12;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (n !== undefined && n !== note) {\n\t\t\t\t\t\t\t// Generate slide from note to n\n\t\t\t\t\t\t\tconst step = n > note ? 1 : -1;\n\t\t\t\t\t\t\tfor (let i = note + step; step > 0 ? i <= n : i >= n; i += step) {\n\t\t\t\t\t\t\t\tsequence.push({\n\t\t\t\t\t\t\t\t\tfrequency: A4_FREQUENCY * SEMITONE_RATIO ** (i - A4_MIDI_NOTE),\n\t\t\t\t\t\t\t\t\tvolume: this.currentVolume,\n\t\t\t\t\t\t\t\t\tspan: this.currentSpan,\n\t\t\t\t\t\t\t\t\tduration: this.currentDuration,\n\t\t\t\t\t\t\t\t\twaveform: this.currentWaveform,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnote = n;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Close any remaining loops\n\t\tif (loops.length > 0 && sequence.length > 0) {\n\t\t\tconst lop = loops.splice(loops.length - 1, 1)[0];\n\t\t\tsequence.push({\n\t\t\t\tfrequency: A4_FREQUENCY,\n\t\t\t\tvolume: 0,\n\t\t\t\tspan: this.currentSpan,\n\t\t\t\tduration: 0,\n\t\t\t\twaveform: this.currentWaveform,\n\t\t\t});\n\n\t\t\tsequence[sequence.length - 1].loopto = lop.start;\n\t\t\tsequence[sequence.length - 1].repeats = lop.repeats;\n\t\t}\n\n\t\tthis.audio.addBeeps(sequence);\n\t}\n}\n","/**\n * Music - Music streaming and playback using HTML5 Audio\n * L8B Music class for LootiScript\n */\nexport class Music {\n\tpublic ready: number = 1;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tpublic tag: HTMLAudioElement;\n\tpublic playing: boolean = false;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string) {\n\t\tthis.audio = audio;\n\t\tthis.url = url;\n\t\tthis.tag = new Audio(this.url);\n\t\tthis.ready = 1;\n\t}\n\n\t/**\n\t * Play music with volume and loop (HTML5 Audio implementation)\n\t */\n\tpublic play(volume: number = 1, loopit: boolean = false): any {\n\t\tthis.playing = true;\n\t\tthis.tag.loop = !!loopit;\n\t\tthis.tag.volume = Math.max(0, Math.min(1, volume));\n\n\t\tif (this.audio.isStarted()) {\n\t\t\tthis.tag.play();\n\t\t} else {\n\t\t\tthis.audio.addToWakeUpList(this);\n\t\t}\n\n\t\tthis.audio.addPlaying(this);\n\n\t\treturn {\n\t\t\tplay: () => {\n\t\t\t\treturn this.tag.play();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tthis.playing = false;\n\t\t\t\tthis.tag.pause();\n\t\t\t\tthis.audio.removePlaying(this);\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tthis.tag.volume = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tgetPosition: () => {\n\t\t\t\treturn this.tag.currentTime;\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn this.tag.duration;\n\t\t\t},\n\t\t\tsetPosition: (pos: number) => {\n\t\t\t\tthis.tag.pause();\n\t\t\t\tthis.tag.currentTime = Math.max(0, Math.min(this.tag.duration, pos));\n\t\t\t\tif (this.playing) {\n\t\t\t\t\tthis.tag.play();\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Wake up audio (for autoplay policy)\n\t */\n\tpublic wakeUp(): void {\n\t\tif (this.playing) {\n\t\t\tthis.tag.play();\n\t\t}\n\t}\n\n\t/**\n\t * Stop music\n\t */\n\tpublic stop(): void {\n\t\tthis.playing = false;\n\t\tthis.tag.pause();\n\t\tthis.audio.removePlaying(this);\n\t}\n}\n","/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\t\t\tcode: \"E7016\",\n\t\t\t\t\t\tmessage: \"Audio decoding failed\",\n\t\t\t\t\t\tdata: { error: `Audio decoding failed: ${String(err)}` },\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\tcode: \"E7016\",\n\t\t\t\tmessage: \"Failed to load sound\",\n\t\t\t\tdata: { error: `Failed to load sound: ${url}` },\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["A4_FREQUENCY","SEMITONE_RATIO","A4_MIDI_NOTE","Beeper","audio","notes","plainNotes","currentOctave","currentDuration","currentVolume","currentSpan","currentWaveform","initializeNotes","noteNames","i","oct","Math","floor","n","beep","input","status","sequence","loops","note","parsed","split","t","undefined","push","frequency","A4_FREQUENCY","SEMITONE_RATIO","A4_MIDI_NOTE","volume","span","duration","waveform","includes","length","lop","splice","loopto","start","repeats","tempo","Number","parseFloat","isNaN","step","addBeeps","Music","ready","name","url","tag","playing","audio","Audio","play","volume","loopit","loop","Math","max","min","isStarted","addToWakeUpList","addPlaying","stop","pause","removePlaying","setVolume","v","getPosition","currentTime","getDuration","duration","setPosition","pos","wakeUp","Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","runtime","listener","reportError","code","message","data","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Sound - Sound effect playback
3
+ * Handles loading and playing audio buffers
4
+ */
1
5
  declare class Sound {
2
6
  ready: number;
3
7
  buffer?: AudioBuffer;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Sound - Sound effect playback
3
+ * Handles loading and playing audio buffers
4
+ */
1
5
  declare class Sound {
2
6
  ready: number;
3
7
  buffer?: AudioBuffer;
@@ -24,7 +24,6 @@ __export(sound_exports, {
24
24
  Sound: () => Sound
25
25
  });
26
26
  module.exports = __toCommonJS(sound_exports);
27
- var import_diagnostics = require("@al8b/diagnostics");
28
27
  var Sound = class _Sound {
29
28
  static {
30
29
  __name(this, "Sound");
@@ -57,14 +56,22 @@ var Sound = class _Sound {
57
56
  this.buffer = buffer;
58
57
  this.ready = 1;
59
58
  }, (err) => {
60
- (0, import_diagnostics.reportRuntimeError)(this.audio?.runtime?.listener, import_diagnostics.APIErrorCode.E7016, {
61
- error: `Audio decoding failed: ${String(err)}`
59
+ this.audio?.runtime?.listener?.reportError?.({
60
+ code: "E7016",
61
+ message: "Audio decoding failed",
62
+ data: {
63
+ error: `Audio decoding failed: ${String(err)}`
64
+ }
62
65
  });
63
66
  });
64
67
  };
65
68
  request.onerror = () => {
66
- (0, import_diagnostics.reportRuntimeError)(this.audio?.runtime?.listener, import_diagnostics.APIErrorCode.E7016, {
67
- error: `Failed to load sound: ${url}`
69
+ this.audio?.runtime?.listener?.reportError?.({
70
+ code: "E7016",
71
+ message: "Failed to load sound",
72
+ data: {
73
+ error: `Failed to load sound: ${url}`
74
+ }
68
75
  });
69
76
  };
70
77
  request.send();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/devices/sound.ts"],"sourcesContent":["/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\t\t\terror: `Audio decoding failed: ${String(err)}`,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\terror: `Failed to load sound: ${url}`,\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","reportRuntimeError","runtime","listener","APIErrorCode","E7016","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
1
+ {"version":3,"sources":["../../src/devices/sound.ts"],"sourcesContent":["/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\t\t\tcode: \"E7016\",\n\t\t\t\t\t\tmessage: \"Audio decoding failed\",\n\t\t\t\t\t\tdata: { error: `Audio decoding failed: ${String(err)}` },\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\tcode: \"E7016\",\n\t\t\t\tmessage: \"Failed to load sound\",\n\t\t\t\tdata: { error: `Failed to load sound: ${url}` },\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","runtime","listener","reportError","code","message","data","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
@@ -2,7 +2,6 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/devices/sound.ts
5
- import { APIErrorCode, reportRuntimeError } from "@al8b/diagnostics";
6
5
  var Sound = class _Sound {
7
6
  static {
8
7
  __name(this, "Sound");
@@ -35,14 +34,22 @@ var Sound = class _Sound {
35
34
  this.buffer = buffer;
36
35
  this.ready = 1;
37
36
  }, (err) => {
38
- reportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {
39
- error: `Audio decoding failed: ${String(err)}`
37
+ this.audio?.runtime?.listener?.reportError?.({
38
+ code: "E7016",
39
+ message: "Audio decoding failed",
40
+ data: {
41
+ error: `Audio decoding failed: ${String(err)}`
42
+ }
40
43
  });
41
44
  });
42
45
  };
43
46
  request.onerror = () => {
44
- reportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {
45
- error: `Failed to load sound: ${url}`
47
+ this.audio?.runtime?.listener?.reportError?.({
48
+ code: "E7016",
49
+ message: "Failed to load sound",
50
+ data: {
51
+ error: `Failed to load sound: ${url}`
52
+ }
46
53
  });
47
54
  };
48
55
  request.send();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/devices/sound.ts"],"sourcesContent":["/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\t\t\terror: `Audio decoding failed: ${String(err)}`,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\treportRuntimeError(this.audio?.runtime?.listener, APIErrorCode.E7016, {\n\t\t\t\terror: `Failed to load sound: ${url}`,\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["APIErrorCode","reportRuntimeError","Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","reportRuntimeError","runtime","listener","APIErrorCode","E7016","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
1
+ {"version":3,"sources":["../../src/devices/sound.ts"],"sourcesContent":["/**\n * Sound - Sound effect playback\n * Handles loading and playing audio buffers\n */\n\nexport class Sound {\n\tpublic ready: number = 0;\n\tpublic buffer?: AudioBuffer;\n\tpublic name: string = \"\";\n\tpublic url: string;\n\tprivate audio: any;\n\n\tconstructor(audio: any, url: string | AudioBuffer) {\n\t\tthis.audio = audio;\n\n\t\tif (url instanceof AudioBuffer) {\n\t\t\tthis.buffer = url;\n\t\t\tthis.url = \"\";\n\t\t\tthis.ready = 1;\n\t\t} else {\n\t\t\tthis.url = url;\n\t\t\tthis.loadSound(url);\n\t\t}\n\t}\n\n\t/**\n\t * Load sound from URL\n\t */\n\tprivate loadSound(url: string): void {\n\t\tconst request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\n\t\trequest.onload = () => {\n\t\t\tthis.audio.context.decodeAudioData(\n\t\t\t\trequest.response,\n\t\t\t\t(buffer: AudioBuffer) => {\n\t\t\t\t\tthis.buffer = buffer;\n\t\t\t\t\tthis.ready = 1;\n\t\t\t\t},\n\t\t\t\t(err: any) => {\n\t\t\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\t\t\tcode: \"E7016\",\n\t\t\t\t\t\tmessage: \"Audio decoding failed\",\n\t\t\t\t\t\tdata: { error: `Audio decoding failed: ${String(err)}` },\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\trequest.onerror = () => {\n\t\t\tthis.audio?.runtime?.listener?.reportError?.({\n\t\t\t\tcode: \"E7016\",\n\t\t\t\tmessage: \"Failed to load sound\",\n\t\t\t\tdata: { error: `Failed to load sound: ${url}` },\n\t\t\t});\n\t\t};\n\n\t\trequest.send();\n\t}\n\n\t/**\n\t * Play sound with volume, pitch, pan, and loop\n\t */\n\tpublic play(volume: number = 1, pitch: number = 1, pan: number = 0, loopit: boolean = false): any {\n\t\tif (!this.buffer)\n\t\t\treturn {\n\t\t\t\tstop: () => {},\n\t\t\t\tfinished: true,\n\t\t\t};\n\n\t\tconst context = this.audio.context;\n\n\t\t// Create source\n\t\tconst source = context.createBufferSource();\n\t\tsource.playbackRate.value = pitch;\n\t\tsource.buffer = this.buffer;\n\t\tif (loopit) source.loop = true;\n\n\t\t// Create gain node\n\t\tconst gain = context.createGain();\n\t\tgain.gain.value = volume;\n\n\t\t// Create panner\n\t\tconst panner: any = context.createPanner();\n\t\tpanner.panningModel = \"equalpower\";\n\t\tpanner.setPan = (p: number) => {\n\t\t\tpanner.setPosition(p, 0, 1 - Math.abs(p));\n\t\t};\n\t\tpanner.setPan(pan);\n\n\t\t// Connect nodes\n\t\tsource.connect(gain);\n\t\tgain.connect(panner);\n\t\tpanner.connect(context.destination);\n\n\t\t// Start playback\n\t\tsource.start();\n\n\t\t// Track playing sounds for looping\n\t\tlet playing: any = null;\n\t\tif (loopit) {\n\t\t\tplaying = {\n\t\t\t\tstop: () => {\n\t\t\t\t\tsource.stop();\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis.audio.addPlaying(playing);\n\t\t}\n\n\t\t// Return control interface\n\t\tconst res = {\n\t\t\tstop: () => {\n\t\t\t\tsource.stop();\n\t\t\t\tif (playing) this.audio.removePlaying(playing);\n\t\t\t\treturn 1;\n\t\t\t},\n\t\t\tsetVolume: (v: number) => {\n\t\t\t\tgain.gain.value = Math.max(0, Math.min(1, v));\n\t\t\t},\n\t\t\tsetPitch: (p: number) => {\n\t\t\t\tsource.playbackRate.value = Math.max(0.001, Math.min(1000, p));\n\t\t\t},\n\t\t\tsetPan: (p: number) => {\n\t\t\t\tpanner.setPan(Math.max(-1, Math.min(1, p)));\n\t\t\t},\n\t\t\tgetDuration: () => {\n\t\t\t\treturn source.buffer ? source.buffer.duration : 0;\n\t\t\t},\n\t\t\tfinished: false,\n\t\t};\n\n\t\tsource.onended = () => {\n\t\t\tres.finished = true;\n\t\t};\n\n\t\treturn res;\n\t}\n\n\t/**\n\t * Create MicroSound class for procedural sound generation\n\t */\n\tpublic static createSoundClass(audiocore: any): any {\n\t\treturn class MicroSound {\n\t\t\tpublic static classname = \"Sound\";\n\t\t\tpublic channels: number;\n\t\t\tpublic length: number;\n\t\t\tpublic sampleRate: number;\n\t\t\tprivate sound: Sound;\n\t\t\tprivate buffer: AudioBuffer;\n\n\t\t\tconstructor(channels: number, length: number, sampleRate: number = 44100) {\n\t\t\t\t// Validate parameters\n\t\t\t\tchannels = channels === 1 ? 1 : 2;\n\t\t\t\tif (!(length > 1 && length < 44100 * 1000)) {\n\t\t\t\t\tlength = 44100;\n\t\t\t\t}\n\t\t\t\tif (!(sampleRate >= 8000 && sampleRate <= 96000)) {\n\t\t\t\t\tsampleRate = 44100;\n\t\t\t\t}\n\n\t\t\t\tthis.channels = channels;\n\t\t\t\tthis.length = length;\n\t\t\t\tthis.sampleRate = sampleRate;\n\n\t\t\t\t// Create audio buffer\n\t\t\t\tthis.buffer = audiocore.context.createBuffer(channels, length, sampleRate);\n\t\t\t\tthis.sound = new Sound(audiocore, this.buffer);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Play the sound\n\t\t\t */\n\t\t\tpublic play(volume?: number, pitch?: number, pan?: number, loopit?: boolean): any {\n\t\t\t\treturn this.sound.play(volume, pitch, pan, loopit);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write sample value to buffer\n\t\t\t */\n\t\t\tpublic write(channel: number, position: number, value: number): void {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\tch1[position] = value;\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\tch2[position] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Read sample value from buffer\n\t\t\t */\n\t\t\tpublic read(channel: number, position: number): number {\n\t\t\t\tif (channel === 0) {\n\t\t\t\t\tconst ch1 = this.buffer.getChannelData(0);\n\t\t\t\t\treturn ch1[position];\n\t\t\t\t} else if (this.channels === 2) {\n\t\t\t\t\tconst ch2 = this.buffer.getChannelData(1);\n\t\t\t\t\treturn ch2[position];\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["Sound","ready","buffer","name","url","audio","AudioBuffer","loadSound","request","XMLHttpRequest","open","responseType","onload","context","decodeAudioData","response","err","runtime","listener","reportError","code","message","data","error","String","onerror","send","play","volume","pitch","pan","loopit","stop","finished","source","createBufferSource","playbackRate","value","loop","gain","createGain","panner","createPanner","panningModel","setPan","p","setPosition","Math","abs","connect","destination","start","playing","addPlaying","res","removePlaying","setVolume","v","max","min","setPitch","getDuration","duration","onended","createSoundClass","audiocore","MicroSound","classname","channels","length","sampleRate","sound","createBuffer","write","channel","position","ch1","getChannelData","ch2","read"]}
package/dist/index.js CHANGED
@@ -28,9 +28,6 @@ __export(index_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(index_exports);
30
30
 
31
- // src/core/audio-core.ts
32
- var import_diagnostics = require("@al8b/diagnostics");
33
-
34
31
  // src/constants.ts
35
32
  var A4_FREQUENCY = 440;
36
33
  var SEMITONE_RATIO = 2 ** (1 / 12);
@@ -479,8 +476,12 @@ var AudioCore = class {
479
476
  const soundName = sound.replace(/\//g, "-");
480
477
  const s = this.runtime.sounds[soundName];
481
478
  if (!s) {
482
- (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7013, {
483
- soundName
479
+ this.runtime?.listener?.reportError?.({
480
+ code: "E7013",
481
+ message: "Sound not found",
482
+ data: {
483
+ soundName
484
+ }
484
485
  });
485
486
  return 0;
486
487
  }
@@ -496,8 +497,12 @@ var AudioCore = class {
496
497
  const musicName = music.replace(/\//g, "-");
497
498
  const m = this.runtime.music[musicName];
498
499
  if (!m) {
499
- (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7014, {
500
- musicName
500
+ this.runtime?.listener?.reportError?.({
501
+ code: "E7014",
502
+ message: "Music not found",
503
+ data: {
504
+ musicName
505
+ }
501
506
  });
502
507
  return 0;
503
508
  }
@@ -564,8 +569,12 @@ var AudioCore = class {
564
569
  this.workletNode.connect(this.context.destination);
565
570
  this.flushBuffer();
566
571
  } catch (e) {
567
- (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7012, {
568
- error: String(e)
572
+ this.runtime?.listener?.reportError?.({
573
+ code: "E7012",
574
+ message: "Audio worklet error",
575
+ data: {
576
+ error: String(e)
577
+ }
569
578
  });
570
579
  }
571
580
  }
@@ -654,8 +663,12 @@ var AudioCore = class {
654
663
  try {
655
664
  p.stop();
656
665
  } catch (err) {
657
- (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7016, {
658
- error: String(err)
666
+ this.runtime?.listener?.reportError?.({
667
+ code: "E7016",
668
+ message: "Audio error",
669
+ data: {
670
+ error: String(err)
671
+ }
659
672
  });
660
673
  }
661
674
  }
@@ -739,7 +752,6 @@ var Music = class {
739
752
  };
740
753
 
741
754
  // src/devices/sound.ts
742
- var import_diagnostics2 = require("@al8b/diagnostics");
743
755
  var Sound = class _Sound {
744
756
  static {
745
757
  __name(this, "Sound");
@@ -772,14 +784,22 @@ var Sound = class _Sound {
772
784
  this.buffer = buffer;
773
785
  this.ready = 1;
774
786
  }, (err) => {
775
- (0, import_diagnostics2.reportRuntimeError)(this.audio?.runtime?.listener, import_diagnostics2.APIErrorCode.E7016, {
776
- error: `Audio decoding failed: ${String(err)}`
787
+ this.audio?.runtime?.listener?.reportError?.({
788
+ code: "E7016",
789
+ message: "Audio decoding failed",
790
+ data: {
791
+ error: `Audio decoding failed: ${String(err)}`
792
+ }
777
793
  });
778
794
  });
779
795
  };
780
796
  request.onerror = () => {
781
- (0, import_diagnostics2.reportRuntimeError)(this.audio?.runtime?.listener, import_diagnostics2.APIErrorCode.E7016, {
782
- error: `Failed to load sound: ${url}`
797
+ this.audio?.runtime?.listener?.reportError?.({
798
+ code: "E7016",
799
+ message: "Failed to load sound",
800
+ data: {
801
+ error: `Failed to load sound: ${url}`
802
+ }
783
803
  });
784
804
  };
785
805
  request.send();