use std::rc::Rc;
use std::sync::Arc;
use rand::Rng;
use rand::SeedableRng;
pub trait Signal: std::fmt::Debug {
fn fill_buffer(&self, sample_offset: usize, dest: &mut [f32]);
fn to_vec_quantized(&self, bits_per_sample: usize, block_size: usize) -> Vec<i32> {
assert!(bits_per_sample <= 24);
assert!(bits_per_sample > 4);
let scalefactor = 1usize << (bits_per_sample - 1);
let min_target = -((1usize << (bits_per_sample - 1)) as i32);
let max_target = (1usize << (bits_per_sample - 1)) as i32 - 1i32;
let mut ret = vec![0i32; block_size];
let mut buffer = vec![0.0f32; block_size];
self.fill_buffer(0, &mut buffer);
for (p, x) in ret.iter_mut().zip(buffer.iter()) {
*p = (scalefactor as f32 * x)
.round()
.clamp(min_target as f32, max_target as f32) as i32;
}
ret
}
fn clip(self) -> Clip<Self>
where
Self: Sized,
{
Clip::new(self)
}
fn noise(self, amplitude: f32) -> Mix<Self, Noise>
where
Self: Sized,
{
self.mix(Noise::new(amplitude))
}
fn noise_with_seed(self, seed0: u64, amplitude: f32) -> Mix<Self, Noise>
where
Self: Sized,
{
self.mix(Noise::with_seed(seed0, amplitude))
}
fn mix<T: Signal + Sized>(self, other: T) -> Mix<Self, T>
where
Self: Sized,
{
Mix::new(1.0, self, 1.0, other)
}
fn concat<T: Signal + Sized>(self, offset_time: usize, other: T) -> Switch<Self, T>
where
Self: Sized,
{
Switch::new(self, offset_time, other)
}
}
macro_rules! impl_signal_for_pointers {
($pointertype:ident) => {
impl<T: Signal + ?Sized> Signal for $pointertype<T> {
fn fill_buffer(&self, sample_offset: usize, dest: &mut [f32]) {
<$pointertype<T> as AsRef<T>>::as_ref(self).fill_buffer(sample_offset, dest);
}
}
};
}
impl_signal_for_pointers!(Box);
impl_signal_for_pointers!(Rc);
impl_signal_for_pointers!(Arc);
#[derive(Clone, Debug)]
pub struct Dc {
offset: f32,
}
impl Dc {
pub fn new(offset: f32) -> Self {
Self { offset }
}
}
impl Signal for Dc {
fn fill_buffer(&self, _offset: usize, dest: &mut [f32]) {
for p in dest {
*p = self.offset;
}
}
}
#[derive(Clone, Debug)]
pub struct Sine {
period: usize,
amplitude: f32,
initial_phase: f32,
}
impl Sine {
pub fn new(period: usize, amplitude: f32) -> Self {
let initial_phase = 0.0;
Self {
period,
amplitude,
initial_phase,
}
}
pub fn with_initial_phase(period: usize, amplitude: f32, initial_phase: f32) -> Self {
Self {
period,
amplitude,
initial_phase,
}
}
}
impl Signal for Sine {
fn fill_buffer(&self, offset: usize, dest: &mut [f32]) {
let period = self.period as f32;
for (t, p) in dest.iter_mut().enumerate() {
let t = (t + offset) as f32;
*p = self.amplitude
* f32::sin(self.initial_phase + 2.0 * std::f32::consts::PI * t / period);
}
}
}
#[derive(Clone, Debug)]
pub struct Noise {
seed0: u64,
amplitude: f32,
}
impl Noise {
pub fn new(amplitude: f32) -> Self {
let seed0: u64 = rand::thread_rng().gen();
Self { seed0, amplitude }
}
pub fn with_seed(seed0: u64, amplitude: f32) -> Self {
Self { seed0, amplitude }
}
}
impl Signal for Noise {
fn fill_buffer(&self, offset: usize, dest: &mut [f32]) {
let mut rng = rand::rngs::StdRng::seed_from_u64(self.seed0.wrapping_add(offset as u64));
for p in dest {
*p = self.amplitude * 2.0 * (rng.sample::<f32, _>(rand::distributions::Open01) - 0.5);
}
}
}
#[derive(Clone, Debug)]
pub struct Mix<T1: Signal + Sized, T2: Signal + Sized> {
weight1: f32,
weight2: f32,
signal1: T1,
signal2: T2,
}
impl<T1: Signal + Sized, T2: Signal + Sized> Mix<T1, T2> {
pub fn new(weight1: f32, signal1: T1, weight2: f32, signal2: T2) -> Self {
Self {
weight1,
weight2,
signal1,
signal2,
}
}
}
impl<T1: Signal + Sized, T2: Signal + Sized> Signal for Mix<T1, T2> {
fn fill_buffer(&self, offset: usize, dest: &mut [f32]) {
for p in &mut *dest {
*p = 0.0f32;
}
let mut buf = vec![0.0f32; dest.len()];
self.signal1.fill_buffer(offset, &mut buf);
for (p, x) in dest.iter_mut().zip(buf.iter()) {
*p += self.weight1 * *x;
}
self.signal2.fill_buffer(offset, &mut buf);
for (p, x) in dest.iter_mut().zip(buf.iter()) {
*p += self.weight2 * *x;
}
}
}
#[derive(Clone, Debug)]
pub struct Clip<T: Signal + Sized> {
inner: T,
min: f32,
max: f32,
}
impl<T: Signal + Sized> Clip<T> {
pub fn new(inner: T) -> Self {
Self {
inner,
min: -1.0,
max: 1.0,
}
}
}
impl<T: Signal + Sized> Signal for Clip<T> {
fn fill_buffer(&self, offset: usize, dest: &mut [f32]) {
self.inner.fill_buffer(offset, dest);
for p in dest {
*p = p.clamp(self.min, self.max);
}
}
}
#[derive(Clone, Debug)]
pub struct Switch<T1: Signal + Sized, T2: Signal + Sized> {
input1: T1,
offset: usize,
input2: T2,
}
impl<T1: Signal + Sized, T2: Signal + Sized> Switch<T1, T2> {
pub fn new(input1: T1, offset: usize, input2: T2) -> Self {
Self {
input1,
offset,
input2,
}
}
}
impl<T1: Signal + Sized, T2: Signal + Sized> Signal for Switch<T1, T2> {
fn fill_buffer(&self, offset: usize, dest: &mut [f32]) {
self.input1.fill_buffer(offset, dest);
self.input2
.fill_buffer(offset + self.offset, &mut dest[self.offset..]);
}
}