euphony_buffer/
decode.rs

1use std::io;
2use symphonia::core::{
3    audio::{AudioBuffer, AudioBufferRef},
4    conv::{FromSample, IntoSample},
5    probe::Hint,
6    sample::{i24, u24, Sample},
7};
8
9#[derive(Clone, Debug)]
10pub struct Samples<S> {
11    pub channels: Vec<Vec<S>>,
12    pub sample_rate: Option<u32>,
13}
14
15impl<S> Samples<S>
16where
17    S: Sample
18        + FromSample<u8>
19        + FromSample<u16>
20        + FromSample<u24>
21        + FromSample<u32>
22        + FromSample<i8>
23        + FromSample<i16>
24        + FromSample<i24>
25        + FromSample<i32>
26        + FromSample<f32>
27        + FromSample<f64>,
28{
29    pub fn from_reader(
30        stream: &mut dyn symphonia::core::formats::FormatReader,
31    ) -> Result<Samples<S>, symphonia::core::errors::Error> {
32        let track = if let Some(track) = stream.default_track() {
33            track
34        } else {
35            return Ok(Samples {
36                channels: vec![],
37                sample_rate: None,
38            });
39        };
40        let sample_rate = track.codec_params.sample_rate;
41        let n_frames = track.codec_params.n_frames;
42
43        let mut decoder =
44            symphonia::default::get_codecs().make(&track.codec_params, &Default::default())?;
45
46        let mut channels = vec![];
47        loop {
48            match stream.next_packet() {
49                Ok(packet) => {
50                    let buffer = decoder.decode(&packet)?;
51                    match buffer {
52                        AudioBufferRef::U8(buf) => copy_buf(&buf, &mut channels),
53                        AudioBufferRef::U16(buf) => copy_buf(&buf, &mut channels),
54                        AudioBufferRef::U24(buf) => copy_buf(&buf, &mut channels),
55                        AudioBufferRef::U32(buf) => copy_buf(&buf, &mut channels),
56                        AudioBufferRef::S8(buf) => copy_buf(&buf, &mut channels),
57                        AudioBufferRef::S16(buf) => copy_buf(&buf, &mut channels),
58                        AudioBufferRef::S24(buf) => copy_buf(&buf, &mut channels),
59                        AudioBufferRef::S32(buf) => copy_buf(&buf, &mut channels),
60                        AudioBufferRef::F32(buf) => copy_buf(&buf, &mut channels),
61                        AudioBufferRef::F64(buf) => copy_buf(&buf, &mut channels),
62                    }
63                }
64                Err(symphonia::core::errors::Error::ResetRequired) => break,
65                Err(symphonia::core::errors::Error::IoError(err)) => {
66                    if err.kind() != io::ErrorKind::UnexpectedEof {
67                        return Err(err.into());
68                    }
69
70                    // make sure we got all of the frames we needed
71                    if let Some(n_frames) = n_frames {
72                        if channels.get(0).map(|c| c.len() as u64).unwrap_or(0) != n_frames {
73                            return Err(err.into());
74                        }
75                    }
76
77                    break;
78                }
79                Err(err) => {
80                    return Err(err);
81                }
82            }
83        }
84
85        Ok(Samples {
86            channels,
87            sample_rate,
88        })
89    }
90}
91
92#[cfg(any(test, feature = "resample"))]
93impl<S> Samples<S>
94where
95    S: rubato::Sample,
96{
97    pub fn resample(&mut self, target: u32) -> Result<(), rubato::ResampleError> {
98        if self.channels.is_empty() {
99            return Ok(());
100        }
101
102        let sample_rate = if let Some(sample_rate) = self.sample_rate {
103            if sample_rate == target {
104                return Ok(());
105            }
106            sample_rate
107        } else {
108            return Ok(());
109        };
110
111        use rubato::{
112            InterpolationParameters, InterpolationType, Resampler, SincFixedIn, WindowFunction,
113        };
114
115        let params = InterpolationParameters {
116            sinc_len: 256,
117            f_cutoff: 0.95,
118            interpolation: InterpolationType::Linear,
119            oversampling_factor: 256,
120            window: WindowFunction::BlackmanHarris2,
121        };
122        let mut resampler = SincFixedIn::<S>::new(
123            target as f64 / sample_rate as f64,
124            2.0,
125            params,
126            self.channels[0].len(),
127            self.channels.len(),
128        )
129        .unwrap();
130
131        self.channels = resampler.process(&self.channels, None)?;
132
133        Ok(())
134    }
135}
136
137pub fn reader(
138    contents: impl io::Read + Send + Sync + 'static,
139    ext: &str,
140) -> symphonia::core::errors::Result<Box<dyn symphonia::core::formats::FormatReader>> {
141    let contents = std::io::BufReader::new(contents);
142    let contents = symphonia::core::io::ReadOnlySource::new(contents);
143
144    let contents =
145        symphonia::core::io::MediaSourceStream::new(Box::new(contents), Default::default());
146
147    let mut hint = Hint::new();
148    if !ext.is_empty() {
149        hint.with_extension(ext);
150    }
151
152    let res = symphonia::default::get_probe().format(
153        &hint,
154        contents,
155        &Default::default(),
156        &Default::default(),
157    )?;
158
159    Ok(res.format)
160}
161
162#[inline]
163fn copy_buf<S: Sample + IntoSample<T>, T>(src: &AudioBuffer<S>, out: &mut Vec<Vec<T>>) {
164    use symphonia::core::audio::Signal;
165
166    let spec = src.spec();
167    let n_channels = spec.channels.count();
168
169    if out.is_empty() {
170        for _ in 0..n_channels {
171            out.push(vec![]);
172        }
173    }
174
175    for (ch, chan) in out.iter_mut().enumerate() {
176        for src in src.chan(ch) {
177            let sample = (*src).into_sample();
178            chan.push(sample);
179        }
180    }
181}