tekhsi_rs 0.1.1

High-performance client for Tektronix TekHSI enabled oscilloscopes
Documentation
use std::f64::consts::PI;

/// FFT window types used for spectrum calculations.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FftWindow {
    BlackmanHarris,
    Blackman,
    Hamming,
    Hann,
    Rectangular,
}

impl FftWindow {
    /// Return the coherent gain for this window.
    ///
    /// ```rust
    /// use tekhsi_rs::fft::FftWindow;
    ///
    /// assert_eq!(FftWindow::Rectangular.coherent_gain(), 1.0);
    /// ```
    pub fn coherent_gain(&self) -> f64 {
        match self {
            FftWindow::Rectangular => 1.0,
            FftWindow::Hann => 0.5,
            FftWindow::Hamming => 0.54,
            FftWindow::Blackman => 0.42,
            FftWindow::BlackmanHarris => 0.35875,
        }
    }
}

pub(super) fn window_coefficients(size: usize, window: FftWindow) -> Vec<f64> {
    if size == 0 {
        return Vec::new();
    }
    if size == 1 {
        return vec![1.0];
    }
    match window {
        FftWindow::Rectangular => vec![1.0; size],
        FftWindow::Hann => cosine_window(size, 0.5, 0.5, 0.0, 0.0),
        FftWindow::Hamming => cosine_window(size, 0.54, 0.46, 0.0, 0.0),
        FftWindow::Blackman => cosine_window(size, 0.42, 0.5, 0.08, 0.0),
        FftWindow::BlackmanHarris => cosine_window(size, 0.35875, 0.48829, 0.14128, 0.01168),
    }
}

fn cosine_window(size: usize, a0: f64, a1: f64, a2: f64, a3: f64) -> Vec<f64> {
    let denom = (size - 1) as f64;
    let mut coeffs = Vec::with_capacity(size);
    for n in 0..size {
        let phase = 2.0 * PI * (n as f64) / denom;
        let value = a0 - a1 * phase.cos() + a2 * (2.0 * phase).cos() - a3 * (3.0 * phase).cos();
        coeffs.push(value);
    }
    coeffs
}