code wiki / (root) / nx_fidelity.nx

nx_fidelity.nx source

↩ module page · 86 lines · 3159 B

1// nx_fidelity.nx -- Calculates segmental SNR as a deci-dB fidelity metric for audio reconstruction quality. 2const FID_MAGIC_131072: i64 = 131072 3const FID_MAGIC_65536: i64 = 65536 4const FID_MAGIC_32768: i64 = 32768 5// nx_fidelity.nx -- AUDIO arc R6: a sovereign FIDELITY metric. Grades how 6// faithfully a reconstruction (a clone, a codec output, an LPC resynthesis) 7// matches a reference, so clone/codec quality is MEASURED, not asserted. 8// 9// Segmental SNR: per frame, 10*log10( sum(ref^2) / sum((ref-test)^2) ), averaged. 10// Higher dB = closer. Uses a sovereign integer log2 (normalize + 16-iteration 11// mantissa squaring, the classic fixed-point log) converted to dB via the 12// constant 10/log2(10). Returned in DECI-decibels (dB*10) for resolution; an 13// exact reconstruction (zero error) caps at 99.0 dB. 14// 15// Pure integer, NO floats, NO imports (caller owns the buffers). 16// nx_segsnr(ref, test, n, frame) -> deci-dB (dB*10) 17// 18// license_tier: ORIGINAL 19// module: nishi-core.audio.fidelity 20// capability: AUDIO_FIDELITY_METRIC 21 22const FID_LOG10_K: i64 = 197336 // 10/log2(10) = 3.0103 in Q16.16 23const FID_CAP_DDB: i64 = 990 // 99.0 dB cap (deci-dB) for near-zero error 24 25// log2(x) for a Q16.16 value x (65536 = 1.0); returns Q16.16. 26func _fid_log2_q16(x: i64) -> i64 { 27 if x <= 0 { return 0 } 28 var v: i64 = x 29 var ip: i64 = 0 30 while v >= FID_MAGIC_131072 { v = v >> 1; ip = ip + 1 } // bring into [1,2) 31 while v < FID_MAGIC_65536 { v = v << 1; ip = ip - 1 } 32 var result: i64 = ip << 16 33 var b: i64 = FID_MAGIC_32768 // mantissa bit weight (Q16 .5) 34 var i: i64 = 0 35 while i < 16 { 36 v = (v * v) >> 16 37 if v >= FID_MAGIC_131072 { v = v >> 1; result = result + b } 38 b = b >> 1 39 i = i + 1 40 } 41 return result 42} 43 44func _fid_i16(p: *u8, i: i64) -> i64 { 45 let lo: i64 = p[i * 2] 46 let hi: i64 = p[i * 2 + 1] 47 var v: i64 = lo | (hi << 8) 48 if v >= 0x8000 { v = v - 0x10000 } 49 return v 50} 51 52func nx_segsnr(ref: *u8, test: *u8, n: i64, frame: i64) -> i64 { 53 var nf: i64 = 0 54 var acc: i64 = 0 55 var f: i64 = 0 56 while (f + 1) * frame <= n { 57 let st: i64 = f * frame 58 var sig: i64 = 0 59 var err: i64 = 0 60 var j: i64 = 0 61 while j < frame { 62 let r: i64 = _fid_i16(ref, st + j) 63 let t: i64 = _fid_i16(test, st + j) 64 sig = sig + r * r 65 let d: i64 = r - t 66 err = err + d * d 67 j = j + 1 68 } 69 var ddb: i64 = FID_CAP_DDB // default = error ~0 -> cap 70 if sig == 0 { ddb = 0 } 71 if err > 0 { 72 if sig > 0 { 73 let ratio_q16: i64 = (sig << 16) / err 74 let l2: i64 = _fid_log2_q16(ratio_q16) 75 let db_q16: i64 = (l2 * FID_LOG10_K) >> 16 // 10*log10(ratio), Q16 76 ddb = (db_q16 * 10) >> 16 // deci-dB (can be <0) 77 if ddb > FID_CAP_DDB { ddb = FID_CAP_DDB } 78 } 79 } 80 acc = acc + ddb 81 nf = nf + 1 82 f = f + 1 83 } 84 if nf < 1 { return 0 } 85 return acc / nf 86}