From d3776887db90ac1ea15fd55d833ff6b3042e7caf Mon Sep 17 00:00:00 2001 From: Grant Shangreaux Date: Fri, 12 Nov 2021 23:40:33 -0600 Subject: Add: Osc Iterator refactor Now the MonoSynth has one main `osc` property, and it holds an Osc struct which contains its own instance of a Phasor. The Phasor has been mostly hidden away from the top level, though we still have our Bender for bending phase. I think we can implement methods on Osc in order to manipulate the Phasor of a particular instance of osc if need be. The outer `frames` function has been partially refactored. However, I think we should/could wrap the Osc's `next` function in something like `next_sample` which returns a Sample (vs an Option). we could also do something like `osc.take(frames_count).map { |s| frames.push(s) }` --- klangfarbrs/src/osc.rs | 51 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'klangfarbrs/src/osc.rs') diff --git a/klangfarbrs/src/osc.rs b/klangfarbrs/src/osc.rs index fd78de1..8225eb1 100644 --- a/klangfarbrs/src/osc.rs +++ b/klangfarbrs/src/osc.rs @@ -1,15 +1,50 @@ use std::f32::consts::TAU; use rand::Rng; -use crate::{Waveform, Phase, Sample}; +use super::{Hz, Sample}; +use super::phasor::{Phasor}; -pub struct Osc {} +/// The various waveforms the `MonoSynth` can generate. +pub enum Waveform { + Sine, + Square, + Triangle, + Sawtooth, + WhiteNoise, + BrownNoise, +} + +pub struct Osc { + pub phasor: Phasor, + pub waveform: Waveform, + pub last_value: Sample, +} impl Osc { - pub fn generate_sample(waveform: &Waveform, phase: Phase, last_value: Sample) -> Sample { - let phase = phase; + pub fn new(frequency: Hz, sample_rate: f32) -> Self { + Self { + phasor: Phasor::new(frequency, sample_rate), + waveform: Waveform::Sine, + last_value: 0.1, + } + } + + pub fn get_frequency(&self) -> Hz { + self.phasor.frequency + } + + pub fn set_frequency(&mut self, frequency: Hz) { + self.phasor.frequency = frequency; + } +} + +impl Iterator for Osc { + type Item = Sample; + + fn next(&mut self) -> Option { + let phase = self.phasor.next().unwrap(); let mut rng = rand::thread_rng(); - match waveform { + let sample = match self.waveform { Waveform::Sine => { (TAU * phase).sin() }, @@ -39,9 +74,11 @@ impl Osc { }, Waveform::BrownNoise => { - (last_value + (rng.gen::()) * 0.2 - 0.1).clamp(-1.0, 1.0) + (self.last_value + (rng.gen::()) * 0.2 - 0.1).clamp(-1.0, 1.0) }, - } + }; + + Some(sample) } } -- cgit v1.2.3