neco-modal 0.1.0

Modal extraction utilities for time-series vibration data
Documentation
use neco_stft::{with_planner, Complex};

pub(super) struct Spectrum {
    bins: Vec<Complex<f64>>,
    power: Vec<f64>,
}

impl Spectrum {
    pub(super) fn power(&self) -> &[f64] {
        &self.power
    }

    pub(super) fn phase_at(&self, bin: usize) -> f64 {
        self.bins[bin].arg()
    }
}

pub(super) fn hann_window_spectrum(readout: &[f64]) -> Spectrum {
    let n = readout.len();
    let nfft = n.next_power_of_two();
    let mut windowed = vec![0.0; nfft];
    for (i, &sample) in readout.iter().enumerate().take(n) {
        let hann = 0.5 * (1.0 - (2.0 * std::f64::consts::PI * i as f64 / (n - 1) as f64).cos());
        windowed[i] = sample * hann;
    }
    let n_pos = nfft / 2;
    with_planner(|planner| {
        let fft = planner.plan_fft_forward(nfft);
        let mut spectrum = fft.make_output_vec();
        fft.process(&mut windowed, &mut spectrum).unwrap();

        let bins = spectrum[..n_pos].to_vec();
        let power = bins.iter().map(|c| c.norm_sqr()).collect();
        Spectrum { bins, power }
    })
}