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 0f6f145957a1e097973b63dbb5d4ee2774d50ff0
parent 03a4abc7f98358af370e1e0c4535783db47ec8f2
Author: [email protected] <[email protected]>
Date:   Thu, 29 Sep 2016 16:10:53 +0300

Implement context passing

Diffstat:
Minclude/kfr/base/basic_expressions.hpp | 45+++++++++++++++++++++++++--------------------
Minclude/kfr/base/expression.hpp | 79+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Minclude/kfr/base/pointer.hpp | 51++++++++++++++++++++++++++++++++++++++++++++++-----
Minclude/kfr/base/types.hpp | 23++++++++++++-----------
Minclude/kfr/base/univector.hpp | 11++++++++---
Minclude/kfr/cometa.hpp | 3++-
Minclude/kfr/dsp/biquad.hpp | 16++++++++--------
Minclude/kfr/dsp/delay.hpp | 16++++++++--------
Minclude/kfr/dsp/fir.hpp | 8++++----
Minclude/kfr/dsp/sample_rate_conversion.hpp | 30+++++++++++++++---------------
Minclude/kfr/dsp/window.hpp | 26+++++++++++++-------------
Minclude/kfr/io/audiofile.hpp | 3++-
Mtests/intrinsic_test.cpp | 12++++++------
13 files changed, 196 insertions(+), 127 deletions(-)

