1 use std::io::{Read, Seek, SeekFrom};
2 use std::time::Duration;
3 use std::vec;
4 
5 use crate::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 stream_reader = OggStreamReader::new(data).unwrap();
29         Ok(Self::from_stream_reader(stream_reader))
30     }
from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self31     pub fn from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self {
32         let mut data = match stream_reader.read_dec_packet_itl() {
33             Ok(Some(d)) => d,
34             _ => Vec::new(),
35         };
36 
37         // The first packet is always empty, therefore
38         // we need to read the second frame to get some data
39         if let Ok(Some(mut d)) = stream_reader.read_dec_packet_itl() {
40             data.append(&mut d);
41         }
42 
43         VorbisDecoder {
44             stream_reader,
45             current_data: data.into_iter(),
46         }
47     }
into_inner(self) -> OggStreamReader<R>48     pub fn into_inner(self) -> OggStreamReader<R> {
49         self.stream_reader
50     }
51 }
52 
53 impl<R> Source for VorbisDecoder<R>
54 where
55     R: Read + Seek,
56 {
57     #[inline]
current_frame_len(&self) -> Option<usize>58     fn current_frame_len(&self) -> Option<usize> {
59         Some(self.current_data.len())
60     }
61 
62     #[inline]
channels(&self) -> u1663     fn channels(&self) -> u16 {
64         self.stream_reader.ident_hdr.audio_channels as u16
65     }
66 
67     #[inline]
sample_rate(&self) -> u3268     fn sample_rate(&self) -> u32 {
69         self.stream_reader.ident_hdr.audio_sample_rate
70     }
71 
72     #[inline]
total_duration(&self) -> Option<Duration>73     fn total_duration(&self) -> Option<Duration> {
74         None
75     }
76 }
77 
78 impl<R> Iterator for VorbisDecoder<R>
79 where
80     R: Read + Seek,
81 {
82     type Item = i16;
83 
84     #[inline]
next(&mut self) -> Option<i16>85     fn next(&mut self) -> Option<i16> {
86         if let Some(sample) = self.current_data.next() {
87             if self.current_data.len() == 0 {
88                 if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
89                     self.current_data = data.into_iter();
90                 }
91             }
92             Some(sample)
93         } else {
94             if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
95                 self.current_data = data.into_iter();
96             }
97             self.current_data.next()
98         }
99     }
100 
101     #[inline]
size_hint(&self) -> (usize, Option<usize>)102     fn size_hint(&self) -> (usize, Option<usize>) {
103         (self.current_data.size_hint().0, None)
104     }
105 }
106 
107 /// 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,108 fn is_vorbis<R>(mut data: R) -> bool
109 where
110     R: Read + Seek,
111 {
112     let stream_pos = data.seek(SeekFrom::Current(0)).unwrap();
113 
114     if OggStreamReader::new(data.by_ref()).is_err() {
115         data.seek(SeekFrom::Start(stream_pos)).unwrap();
116         return false;
117     }
118 
119     data.seek(SeekFrom::Start(stream_pos)).unwrap();
120     true
121 }
122