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 9d6eeb6c78e3163d8db5acf913001fd0f889b648
parent 0bb318a6a0a8caffa4ff1e38d2a0956c5026df87
Author: d.levin256@gmail.com <d.levin256@gmail.com>
Date:   Tue, 18 Dec 2018 11:39:54 +0000

univector_type

Diffstat:
Minclude/kfr/base/conversion.hpp | 6+++---
Minclude/kfr/base/filter.hpp | 8++++----
Minclude/kfr/base/reduce.hpp | 1+
Minclude/kfr/base/univector.hpp | 25++++++++++++++++---------
Minclude/kfr/dft/cache.hpp | 8++++----
Minclude/kfr/dft/convolution.hpp | 6+++---
Minclude/kfr/dft/fft.hpp | 18+++++++++---------
Minclude/kfr/dsp/ebu.hpp | 2+-
Minclude/kfr/dsp/fir.hpp | 2+-
Minclude/kfr/dsp/fir_design.hpp | 8++++----
Minclude/kfr/dsp/sample_rate_conversion.hpp | 2+-
Minclude/kfr/io/tostring.hpp | 2+-
12 files changed, 48 insertions(+), 40 deletions(-)

diff --git a/include/kfr/base/conversion.hpp b/include/kfr/base/conversion.hpp @@ -192,7 +192,7 @@ void deinterleave(Tout* out[], const Tin* in, size_t channels, size_t size) } /// @brief Deinterleaves and converts audio samples -template <typename Tout, size_t Tag1, size_t Tag2, typename Tin, size_t Tag3> +template <typename Tout, univector_tag Tag1, univector_tag Tag2, typename Tin, univector_tag Tag3> void deinterleave(univector2d<Tout, Tag1, Tag2>& out, const univector<Tin, Tag3>& in) { if (in.empty() || out.empty()) @@ -218,7 +218,7 @@ void interleave(Tout* out, const Tin* in[], size_t channels, size_t size) } /// @brief Interleaves and converts audio samples -template <typename Tout, size_t Tag1, typename Tin, size_t Tag2, size_t Tag3> +template <typename Tout, univector_tag Tag1, typename Tin, univector_tag Tag2, univector_tag Tag3> void interleave(univector<Tout, Tag1>& out, const univector2d<Tin, Tag2, Tag3>& in) { if (in.empty() || out.empty()) @@ -232,7 +232,7 @@ void interleave(univector<Tout, Tag1>& out, const univector2d<Tin, Tag2, Tag3>& } /// @brief Interleaves and converts audio samples -template <typename Tin, size_t Tag1, size_t Tag2> +template <typename Tin, univector_tag Tag1, univector_tag Tag2> univector<Tin> interleave(const univector2d<Tin, Tag1, Tag2>& in) { if (in.empty()) diff --git a/include/kfr/base/filter.hpp b/include/kfr/base/filter.hpp @@ -58,14 +58,14 @@ public: } /// @brief Applies filter to a univector - template <size_t Tag> + template <univector_tag Tag> void apply(univector<T, Tag>& buffer) { process_buffer(buffer.data(), buffer.data(), buffer.size()); } /// @brief Applies filter to a univector and write the result to another univector - template <size_t Tag1, size_t Tag2> + template <univector_tag Tag1, univector_tag Tag2> void apply(univector<T, Tag1>& dest, const univector<T, Tag2>& src) { process_buffer(dest.data(), src.data(), std::min(dest.size(), src.size())); @@ -75,7 +75,7 @@ public: void apply(T* dest, const T* src, size_t size) { process_buffer(dest, src, size); } - template <size_t Tag> + template <univector_tag Tag> void apply(univector<T, Tag>& dest, const expression_pointer<T>& src) { process_expression(dest.data(), src, size_min(dest.size(), src.size())); @@ -86,7 +86,7 @@ public: process_expression(dest, src, size_min(size, src.size())); } - template <size_t Tag, typename Expr, KFR_ENABLE_IF(is_input_expression<Expr>::value)> + template <univector_tag Tag, typename Expr, KFR_ENABLE_IF(is_input_expression<Expr>::value)> void apply(univector<T, Tag>& dest, const Expr& src) { process_expression(dest.data(), to_pointer(src), size_min(dest.size(), src.size())); diff --git a/include/kfr/base/reduce.hpp b/include/kfr/base/reduce.hpp @@ -29,6 +29,7 @@ #include "function.hpp" #include "min_max.hpp" #include "operators.hpp" +#include "horizontal.hpp" #include "vec.hpp" namespace kfr diff --git a/include/kfr/base/univector.hpp b/include/kfr/base/univector.hpp @@ -38,8 +38,13 @@ CMT_PRAGMA_MSVC(warning(disable : 4324)) namespace kfr { -constexpr size_t tag_array_ref = 0; -constexpr size_t tag_dynamic_vector = max_size_t; +using univector_tag = size_t; + +enum : size_t +{ + tag_array_ref = 0, + tag_dynamic_vector = max_size_t, +}; /** * @brief Class that represent data in KFR. Many KFR functions can take this class as an argument. @@ -58,7 +63,7 @@ constexpr size_t tag_dynamic_vector = max_size_t; * some_function(make_univector(buffer, size)); * @endcode */ -template <typename T, size_t Size = tag_dynamic_vector> +template <typename T, univector_tag Tag = tag_dynamic_vector> struct univector; /// @brief Base class for all univector specializations. @@ -282,19 +287,21 @@ struct univector<T, tag_array_ref> : array_ref<T>, univector_base<T, univector<T constexpr univector(const array_ref<T>& other) : array_ref<T>(other) {} constexpr univector(array_ref<T>&& other) : array_ref<T>(std::move(other)) {} - template <size_t Tag> + template <univector_tag Tag> constexpr univector(const univector<T, Tag>& other) : array_ref<T>(other.data(), other.size()) { } - template <size_t Tag> + template <univector_tag Tag> constexpr univector(univector<T, Tag>& other) : array_ref<T>(other.data(), other.size()) { } - template <typename U, size_t Tag, KFR_ENABLE_IF(is_same<remove_const<T>, U>::value&& is_const<T>::value)> + template <typename U, univector_tag Tag, + KFR_ENABLE_IF(is_same<remove_const<T>, U>::value&& is_const<T>::value)> constexpr univector(const univector<U, Tag>& other) : array_ref<T>(other.data(), other.size()) { } - template <typename U, size_t Tag, KFR_ENABLE_IF(is_same<remove_const<T>, U>::value&& is_const<T>::value)> + template <typename U, univector_tag Tag, + KFR_ENABLE_IF(is_same<remove_const<T>, U>::value&& is_const<T>::value)> constexpr univector(univector<U, Tag>& other) : array_ref<T>(other.data(), other.size()) { } @@ -421,7 +428,7 @@ struct lockfree_ring_buffer return tail.load(std::memory_order_relaxed) - front.load(std::memory_order_relaxed); } - template <size_t Tag> + template <univector_tag Tag> size_t try_enqueue(const T* source, size_t size, univector<T, Tag>& buffer, bool partial = false) { const size_t cur_tail = tail.load(std::memory_order_relaxed); @@ -445,7 +452,7 @@ struct lockfree_ring_buffer return size; } - template <size_t Tag> + template <univector_tag Tag> size_t try_dequeue(T* dest, size_t size, const univector<T, Tag>& buffer, bool partial = false) { const size_t cur_front = front.load(std::memory_order_relaxed); diff --git a/include/kfr/dft/cache.hpp b/include/kfr/dft/cache.hpp @@ -124,7 +124,7 @@ private: using dft_cache = dft_cache_impl<>; /// @brief Performs Direct DFT using cached plan -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> univector<complex<T>> dft(const univector<complex<T>, Tag>& input) { dft_plan_ptr<T> dft = dft_cache::instance().get(ctype_t<T>(), input.size()); @@ -135,7 +135,7 @@ univector<complex<T>> dft(const univector<complex<T>, Tag>& input) } /// @brief Performs Inverse DFT using cached plan -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> univector<complex<T>> idft(const univector<complex<T>, Tag>& input) { dft_plan_ptr<T> dft = dft_cache::instance().get(ctype_t<T>(), input.size()); @@ -146,7 +146,7 @@ univector<complex<T>> idft(const univector<complex<T>, Tag>& input) } /// @brief Performs Real Direct DFT using cached plan -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> univector<complex<T>> realdft(const univector<T, Tag>& input) { dft_plan_real_ptr<T> dft = dft_cache::instance().getreal(ctype_t<T>(), input.size()); @@ -157,7 +157,7 @@ univector<complex<T>> realdft(const univector<T, Tag>& input) } /// @brief Permorms Real Inverse DFT using cached plan -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> univector<T> irealdft(const univector<complex<T>, Tag>& input) { dft_plan_real_ptr<T> dft = dft_cache::instance().getreal(ctype_t<T>(), (input.size() - 1) * 2); diff --git a/include/kfr/dft/convolution.hpp b/include/kfr/dft/convolution.hpp @@ -54,21 +54,21 @@ univector<T> autocorrelate(const univector_ref<const T>& src1); } // namespace internal /// @brief Convolution -template <typename T, size_t Tag1, size_t Tag2> +template <typename T, univector_tag Tag1, univector_tag Tag2> univector<T> convolve(const univector<T, Tag1>& src1, const univector<T, Tag2>& src2) { return internal::convolve(src1.slice(), src2.slice()); } /// @brief Correlation -template <typename T, size_t Tag1, size_t Tag2> +template <typename T, univector_tag Tag1, univector_tag Tag2> univector<T> correlate(const univector<T, Tag1>& src1, const univector<T, Tag2>& src2) { return internal::correlate(src1.slice(), src2.slice()); } /// @brief Auto-correlation -template <typename T, size_t Tag1> +template <typename T, univector_tag Tag1> univector<T> autocorrelate(const univector<T, Tag1>& src) { return internal::autocorrelate(src.slice()); diff --git a/include/kfr/dft/fft.hpp b/include/kfr/dft/fft.hpp @@ -90,7 +90,7 @@ struct dft_plan execute_dft(inv, out, in, temp); } - template <size_t Tag1, size_t Tag2, size_t Tag3> + template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> KFR_INTRIN void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in, univector<u8, Tag3>& temp, bool inverse = false) const { @@ -99,7 +99,7 @@ struct dft_plan else execute_dft(cfalse, out.data(), in.data(), temp.data()); } - template <bool inverse, size_t Tag1, size_t Tag2, size_t Tag3> + template <bool inverse, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> KFR_INTRIN void execute(univector<complex<T>, Tag1>& out, const univector<complex<T>, Tag2>& in, univector<u8, Tag3>& temp, cbool_t<inverse> inv) const { @@ -147,11 +147,11 @@ struct dft_plan_real : dft_plan<T> template <bool inverse> void execute(complex<T>*, const complex<T>*, u8*, cbool_t<inverse>) const = delete; - template <size_t Tag1, size_t Tag2, size_t Tag3> + template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> void execute(univector<complex<T>, Tag1>&, const univector<complex<T>, Tag2>&, univector<u8, Tag3>&, bool = false) const = delete; - template <bool inverse, size_t Tag1, size_t Tag2, size_t Tag3> + template <bool inverse, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> void execute(univector<complex<T>, Tag1>&, const univector<complex<T>, Tag2>&, univector<u8, Tag3>&, cbool_t<inverse>) const = delete; @@ -169,14 +169,14 @@ struct dft_plan_real : dft_plan<T> this->execute_dft(ctrue, outdata, outdata, temp); } - template <size_t Tag1, size_t Tag2, size_t Tag3> + template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> KFR_INTRIN void execute(univector<complex<T>, Tag1>& out, const univector<T, Tag2>& in, univector<u8, Tag3>& temp, dft_pack_format fmt = dft_pack_format::CCs) const { this->execute_dft(cfalse, out.data(), ptr_cast<complex<T>>(in.data()), temp.data()); to_fmt(out.data(), fmt); } - template <size_t Tag1, size_t Tag2, size_t Tag3> + template <univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> KFR_INTRIN void execute(univector<T, Tag1>& out, const univector<complex<T>, Tag2>& in, univector<u8, Tag3>& temp, dft_pack_format fmt = dft_pack_format::CCs) const { @@ -192,7 +192,7 @@ private: void from_fmt(complex<T>* out, const complex<T>* in, dft_pack_format fmt) const; }; -template <typename T, size_t Tag1, size_t Tag2, size_t Tag3> +template <typename T, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> void fft_multiply(univector<complex<T>, Tag1>& dest, const univector<complex<T>, Tag2>& src1, const univector<complex<T>, Tag3>& src2, dft_pack_format fmt = dft_pack_format::CCs) { @@ -204,7 +204,7 @@ void fft_multiply(univector<complex<T>, Tag1>& dest, const univector<complex<T>, dest[0] = f0; } -template <typename T, size_t Tag1, size_t Tag2, size_t Tag3> +template <typename T, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3> void fft_multiply_accumulate(univector<complex<T>, Tag1>& dest, const univector<complex<T>, Tag2>& src1, const univector<complex<T>, Tag3>& src2, dft_pack_format fmt = dft_pack_format::CCs) @@ -217,7 +217,7 @@ void fft_multiply_accumulate(univector<complex<T>, Tag1>& dest, const univector< if (fmt == dft_pack_format::Perm) dest[0] = f0; } -template <typename T, size_t Tag1, size_t Tag2, size_t Tag3, size_t Tag4> +template <typename T, univector_tag Tag1, univector_tag Tag2, univector_tag Tag3, univector_tag Tag4> void fft_multiply_accumulate(univector<complex<T>, Tag1>& dest, const univector<complex<T>, Tag2>& src1, const univector<complex<T>, Tag3>& src2, const univector<complex<T>, Tag4>& src3, dft_pack_format fmt = dft_pack_format::CCs) diff --git a/include/kfr/dsp/ebu.hpp b/include/kfr/dsp/ebu.hpp @@ -277,7 +277,7 @@ public: process_packet<tag_array_ref>(source); } - template <size_t Tag> + template <univector_tag Tag> void process_packet(const std::vector<univector<T, Tag>>& source) { T momentary = 0; diff --git a/include/kfr/dsp/fir.hpp b/include/kfr/dsp/fir.hpp @@ -153,7 +153,7 @@ struct expression_fir : expression_base<E1> * @param e1 an input expression * @param taps coefficients for the FIR filter */ -template <typename T, typename E1, size_t Tag> +template <typename T, typename E1, univector_tag Tag> CMT_INLINE internal::expression_fir<T, value_type_of<E1>, E1> fir(E1&& e1, const univector<T, Tag>& taps) { return internal::expression_fir<T, value_type_of<E1>, E1>(std::forward<E1>(e1), taps.ref()); diff --git a/include/kfr/dsp/fir_design.hpp b/include/kfr/dsp/fir_design.hpp @@ -127,7 +127,7 @@ KFR_I_FN(fir_bandstop) * @param window pointer to a window function * @param normalize true for normalized coefficients */ -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> CMT_INLINE void fir_lowpass(univector<T, Tag>& taps, identity<T> cutoff, const expression_pointer<T>& window, bool normalize = true) { @@ -141,7 +141,7 @@ CMT_INLINE void fir_lowpass(univector<T, Tag>& taps, identity<T> cutoff, const e * @param window pointer to a window function * @param normalize true for normalized coefficients */ -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> CMT_INLINE void fir_highpass(univector<T, Tag>& taps, identity<T> cutoff, const expression_pointer<T>& window, bool normalize = true) { @@ -156,7 +156,7 @@ CMT_INLINE void fir_highpass(univector<T, Tag>& taps, identity<T> cutoff, const * @param window pointer to a window function * @param normalize true for normalized coefficients */ -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> CMT_INLINE void fir_bandpass(univector<T, Tag>& taps, identity<T> frequency1, identity<T> frequency2, const expression_pointer<T>& window, bool normalize = true) { @@ -171,7 +171,7 @@ CMT_INLINE void fir_bandpass(univector<T, Tag>& taps, identity<T> frequency1, id * @param window pointer to a window function * @param normalize true for normalized coefficients */ -template <typename T, size_t Tag> +template <typename T, univector_tag Tag> CMT_INLINE void fir_bandstop(univector<T, Tag>& taps, identity<T> frequency1, identity<T> frequency2, const expression_pointer<T>& window, bool normalize = true) { diff --git a/include/kfr/dsp/sample_rate_conversion.hpp b/include/kfr/dsp/sample_rate_conversion.hpp @@ -144,7 +144,7 @@ struct sample_rate_converter /// @brief Writes output.size() samples to output reading at most input.size(), then consuming zeros as /// input. /// @returns Number of processed input samples (may be less than input.size()). - template <size_t Tag> + template <univector_tag Tag> size_t process(univector<T, Tag>& output, univector_ref<const T> input) { const itype required_input_size = input_size_for_output(output.size()); diff --git a/include/kfr/io/tostring.hpp b/include/kfr/io/tostring.hpp @@ -148,7 +148,7 @@ struct representation<kfr::mask<T, N>> } }; -template <typename T, size_t Tag> +template <typename T, kfr::univector_tag Tag> struct representation<kfr::univector<T, Tag>> { using type = std::string;