aotuv_lancer_vorbis_sys/
lib.rs1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3
4extern crate ogg_next_sys;
8
9use ogg_next_sys::*;
10
11include!("bindings.rs");
12
13#[cfg(test)]
14mod test {
15 use std::{
16 ffi::CStr,
17 io::{Cursor, Read, Write},
18 mem::MaybeUninit,
19 os::raw::{c_int, c_long, c_void},
20 ptr, slice
21 };
22
23 use ogg_next_sys::{ogg_stream_init, ogg_stream_packetin};
24
25 use super::*;
26
27 #[test]
28 fn roundtrip_decode_and_encode() {
29 let mut input_data =
30 Cursor::new(&include_bytes!("8khz_500ms_mono_400hz_sine_wave.ogg")[..]);
31 let mut output_buffer = Cursor::new(vec![]);
32
33 unsafe {
37 let mut ogg_vorbis_file = MaybeUninit::uninit();
40 assert_eq!(
41 ov_open_callbacks(
42 &mut input_data as *mut Cursor<&[u8]> as *mut c_void,
43 ogg_vorbis_file.as_mut_ptr(),
44 ptr::null(),
45 0,
46 ov_callbacks {
47 read_func: {
48 unsafe extern "C" fn read_func(
51 ptr: *mut std::ffi::c_void,
52 size: usize,
53 count: usize,
54 datasource: *mut std::ffi::c_void
55 ) -> usize {
56 let data = &mut *(datasource as *mut Cursor<&[u8]>);
57 let buf = slice::from_raw_parts_mut(ptr as *mut u8, size * count);
58 match data.read(buf) {
59 Ok(n) => n / size,
60 Err(_) => 0
61 }
62 }
63 Some(read_func)
64 },
65 seek_func: None,
66 close_func: None,
67 tell_func: None
68 }
69 ),
70 0
71 );
72 let ogg_vorbis_file = ogg_vorbis_file.assume_init_mut();
73
74 let ogg_vorbis_info = &*ov_info(ogg_vorbis_file, -1);
75 eprintln!(
76 "Encoder version string: {}",
77 CStr::from_ptr(vorbis_version_string())
78 .to_str()
79 .unwrap_or_default()
80 );
81 eprintln!("Bitrate: {}", ov_bitrate(ogg_vorbis_file, -1));
82 eprintln!("Channels: {}", ogg_vorbis_info.channels);
83 eprintln!("Sampling frequency: {}", ogg_vorbis_info.rate);
84
85 let mut vorbis_info = MaybeUninit::uninit();
88 vorbis_info_init(vorbis_info.as_mut_ptr());
89 let vorbis_info = vorbis_info.assume_init_mut();
90
91 assert_eq!(
92 vorbis_encode_init_vbr(
94 vorbis_info,
95 ogg_vorbis_info.channels as c_long,
96 ogg_vorbis_info.rate,
97 -0.2 ),
99 0
100 );
101
102 let mut vorbis_dsp_state = MaybeUninit::uninit();
103 assert_eq!(
104 vorbis_analysis_init(vorbis_dsp_state.as_mut_ptr(), vorbis_info),
105 0
106 );
107 let vorbis_dsp_state = vorbis_dsp_state.assume_init_mut();
108
109 let mut vorbis_block = MaybeUninit::uninit();
110 assert_eq!(
111 vorbis_block_init(vorbis_dsp_state, vorbis_block.as_mut_ptr()),
112 0
113 );
114 let vorbis_block = vorbis_block.assume_init_mut();
115
116 let mut vorbis_comment = MaybeUninit::uninit();
117 vorbis_comment_init(vorbis_comment.as_mut_ptr());
118 let vorbis_comment = vorbis_comment.assume_init_mut();
119
120 let mut vorbis_identification_packet = MaybeUninit::uninit();
123 let mut vorbis_comment_packet = MaybeUninit::uninit();
124 let mut vorbis_setup_packet = MaybeUninit::uninit();
125 assert_eq!(
126 vorbis_analysis_headerout(
127 vorbis_dsp_state,
128 vorbis_comment,
129 vorbis_identification_packet.as_mut_ptr(),
130 vorbis_comment_packet.as_mut_ptr(),
131 vorbis_setup_packet.as_mut_ptr()
132 ),
133 0
134 );
135 let vorbis_identification_packet = vorbis_identification_packet.assume_init_mut();
136 let vorbis_comment_packet = vorbis_comment_packet.assume_init_mut();
137 let vorbis_setup_packet = vorbis_setup_packet.assume_init_mut();
138
139 let mut ogg_stream = MaybeUninit::uninit();
142 assert_eq!(ogg_stream_init(ogg_stream.as_mut_ptr(), 0), 0);
143 let ogg_stream = ogg_stream.assume_init_mut();
144
145 assert_eq!(
146 ogg_stream_packetin(ogg_stream, vorbis_identification_packet),
147 0
148 );
149 assert_eq!(ogg_stream_packetin(ogg_stream, vorbis_comment_packet), 0);
150 assert_eq!(ogg_stream_packetin(ogg_stream, vorbis_setup_packet), 0);
151
152 let mut ogg_page = MaybeUninit::uninit();
153 loop {
154 if ogg_stream_flush(ogg_stream, ogg_page.as_mut_ptr()) == 0 {
155 break;
156 }
157 let ogg_page = ogg_page.assume_init_mut();
158
159 output_buffer
161 .write_all(slice::from_raw_parts(
162 ogg_page.header,
163 ogg_page.header_len as usize
164 ))
165 .unwrap();
166 output_buffer
167 .write_all(slice::from_raw_parts(
168 ogg_page.body,
169 ogg_page.body_len as usize
170 ))
171 .unwrap();
172 }
173 let ogg_page = ogg_page.assume_init_mut();
174
175 let mut sample_source_buf = MaybeUninit::uninit();
178 let mut bitstream_id = MaybeUninit::uninit();
179 let mut previous_bitstream_id = None;
180
181 loop {
182 let samples_read = ov_read_float(
183 ogg_vorbis_file,
184 sample_source_buf.as_mut_ptr(),
185 1024,
186 bitstream_id.as_mut_ptr()
187 );
188 assert!(samples_read >= 0);
189 let sample_source_buf = *sample_source_buf.assume_init_mut();
190
191 let bitstream_id = *bitstream_id.assume_init_mut();
192 assert!(
193 previous_bitstream_id.is_none() || previous_bitstream_id == Some(bitstream_id),
194 "Chained Ogg Vorbis files are not supported"
195 );
196 previous_bitstream_id = Some(bitstream_id);
197
198 if samples_read == 0 {
199 assert_eq!(vorbis_analysis_wrote(vorbis_dsp_state, 0), 0);
201 } else {
202 let sample_sink_buf =
203 vorbis_analysis_buffer(vorbis_dsp_state, samples_read as c_int);
204
205 for i in 0..ogg_vorbis_info.channels {
207 (*sample_source_buf.offset(i as isize)).copy_to_nonoverlapping(
208 *sample_sink_buf.offset(i as isize),
209 samples_read as usize
210 );
211 }
212
213 assert_eq!(
214 vorbis_analysis_wrote(vorbis_dsp_state, samples_read as c_int),
215 0
216 );
217 }
218
219 loop {
221 let blockout_result = vorbis_analysis_blockout(vorbis_dsp_state, vorbis_block);
222 assert!(blockout_result >= 0);
223 if blockout_result != 1 {
224 break;
225 }
226
227 assert_eq!(vorbis_analysis(vorbis_block, ptr::null_mut()), 0);
228 assert_eq!(vorbis_bitrate_addblock(vorbis_block), 0);
229
230 loop {
231 let mut ogg_packet = MaybeUninit::uninit();
232 let flushpacket_result =
233 vorbis_bitrate_flushpacket(vorbis_dsp_state, ogg_packet.as_mut_ptr());
234 assert!(flushpacket_result >= 0);
235 if flushpacket_result != 1 {
236 break;
237 }
238
239 ogg_stream_packetin(ogg_stream, ogg_packet.assume_init_mut());
240 if ogg_stream_pageout(ogg_stream, ogg_page) != 0 {
241 output_buffer
242 .write_all(slice::from_raw_parts(
243 ogg_page.header,
244 ogg_page.header_len as usize
245 ))
246 .unwrap();
247 output_buffer
248 .write_all(slice::from_raw_parts(
249 ogg_page.body,
250 ogg_page.body_len as usize
251 ))
252 .unwrap();
253 }
254 }
255 }
256
257 if samples_read == 0 {
258 break;
259 }
260 }
261
262 ogg_stream_clear(ogg_stream);
264
265 vorbis_dsp_clear(vorbis_dsp_state);
267 vorbis_block_clear(vorbis_block);
268 vorbis_comment_clear(vorbis_comment);
269 vorbis_info_clear(vorbis_info);
270
271 ov_clear(ogg_vorbis_file);
273 }
274
275 assert_eq!(&output_buffer.into_inner()[..4], b"OggS");
277 }
278}