code wiki / (root) / nx_vcodec_nf.nx

nx_vcodec_nf.nx source

↩ module page · 92 lines · 4339 B

1// nx_vcodec_nf.nx -- LEARNED decoder-side RESTORATION FILTER (NEURAL track rung 1, task #46; operator 2// 2026-07-07: "achieve true neural sota as we climb ... and these things are all going live"). 3// A data-TRAINED piecewise-linear restorer (RAISR/Wiener-class -- the same family as AV1's loop 4// restoration): every interior pixel of the DEBLOCKED recon is classified by its local gradient 5// (flat + 4 directions x 2 strengths = 9 classes) inside a qp band (3 bands), and restored by that 6// class's TRAINED 3x3+bias filter (Q12 integer weights, trained by nx_vcodec_nf_train on 7// (our-codec-recon -> source) pairs from REAL frames -- no floats anywhere, sovereign end to end). 8// DISPLAY-PATH ONLY by design: the P-reference chain keeps the unfiltered recon (bit-exactness of the 9// codec is untouched; a receiver applies this after decode, before YUV->RGBA). The trained table is 10// caller-provided (vc_nf_load from the GENERATED nx_vcodec_nf_table.nx fills it) -- this module stays 11// allocation-free and wasm-clean. license_tier: ORIGINAL 12import "nx_syscalls.nx" 13 14const VC_NF_CLASSES: i64 = 9 // 0=flat, 1..4 = H/V/D1/D2 moderate, 5..8 = H/V/D1/D2 strong 15const VC_NF_BANDS: i64 = 3 // qp bands: <16, 16..27, >=28 (quant noise scales with qp) 16const VC_NF_TAPS: i64 = 10 // 3x3 raster taps + bias, Q12 17const VC_NF_TBL: i64 = 270 // table length in i64 (bands * classes * taps) 18 19func vc_nf_band(qp: i64) -> i64 { 20 if qp < 16 { return 0 } 21 if qp < 28 { return 1 } 22 return 2 23} 24// gradient classifier. The bin edges (8 = below-noise-floor sum, 48 = strong-edge sum, 2x = direction 25// dominance) only PARTITION the data -- the trained per-class weights adapt to whatever falls in each 26// bin, so these are classifier geometry, not quality knobs. 27func vc_nf_class(gx: i64, gy: i64) -> i64 { 28 var ax: i64 = gx 29 if ax < 0 { ax = 0 - ax } 30 var ay: i64 = gy 31 if ay < 0 { ay = 0 - ay } 32 if ax + ay < 8 { return 0 } 33 var d: i64 = 0 34 if ax >= 2*ay { d = 1 } else { 35 if ay >= 2*ax { d = 2 } else { 36 var s: i64 = 1 37 if gx < 0 { s = 0 - s } 38 if gy < 0 { s = 0 - s } 39 if s >= 0 { d = 3 } else { d = 4 } 40 } 41 } 42 if ax + ay >= 48 { return d + 4 } 43 return d 44} 45// apply the trained filter: src (deblocked recon plane) -> out. Interior pixels restored, 1-px border 46// copied. out MUST be a different buffer (the 3x3 context reads pre-filter values by construction). 47func vc_nf_apply(src: *u8, W: i64, H: i64, out: *u8, qp: i64, tbl: *i64) -> i64 { 48 let boff: i64 = vc_nf_band(qp) * VC_NF_CLASSES * VC_NF_TAPS 49 var x: i64 = 0 50 while x < W { out[x] = src[x]; out[(H-1)*W + x] = src[(H-1)*W + x]; x = x + 1 } 51 var y: i64 = 1 52 while y < H - 1 { 53 let r0: i64 = (y-1) * W 54 let r1: i64 = y * W 55 let r2: i64 = (y+1) * W 56 out[r1] = src[r1] 57 out[r1 + W - 1] = src[r1 + W - 1] 58 var xx: i64 = 1 59 while xx < W - 1 { 60 let p00: i64 = src[r0 + xx - 1] as i64 61 let p01: i64 = src[r0 + xx] as i64 62 let p02: i64 = src[r0 + xx + 1] as i64 63 let p10: i64 = src[r1 + xx - 1] as i64 64 let p11: i64 = src[r1 + xx] as i64 65 let p12: i64 = src[r1 + xx + 1] as i64 66 let p20: i64 = src[r2 + xx - 1] as i64 67 let p21: i64 = src[r2 + xx] as i64 68 let p22: i64 = src[r2 + xx + 1] as i64 69 let cls: i64 = vc_nf_class(p12 - p10, p21 - p01) 70 let base: i64 = boff + cls * VC_NF_TAPS 71 var acc: i64 = tbl[base]*p00 + tbl[base+1]*p01 + tbl[base+2]*p02 72 acc = acc + tbl[base+3]*p10 + tbl[base+4]*p11 + tbl[base+5]*p12 73 acc = acc + tbl[base+6]*p20 + tbl[base+7]*p21 + tbl[base+8]*p22 74 acc = acc + tbl[base+9] 75 var v: i64 = (acc + 2048) >> 12 76 if v < 0 { v = 0 } 77 if v > 255 { v = 255 } 78 out[r1 + xx] = v as u8 79 xx = xx + 1 80 } 81 y = y + 1 82 } 83 return 0 84} 85// identity table (center tap = 1.0): the safe do-nothing baseline the trainer must beat. 86func vc_nf_identity(tbl: *i64) -> i64 { 87 var i: i64 = 0 88 while i < VC_NF_TBL { tbl[i] = 0; i = i + 1 } 89 var bc: i64 = 0 90 while bc < VC_NF_BANDS * VC_NF_CLASSES { tbl[bc * VC_NF_TAPS + 4] = 4096; bc = bc + 1 } 91 return 0 92}