1#![allow(dead_code)]
2
3use std::{any::TypeId, borrow::Cow, slice};
4
5use resampler::Resampler;
6use sampletypes::SampleType;
7use downmixer::{Downmixer, DownmixerParams};
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum AudioConvError {
11 InvalidArguments(String),
13
14 FrameChannelsNotSame,
16
17 ChannelsNotInSameSize,
19
20 TruncatedSamples,
22}
23
24pub fn stereos_to_dual_monos<S>(stereos: &[(S, S)]) -> (Vec<S>, Vec<S>)
26where
27 S: SampleType,
28{
29 let l = stereos.iter().map(|(l, _r): &(S, S)| -> S { *l }).collect();
30 let r = stereos.iter().map(|(_l, r): &(S, S)| -> S { *r }).collect();
31 (l, r)
32}
33
34pub fn is_same_len<S>(data: &[Vec<S>]) -> Option<(bool, usize)>
36where
37 S: SampleType,
38{
39 if data.is_empty() {
40 None
41 } else {
42 let lengths: Vec<usize> = data.iter().map(|item| item.len()).collect();
43 let first = lengths[0];
44 Some((lengths.iter().all(|&item| item == first), first))
45 }
46}
47
48pub fn frames_to_stereos<S>(channel_mask: u32, frames: &[Vec<S>]) -> Result<Vec<(S, S)>, AudioConvError>
50where
51 S: SampleType,
52{
53 match is_same_len(frames) {
54 None => Ok(Vec::<(S, S)>::new()),
55 Some((equal, _channels)) => match equal {
56 false => Err(AudioConvError::FrameChannelsNotSame),
57 true => {
58 let downmixer = Downmixer::new(channel_mask, DownmixerParams::default());
59 Ok(frames.iter().map(|frame: &Vec<S>| -> (S, S) {downmixer.downmix_frame_to_stereo(frame)}).collect())
60 }
61 },
62 }
63}
64
65pub fn frames_to_dual_mono<S>(channel_mask: u32, frames: &[Vec<S>]) -> Result<(Vec<S>, Vec<S>), AudioConvError>
67where
68 S: SampleType,
69{
70 Ok(stereos_to_dual_monos(&frames_to_stereos(channel_mask, frames)?))
71}
72
73pub fn frames_to_monos<S>(
76 frames: &[Vec<S>],
77) -> Result<Vec<Vec<S>>, AudioConvError>
78where
79 S: SampleType,
80{
81 match is_same_len(frames) {
82 None => Ok(Vec::<Vec<S>>::new()),
83 Some((equal, length)) => match equal {
84 false => Err(AudioConvError::FrameChannelsNotSame),
85 true => Ok((0..length)
86 .map(|channel| -> Vec<S> {
87 frames
88 .iter()
89 .map(|frame: &Vec<S>| -> S { frame[channel] })
90 .collect()
91 })
92 .collect()),
93 },
94 }
95}
96
97pub fn monos_to_frames<S>(monos: &[Vec<S>]) -> Result<Vec<Vec<S>>, AudioConvError>
99where
100 S: SampleType,
101{
102 match is_same_len(monos) {
103 None => Ok(Vec::<Vec<S>>::new()),
104 Some((equal, length)) => match equal {
105 false => Err(AudioConvError::ChannelsNotInSameSize),
106 true => Ok((0..length)
107 .map(|position: usize| -> Vec<S> {
108 monos
109 .iter()
110 .map(|channel: &Vec<S>| -> S { channel[position] })
111 .collect()
112 })
113 .collect()),
114 },
115 }
116}
117
118pub fn monos_to_interleaved_samples<S>(monos: &[Vec<S>]) -> Result<Vec<S>, AudioConvError>
120where
121 S: SampleType,
122{
123 Ok(monos_to_frames(monos)?.into_iter().flatten().collect())
124}
125
126pub fn frames_to_interleaved_samples<S>(
128 frames: &[Vec<S>]
129) -> Result<Vec<S>, AudioConvError>
130where
131 S: SampleType,
132{
133 monos_to_interleaved_samples(&frames_to_monos(frames)?)
134}
135
136pub fn interleaved_samples_to_frames<S>(
138 samples: &[S],
139 channels: u16,
140) -> Result<Vec<Vec<S>>, AudioConvError>
141where
142 S: SampleType,
143{
144 monos_to_frames(&interleaved_samples_to_monos(samples, channels)?)
145}
146
147pub fn stereos_to_interleaved_samples<S>(stereos: &[(S, S)]) -> Vec<S>
149where
150 S: SampleType,
151{
152 stereos
153 .iter()
154 .flat_map(|(l, r): &(S, S)| -> [S; 2] { [*l, *r] })
155 .collect()
156}
157
158pub fn interleaved_samples_to_monos<S>(
160 samples: &[S],
161 channels: u16,
162) -> Result<Vec<Vec<S>>, AudioConvError>
163where
164 S: SampleType,
165{
166 if channels == 0 {
167 Err(AudioConvError::InvalidArguments(
168 "Channels must not be zero".to_owned(),
169 ))
170 } else {
171 Ok((0..channels)
172 .map(|channel| -> Vec<S> {
173 samples
174 .iter()
175 .skip(channel as usize)
176 .step_by(channels as usize)
177 .copied()
178 .collect()
179 })
180 .collect())
181 }
182}
183
184pub fn dual_monos_to_stereos<S>(
186 dual_monos: &(Vec<S>, Vec<S>),
187) -> Result<Vec<(S, S)>, AudioConvError>
188where
189 S: SampleType,
190{
191 let (l, r) = dual_monos;
192 if l.len() != r.len() {
193 Err(AudioConvError::ChannelsNotInSameSize)
194 } else {
195 Ok(l.iter()
196 .zip(r)
197 .map(|(l, r): (&S, &S)| -> (S, S) { (*l, *r) })
198 .collect())
199 }
200}
201
202pub fn interleaved_samples_to_stereos<S>(samples: &[S]) -> Result<Vec<(S, S)>, AudioConvError>
204where
205 S: SampleType,
206{
207 if (samples.len() & 1) != 0 {
208 Err(AudioConvError::TruncatedSamples)
209 } else {
210 Ok((0..(samples.len() / 2))
211 .map(|position| -> (S, S) { (samples[position * 2], samples[position * 2 + 1]) })
212 .collect())
213 }
214}
215
216pub fn dual_monos_to_monos<S>(dual_monos: &(Vec<S>, Vec<S>)) -> Result<Vec<S>, AudioConvError>
218where
219 S: SampleType,
220{
221 let (l, r) = dual_monos;
222 if l.len() != r.len() {
223 Err(AudioConvError::ChannelsNotInSameSize)
224 } else {
225 Ok(l.iter()
226 .zip(r)
227 .map(|(l, r): (&S, &S)| -> S { S::average(*l, *r) })
228 .collect())
229 }
230}
231
232pub fn monos_to_dual_monos<S>(monos: &[S]) -> (Vec<S>, Vec<S>)
234where
235 S: SampleType,
236{
237 (monos.to_vec(), monos.to_vec())
238}
239
240pub fn stereos_to_mono_channel<S>(stereos: &[(S, S)]) -> Vec<S>
242where
243 S: SampleType,
244{
245 stereos
246 .iter()
247 .map(|(l, r): &(S, S)| -> S { S::average(*l, *r) })
248 .collect()
249}
250
251pub fn monos_to_stereos<S>(monos: &[S]) -> Vec<(S, S)>
253where
254 S: SampleType,
255{
256 monos.iter().map(|s| (*s, *s)).collect()
257}
258
259#[inline(always)]
261pub fn stereo_conv<S, D>(frame: (S, S)) -> (D, D)
262where
263 S: SampleType,
264 D: SampleType,
265{
266 let (l, r) = frame;
267 (D::scale_from(l), D::scale_from(r))
268}
269
270pub fn sample_conv<S, D>(frame: &[S]) -> Cow<'_, [D]>
274where
275 S: SampleType,
276 D: SampleType,
277{
278 if TypeId::of::<S>() == TypeId::of::<D>() {
279 Cow::Borrowed(unsafe { slice::from_raw_parts(frame.as_ptr() as *const D, frame.len()) })
280 } else {
281 Cow::Owned(
282 frame
283 .iter()
284 .map(|sample: &S| -> D { D::scale_from(*sample) })
285 .collect(),
286 )
287 }
288}
289
290pub fn stereos_conv<S, D>(stereos: &[(S, S)]) -> Cow<'_, [(D, D)]>
292where
293 S: SampleType,
294 D: SampleType,
295{
296 if TypeId::of::<S>() == TypeId::of::<D>() {
297 Cow::Borrowed(unsafe {
298 slice::from_raw_parts(stereos.as_ptr() as *const (D, D), stereos.len())
299 })
300 } else {
301 Cow::Owned(
302 stereos
303 .iter()
304 .map(|stereo: &(S, S)| -> (D, D) { stereo_conv(*stereo) })
305 .collect(),
306 )
307 }
308}
309
310pub fn sample_conv_batch<S, D>(frames: &[Vec<S>]) -> Cow<'_, [Vec<D>]>
312where
313 S: SampleType,
314 D: SampleType,
315{
316 if TypeId::of::<S>() == TypeId::of::<D>() {
317 Cow::Borrowed(unsafe {
318 slice::from_raw_parts(frames.as_ptr() as *const Vec<D>, frames.len())
319 })
320 } else {
321 Cow::Owned(
322 frames
323 .iter()
324 .map(|frames: &Vec<S>| -> Vec<D> { sample_conv(frames).to_vec() })
325 .collect(),
326 )
327 }
328}
329
330pub fn do_resample_mono<S>(
332 resampler: &Resampler,
333 input: &[S],
334 src_sample_rate: u32,
335 dst_sample_rate: u32,
336) -> Vec<S>
337where
338 S: SampleType,
339{
340 let input = sample_conv::<S, f32>(input);
341 let result = resampler
342 .resample(&input, src_sample_rate, dst_sample_rate)
343 .unwrap();
344 sample_conv::<f32, S>(&result).to_vec()
345}
346
347pub fn do_resample_stereo<S>(
349 resampler: &Resampler,
350 input: &[(S, S)],
351 src_sample_rate: u32,
352 dst_sample_rate: u32,
353) -> Vec<(S, S)>
354where
355 S: SampleType,
356{
357 let block = stereos_to_dual_monos(input);
358 let l = do_resample_mono(resampler, &block.0, src_sample_rate, dst_sample_rate);
359 let r = do_resample_mono(resampler, &block.1, src_sample_rate, dst_sample_rate);
360 dual_monos_to_stereos(&(l, r)).unwrap()
361}
362
363pub fn do_resample_frames<S>(
365 resampler: &Resampler,
366 input: &[Vec<S>],
367 src_sample_rate: u32,
368 dst_sample_rate: u32,
369) -> Vec<Vec<S>>
370where
371 S: SampleType,
372{
373 let monos = frames_to_monos(input).unwrap();
374 let monos: Vec<Vec<S>> = monos
375 .into_iter()
376 .map(|mono| do_resample_mono(resampler, &mono, src_sample_rate, dst_sample_rate))
377 .collect();
378 monos_to_frames(&monos).unwrap()
379}