summaryrefslogtreecommitdiff
path: root/klangfarbrs/src/phasor.rs
diff options
context:
space:
mode:
authorGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-12 23:40:33 -0600
committerGrant Shangreaux <grant@unabridgedsoftware.com>2021-11-12 23:40:33 -0600
commitd3776887db90ac1ea15fd55d833ff6b3042e7caf (patch)
treea23ba500470883cf12635405f86fb2adc0ba1546 /klangfarbrs/src/phasor.rs
parent200e3568f5b7b5aab5388512ddefceb813168f90 (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.rs28
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)
}
}