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}