rodio/decoder/
flac.rs
1use std::cmp::Ordering;
2use std::io::{Read, Seek, SeekFrom};
3use std::mem;
4use std::time::Duration;
5
6use crate::source::SeekError;
7use crate::Source;
8
9use claxon::FlacReader;
10
11pub struct FlacDecoder<R>
13where
14 R: Read + Seek,
15{
16 reader: FlacReader<R>,
17 current_block: Vec<i32>,
18 current_block_channel_len: usize,
19 current_block_off: usize,
20 bits_per_sample: u32,
21 sample_rate: u32,
22 channels: u16,
23 samples: Option<u64>,
24}
25
26impl<R> FlacDecoder<R>
27where
28 R: Read + Seek,
29{
30 pub fn new(mut data: R) -> Result<FlacDecoder<R>, R> {
32 if !is_flac(data.by_ref()) {
33 return Err(data);
34 }
35
36 let reader = FlacReader::new(data).unwrap();
37 let spec = reader.streaminfo();
38
39 Ok(FlacDecoder {
40 reader,
41 current_block: Vec::with_capacity(
42 spec.max_block_size as usize * spec.channels as usize,
43 ),
44 current_block_channel_len: 1,
45 current_block_off: 0,
46 bits_per_sample: spec.bits_per_sample,
47 sample_rate: spec.sample_rate,
48 channels: spec.channels as u16,
49 samples: spec.samples,
50 })
51 }
52 pub fn into_inner(self) -> R {
53 self.reader.into_inner()
54 }
55}
56
57impl<R> Source for FlacDecoder<R>
58where
59 R: Read + Seek,
60{
61 #[inline]
62 fn current_frame_len(&self) -> Option<usize> {
63 None
64 }
65
66 #[inline]
67 fn channels(&self) -> u16 {
68 self.channels
69 }
70
71 #[inline]
72 fn sample_rate(&self) -> u32 {
73 self.sample_rate
74 }
75
76 #[inline]
77 fn total_duration(&self) -> Option<Duration> {
78 self.samples
81 .map(|s| Duration::from_micros(s * 1_000_000 / self.sample_rate as u64))
82 }
83
84 #[inline]
85 fn try_seek(&mut self, _: Duration) -> Result<(), SeekError> {
86 Err(SeekError::NotSupported {
87 underlying_source: std::any::type_name::<Self>(),
88 })
89 }
90}
91
92impl<R> Iterator for FlacDecoder<R>
93where
94 R: Read + Seek,
95{
96 type Item = i16;
97
98 #[inline]
99 fn next(&mut self) -> Option<i16> {
100 loop {
101 if self.current_block_off < self.current_block.len() {
102 let real_offset = (self.current_block_off % self.channels as usize)
104 * self.current_block_channel_len
105 + self.current_block_off / self.channels as usize;
106 let raw_val = self.current_block[real_offset];
107 self.current_block_off += 1;
108 let real_val = match self.bits_per_sample.cmp(&16) {
109 Ordering::Less => (raw_val << (16 - self.bits_per_sample)) as i16,
110 Ordering::Equal => raw_val as i16,
111 Ordering::Greater => (raw_val >> (self.bits_per_sample - 16)) as i16,
112 };
113 return Some(real_val);
114 }
115
116 self.current_block_off = 0;
118 let buffer = mem::take(&mut self.current_block);
119 match self.reader.blocks().read_next_or_eof(buffer) {
120 Ok(Some(block)) => {
121 self.current_block_channel_len = (block.len() / block.channels()) as usize;
122 self.current_block = block.into_buffer();
123 }
124 _ => return None,
125 }
126 }
127 }
128}
129
130fn is_flac<R>(mut data: R) -> bool
132where
133 R: Read + Seek,
134{
135 let stream_pos = data.stream_position().unwrap();
136
137 if FlacReader::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}