extern crate basic_dsp_vector;
extern crate num_complex;
pub mod facade32;
pub mod facade64;
use basic_dsp_vector::conv_types::*;
use basic_dsp_vector::numbers::RealNumber;
use basic_dsp_vector::window_functions::*;
use basic_dsp_vector::{
ErrorReason, GenDspVec, PaddingOption, ScalarResult, SingleBuffer, TransRes, VoidResult,
};
use num_complex::Complex;
pub struct InteropVec<T>
where
T: RealNumber,
{
buffer: SingleBuffer<T>,
vec: GenDspVec<Vec<T>, T>,
}
impl<T> InteropVec<T>
where
T: RealNumber,
{
pub fn convert_vec<F>(mut self, op: F) -> VectorInteropResult<InteropVec<T>>
where
F: Fn(&mut GenDspVec<Vec<T>, T>, &mut SingleBuffer<T>) -> VoidResult,
{
let result = op(&mut self.vec, &mut self.buffer);
match result {
Ok(()) => {
let vector = Box::new(self);
let result_code = get_error_marker(&vector);
VectorInteropResult {
vector,
result_code,
}
}
Err(res) => VectorInteropResult {
vector: Box::new(self),
result_code: translate_error(res),
},
}
}
pub fn trans_vec<F>(self, op: F) -> VectorInteropResult<InteropVec<T>>
where
F: Fn(GenDspVec<Vec<T>, T>, &mut SingleBuffer<T>) -> TransRes<GenDspVec<Vec<T>, T>>,
{
let mut buffer = self.buffer;
let vec = self.vec;
let result = op(vec, &mut buffer);
match result {
Ok(vec) => {
let vector = Box::new(InteropVec {
vec: vec,
buffer: buffer,
});
let result_code = get_error_marker(&vector);
VectorInteropResult {
vector,
result_code,
}
}
Err((err, vec)) => VectorInteropResult {
vector: Box::new(InteropVec {
vec: vec,
buffer: buffer,
}),
result_code: translate_error(err),
},
}
}
pub fn convert_scalar<F, TT>(&self, op: F, default: TT) -> ScalarInteropResult<TT>
where
F: Fn(&GenDspVec<Vec<T>, T>) -> ScalarResult<TT>,
{
let result = op(&self.vec);
match result {
Ok(res) => ScalarInteropResult {
result: res,
result_code: get_error_marker(&self),
},
Err(res) => ScalarInteropResult {
result: default,
result_code: translate_error(res),
},
}
}
pub fn decompose(self) -> (GenDspVec<Vec<T>, T>, SingleBuffer<T>) {
(self.vec, self.buffer)
}
}
pub fn convert_void(result: VoidResult) -> i32 {
match result {
Ok(()) => 9,
Err(err) => translate_error(err),
}
}
pub fn translate_error(reason: ErrorReason) -> i32 {
match reason {
ErrorReason::InputMustHaveTheSameSize => 1,
ErrorReason::InputMetaDataMustAgree => 2,
ErrorReason::InputMustBeComplex => 3,
ErrorReason::InputMustBeReal => 4,
ErrorReason::InputMustBeInTimeDomain => 5,
ErrorReason::InputMustBeInFrequencyDomain => 6,
ErrorReason::InvalidArgumentLength => 7,
ErrorReason::InputMustBeConjSymmetric => 8,
ErrorReason::InputMustHaveAnOddLength => 9,
ErrorReason::ArgumentFunctionMustBeSymmetric => 10,
ErrorReason::InvalidNumberOfArgumentsForCombinedOp => 11,
ErrorReason::InputMustNotBeEmpty => 12,
ErrorReason::InputMustHaveAnEvenLength => 13,
ErrorReason::TypeCanNotResize => 14,
}
}
pub fn get_error_marker<T: RealNumber>(vec: &InteropVec<T>) -> i32 {
if vec.vec.is_erroneous() {
-1
} else {
0
}
}
pub fn translate_to_window_function<T>(value: i32) -> Box<dyn WindowFunction<T>>
where
T: RealNumber,
{
match value {
0 => Box::new(TriangularWindow),
1 => Box::new(HammingWindow::default()),
2 => Box::new(BlackmanHarrisWindow),
3 => Box::new(RectangularWindow),
_ => Box::new(RectangularWindow),
}
}
pub fn translate_to_real_convolution_function<T>(
value: i32,
rolloff: T,
) -> Box<dyn RealImpulseResponse<T>>
where
T: RealNumber,
{
if value == 0 {
Box::new(SincFunction::new())
} else {
Box::new(RaisedCosineFunction::new(rolloff))
}
}
pub fn translate_to_real_frequency_response<T>(
value: i32,
rolloff: T,
) -> Box<dyn RealFrequencyResponse<T>>
where
T: RealNumber,
{
if value == 0 {
Box::new(SincFunction::new())
} else {
Box::new(RaisedCosineFunction::new(rolloff))
}
}
pub fn translate_to_padding_option(value: i32) -> PaddingOption {
match value {
0 => PaddingOption::End,
1 => PaddingOption::Surround,
_ => PaddingOption::Center,
}
}
#[repr(C)]
pub struct VectorInteropResult<T> {
pub result_code: i32,
pub vector: Box<T>,
}
#[repr(C)]
pub struct BinaryVectorInteropResult<T> {
pub result_code: i32,
pub vector1: Box<T>,
pub vector2: Box<T>,
}
#[repr(C)]
pub struct ScalarInteropResult<T>
where
T: Sized,
{
pub result_code: i32,
pub result: T,
}
struct ForeignWindowFunction<T>
where
T: RealNumber,
{
pub window_function: extern "C" fn(*const std::os::raw::c_void, usize, usize) -> T,
pub window_data: usize,
pub is_symmetric: bool,
}
impl<T> WindowFunction<T> for ForeignWindowFunction<T>
where
T: RealNumber,
{
fn is_symmetric(&self) -> bool {
self.is_symmetric
}
fn window(&self, idx: usize, points: usize) -> T {
let fun = self.window_function;
fun(self.window_data as *const std::os::raw::c_void, idx, points)
}
}
struct ForeignRealConvolutionFunction<T>
where
T: RealNumber,
{
pub conv_function: extern "C" fn(*const std::os::raw::c_void, T) -> T,
pub conv_data: usize,
pub is_symmetric: bool,
}
impl<T> RealImpulseResponse<T> for ForeignRealConvolutionFunction<T>
where
T: RealNumber,
{
fn is_symmetric(&self) -> bool {
self.is_symmetric
}
fn calc(&self, x: T) -> T {
let fun = self.conv_function;
fun(self.conv_data as *const std::os::raw::c_void, x)
}
}
impl<T> RealFrequencyResponse<T> for ForeignRealConvolutionFunction<T>
where
T: RealNumber,
{
fn is_symmetric(&self) -> bool {
self.is_symmetric
}
fn calc(&self, x: T) -> T {
let fun = self.conv_function;
fun(self.conv_data as *const std::os::raw::c_void, x)
}
}
struct ForeignComplexConvolutionFunction<T>
where
T: RealNumber,
{
pub conv_function: extern "C" fn(*const std::os::raw::c_void, T) -> Complex<T>,
pub conv_data: usize,
pub is_symmetric: bool,
}
impl<T> ComplexImpulseResponse<T> for ForeignComplexConvolutionFunction<T>
where
T: RealNumber,
{
fn is_symmetric(&self) -> bool {
self.is_symmetric
}
fn calc(&self, x: T) -> Complex<T> {
let fun = self.conv_function;
fun(self.conv_data as *const std::os::raw::c_void, x)
}
}
impl<T> ComplexFrequencyResponse<T> for ForeignComplexConvolutionFunction<T>
where
T: RealNumber,
{
fn is_symmetric(&self) -> bool {
self.is_symmetric
}
fn calc(&self, x: T) -> Complex<T> {
let fun = self.conv_function;
fun(self.conv_data as *const std::os::raw::c_void, x)
}
}