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