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