rodiogaga/decoder/
vorbis.rs1use std::io::{Read, Seek, SeekFrom};
2use std::time::Duration;
3use std::vec;
4
5use crate::Source;
6
7use lewton::inside_ogg::OggStreamReader;
8
9pub struct VorbisDecoder<R>
11where
12 R: Read + Seek,
13{
14 stream_reader: OggStreamReader<R>,
15 current_data: vec::IntoIter<i16>,
16}
17
18impl<R> VorbisDecoder<R>
19where
20 R: Read + Seek,
21{
22 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 }
31 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 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 }
48 pub fn into_inner(self) -> OggStreamReader<R> {
49 self.stream_reader
50 }
51}
52
53impl<R> Source for VorbisDecoder<R>
54where
55 R: Read + Seek,
56{
57 #[inline]
58 fn current_frame_len(&self) -> Option<usize> {
59 Some(self.current_data.len())
60 }
61
62 #[inline]
63 fn channels(&self) -> u16 {
64 self.stream_reader.ident_hdr.audio_channels as u16
65 }
66
67 #[inline]
68 fn sample_rate(&self) -> u32 {
69 self.stream_reader.ident_hdr.audio_sample_rate
70 }
71
72 #[inline]
73 fn total_duration(&self) -> Option<Duration> {
74 None
75 }
76}
77
78impl<R> Iterator for VorbisDecoder<R>
79where
80 R: Read + Seek,
81{
82 type Item = i16;
83
84 #[inline]
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]
102 fn size_hint(&self) -> (usize, Option<usize>) {
103 (self.current_data.size_hint().0, None)
104 }
105}
106
107fn is_vorbis<R>(mut data: R) -> bool
109where
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}