View Source NxSignal.Waveforms (NxSignal v0.2.0)

Functions that calculate waveforms given a time tensor.

Link to this section Summary

Functions: Waveforms

Gaussian modulated sinusoid.

Frequency-swept cosine generator, with a time-dependent frequency.

Periodic sawtooth or triangular waveform.

A periodic square wave with period $2\pi$.

Discrete delta function or unit basis vector.

Link to this section Functions: Waveforms

Link to this function

chirp(t, f0, t1, f1, opts \\ [])

View Source

Chirp function.

Starts at t with frequency f0 and ends at t1 with frequency f1.

options

Options

  • :phi - phase shift for the chirp.
  • :vertex_zero - determines the position of the parabolic vertex for when method: :quadratic. Defaults to true.
  • :method - One of various frequency interpolation methods:
    • :linear - linear interpolation.
    • :quadratic - parabolic interpolation with vertex at t1 or t0, depending if vertex_zero: false or vertex_zero: true respectively.
    • :hyperbolic - hyperbolic interpolation.
    • :logarithmic - logarithmic (also known as geometric or exponential) interpolation. f0 and f1 must be non-zero and have the same sign.

examples

Examples

iex> t = Nx.linspace(0, 10, n: 5)
iex> NxSignal.Waveforms.chirp(t, 10, 10, 1, method: :linear)
#Nx.Tensor<
  f32[5]
  [1.0, 0.38268470764160156, 3.795033308051643e-6, -0.382683128118515, 1.0]
>
iex> NxSignal.Waveforms.chirp(t, 10, 10, 1, method: :quadratic)
#Nx.Tensor<
  f32[5]
  [1.0, -0.9807833433151245, -9.958475288840418e-8, -0.5555803775787354, 1.0]
>
iex> NxSignal.Waveforms.chirp(t, 10, 10, 1, method: :quadratic, vertex_zero: false)
#Nx.Tensor<
  f32[5]
  [1.0, 0.5555850863456726, -7.490481493732659e-6, 0.98078453540802, 1.0]
>
iex> NxSignal.Waveforms.chirp(t, 10, 10, 1, method: :hyperbolic)
#Nx.Tensor<
  f32[5]
  [1.0, 0.8229323029518127, 0.9335360527038574, 0.013466471806168556, -0.8630329966545105]
>
iex> NxSignal.Waveforms.chirp(t, 10, 10, 1, method: :logarithmic)
#Nx.Tensor<
  f32[5]
  [1.0, 0.9989554286003113, -0.33371755480766296, -0.2700612545013428, 0.8558982610702515]
>
Link to this function

gaussian_pulse(t, opts \\ [])

View Source

Gaussian modulated sinusoid.

The returned value follows the formula:

$$ f(t) = e^{-at^2}(cos(2 \pi f_c t) + isin(2 \pi f_c t)) $$

Where the exponential envelope is returned as envelope, and the real and imaginary parts of $f(t)$ are returned as in_phase and quadrature in the output map.

Note that in_phase and quadrature are are equivalent to $\operatorname{Re} \lbrace f(t) \rbrace$ and $\operatorname{Im} \lbrace f(t) \rbrace$ respectively.

examples

Examples

iex> t = Nx.linspace(0, 1, n: 4)
iex> pulse = NxSignal.Waveforms.gaussian_pulse(t, center_frequency: 4)
iex> pulse.envelope
#Nx.Tensor<
  f32[4]
  [1.0, 0.20443114638328552, 0.001746579073369503, 6.236254534996988e-7]
>
iex> pulse.in_phase
#Nx.Tensor<
  f32[4]
  [1.0, -0.10221561044454575, -8.732887799851596e-4, 6.236254534996988e-7]
>
iex> pulse.quadrature
#Nx.Tensor<
  f32[4]
  [0.0, 0.17704254388809204, -0.0015125821810215712, 4.361525517918713e-13]
>

iex> t = Nx.linspace(0, 1, n: 4)
iex> pulse = NxSignal.Waveforms.gaussian_pulse(t, center_frequency: 4, bandwidth: 0.25)
iex> pulse.envelope
#Nx.Tensor<
  f32[4]
  [1.0, 0.6724140048027039, 0.20443114638328552, 0.028101593255996704]
>
iex> pulse.in_phase
#Nx.Tensor<
  f32[4]
  [1.0, -0.3362071216106415, -0.1022154912352562, 0.028101593255996704]
>
iex> pulse.quadrature
#Nx.Tensor<
  f32[4]
  [0.0, 0.5823275446891785, -0.177042618393898, 1.9653754179671523e-8]
>
Link to this function

polynomial_sweep(t, coefs, opts \\ [])

