code wiki / (root) / nx_audio_dred.nx

nx_audio_dred.nx source

↩ module page · 40 lines · 2132 B

1// nx_audio_dred.nx -- DEEP REDUNDANCY for voice, the keystone for surviving bursty mobile packet loss WITHOUT a 2// retransmit (at 150ms RTT a retransmit is a dead frame). The Opus-1.5 DRED idea, classical first: every packet carries 3// a heavily-quantised "redundancy tail" = coarse copies of the previous K frames (just the LPC reflection envelope + 4// energy, enough to resynthesise an intelligible frame). When a burst loses B<=K consecutive frames, the first packet 5// that arrives after the burst carries coarse copies of the whole gap -> the receiver reconstructs every lost frame with 6// no retransmit. K sets the recoverable burst length (~1s of audio at K=50 @ 20ms frames). Pure integer; the neural 7// codebook (true DRED's 12-32kb/s for 1s) is the phone-CPU moonshot on top of this scheduler. license_tier: ORIGINAL 8 9// coarse-quantise a reflection coeff (Q15, |k|<1) to i8 (Q7) for the tail, and back (lossy -- the spectral envelope at 10// reduced precision; the excitation is regenerated on recovery). 11func dred_coarse_q(k_q15: i64) -> i64 { return k_q15 >> 8 } 12func dred_coarse_dq(k_q7: i64) -> i64 { return k_q7 << 8 } 13 14// recovery scheduler: given a per-frame lost bitmap (lost[i]=1 lost), n frames, and redundancy depth K (each packet's 15// tail covers the previous K frames), count how many lost frames remain GAPS (no later non-lost packet within K carries 16// their coarse copy). A lost frame j is recoverable iff some packet p in [j+1, j+K] arrived (not lost). 17func dred_gaps(lost: *i64, n: i64, K: i64) -> i64 { 18 var gaps: i64 = 0 19 var j: i64 = 0 20 while j < n { 21 if lost[j] == 1 { 22 var rec: i64 = 0 23 var p: i64 = j + 1 24 while p <= j + K { 25 if p < n { if lost[p] == 0 { rec = 1 } } 26 p = p + 1 27 } 28 if rec == 0 { gaps = gaps + 1 } 29 } 30 j = j + 1 31 } 32 return gaps 33} 34// recovered = total lost - gaps 35func dred_recovered(lost: *i64, n: i64, K: i64) -> i64 { 36 var nl: i64 = 0 37 var i: i64 = 0 38 while i < n { if lost[i] == 1 { nl = nl + 1 } i = i + 1 } 39 return nl - dred_gaps(lost, n, K) 40}