1 // Vorbis decoder written in Rust
2 //
3 // This example file is licensed
4 // under the CC-0 license:
5 // https://creativecommons.org/publicdomain/zero/1.0/
6 
7 extern crate alto;
8 extern crate lewton;
9 extern crate byteorder;
10 
11 use std::env;
12 use lewton::VorbisError;
13 use lewton::inside_ogg::OggStreamReader;
14 use std::fs::File;
15 use std::thread::sleep;
16 use std::time::{Instant, Duration};
17 use alto::{Alto, Mono, Stereo, Source};
18 
main()19 fn main() {
20 	match run() {
21 		Ok(_) =>(),
22 		Err(err) => println!("Error: {}", err),
23 	}
24 }
25 
run() -> Result<(), VorbisError>26 fn run() -> Result<(), VorbisError> {
27 	let file_path = env::args().nth(1).expect("No arg found. Please specify a file to open.");
28 	println!("Opening file: {}", file_path);
29 	let f = File::open(file_path).expect("Can't open file");
30 
31 	// Prepare the reading
32 	let mut srr = try!(OggStreamReader::new(f));
33 
34 	// Prepare the playback.
35 	let al = Alto::load_default().expect("Could not load alto");
36 	let device = al.open(None).expect("Could not open device");
37 	let cxt = device.new_context(None).expect("Could not create context");
38 	let mut str_src = cxt.new_streaming_source()
39 		.expect("could not create streaming src");
40 	let sample_rate = srr.ident_hdr.audio_sample_rate as i32;
41 
42 	if srr.ident_hdr.audio_channels > 2 {
43 		// the openal crate can't process these many channels directly
44 		println!("Stream error: {} channels are too many!", srr.ident_hdr.audio_channels);
45 	}
46 
47 	println!("Sample rate: {}", srr.ident_hdr.audio_sample_rate);
48 
49 	// Now the fun starts..
50 	let mut n = 0;
51 	let mut len_play = 0.0;
52 	let mut start_play_time = None;
53 	let start_decode_time = Instant::now();
54 	let sample_channels = srr.ident_hdr.audio_channels as f32 *
55 		srr.ident_hdr.audio_sample_rate as f32;
56 	while let Some(pck_samples) = try!(srr.read_dec_packet_itl()) {
57 		println!("Decoded packet no {}, with {} samples.", n, pck_samples.len());
58 		n += 1;
59 		let buf = match srr.ident_hdr.audio_channels {
60 			1 => cxt.new_buffer::<Mono<i16>,_>(&pck_samples, sample_rate),
61 			2 => cxt.new_buffer::<Stereo<i16>,_>(&pck_samples, sample_rate),
62 			n => panic!("unsupported number of channels: {}", n),
63 		}.unwrap();
64 
65 		str_src.queue_buffer(buf).unwrap();
66 
67 		len_play += pck_samples.len() as f32 / sample_channels;
68 		// If we are faster than realtime, we can already start playing now.
69 		if n == 100 {
70 			let cur = Instant::now();
71 			if cur - start_decode_time < Duration::from_millis((len_play * 1000.0) as u64) {
72 				start_play_time = Some(cur);
73 				str_src.play();
74 			}
75 		}
76 	}
77 	let total_duration = Duration::from_millis((len_play * 1000.0) as u64);
78 	let sleep_duration = total_duration - match start_play_time {
79 			None => {
80 				str_src.play();
81 				Duration::from_millis(0)
82 			},
83 			Some(t) => (Instant::now() - t)
84 		};
85 	println!("The piece is {} s long.", len_play);
86 	sleep(sleep_duration);
87 
88 	Ok(())
89 }
90