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:
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); }