#ifndef _INTERPOLATION_UPSAMPLER_HPP_ #define _INTERPOLATION_UPSAMPLER_HPP_ #pragma once #include #include namespace Radio { namespace Interpolation { // -------------------------------------------------------------- // Complex FIR-based UpSampler // -------------------------------------------------------------- class UpSampler { public: UpSampler() : m_pFir(nullptr) , m_pCoeff(nullptr) , m_L(0) { } ~UpSampler() { if (m_pFir) delete [] m_pFir; if (m_pCoeff) delete [] m_pCoeff; } void init(uint32_t L, RealScalar const *coeff, uint32_t N) { uint32_t i, j; uint32_t stage_N; uint32_t stage; if (m_pFir) delete [] m_pFir; if (m_pCoeff) delete [] m_pCoeff; m_pFir = new FirComplex[L]; m_pCoeff = new RVec[L]; for (stage=0; stage < L; stage++) { stage_N = 0; for (i=L-stage-1; i < N; i += L) { stage_N++; } m_pFir[stage].setNumTaps(stage_N); m_pCoeff[stage].resize(stage_N); j=0; for (i=L-stage-1; i < N; i += L) { if (coeff) { m_pCoeff[stage][j++] = coeff[i]; } } } m_L = L; } uint32_t process(CVec &dst, CVec const &src, uint32_t len) { uint32_t i; uint32_t j; uint32_t currStage; j = 0; for (i=0; i < len; i++) { for (currStage=0; currStage < m_L; currStage++) { m_pFir[currStage].feed(src[i]); dst[m_L-1-currStage+j] = m_pFir[currStage].processReal(m_pCoeff[currStage]); } j += m_L; } return j; } private: FirComplex *m_pFir; RVec *m_pCoeff; uint32_t m_L; }; } // Radio::Interpolation } // ::Radio #endif // _INTERPOLATION_UPSAMPLER_HPP_