Skip to content

Add support for offsetting the phase of a signal #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions .idea/dasp.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 86 additions & 4 deletions dasp_signal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub trait Signal {
///
/// fn main() {
/// // Infinite signals always return `false`.
/// use dasp_signal::Step;
/// let sine_signal = signal::rate(44_100.0).const_hz(400.0).sine();
/// assert_eq!(sine_signal.is_exhausted(), false);
///
Expand Down Expand Up @@ -960,6 +961,16 @@ pub struct NoiseSimplex<S> {
phase: Phase<S>,
}

// A signal generator with offset phase.
#[derive(Clone)]
pub struct OffsetPhase<S>
where
S: Signal + Step,
{
step: S,
offset: f64,
}

/// An iterator that yields the sum of the frames yielded by both `other` and `self` in lock-step.
#[derive(Clone)]
pub struct AddAmp<A, B> {
Expand Down Expand Up @@ -1444,10 +1455,7 @@ pub fn phase<S>(step: S) -> Phase<S>
where
S: Step,
{
Phase {
step: step,
next: 0.0,
}
Phase { step, next: 0.0 }
}

/// Creates a frame `Rate` (aka sample rate) representing the rate at which a signal may be
Expand Down Expand Up @@ -1850,6 +1858,34 @@ where
pub fn noise_simplex(self) -> NoiseSimplex<Self> {
self.phase().noise_simplex()
}

/// Offsets the phase of a signal by the specified value, between 0.0 and 1.0 by default.
///
/// # Example
///
/// ```rust
/// use dasp_signal::{self as signal, Signal};
///
/// fn main() {
/// let step = signal::rate(4.0).const_hz(1.0).offset_phase(0.25);
/// let mut phase = step.phase();
/// assert_eq!(phase.next(), 0.25);
/// assert_eq!(phase.next(), 0.5);
/// assert_eq!(phase.next(), 0.75);
/// assert_eq!(phase.next(), 0.0);
/// assert_eq!(phase.next(), 0.25);
/// assert_eq!(phase.next(), 0.5);
/// }
/// ```
#[inline]
pub fn offset_phase(self, offset: f64) -> OffsetPhase<Self> {
let rem = 1.0;

OffsetPhase {
step: self,
offset: offset % rem,
}
}
}

impl ConstHz {
Expand Down Expand Up @@ -1882,6 +1918,16 @@ impl ConstHz {
pub fn noise_simplex(self) -> NoiseSimplex<Self> {
self.phase().noise_simplex()
}

#[inline]
pub fn offset_phase(self, offset: f64) -> OffsetPhase<Self> {
let rem = 1.0;

OffsetPhase {
step: self,
offset: offset % rem,
}
}
}

/// Types that may be used to give a phase step size based on some `hz / sample rate`.
Expand Down Expand Up @@ -2097,6 +2143,42 @@ where
}
}

impl<S: Signal + Step> OffsetPhase<S> {
/// Construct a `Phase` iterator that is incremented via the constant step size, `self.step`,
/// and takes an offset into account.
#[inline]
pub fn phase(self) -> Phase<S> {
Phase {
step: self.step,
next: self.offset,
}
}

/// A composable alternative to the `signal::sine` function.
#[inline]
pub fn sine(self) -> Sine<S> {
self.phase().sine()
}

/// A composable alternative to the `signal::saw` function.
#[inline]
pub fn saw(self) -> Saw<S> {
self.phase().saw()
}

/// A composable alternative to the `signal::square` function.
#[inline]
pub fn square(self) -> Square<S> {
self.phase().square()
}

/// A composable alternative to the `signal::noise_simplex` function.
#[inline]
pub fn noise_simplex(self) -> NoiseSimplex<S> {
self.phase().noise_simplex()
}
}

impl<A, B> Signal for AddAmp<A, B>
where
A: Signal,
Expand Down