Expand description
Rust waveform generator, with no_std support.
§Quickstart
use wavegen::{wf, sine, dc_bias, sawtooth};
// Define a Waveform with 200Hz sampling rate and three function components,
// choosing f32 as the output type:
let waveform = wf!(f32, 200., sine!(50., 10.), sawtooth!(20.), dc_bias!(-5.));
// Use Waveform as an infinite iterator:
let two_seconds_of_samples: Vec<f32> = waveform.iter().take(400).collect();
Look into macros section for a complete list of defined periodic functions and their constructors.
§Periodic function macros
The macros for building predefined PeriodicFunctions generally have a form of:
function!(frequency, [amplitude, [phase]])
(Square braces “[]” indicate optional argument).
They come in an annotated and non-annotated form, so for example a Sine function can be expressed in both ways:
use wavegen::{wf, sine, PeriodicFunction};
let _: PeriodicFunction<f32> = sine!(100., 20., 0.25);
use wavegen::{wf, sine, PeriodicFunction};
let _: PeriodicFunction<f32> = sine!(frequency: 100., amplitude: 20., phase: 0.25);
Refer to Macros section for more info.
§Custom periodic functions
Supported, of course. Just define your custom function as Box<Fn(f64) -> f64>
and use it with Waveform
.
use wavegen::{wf, PeriodicFunction};
let waveform = wf!(f64, 100.0, PeriodicFunction::custom(|x| x % 2.0));
§Overflows
As Waveform
can be composed of multiple components, it is possible for it to overflow during samples collection.
If overflow occurs, the sample’s value will be clamped to the largest possible representation of sample’s type.
That means +/- Inf
for floating point types, and MAX/MIN
for integers.
use wavegen::{Waveform, dc_bias};
let wf = Waveform::<f64>::with_components(100.0, vec![dc_bias![f32::MAX], dc_bias![f32::MAX]]);
let sample = wf.iter().take(1).collect::<Vec<_>>()[0];
assert_eq!(sample, f64::INFINITY);
use wavegen::{Waveform, dc_bias};
let wf = Waveform::<i32>::with_components(100.0, vec![dc_bias![f32::MAX], dc_bias![f32::MAX]]);
let sample = wf.iter().take(1).collect::<Vec<_>>()[0];
assert_eq!(sample, i32::MAX);
§Calculation precision
By default, all calculations in Waveform
use single floating point precision f32
. This can be set to f64
if needed, possibly in case of very high frequencies. To do so, set the P
type parameter to f64
:
let double_precision_waveform = wavegen::Waveform::<f64, f64>::new(1e100);
§Iterator infinity
WaveformIterator
is a mostly infinite iterator, with one exception:
The WaveformIterator::next
method can return None
in some rare cases if it is not able to convert the inner sample type f64
into the target sample type.
f64::NAN
cannot be represented as i32
:
use wavegen::{Waveform, PeriodicFunction};
let mut wf = Waveform::<i32, f64>::new(100.0);
wf.add_component(PeriodicFunction::dc_bias(f64::NAN));
assert_eq!(None, wf.iter().next())
This however is fine, as f64::NAN
can be represented as f32::NAN
:
use wavegen::{Waveform, PeriodicFunction};
let mut wf = Waveform::<f32, f64>::new(100.0);
wf.add_component(PeriodicFunction::dc_bias(f64::NAN));
assert!(wf.iter().next().unwrap().is_nan())
It is probably a good practice to sanitize the parameters of the periodic function before it is constructed.
§Note about Nyquist-Shannon rule enforcement
As a rule of thumb in signal processing, the sampling frequency should be at least 2 times bigger than the highest frequency of sampled continous signal.
This lib will not enforce the Nyquist-Shannon rule on the waveforms you create, therefore abominations like this are possible (altough not recommended):
use wavegen::{Waveform, sine};
// 100 Hz sampling of 80 Hz sine... will not yield realistic results.
let wf = Waveform::<f32>::with_components(100.0, vec![sine!(80.)]);
As it is often a case, it is you, the programmer, who’s left in charge of making sure the input data makes sense.
Macros§
- dc_bias
- Builder macro for DC Bias
PeriodicFunction
. - sawtooth
- Builder macro for Sawtooth
PeriodicFunction
. - sine
- Builder macro for Sine
PeriodicFunction
. - square
- Builder macro for Square
PeriodicFunction
. - wf
- Helper macro to construct
Waveform
instance.
Structs§
- Periodic
Function - Wrapper struct for a periodic function (in most cases a
f32 -> f32
orf64 -> f64
map). - Waveform
- Struct representing a waveform, consisting of output numeric type, sampling rate and a vector of
PeriodicFunction
s. - Waveform
Iterator - An iterator that allows to sample a
Waveform
.
Traits§
- Precision
- Defines precision of inner
Waveform
andPeriodicFunction
calcualtions. - Sample
Type - Helper trait defining all the types that can be used as
Waveform
’s sample type.