1use std::error::Error;
4use std::fmt;
5#[allow(unused_imports)]
6use std::io::{Read, Seek, SeekFrom};
7use std::mem;
8use std::str::FromStr;
9use std::time::Duration;
10
11use crate::source::SeekError;
12use crate::Source;
13
14#[cfg(feature = "symphonia")]
15use self::read_seek_source::ReadSeekSource;
16#[cfg(feature = "symphonia")]
17use ::symphonia::core::io::{MediaSource, MediaSourceStream};
18
19#[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
20mod flac;
21#[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
22mod mp3;
23#[cfg(feature = "symphonia")]
24mod read_seek_source;
25#[cfg(feature = "symphonia")]
26pub mod symphonia;
28#[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
29mod vorbis;
30#[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
31mod wav;
32
33pub struct Decoder<R>(DecoderImpl<R>)
37where
38 R: Read + Seek;
39
40pub struct LoopedDecoder<R>(DecoderImpl<R>)
45where
46 R: Read + Seek;
47
48#[allow(clippy::large_enum_variant)]
51enum DecoderImpl<R>
52where
53 R: Read + Seek,
54{
55 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
56 Wav(wav::WavDecoder<R>),
57 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
58 Vorbis(vorbis::VorbisDecoder<R>),
59 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
60 Flac(flac::FlacDecoder<R>),
61 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
62 Mp3(mp3::Mp3Decoder<R>),
63 #[cfg(feature = "symphonia")]
64 Symphonia(symphonia::SymphoniaDecoder),
65 None(::std::marker::PhantomData<R>),
66}
67
68impl<R: Read + Seek> DecoderImpl<R> {
69 #[inline]
70 fn next(&mut self) -> Option<i16> {
71 match self {
72 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
73 DecoderImpl::Wav(source) => source.next(),
74 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
75 DecoderImpl::Vorbis(source) => source.next(),
76 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
77 DecoderImpl::Flac(source) => source.next(),
78 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
79 DecoderImpl::Mp3(source) => source.next(),
80 #[cfg(feature = "symphonia")]
81 DecoderImpl::Symphonia(source) => source.next(),
82 DecoderImpl::None(_) => None,
83 }
84 }
85
86 #[inline]
87 fn size_hint(&self) -> (usize, Option<usize>) {
88 match self {
89 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
90 DecoderImpl::Wav(source) => source.size_hint(),
91 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
92 DecoderImpl::Vorbis(source) => source.size_hint(),
93 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
94 DecoderImpl::Flac(source) => source.size_hint(),
95 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
96 DecoderImpl::Mp3(source) => source.size_hint(),
97 #[cfg(feature = "symphonia")]
98 DecoderImpl::Symphonia(source) => source.size_hint(),
99 DecoderImpl::None(_) => (0, None),
100 }
101 }
102
103 #[inline]
104 fn current_frame_len(&self) -> Option<usize> {
105 match self {
106 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
107 DecoderImpl::Wav(source) => source.current_frame_len(),
108 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
109 DecoderImpl::Vorbis(source) => source.current_frame_len(),
110 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
111 DecoderImpl::Flac(source) => source.current_frame_len(),
112 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
113 DecoderImpl::Mp3(source) => source.current_frame_len(),
114 #[cfg(feature = "symphonia")]
115 DecoderImpl::Symphonia(source) => source.current_frame_len(),
116 DecoderImpl::None(_) => Some(0),
117 }
118 }
119
120 #[inline]
121 fn channels(&self) -> u16 {
122 match self {
123 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
124 DecoderImpl::Wav(source) => source.channels(),
125 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
126 DecoderImpl::Vorbis(source) => source.channels(),
127 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
128 DecoderImpl::Flac(source) => source.channels(),
129 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
130 DecoderImpl::Mp3(source) => source.channels(),
131 #[cfg(feature = "symphonia")]
132 DecoderImpl::Symphonia(source) => source.channels(),
133 DecoderImpl::None(_) => 0,
134 }
135 }
136
137 #[inline]
138 fn sample_rate(&self) -> u32 {
139 match self {
140 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
141 DecoderImpl::Wav(source) => source.sample_rate(),
142 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
143 DecoderImpl::Vorbis(source) => source.sample_rate(),
144 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
145 DecoderImpl::Flac(source) => source.sample_rate(),
146 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
147 DecoderImpl::Mp3(source) => source.sample_rate(),
148 #[cfg(feature = "symphonia")]
149 DecoderImpl::Symphonia(source) => source.sample_rate(),
150 DecoderImpl::None(_) => 1,
151 }
152 }
153
154 #[inline]
155 fn total_duration(&self) -> Option<Duration> {
156 match self {
157 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
158 DecoderImpl::Wav(source) => source.total_duration(),
159 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
160 DecoderImpl::Vorbis(source) => source.total_duration(),
161 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
162 DecoderImpl::Flac(source) => source.total_duration(),
163 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
164 DecoderImpl::Mp3(source) => source.total_duration(),
165 #[cfg(feature = "symphonia")]
166 DecoderImpl::Symphonia(source) => source.total_duration(),
167 DecoderImpl::None(_) => Some(Duration::default()),
168 }
169 }
170
171 #[inline]
172 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
173 match self {
174 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
175 DecoderImpl::Wav(source) => source.try_seek(pos),
176 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
177 DecoderImpl::Vorbis(source) => source.try_seek(pos),
178 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
179 DecoderImpl::Flac(source) => source.try_seek(pos),
180 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
181 DecoderImpl::Mp3(source) => source.try_seek(pos),
182 #[cfg(feature = "symphonia")]
183 DecoderImpl::Symphonia(source) => source.try_seek(pos),
184 DecoderImpl::None(_) => Err(SeekError::NotSupported {
185 underlying_source: "DecoderImpl::None",
186 }),
187 }
188 }
189}
190
191impl<R> Decoder<R>
192where
193 R: Read + Seek + Send + Sync + 'static,
194{
195 #[allow(unused_variables)]
199 pub fn new(data: R) -> Result<Decoder<R>, DecoderError> {
200 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
201 let data = match wav::WavDecoder::new(data) {
202 Err(data) => data,
203 Ok(decoder) => {
204 return Ok(Decoder(DecoderImpl::Wav(decoder)));
205 }
206 };
207
208 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
209 let data = match flac::FlacDecoder::new(data) {
210 Err(data) => data,
211 Ok(decoder) => {
212 return Ok(Decoder(DecoderImpl::Flac(decoder)));
213 }
214 };
215
216 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
217 let data = match vorbis::VorbisDecoder::new(data) {
218 Err(data) => data,
219 Ok(decoder) => {
220 return Ok(Decoder(DecoderImpl::Vorbis(decoder)));
221 }
222 };
223
224 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
225 let data = match mp3::Mp3Decoder::new(data) {
226 Err(data) => data,
227 Ok(decoder) => {
228 return Ok(Decoder(DecoderImpl::Mp3(decoder)));
229 }
230 };
231
232 #[cfg(feature = "symphonia")]
233 {
234 let mss = MediaSourceStream::new(
235 Box::new(ReadSeekSource::new(data)) as Box<dyn MediaSource>,
236 Default::default(),
237 );
238
239 match symphonia::SymphoniaDecoder::new(mss, None) {
240 Err(e) => Err(e),
241 Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
242 }
243 }
244 #[cfg(not(feature = "symphonia"))]
245 Err(DecoderError::UnrecognizedFormat)
246 }
247
248 pub fn new_looped(data: R) -> Result<LoopedDecoder<R>, DecoderError> {
252 Self::new(data).map(LoopedDecoder::new)
253 }
254
255 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
257 pub fn new_wav(data: R) -> Result<Decoder<R>, DecoderError> {
258 match wav::WavDecoder::new(data) {
259 Err(_) => Err(DecoderError::UnrecognizedFormat),
260 Ok(decoder) => Ok(Decoder(DecoderImpl::Wav(decoder))),
261 }
262 }
263
264 #[cfg(feature = "symphonia-wav")]
266 pub fn new_wav(data: R) -> Result<Decoder<R>, DecoderError> {
267 Decoder::new_symphonia(data, "wav")
268 }
269
270 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
272 pub fn new_flac(data: R) -> Result<Decoder<R>, DecoderError> {
273 match flac::FlacDecoder::new(data) {
274 Err(_) => Err(DecoderError::UnrecognizedFormat),
275 Ok(decoder) => Ok(Decoder(DecoderImpl::Flac(decoder))),
276 }
277 }
278
279 #[cfg(feature = "symphonia-flac")]
281 pub fn new_flac(data: R) -> Result<Decoder<R>, DecoderError> {
282 Decoder::new_symphonia(data, "flac")
283 }
284
285 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
287 pub fn new_vorbis(data: R) -> Result<Decoder<R>, DecoderError> {
288 match vorbis::VorbisDecoder::new(data) {
289 Err(_) => Err(DecoderError::UnrecognizedFormat),
290 Ok(decoder) => Ok(Decoder(DecoderImpl::Vorbis(decoder))),
291 }
292 }
293
294 #[cfg(feature = "symphonia-vorbis")]
296 pub fn new_vorbis(data: R) -> Result<Decoder<R>, DecoderError> {
297 Decoder::new_symphonia(data, "ogg")
298 }
299
300 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
302 pub fn new_mp3(data: R) -> Result<Decoder<R>, DecoderError> {
303 match mp3::Mp3Decoder::new(data) {
304 Err(_) => Err(DecoderError::UnrecognizedFormat),
305 Ok(decoder) => Ok(Decoder(DecoderImpl::Mp3(decoder))),
306 }
307 }
308
309 #[cfg(feature = "symphonia-mp3")]
311 pub fn new_mp3(data: R) -> Result<Decoder<R>, DecoderError> {
312 Decoder::new_symphonia(data, "mp3")
313 }
314
315 #[cfg(feature = "symphonia-aac")]
317 pub fn new_aac(data: R) -> Result<Decoder<R>, DecoderError> {
318 Decoder::new_symphonia(data, "aac")
319 }
320
321 #[cfg(feature = "symphonia-isomp4")]
323 pub fn new_mp4(data: R, hint: Mp4Type) -> Result<Decoder<R>, DecoderError> {
324 Decoder::new_symphonia(data, &hint.to_string())
325 }
326
327 #[cfg(feature = "symphonia")]
328 fn new_symphonia(data: R, hint: &str) -> Result<Decoder<R>, DecoderError> {
329 let mss = MediaSourceStream::new(
330 Box::new(ReadSeekSource::new(data)) as Box<dyn MediaSource>,
331 Default::default(),
332 );
333
334 match symphonia::SymphoniaDecoder::new(mss, Some(hint)) {
335 Err(e) => Err(e),
336 Ok(decoder) => Ok(Decoder(DecoderImpl::Symphonia(decoder))),
337 }
338 }
339}
340
341#[allow(missing_docs)] #[derive(Debug)]
343pub enum Mp4Type {
344 Mp4,
345 M4a,
346 M4p,
347 M4b,
348 M4r,
349 M4v,
350 Mov,
351}
352
353impl FromStr for Mp4Type {
354 type Err = String;
355
356 fn from_str(input: &str) -> Result<Mp4Type, Self::Err> {
357 match &input.to_lowercase()[..] {
358 "mp4" => Ok(Mp4Type::Mp4),
359 "m4a" => Ok(Mp4Type::M4a),
360 "m4p" => Ok(Mp4Type::M4p),
361 "m4b" => Ok(Mp4Type::M4b),
362 "m4r" => Ok(Mp4Type::M4r),
363 "m4v" => Ok(Mp4Type::M4v),
364 "mov" => Ok(Mp4Type::Mov),
365 _ => Err(format!("{input} is not a valid mp4 extension")),
366 }
367 }
368}
369
370impl fmt::Display for Mp4Type {
371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372 let text = match self {
373 Mp4Type::Mp4 => "mp4",
374 Mp4Type::M4a => "m4a",
375 Mp4Type::M4p => "m4p",
376 Mp4Type::M4b => "m4b",
377 Mp4Type::M4r => "m4r",
378 Mp4Type::M4v => "m4v",
379 Mp4Type::Mov => "mov",
380 };
381 write!(f, "{text}")
382 }
383}
384
385impl<R> LoopedDecoder<R>
386where
387 R: Read + Seek,
388{
389 fn new(decoder: Decoder<R>) -> LoopedDecoder<R> {
390 Self(decoder.0)
391 }
392}
393
394impl<R> Iterator for Decoder<R>
395where
396 R: Read + Seek,
397{
398 type Item = i16;
399
400 #[inline]
401 fn next(&mut self) -> Option<i16> {
402 self.0.next()
403 }
404
405 #[inline]
406 fn size_hint(&self) -> (usize, Option<usize>) {
407 self.0.size_hint()
408 }
409}
410
411impl<R> Source for Decoder<R>
412where
413 R: Read + Seek,
414{
415 #[inline]
416 fn current_frame_len(&self) -> Option<usize> {
417 self.0.current_frame_len()
418 }
419
420 #[inline]
421 fn channels(&self) -> u16 {
422 self.0.channels()
423 }
424
425 fn sample_rate(&self) -> u32 {
426 self.0.sample_rate()
427 }
428
429 #[inline]
430 fn total_duration(&self) -> Option<Duration> {
431 self.0.total_duration()
432 }
433
434 #[inline]
435 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
436 self.0.try_seek(pos)
437 }
438}
439
440impl<R> Iterator for LoopedDecoder<R>
441where
442 R: Read + Seek,
443{
444 type Item = i16;
445
446 #[inline]
447 fn next(&mut self) -> Option<i16> {
448 if let Some(sample) = self.0.next() {
449 Some(sample)
450 } else {
451 let decoder = mem::replace(&mut self.0, DecoderImpl::None(Default::default()));
452 let (decoder, sample) = match decoder {
453 #[cfg(all(feature = "wav", not(feature = "symphonia-wav")))]
454 DecoderImpl::Wav(source) => {
455 let mut reader = source.into_inner();
456 reader.seek(SeekFrom::Start(0)).ok()?;
457 let mut source = wav::WavDecoder::new(reader).ok()?;
458 let sample = source.next();
459 (DecoderImpl::Wav(source), sample)
460 }
461 #[cfg(all(feature = "vorbis", not(feature = "symphonia-vorbis")))]
462 DecoderImpl::Vorbis(source) => {
463 use lewton::inside_ogg::OggStreamReader;
464 let mut reader = source.into_inner().into_inner();
465 reader.seek_bytes(SeekFrom::Start(0)).ok()?;
466 let mut source = vorbis::VorbisDecoder::from_stream_reader(
467 OggStreamReader::from_ogg_reader(reader).ok()?,
468 );
469 let sample = source.next();
470 (DecoderImpl::Vorbis(source), sample)
471 }
472 #[cfg(all(feature = "flac", not(feature = "symphonia-flac")))]
473 DecoderImpl::Flac(source) => {
474 let mut reader = source.into_inner();
475 reader.seek(SeekFrom::Start(0)).ok()?;
476 let mut source = flac::FlacDecoder::new(reader).ok()?;
477 let sample = source.next();
478 (DecoderImpl::Flac(source), sample)
479 }
480 #[cfg(all(feature = "minimp3", not(feature = "symphonia-mp3")))]
481 DecoderImpl::Mp3(source) => {
482 let mut reader = source.into_inner();
483 reader.seek(SeekFrom::Start(0)).ok()?;
484 let mut source = mp3::Mp3Decoder::new(reader).ok()?;
485 let sample = source.next();
486 (DecoderImpl::Mp3(source), sample)
487 }
488 #[cfg(feature = "symphonia")]
489 DecoderImpl::Symphonia(source) => {
490 let mut reader = source.into_inner();
491 reader.seek(SeekFrom::Start(0)).ok()?;
492 let mut source = symphonia::SymphoniaDecoder::new(reader, None).ok()?;
493 let sample = source.next();
494 (DecoderImpl::Symphonia(source), sample)
495 }
496 none @ DecoderImpl::None(_) => (none, None),
497 };
498 self.0 = decoder;
499 sample
500 }
501 }
502
503 #[inline]
504 fn size_hint(&self) -> (usize, Option<usize>) {
505 self.0.size_hint()
506 }
507}
508
509impl<R> Source for LoopedDecoder<R>
510where
511 R: Read + Seek,
512{
513 #[inline]
514 fn current_frame_len(&self) -> Option<usize> {
515 self.0.current_frame_len()
516 }
517
518 #[inline]
519 fn channels(&self) -> u16 {
520 self.0.channels()
521 }
522
523 #[inline]
524 fn sample_rate(&self) -> u32 {
525 self.0.sample_rate()
526 }
527
528 #[inline]
529 fn total_duration(&self) -> Option<Duration> {
530 None
531 }
532
533 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
534 self.0.try_seek(pos)
535 }
536}
537
538#[derive(Debug, Clone)]
540pub enum DecoderError {
541 UnrecognizedFormat,
543
544 #[cfg(feature = "symphonia")]
546 IoError(String),
547
548 #[cfg(feature = "symphonia")]
550 DecodeError(&'static str),
551
552 #[cfg(feature = "symphonia")]
555 LimitError(&'static str),
556
557 #[cfg(feature = "symphonia")]
559 ResetRequired,
560
561 #[cfg(feature = "symphonia")]
563 NoStreams,
564}
565
566impl fmt::Display for DecoderError {
567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568 let text = match self {
569 DecoderError::UnrecognizedFormat => "Unrecognized format",
570 #[cfg(feature = "symphonia")]
571 DecoderError::IoError(msg) => &msg[..],
572 #[cfg(feature = "symphonia")]
573 DecoderError::DecodeError(msg) => msg,
574 #[cfg(feature = "symphonia")]
575 DecoderError::LimitError(msg) => msg,
576 #[cfg(feature = "symphonia")]
577 DecoderError::ResetRequired => "Reset required",
578 #[cfg(feature = "symphonia")]
579 DecoderError::NoStreams => "No streams",
580 };
581 write!(f, "{text}")
582 }
583}
584
585impl Error for DecoderError {}