#pragma once #include "type_checks.h" #include "typedefs.h" namespace fratio { /*! \brief Transform an analog signal to a discrete signal and vice versa. * * \see https://en.wikipedia.org/wiki/Bilinear_transform * \tparam T Floating (complex) types. */ template struct BilinearTransform { using SubType = internal::complex_sub_type_t; /*!< Sub-type of the complex if T is complex, T otherwise */ static_assert(std::is_floating_point::value, "This struct can only accept floating point types (real and complex)."); /*! \brief Transformation from analog to discrete. * \param fs Sampling frequency. * \param sPlanePole Analog data. * \param[out] zPlanePole Resulting discrete data. */ static void SToZ(SubType fs, const T& sPlanePole, T& zPlanePole); /*! \brief Transformation from analog to discrete. * \param fs Sampling frequency. * \param sPlanePole Analog signal. * \param[out] zPlanePole Resulting discrete signal. */ static void SToZ(SubType fs, const vectX_t& sPlanePoles, Eigen::Ref>& zPlanePoles); // Can be optimized maybe /*! \brief Transformation from discrete to analog. * \param fs Sampling frequency. * \param zPlanePole Discrete data. * \param[out] sPlanePole Resulting analog data. */ static void ZToS(SubType fs, const T& zPlanePole, T& sPlanePole); /*! \brief Transformation from discrete to analog. * \param fs Sampling frequency. * \param zPlanePole Discrete signal. * \param[out] sPlanePole Resulting analog signal. */ static void ZToS(SubType fs, const vectX_t& zPlanePoles, Eigen::Ref>& sPlanePoles); // Can be optimized maybe }; template void BilinearTransform::SToZ(SubType fs, const T& sPlanePole, T& zPlanePole) { T scalePole = sPlanePole / (2 * fs); zPlanePole = (T(1) + scalePole) / (T(1) - scalePole); } template void BilinearTransform::SToZ(SubType fs, const vectX_t& sPlanePoles, Eigen::Ref>& zPlanePoles) { assert(sPlanePoles.size() == zPlanePoles.size()); for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k) SToZ(fs, sPlanePoles(k), zPlanePoles(k)); } template void BilinearTransform::ZToS(SubType fs, const T& zPlanePole, T& sPlanePole) { T invPole = T(1) / zPlanePole; sPlanePole = 2 * fs * (T(1) - invPole) / (T(1) + invPole); } template void BilinearTransform::ZToS(SubType fs, const vectX_t& zPlanePoles, Eigen::Ref>& sPlanePoles) { assert(zPlanePoles.size() == sPlanePoles.size()); for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k) ZToS(fs, zPlanePoles(k), sPlanePoles(k)); } } // namespace fratio