use crate::data::{AnalogWaveform, IqWaveform};
use crate::fft::core::{FftResult, ReusableFftStateComplex, ReusableFftStateReal};
use crate::fft::window::FftWindow;
pub trait FftWaveform {
fn fft_mag(&self, window: FftWindow, fft_len: Option<usize>) -> FftResult;
fn fft_mag_cached<'a>(
&self,
state: &'a mut ReusableFftStateReal,
window: FftWindow,
fft_len: Option<usize>,
) -> &'a mut FftResult;
}
impl FftWaveform for AnalogWaveform {
fn fft_mag(&self, window: FftWindow, fft_len: Option<usize>) -> FftResult {
ReusableFftStateReal::new()
.fft_points_mag(
self.iter_normalized_values(),
analog_sample_rate(self),
fft_len,
window,
)
.clone()
}
fn fft_mag_cached<'a>(
&self,
state: &'a mut ReusableFftStateReal,
window: FftWindow,
fft_len: Option<usize>,
) -> &'a mut FftResult {
state.fft_points_mag(
self.iter_normalized_values(),
analog_sample_rate(self),
fft_len,
window,
)
}
}
impl FftWaveform for IqWaveform {
fn fft_mag(&self, window: FftWindow, fft_len: Option<usize>) -> FftResult {
ReusableFftStateReal::new()
.fft_points_mag(
self.iter_normalized_values()
.map(|value| (value.re * value.re + value.im * value.im).sqrt()),
iq_sample_rate(self),
fft_len,
window,
)
.clone()
}
fn fft_mag_cached<'a>(
&self,
state: &'a mut ReusableFftStateReal,
window: FftWindow,
fft_len: Option<usize>,
) -> &'a mut FftResult {
state.fft_points_mag(
self.iter_normalized_values()
.map(|value| (value.re * value.re + value.im * value.im).sqrt()),
iq_sample_rate(self),
fft_len,
window,
)
}
}
pub trait ComplexFftWaveform {
fn fft_complex(&self, window: FftWindow, fft_len: Option<usize>) -> FftResult;
fn fft_complex_cached<'a>(
&self,
state: &'a mut ReusableFftStateComplex,
window: FftWindow,
fft_len: Option<usize>,
) -> &'a mut FftResult;
}
impl ComplexFftWaveform for IqWaveform {
fn fft_complex(&self, window: FftWindow, fft_len: Option<usize>) -> FftResult {
ReusableFftStateComplex::new()
.fft_points_complex(
self.iter_normalized_values(),
iq_sample_rate(self),
self.meta_info.iq_center_frequency,
fft_len,
window,
)
.clone()
}
fn fft_complex_cached<'a>(
&self,
state: &'a mut ReusableFftStateComplex,
window: FftWindow,
fft_len: Option<usize>,
) -> &'a mut FftResult {
state.fft_points_complex(
self.iter_normalized_values(),
iq_sample_rate(self),
self.meta_info.iq_center_frequency,
fft_len,
window,
)
}
}
fn analog_sample_rate(analog: &AnalogWaveform) -> f64 {
if analog.x_axis_spacing > 0.0 {
1.0 / analog.x_axis_spacing
} else {
0.0
}
}
fn iq_sample_rate(iq: &IqWaveform) -> f64 {
if iq.meta_info.iq_sample_rate > 0.0 {
iq.meta_info.iq_sample_rate
} else if iq.x_axis_spacing > 0.0 {
1.0 / iq.x_axis_spacing
} else {
0.0
}
}