1 use std::io::{Read, Seek, SeekFrom};
2 use std::time::Duration;
3 use std::vec;
4 
5 use Source;
6 
7 use lewton::inside_ogg::OggStreamReader;
8 
9 /// Decoder for an OGG file that contains Vorbis sound format.
10 pub struct VorbisDecoder<R>
11 where
12     R: Read + Seek,
13 {
14     stream_reader: OggStreamReader<R>,
15     current_data: vec::IntoIter<i16>,
16 }
17 
18 impl<R> VorbisDecoder<R>
19 where
20     R: Read + Seek,
21 {
22     /// Attempts to decode the data as ogg/vorbis.
new(mut data: R) -> Result<VorbisDecoder<R>, R>23     pub fn new(mut data: R) -> Result<VorbisDecoder<R>, R> {
24         if !is_vorbis(data.by_ref()) {
25             return Err(data);
26         }
27 
28         let mut stream_reader = OggStreamReader::new(data).unwrap();
29 
30         let mut data = match stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
31             Some(d) => d,
32             None => Vec::new(),
33         };
34 
35         // The first packet is always empty, therefore
36         // we need to read the second frame to get some data
37         match stream_reader.read_dec_packet_itl().ok().and_then(|v| v) {
38             Some(mut d) => data.append(&mut d),
39             None => (),
40         };
41 
42         Ok(VorbisDecoder {
43             stream_reader: stream_reader,
44             current_data: data.into_iter(),
45         })
46     }
47 }
48 
49 impl<R> Source for VorbisDecoder<R>
50 where
51     R: Read + Seek,
52 {
53     #[inline]
current_frame_len(&self) -> Option<usize>54     fn current_frame_len(&self) -> Option<usize> {
55         Some(self.current_data.len())
56     }
57 
58     #[inline]
channels(&self) -> u1659     fn channels(&self) -> u16 {
60         self.stream_reader.ident_hdr.audio_channels as u16
61     }
62 
63     #[inline]
sample_rate(&self) -> u3264     fn sample_rate(&self) -> u32 {
65         self.stream_reader.ident_hdr.audio_sample_rate
66     }
67 
68     #[inline]
total_duration(&self) -> Option<Duration>69     fn total_duration(&self) -> Option<Duration> {
70         None
71     }
72 }
73 
74 impl<R> Iterator for VorbisDecoder<R>
75 where
76     R: Read + Seek,
77 {
78     type Item = i16;
79 
80     #[inline]
next(&mut self) -> Option<i16>81     fn next(&mut self) -> Option<i16> {
82         if let Some(sample) = self.current_data.next() {
83             if self.current_data.len() == 0 {
84                 if let Some(data) = self
85                     .stream_reader
86                     .read_dec_packet_itl()
87                     .ok()
88                     .and_then(|v| v)
89                 {
90                     self.current_data = data.into_iter();
91                 }
92             }
93             return Some(sample);
94         } else {
95             if let Some(data) = self
96                 .stream_reader
97                 .read_dec_packet_itl()
98                 .ok()
99                 .and_then(|v| v)
100             {
101                 self.current_data = data.into_iter();
102             }
103             return self.current_data.next();
104         }
105     }
106 
107     #[inline]
size_hint(&self) -> (usize, Option<usize>)108     fn size_hint(&self) -> (usize, Option<usize>) {
109         (self.current_data.size_hint().0, None)
110     }
111 }
112 
113 /// Returns true if the stream contains Vorbis data, then resets it to where it was.
is_vorbis<R>(mut data: R) -> bool where R: Read + Seek,114 fn is_vorbis<R>(mut data: R) -> bool
115 where
116     R: Read + Seek,
117 {
118     let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
119 
120     if OggStreamReader::new(data.by_ref()).is_err() {
121         data.seek(SeekFrom::Start(stream_pos)).unwrap();
122         return false;
123     }
124 
125     data.seek(SeekFrom::Start(stream_pos)).unwrap();
126     true
127 }
128