code wiki / (root) / nx_flac_frame.nx

nx_flac_frame.nx source

↩ module page · 311 lines · 10488 B

1// nx_flac_frame.nx -- FLAC frame and subframe decoding. 2// 3// Completes the FLAC decode path. nx_flac.nx holds the maths (Rice, fixed and 4// LPC predictors, stereo decorrelation, CRC-8, the header tables); this reads 5// an actual frame off a bitstream and turns it into samples. 6// 7// THE HEADER LENGTH IS NOT FIXED. A frame header is 4 bytes of flags, then a 8// UTF-8-style extended number of 1-7 bytes, then optionally an 8- or 16-bit 9// block size, then optionally an 8- or 16-bit sample rate, then the CRC-8. 10// The CRC covers exactly those bytes and no more, so the parser has to know 11// where it stopped. Hard-coding a length is the classic FLAC bug: it works on 12// every small file (frame number < 128, standard block size and rate) and 13// fails the moment a stream runs past frame 127. 14// 15// THE PARTITION SPLIT IS UNEVEN. Residuals are Rice-coded in 2^order 16// partitions, and the FIRST partition is short by the predictor order because 17// those samples are warm-up, already carried literally. Every later partition 18// is full width. Splitting evenly decodes without error and desyncs the 19// bitstream by exactly `order` samples. 20// 21// genealogy_id: flac_format_spec_frame 22// lineage_id: nx_flac_frame_v1 23// license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26import "nx_bitstream.nx" 27import "nx_flac.nx" 28 29const NX_FLACF_SYNC: i64 = 0x3ffe 30const NX_FLACF_ESC4: i64 = 15 31const NX_FLACF_ESC5: i64 = 31 32 33// frame field slots 34const NX_FLACF_FLD_BLOCKSIZE: i64 = 0 35const NX_FLACF_FLD_RATE: i64 = 1 36const NX_FLACF_FLD_CHANNELS: i64 = 2 37const NX_FLACF_FLD_CHANASSIGN:i64 = 3 38const NX_FLACF_FLD_BPS: i64 = 4 39const NX_FLACF_FLD_NUMBER: i64 = 5 40const NX_FLACF_FLD_HDRLEN: i64 = 6 41 42// ===== UTF-8-style extended number ================================ 43// 44// FLAC borrows UTF-8's shape but allows up to 7 bytes (36 bits) so a sample 45// number can address a very long stream. Returns -1 on a malformed leader. 46 47func nx_flac_utf8_len(first: i64) -> i64 { 48 let b: i64 = first & 255 49 if (b & 0x80) == 0 { return 1 } 50 if (b & 0xe0) == 0xc0 { return 2 } 51 if (b & 0xf0) == 0xe0 { return 3 } 52 if (b & 0xf8) == 0xf0 { return 4 } 53 if (b & 0xfc) == 0xf8 { return 5 } 54 if (b & 0xfe) == 0xfc { return 6 } 55 if b == 0xfe { return 7 } 56 return 0 - 1 57} 58 59func nx_flac_utf8_read(data: *u8, n: i64, off: i64, out_len: *i64) -> i64 { 60 if off >= n { return 0 - 1 } 61 let first: i64 = (data[off] as i64) & 255 62 let len: i64 = nx_flac_utf8_len(first) 63 if len < 0 { return 0 - 1 } 64 if off + len > n { return 0 - 1 } 65 out_len[0] = len 66 if len == 1 { return first } 67 68 // the leader carries (7 - len) payload bits 69 var v: i64 = first & ((1 << (7 - len)) - 1) 70 var i: i64 = 1 71 while i < len { 72 let c: i64 = (data[off + i] as i64) & 255 73 if (c & 0xc0) != 0x80 { return 0 - 1 } 74 v = (v << 6) | (c & 0x3f) 75 i = i + 1 76 } 77 return v 78} 79 80// ===== frame header =============================================== 81// 82// Returns 1 and fills fld, or 0. The CRC-8 is checked over exactly the header 83// bytes consumed -- computing the length is the whole job. 84 85func nx_flac_frame_parse(data: *u8, n: i64, off: i64, fld: *i64) -> i64 { 86 if off + 5 > n { return 0 } 87 let b0: i64 = (data[off] as i64) & 255 88 let b1: i64 = (data[off+1] as i64) & 255 89 // 14-bit sync then a reserved zero 90 if b0 != 0xff { return 0 } 91 if (b1 & 0xfc) != 0xf8 { return 0 } 92 93 let b2: i64 = (data[off+2] as i64) & 255 94 let b3: i64 = (data[off+3] as i64) & 255 95 let bs_code: i64 = (b2 >> 4) & 15 96 let sr_code: i64 = b2 & 15 97 let ch_code: i64 = (b3 >> 4) & 15 98 let bps_code: i64 = (b3 >> 1) & 7 99 if (b3 & 1) != 0 { return 0 } 100 101 var blocksize: i64 = nx_flac_block_size(bs_code) 102 if blocksize < 0 { return 0 } 103 var rate: i64 = nx_flac_sample_rate(sr_code) 104 if rate < 0 { return 0 } 105 let bps: i64 = nx_flac_bit_depth(bps_code) 106 if bps < 0 { return 0 } 107 if ch_code > 10 { return 0 } 108 109 let ulen: *i64 = sys_mmap(64) as *i64 110 let number: i64 = nx_flac_utf8_read(data, n, off + 4, ulen) 111 if number < 0 { return 0 } 112 var p: i64 = off + 4 + ulen[0] 113 114 // deferred block size 115 if bs_code == 6 { 116 if p + 1 > n { return 0 } 117 blocksize = ((data[p] as i64) & 255) + 1 118 p = p + 1 119 } 120 if bs_code == 7 { 121 if p + 2 > n { return 0 } 122 blocksize = ((((data[p] as i64) & 255) << 8) | ((data[p+1] as i64) & 255)) + 1 123 p = p + 2 124 } 125 // deferred sample rate 126 if sr_code == 12 { 127 if p + 1 > n { return 0 } 128 rate = ((data[p] as i64) & 255) * 1000 129 p = p + 1 130 } 131 if sr_code == 13 { 132 if p + 2 > n { return 0 } 133 rate = (((data[p] as i64) & 255) << 8) | ((data[p+1] as i64) & 255) 134 p = p + 2 135 } 136 if sr_code == 14 { 137 if p + 2 > n { return 0 } 138 rate = ((((data[p] as i64) & 255) << 8) | ((data[p+1] as i64) & 255)) * 10 139 p = p + 2 140 } 141 142 if p + 1 > n { return 0 } 143 let stored_crc: i64 = (data[p] as i64) & 255 144 let calc: i64 = nx_flac_crc8(data + off, p - off) 145 if calc != stored_crc { return 0 } 146 p = p + 1 147 148 var channels: i64 = ch_code + 1 149 if ch_code >= 8 { channels = 2 } 150 151 fld[NX_FLACF_FLD_BLOCKSIZE] = blocksize 152 fld[NX_FLACF_FLD_RATE] = rate 153 fld[NX_FLACF_FLD_CHANNELS] = channels 154 fld[NX_FLACF_FLD_CHANASSIGN] = ch_code 155 fld[NX_FLACF_FLD_BPS] = bps 156 fld[NX_FLACF_FLD_NUMBER] = number 157 fld[NX_FLACF_FLD_HDRLEN] = p - off 158 return 1 159} 160 161// ===== signed field off the bitstream ============================= 162 163func nx_flac_read_signed(bs: *NxBitStream, bits: i64) -> i64 { 164 if bits <= 0 { return 0 } 165 let v: i64 = nx_bitstream_read_msb(bs, bits) 166 let sign: i64 = 1 << (bits - 1) 167 if (v & sign) != 0 { return v - (1 << bits) } 168 return v 169} 170 171// ===== residual =================================================== 172// 173// Rice partitions. The FIRST partition is short by the predictor order. 174 175func nx_flac_read_residual(bs: *NxBitStream, buf: *i64, blocksize: i64, order: i64) -> i64 { 176 let method: i64 = nx_bitstream_read_msb(bs, 2) 177 if method > 1 { return 0 } 178 var param_bits: i64 = 4 179 var escape: i64 = NX_FLACF_ESC4 180 if method == 1 { param_bits = 5; escape = NX_FLACF_ESC5 } 181 182 let porder: i64 = nx_bitstream_read_msb(bs, 4) 183 let nparts: i64 = 1 << porder 184 if blocksize % nparts != 0 { return 0 } 185 let part_len: i64 = blocksize >> porder 186 if part_len < order { return 0 } 187 188 var idx: i64 = order 189 var pi: i64 = 0 190 while pi < nparts { 191 var count: i64 = part_len 192 if pi == 0 { count = part_len - order } 193 let param: i64 = nx_bitstream_read_msb(bs, param_bits) 194 if param == escape { 195 let raw_bits: i64 = nx_bitstream_read_msb(bs, 5) 196 var k: i64 = 0 197 while k < count { 198 buf[idx] = nx_flac_read_signed(bs, raw_bits) 199 idx = idx + 1 200 k = k + 1 201 } 202 } else { 203 var k2: i64 = 0 204 while k2 < count { 205 buf[idx] = nx_flac_read_rice(bs, param) 206 idx = idx + 1 207 k2 = k2 + 1 208 } 209 } 210 if bs.overflow == 1 { return 0 } 211 pi = pi + 1 212 } 213 return 1 214} 215 216// ===== one subframe =============================================== 217// 218// Writes blocksize samples into buf. Returns 1, or 0 on a malformed subframe. 219 220func nx_flac_subframe(bs: *NxBitStream, buf: *i64, blocksize: i64, bps: i64) -> i64 { 221 if nx_bitstream_read_msb(bs, 1) != 0 { return 0 } 222 let type_code: i64 = nx_bitstream_read_msb(bs, 6) 223 let has_wasted: i64 = nx_bitstream_read_msb(bs, 1) 224 var wasted: i64 = 0 225 if has_wasted == 1 { 226 var k: i64 = 1 227 var go: i64 = 1 228 while go == 1 { 229 if nx_bitstream_read_msb(bs, 1) == 1 { go = 0 } else { 230 k = k + 1 231 if k > 32 { return 0 } 232 } 233 } 234 wasted = k 235 } 236 let eff: i64 = bps - wasted 237 if eff <= 0 { return 0 } 238 239 var ok: i64 = 0 240 if type_code == 0 { 241 // CONSTANT 242 let v: i64 = nx_flac_read_signed(bs, eff) 243 var i: i64 = 0 244 while i < blocksize { buf[i] = v; i = i + 1 } 245 ok = 1 246 } else { 247 if type_code == 1 { 248 // VERBATIM 249 var i: i64 = 0 250 while i < blocksize { buf[i] = nx_flac_read_signed(bs, eff); i = i + 1 } 251 ok = 1 252 } else { 253 if type_code >= 8 { 254 if type_code <= 12 { 255 // FIXED, order = type_code - 8 256 let order: i64 = type_code - 8 257 var i: i64 = 0 258 while i < order { buf[i] = nx_flac_read_signed(bs, eff); i = i + 1 } 259 if nx_flac_read_residual(bs, buf, blocksize, order) == 0 { return 0 } 260 if nx_flac_restore_fixed(buf, blocksize, order) == 0 { return 0 } 261 ok = 1 262 } else { 263 if type_code >= 32 { 264 // LPC, order = (type_code & 31) + 1 265 let order: i64 = (type_code & 31) + 1 266 var i: i64 = 0 267 while i < order { buf[i] = nx_flac_read_signed(bs, eff); i = i + 1 } 268 let precision: i64 = nx_bitstream_read_msb(bs, 4) + 1 269 if precision > 15 { return 0 } 270 let shift: i64 = nx_flac_read_signed(bs, 5) 271 if shift < 0 { return 0 } 272 let coef: *i64 = sys_mmap(order * 8 + 64) as *i64 273 i = 0 274 while i < order { coef[i] = nx_flac_read_signed(bs, precision); i = i + 1 } 275 if nx_flac_read_residual(bs, buf, blocksize, order) == 0 { return 0 } 276 if nx_flac_restore_lpc(buf, blocksize, order, coef, shift) == 0 { return 0 } 277 ok = 1 278 } } 279 } } } 280 281 if ok == 0 { return 0 } 282 if wasted > 0 { 283 var i: i64 = 0 284 while i < blocksize { buf[i] = buf[i] << wasted; i = i + 1 } 285 } 286 if bs.overflow == 1 { return 0 } 287 return 1 288} 289 290// ===== CRC-16 (polynomial 0x8005) ================================= 291// 292// Guards the whole frame, header included. 293 294func nx_flac_crc16(data: *u8, n: i64) -> i64 { 295 var crc: i64 = 0 296 var i: i64 = 0 297 while i < n { 298 crc = crc ^ (((data[i] as i64) & 255) << 8) 299 var b: i64 = 0 300 while b < 8 { 301 if (crc & 0x8000) != 0 { 302 crc = ((crc << 1) ^ 0x8005) & 0xffff 303 } else { 304 crc = (crc << 1) & 0xffff 305 } 306 b = b + 1 307 } 308 i = i + 1 309 } 310 return crc & 0xffff 311}