Struct Signal
pub struct Signal<T: SignalType> { /* private fields */ }Expand description
A generic signal container supporting both f32 and f64
§Examples
use ferro_wave::Signal;
// Create a signal from a vector
let signal = Signal::<f64>::new(vec![1.0, 2.0, 3.0, 4.0]);
assert_eq!(signal.len(), 4);
// Create a signal with sample rate
let mut signal = Signal::<f32>::with_sample_rate(vec![0.0; 100], 44100.0);
assert_eq!(signal.sample_rate(), Some(44100.0));Implementations§
§impl<T: SignalType> Signal<T>
impl<T: SignalType> Signal<T>
pub fn with_sample_rate(data: Vec<T>, sample_rate: f64) -> Self
pub fn with_sample_rate(data: Vec<T>, sample_rate: f64) -> Self
Create a new signal with a specified sample rate
pub fn from_slice(data: &[T]) -> Self
pub fn from_slice(data: &[T]) -> Self
Create a signal from a slice
pub fn sample_rate(&self) -> Option<f64>
pub fn sample_rate(&self) -> Option<f64>
Get the sample rate if available
pub fn set_sample_rate(&mut self, rate: f64)
pub fn set_sample_rate(&mut self, rate: f64)
Set the sample rate
pub fn metadata(&self) -> &SignalMetadata
pub fn metadata(&self) -> &SignalMetadata
Get metadata
pub fn metadata_mut(&mut self) -> &mut SignalMetadata
pub fn metadata_mut(&mut self) -> &mut SignalMetadata
Get mutable metadata
pub fn mean(&self) -> T
pub fn mean(&self) -> T
Compute the mean of the signal
pub fn std(&self) -> T
pub fn std(&self) -> T
Compute the sample standard deviation using Welford’s numerically stable algorithm
This calculates the sample standard deviation using Bessel’s correction (n-1 denominator) for unbiased estimation, not the population standard deviation (n denominator).
Formula: σ = sqrt(Σ(xi - μ)² / (n-1))
Where:
- xi: individual sample values
- μ: sample mean
- n: number of samples
§Why Sample Standard Deviation?
We use the sample standard deviation (with n-1) because:
- It provides an unbiased estimate when working with samples from a larger population
- It’s the standard choice in signal processing and statistics
- It prevents underestimation of variance in finite samples
§Returns
Returns 0 if the signal has fewer than 2 samples.
§Example
use ferro_wave::Signal;
let signal = Signal::<f64>::new(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let std = signal.std(); // Sample standard deviation
assert!((std - 1.5811388300841898).abs() < 1e-10);pub fn std_population(&self) -> T
pub fn std_population(&self) -> T
Compute the population standard deviation
This calculates the population standard deviation using n as the denominator, suitable when you have the complete population rather than a sample.
Formula: σ = sqrt(Σ(xi - μ)² / n)
§Comparison with std()
- Use
std()(sample) when working with a sample from a larger population - Use
std_population()when you have the entire population - For large n, the difference becomes negligible
§Example
use ferro_wave::Signal;
let signal = Signal::<f64>::new(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let std_sample = signal.std(); // Uses n-1
let std_pop = signal.std_population(); // Uses n
assert!(std_sample > std_pop); // Sample std is always largerpub fn normalize(&self) -> Self
pub fn normalize(&self) -> Self
Normalize the signal to have zero mean and unit variance
Uses the sample standard deviation (with Bessel’s correction) for normalization. This is the standard approach in signal processing as it provides unbiased estimation.
The transformation applied is: x’ = (x - μ) / σ
Where:
- x: original sample value
- μ: sample mean
- σ: sample standard deviation (using n-1)
- x’: normalized value
§Returns
Returns a new signal with mean ≈ 0 and standard deviation ≈ 1. If the standard deviation is zero (constant signal), returns a clone of the original.
§Examples
use ferro_wave::Signal;
let signal = Signal::<f64>::new(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let normalized = signal.normalize();
assert!((normalized.mean()).abs() < 1e-10);
assert!((normalized.std() - 1.0).abs() < 1e-10); // Sample std = 1pub fn energy(&self) -> T
pub fn energy(&self) -> T
Compute the energy of the signal (sum of squared values)
Energy = Σ(xi²) where xi are the signal samples
pub fn rms(&self) -> T
pub fn rms(&self) -> T
Compute the RMS (Root Mean Square) value of the signal
RMS = sqrt(Σ(xi²) / n) where xi are the signal samples and n is the length
pub fn peak_to_peak(&self) -> T
pub fn peak_to_peak(&self) -> T
Compute the peak-to-peak amplitude
§impl Signal<f64>
impl Signal<f64>
pub fn energy_fast(&self) -> f64
pub fn energy_fast(&self) -> f64
Optimized energy calculation for f64 signals
pub fn normalize_inplace(&mut self)
pub fn normalize_inplace(&mut self)
In-place normalization for f64 signals
pub fn add_scalar_inplace(&mut self, scalar: f64)
pub fn add_scalar_inplace(&mut self, scalar: f64)
Add a scalar value to all elements (in-place)
pub fn scale_inplace(&mut self, scalar: f64)
pub fn scale_inplace(&mut self, scalar: f64)
Multiply all elements by a scalar (in-place)
Trait Implementations§
§impl<T: Clone + SignalType> Clone for Signal<T>
impl<T: Clone + SignalType> Clone for Signal<T>
§impl<T: Debug + SignalType> Debug for Signal<T>
impl<T: Debug + SignalType> Debug for Signal<T>
§impl<T: SignalType> From<&[T]> for Signal<T>
impl<T: SignalType> From<&[T]> for Signal<T>
Auto Trait Implementations§
impl<T> Freeze for Signal<T>
impl<T> RefUnwindSafe for Signal<T>where
T: RefUnwindSafe,
impl<T> Send for Signal<T>
impl<T> Sync for Signal<T>
impl<T> Unpin for Signal<T>where
T: Unpin,
impl<T> UnwindSafe for Signal<T>where
T: UnwindSafe,
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)§impl<T> IntoEither for T
impl<T> IntoEither for T
§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.