More synth work, but think I'm going to startover

This commit is contained in:
Jamie Hardt 2024-08-08 16:39:35 -07:00
parent fc22b37f1b
commit 128fa74554
2 changed files with 57 additions and 34 deletions

View file

@ -30,7 +30,7 @@ pub use self::skippable::Skippable;
pub use self::spatial::Spatial;
pub use self::speed::Speed;
pub use self::stoppable::Stoppable;
pub use self::synth_waveforms::SynthWaveform;
pub use self::synth_waveforms::{BufferedSynthWaveform, SynthWaveformFunction};
pub use self::take::TakeDuration;
pub use self::uniform::UniformSourceIterator;
pub use self::zero::Zero;

View file

@ -4,6 +4,16 @@ use std::time::Duration;
use super::SeekError;
use crate::{buffer::SamplesBuffer, source::Repeat, Source};
/// Express a frequency as a rational number.
/// .0 Cycles per time quanta
/// .1 Time quanta per second
///
/// Examples:
/// 1000,1 1000 Hz
/// 12345,100 123.45 Hz
pub struct RationalFrequency(u32, u32);
/// Syntheizer waveform functions. All of the synth waveforms are in the
/// codomain [-1.0, 1.0].
#[derive(Clone, Debug)]
@ -15,60 +25,67 @@ pub enum SynthWaveformFunction {
}
impl SynthWaveformFunction {
/// Create a `SamplesBuffer` containing one period of `self` with the given
/// sample rate and frequency.
pub fn create_buffer(&self, sample_rate: u32, frequency: u32) -> SamplesBuffer<f32> {
let p: usize = (sample_rate / frequency) as usize;
let mut samples_vec = vec![0.0f32; p];
/// Create a single sample for the given waveform
#[inline]
pub fn render(&self, sample: u32, period: u32) -> f32 {
let i_div_p: f32 = sample as f32 / period as f32;
fn _pwm_impl(duty: f32, t: f32) -> f32 {
if t < duty.abs() {
1f32
} else {
-1f32
}
}
for i in 0..p {
let i_div_p: f32 = i as f32 / p as f32;
samples_vec[i] = match self {
match self {
Self::Sine => (TAU * i_div_p).sin(),
Self::Triangle => 4.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
Self::Triangle => 04.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()).abs() - 1f32,
Self::Square => {
if i_div_p < 0.5f32 {
1.0f32
} else {
-1.0f32
}
}
},
Self::Sawtooth => 2.0f32 * (i_div_p - (i_div_p + 0.5f32).floor()),
}
}
SamplesBuffer::new(1, sample_rate, samples_vec)
/// Create a `SamplesBuffer` containing one period of `self` with the given
/// sample rate and frequency.
pub fn create_buffer(
&self,
sample_rate: cpal::SampleRate,
frequency: u32,
) -> SamplesBuffer<f32> {
let period: usize = (sample_rate.0 / frequency) as usize;
let mut samples_vec = vec![0.0f32; period];
for i in 0..period {
samples_vec[i] = self.render(i as u32, period as u32);
}
SamplesBuffer::new(1, sample_rate.0, samples_vec)
}
}
/// An infinite source that produces one of a selection of synthesizer
/// waveforms from a buffered source.
#[derive(Clone)]
pub struct SynthWaveform {
pub struct BufferedSynthWaveform {
input: Repeat<SamplesBuffer<f32>>,
}
impl SynthWaveform {
impl BufferedSynthWaveform {
/// Create a new `SynthWaveform` object that generates an endless waveform
/// `f`.
#[inline]
pub fn new(sample_rate: u32, frequency: u32, f: SynthWaveformFunction) -> SynthWaveform {
pub fn new(
sample_rate: cpal::SampleRate,
frequency: u32,
f: SynthWaveformFunction,
) -> BufferedSynthWaveform {
let buffer = f.create_buffer(sample_rate, frequency);
SynthWaveform {
BufferedSynthWaveform {
input: buffer.repeat_infinite(),
}
}
}
impl Iterator for SynthWaveform {
impl Iterator for BufferedSynthWaveform {
type Item = f32;
#[inline]
@ -77,7 +94,7 @@ impl Iterator for SynthWaveform {
}
}
impl Source for SynthWaveform {
impl Source for BufferedSynthWaveform {
#[inline]
fn current_frame_len(&self) -> Option<usize> {
self.input.current_frame_len()
@ -110,7 +127,8 @@ mod tests {
#[test]
fn square() {
let mut wf = SynthWaveform::new(1000, 250, SynthWaveformFunction::Square);
let mut wf =
BufferedSynthWaveform::new(cpal::SampleRate(1000), 250, SynthWaveformFunction::Square);
assert_eq!(wf.next(), Some(1.0f32));
assert_eq!(wf.next(), Some(1.0f32));
assert_eq!(wf.next(), Some(-1.0f32));
@ -123,7 +141,11 @@ mod tests {
#[test]
fn triangle() {
let mut wf = SynthWaveform::new(8000, 1000, SynthWaveformFunction::Triangle);
let mut wf = BufferedSynthWaveform::new(
cpal::SampleRate(8000),
1000,
SynthWaveformFunction::Triangle,
);
assert_eq!(wf.next(), Some(-1.0f32));
assert_eq!(wf.next(), Some(-0.5f32));
assert_eq!(wf.next(), Some(0.0f32));
@ -144,7 +166,8 @@ mod tests {
#[test]
fn saw() {
let mut wf = SynthWaveform::new(200, 50, SynthWaveformFunction::Sawtooth);
let mut wf =
BufferedSynthWaveform::new(cpal::SampleRate(200), 50, SynthWaveformFunction::Sawtooth);
assert_eq!(wf.next(), Some(0.0f32));
assert_eq!(wf.next(), Some(0.5f32));
assert_eq!(wf.next(), Some(-1.0f32));