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