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 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}