feat(packages): ludic.audio - world sounds with a gain, a pan and a pitch from where they are relative to a listener port, flat interface sounds, clips loaded past Audio.load's blind spot for packed assets, loops and the master volume; the one door to Audio.*
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
47ba3d9028
commit
fdf9866e88
10 changed files with 338 additions and 0 deletions
43
packages/ludic.audio/emit.ludic
Normal file
43
packages/ludic.audio/emit.ludic
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# emit.ludic - the only calls into the runtime's playback. aud_emit is the ONE place a float
|
||||
# crosses into Audio.play_at's Q16.16: handed over unconverted, 0.94 as a pitch clamped to 4x and
|
||||
# -0.85 as a pan to hard left, and every sound in a valley played fast out of one speaker
|
||||
var last_gain: float = 0.0
|
||||
var last_pitch: float = 0.0
|
||||
var last_pan: float = 0.0
|
||||
var emitted: int = 0
|
||||
|
||||
export function aud_emit(h: int, gain: float, pitch: float, pan: float) -> void {
|
||||
if h == 0 { return }
|
||||
last_gain = gain
|
||||
last_pitch = pitch
|
||||
last_pan = pan
|
||||
emitted += 1
|
||||
Audio.play_at(h, fixed(gain), fixed(pitch), fixed(pan))
|
||||
}
|
||||
|
||||
# a sound at a place in the world, heard within `range` metres: false (and nothing played) when the
|
||||
# listener is out of earshot
|
||||
export function aud_emit_at(h: int, x: float, z: float, range: float) -> bool {
|
||||
let g = aud_gain_at(x, z, range)
|
||||
if g == 0.0 { return false }
|
||||
aud_emit(h, g, aud_pitch_at(g), aud_pan_at(x, z))
|
||||
return true
|
||||
}
|
||||
|
||||
# a click, a chime, a shutter, a warning: in the player's head, flat
|
||||
export function aud_ui(h: int) -> void {
|
||||
if h == 0 { return }
|
||||
emitted += 1
|
||||
Audio.play(h)
|
||||
}
|
||||
|
||||
export function aud_music(h: int) -> void { if h != 0 { Audio.play_music(h) } }
|
||||
export function aud_stop_music() -> void { Audio.stop_music() }
|
||||
export function aud_master(v: float) -> void { Audio.volume(fixed(Math.clamp(v, 0.0, 1.0))) }
|
||||
|
||||
# what the last emit handed the runtime, and how many shots so far: Audio.* is a no-op headless, so
|
||||
# the numbers are the only thing a test can hear
|
||||
export function aud_last_gain() -> float { return last_gain }
|
||||
export function aud_last_pitch() -> float { return last_pitch }
|
||||
export function aud_last_pan() -> float { return last_pan }
|
||||
export function aud_emitted() -> int { return emitted }
|
||||
Loading…
Add table
Add a link
Reference in a new issue