extern crate claxon;
extern crate hound;
extern crate ogg;
use std::env;
use std::fs::File;
use std::io;
use std::path::Path;
use claxon::input::ReadBytes;
use claxon::metadata::{StreamInfo, read_metadata_block_with_header};
use hound::{WavSpec, WavWriter};
fn decode_file(fname: &Path) {
let file = File::open(fname).expect("failed to open ogg file");
let bufread = io::BufReader::new(file);
let mut preader = ogg::PacketReader::new(bufread);
let first_packet = preader.read_packet_expected().expect("failed to read ogg");
let (streaminfo, header_packets_left) = read_first_packet(&first_packet);
for _ in 0..header_packets_left {
let packet = preader.read_packet_expected().expect("failed to read ogg");
let mut cursor = io::Cursor::new(&packet.data);
let _metadata_block = read_metadata_block_with_header(&mut cursor).unwrap();
}
let spec = WavSpec {
channels: streaminfo.channels as u16,
sample_rate: streaminfo.sample_rate,
bits_per_sample: streaminfo.bits_per_sample as u16,
sample_format: hound::SampleFormat::Int,
};
let fname_wav = fname.with_extension("wav");
let opt_wav_writer = WavWriter::create(fname_wav, spec);
let mut wav_writer = opt_wav_writer.expect("failed to create wav file");
let mut buffer = Vec::with_capacity(streaminfo.max_block_size as usize *
streaminfo.channels as usize);
while let Some(packet) = preader.read_packet().expect("failed to read ogg") {
if packet.data.len() == 0 { continue }
buffer = decode_frame(&packet, buffer, &mut wav_writer);
}
}
fn read_first_packet(packet: &ogg::Packet) -> (StreamInfo, u16) {
use claxon::metadata::MetadataBlock;
let mut cursor = io::Cursor::new(&packet.data);
cursor.skip(7).unwrap();
let header_packets_left = cursor.read_be_u16().unwrap();
cursor.skip(4).unwrap();
match read_metadata_block_with_header(&mut cursor) {
Ok(MetadataBlock::StreamInfo(si)) => (si, header_packets_left),
Ok(..) => panic!("expected streaminfo, found other metadata block"),
Err(err) => panic!("failed to read streaminfo: {:?}", err),
}
}
fn decode_frame<W>(packet: &ogg::Packet,
buffer: Vec<i32>,
wav_writer: &mut WavWriter<W>)
-> Vec<i32>
where W: io::Seek + io::Write {
let cursor = io::Cursor::new(&packet.data);
let mut frame_reader = claxon::frame::FrameReader::new(cursor);
let result = frame_reader.read_next_or_eof(buffer);
let block = result.expect("failed to decode frame").expect("unexpected EOF");
for (sl, sr) in block.stereo_samples() {
wav_writer.write_sample(sl).expect("failed to write wav file");
wav_writer.write_sample(sr).expect("failed to write wav file");
}
block.into_buffer()
}
fn main() {
for fname in env::args().skip(1) {
decode_file(&Path::new(&fname));
}
}