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