pub trait Signal {
type Frame: Frame;
Show 22 methods
// Required method
fn next(&mut self) -> Self::Frame;
// Provided methods
fn is_exhausted(&self) -> bool { ... }
fn map<M, F>(self, map: M) -> Map<Self, M, F>
where Self: Sized,
M: FnMut(Self::Frame) -> F,
F: Frame { ... }
fn zip_map<O, M, F>(self, other: O, map: M) -> ZipMap<Self, O, M, F>
where Self: Sized,
M: FnMut(Self::Frame, O::Frame) -> F,
O: Signal,
F: Frame { ... }
fn add_amp<S>(self, other: S) -> AddAmp<Self, S>
where Self: Sized,
S: Signal,
S::Frame: Frame<Sample = <<Self::Frame as Frame>::Sample as Sample>::Signed, NumChannels = <Self::Frame as Frame>::NumChannels> { ... }
fn mul_amp<S>(self, other: S) -> MulAmp<Self, S>
where Self: Sized,
S: Signal,
S::Frame: Frame<Sample = <<Self::Frame as Frame>::Sample as Sample>::Float, NumChannels = <Self::Frame as Frame>::NumChannels> { ... }
fn offset_amp(
self,
offset: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> OffsetAmp<Self>
where Self: Sized { ... }
fn scale_amp(
self,
amp: <<Self::Frame as Frame>::Sample as Sample>::Float,
) -> ScaleAmp<Self>
where Self: Sized { ... }
fn offset_amp_per_channel<F>(
self,
amp_frame: F,
) -> OffsetAmpPerChannel<Self, F>
where Self: Sized,
F: Frame<Sample = <<Self::Frame as Frame>::Sample as Sample>::Signed, NumChannels = <Self::Frame as Frame>::NumChannels> { ... }
fn scale_amp_per_channel<F>(
self,
amp_frame: F,
) -> ScaleAmpPerChannel<Self, F>
where Self: Sized,
F: Frame<Sample = <<Self::Frame as Frame>::Sample as Sample>::Float, NumChannels = <Self::Frame as Frame>::NumChannels> { ... }
fn mul_hz<M, I>(
self,
interpolator: I,
mul_per_frame: M,
) -> MulHz<Self, M, I>
where Self: Sized,
M: Signal<Frame = f64>,
I: Interpolator { ... }
fn from_hz_to_hz<I>(
self,
interpolator: I,
source_hz: f64,
target_hz: f64,
) -> Converter<Self, I>
where Self: Sized,
I: Interpolator { ... }
fn scale_hz<I>(self, interpolator: I, multi: f64) -> Converter<Self, I>
where Self: Sized,
I: Interpolator { ... }
fn delay(self, n_frames: usize) -> Delay<Self>
where Self: Sized { ... }
fn into_interleaved_samples(self) -> IntoInterleavedSamples<Self>
where Self: Sized { ... }
fn clip_amp(
self,
thresh: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> ClipAmp<Self>
where Self: Sized { ... }
fn inspect<F>(self, inspect: F) -> Inspect<Self, F>
where Self: Sized,
F: FnMut(&Self::Frame) { ... }
fn fork<S>(self, ring_buffer: Bounded<S>) -> Fork<Self, S>
where Self: Sized,
S: SliceMut<Element = Self::Frame> { ... }
fn take(self, n: usize) -> Take<Self> ⓘ
where Self: Sized { ... }
fn until_exhausted(self) -> UntilExhausted<Self> ⓘ
where Self: Sized { ... }
fn buffered<S>(self, ring_buffer: Bounded<S>) -> Buffered<Self, S>
where Self: Sized,
S: Slice<Element = Self::Frame> + SliceMut { ... }
fn by_ref(&mut self) -> &mut Self
where Self: Sized { ... }
}
Expand description
Types that yield Frame
s of a one-or-more-channel PCM signal.
For example, Signal
allows us to add two signals, modulate a signal’s amplitude by another
signal, scale a signal’s amplitude and much more.
The Signal trait is inspired by the Iterator
trait but is different in the sense that it
will always yield frames and will never return None
. That said, implementors of Signal
may
optionally indicate exhaustian via the is_exhausted
method. This allows for converting
exhaustive signals back to iterators that are well behaved. Calling next on an exhausted
signal should always yield Self::Frame::EQUILIBRIUM
.
Required Associated Types§
Required Methods§
Sourcefn next(&mut self) -> Self::Frame
fn next(&mut self) -> Self::Frame
Yield the next Frame
in the Signal
.
§Example
An example of a mono (single-channel) signal.
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.2, -0.6, 0.4];
let mut signal = signal::from_iter(frames.iter().cloned());
assert_eq!(signal.next(), 0.2);
assert_eq!(signal.next(), -0.6);
assert_eq!(signal.next(), 0.4);
}
An example of a stereo (dual-channel) signal.
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[0.2, 0.2], [-0.6, -0.6], [0.4, 0.4]];
let mut signal = signal::from_iter(frames.iter().cloned());
assert_eq!(signal.next(), [0.2, 0.2]);
assert_eq!(signal.next(), [-0.6, -0.6]);
assert_eq!(signal.next(), [0.4, 0.4]);
}
Provided Methods§
Sourcefn is_exhausted(&self) -> bool
fn is_exhausted(&self) -> bool
Whether or not the signal is exhausted of meaningful frames.
By default, this returns false
and assumes that the Signal
is infinite.
As an example, signal::FromIterator
becomes exhausted once the inner Iterator
has been
exhausted. Sine
on the other hand will always return false
as it will produce
meaningful values infinitely.
It should be rare for users to need to call this method directly, unless they are
implementing their own custom Signal
s. Instead, idiomatic code will tend toward the
Signal::until_exhasted
method which produces an Iterator
that yields Frame
s until
Signal::is_exhausted
returns true
.
Adaptors that source frames from more than one signal (AddAmp
, MulHz
, etc) will return
true
if any of the source signals return true
. In this sense exhaustiveness is
contagious. This can be likened to the way that Iterator::zip
begins returning None
when either A
or B
begins returning None
.
use dasp_signal::{self as signal, Signal};
fn main() {
// Infinite signals always return `false`.
let sine_signal = signal::rate(44_100.0).const_hz(400.0).sine();
assert_eq!(sine_signal.is_exhausted(), false);
// Signals over iterators return `true` when the inner iterator is exhausted.
let frames = [0.2, -0.6, 0.4];
let mut iter_signal = signal::from_iter(frames.iter().cloned());
assert_eq!(iter_signal.is_exhausted(), false);
iter_signal.by_ref().take(3).count();
assert_eq!(iter_signal.is_exhausted(), true);
// Adaptors return `true` when the first signal becomes exhausted.
let a = [1, 2];
let b = [1, 2, 3, 4];
let a_signal = signal::from_iter(a.iter().cloned());
let b_signal = signal::from_iter(b.iter().cloned());
let mut added = a_signal.add_amp(b_signal);
assert_eq!(added.is_exhausted(), false);
added.by_ref().take(2).count();
assert_eq!(added.is_exhausted(), true);
}
Sourcefn map<M, F>(self, map: M) -> Map<Self, M, F>
fn map<M, F>(self, map: M) -> Map<Self, M, F>
A signal that maps one set of frames to another.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = signal::gen(|| 0.5);
let mut mapper = frames.map(|f| [f, 0.25]);
assert_eq!(mapper.next(), [0.5, 0.25]);
assert_eq!(mapper.next(), [0.5, 0.25]);
assert_eq!(mapper.next(), [0.5, 0.25]);
}
This can also be useful for monitoring the peak values of a signal.
use dasp_frame::Frame;
use dasp_peak as peak;
use dasp_signal::{self as signal, Signal};
fn main() {
let sine_wave = signal::rate(4.0).const_hz(1.0).sine();
let mut peak = sine_wave
.map(peak::full_wave)
.map(|f| f.round());
assert_eq!(
peak.take(4).collect::<Vec<_>>(),
vec![0.0, 1.0, 0.0, 1.0]
);
}
Sourcefn zip_map<O, M, F>(self, other: O, map: M) -> ZipMap<Self, O, M, F>
fn zip_map<O, M, F>(self, other: O, map: M) -> ZipMap<Self, O, M, F>
A signal that maps one set of frames to another.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = signal::gen(|| 0.5);
let more_frames = signal::gen(|| 0.25);
let mut mapper = frames.zip_map(more_frames, |f, o| [f, o]);
assert_eq!(mapper.next(), [0.5, 0.25]);
assert_eq!(mapper.next(), [0.5, 0.25]);
assert_eq!(mapper.next(), [0.5, 0.25]);
}
Sourcefn add_amp<S>(self, other: S) -> AddAmp<Self, S>
fn add_amp<S>(self, other: S) -> AddAmp<Self, S>
Provides an iterator that yields the sum of the frames yielded by both other
and self
in lock-step.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let a = [0.2, -0.6, 0.4];
let b = [0.2, 0.1, -0.8];
let a_signal = signal::from_iter(a.iter().cloned());
let b_signal = signal::from_iter(b.iter().cloned());
let added: Vec<_> = a_signal.add_amp(b_signal).take(3).collect();
assert_eq!(added, vec![0.4, -0.5, -0.4]);
}
Sourcefn mul_amp<S>(self, other: S) -> MulAmp<Self, S>
fn mul_amp<S>(self, other: S) -> MulAmp<Self, S>
Provides an iterator that yields the product of the frames yielded by both other
and
self
in lock-step.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let a = [0.25, -0.8, -0.5];
let b = [0.2, 0.5, 0.8];
let a_signal = signal::from_iter(a.iter().cloned());
let b_signal = signal::from_iter(b.iter().cloned());
let added: Vec<_> = a_signal.mul_amp(b_signal).take(3).collect();
assert_eq!(added, vec![0.05, -0.4, -0.4]);
}
Sourcefn offset_amp(
self,
offset: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> OffsetAmp<Self>where
Self: Sized,
fn offset_amp(
self,
offset: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> OffsetAmp<Self>where
Self: Sized,
Provides an iterator that offsets the amplitude of every channel in each frame of the signal by some sample value and yields the resulting frames.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[0.25, 0.4], [-0.2, -0.5]];
let signal = signal::from_iter(frames.iter().cloned());
let offset: Vec<_> = signal.offset_amp(0.5).take(2).collect();
assert_eq!(offset, vec![[0.75, 0.9], [0.3, 0.0]]);
}
Sourcefn scale_amp(
self,
amp: <<Self::Frame as Frame>::Sample as Sample>::Float,
) -> ScaleAmp<Self>where
Self: Sized,
fn scale_amp(
self,
amp: <<Self::Frame as Frame>::Sample as Sample>::Float,
) -> ScaleAmp<Self>where
Self: Sized,
Produces an Iterator
that scales the amplitude of the sample of each channel in every
Frame
yielded by self
by the given amplitude.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.2, -0.5, -0.4, 0.3];
let signal = signal::from_iter(frames.iter().cloned());
let scaled: Vec<_> = signal.scale_amp(2.0).take(4).collect();
assert_eq!(scaled, vec![0.4, -1.0, -0.8, 0.6]);
}
Sourcefn offset_amp_per_channel<F>(self, amp_frame: F) -> OffsetAmpPerChannel<Self, F>
fn offset_amp_per_channel<F>(self, amp_frame: F) -> OffsetAmpPerChannel<Self, F>
Produces a new Signal
that offsets the amplitude of every Frame
in self
by the
respective amplitudes in each channel of the given amp_frame
.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[0.5, 0.3], [-0.25, 0.9]];
let signal = signal::from_iter(frames.iter().cloned());
let offset: Vec<_> = signal.offset_amp_per_channel([0.25, -0.5]).take(2).collect();
assert_eq!(offset, vec![[0.75, -0.2], [0.0, 0.4]]);
}
Sourcefn scale_amp_per_channel<F>(self, amp_frame: F) -> ScaleAmpPerChannel<Self, F>
fn scale_amp_per_channel<F>(self, amp_frame: F) -> ScaleAmpPerChannel<Self, F>
Produces a new Signal
that scales the amplitude of every Frame
in self
by the
respective amplitudes in each channel of the given amp_frame
.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[0.2, -0.5], [-0.4, 0.3]];
let signal = signal::from_iter(frames.iter().cloned());
let scaled: Vec<_> = signal.scale_amp_per_channel([0.5, 2.0]).take(2).collect();
assert_eq!(scaled, vec![[0.1, -1.0], [-0.2, 0.6]]);
}
Sourcefn mul_hz<M, I>(self, interpolator: I, mul_per_frame: M) -> MulHz<Self, M, I>
fn mul_hz<M, I>(self, interpolator: I, mul_per_frame: M) -> MulHz<Self, M, I>
Multiplies the rate at which frames of self
are yielded by the given signal
.
This happens by wrapping self
in a rate::Converter
and calling set_playback_hz_scale
with each value yielded by signal
§Example
use dasp_interpolate::linear::Linear;
use dasp_signal::{self as signal, Signal};
fn main() {
let foo = [0.0, 1.0, 0.0, -1.0];
let mul = [1.0, 1.0, 0.5, 0.5, 0.5, 0.5];
let mut source = signal::from_iter(foo.iter().cloned());
let a = source.next();
let b = source.next();
let interp = Linear::new(a, b);
let hz_signal = signal::from_iter(mul.iter().cloned());
let frames: Vec<_> = source.mul_hz(interp, hz_signal).take(6).collect();
assert_eq!(&frames[..], &[0.0, 1.0, 0.0, -0.5, -1.0, -0.5][..]);
}
Sourcefn from_hz_to_hz<I>(
self,
interpolator: I,
source_hz: f64,
target_hz: f64,
) -> Converter<Self, I>where
Self: Sized,
I: Interpolator,
fn from_hz_to_hz<I>(
self,
interpolator: I,
source_hz: f64,
target_hz: f64,
) -> Converter<Self, I>where
Self: Sized,
I: Interpolator,
Converts the rate at which frames of the Signal
are yielded using interpolation.
§Example
use dasp_interpolate::linear::Linear;
use dasp_signal::{self as signal, Signal};
fn main() {
let foo = [0.0, 1.0, 0.0, -1.0];
let mut source = signal::from_iter(foo.iter().cloned());
let a = source.next();
let b = source.next();
let interp = Linear::new(a, b);
let frames: Vec<_> = source.from_hz_to_hz(interp, 1.0, 2.0).take(8).collect();
assert_eq!(&frames[..], &[0.0, 0.5, 1.0, 0.5, 0.0, -0.5, -1.0, -0.5][..]);
}
Sourcefn scale_hz<I>(self, interpolator: I, multi: f64) -> Converter<Self, I>where
Self: Sized,
I: Interpolator,
fn scale_hz<I>(self, interpolator: I, multi: f64) -> Converter<Self, I>where
Self: Sized,
I: Interpolator,
Multiplies the rate at which frames of the Signal
are yielded by the given value.
§Example
use dasp_interpolate::linear::Linear;
use dasp_signal::{self as signal, Signal};
fn main() {
let foo = [0.0, 1.0, 0.0, -1.0];
let mut source = signal::from_iter(foo.iter().cloned());
let a = source.next();
let b = source.next();
let interp = Linear::new(a, b);
let frames: Vec<_> = source.scale_hz(interp, 0.5).take(8).collect();
assert_eq!(&frames[..], &[0.0, 0.5, 1.0, 0.5, 0.0, -0.5, -1.0, -0.5][..]);
}
Sourcefn delay(self, n_frames: usize) -> Delay<Self>where
Self: Sized,
fn delay(self, n_frames: usize) -> Delay<Self>where
Self: Sized,
Delays the Signal
by the given number of frames.
The delay is performed by yielding Frame::EQUILIBRIUM
n_frames
times before
continuing to yield frames from signal
.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.2, 0.4];
let signal = signal::from_iter(frames.iter().cloned());
let delayed: Vec<_> = signal.delay(2).take(4).collect();
assert_eq!(delayed, vec![0.0, 0.0, 0.2, 0.4]);
}
Sourcefn into_interleaved_samples(self) -> IntoInterleavedSamples<Self>where
Self: Sized,
fn into_interleaved_samples(self) -> IntoInterleavedSamples<Self>where
Self: Sized,
Converts a Signal
into a type that yields the interleaved Sample
s.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[0.1, 0.2], [0.3, 0.4]];
let signal = signal::from_iter(frames.iter().cloned());
let samples = signal.into_interleaved_samples();
let samples: Vec<_> = samples.into_iter().take(4).collect();
assert_eq!(samples, vec![0.1, 0.2, 0.3, 0.4]);
}
Sourcefn clip_amp(
self,
thresh: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> ClipAmp<Self>where
Self: Sized,
fn clip_amp(
self,
thresh: <<Self::Frame as Frame>::Sample as Sample>::Signed,
) -> ClipAmp<Self>where
Self: Sized,
Clips the amplitude of each channel in each Frame
yielded by self
to the given
threshold amplitude.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [[1.2, 0.8], [-0.7, -1.4]];
let signal = signal::from_iter(frames.iter().cloned());
let clipped: Vec<_> = signal.clip_amp(0.9).take(2).collect();
assert_eq!(clipped, vec![[0.9, 0.8], [-0.7, -0.9]]);
}
Sourcefn inspect<F>(self, inspect: F) -> Inspect<Self, F>
fn inspect<F>(self, inspect: F) -> Inspect<Self, F>
Create a new Signal
that calls the enclosing function on each iteration.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let mut f = 0.0;
let mut signal = signal::gen_mut(move || {
f += 0.1;
f
});
let func = |x: &f64| {
assert_eq!(*x, 0.1);
};
let mut inspected = signal.inspect(func);
let out = inspected.next();
assert_eq!(out, 0.1);
}
Sourcefn fork<S>(self, ring_buffer: Bounded<S>) -> Fork<Self, S>
fn fork<S>(self, ring_buffer: Bounded<S>) -> Fork<Self, S>
Forks Self
into two signals that produce the same frames.
The given ring_buffer
must be empty to ensure correct behaviour.
Each time a frame is requested from the signal on one branch, that frame will be pushed to
the given ring_buffer
of pending frames to be collected by the other branch and a flag
will be set to indicate that there are pending frames.
Fork can be used to share the queue between the two branches by reference
fork.by_ref()
or via a reference counted pointer fork.by_rc()
.
Fork is a slightly more efficient alternative to Bus when only two branches are required.
Note: It is up to the user to ensure that there are never more than
ring_buffer.max_len()
pending frames - otherwise the oldest frames will be overridden and
glitching may occur on the lagging branch.
**Panic!**s if the given ring_buffer
is not empty in order to guarantee correct
behaviour.
use dasp_ring_buffer as ring_buffer;
use dasp_signal::{self as signal, Signal};
fn main() {
let signal = signal::rate(44_100.0).const_hz(440.0).sine();
let ring_buffer = ring_buffer::Bounded::from([0f64; 64]);
let mut fork = signal.fork(ring_buffer);
// Forks can be split into their branches via reference.
{
let (mut a, mut b) = fork.by_ref();
assert_eq!(a.next(), b.next());
assert_eq!(a.by_ref().take(64).collect::<Vec<_>>(),
b.by_ref().take(64).collect::<Vec<_>>());
}
// Forks can also be split via reference counted pointer.
let (mut a, mut b) = fork.by_rc();
assert_eq!(a.next(), b.next());
assert_eq!(a.by_ref().take(64).collect::<Vec<_>>(),
b.by_ref().take(64).collect::<Vec<_>>());
// The lagging branch will be missing frames if we exceed `ring_buffer.max_len()`
// pending frames.
assert!(a.by_ref().take(67).collect::<Vec<_>>() !=
b.by_ref().take(67).collect::<Vec<_>>())
}
Sourcefn take(self, n: usize) -> Take<Self> ⓘwhere
Self: Sized,
fn take(self, n: usize) -> Take<Self> ⓘwhere
Self: Sized,
Converts the Signal
into an Iterator
that will yield the given number for Frame
s
before returning None
.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.1, 0.2, 0.3, 0.4];
let mut signal = signal::from_iter(frames.iter().cloned()).take(2);
assert_eq!(signal.next(), Some(0.1));
assert_eq!(signal.next(), Some(0.2));
assert_eq!(signal.next(), None);
}
Sourcefn until_exhausted(self) -> UntilExhausted<Self> ⓘwhere
Self: Sized,
fn until_exhausted(self) -> UntilExhausted<Self> ⓘwhere
Self: Sized,
Converts the Signal
into an Iterator
yielding frames until the signal.is_exhausted()
returns true
.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [1, 2];
let signal = signal::from_iter(frames.iter().cloned());
assert_eq!(signal.until_exhausted().count(), 2);
}
Sourcefn buffered<S>(self, ring_buffer: Bounded<S>) -> Buffered<Self, S>
fn buffered<S>(self, ring_buffer: Bounded<S>) -> Buffered<Self, S>
Buffers the signal using the given ring buffer.
When next
is called on the returned signal, it will first check if the ring buffer is
empty. If so, it will completely fill the ring buffer with the inner signal before yielding
the next value. If the ring buffer still contains un-yielded values, the next frame will be
popped from the front of the ring buffer and immediately returned.
use dasp_ring_buffer as ring_buffer;
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.1, 0.2, 0.3, 0.4];
let signal = signal::from_iter(frames.iter().cloned());
let ring_buffer = ring_buffer::Bounded::from([0f32; 2]);
let mut buffered_signal = signal.buffered(ring_buffer);
assert_eq!(buffered_signal.next(), 0.1);
assert_eq!(buffered_signal.next(), 0.2);
assert_eq!(buffered_signal.next(), 0.3);
assert_eq!(buffered_signal.next(), 0.4);
assert_eq!(buffered_signal.next(), 0.0);
}
If the given ring buffer already contains frames, those will be yielded first.
use dasp_ring_buffer as ring_buffer;
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0.1, 0.2, 0.3, 0.4];
let signal = signal::from_iter(frames.iter().cloned());
let ring_buffer = ring_buffer::Bounded::from_full([0.8, 0.9]);
let mut buffered_signal = signal.buffered(ring_buffer);
assert_eq!(buffered_signal.next(), 0.8);
assert_eq!(buffered_signal.next(), 0.9);
assert_eq!(buffered_signal.next(), 0.1);
assert_eq!(buffered_signal.next(), 0.2);
assert_eq!(buffered_signal.next(), 0.3);
assert_eq!(buffered_signal.next(), 0.4);
assert_eq!(buffered_signal.next(), 0.0);
}
Sourcefn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Borrows a Signal rather than consuming it.
This is useful to allow applying signal adaptors while still retaining ownership of the original signal.
§Example
use dasp_signal::{self as signal, Signal};
fn main() {
let frames = [0, 1, 2, 3, 4];
let mut signal = signal::from_iter(frames.iter().cloned());
assert_eq!(signal.next(), 0);
assert_eq!(signal.by_ref().take(2).collect::<Vec<_>>(), vec![1, 2]);
assert_eq!(signal.next(), 3);
assert_eq!(signal.next(), 4);
}