kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

commit 081388e674a62c448c7372503b6969c309a51cdd
parent 1ea2976070eb563c7b2938486e322e0b543d5f7c
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Mon, 18 Jul 2016 16:26:32 +0300

Feature added: Fractional delay

Diffstat:
Minclude/kfr/all.hpp | 1+
Ainclude/kfr/dsp/fracdelay.hpp | 44++++++++++++++++++++++++++++++++++++++++++++
Msources.cmake | 1+
Mtests/CMakeLists.txt | 3+++
Atests/fracdelay_test.cpp | 41+++++++++++++++++++++++++++++++++++++++++
5 files changed, 90 insertions(+), 0 deletions(-)

diff --git a/include/kfr/all.hpp b/include/kfr/all.hpp @@ -68,6 +68,7 @@ #include "data/sincos.hpp" #include "dsp/biquad.hpp" #include "dsp/fir.hpp" +#include "dsp/fracdelay.hpp" #include "dsp/goertzel.hpp" #include "dsp/interpolation.hpp" #include "dsp/oscillators.hpp" diff --git a/include/kfr/dsp/fracdelay.hpp b/include/kfr/dsp/fracdelay.hpp @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2016 D Levin (http://www.kfrlib.com) + * This file is part of KFR + * + * KFR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with KFR. + * + * If GPL is not suitable for your project, you must purchase a commercial license to use KFR. + * Buying a commercial license is mandatory as soon as you develop commercial activities without + * disclosing the source code of your own applications. + * See http://www.kfrlib.com for details. + */ +#pragma once + +#include "fir.hpp" + +namespace kfr +{ + +namespace native +{ + +template <typename T, typename E1> +KFR_INLINE internal::in_fir<>::expression_short_fir<2, T, E1> fracdelay(E1&& e1, T delay) +{ + if (delay < 0) + delay = 0; + if (delay > 1) + delay = fract(delay); + univector<T, 2> taps({ 1 - delay, delay }); + return internal::in_fir<>::expression_short_fir<2, T, E1>(std::forward<E1>(e1), taps.ref()); +} +} +} diff --git a/sources.cmake b/sources.cmake @@ -57,6 +57,7 @@ set( ${PROJECT_SOURCE_DIR}/include/kfr/dsp/oscillators.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/units.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/fir.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/dsp/fracdelay.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/goertzel.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/interpolation.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/resample.hpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt @@ -27,6 +27,7 @@ include_directories(../include) add_executable(basic_vector_test basic_vector_test.cpp ${KFR_SRC}) add_executable(dft_test dft_test.cpp ${KFR_SRC}) add_executable(conv_test conv_test.cpp ${KFR_SRC}) +add_executable(fracdelay_test fracdelay_test.cpp ${KFR_SRC}) add_executable(empty_test empty_test.cpp ${KFR_SRC}) add_executable(complex_test complex_test.cpp ${KFR_SRC}) add_executable(vec_test vec_test.cpp ${KFR_SRC}) @@ -35,6 +36,8 @@ enable_testing() add_test(NAME dft_test COMMAND ${PROJECT_BINARY_DIR}/tests/dft_test) +add_test(NAME fracdelay_test + COMMAND ${PROJECT_BINARY_DIR}/tests/fracdelay_test) add_test(NAME conv_test COMMAND ${PROJECT_BINARY_DIR}/tests/conv_test) add_test(NAME complex_test diff --git a/tests/fracdelay_test.cpp b/tests/fracdelay_test.cpp @@ -0,0 +1,41 @@ +/** + * KFR (http://kfrlib.com) + * Copyright (C) 2016 D Levin + * See LICENSE.txt for details + */ + +// library_version() +#include <kfr/io/tostring.hpp> +#include <kfr/version.hpp> + +#include <kfr/expressions/reduce.hpp> + +#include <tuple> + +#include "testo/testo.hpp" +#include <kfr/dsp/fracdelay.hpp> + +using namespace kfr; + +TEST(test_fracdelay) +{ + univector<double, 5> a({ 1, 2, 3, 4, 5 }); + univector<double, 5> b = native::fracdelay(a, 0.5); + CHECK(native::rms(b - univector<double>({ 0.5, 1.5, 2.5, 3.5, 4.5 })) < c_epsilon<double> * 5); + + b = native::fracdelay(a, 0.1); + CHECK(native::rms(b - univector<double>({ 0.9, 1.9, 2.9, 3.9, 4.9 })) < c_epsilon<double> * 5); + + b = native::fracdelay(a, 0.0); + CHECK(native::rms(b - univector<double>({ 1, 2, 3, 4, 5 })) < c_epsilon<double> * 5); + + b = native::fracdelay(a, 1.0); + CHECK(native::rms(b - univector<double>({ 0, 1, 2, 3, 4 })) < c_epsilon<double> * 5); +} + +int main(int argc, char** argv) +{ + println(library_version()); + + return testo::run_all("", true); +}