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 81230f191404a6c4322ea1fed012f37cbcdb3b90
parent 790613537488483c1d2ec3ba6834066fd301a4e3
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Thu, 11 Aug 2016 08:33:48 +0300

Delay line

Diffstat:
Minclude/kfr/dsp.hpp | 1+
Ainclude/kfr/dsp/delay.hpp | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msources.cmake | 1+
Mtests/vec_test.cpp | 18++++++++++++++++++
4 files changed, 118 insertions(+), 0 deletions(-)

diff --git a/include/kfr/dsp.hpp b/include/kfr/dsp.hpp @@ -27,6 +27,7 @@ #include "dsp/biquad.hpp" #include "dsp/biquad_design.hpp" #include "dsp/dcremove.hpp" +#include "dsp/delay.hpp" #include "dsp/fir.hpp" #include "dsp/fir_design.hpp" #include "dsp/fracdelay.hpp" diff --git a/include/kfr/dsp/delay.hpp b/include/kfr/dsp/delay.hpp @@ -0,0 +1,98 @@ +/** + * 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 "../base/expression.hpp" +#include "../base/univector.hpp" + +namespace kfr +{ + +namespace internal +{ +template <size_t delay, typename E> +struct expression_delay : expression<E> +{ + using value_type = value_type_of<E>; + using expression<E>::expression; + + template <typename T, size_t N, KFR_ENABLE_IF(N <= delay)> + vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + { + vec<T, N> out; + size_t c = cursor; + data.ringbuf_read(c, out); + const vec<T, N> in = this->argument_first(index, vec_t<T, N>()); + data.ringbuf_write(cursor, in); + return out; + } + template <typename T> + vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const + { + T out; + size_t c = cursor; + data.ringbuf_read(c, out); + const T in = this->argument_first(index, vec_t<T, 1>())[0]; + data.ringbuf_write(cursor, in); + return out; + } + template <typename T, size_t N, KFR_ENABLE_IF(N > delay)> + vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + { + vec<T, delay> out; + size_t c = cursor; + data.ringbuf_read(c, out); + const vec<T, N> in = this->argument_first(index, vec_t<T, N>()); + data.ringbuf_write(cursor, slice<N - delay, delay>(in)); + return concat_and_slice<0, N>(out, in); + } + + mutable univector<value_type, delay> data = scalar(value_type(0)); + mutable size_t cursor = 0; +}; + +template <typename E> +struct expression_delay<1, E> : expression<E> +{ + using value_type = value_type_of<E>; + using expression<E>::expression; + + template <typename T, size_t N> + vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + { + const vec<T, N> in = this->argument_first(index, vec_t<T, N>()); + const vec<T, N> out = insertleft(data, in); + data = in[N - 1]; + return out; + } + mutable value_type data = value_type(0); +}; +} + +template <size_t samples = 1, typename E1> +CMT_INLINE internal::expression_delay<samples, E1> delay(E1&& e1, csize_t<samples> = csize<samples>) +{ + static_assert(samples >= 1 && samples < 1024, ""); + return internal::expression_delay<samples, E1>(std::forward<E1>(e1)); +} +} diff --git a/sources.cmake b/sources.cmake @@ -66,6 +66,7 @@ set( ${PROJECT_SOURCE_DIR}/include/kfr/dsp/biquad.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/biquad_design.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/dcremove.hpp + ${PROJECT_SOURCE_DIR}/include/kfr/dsp/delay.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/fir.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/fir_design.hpp ${PROJECT_SOURCE_DIR}/include/kfr/dsp/fracdelay.hpp diff --git a/tests/vec_test.cpp b/tests/vec_test.cpp @@ -277,4 +277,22 @@ TEST(vec_pack_expr) CHECK(v4[19] == f32x2{ 220, 20 }); } +TEST(test_delay) +{ + const univector<float, 33> v1 = counter() + 100; + const univector<float, 33> v2 = delay(v1); + CHECK(v2[0] == 0); + CHECK(v2[1] == 100); + CHECK(v2[2] == 101); + CHECK(v2[19] == 118); + + const univector<float, 33> v3 = delay(v1, csize<3>); + CHECK(v3[0] == 0); + CHECK(v3[1] == 0); + CHECK(v3[2] == 0); + CHECK(v3[3] == 100); + CHECK(v3[4] == 101); + CHECK(v3[19] == 116); +} + int main(int argc, char** argv) { return testo::run_all("", true); }