1 // Vorbis decoder written in Rust
2 //
3 // Copyright (c) 2016 est31 <MTest31@outlook.com>
4 // and contributors. All rights reserved.
5 // Licensed under MIT license, or Apache 2 license,
6 // at your option. Please see the LICENSE file
7 // attached to this source distribution for details.
8 
9 #![cfg_attr(not(cargo_c), forbid(unsafe_code))]
10 #![cfg_attr(test, deny(warnings))]
11 
12 /*!
13 A `vorbis` decoder, written in Rust.
14 
15 If you "just" want to decode `ogg/vorbis` files, take a look into
16 the `inside_ogg` module (make sure you haven't disabled the `ogg` feature).
17 
18 For lower level, per-packet usage, you can have a look at the `audio` and `header`
19 modules.
20 */
21 
22 extern crate byteorder;
23 extern crate tinyvec;
24 #[cfg(feature = "ogg")]
25 extern crate ogg;
26 #[cfg(feature = "async_ogg")]
27 #[macro_use]
28 extern crate futures;
29 #[cfg(feature = "async_ogg")]
30 extern crate tokio_io;
31 
32 macro_rules! try {
33 	($expr:expr) => (match $expr {
34 		$crate::std::result::Result::Ok(val) => val,
35 		$crate::std::result::Result::Err(err) => {
36 			return Err($crate::std::convert::From::from(err));
37 		}
38 	})
39 }
40 
41 /*
42 // This little thing is very useful.
43 macro_rules! try {
44 	($expr:expr) => (match $expr {
45 		$crate::std::result::Result::Ok(val) => val,
46 		$crate::std::result::Result::Err(err) => {
47 			panic!("Panic on Err turned on for debug reasons. Encountered Err: {:?}", err)
48 		}
49 	})
50 }
51 // */
52 
53 // The following macros are super useful for debugging
54 
55 macro_rules! record_residue_pre_inverse {
56 	($residue_vectors:expr) => {
57 // 		for v in $residue_vectors.iter() {
58 // 			for &re in v {
59 // 				println!("{}", re);
60 // 			}
61 // 		}
62 	}
63 }
64 
65 macro_rules! record_residue_post_inverse {
66 	($residue_vectors:expr) => {
67 // 		for v in $residue_vectors.iter() {
68 // 			for &re in v {
69 // 				println!("{}", re);
70 // 			}
71 // 		}
72 	}
73 }
74 
75 macro_rules! record_pre_mdct {
76 	($audio_spectri:expr) => {
77 // 		for v in $audio_spectri.iter() {
78 // 			for &s in v {
79 // 				println!("{:.5}", s);
80 // 			}
81 // 		}
82 	}
83 }
84 
85 macro_rules! record_post_mdct {
86 	($audio_spectri:expr) => {
87 // 		for v in $audio_spectri.iter() {
88 // 			for &s in v {
89 // 				println!("{:.4}", s);
90 // 			}
91 // 		}
92 	}
93 }
94 
95 pub mod header;
96 mod header_cached;
97 mod huffman_tree;
98 mod imdct;
99 #[cfg(test)]
100 mod imdct_test;
101 pub mod audio;
102 mod bitpacking;
103 #[cfg(feature = "ogg")]
104 pub mod inside_ogg;
105 pub mod samples;
106 
107 #[cfg(feature = "ogg")]
108 #[doc(no_inline)]
109 pub use ogg::OggReadError;
110 
111 #[cfg(cargo_c)]
112 mod capi;
113 
114 #[cfg(cargo_c)]
115 pub use capi::*;
116 
117 /// Errors that can occur during decoding
118 #[derive(Debug)]
119 pub enum VorbisError {
120 	BadAudio(audio::AudioReadError),
121 	BadHeader(header::HeaderReadError),
122 	#[cfg(feature = "ogg")]
123 	OggError(OggReadError),
124 }
125 
126 impl std::error::Error for VorbisError {}
127 
128 impl std::fmt::Display for VorbisError {
fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>129 	fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
130 		write!(fmt, "{}", match self {
131 			VorbisError::BadAudio(_) => "Vorbis bitstream audio decode problem",
132 			VorbisError::BadHeader(_) => "Vorbis bitstream header decode problem",
133 			#[cfg(feature = "ogg")]
134 			VorbisError::OggError(_) => "Ogg decode problem",
135 		})
136 	}
137 }
138 
139 impl From<audio::AudioReadError> for VorbisError {
from(err :audio::AudioReadError) -> VorbisError140 	fn from(err :audio::AudioReadError) -> VorbisError {
141 		VorbisError::BadAudio(err)
142 	}
143 }
144 
145 impl From<header::HeaderReadError> for VorbisError {
from(err :header::HeaderReadError) -> VorbisError146 	fn from(err :header::HeaderReadError) -> VorbisError {
147 		VorbisError::BadHeader(err)
148 	}
149 }
150 
151 #[cfg(feature = "ogg")]
152 impl From<OggReadError> for VorbisError {
from(err :OggReadError) -> VorbisError153 	fn from(err :OggReadError) -> VorbisError {
154 		VorbisError::OggError(err)
155 	}
156 }
157 
ilog(val :u64) -> u8158 fn ilog(val :u64) -> u8 {
159 	64 - val.leading_zeros() as u8
160 }
161 
162 #[test]
test_ilog()163 fn test_ilog() {
164 	// Uses the test vectors from the Vorbis I spec
165 	assert_eq!(ilog(0), 0);
166 	assert_eq!(ilog(1), 1);
167 	assert_eq!(ilog(2), 2);
168 	assert_eq!(ilog(3), 2);
169 	assert_eq!(ilog(4), 3);
170 	assert_eq!(ilog(7), 3);
171 }
172 
bit_reverse(n :u32) -> u32173 fn bit_reverse(n :u32) -> u32 {
174 	// From the stb_vorbis implementation
175 	let mut nn = n;
176 	nn = ((nn & 0xAAAAAAAA) >> 1) | ((nn & 0x55555555) << 1);
177 	nn = ((nn & 0xCCCCCCCC) >> 2) | ((nn & 0x33333333) << 2);
178 	nn = ((nn & 0xF0F0F0F0) >> 4) | ((nn & 0x0F0F0F0F) << 4);
179 	nn = ((nn & 0xFF00FF00) >> 8) | ((nn & 0x00FF00FF) << 8);
180 	return (nn >> 16) | (nn << 16);
181 }
182 
183 
184 #[allow(dead_code)]
print_u8_slice(arr :&[u8])185 fn print_u8_slice(arr :&[u8]) {
186 	if arr.len() <= 4 {
187 		for a in arr {
188 			print!("0x{:02x} ", a);
189 		}
190 		println!("");
191 		return;
192 	}
193 	println!("[");
194 	let mut i :usize = 0;
195 	while i * 4 < arr.len() - 4 {
196 		println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x},",
197 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
198 		i += 1;
199 	}
200 	match arr.len() as i64 - i as i64 * 4 {
201 		1 => println!("\t0x{:02x}];", arr[i * 4]),
202 		2 => println!("\t0x{:02x}, 0x{:02x}];", arr[i * 4], arr[i * 4 + 1]),
203 		3 => println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}];",
204 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
205 		4 => println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}];",
206 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
207 		de => panic!("impossible value {}", de),
208 	}
209 }
210 
211 #[allow(dead_code)]
print_u32_slice(arr :&[u32])212 fn print_u32_slice(arr :&[u32]) {
213 	if arr.len() <= 4 {
214 		for a in arr {
215 			print!("0x{:02x} ", a);
216 		}
217 		println!("");
218 		return;
219 	}
220 	println!("[");
221 	let mut i :usize = 0;
222 	while i * 4 < arr.len() - 4 {
223 		println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x},",
224 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
225 		i += 1;
226 	}
227 	match arr.len() as i64 - i as i64 * 4 {
228 		1 => println!("\t0x{:08x}];", arr[i * 4]),
229 		2 => println!("\t0x{:08x}, 0x{:08x}];", arr[i * 4], arr[i * 4 + 1]),
230 		3 => println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}];",
231 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
232 		4 => println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}];",
233 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
234 		de => panic!("impossible value {}", de),
235 	}
236 }
237 
238 
239 #[allow(dead_code)]
print_f64_slice(arr :&[f64])240 fn print_f64_slice(arr :&[f64]) {
241 	if arr.len() <= 4 {
242 		for a in arr {
243 			print!("0x{} ", a);
244 		}
245 		println!("");
246 		return;
247 	}
248 	println!("[");
249 	let mut i :usize = 0;
250 	while i * 4 < arr.len() - 4 {
251 		println!("\t{}, {}, {}, {},",
252 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
253 		i += 1;
254 	}
255 	match arr.len() as i64 - i as i64 * 4 {
256 		1 => println!("\t{}];", arr[i * 4]),
257 		2 => println!("\t{}, {}];", arr[i * 4], arr[i * 4 + 1]),
258 		3 => println!("\t{}, {}, {}];",
259 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
260 		4 => println!("\t{}, {}, {}, {}];",
261 				arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
262 		de => panic!("impossible value {}", de),
263 	}
264 }
265