View Source

Frequency-swept cosine generator, with a time-dependent frequency.

This function generates a sinusoidal function whose instantaneous frequency varies with time. The frequency at time t is given by the polynomial specified by the coefficients contained in coefs.

See also: chirp/5

options

Options

  • :phi - phase shift to be applied before calculating the Nx.cos for the output. Defaults to 0.
  • :phi_unit - determines if :phi is given in :radians or :degrees. Defaults to :radians.

examples

Examples

iex> t = Nx.linspace(0, 10, n: 5)
iex> NxSignal.Waveforms.polynomial_sweep(t, Nx.tensor([2, 0, 1]))
#Nx.Tensor<
  f32[5]
  [1.0, 0.866027295589447, -0.500006377696991, 1.7942518752533942e-5, -0.49998921155929565]
>
iex> NxSignal.Waveforms.polynomial_sweep(t, Nx.tensor([2, 0, 1]), phi: :math.pi() / 2)
#Nx.Tensor<
  f32[5]
  [-4.371138828673793e-8, 0.499999463558197, -0.8660194873809814, 1.0, 0.8660338521003723]
>
iex> NxSignal.Waveforms.polynomial_sweep(t, Nx.tensor([1, 0]))
#Nx.Tensor<
  f32[5]
  [1.0, 0.7071065306663513, -1.0, 0.7071084976196289, 1.0]
>
iex> NxSignal.Waveforms.polynomial_sweep(t, Nx.tensor([1, 0]), phi: 180, phi_unit: :degrees)
#Nx.Tensor<
  f32[5]
  [-1.0, -0.7071069478988647, 1.0, -0.7071129679679871, -1.0]
>

Periodic sawtooth or triangular waveform.

The wave as a period of $2\pi$, rising from -1 to 1 in the interval $[0, 2\pi\cdot\text{width}]$ and dropping from 1 to -1 in the interval $[2\pi \cdot \text{width}, 2\pi]$.

options

Options

  • :width - the width of the sawtooth. Must be a number between 0 and 1 (both inclusive). Defaults to 1.

examples

Examples

A 5Hz waveform sampled at 500Hz for 1 second can be defined as:

t = Nx.linspace(0, 1, n: 500)
n = Nx.multiply(2 * :math.pi() * 5, t)
wave = NxSignal.Waveforms.sawtooth(n)

A periodic square wave with period $2\pi$.

Evaluates to 1 in the interval $[0, 2\pi\text{duty}]$ and -1 in the interval $[2\pi\text{duty}, 2\pi]$.

options

Options

  • :duty - a number or tensor representing the duty cycle. If a tensor is given, the waveform changes over time, and it must have the same length as the t input. Defaults to 0.5.

examples

Examples

iex> t = Nx.iota({10}) |> Nx.multiply(:math.pi() * 2 / 10)
iex> NxSignal.Waveforms.square(t, duty: 0.1)
#Nx.Tensor<
  s64[10]
  [1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
>
iex> NxSignal.Waveforms.square(t, duty: 0.5)
#Nx.Tensor<
  s64[10]
  [1, 1, 1, 1, 1, -1, -1, -1, -1, -1]
>
iex> NxSignal.Waveforms.square(t, duty: 1)
#Nx.Tensor<
  s64[10]
  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>

iex> t = Nx.iota({10}) |> Nx.multiply(:math.pi() * 2 / 10)
iex> duty = Nx.tensor([0.1, 0, 0.3, 0, 0.5, 0, 0.7, 0, 0.9, 0])
iex> NxSignal.Waveforms.square(t, duty: duty)
#Nx.Tensor<
  s64[10]
  [1, -1, 1, -1, 1, -1, 1, -1, 1, -1]
>
Link to this function

unit_impulse(shape, opts \\ [])

View Source

Discrete delta function or unit basis vector.

options

Options

  • :index - one of number, numerical tensor with length equal to the rank of the given shape, or :midpoint. index: :midpoint, is a shortcut for inserting the impulse at the index which corresponds to half of each dimension. Defaults to 0.

  • :type - datatype for the output. Defaults to :f32.

examples

Examples

iex> NxSignal.Waveforms.unit_impulse({2})
#Nx.Tensor<
  f32[2]
  [1.0, 0.0]
>

iex> NxSignal.Waveforms.unit_impulse({3, 5}, type: :s64, index: :midpoint)
#Nx.Tensor<
  s64[3][5]
  [
    [0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0]
  ]
>

iex> NxSignal.Waveforms.unit_impulse({3, 5}, index: Nx.tensor([[2, 3]]), type: :s64)
#Nx.Tensor<
  s64[3][5]
  [
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 1, 0]
  ]
>