Skip to content

Commit

Permalink
Added window functions to facade
Browse files Browse the repository at this point in the history
  • Loading branch information
liebharc committed Jan 3, 2016
1 parent bdaf5a9 commit 535b877
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 20 deletions.
32 changes: 32 additions & 0 deletions src/interop_facade/facade32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,4 +470,36 @@ pub extern fn sifft32(vector: Box<DataVector32>, even_odd: i32) -> VectorResult<
pub extern fn mirror32(vector: Box<DataVector32>, even_odd: i32) -> VectorResult<DataVector32> {
let even_odd = translate_to_even_odd(even_odd);
convert_vec!(vector.mirror(even_odd))
}

#[no_mangle]
pub extern fn apply_window32(vector: Box<DataVector32>, window: i32) -> VectorResult<DataVector32> {
let window = translate_to_window_function(window);
convert_vec!(vector.apply_window(window.as_ref()))
}

#[no_mangle]
pub extern fn unapply_window32(vector: Box<DataVector32>, window: i32) -> VectorResult<DataVector32> {
let window = translate_to_window_function(window);
convert_vec!(vector.unapply_window(window.as_ref()))
}


#[no_mangle]
pub extern fn windowed_fft32(vector: Box<DataVector32>, window: i32) -> VectorResult<DataVector32> {
let window = translate_to_window_function(window);
convert_vec!(vector.windowed_fft(window.as_ref()))
}

#[no_mangle]
pub extern fn windowed_ifft32(vector: Box<DataVector32>, window: i32) -> VectorResult<DataVector32> {
let window = translate_to_window_function(window);
convert_vec!(vector.windowed_ifft(window.as_ref()))
}

#[no_mangle]
pub extern fn windowed_sifft32(vector: Box<DataVector32>, even_odd: i32, window: i32) -> VectorResult<DataVector32> {
let even_odd = translate_to_even_odd(even_odd);
let window = translate_to_window_function(window);
convert_vec!(vector.windowed_sifft(even_odd, window.as_ref()))
}
11 changes: 11 additions & 0 deletions src/interop_facade/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub mod facade64;
use vector_types::{
ErrorReason,
EvenOdd};
use window_functions::*;
use RealNumber;

