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/phasor.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'klangfarbrs/src/phasor.rs') diff --git a/klangfarbrs/src/phasor.rs b/klangfarbrs/src/phasor.rs index 00372c0..ace374a 100644 --- a/klangfarbrs/src/phasor.rs +++ b/klangfarbrs/src/phasor.rs @@ -1,26 +1,28 @@ use super::{SamplesPerSecond, Hz}; -type Phase = f32; // Phase will always be between 0.0 and 1.0. +pub type Phase = f32; // Phase will always be between 0.0 and 1.0. -pub struct PhasorIter { +/// Phase stays between 0.0 and 1.0 and represents position on the axis of time +/// for a given wave form. Since audio signals are periodic, we can just calculate +/// the first cycle of a wave repeatedly. This also prevents pitch drift caused by +/// floating point errors over time. +pub struct Phasor { pub phase: Phase, pub frequency: Hz, - sample_rate: SamplesPerSecond, + pub sample_rate: SamplesPerSecond, } -impl PhasorIter { - fn new(frequency: Hz, sample_rate: SamplesPerSecond) -> Self { +impl Phasor { + pub fn new(frequency: Hz, sample_rate: SamplesPerSecond) -> Self { Self { phase: 0.0, frequency, sample_rate } } } -impl Iterator for PhasorIter { +impl Iterator for Phasor { type Item = Phase; fn next(&mut self) -> Option { - self.phase += (self.frequency / self.sample_rate); - - if self.phase > 1.0 { self.phase -= 1.0; } + self.phase = (self.phase + self.frequency / self.sample_rate) % 1.0; Some(self.phase) } @@ -32,15 +34,15 @@ mod tests { #[test] fn it_produces_expected_next_value() { - let mut phasor = PhasorIter::new(10.0, 100.0); + let mut phasor = Phasor::new(10.0, 100.0); assert_eq!(phasor.next(), Some(0.1)) } #[test] fn it_produces_expected_next_values() { - let phasor = PhasorIter::new(10.0, 100.0); - let next = phasor.take(11); - assert_eq!(0.1, next.last().unwrap()) + let phasor = Phasor::new(10.0, 100.0); + let taken_iterator = phasor.take(11); + assert_eq!(taken_iterator.last(), Some(0.1)) // assert_eq!([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.1], next) } } -- cgit v1.2.3