code wiki / (root) / nx_audio_spatial.nx

nx_audio_spatial.nx source

↩ module page · 34 lines · 1492 B

1// nx_audio_spatial.nx -- SOVEREIGN AUDIO ENGINE rung R6: 3D positional audio. 2// 3// Places a mono source at (sx,sy) relative to a listener at the origin: distance 4// drives a linear rolloff attenuation over max_dist, horizontal offset drives the 5// L/R balance. This is what makes game audio spatial (footsteps to your left, 6// etc.). Includes a sovereign integer sqrt (Newton's method). Reuses ae_clamp. 7// license_tier: ORIGINAL. 8 9import "nx_syscalls.nx" 10import "nx_audio_mix.nx" 11import "nx_isqrt.nx" // CANONICAL integer sqrt -- removed a local Newton duplicate (DRY) 12 13// place mono[0..n) at (sx,sy) into stereo outL/outR; atten by distance, pan by sx 14func spatial_place(mono: *i64, n: i64, sx: i64, sy: i64, max_dist: i64, outL: *i64, outR: *i64) -> i64 { 15 let d: i64 = nx_isqrt(sx * sx + sy * sy) 16 var atten: i64 = 0 // Q8 distance gain 17 if d < max_dist { atten = ((max_dist - d) * 256) / max_dist } 18 var gl: i64 = 128 // Q8 L/R balance (centered default) 19 var gr: i64 = 128 20 if d > 0 { 21 let frac: i64 = (sx * 256) / d // -256..256 (left..right) 22 gr = (frac + 256) / 2 // 0..256 23 gl = 256 - gr 24 } 25 let fl: i64 = (atten * gl) / 256 26 let fr: i64 = (atten * gr) / 256 27 var i: i64 = 0 28 while i < n { 29 outL[i] = ae_clamp((mono[i] * fl) / 256) 30 outR[i] = ae_clamp((mono[i] * fr) / 256) 31 i = i + 1 32 } 33 return n 34}