old school music tracker audio backend
at dev 165 lines 4.4 kB view raw
1use core::slice; 2use std::{ 3 array, 4 ops::{Div, DivAssign, IndexMut}, 5}; 6 7use dasp::sample::ToSample; 8 9pub(crate) mod instrument; 10pub mod playback; 11pub(crate) mod sample; 12 13pub use sample::Interpolation; 14 15#[repr(transparent)] 16#[derive(Clone, Copy, Default, Debug, PartialEq)] 17pub struct Frame([f32; 2]); 18 19impl std::ops::AddAssign for Frame { 20 fn add_assign(&mut self, rhs: Self) { 21 *self = *self + rhs; 22 } 23} 24 25impl std::ops::Add for Frame { 26 type Output = Self; 27 28 fn add(self, rhs: Self) -> Self::Output { 29 Self([self.0[0] + rhs.0[0], self.0[1] + rhs.0[1]]) 30 } 31} 32 33impl std::ops::Sub for Frame { 34 type Output = Self; 35 36 fn sub(self, rhs: Self) -> Self::Output { 37 Self([self.0[0] - rhs.0[0], self.0[1] - rhs.0[1]]) 38 } 39} 40 41impl std::ops::SubAssign for Frame { 42 fn sub_assign(&mut self, rhs: Self) { 43 *self = *self - rhs; 44 } 45} 46 47impl std::ops::MulAssign<f32> for Frame { 48 fn mul_assign(&mut self, rhs: f32) { 49 *self.0.index_mut(0) *= rhs; 50 *self.0.index_mut(1) *= rhs; 51 } 52} 53 54impl std::ops::Mul<f32> for Frame { 55 type Output = Self; 56 57 fn mul(self, rhs: f32) -> Self::Output { 58 Self([self.0[0] * rhs, self.0[1] * rhs]) 59 } 60} 61 62impl Div<f32> for Frame { 63 type Output = Frame; 64 65 fn div(self, rhs: f32) -> Self::Output { 66 Self([self.0[0] / rhs, self.0[1] / rhs]) 67 } 68} 69 70impl DivAssign<f32> for Frame { 71 fn div_assign(&mut self, rhs: f32) { 72 *self.0.index_mut(0) *= rhs; 73 *self.0.index_mut(1) *= rhs; 74 } 75} 76 77impl crate::sample::ProcessingFrame for Frame { 78 fn mul_add(self, mul: f32, add: Self) -> Self { 79 Self([ 80 f32::mul_add(self.0[0], mul, add.0[0]), 81 f32::mul_add(self.0[1], mul, add.0[1]), 82 ]) 83 } 84} 85 86impl std::iter::Sum for Frame { 87 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { 88 iter.reduce(|acc, x| acc + x).unwrap_or_default() 89 } 90} 91 92impl From<[f32; 2]> for Frame { 93 fn from(value: [f32; 2]) -> Self { 94 Self(value) 95 } 96} 97 98impl From<f32> for Frame { 99 fn from(value: f32) -> Self { 100 Self([value, value]) 101 } 102} 103 104impl Frame { 105 // split into left and right. 106 pub fn split_array<const N: usize>(value: [Frame; N]) -> ([f32; N], [f32; N]) { 107 ( 108 array::from_fn(|i| value[i].0[0]), 109 array::from_fn(|i| value[i].0[1]), 110 ) 111 } 112 113 pub fn sum_to_mono(self) -> f32 { 114 self.0[0] + self.0[1] 115 } 116 117 pub fn from_mut<'a>(value: &'a mut [f32; 2]) -> &'a mut Self { 118 // SAFETY: lifetime is specified, both mut, Self is repr(transparent). 119 unsafe { std::mem::transmute::<&'a mut [f32; 2], &'a mut Self>(value) } 120 } 121 122 pub fn from_interleaved(value: &[f32]) -> &[Frame] { 123 debug_assert!(value.len().rem_euclid(2) == 0); 124 let len = value.len() / 2; 125 let ptr = value.as_ptr().cast(); 126 // SAFETY: keeps the same lifetime and mutability. 127 // [f32; 2] is a valid frame 128 unsafe { slice::from_raw_parts(ptr, len) } 129 } 130 131 pub fn from_ref<'a>(value: &'a [f32; 2]) -> &'a Self { 132 // SAFETY: lifetime is specified, both not mut, Self is repr(transparent). 133 unsafe { std::mem::transmute::<&'a [f32; 2], &'a Self>(value) } 134 } 135 136 pub fn to_sample<S: dasp::sample::FromSample<f32>>(self) -> [S; 2] { 137 [self.0[0].to_sample_(), self.0[1].to_sample_()] 138 } 139 140 pub fn to_raw<'a>(into: &mut [Self]) -> &'a mut [[f32; 2]] { 141 unsafe { std::mem::transmute(into) } 142 } 143 144 // pan laws taken from: https://www.cs.cmu.edu/~music/icm-online/readings/panlaws/index.html 145 146 // /// angle in radians between 0 and 90° 147 // pub fn pan_linear(&mut self, angle: f32) { 148 // self.0[0] *= (std::f32::consts::FRAC_PI_2 - angle) * std::f32::consts::FRAC_2_PI; 149 // self.0[1] *= angle * std::f32::consts::FRAC_2_PI; 150 // } 151 152 /// angle in radians between 0 and 90° 153 pub fn pan_constant_power(&mut self, angle: f32) { 154 self.0[0] *= angle.cos(); 155 self.0[1] *= angle.sin(); 156 } 157 158 // /// angle in radians between 0 and 90° 159 // pub fn pan_compromise(&mut self, angle: f32) { 160 // self.0[0] *= f32::sqrt( 161 // (std::f32::consts::FRAC_PI_2 - angle) * std::f32::consts::FRAC_2_PI * angle.cos(), 162 // ); 163 // self.0[1] *= f32::sqrt(angle * std::f32::consts::FRAC_2_PI * angle.sin()); 164 // } 165}