diff options
author | Grant Shangreaux <grant@unabridgedsoftware.com> | 2021-11-12 23:40:33 -0600 |
---|---|---|
committer | Grant Shangreaux <grant@unabridgedsoftware.com> | 2021-11-12 23:40:33 -0600 |
commit | d3776887db90ac1ea15fd55d833ff6b3042e7caf (patch) | |
tree | a23ba500470883cf12635405f86fb2adc0ba1546 /klangfarbrs/src/phasor.rs | |
parent | 200e3568f5b7b5aab5388512ddefceb813168f90 (diff) |
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) }`
Diffstat (limited to 'klangfarbrs/src/phasor.rs')
-rw-r--r-- | klangfarbrs/src/phasor.rs | 28 |
1 files changed, 15 insertions, 13 deletions
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::Item> { - 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) } } |