torque_tracker_engine/
sample.rs1use std::{
2 fmt::Debug,
3 iter::repeat_n,
4 num::NonZero,
5 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
6 sync::Arc,
7};
8
9use crate::{
10 audio_processing::Frame, file::impulse_format::sample::VibratoWave, project::note_event::Note,
11};
12
13pub(crate) trait ProcessingFrame:
14 Add<Self, Output = Self>
15 + AddAssign<Self>
16 + Sub<Self, Output = Self>
17 + SubAssign<Self>
18 + Mul<f32, Output = Self>
19 + MulAssign<f32>
20 + Copy
21{
22}
23
24impl ProcessingFrame for Frame {}
25
26impl ProcessingFrame for f32 {}
27
28pub(crate) trait ProcessingFunction<const N: usize, Fr: ProcessingFrame> {
29 fn process(self, data: &[Fr; N]) -> Fr;
30}
31
32#[derive(Clone)]
33pub struct Sample {
34 mono: bool,
35 data: Arc<[f32]>,
36}
37
38impl Sample {
39 pub const MAX_LENGTH: usize = 16_000_000;
40 pub const MAX_RATE: usize = 192_000;
41 pub const PAD_SIZE_EACH: usize = 4;
43
44 pub fn is_mono(&self) -> bool {
45 self.mono
46 }
47
48 pub fn len_with_pad(&self) -> usize {
50 if self.mono {
51 self.data.len()
52 } else {
53 self.data.len() / 2
54 }
55 }
56
57 pub(crate) fn compute<
58 const N: usize,
59 Proc: ProcessingFunction<N, f32> + ProcessingFunction<N, Frame>,
63 >(
64 &self,
65 index: usize,
66 proc: Proc,
67 ) -> Frame {
68 if self.is_mono() {
69 let data: &[f32; N] = self.data[index..index + N].try_into().unwrap();
70 Frame::from(proc.process(data))
71 } else {
72 let data: &[Frame; N] = Frame::from_interleaved(&self.data[index * 2..(index + N) * 2])
73 .try_into()
74 .unwrap();
75 proc.process(data)
76 }
77 }
78
79 pub fn index(&self, idx: usize) -> Frame {
80 if self.is_mono() {
81 Frame::from(self.data[idx])
82 } else {
83 Frame::from([self.data[idx * 2], self.data[idx * 2 + 1]])
84 }
85 }
86
87 pub(crate) fn strongcount(&self) -> usize {
88 Arc::strong_count(&self.data)
89 }
90
91 pub fn new_stereo_interpolated<I: IntoIterator<Item = f32>>(data: I) -> Self {
92 Self::new_stereo_interpolated_padded(
93 repeat_n(0f32, 2 * Self::PAD_SIZE_EACH)
94 .chain(data)
95 .chain(repeat_n(0f32, 2 * Self::PAD_SIZE_EACH)),
96 )
97 }
98
99 pub fn new_stereo_interpolated_padded<I: IntoIterator<Item = f32>>(data: I) -> Self {
100 Self {
101 mono: false,
102 data: Arc::from_iter(data),
103 }
104 }
105
106 pub fn new_mono<I: IntoIterator<Item = f32>>(data: I) -> Self {
107 Self::new_mono_padded(
108 repeat_n(0f32, Self::PAD_SIZE_EACH)
109 .chain(data)
110 .chain(repeat_n(0f32, Self::PAD_SIZE_EACH)),
111 )
112 }
113
114 pub fn new_mono_padded<I: IntoIterator<Item = f32>>(data: I) -> Self {
115 Self {
116 mono: true,
117 data: Arc::from_iter(data),
118 }
119 }
120}
121
122impl Debug for Sample {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 f.debug_struct("Sample")
125 .field("mono", &self.mono)
126 .field("data_len", &self.len_with_pad())
127 .finish_non_exhaustive()
128 }
129}
130
131#[derive(Clone, Copy, Debug)]
132pub struct SampleMetaData {
133 pub default_volume: u8,
134 pub global_volume: u8,
135 pub default_pan: Option<u8>,
136 pub vibrato_speed: u8,
137 pub vibrato_depth: u8,
138 pub vibrato_rate: u8,
139 pub vibrato_waveform: VibratoWave,
140 pub sample_rate: NonZero<u32>,
141 pub base_note: Note,
142}