pub fn translate_error(reason: ErrorReason) -> i32 {
match reason {
Expand All @@ -58,6 +60,15 @@ pub fn translate_to_even_odd(value: i32) -> EvenOdd {
if value != 0 { EvenOdd::Odd } else { EvenOdd::Even }
}

pub fn translate_to_window_function<T>(value: i32) -> Box<WindowFunction<T>>
where T: RealNumber {
if value == 0 {
Box::new(TriangularWindow)
} else {
Box::new(TriangularWindow)
}
}

/// Result of a vector operation. Check the ```result_code```.
#[repr(C)]
pub struct VectorResult<T> {
Expand Down
28 changes: 14 additions & 14 deletions src/vector_types/time_freq_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ pub trait TimeDomainOperations<T> : DataVector<T>

/// Applies a FFT window and performs a Fast Fourier Transformation transforming a time domain vector
/// into a frequency domain vector.
fn windowed_fft<W>(self, window: W) -> VecResult<Self::FreqPartner> where W: WindowFunction<T>;
fn windowed_fft(self, window: &WindowFunction<T>) -> VecResult<Self::FreqPartner>;

/// Applies a window to the data vector.
fn apply_window<W>(self, window: W) -> VecResult<Self> where W: WindowFunction<T>;
fn apply_window(self, window: &WindowFunction<T>) -> VecResult<Self>;

/// Removes a window from the data vector.
fn unapply_window<W>(self, window: W) -> VecResult<Self> where W: WindowFunction<T>;
fn unapply_window(self, window: &WindowFunction<T>) -> VecResult<Self>;
}

/// Defines all operations which are valid on `DataVectors` containing complex data.
Expand Down Expand Up @@ -170,7 +170,7 @@ pub trait FrequencyDomainOperations<T> : DataVector<T>

/// Performs an Inverse Fast Fourier Transformation transforming a frequency domain vector
/// into a time domain vector and removes the FFT window.
fn windowed_ifft<W>(self, window: W) -> VecResult<Self::ComplexTimePartner> where W: WindowFunction<T>;
fn windowed_ifft(self, window: &WindowFunction<T>) -> VecResult<Self::ComplexTimePartner>;

/// Performs a Symmetric Inverse Fast Fourier Transformation (SIFFT) and removes the FFT window.
/// The SIFFT is performed under the assumption that `self`
Expand All @@ -181,7 +181,7 @@ pub trait FrequencyDomainOperations<T> : DataVector<T>
/// The argument indicates whether the resulting real vector should have `2*N` or `2*N-1` points.
/// # Unstable
/// Symmetric IFFTs are unstable and may only work under certain conditions.
fn windowed_sifft<W>(self, even_odd: EvenOdd, window: W) -> VecResult<Self::RealTimePartner> where W: WindowFunction<T>;
fn windowed_sifft(self, even_odd: EvenOdd, window: &WindowFunction<T>) -> VecResult<Self::RealTimePartner>;
}

macro_rules! define_time_domain_forward {
Expand All @@ -193,19 +193,19 @@ macro_rules! define_time_domain_forward {
Self::FreqPartner::from_genres(self.to_gen().plain_fft())
}

fn apply_window<W>(self, window: W) -> VecResult<Self> where W: WindowFunction<$data_type> {
fn apply_window(self, window: &WindowFunction<$data_type>) -> VecResult<Self> {
Self::from_genres(self.to_gen().apply_window(window))
}

fn unapply_window<W>(self, window: W) -> VecResult<Self> where W: WindowFunction<$data_type> {
fn unapply_window(self, window: &WindowFunction<$data_type>) -> VecResult<Self> {
Self::from_genres(self.to_gen().unapply_window(window))
}

fn fft(self) -> VecResult<Self::FreqPartner> {
Self::FreqPartner::from_genres(self.to_gen().fft())
}

fn windowed_fft<W>(self, window: W) -> VecResult<Self::FreqPartner> where W: WindowFunction<$data_type> {
fn windowed_fft(self, window: &WindowFunction<$data_type>) -> VecResult<Self::FreqPartner> {
Self::FreqPartner::from_genres(self.to_gen().windowed_fft(window))
}
}
Expand All @@ -216,7 +216,7 @@ macro_rules! define_time_domain_forward {
macro_rules! implement_window_function {
($($name:ident, $data_type:ident, $operation: ident);*) => {
$(
fn $name<W>(mut self, window: W) -> VecResult<Self> where W: WindowFunction<$data_type> {
fn $name(mut self, window: &WindowFunction<$data_type>) -> VecResult<Self> {
assert_time!(self);
if self.is_complex {
let len = self.len();
Expand Down Expand Up @@ -284,7 +284,7 @@ macro_rules! add_time_freq_impl {
.and_then(|v|v.swap_halves())
}

fn windowed_fft<W>(self, window: W) -> VecResult<Self::FreqPartner> where W: WindowFunction<$data_type> {
fn windowed_fft(self, window: &WindowFunction<$data_type>) -> VecResult<Self::FreqPartner> {
self.apply_window(window)
.and_then(|v|v.plain_fft())
.and_then(|v|v.swap_halves())
Expand Down Expand Up @@ -374,15 +374,15 @@ macro_rules! add_time_freq_impl {
.and_then(|v| v.plain_sifft(even_odd))
}

fn windowed_ifft<W>(self, window: W) -> VecResult<Self::ComplexTimePartner> where W: WindowFunction<$data_type> {
fn windowed_ifft(self, window: &WindowFunction<$data_type>) -> VecResult<Self::ComplexTimePartner> {
let points = self.points();
self.real_scale(1.0 / points as $data_type)
.and_then(|v| v.swap_halves())
.and_then(|v| v.plain_ifft())
.and_then(|v|v.unapply_window(window))
}

fn windowed_sifft<W>(self, even_odd: EvenOdd, window: W) -> VecResult<Self::RealTimePartner> where W: WindowFunction<$data_type> {
fn windowed_sifft(self, even_odd: EvenOdd, window: &WindowFunction<$data_type>) -> VecResult<Self::RealTimePartner> {
let points = self.points();
self.real_scale(1.0 / points as $data_type)
.and_then(|v| v.swap_halves())
Expand Down Expand Up @@ -414,11 +414,11 @@ macro_rules! add_time_freq_impl {
Self::RealTimePartner::from_genres(self.to_gen().sifft(even_odd))
}

fn windowed_ifft<W>(self, window: W) -> VecResult<Self::ComplexTimePartner> where W: WindowFunction<$data_type> {
fn windowed_ifft(self, window: &WindowFunction<$data_type>) -> VecResult<Self::ComplexTimePartner> {
Self::ComplexTimePartner::from_genres(self.to_gen().windowed_ifft(window))
}

fn windowed_sifft<W>(self, even_odd: EvenOdd, window: W) -> VecResult<Self::RealTimePartner> where W: WindowFunction<$data_type> {
fn windowed_sifft(self, even_odd: EvenOdd, window: &WindowFunction<$data_type>) -> VecResult<Self::RealTimePartner> {
Self::RealTimePartner::from_genres(self.to_gen().windowed_sifft(even_odd, window))
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/window_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::RealNumber;
/// 1. The second argument is of the function is always `self.points()` and the possible values for the first argument ranges from `0..self.points()`.
/// 2. A window function must be symmetric about the y-axis.
/// 3. All real return values are allowed
pub trait WindowFunction<T> : Sized
pub trait WindowFunction<T>
where T: RealNumber {
/// Calculates a point of the window function
fn window(&self, n: usize, length: usize) -> T;
Expand Down
10 changes: 5 additions & 5 deletions tests/time_freq_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ mod slow_test {
fn window_real_vs_complex_vector64() {
let vector = new_sinusoid_vector();
let complex = vector.clone().to_complex().unwrap();
let complex_windowed = complex.apply_window(HammingWindow::default()).unwrap();
let real_windowed = vector.apply_window(HammingWindow::default()).unwrap();
let complex_windowed = complex.apply_window(&HammingWindow::default()).unwrap();
let real_windowed = vector.apply_window(&HammingWindow::default()).unwrap();
assert_eq!(real_windowed.data(), complex_windowed.to_real().unwrap().data());
}

Expand All @@ -62,7 +62,7 @@ mod slow_test {
fn windowed_fft_vector64() {
let vector = new_sinusoid_vector();
let complex = vector.to_complex().unwrap();
let fft = complex.windowed_fft(HammingWindow::default()).unwrap().magnitude().unwrap();
let fft = complex.windowed_fft(&HammingWindow::default()).unwrap().magnitude().unwrap();
// Expected data has been created with GNU Octave
let expected: &[f64] = &[0.07411808515197066, 0.07422272322333621, 0.07453841468679659, 0.07506988195440296, 0.07582541343880053,
0.07681696328361777, 0.07806061998281554, 0.07957802869766938, 0.08139483126598358, 0.08354572044699357, 0.0860733404576818,
Expand Down Expand Up @@ -91,8 +91,8 @@ mod slow_test {
fn windowed_fft_windowed_ifft_vector64() {
let vector = new_sinusoid_vector();
let complex = vector.clone().to_complex().unwrap();
let fft = complex.windowed_fft(HammingWindow::default()).unwrap();
let ifft = fft.windowed_ifft(HammingWindow::default()).unwrap().to_real().unwrap();
let fft = complex.windowed_fft(&HammingWindow::default()).unwrap();
let ifft = fft.windowed_ifft(&HammingWindow::default()).unwrap().to_real().unwrap();
assert_vector_eq(vector.data(), ifft.data());
}

Expand Down

0 comments on commit 535b877

Please sign in to comment.