rodio/decoder/
vorbis.rs
1use std::io::{Read, Seek, SeekFrom};
2use std::time::Duration;
3
4use crate::source::SeekError;
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<i16>,
16 next: usize,
17}
18
19impl<R> VorbisDecoder<R>
20where
21 R: Read + Seek,
22{
23 pub fn new(mut data: R) -> Result<VorbisDecoder<R>, R> {
25 if !is_vorbis(data.by_ref()) {
26 return Err(data);
27 }
28
29 let stream_reader = OggStreamReader::new(data).unwrap();
30 Ok(Self::from_stream_reader(stream_reader))
31 }
32 pub fn from_stream_reader(mut stream_reader: OggStreamReader<R>) -> Self {
33 let mut data = match stream_reader.read_dec_packet_itl() {
34 Ok(Some(d)) => d,
35 _ => Vec::new(),
36 };
37
38 if let Ok(Some(mut d)) = stream_reader.read_dec_packet_itl() {
41 data.append(&mut d);
42 }
43
44 VorbisDecoder {
45 stream_reader,
46 current_data: data,
47 next: 0,
48 }
49 }
50 pub fn into_inner(self) -> OggStreamReader<R> {
51 self.stream_reader
52 }
53}
54
55impl<R> Source for VorbisDecoder<R>
56where
57 R: Read + Seek,
58{
59 #[inline]
60 fn current_frame_len(&self) -> Option<usize> {
61 Some(self.current_data.len())
62 }
63
64 #[inline]
65 fn channels(&self) -> u16 {
66 self.stream_reader.ident_hdr.audio_channels as u16
67 }
68
69 #[inline]
70 fn sample_rate(&self) -> u32 {
71 self.stream_reader.ident_hdr.audio_sample_rate
72 }
73
74 #[inline]
75 fn total_duration(&self) -> Option<Duration> {
76 None
77 }
78
79 #[inline]
89 fn try_seek(&mut self, _: Duration) -> Result<(), SeekError> {
90 Err(SeekError::NotSupported {
91 underlying_source: std::any::type_name::<Self>(),
92 })
93 }
94}
95
96impl<R> Iterator for VorbisDecoder<R>
97where
98 R: Read + Seek,
99{
100 type Item = i16;
101
102 #[inline]
103 fn next(&mut self) -> Option<i16> {
104 if let Some(sample) = self.current_data.get(self.next).copied() {
105 self.next += 1;
106 if self.current_data.is_empty() {
107 if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
108 self.current_data = data;
109 self.next = 0;
110 }
111 }
112 Some(sample)
113 } else {
114 if let Ok(Some(data)) = self.stream_reader.read_dec_packet_itl() {
115 self.current_data = data;
116 self.next = 0;
117 }
118 let sample = self.current_data.get(self.next).copied();
119 self.next += 1;
120 sample
121 }
122 }
123
124 #[inline]
125 fn size_hint(&self) -> (usize, Option<usize>) {
126 (self.current_data.len(), None)
127 }
128}
129
130fn is_vorbis<R>(mut data: R) -> bool
132where
133 R: Read + Seek,
134{
135 let stream_pos = data.stream_position().unwrap();
136
137 if OggStreamReader::new(data.by_ref()).is_err() {
138 data.seek(SeekFrom::Start(stream_pos)).unwrap();
139 return false;
140 }
141
142 data.seek(SeekFrom::Start(stream_pos)).unwrap();
143 true
144}