diff --git a/include/kfr/base/basic_expressions.hpp b/include/kfr/base/basic_expressions.hpp @@ -42,9 +42,9 @@ struct expression_convert : expression<E> CMT_INLINE expression_convert(E&& expr) noexcept : expression<E>(std::forward<E>(expr)) {} template <size_t N> - CMT_INLINE vec<To, N> operator()(cinput_t, size_t index, vec_t<To, N>) const + CMT_INLINE vec<To, N> operator()(cinput_t input, size_t index, vec_t<To, N>) const { - return this->argument_first(index, vec_t<To, N>()); + return this->argument_first(input, index, vec_t<To, N>()); } }; @@ -201,9 +201,9 @@ struct expression_slice : expression<E1> { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { - return this->argument_first(index + start, y); + return this->argument_first(cinput, index + start, y); } size_t size() const { return new_size; } size_t start; @@ -217,9 +217,9 @@ struct expression_reverse : expression<E1> using T = value_type; expression_reverse(E1&& e1) : expression<E1>(std::forward<E1>(e1)), expr_size(e1.size()) {} template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { - return reverse(this->argument_first(expr_size - index - N, y)); + return reverse(this->argument_first(cinput, expr_size - index - N, y)); } size_t size() const { return expr_size; } size_t expr_size; @@ -305,12 +305,12 @@ public: } template <size_t N> - CMT_NOINLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_NOINLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { std::size_t sindex = size_t(std::upper_bound(std::begin(segments), std::end(segments), index) - 1 - std::begin(segments)); if (segments[sindex + 1] - index >= N) - return get(index, sindex - 1, y); + return get(cinput, index, sindex - 1, y); else { vec<T, N> result; @@ -318,7 +318,7 @@ public: for (size_t i = 0; i < N; i++) { sindex = segments[sindex + 1] == index ? sindex + 1 : sindex; - result.data()[i] = get(index, sindex - 1, vec_t<T, 1>())[0]; + result.data()[i] = get(cinput, index, sindex - 1, vec_t<T, 1>())[0]; index++; } return result; @@ -327,9 +327,10 @@ public: protected: template <size_t N> - CMT_NOINLINE vec<T, N> get(size_t index, size_t expr_index, vec_t<T, N> y) + CMT_NOINLINE vec<T, N> get(cinput_t cinput, size_t index, size_t expr_index, vec_t<T, N> y) { - return cswitch(indicesfor<E...>, expr_index, [&](auto val) { return this->argument(val, index, y); }, + return cswitch(indicesfor<E...>, expr_index, + [&](auto val) { return this->argument(cinput, val, index, y); }, [&]() { return zerovector(y); }); } @@ -345,9 +346,9 @@ struct expression_adjacent : expression<E> expression_adjacent(Fn&& fn, E&& e) : expression<E>(std::forward<E>(e)), fn(std::forward<Fn>(fn)) {} template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, 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> in = this->argument_first(cinput, index, vec_t<T, N>()); const vec<T, N> delayed = insertleft(data, in); data = in[N - 1]; return this->fn(in, delayed); @@ -419,7 +420,7 @@ struct multioutput : output_expression { } template <typename T, size_t N> - void operator()(coutput_t, size_t index, const vec<T, N>& x) + void operator()(coutput_t coutput, size_t index, const vec<T, N>& x) { cfor(csize<0>, csize<sizeof...(E)>, [&](auto n) { std::get<val_of(decltype(n)())>(outputs)(coutput, index, x); }); @@ -430,7 +431,7 @@ private: }; template <typename... E> -struct expression_pack : expression<E...>, output_expression +struct expression_pack : expression<E...> { constexpr static size_t count = sizeof...(E); @@ -441,15 +442,19 @@ struct expression_pack : expression<E...>, output_expression using expression<E...>::size; template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { - return this->call(fn::packtranspose(), index, y); + return this->call(cinput, fn::packtranspose(), index, y); } }; template <typename... E> struct expression_unpack : private expression<E...>, output_expression { + using expression<E...>::begin_block; + using expression<E...>::end_block; + using output_expression::begin_block; + using output_expression::end_block; constexpr static size_t count = sizeof...(E); expression_unpack(E&&... e) : expression<E...>(std::forward<E>(e)...) {} @@ -457,9 +462,9 @@ struct expression_unpack : private expression<E...>, output_expression using expression<E...>::size; template <typename U, size_t N> - CMT_INLINE void operator()(coutput_t, size_t index, const vec<vec<U, count>, N>& x) + CMT_INLINE void operator()(coutput_t coutput, size_t index, const vec<vec<U, count>, N>& x) { - output(index, x, csizeseq<count>); + output(coutput, index, x, csizeseq<count>); } template <typename Input, KFR_ENABLE_IF(is_input_expression<Input>::value)> @@ -472,7 +477,7 @@ struct expression_unpack : private expression<E...>, output_expression private: template <typename U, size_t N, size_t... indices> - void output(size_t index, const vec<vec<U, count>, N>& x, csizes_t<indices...>) + void output(coutput_t coutput, size_t index, const vec<vec<U, count>, N>& x, csizes_t<indices...>) { const vec<vec<U, N>, count> xx = compcast<vec<U, N>>(transpose<count>(flatten(x))); swallow{ (std::get<indices>(this->args)(coutput, index, xx[indices]), void(), 0)... }; diff --git a/include/kfr/base/expression.hpp b/include/kfr/base/expression.hpp @@ -67,8 +67,8 @@ struct input_expression constexpr static bool is_incremental = false; - CMT_INLINE void begin_block(size_t) const {} - CMT_INLINE void end_block(size_t) const {} + CMT_INLINE constexpr void begin_block(cinput_t, size_t) const {} + CMT_INLINE constexpr void end_block(cinput_t, size_t) const {} }; /// @brief Base class of all output expressoins @@ -78,8 +78,8 @@ struct output_expression constexpr static bool is_incremental = false; - CMT_INLINE void output_begin_block(size_t) const {} - CMT_INLINE void output_end_block(size_t) const {} + CMT_INLINE constexpr void begin_block(coutput_t, size_t) const {} + CMT_INLINE constexpr void end_block(coutput_t, size_t) const {} }; /// @brief Check if the type argument is an input expression @@ -116,7 +116,7 @@ struct expression_lambda : input_expression CMT_INLINE expression_lambda(Fn&& fn) : fn(std::move(fn)) {} template <size_t N, KFR_ENABLE_IF(N&& is_callable<Fn, cinput_t, size_t, vec_t<T, N>>::value)> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return fn(cinput, index, y); } @@ -196,11 +196,23 @@ struct expression : input_expression expression() = delete; constexpr expression(Args&&... args) noexcept : args(std::forward<Args>(args)...) {} - CMT_INLINE void begin_block(size_t size) { begin_block_impl(size, indicesfor_t<Args...>()); } - CMT_INLINE void end_block(size_t size) { end_block_impl(size, indicesfor_t<Args...>()); } + CMT_INLINE void begin_block(cinput_t cinput, size_t size) + { + begin_block_impl(cinput, size, indicesfor_t<Args...>()); + } + CMT_INLINE void end_block(cinput_t cinput, size_t size) + { + end_block_impl(cinput, size, indicesfor_t<Args...>()); + } - CMT_INLINE void begin_block(size_t size) const { begin_block_impl(size, indicesfor_t<Args...>()); } - CMT_INLINE void end_block(size_t size) const { end_block_impl(size, indicesfor_t<Args...>()); } + CMT_INLINE void begin_block(cinput_t cinput, size_t size) const + { + begin_block_impl(cinput, size, indicesfor_t<Args...>()); + } + CMT_INLINE void end_block(cinput_t cinput, size_t size) const + { + end_block_impl(cinput, size, indicesfor_t<Args...>()); + } std::tuple<Args...> args; @@ -212,20 +224,20 @@ protected: } template <typename Fn, typename T, size_t N> - CMT_INLINE vec<T, N> call(Fn&& fn, size_t index, vec_t<T, N> x) const + CMT_INLINE vec<T, N> call(cinput_t cinput, Fn&& fn, size_t index, vec_t<T, N> x) const { - return call_impl(std::forward<Fn>(fn), indicesfor_t<Args...>(), index, x); + return call_impl(cinput, std::forward<Fn>(fn), indicesfor_t<Args...>(), index, x); } template <size_t ArgIndex, typename U, size_t N, typename T = value_type_of<typename details::get_nth_type<ArgIndex, Args...>::type>> - CMT_INLINE vec<U, N> argument(csize_t<ArgIndex>, size_t index, vec_t<U, N>) const + CMT_INLINE vec<U, N> argument(cinput_t cinput, csize_t<ArgIndex>, size_t index, vec_t<U, N>) const { static_assert(ArgIndex < count, "Incorrect ArgIndex"); return static_cast<vec<U, N>>(std::get<ArgIndex>(this->args)(cinput, index, vec_t<T, N>())); } template <typename U, size_t N, typename T = value_type_of<typename details::get_nth_type<0, Args...>::type>> - CMT_INLINE vec<U, N> argument_first(size_t index, vec_t<U, N>) const + CMT_INLINE vec<U, N> argument_first(cinput_t cinput, size_t index, vec_t<U, N>) const { return static_cast<vec<U, N>>(std::get<0>(this->args)(cinput, index, vec_t<T, N>())); } @@ -237,29 +249,30 @@ private: return {}; } template <typename Fn, typename T, size_t N, size_t... indices> - CMT_INLINE vec<T, N> call_impl(Fn&& fn, csizes_t<indices...>, size_t index, vec_t<T, N>) const + CMT_INLINE vec<T, N> call_impl(cinput_t cinput, Fn&& fn, csizes_t<indices...>, size_t index, + vec_t<T, N>) const { return fn(std::get<indices>(this->args)(cinput, index, vec_t_for<Args, N>())...); } template <size_t... indices> - CMT_INLINE void begin_block_impl(size_t size, csizes_t<indices...>) + CMT_INLINE void begin_block_impl(cinput_t cinput, size_t size, csizes_t<indices...>) { - swallow{ (std::get<indices>(args).begin_block(size), 0)... }; + swallow{ (std::get<indices>(args).begin_block(cinput, size), 0)... }; } template <size_t... indices> - CMT_INLINE void end_block_impl(size_t size, csizes_t<indices...>) + CMT_INLINE void end_block_impl(cinput_t cinput, size_t size, csizes_t<indices...>) { - swallow{ (std::get<indices>(args).end_block(size), 0)... }; + swallow{ (std::get<indices>(args).end_block(cinput, size), 0)... }; } template <size_t... indices> - CMT_INLINE void begin_block_impl(size_t size, csizes_t<indices...>) const + CMT_INLINE void begin_block_impl(cinput_t cinput, size_t size, csizes_t<indices...>) const { - swallow{ (std::get<indices>(args).begin_block(size), 0)... }; + swallow{ (std::get<indices>(args).begin_block(cinput, size), 0)... }; } template <size_t... indices> - CMT_INLINE void end_block_impl(size_t size, csizes_t<indices...>) const + CMT_INLINE void end_block_impl(cinput_t cinput, size_t size, csizes_t<indices...>) const { - swallow{ (std::get<indices>(args).end_block(size), 0)... }; + swallow{ (std::get<indices>(args).end_block(cinput, size), 0)... }; } }; @@ -324,9 +337,9 @@ struct expression_function : expression<arg<Args>...> { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> x) const { - return this->call(fn, index, x); + return this->call(cinput, fn, index, x); } const Fn& get_fn() const noexcept { return fn; } @@ -376,7 +389,8 @@ CMT_INLINE internal::expression_function<Fn, NewArgs...> rebind( namespace internal { template <size_t width, typename OutputExpr, typename InputExpr> -CMT_INLINE void process_cycle(OutputExpr&& outfn, const InputExpr& fn, size_t& i, size_t end) +CMT_INLINE void process_cycle(coutput_t coutput, cinput_t cinput, OutputExpr&& outfn, const InputExpr& fn, + size_t& i, size_t end) { using Tin = value_type_of<InputExpr>; CMT_LOOP_NOUNROLL @@ -390,7 +404,8 @@ CMT_INLINE void process_cycle(OutputExpr&& outfn, const InputExpr& fn, size_t& i template <typename Tout, cpu_t c = cpu_t::native, size_t width = 0, typename OutputExpr, typename InputExpr, size_t groupsize = 1> CMT_INLINE size_t process(OutputExpr&& out, const InputExpr& in, size_t start = 0, - size_t size = infinite_size, csize_t<groupsize> = csize_t<groupsize>()) + size_t size = infinite_size, coutput_t coutput = nullptr, cinput_t cinput = nullptr, + csize_t<groupsize> = csize_t<groupsize>()) { static_assert(is_output_expression<OutputExpr>::value, "OutFn must be an expression"); static_assert(is_input_expression<InputExpr>::value, "Fn must be an expression"); @@ -399,8 +414,8 @@ CMT_INLINE size_t process(OutputExpr&& out, const InputExpr& in, size_t start = if (size == 0 || size == infinite_size) return size; const size_t end = start + size; - out.output_begin_block(size); - in.begin_block(size); + out.begin_block(coutput, size); + in.begin_block(cinput, size); #ifdef NDEBUG constexpr size_t w = width == 0 ? internal::get_vector_width<Tout, c>(2, 4) : width; @@ -409,11 +424,11 @@ CMT_INLINE size_t process(OutputExpr&& out, const InputExpr& in, size_t start = #endif size_t i = start; - internal::process_cycle<w>(std::forward<OutputExpr>(out), in, i, end); - internal::process_cycle<groupsize>(std::forward<OutputExpr>(out), in, i, end); + internal::process_cycle<w>(coutput, cinput, std::forward<OutputExpr>(out), in, i, end); + internal::process_cycle<groupsize>(coutput, cinput, std::forward<OutputExpr>(out), in, i, end); - in.end_block(size); - out.output_end_block(size); + in.end_block(cinput, size); + out.end_block(coutput, size); return size; } diff --git a/include/kfr/base/pointer.hpp b/include/kfr/base/pointer.hpp @@ -64,7 +64,7 @@ std::shared_ptr<expression_resource> make_resource(E&& e) std::allocate_shared<T>(allocator<T>(), std::move(e))); } -template <typename T, size_t maxwidth = maximum_expression_width()> +template <typename T, size_t maxwidth = maximum_expression_width(), bool enable_resource = true> struct expression_pointer : input_expression { using value_type = T; @@ -88,13 +88,13 @@ struct expression_pointer : input_expression vec<T, N> result = vec<T, N>(func(instance, index)); return result; } - CMT_INLINE void begin_block(size_t size) const + CMT_INLINE void begin_block(cinput_t, size_t size) const { using func_t = void (*)(void*, size_t); func_t func = reinterpret_cast<func_t>((*vtable)[0]); func(instance, size); } - CMT_INLINE void end_block(size_t size) const + CMT_INLINE void end_block(cinput_t, size_t size) const { using func_t = void (*)(void*, size_t); func_t func = reinterpret_cast<func_t>((*vtable)[1]); @@ -107,6 +107,47 @@ private: std::shared_ptr<expression_resource> resource; }; +template <typename T, size_t maxwidth> +struct expression_pointer<T, maxwidth, false> : input_expression +{ + using value_type = T; + + static_assert(is_poweroftwo(maxwidth), "N must be a power of two"); + expression_pointer() noexcept : instance(nullptr), vtable(nullptr) {} + expression_pointer(void* instance, const expression_vtable<T, maxwidth>* vtable) + : instance(instance), vtable(vtable) + { + } + template <size_t N> + CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + { + using func_t = simd<T, N> (*)(void*, size_t); + + static_assert(is_poweroftwo(N), "N must be a power of two"); + constexpr size_t findex = ilog2(N); + static_assert(N <= maxwidth, "N is greater than maxwidth"); + func_t func = reinterpret_cast<func_t>((*vtable)[2 + findex]); + vec<T, N> result = vec<T, N>(func(instance, index)); + return result; + } + CMT_INLINE void begin_block(cinput_t, size_t size) const + { + using func_t = void (*)(void*, size_t); + func_t func = reinterpret_cast<func_t>((*vtable)[0]); + func(instance, size); + } + CMT_INLINE void end_block(cinput_t, size_t size) const + { + using func_t = void (*)(void*, size_t); + func_t func = reinterpret_cast<func_t>((*vtable)[1]); + func(instance, size); + } + +private: + void* instance; + const expression_vtable<T, maxwidth>* vtable; +}; + namespace internal { template <typename T, size_t N, typename Fn, typename Ret = simd<T, N>, @@ -121,12 +162,12 @@ CMT_INLINE NonMemFn make_expression_func() template <typename Fn, typename NonMemFn = void (*)(void*, size_t)> CMT_INLINE NonMemFn make_expression_begin_block() { - return [](void* fn, size_t size) { reinterpret_cast<Fn*>(fn)->begin_block(size); }; + return [](void* fn, size_t size) { reinterpret_cast<Fn*>(fn)->begin_block(cinput, size); }; } template <typename Fn, typename NonMemFn = void (*)(void*, size_t)> CMT_INLINE NonMemFn make_expression_end_block() { - return [](void* fn, size_t size) { reinterpret_cast<Fn*>(fn)->end_block(size); }; + return [](void* fn, size_t size) { reinterpret_cast<Fn*>(fn)->end_block(cinput, size); }; } template <typename T, size_t maxwidth, typename E> diff --git a/include/kfr/base/types.hpp b/include/kfr/base/types.hpp @@ -172,22 +172,23 @@ inline datatype operator&(datatype x, datatype y) return static_cast<datatype>(static_cast<type>(x) | static_cast<type>(y)); } -enum class outputinput_t +constexpr size_t inout_context_size = 16; + +struct coutput_context { - output, - input + pconstvoid data[inout_context_size]; }; -template <outputinput_t p> -using coutputinput_t = cval_t<outputinput_t, p>; -template <outputinput_t p> -constexpr coutputinput_t<p> coutputinput{}; +struct cinput_context +{ + pconstvoid data[inout_context_size]; +}; -using coutput_t = coutputinput_t<outputinput_t::output>; -using cinput_t = coutputinput_t<outputinput_t::input>; +using coutput_t = const coutput_context*; +using cinput_t = const cinput_context*; -constexpr coutput_t coutput{}; -constexpr cinput_t cinput{}; +constexpr cinput_t cinput = nullptr; +constexpr coutput_t coutput = nullptr; template <typename T> constexpr datatype typeclass = std::is_floating_point<typename compound_type_traits<T>::subtype>::value diff --git a/include/kfr/base/univector.hpp b/include/kfr/base/univector.hpp @@ -44,6 +44,11 @@ struct univector; template <typename T, typename Class> struct univector_base : input_expression, output_expression { + using input_expression::begin_block; + using input_expression::end_block; + using output_expression::begin_block; + using output_expression::end_block; + template <typename U, size_t N> CMT_INLINE void operator()(coutput_t, size_t index, const vec<U, N>& value) { @@ -310,20 +315,20 @@ template <typename T, size_t Size1 = tag_dynamic_vector, size_t Size2 = tag_dyna using univector3d = univector<univector<univector<T, Size3>, Size2>, Size1>; template <cpu_t c = cpu_t::native, size_t Tag, typename T, typename Fn> -CMT_INLINE void process(univector<T, Tag>& vector, Fn&& fn) +CMT_INLINE size_t process(univector<T, Tag>& vector, Fn&& fn) { static_assert(is_input_expression<Fn>::value, "Fn must be an expression"); return process<T, c>(vector, std::forward<Fn>(fn), vector.size()); } template <cpu_t c = cpu_t::native, typename T, size_t Nsize, typename Fn> -CMT_INLINE void process(T (&dest)[Nsize], Fn&& fn) +CMT_INLINE size_t process(T (&dest)[Nsize], Fn&& fn) { static_assert(is_input_expression<Fn>::value, "Fn must be an expression"); return process<T, c>(univector<T, tag_array_ref>(dest), std::forward<Fn>(fn), Nsize); } template <cpu_t c = cpu_t::native, typename T, typename Fn> -CMT_INLINE void process(const array_ref<T>& vector, Fn&& fn) +CMT_INLINE size_t process(const array_ref<T>& vector, Fn&& fn) { static_assert(is_input_expression<Fn>::value, "Fn must be an expression"); return process<T, c>(univector<T, tag_array_ref>(vector), std::forward<Fn>(fn), vector.size()); diff --git a/include/kfr/cometa.hpp b/include/kfr/cometa.hpp @@ -46,7 +46,8 @@ char (&COUNTOF_REQUIRES_ARRAY_ARGUMENT(T (&)[N]))[N]; #define CMT_ARRAYSIZE(arr) sizeof(arr) / sizeof(arr[0]) #endif -using pvoid = void*; +using pvoid = void*; +using pconstvoid = const void*; template <typename...> using void_t = void; diff --git a/include/kfr/dsp/biquad.hpp b/include/kfr/dsp/biquad.hpp @@ -146,9 +146,9 @@ struct expression_biquads : public expression<E1> { } template <size_t width> - KFR_INTRIN vec<T, width> operator()(cinput_t, size_t index, vec_t<T, width> t) const + KFR_INTRIN vec<T, width> operator()(cinput_t cinput, size_t index, vec_t<T, width> t) const { - const vec<T, width> in = this->argument_first(index, t); + const vec<T, width> in = this->argument_first(cinput, index, t); vec<T, width> out; CMT_LOOP_UNROLL @@ -182,25 +182,25 @@ struct expression_biquads_zl : expression<E1> { } - CMT_INLINE void begin_block(size_t size) const + CMT_INLINE void begin_block(cinput_t cinput, size_t size) const { block_end = size; for (size_t i = 0; i < filters - 1; i++) { - const vec<T, 1> in = this->argument_first(i, vec_t<T, 1>()); + const vec<T, 1> in = this->argument_first(cinput, i, vec_t<T, 1>()); state.out = process(bq, state, insertleft(in[i], state.out)); } } - CMT_INLINE void end_block(size_t) const { state = saved_state; } + CMT_INLINE void end_block(cinput_t cinput, size_t) const { state = saved_state; } template <size_t width> - KFR_INTRIN vec<T, width> operator()(cinput_t, size_t index, vec_t<T, width> t) const + KFR_INTRIN vec<T, width> operator()(cinput_t cinput, size_t index, vec_t<T, width> t) const { index += filters - 1; vec<T, width> out; if (index + width <= block_end) { - const vec<T, width> in = this->argument_first(index, t); + const vec<T, width> in = this->argument_first(cinput, index, t); CMT_LOOP_UNROLL for (size_t i = 0; i < width; i++) @@ -225,7 +225,7 @@ struct expression_biquads_zl : expression<E1> size_t i = 0; for (; i < std::min(width, block_end - index); i++) { - const vec<T, 1> in = this->argument_first(index + i, vec_t<T, 1>()); + const vec<T, 1> in = this->argument_first(cinput, index + i, vec_t<T, 1>()); state.out = process(bq, state, insertleft(in[i], state.out)); out(i) = state.out[filters - 1]; } diff --git a/include/kfr/dsp/delay.hpp b/include/kfr/dsp/delay.hpp @@ -41,31 +41,31 @@ struct expression_delay : expression<E> using expression<E>::expression; template <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> operator()(cinput_t cinput, 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>()); + const vec<T, N> in = this->argument_first(cinput, index, vec_t<T, N>()); data.ringbuf_write(cursor, in); return out; } - vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const + vec<T, 1> operator()(cinput_t cinput, 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]; + const T in = this->argument_first(cinput, index, vec_t<T, 1>())[0]; data.ringbuf_write(cursor, in); return out; } template <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> operator()(cinput_t cinput, 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>()); + const vec<T, N> in = this->argument_first(cinput, index, vec_t<T, N>()); data.ringbuf_write(cursor, slice<N - delay, delay>(in)); return concat_and_slice<0, N>(out, in); } @@ -82,9 +82,9 @@ struct expression_delay<1, E> : expression<E> using expression<E>::expression; template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, 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> in = this->argument_first(cinput, index, vec_t<T, N>()); const vec<T, N> out = insertleft(data, in); data = in[N - 1]; return out; diff --git a/include/kfr/dsp/fir.hpp b/include/kfr/dsp/fir.hpp @@ -55,9 +55,9 @@ struct expression_short_fir : expression<E1> { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> x) const { - vec<T, N> in = this->argument_first(index, x); + vec<T, N> in = this->argument_first(cinput, index, x); vec<T, N> out = in * taps[0]; cfor(csize<1>, csize<tapcount>, @@ -78,10 +78,10 @@ struct expression_fir : expression<E1> { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> x) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> x) const { const size_t tapcount = taps.size(); - const vec<T, N> input = this->argument_first(index, x); + const vec<T, N> input = this->argument_first(cinput, index, x); vec<T, N> output; size_t cursor = delayline_cursor; diff --git a/include/kfr/dsp/sample_rate_conversion.hpp b/include/kfr/dsp/sample_rate_conversion.hpp @@ -215,17 +215,17 @@ struct expression_upsample<2, E> : expression<E> using T = value_type; template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N>) const { - const vec<T, N / 2> x = this->argument_first(index / 2, vec_t<T, N / 2>()); + const vec<T, N / 2> x = this->argument_first(cinput, index / 2, vec_t<T, N / 2>()); return interleave(x, zerovector(x)); } - vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const + vec<T, 1> operator()(cinput_t cinput, size_t index, vec_t<T, 1>) const { if (index & 1) return 0; else - return this->argument_first(index / 2, vec_t<T, 1>()); + return this->argument_first(cinput, index / 2, vec_t<T, 1>()); } }; @@ -237,31 +237,31 @@ struct expression_upsample<4, E> : expression<E> using T = value_type; template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N>) const { - const vec<T, N / 4> x = this->argument_first(index / 4, vec_t<T, N / 4>()); + const vec<T, N / 4> x = this->argument_first(cinput, index / 4, vec_t<T, N / 4>()); const vec<T, N / 2> xx = interleave(x, zerovector(x)); return interleave(xx, zerovector(xx)); } - vec<T, 2> operator()(cinput_t, size_t index, vec_t<T, 2>) const + vec<T, 2> operator()(cinput_t cinput, size_t index, vec_t<T, 2>) const { switch (index & 3) { case 0: - return interleave(this->argument_first(index / 4, vec_t<T, 1>()), zerovector<T, 1>()); + return interleave(this->argument_first(cinput, index / 4, vec_t<T, 1>()), zerovector<T, 1>()); case 3: - return interleave(zerovector<T, 1>(), this->argument_first(index / 4, vec_t<T, 1>())); + return interleave(zerovector<T, 1>(), this->argument_first(cinput, index / 4, vec_t<T, 1>())); default: return 0; } } template <typename T> - vec<T, 1> operator()(cinput_t, size_t index, vec_t<T, 1>) const + vec<T, 1> operator()(cinput_t cinput, size_t index, vec_t<T, 1>) const { if (index & 3) return 0; else - return this->argument_first(index / 4, vec_t<T, 1>()); + return this->argument_first(cinput, index / 4, vec_t<T, 1>()); } }; @@ -273,9 +273,9 @@ struct expression_downsample<2, offset, E> : expression<E> using T = value_type; template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N>) const { - const vec<T, N* 2> x = this->argument_first(index * 2, vec_t<T, N * 2>()); + const vec<T, N* 2> x = this->argument_first(cinput, index * 2, vec_t<T, N * 2>()); return shufflevector<N, internal::shuffle_index<offset, 2>>(x); } }; @@ -288,9 +288,9 @@ struct expression_downsample<4, offset, E> : expression<E> using T = value_type; template <size_t N> - vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N>) const + vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N>) const { - const vec<T, N* 4> x = this->argument_first(index * 4, vec_t<T, N * 4>()); + const vec<T, N* 4> x = this->argument_first(cinput, index * 4, vec_t<T, N * 4>()); return shufflevector<N, internal::shuffle_index<offset, 4>>(x); } }; diff --git a/include/kfr/dsp/window.hpp b/include/kfr/dsp/window.hpp @@ -147,7 +147,7 @@ struct expression_triangular : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return 1 - abs(linspace(cinput, index, y)); } @@ -168,7 +168,7 @@ struct expression_bartlett : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return 1 - abs(linspace(cinput, index, y)); } @@ -189,7 +189,7 @@ struct expression_cosine : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return sin(c_pi<T> * linspace(cinput, index, y)); } @@ -210,7 +210,7 @@ struct expression_hann : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return T(0.5) * (T(1) - cos(c_pi<T, 2> * linspace(cinput, index, y))); } @@ -231,7 +231,7 @@ struct expression_bartlett_hann : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> xx = linspace(cinput, index, y); return T(0.62) - T(0.48) * abs(xx - T(0.5)) + T(0.38) * cos(c_pi<T, 2> * (xx - T(0.5))); @@ -253,7 +253,7 @@ struct expression_hamming : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return alpha - (1.0 - alpha) * (cos(c_pi<T, 2> * linspace(cinput, index, y))); } @@ -275,7 +275,7 @@ struct expression_bohman : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> n = abs(linspace(cinput, index, y)); return (T(1) - n) * cos(c_pi<T> * n) + (T(1) / c_pi<T>)*sin(c_pi<T> * n); @@ -297,7 +297,7 @@ struct expression_blackman : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> n = linspace(cinput, index, y); return a0 - a1 * cos(c_pi<T, 2> * n) + a2 * cos(c_pi<T, 4> * n); @@ -320,7 +320,7 @@ struct expression_blackman_harris : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> n = linspace(cinput, index, y) * c_pi<T, 2>; return T(0.35875) - T(0.48829) * cos(n) + T(0.14128) * cos(2 * n) - T(0.01168) * cos(3 * n); @@ -343,7 +343,7 @@ struct expression_kaiser : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return modzerobessel(beta * sqrt(1 - sqr(linspace(cinput, index, y)))) * m; } @@ -366,7 +366,7 @@ struct expression_flattop : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { const vec<T, N> n = linspace(cinput, index, y) * c_pi<T, 2>; constexpr T a0 = 1; @@ -393,7 +393,7 @@ struct expression_gaussian : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return exp(-0.5 * sqr(alpha * linspace(cinput, index, y))); } @@ -415,7 +415,7 @@ struct expression_lanczos : input_expression { } template <size_t N> - CMT_INLINE vec<T, N> operator()(cinput_t, size_t index, vec_t<T, N> y) const + CMT_INLINE vec<T, N> operator()(cinput_t cinput, size_t index, vec_t<T, N> y) const { return sinc(linspace(cinput, index, y)); } diff --git a/include/kfr/io/audiofile.hpp b/include/kfr/io/audiofile.hpp @@ -44,7 +44,8 @@ void write_interleaved(E1&& dest, const univector2d<Tin, Tag1, Tag2>& src) } else if (channels == 2) { - process<Tout>(std::forward<E1>(dest), pack(src[0], src[1]), 0, infinite_size, csize<2>); + process<Tout>(std::forward<E1>(dest), pack(src[0], src[1]), 0, infinite_size, nullptr, nullptr, + csize<2>); } else { diff --git a/tests/intrinsic_test.cpp b/tests/intrinsic_test.cpp @@ -143,7 +143,7 @@ TEST(intrin_abs) testo::matrix(named("type") = signed_types, named("value") = std::vector<int>{ -1, 0, +1 }, [](auto type, int value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value); CHECK(kfr::abs(x) == apply([](auto x) { return ref_abs(x); }, x)); }); @@ -169,7 +169,7 @@ TEST(intrin_sqrt) CHECK(kfr::sqrt(make_vector(-9)) == make_vector<fbase>(qnan)); testo::matrix(named("type") = float_types, named("value") = std::vector<int>{ 0, 2, 65536 }, [](auto type, int value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value); CHECK(kfr::sqrt(x) == apply([](auto x) { return std::sqrt(x); }, x)); }); @@ -196,7 +196,7 @@ TEST(intrin_round) testo::matrix(named("type") = float_types, named("value") = std::vector<fbase>{ -1.51, -1.49, 0.0, +1.49, +1.51 }, [](auto type, fbase value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value); CHECK(kfr::floor(x) == apply([](auto x) { return std::floor(x); }, x)); CHECK(kfr::ceil(x) == apply([](auto x) { return std::ceil(x); }, x)); @@ -226,7 +226,7 @@ TEST(intrin_min_max) testo::matrix(named("type") = float_types, named("value") = std::vector<std::pair<fbase, fbase>>{ { -100, +100 }, { infinity, 0.0 } }, [](auto type, std::pair<fbase, fbase> value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value.first); const T y(value.second); CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y)); @@ -239,7 +239,7 @@ TEST(intrin_min_max) testo::matrix(named("type") = signed_types, named("value") = std::vector<std::pair<int, int>>{ { -100, +100 } }, [](auto type, std::pair<int, int> value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value.first); const T y(value.second); CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y)); @@ -252,7 +252,7 @@ TEST(intrin_min_max) testo::matrix(named("type") = unsigned_types, named("value") = std::vector<std::pair<unsigned, unsigned>>{ { 0, +200 } }, [](auto type, std::pair<unsigned, unsigned> value) { - using T = type_of<decltype(type)>; + using T = type_of<decltype(type)>; const T x(value.first); const T y(value.second); CHECK(kfr::min(x, y) == apply([](auto x, auto y) { return std::min(x, y); }, x, y));