kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

biquad.cpp (6081B)


      1 /**
      2  * KFR (https://www.kfrlib.com)
      3  * Copyright (C) 2016-2023 Dan Cazarin
      4  * See LICENSE.txt for details
      5  */
      6 
      7 #include <kfr/base/reduce.hpp>
      8 #include <kfr/base/simd_expressions.hpp>
      9 #include <kfr/base/univector.hpp>
     10 #include <kfr/dsp/biquad.hpp>
     11 #include <kfr/dsp/biquad_design.hpp>
     12 #include <kfr/dsp/special.hpp>
     13 
     14 CMT_PRAGMA_MSVC(warning(push))
     15 CMT_PRAGMA_MSVC(warning(disable : 4305))
     16 
     17 namespace kfr
     18 {
     19 inline namespace CMT_ARCH_NAME
     20 {
     21 
     22 template <typename T, typename... Ts, univector_tag Tag>
     23 inline const univector<T, Tag>& choose_array(const univector<T, Tag>& array, const univector<Ts, Tag>&...)
     24 {
     25     return array;
     26 }
     27 
     28 template <typename T, typename T2, typename... Ts, univector_tag Tag, KFR_ENABLE_IF(!std::is_same_v<T, T2>)>
     29 inline const univector<T, Tag>& choose_array(const univector<T2, Tag>&, const univector<Ts, Tag>&... arrays)
     30 {
     31     return choose_array<T>(arrays...);
     32 }
     33 
     34 TEST(biquad_lowpass1)
     35 {
     36     testo::matrix(named("type") = ctypes_t<float, double>{},
     37                   [](auto type)
     38                   {
     39                       using T = typename decltype(type)::type;
     40 
     41                       const biquad_section<T> bq = biquad_lowpass<T>(0.1, 0.7);
     42 
     43                       constexpr size_t size = 32;
     44 
     45                       const univector<float, size> test_vector_f32{
     46                           +0x8.9bce2p-7,  +0xd.8383ep-6,  +0x8.f908dp-5,  +0xe.edc21p-6,  +0x9.ae104p-6,
     47                           +0x9.dcc24p-7,  +0xd.50584p-9,  -0xf.2668p-13,  -0xd.09ca1p-10, -0xe.15995p-10,
     48                           -0xa.b90d2p-10, -0xc.edea4p-11, -0xb.f14eap-12, -0xc.2cb44p-14, +0xb.4a4dep-15,
     49                           +0xb.685dap-14, +0xa.b181fp-14, +0xf.0cb2bp-15, +0x8.695d6p-15, +0xd.bedd4p-17,
     50                           +0xf.5474p-20,  -0xd.bb266p-19, -0x9.63ca1p-18, -0xf.ca567p-19, -0xa.5231p-19,
     51                           -0xa.9e934p-20, -0xe.ab52p-22,  +0xa.3c4cp-26,  +0xd.721ffp-23, +0xe.ccc1ap-23,
     52                           +0xb.5f248p-23, +0xd.d2c9ap-24,
     53                       };
     54 
     55                       const univector<double, size> test_vector_f64{
     56                           +0x8.9bce2bf3663e8p-7,  +0xd.8384010fdf1dp-6,   +0x8.f908e7a36df6p-5,
     57                           +0xe.edc2332a6d0bp-6,   +0x9.ae104af1da9ap-6,   +0x9.dcc235ef68e7p-7,
     58                           +0xd.5057ee425e05p-9,   -0xf.266e42a99aep-13,   -0xd.09cad73642208p-10,
     59                           -0xe.1599f32a83dp-10,   -0xa.b90d8910a117p-10,  -0xc.edeaabb890948p-11,
     60                           -0xb.f14edbb55383p-12,  -0xc.2cb39b86f2dap-14,  +0xb.4a506ecff055p-15,
     61                           +0xb.685edfdb55358p-14, +0xa.b182e32f8e298p-14, +0xf.0cb3dfd894b2p-15,
     62                           +0x8.695df725b4438p-15, +0xd.beddc3606b9p-17,   +0xf.547004d20874p-20,
     63                           -0xd.bb29b25b49b6p-19,  -0x9.63cb9187da1dp-18,  -0xf.ca588634fc618p-19,
     64                           -0xa.52322d320da78p-19, -0xa.9e9420154e4p-20,   -0xe.ab51f7b0335ap-22,
     65                           +0xa.3c6479980e1p-26,   +0xd.7223836599fp-23,   +0xe.ccc47ddd18678p-23,
     66                           +0xb.5f265b1be1728p-23, +0xd.d2cb83f8483f8p-24,
     67                       };
     68 
     69                       const univector<T, size> ir = iir(unitimpulse<T>(), iir_params{ bq });
     70 
     71                       CHECK(absmaxof(choose_array<T>(test_vector_f32, test_vector_f64) - ir) == 0);
     72                   });
     73 }
     74 
     75 TEST(biquad_lowpass2)
     76 {
     77     testo::matrix(named("type") = ctypes_t<float, double>{},
     78                   [](auto type)
     79                   {
     80                       using T = typename decltype(type)::type;
     81 
     82                       const biquad_section<T> bq = biquad_lowpass<T>(0.45, 0.2);
     83 
     84                       constexpr size_t size = 32;
     85 
     86                       const univector<float, size> test_vector_f32{
     87                           +0x8.ce416p-4,  +0x8.2979p-4,   -0x8.a9d04p-7,  +0xe.aeb3p-11,  +0x8.204f8p-13,
     88                           -0x8.20d78p-12, +0x8.3379p-12,  -0xf.83d81p-13, +0xe.8b5c4p-13, -0xd.9ddadp-13,
     89                           +0xc.bedfcp-13, -0xb.ee123p-13, +0xb.2a9e5p-13, -0xa.73ac4p-13, +0x9.c86f6p-13,
     90                           -0x9.2828p-13,  +0x8.92229p-13, -0x8.05b7p-13,  +0xf.048ffp-14, -0xe.0e849p-14,
     91                           +0xd.28384p-14, -0xc.50a9p-14,  +0xb.86e56p-14, -0xa.ca0b6p-14, +0xa.19476p-14,
     92                           -0x9.73d38p-14, +0x8.d8f64p-14, -0x8.48024p-14, +0xf.80aa2p-15, -0xe.82ad8p-15,
     93                           +0xd.94f22p-15, -0xc.b66d9p-15,
     94                       };
     95 
     96                       const univector<double, size> test_vector_f64{
     97                           +0x8.ce416c0d31e88p-4,  +0x8.2978efe51dafp-4,   -0x8.a9d088b81da6p-7,
     98                           +0xe.aeb56c029358p-11,  +0x8.20492639873ap-13,  -0x8.20d4e21aab538p-12,
     99                           +0x8.3376b2d53b4a8p-12, -0xf.83d3d1c17343p-13,  +0xe.8b584f0dd5ac8p-13,
    100                           -0xd.9dd740ceaacf8p-13, +0xc.bedc85e7a621p-13,  -0xb.ee0f472bf8968p-13,
    101                           +0xb.2a9baed1fe6cp-13,  -0xa.73a9d1670f4ep-13,  +0x9.c86d29d297798p-13,
    102                           -0x9.2825f4d894088p-13, +0x8.9220a956d651p-13,  -0x8.05b539fdd79e8p-13,
    103                           +0xf.048cb5194cfa8p-14, -0xe.0e819fa128938p-14, +0xd.2835957d684cp-14,
    104                           -0xc.50a69c2a8dc18p-14, +0xb.86e33bbaf3cbp-14,  -0xa.ca097058af2cp-14,
    105                           +0xa.1945ad1703dcp-14,  -0x9.73d1eef7d8b68p-14, +0x8.d8f4df1bb3efp-14,
    106                           -0x8.48010323c6f7p-14,  +0xf.80a7f5baeeb2p-15,  -0xe.82ab94bb68a8p-15,
    107                           +0xd.94f05f80af008p-15, -0xc.b66c0799b21a8p-15,
    108                       };
    109 
    110                       const univector<T, size> ir = iir(unitimpulse<T>(), iir_params{ bq });
    111 
    112                       CHECK(absmaxof(choose_array<T>(test_vector_f32, test_vector_f64) - ir) == 0);
    113                   });
    114 }
    115 
    116 TEST(iir_filter)
    117 {
    118     biquad_section<float> params[16];
    119     auto f = iir_filter<float>(iir_params{ params });
    120     float buf[256];
    121     f.apply(buf);
    122 }
    123 } // namespace CMT_ARCH_NAME
    124 } // namespace kfr
    125 
    126 CMT_PRAGMA_MSVC(warning(pop))