/src/symphonia/symphonia-codec-vorbis/src/codebook.rs
Line | Count | Source |
1 | | // Symphonia |
2 | | // Copyright (c) 2019-2026 The Project Symphonia Developers. |
3 | | // |
4 | | // This Source Code Form is subject to the terms of the Mozilla Public |
5 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
6 | | // file, You can obtain one at https://mozilla.org/MPL/2.0/. |
7 | | |
8 | | use symphonia_core::errors::{Result, decode_error}; |
9 | | use symphonia_core::io::{ |
10 | | ReadBitsRtl, |
11 | | vlc::{BitOrder, Codebook, CodebookBuilder, Entry32x32}, |
12 | | }; |
13 | | |
14 | | use super::common::*; |
15 | | |
16 | | /// As defined in section 9.2.2 of the Vorbis I specification. |
17 | | /// |
18 | | /// `float32_unpack` is intended to translate the packed binary representation of a Vorbis |
19 | | /// codebook float value into the representation used by the decoder for floating point numbers. |
20 | | #[inline(always)] |
21 | 0 | fn float32_unpack(x: u32) -> f32 { |
22 | 0 | let mantissa = x & 0x1fffff; |
23 | 0 | let sign = x & 0x80000000; |
24 | 0 | let exponent = (x & 0x7fe00000) >> 21; |
25 | 0 | let value = (mantissa as f32) * 2.0f32.powi(exponent as i32 - 788); |
26 | 0 | if sign == 0 { value } else { -value } |
27 | 0 | } |
28 | | |
29 | | /// As defined in section 9.2.3 of the Vorbis I specification. |
30 | | /// |
31 | | /// The return value for this function is defined to be ’the greatest integer value for which the |
32 | | /// return value to the power of `dimensions` is less than or equal to `entries`. |
33 | | #[inline(always)] |
34 | 0 | fn lookup1_values(entries: u32, dimensions: u16) -> u32 { |
35 | | // Prevent division by 0. |
36 | 0 | if dimensions == 0 { |
37 | 0 | return 0; |
38 | 0 | } |
39 | | |
40 | | // (value ^ dimensions) <= entries |
41 | | // [(value ^ dimensions) ^ (1 / dimensions)] = lower[entries ^ (1 / dimensions)] |
42 | | // value = lower[entries ^ (1 / dimensions)] |
43 | 0 | let value = (entries as f32).powf(1.0f32 / f32::from(dimensions)).floor() as u32; |
44 | | |
45 | 0 | assert!(value.pow(u32::from(dimensions)) <= entries); |
46 | | |
47 | 0 | value |
48 | 0 | } |
49 | | |
50 | | /// As defined in section 3.2.1 of the Vorbis I specification. |
51 | 0 | fn unpack_vq_lookup_type1( |
52 | 0 | multiplicands: &[u16], |
53 | 0 | min_value: f32, |
54 | 0 | delta_value: f32, |
55 | 0 | sequence_p: bool, |
56 | 0 | codebook_entries: u32, |
57 | 0 | codebook_dimensions: u16, |
58 | 0 | lookup_values: u32, |
59 | 0 | ) -> Vec<f32> { |
60 | 0 | let mut vq_lookup = vec![0.0; codebook_entries as usize * codebook_dimensions as usize]; |
61 | | |
62 | 0 | for (v, value_vector) in vq_lookup.chunks_exact_mut(codebook_dimensions as usize).enumerate() { |
63 | 0 | let lookup_offset = v as u32; |
64 | | |
65 | 0 | let mut last = 0.0; |
66 | 0 | let mut index_divisor = 1; |
67 | | |
68 | 0 | for value in value_vector.iter_mut() { |
69 | 0 | let multiplicand_offset = ((lookup_offset / index_divisor) % lookup_values) as usize; |
70 | | |
71 | 0 | *value = f32::from(multiplicands[multiplicand_offset]) * delta_value + min_value + last; |
72 | | |
73 | 0 | if sequence_p { |
74 | 0 | last = *value; |
75 | 0 | } |
76 | | |
77 | 0 | index_divisor *= lookup_values; |
78 | | } |
79 | | } |
80 | | |
81 | 0 | vq_lookup |
82 | 0 | } |
83 | | |
84 | | /// As defined in section 3.2.1 of the Vorbis I specification. |
85 | 0 | fn unpack_vq_lookup_type2( |
86 | 0 | multiplicands: &[u16], |
87 | 0 | min_value: f32, |
88 | 0 | delta_value: f32, |
89 | 0 | sequence_p: bool, |
90 | 0 | codebook_entries: u32, |
91 | 0 | codebook_dimensions: u16, |
92 | 0 | ) -> Vec<f32> { |
93 | 0 | let mut vq_lookup = vec![0.0; codebook_entries as usize * codebook_dimensions as usize]; |
94 | | |
95 | 0 | for (lookup_offset, value_vector) in |
96 | 0 | vq_lookup.chunks_exact_mut(codebook_dimensions as usize).enumerate() |
97 | | { |
98 | 0 | let mut last = 0.0; |
99 | 0 | let offset = lookup_offset * codebook_dimensions as usize; |
100 | | |
101 | 0 | for (offset, value) in (offset..).zip(value_vector.iter_mut()) { |
102 | 0 | *value = f32::from(multiplicands[offset]) * delta_value + min_value + last; |
103 | | |
104 | 0 | if sequence_p { |
105 | 0 | last = *value; |
106 | 0 | } |
107 | | } |
108 | | } |
109 | | |
110 | 0 | vq_lookup |
111 | 0 | } |
112 | | |
113 | 0 | fn synthesize_codewords(code_lens: &[u8]) -> Result<Vec<u32>> { |
114 | | // This codeword generation algorithm works by maintaining a table of the next valid codeword for |
115 | | // each codeword length. |
116 | | // |
117 | | // Consider a huffman tree. Each level of the tree correlates to a specific length of codeword. |
118 | | // For example, given a leaf node at level 2 of the huffman tree, that codeword would be 2 bits |
119 | | // long. Therefore, the table being maintained contains the codeword that would identify the next |
120 | | // available left-most node in the huffman tree at a given level. Therefore, this table can be |
121 | | // interrogated to get the next codeword in a simple lookup and the tree will fill-out in the |
122 | | // canonical order. |
123 | | // |
124 | | // Note however that, after selecting a codeword, C, of length N, all codewords of length > N |
125 | | // cannot use C as a prefix anymore. Therefore, all table entries for codeword lengths > N must |
126 | | // be updated such that these codewords are skipped over. Likewise, the table must be updated for |
127 | | // lengths < N to account for jumping between nodes. |
128 | | // |
129 | | // This algorithm is a modified version of the one found in the Vorbis reference implementation. |
130 | 0 | let mut codewords = Vec::new(); |
131 | | |
132 | 0 | let mut next_codeword = [0u32; 33]; |
133 | | |
134 | 0 | for &len in code_lens.iter() { |
135 | | // This should always be true. |
136 | 0 | debug_assert!(len <= 32); |
137 | | |
138 | | // Zero length codewords are invalid and ignored. |
139 | 0 | if len == 0 { |
140 | 0 | continue; |
141 | 0 | } |
142 | | |
143 | | // The codeword length, N. |
144 | 0 | let codeword_len = usize::from(len); |
145 | | |
146 | | // The selected codeword, C. |
147 | 0 | let codeword = next_codeword[codeword_len]; |
148 | | |
149 | 0 | if len < 32 && (codeword >> len) > 0 { |
150 | 0 | return decode_error("vorbis: codebook overspecified"); |
151 | 0 | } |
152 | | |
153 | 0 | for i in (1..codeword_len + 1).rev() { |
154 | | // If the least significant bit (LSb) of the next codeword for codewords of length N |
155 | | // toggles from 1 to 0, that indicates the next-least-LSb will toggle. This means that |
156 | | // the next codeword will branch off a new parent node. Therefore, the next codeword for |
157 | | // codewords of length N will use the next codeword for codewords of length N-1 as its |
158 | | // prefix. |
159 | 0 | if next_codeword[i] & 1 == 1 { |
160 | 0 | if i == 1 { |
161 | 0 | next_codeword[1] += 1; |
162 | 0 | } |
163 | 0 | else { |
164 | 0 | next_codeword[i] = next_codeword[i - 1] << 1; |
165 | 0 | } |
166 | 0 | break; |
167 | 0 | } |
168 | | |
169 | | // Otherwise, simply increment the next codeword for codewords of length N by 1. Iterate |
170 | | // again since there is now 1 branch dangling off the parent node. The parent must now be |
171 | | // incremented updated in the same way. |
172 | 0 | next_codeword[i] += 1; |
173 | | } |
174 | | |
175 | | // Given a codeword, C, of length N bits, the codeword is a leaf on the tree and cannot have |
176 | | // any branches. Otherwise, another codeword would have C as its prefix and that is not |
177 | | // allowed. Therefore, if the next codeword for codewords of length N+1 uses codeword C as a |
178 | | // prefix, then the next codeword for codewords of length N+1 must be modified to branch off |
179 | | // the next codeword of length N instead. Then this modification must be propagated down the |
180 | | // tree in a similar pattern. In this way, all next codewords for codewords of lengths > N |
181 | | // that would've used C as a prefix are skipped over and can't be selected regardless of the |
182 | | // length of the next codeword. |
183 | 0 | let branch = next_codeword[codeword_len]; |
184 | | |
185 | 0 | for (i, next) in next_codeword[codeword_len..].iter_mut().enumerate().skip(1) { |
186 | | // If the next codeword for this length of codewords is using the selected codeword, C, |
187 | | // as a prefix, move it to the next branch. |
188 | 0 | if *next == codeword << i { |
189 | 0 | *next = branch << i; |
190 | 0 | } |
191 | | else { |
192 | 0 | break; |
193 | | } |
194 | | } |
195 | | |
196 | | // Push the codeword. |
197 | 0 | codewords.push(codeword); |
198 | | } |
199 | | |
200 | | // Check that the tree is fully specified and complete. This means that the next codeword for |
201 | | // codes of length 1 to 32, inclusive, are saturated. |
202 | 0 | let is_underspecified = |
203 | 0 | next_codeword.iter().enumerate().skip(1).any(|(i, &c)| c & (u32::MAX >> (32 - i)) != 0); |
204 | | |
205 | 0 | if is_underspecified { |
206 | 0 | return decode_error("vorbis: codebook underspecified"); |
207 | 0 | } |
208 | | |
209 | 0 | Ok(codewords) |
210 | 0 | } |
211 | | |
212 | | pub struct VorbisCodebook { |
213 | | codebook: Codebook<Entry32x32>, |
214 | | dimensions: u16, |
215 | | vq_vec: Option<Vec<f32>>, |
216 | | } |
217 | | |
218 | | impl VorbisCodebook { |
219 | 0 | pub fn read<B: ReadBitsRtl>(bs: &mut B) -> Result<Self> { |
220 | | // Verify codebook synchronization word. |
221 | 0 | let sync = bs.read_bits_leq32(24)?; |
222 | | |
223 | 0 | if sync != 0x564342 { |
224 | 0 | return decode_error("vorbis: invalid codebook sync"); |
225 | 0 | } |
226 | | |
227 | | // Read codebook number of dimensions and entries. |
228 | 0 | let codebook_dimensions = bs.read_bits_leq32(16)? as u16; |
229 | 0 | let codebook_entries = bs.read_bits_leq32(24)?; |
230 | | |
231 | | // The codebook dimensions cannot be 0 for VQ codebooks. |
232 | 0 | if codebook_dimensions == 0 { |
233 | 0 | return decode_error("vorbis: codebook dimenion cannot be 0"); |
234 | 0 | } |
235 | | |
236 | | // Limit the size of codebooks to something reasonable. This limits should never be seen in |
237 | | // any real bitstream. These limits, together, limit the in-memory size of a VQ codebook to |
238 | | // 16MB. A scalar codebook is limited to 512kB. |
239 | 0 | if codebook_dimensions > 32 { |
240 | 0 | return decode_error("vorbis: codebook dimension is too large (report this)"); |
241 | 0 | } |
242 | 0 | if codebook_entries > 128 * 1024 { |
243 | 0 | return decode_error("vorbis: codebook entries too large (report this)"); |
244 | 0 | } |
245 | | |
246 | | // Ordered flag. |
247 | 0 | let is_length_ordered = bs.read_bool()?; |
248 | | |
249 | 0 | let mut code_lens = Vec::<u8>::with_capacity(codebook_entries as usize); |
250 | 0 | let mut code_values = Vec::<u32>::with_capacity(codebook_entries as usize); |
251 | | |
252 | 0 | if !is_length_ordered { |
253 | | // Codeword list is not length ordered. |
254 | 0 | let is_sparse = bs.read_bool()?; |
255 | | |
256 | 0 | if is_sparse { |
257 | | // Sparsely packed codeword entry list. |
258 | 0 | for entry in 0..codebook_entries { |
259 | 0 | let is_used = bs.read_bool()?; |
260 | | |
261 | | // The codeword list is sparse. Only populate entries that are used. |
262 | 0 | if is_used { |
263 | 0 | let code_len = bs.read_bits_leq32(5)? as u8 + 1; |
264 | | |
265 | 0 | code_lens.push(code_len); |
266 | 0 | code_values.push(entry); |
267 | 0 | } |
268 | | } |
269 | | } |
270 | | else { |
271 | | // Densely packed codeword entry list. |
272 | 0 | for _ in 0..codebook_entries { |
273 | 0 | let code_len = bs.read_bits_leq32(5)? as u8 + 1; |
274 | 0 | code_lens.push(code_len) |
275 | | } |
276 | | |
277 | | // The codeword list is not sparse. Populate all values. |
278 | 0 | code_values.extend(0..codebook_entries); |
279 | | } |
280 | | } |
281 | | else { |
282 | | // Codeword list is length ordered. |
283 | 0 | let mut cur_entry = 0; |
284 | 0 | let mut cur_len = bs.read_bits_leq32(5)? + 1; |
285 | | |
286 | | loop { |
287 | 0 | let num_bits = if codebook_entries > cur_entry { |
288 | 0 | ilog(codebook_entries - cur_entry) |
289 | | } |
290 | | else { |
291 | 0 | 0 |
292 | | }; |
293 | | |
294 | 0 | let num = bs.read_bits_leq32(num_bits)?; |
295 | | |
296 | 0 | code_lens.extend(std::iter::repeat_n(cur_len as u8, num as usize)); |
297 | | |
298 | 0 | cur_len += 1; |
299 | 0 | cur_entry += num; |
300 | | |
301 | 0 | if cur_entry > codebook_entries { |
302 | 0 | return decode_error("vorbis: invalid codebook"); |
303 | 0 | } |
304 | | |
305 | 0 | if cur_entry == codebook_entries { |
306 | 0 | break; |
307 | 0 | } |
308 | | } |
309 | | |
310 | | // The codeword list is not sparse. Populate all values. |
311 | 0 | code_values.extend(0..cur_entry); |
312 | | } |
313 | | |
314 | | // Single-entry codebooks are technically invalid because the minimum possible codeword |
315 | | // length is 1 which requires two entries. If only one entry is provided, then the codebook |
316 | | // will contain an entry for codeword 0b0 but not for codeword 0b1. However, per the |
317 | | // Vorbis I specification, errata 20150226, this special-case must be supported by decoding |
318 | | // both codewords to the same value. Detect single-entry codebooks and add a duplicate entry |
319 | | // such that both codewords will yield the same value and the codebook will be fully |
320 | | // specified. Do not support single-entry codebooks for codeword lengths > 1. |
321 | 0 | if code_lens.len() == 1 && code_lens[0] == 1 { |
322 | 0 | code_lens.push(code_lens[0]); |
323 | 0 | code_values.push(code_values[0]); |
324 | 0 | } |
325 | | |
326 | | // Read and unpack vector quantization (VQ) lookup table. |
327 | 0 | let lookup_type = bs.read_bits_leq32(4)?; |
328 | | |
329 | 0 | let vq_vec = match lookup_type & 0xf { |
330 | 0 | 0 => None, |
331 | | 1 | 2 => { |
332 | 0 | let min_value = float32_unpack(bs.read_bits_leq32(32)?); |
333 | 0 | let delta_value = float32_unpack(bs.read_bits_leq32(32)?); |
334 | 0 | let value_bits = bs.read_bits_leq32(4)? + 1; |
335 | 0 | let sequence_p = bs.read_bool()?; |
336 | | |
337 | | // Lookup type is either 1 or 2 as per outer match. |
338 | 0 | let lookup_values = match lookup_type { |
339 | 0 | 1 => lookup1_values(codebook_entries, codebook_dimensions), |
340 | 0 | 2 => codebook_entries * u32::from(codebook_dimensions), |
341 | 0 | _ => unreachable!(), |
342 | | }; |
343 | | |
344 | 0 | let mut multiplicands = Vec::<u16>::new(); |
345 | | |
346 | 0 | for _ in 0..lookup_values { |
347 | 0 | multiplicands.push(bs.read_bits_leq32(value_bits)? as u16); |
348 | | } |
349 | | |
350 | 0 | let vq_lookup = match lookup_type { |
351 | 0 | 1 => unpack_vq_lookup_type1( |
352 | 0 | &multiplicands, |
353 | 0 | min_value, |
354 | 0 | delta_value, |
355 | 0 | sequence_p, |
356 | 0 | codebook_entries, |
357 | 0 | codebook_dimensions, |
358 | 0 | lookup_values, |
359 | | ), |
360 | 0 | 2 => unpack_vq_lookup_type2( |
361 | 0 | &multiplicands, |
362 | 0 | min_value, |
363 | 0 | delta_value, |
364 | 0 | sequence_p, |
365 | 0 | codebook_entries, |
366 | 0 | codebook_dimensions, |
367 | | ), |
368 | 0 | _ => unreachable!(), |
369 | | }; |
370 | | |
371 | 0 | Some(vq_lookup) |
372 | | } |
373 | 0 | _ => return decode_error("vorbis: invalid codeword lookup type"), |
374 | | }; |
375 | | |
376 | | // Generate a canonical list of codewords given the set of codeword lengths. |
377 | 0 | let code_words = synthesize_codewords(&code_lens)?; |
378 | | |
379 | | // Finally, generate the codebook with a reverse (LSb) bit order. |
380 | 0 | let mut builder = CodebookBuilder::new(BitOrder::Reverse); |
381 | | |
382 | | // Read in 4-8 bit-wide blocks. |
383 | 0 | builder.bits_per_read(code_lens.iter().max().copied().unwrap_or(0).clamp(4, 8)); |
384 | | |
385 | 0 | let codebook = builder.make::<Entry32x32>(&code_words, &code_lens, &code_values)?; |
386 | | |
387 | 0 | Ok(VorbisCodebook { codebook, dimensions: codebook_dimensions, vq_vec }) |
388 | 0 | } |
389 | | |
390 | | #[inline(always)] |
391 | 0 | pub fn read_scalar<B: ReadBitsRtl>(&self, bs: &mut B) -> Result<u32> { |
392 | | // An entry in a scalar codebook is just the value. |
393 | 0 | Ok(bs.read_codebook(&self.codebook)?.0) |
394 | 0 | } |
395 | | |
396 | | #[inline(always)] |
397 | 0 | pub fn read_vq<B: ReadBitsRtl>(&self, bs: &mut B) -> Result<&[f32]> { |
398 | | // An entry in a VQ codebook is the index of the VQ vector. |
399 | 0 | let entry = bs.read_codebook(&self.codebook)?.0; |
400 | | |
401 | 0 | if let Some(vq) = &self.vq_vec { |
402 | 0 | let dim = self.dimensions as usize; |
403 | 0 | let start = dim * entry as usize; |
404 | | |
405 | 0 | Ok(&vq[start..start + dim]) |
406 | | } |
407 | | else { |
408 | 0 | decode_error("vorbis: not a vq codebook") |
409 | | } |
410 | 0 | } |
411 | | |
412 | | #[inline(always)] |
413 | 0 | pub fn dimensions(&self) -> u16 { |
414 | 0 | self.dimensions |
415 | 0 | } |
416 | | } |
417 | | |
418 | | #[cfg(test)] |
419 | | mod tests { |
420 | | use super::{ilog, lookup1_values, synthesize_codewords}; |
421 | | |
422 | | #[test] |
423 | | fn verify_ilog() { |
424 | | assert_eq!(ilog(0), 0); |
425 | | assert_eq!(ilog(1), 1); |
426 | | assert_eq!(ilog(2), 2); |
427 | | assert_eq!(ilog(3), 2); |
428 | | assert_eq!(ilog(4), 3); |
429 | | assert_eq!(ilog(7), 3); |
430 | | } |
431 | | |
432 | | fn naive_lookup1_values(entries: u32, dimensions: u16) -> u32 { |
433 | | let mut x = 1u32; |
434 | | |
435 | | // If dimensions is 0, then the only acceptable value for entries is 0 because 0 ^ 0 = 1. |
436 | | if dimensions > 0 { |
437 | | loop { |
438 | | // Since entries is 24-bit, an overflow of u32 will by definition exceed the number |
439 | | // of entries. |
440 | | let Some(x_pow) = x.checked_pow(u32::from(dimensions)) |
441 | | else { |
442 | | break; |
443 | | }; |
444 | | |
445 | | if x_pow > entries { |
446 | | break; |
447 | | } |
448 | | x += 1; |
449 | | } |
450 | | } |
451 | | |
452 | | x - 1 |
453 | | } |
454 | | |
455 | | #[test] |
456 | | fn verify_lookup1_values() { |
457 | | assert_eq!(lookup1_values(0, 0), naive_lookup1_values(0, 1)); |
458 | | assert_eq!(lookup1_values(1, 0), naive_lookup1_values(1, 0)); |
459 | | assert_eq!(lookup1_values(0, 1), naive_lookup1_values(0, 1)); |
460 | | assert_eq!(lookup1_values(1, 1), naive_lookup1_values(1, 1)); |
461 | | assert_eq!(lookup1_values(361, 2), naive_lookup1_values(361, 2)); |
462 | | assert_eq!(lookup1_values(361, 2), naive_lookup1_values(361, 2)); |
463 | | assert_eq!(lookup1_values(560, 3), naive_lookup1_values(560, 3)); |
464 | | assert_eq!(lookup1_values(3, 950), naive_lookup1_values(3, 950)); |
465 | | assert_eq!(lookup1_values(0xffff, 0xff), naive_lookup1_values(0xffff, 0xff)); |
466 | | assert_eq!(lookup1_values(0, u16::MAX), naive_lookup1_values(0, u16::MAX)); |
467 | | assert_eq!(lookup1_values(1, u16::MAX), naive_lookup1_values(1, u16::MAX)); |
468 | | assert_eq!(lookup1_values(0xff_ffff, u16::MAX), naive_lookup1_values(0xff_ffff, u16::MAX)); |
469 | | } |
470 | | |
471 | | #[test] |
472 | | fn verify_synthesize_codewords() { |
473 | | const CODEWORD_LENGTHS: &[u8] = &[2, 4, 4, 4, 4, 2, 3, 3]; |
474 | | const EXPECTED_CODEWORDS: &[u32] = &[0, 0x4, 0x5, 0x6, 0x7, 0x2, 0x6, 0x7]; |
475 | | let codewords = synthesize_codewords(CODEWORD_LENGTHS).unwrap(); |
476 | | assert_eq!(&codewords, EXPECTED_CODEWORDS); |
477 | | } |
478 | | |
479 | | #[test] |
480 | | fn verify_synthesize_codewords_overspecified() { |
481 | | // These codebooks are overspecified and shouldn't panic. |
482 | | assert!(synthesize_codewords(&[1, 1, 1]).is_err()); |
483 | | assert!(synthesize_codewords(&[1, 1, 32]).is_err()); |
484 | | } |
485 | | } |