90 lines
2.7 KiB
Rust
90 lines
2.7 KiB
Rust
// Vorbis decoder written in Rust
|
|
//
|
|
// This example file is licensed
|
|
// under the CC-0 license:
|
|
// https://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
extern crate alto;
|
|
extern crate lewton;
|
|
extern crate byteorder;
|
|
|
|
use std::env;
|
|
use lewton::VorbisError;
|
|
use lewton::inside_ogg::OggStreamReader;
|
|
use std::fs::File;
|
|
use std::thread::sleep;
|
|
use std::time::{Instant, Duration};
|
|
use alto::{Alto, Mono, Stereo, Source};
|
|
|
|
fn main() {
|
|
match run() {
|
|
Ok(_) =>(),
|
|
Err(err) => println!("Error: {}", err),
|
|
}
|
|
}
|
|
|
|
fn run() -> Result<(), VorbisError> {
|
|
let file_path = env::args().nth(1).expect("No arg found. Please specify a file to open.");
|
|
println!("Opening file: {}", file_path);
|
|
let f = File::open(file_path).expect("Can't open file");
|
|
|
|
// Prepare the reading
|
|
let mut srr = try!(OggStreamReader::new(f));
|
|
|
|
// Prepare the playback.
|
|
let al = Alto::load_default().expect("Could not load alto");
|
|
let device = al.open(None).expect("Could not open device");
|
|
let cxt = device.new_context(None).expect("Could not create context");
|
|
let mut str_src = cxt.new_streaming_source()
|
|
.expect("could not create streaming src");
|
|
let sample_rate = srr.ident_hdr.audio_sample_rate as i32;
|
|
|
|
if srr.ident_hdr.audio_channels > 2 {
|
|
// the openal crate can't process these many channels directly
|
|
println!("Stream error: {} channels are too many!", srr.ident_hdr.audio_channels);
|
|
}
|
|
|
|
println!("Sample rate: {}", srr.ident_hdr.audio_sample_rate);
|
|
|
|
// Now the fun starts..
|
|
let mut n = 0;
|
|
let mut len_play = 0.0;
|
|
let mut start_play_time = None;
|
|
let start_decode_time = Instant::now();
|
|
let sample_channels = srr.ident_hdr.audio_channels as f32 *
|
|
srr.ident_hdr.audio_sample_rate as f32;
|
|
while let Some(pck_samples) = try!(srr.read_dec_packet_itl()) {
|
|
println!("Decoded packet no {}, with {} samples.", n, pck_samples.len());
|
|
n += 1;
|
|
let buf = match srr.ident_hdr.audio_channels {
|
|
1 => cxt.new_buffer::<Mono<i16>,_>(&pck_samples, sample_rate),
|
|
2 => cxt.new_buffer::<Stereo<i16>,_>(&pck_samples, sample_rate),
|
|
n => panic!("unsupported number of channels: {}", n),
|
|
}.unwrap();
|
|
|
|
str_src.queue_buffer(buf).unwrap();
|
|
|
|
len_play += pck_samples.len() as f32 / sample_channels;
|
|
// If we are faster than realtime, we can already start playing now.
|
|
if n == 100 {
|
|
let cur = Instant::now();
|
|
if cur - start_decode_time < Duration::from_millis((len_play * 1000.0) as u64) {
|
|
start_play_time = Some(cur);
|
|
str_src.play();
|
|
}
|
|
}
|
|
}
|
|
let total_duration = Duration::from_millis((len_play * 1000.0) as u64);
|
|
let sleep_duration = total_duration - match start_play_time {
|
|
None => {
|
|
str_src.play();
|
|
Duration::from_millis(0)
|
|
},
|
|
Some(t) => (Instant::now() - t)
|
|
};
|
|
println!("The piece is {} s long.", len_play);
|
|
sleep(sleep_duration);
|
|
|
|
Ok(())
|
|
}
|