LCOV - code coverage report
Current view: top level - Delay - UniversalVariableDelayLineFilter.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 62 62 100.0 %
Date: 2021-02-18 20:07:22 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /**
       2             :  * \file UniversalVariableDelayLineFilter.cpp
       3             :  */
       4             : 
       5             : #include "UniversalVariableDelayLineFilter.h"
       6             : #include <ATK/Core/Utilities.h>
       7             : 
       8             : #include <cassert>
       9             : #include <cmath>
      10             : #include <cstdint>
      11             : #include <cstring>
      12             : 
      13             : namespace ATK
      14             : {
      15             :   template<typename DataType>
      16             :   class UniversalVariableDelayLineFilter<DataType>::UVDLF_Impl
      17             :   {
      18             :   public:
      19             :     /// Delay line contains the last size elements + max_delay of the last delay line
      20             :     std::vector<DataType> delay_line;
      21             :     std::vector<DataType> processed_input;
      22             : 
      23             :     /// Integer portion of the delay for the last processed chunk
      24             :     std::vector<gsl::index> integer_delay;
      25             :     /// Fractional portion of the delay for the last processed chunk, used for the interpolation
      26             :     std::vector<DataType> fractional_delay;
      27             :     DataType last_delay{0};
      28             : 
      29           8 :     explicit UVDLF_Impl(gsl::index max_delay)
      30           8 :       :processed_input(max_delay, 0)
      31             :     {
      32           8 :     }
      33             : 
      34           8 :     void update_delay_line(gsl::index max_delay, gsl::index size)
      35             :     {
      36           8 :       auto array_size = processed_input.size();
      37             :       // Update delay line
      38      192520 :       ATK_VECTORIZE for (gsl::index i = 0; i < max_delay; ++i)
      39             :       {
      40      192512 :         processed_input[i] = processed_input[array_size + i - max_delay];
      41             :       }
      42           8 :       delay_line.resize(size);
      43           8 :       processed_input.resize(size + max_delay);
      44           8 :       integer_delay.resize(size);
      45           8 :       fractional_delay.resize(size);
      46           8 :     }
      47             :   };
      48             : 
      49             :   template<typename DataType_>
      50           8 :   UniversalVariableDelayLineFilter<DataType_>::UniversalVariableDelayLineFilter(gsl::index max_delay)
      51           8 :     :Parent(2, 1), impl(std::make_unique<UVDLF_Impl>(max_delay)), max_delay(max_delay), central_delay(max_delay / 2)
      52             :   {
      53           8 :   }
      54             :   
      55             :   template<typename DataType_>
      56           8 :   UniversalVariableDelayLineFilter<DataType_>::~UniversalVariableDelayLineFilter()
      57             :   {
      58             :     
      59           8 :   }
      60             : 
      61             :   template<typename DataType_>
      62           1 :   void UniversalVariableDelayLineFilter<DataType_>::set_central_delay(gsl::index central_delay)
      63             :   {
      64           1 :     this->central_delay = central_delay;
      65           1 :   }
      66             : 
      67             :   template<typename DataType_>
      68           1 :   gsl::index UniversalVariableDelayLineFilter<DataType_>::get_central_delay() const
      69             :   {
      70           1 :     return central_delay;
      71             :   }
      72             : 
      73             :   template<typename DataType_>
      74           2 :   void UniversalVariableDelayLineFilter<DataType_>::set_blend(DataType_ blend)
      75             :   {
      76           2 :     this->blend = blend;
      77           2 :   }
      78             :   
      79             :   template<typename DataType_>
      80           1 :   DataType_ UniversalVariableDelayLineFilter<DataType_>::get_blend() const
      81             :   {
      82           1 :     return blend;
      83             :   }
      84             :   
      85             :   template<typename DataType_>
      86           4 :   void UniversalVariableDelayLineFilter<DataType_>::set_feedback(DataType_ feedback)
      87             :   {
      88           4 :     if(std::abs(feedback) >= 1)
      89             :     {
      90           2 :       throw ATK::RuntimeError("Feedback must be between -1 and 1 to avoid divergence");
      91             :     }
      92           2 :     this->feedback = feedback;
      93           2 :   }
      94             :   
      95             :   template<typename DataType_>
      96           1 :   DataType_ UniversalVariableDelayLineFilter<DataType_>::get_feedback() const
      97             :   {
      98           1 :     return feedback;
      99             :   }
     100             :   
     101             :   template<typename DataType_>
     102           2 :   void UniversalVariableDelayLineFilter<DataType_>::set_feedforward(DataType_ feedforward)
     103             :   {
     104           2 :     this->feedforward = feedforward;
     105           2 :   }
     106             :   
     107             :   template<typename DataType_>
     108           1 :   DataType_ UniversalVariableDelayLineFilter<DataType_>::get_feedforward() const
     109             :   {
     110           1 :     return feedforward;
     111             :   }
     112             : 
     113             :   template<typename DataType_>
     114           2 :   void UniversalVariableDelayLineFilter<DataType_>::full_setup()
     115             :   {
     116             :     // reset the delay line
     117           2 :     impl->processed_input.assign(max_delay, 0);
     118           2 :     impl->last_delay = 0;
     119           2 :   }
     120             : 
     121             :   template<typename DataType_>
     122           8 :   void UniversalVariableDelayLineFilter<DataType_>::process_impl(gsl::index size) const
     123             :   {
     124           8 :     impl->update_delay_line(max_delay, size);
     125           8 :     const DataType* ATK_RESTRICT input1 = converted_inputs[0]; // samples
     126           8 :     const DataType* ATK_RESTRICT input2 = converted_inputs[1]; // delay
     127           8 :     DataType* ATK_RESTRICT output = outputs[0];
     128             : 
     129           8 :     DataType* ATK_RESTRICT delay_line = impl->delay_line.data();
     130           8 :     DataType* ATK_RESTRICT processed_input = impl->processed_input.data();
     131           8 :     gsl::index* ATK_RESTRICT integer_delay = impl->integer_delay.data();
     132           8 :     DataType* ATK_RESTRICT fractional_delay = impl->fractional_delay.data();
     133             : 
     134             :     // Update the delay line
     135        2056 :     ATK_VECTORIZE for(gsl::index i = 0; i < size; ++i)
     136             :     {
     137        2048 :       auto rounded = static_cast<gsl::index>(input2[i]);
     138        2048 :       integer_delay[i] = rounded >= max_delay ? 0 : rounded;
     139        2048 :       fractional_delay[i] = input2[i] - integer_delay[i];
     140             :     }
     141             : 
     142        2056 :     ATK_VECTORIZE for(gsl::index i = 0; i < size; ++i)
     143             :     {
     144        2048 :       delay_line[i] = (processed_input[i + max_delay - integer_delay[i]] - impl->last_delay) * (1 - fractional_delay[i]) + processed_input[i + max_delay - integer_delay[i] - 1];
     145        2048 :       processed_input[max_delay + i] = input1[i] + feedback * processed_input[max_delay + i - central_delay]; // FB only uses the central delay and is not varying
     146        2048 :       output[i] = blend * processed_input[max_delay + i] + feedforward * delay_line[i];
     147        2048 :       impl->last_delay = delay_line[i]; // the reason why the test is not that simple!
     148             :     }
     149           8 :   }
     150             :   
     151             :   template class UniversalVariableDelayLineFilter<double>;
     152             : #if ATK_ENABLE_INSTANTIATION
     153             :   template class UniversalVariableDelayLineFilter<float>;
     154             : #endif
     155             : }

Generated by: LCOV version TK-3.3.0-4-gdba42eea