basic_dsp_vector/vector_types/time_freq/
freq_to_time.rs

1use super::super::{
2    Buffer, ComplexNumberSpace, DataDomain, DspVec, ErrorReason, FloatIndex, FrequencyDomain,
3    FrequencyDomainOperations, InsertZerosOpsBuffered, MetaData, RededicateForceOps, ScaleOps,
4    TimeDomainOperations, ToRealTimeResult, ToSliceMut, ToTimeResult, TransRes, Vector,
5};
6use super::fft;
7use crate::multicore_support::*;
8use crate::numbers::*;
9use crate::window_functions::*;
10use rustfft::FftDirection;
11
12/// Defines all operations which are valid on `DataVecs` containing frequency domain data.
13/// # Failures
14/// All operations in this trait set `self.len()` to `0`
15/// if the vector isn't in frequency domain and complex number space.
16pub trait FrequencyToTimeDomainOperations<S, T>: ToTimeResult
17where
18    S: ToSliceMut<T>,
19    T: RealNumber,
20{
21    /// Performs an Inverse Fast Fourier Transformation transforming a frequency domain vector
22    /// into a time domain vector.
23    ///
24    /// This version of the IFFT neither applies a window nor does it scale the
25    /// vector.
26    /// # Example
27    ///
28    /// ```
29    /// use std::f32;
30    /// use basic_dsp_vector::*;
31    /// # use num_complex::Complex;
32    /// let vector = vec!(Complex::new(0.0, 0.0), Complex::new(1.0, 0.0), Complex::new(0.0, 0.0)).to_complex_freq_vec();
33    /// let mut buffer = SingleBuffer::new();
34    /// let result = vector.plain_ifft(&mut buffer);
35    /// let actual = &result[..];
36    /// let expected = &[Complex::new(1.0, 0.0), Complex::new(-0.5, 0.8660254), Complex::new(-0.5, -0.8660254)];
37    /// assert_eq!(actual.len(), expected.len());
38    /// for i in 0..actual.len() {
39    ///        assert!((actual[i] - expected[i]).norm() < 1e-4);
40    /// }
41    /// ```
42    fn plain_ifft<B>(self, buffer: &mut B) -> Self::TimeResult
43    where
44        B: for<'a> Buffer<'a, S, T>;
45
46    /// Performs an Inverse Fast Fourier Transformation transforming a frequency domain vector
47    /// into a time domain vector.
48    /// # Example
49    ///
50    /// ```
51    /// use std::f32;
52    /// use basic_dsp_vector::*;
53    /// # use num_complex::Complex;
54    /// let vector = vec!(Complex::new(0.0, 0.0), Complex::new(0.0, 0.0), Complex::new(3.0, 0.0)).to_complex_freq_vec();
55    /// let mut buffer = SingleBuffer::new();
56    /// let result = vector.ifft(&mut buffer);
57    /// let actual = &result[..];
58    /// let expected = &[Complex::new(1.0, 0.0), Complex::new(-0.5, 0.8660254), Complex::new(-0.5, -0.8660254)];
59    /// assert_eq!(actual.len(), expected.len());
60    /// for i in 0..actual.len() {
61    ///        assert!((actual[i] - expected[i]).norm() < 1e-4);
62    /// }
63    /// ```
64    fn ifft<B>(self, buffer: &mut B) -> Self::TimeResult
65    where
66        B: for<'a> Buffer<'a, S, T>;
67
68    /// Performs an Inverse Fast Fourier Transformation transforming a frequency domain vector
69    /// into a time domain vector and removes the FFT window.
70    fn windowed_ifft<B>(self, buffer: &mut B, window: &dyn WindowFunction<T>) -> Self::TimeResult
71    where
72        B: for<'a> Buffer<'a, S, T>;
73}
74
75/// Defines all operations which are valid on `DataVecs` containing frequency domain data and
76/// the data is assumed to half of complex conjugate symmetric spectrum round 0 Hz where
77/// the 0 Hz element itself is real.
78/// # Failures
79/// All operations in this trait set `self.len()` to `0` if the first element (0Hz)
80/// isn't real.
81pub trait SymmetricFrequencyToTimeDomainOperations<S, T>: ToRealTimeResult
82where
83    S: ToSliceMut<T>,
84    T: RealNumber,
85{
86    /// Performs a Symmetric Inverse Fast Fourier Transformation under the assumption that `self`
87    /// contains half of a symmetric spectrum starting from 0 Hz. This assumption
88    /// isn't verified and no error is raised if the spectrum isn't symmetric. The reason
89    /// for this is that there is no robust verification possible.
90    ///
91    /// The argument indicates whether the resulting real vector should have `2*N`
92    /// or `2*N-1` points.
93    ///
94    /// This version of the IFFT neither applies a window nor does it scale the
95    /// vector.
96    fn plain_sifft<B>(self, buffer: &mut B) -> TransRes<Self::RealTimeResult>
97    where
98        B: for<'a> Buffer<'a, S, T>;
99
100    /// Performs a Symmetric Inverse Fast Fourier Transformation under the assumption that `self`
101    /// contains half of a symmetric spectrum starting from 0 Hz. This assumption
102    /// isn't verified and no error is raised if the spectrum isn't symmetric. The reason
103    /// for this is that there is no robust verification possible.
104    ///
105    /// The argument indicates whether the resulting real vector should have `2*N` or
106    /// `2*N-1` points.
107    fn sifft<B>(self, buffer: &mut B) -> TransRes<Self::RealTimeResult>
108    where
109        B: for<'a> Buffer<'a, S, T>;
110
111    /// Performs a Symmetric Inverse Fast Fourier Transformation (SIFFT) and removes the FFT
112    /// window. The SIFFT is performed under the assumption that `self`
113    /// contains half of a symmetric spectrum starting from 0 Hz. This assumption
114    /// isn't verified and no error is raised if the spectrum isn't symmetric. The reason
115    /// for this is that there is no robust verification possible.
116    ///
117    /// The argument indicates whether the resulting real vector should have `2*N` or `2*N-1`
118    /// points.
119    fn windowed_sifft<B>(
120        self,
121        buffer: &mut B,
122        window: &dyn WindowFunction<T>,
123    ) -> TransRes<Self::RealTimeResult>
124    where
125        B: for<'a> Buffer<'a, S, T>;
126}
127
128impl<S, T, N, D> FrequencyToTimeDomainOperations<S, T> for DspVec<S, T, N, D>
129where
130    DspVec<S, T, N, D>: ToTimeResult,
131    <DspVec<S, T, N, D> as ToTimeResult>::TimeResult:
132        RededicateForceOps<DspVec<S, T, N, D>> + TimeDomainOperations<S, T>,
133    S: ToSliceMut<T>,
134    T: RealNumber,
135    N: ComplexNumberSpace,
136    D: FrequencyDomain,
137{
138    fn plain_ifft<B>(mut self, buffer: &mut B) -> Self::TimeResult
139    where
140        B: for<'a> Buffer<'a, S, T>,
141    {
142        if self.domain() != DataDomain::Frequency {
143            self.mark_vector_as_invalid();
144            self.number_space.to_complex();
145            self.domain.to_freq();
146            return Self::TimeResult::rededicate_from_force(self);
147        }
148
149        if !self.is_complex() {
150            self.zero_interleave_b(buffer, 2);
151            self.number_space.to_complex();
152        }
153
154        fft(&mut self, buffer, FftDirection::Inverse);
155
156        self.domain.to_freq();
157        Self::TimeResult::rededicate_from_force(self)
158    }
159
160    fn ifft<B>(mut self, buffer: &mut B) -> Self::TimeResult
161    where
162        B: for<'a> Buffer<'a, S, T>,
163    {
164        let points = self.points();
165        self.scale(T::one() / T::from(points).unwrap());
166        self.ifft_shift();
167        self.plain_ifft(buffer)
168    }
169
170    fn windowed_ifft<B>(self, buffer: &mut B, window: &dyn WindowFunction<T>) -> Self::TimeResult
171    where
172        B: for<'a> Buffer<'a, S, T>,
173    {
174        let mut result = self.ifft(buffer);
175        result.unapply_window(window);
176        result
177    }
178}
179
180impl<S, T, N, D> SymmetricFrequencyToTimeDomainOperations<S, T> for DspVec<S, T, N, D>
181where
182    DspVec<S, T, N, D>: ToRealTimeResult + ToTimeResult + FrequencyDomainOperations<S, T>,
183    <DspVec<S, T, N, D> as ToRealTimeResult>::RealTimeResult:
184        RededicateForceOps<DspVec<S, T, N, D>> + TimeDomainOperations<S, T>,
185    S: ToSliceMut<T>,
186    T: RealNumber,
187    N: ComplexNumberSpace,
188    D: FrequencyDomain,
189{
190    fn plain_sifft<B>(mut self, buffer: &mut B) -> TransRes<Self::RealTimeResult>
191    where
192        B: for<'a> Buffer<'a, S, T>,
193    {
194        if self.domain() != DataDomain::Frequency || !self.is_complex() {
195            self.mark_vector_as_invalid();
196            self.number_space.to_complex();
197            self.domain.to_freq();
198            return Err((
199                ErrorReason::InputMustBeInFrequencyDomain,
200                Self::RealTimeResult::rededicate_from_force(self),
201            ));
202        }
203
204        if self.points() > 0 && self.data(1).abs() > T::from(1e-10).unwrap() {
205            self.mark_vector_as_invalid();
206            self.number_space.to_complex();
207            self.domain.to_freq();
208            return Err((
209                ErrorReason::InputMustBeConjSymmetric,
210                Self::RealTimeResult::rededicate_from_force(self),
211            ));
212        }
213
214        self.mirror(buffer);
215
216        fft(&mut self, buffer, FftDirection::Inverse);
217
218        self.domain.to_freq();
219        self.pure_complex_to_real_operation(buffer, |x, _arg| x.re, (), Complexity::Small);
220        Ok(Self::RealTimeResult::rededicate_from_force(self))
221    }
222
223    fn sifft<B>(mut self, buffer: &mut B) -> TransRes<Self::RealTimeResult>
224    where
225        B: for<'a> Buffer<'a, S, T>,
226    {
227        let points = self.points();
228        self.scale(Complex::<T>::new(
229            T::one() / T::from(points).unwrap(),
230            T::zero(),
231        ));
232        self.ifft_shift();
233        self.plain_sifft(buffer)
234    }
235
236    fn windowed_sifft<B>(
237        self,
238        buffer: &mut B,
239        window: &dyn WindowFunction<T>,
240    ) -> TransRes<Self::RealTimeResult>
241    where
242        B: for<'a> Buffer<'a, S, T>,
243    {
244        let mut result = self.sifft(buffer)?;
245        result.unapply_window(window);
246        Ok(result)
247    }
248}