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}