code wiki / (root) / nx_audio_mix.nx

nx_audio_mix.nx source

↩ module page · 58 lines · 2066 B

1// nx_audio_mix.nx -- SOVEREIGN AUDIO ENGINE, rung R0: the PCM mixer atom. 2// 3// Direct answer to "no FMOD/Wwise -- build S-class from the hardware rung up." 4// The core of ANY audio engine (FMOD included) is summing sample streams with 5// per-source gain and clamping to the sample range. This is that, in raw integer 6// PCM math -- no third party, deterministic, inspectable. Samples are i64 in the 7// signed-16-bit range; gain is Q8 fixed point (256 = 1.0x). Later rungs: N-chan, 8// resample, stereo pan, oscillators/ADSR, filters/reverb, 3D spatialization, 9// codecs -- the ladder to EXCEED FMOD (sovereign + no licensing + deterministic). 10// license_tier: ORIGINAL. 11 12import "nx_syscalls.nx" 13 14const AE_GAIN_UNIT: i64 = 256 // Q8 gain: 256 = 1.0x, 128 = 0.5x 15const AE_SMAX: i64 = 32767 // i16 max 16const AE_SMIN: i64 = 0 - 32768 // i16 min 17 18// clamp a mixed sample to the i16 range (prevents wrap/overflow distortion) 19func ae_clamp(x: i64) -> i64 { 20 if x > AE_SMAX { return AE_SMAX } 21 if x < AE_SMIN { return AE_SMIN } 22 return x 23} 24 25// mix two sample buffers with Q8 gains into out[0..n), clamped 26func ae_mix2(a: *i64, b: *i64, ga: i64, gb: i64, out: *i64, n: i64) -> i64 { 27 var i: i64 = 0 28 while i < n { 29 let s: i64 = (a[i] * ga + b[i] * gb) / AE_GAIN_UNIT 30 out[i] = ae_clamp(s) 31 i = i + 1 32 } 33 return n 34} 35 36// mix K sources (srcs[j] = *i64 buffer as i64) with Q8 gains[j] into out[0..n) 37func ae_mixn(srcs: *i64, gains: *i64, k: i64, out: *i64, n: i64) -> i64 { 38 var i: i64 = 0 39 while i < n { 40 var acc: i64 = 0 41 var j: i64 = 0 42 while j < k { 43 let buf: *i64 = srcs[j] as *i64 44 acc = acc + buf[i] * gains[j] 45 j = j + 1 46 } 47 out[i] = ae_clamp(acc / AE_GAIN_UNIT) 48 i = i + 1 49 } 50 return n 51} 52 53// apply a Q8 gain (volume) to a buffer in place, clamped 54func ae_gain(buf: *i64, g: i64, n: i64) -> i64 { 55 var i: i64 = 0 56 while i < n { buf[i] = ae_clamp((buf[i] * g) / AE_GAIN_UNIT); i = i + 1 } 57 return n 58}