/* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * * This file is part of PortaPack. * * This program 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 2, or (at your option) * any later version. * * This program 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 this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef __DSP_DECIMATE_H__ #define __DSP_DECIMATE_H__ #include #include #include #include #include "utility.hpp" #include "dsp_types.hpp" #include "simd.hpp" namespace dsp { namespace decimate { class Complex8DecimateBy2CIC3 { public: buffer_c16_t execute( const buffer_c8_t& src, const buffer_c16_t& dst ); private: uint32_t _i1_i0 { 0 }; uint32_t _q1_q0 { 0 }; }; class TranslateByFSOver4AndDecimateBy2CIC3 { public: buffer_c16_t execute( const buffer_c8_t& src, const buffer_c16_t& dst ); private: uint32_t _q1_i0 { 0 }; uint32_t _q0_i1 { 0 }; }; class DecimateBy2CIC3 { public: buffer_c16_t execute( const buffer_c16_t& src, const buffer_c16_t& dst ); private: uint32_t _iq0 { 0 }; uint32_t _iq1 { 0 }; }; class FIR64AndDecimateBy2Real { public: static constexpr size_t taps_count = 64; void configure( const std::array& taps ); buffer_s16_t execute( const buffer_s16_t& src, const buffer_s16_t& dst ); private: std::array z; std::array taps; }; class FIRC8xR16x24FS4Decim4 { public: static constexpr size_t taps_count = 24; static constexpr size_t decimation_factor = 4; using sample_t = complex8_t; using tap_t = int16_t; enum class Shift : bool { Down = true, Up = false }; FIRC8xR16x24FS4Decim4(); void configure( const std::array& taps, const int32_t scale, const Shift shift = Shift::Down ); buffer_c16_t execute( const buffer_c8_t& src, const buffer_c16_t& dst ); private: std::array z_; std::array taps_; int32_t output_scale = 0; }; class FIRC8xR16x24FS4Decim8 { public: static constexpr size_t taps_count = 24; static constexpr size_t decimation_factor = 8; using sample_t = complex8_t; using tap_t = int16_t; enum class Shift : bool { Down = true, Up = false }; FIRC8xR16x24FS4Decim8(); void configure( const std::array& taps, const int32_t scale, const Shift shift = Shift::Down ); buffer_c16_t execute( const buffer_c8_t& src, const buffer_c16_t& dst ); private: std::array z_; std::array taps_; int32_t output_scale = 0; }; class FIRC16xR16x16Decim2 { public: static constexpr size_t taps_count = 16; static constexpr size_t decimation_factor = 2; using sample_t = complex16_t; using tap_t = int16_t; FIRC16xR16x16Decim2(); void configure( const std::array& taps, const int32_t scale ); buffer_c16_t execute( const buffer_c16_t& src, const buffer_c16_t& dst ); private: std::array z_; std::array taps_; int32_t output_scale = 0; }; class FIRC16xR16x32Decim8 { public: static constexpr size_t taps_count = 32; static constexpr size_t decimation_factor = 8; using sample_t = complex16_t; using tap_t = int16_t; FIRC16xR16x32Decim8(); void configure( const std::array& taps, const int32_t scale ); buffer_c16_t execute( const buffer_c16_t& src, const buffer_c16_t& dst ); private: std::array z_; std::array taps_; int32_t output_scale = 0; }; class FIRAndDecimateComplex { public: using sample_t = complex16_t; using tap_t = complex16_t; using taps_t = tap_t[]; /* NOTE! Current code makes an assumption that block of samples to be * processed will be a multiple of the taps_count. */ FIRAndDecimateComplex( ) : taps_count_ { 0 }, decimation_factor_ { 1 } { } template void configure( const T& taps, const size_t decimation_factor ) { samples_ = std::make_unique(taps.size()); taps_reversed_ = std::make_unique(taps.size()); taps_count_ = taps.size(); decimation_factor_ = decimation_factor; std::reverse_copy(taps.cbegin(), taps.cend(), &taps_reversed_[0]); } buffer_c16_t execute( const buffer_c16_t& src, const buffer_c16_t& dst ); private: using samples_t = sample_t[]; std::unique_ptr samples_; std::unique_ptr taps_reversed_; size_t taps_count_; size_t decimation_factor_; }; class DecimateBy2CIC4Real { public: buffer_s16_t execute( const buffer_s16_t& src, const buffer_s16_t& dst ); private: int16_t z[5]; }; } /* namespace decimate */ } /* namespace dsp */ #endif/*__DSP_DECIMATE_H__*/