Line data Source code
1 : /** 2 : * \file FeedbackDelayNetworkFilter.hxx 3 : */ 4 : 5 : #ifndef ATK_DELAY_FEEDBACKDELAYNETWORKFILTER_HXX 6 : #define ATK_DELAY_FEEDBACKDELAYNETWORKFILTER_HXX 7 : 8 : #include <ATK/Delay/FeedbackDelayNetworkFilter.h> 9 : #include <ATK/Core/Utilities.h> 10 : 11 : #include <Eigen/Dense> 12 : 13 : #include <complex> 14 : 15 : namespace ATK 16 : { 17 : template<typename Mixture> 18 : class FeedbackDelayNetworkFilter<Mixture>::HFDN_Impl: public Mixture::MixtureImpl 19 : { 20 : public: 21 : using Vector = typename Mixture::MixtureImpl::Vector; 22 : using Matrix = typename Mixture::MixtureImpl::Matrix; 23 : 24 : std::vector<Vector, boost::alignment::aligned_allocator<Vector, 32>> delay_line; 25 : std::vector<Vector, boost::alignment::aligned_allocator<Vector, 32>> processed_input; 26 : int64_t index{0}; 27 : Vector ingain = Vector::Zero(); 28 : Vector outgain = Vector::Zero(); 29 : Vector feedback = Vector::Zero(); 30 : 31 30 : explicit HFDN_Impl(gsl::index max_delay) 32 30 : :processed_input(max_delay, Vector::Zero()) 33 : { 34 30 : } 35 : }; 36 : 37 : template<typename Mixture> 38 30 : FeedbackDelayNetworkFilter<Mixture>::FeedbackDelayNetworkFilter(gsl::index max_delay) 39 30 : :Parent(1, 2), impl(std::make_unique<HFDN_Impl>(max_delay)), max_delay(max_delay) 40 : { 41 30 : delay.fill(max_delay - 1); 42 30 : } 43 : 44 : template<typename Mixture> 45 30 : FeedbackDelayNetworkFilter<Mixture>::~FeedbackDelayNetworkFilter() 46 : { 47 30 : } 48 : 49 : template<typename Mixture> 50 26 : void FeedbackDelayNetworkFilter<Mixture>::set_delay(unsigned int channel, gsl::index delay) 51 : { 52 26 : if (delay == 0) 53 : { 54 2 : throw ATK::RuntimeError("Delay must be strictly positive"); 55 : } 56 24 : if (delay >= max_delay) 57 : { 58 2 : throw ATK::RuntimeError("Delay must be less than delay line size"); 59 : } 60 : 61 22 : this->delay[channel] = delay; 62 22 : } 63 : 64 : template<typename Mixture> 65 2 : gsl::index FeedbackDelayNetworkFilter<Mixture>::get_delay(unsigned int channel) const 66 : { 67 2 : return delay[channel]; 68 : } 69 : 70 : template<typename Mixture> 71 22 : void FeedbackDelayNetworkFilter<Mixture>::set_ingain(unsigned int channel, DataType ingain) 72 : { 73 22 : impl->ingain(channel) = ingain; 74 22 : } 75 : 76 : template<typename Mixture> 77 2 : typename FeedbackDelayNetworkFilter<Mixture>::DataType FeedbackDelayNetworkFilter<Mixture>::get_ingain(unsigned int channel) const 78 : { 79 2 : return impl->ingain(channel); 80 : } 81 : 82 : template<typename Mixture> 83 14 : void FeedbackDelayNetworkFilter<Mixture>::set_feedback(unsigned int channel, DataType feedback) 84 : { 85 14 : if (std::abs(feedback * static_cast<DataType>(Mixture::gain_factor)) >= 1) 86 : { 87 4 : throw ATK::RuntimeError("Feedback must be between " + std::to_string(-Mixture::gain_factor) + " and " + std::to_string(Mixture::gain_factor) + " to avoid divergence"); 88 : } 89 10 : impl->feedback(channel) = feedback * static_cast<DataType>(Mixture::gain_factor); 90 10 : } 91 : 92 : template<typename Mixture> 93 2 : typename FeedbackDelayNetworkFilter<Mixture>::DataType FeedbackDelayNetworkFilter<Mixture>::get_feedback(unsigned int channel) const 94 : { 95 2 : return impl->feedback(channel) / static_cast<DataType>(Mixture::gain_factor); 96 : } 97 : 98 : template<typename Mixture> 99 22 : void FeedbackDelayNetworkFilter<Mixture>::set_outgain(unsigned int channel, DataType outgain) 100 : { 101 22 : impl->outgain(channel) = outgain; 102 22 : } 103 : 104 : template<typename Mixture> 105 2 : typename FeedbackDelayNetworkFilter<Mixture>::DataType FeedbackDelayNetworkFilter<Mixture>::get_outgain(unsigned int channel) const 106 : { 107 2 : return impl->outgain(channel); 108 : } 109 : 110 : template<typename Mixture> 111 14 : void FeedbackDelayNetworkFilter<Mixture>::full_setup() 112 : { 113 : // reset the delay line 114 14 : impl->processed_input.assign(max_delay, HFDN_Impl::Vector::Zero()); 115 14 : } 116 : 117 : template<typename Mixture> 118 4222 : void FeedbackDelayNetworkFilter<Mixture>::process_impl(gsl::index size) const 119 : { 120 4222 : const DataType* ATK_RESTRICT input = converted_inputs[0]; 121 4222 : DataType* ATK_RESTRICT output = outputs[0]; 122 : 123 4222 : impl->delay_line.resize(size); 124 : 125 2298861 : for (gsl::index i = 0; i < size; ++i) 126 : { 127 9197780 : for (gsl::index channel = 0; channel < nb_channels; ++channel) 128 : { 129 6903130 : auto j = impl->index - static_cast<int64_t>(delay[channel]); 130 6903130 : if (j < 0) 131 : { 132 4806210 : j += max_delay; 133 : } 134 : 135 6903130 : impl->delay_line[i](channel) = impl->processed_input[j](channel); 136 : } 137 2294640 : impl->processed_input[impl->index] = (impl->ingain * input[i]).array() + impl->mix(impl->delay_line[i]).array() * impl->feedback.array(); 138 : 139 2294640 : output[i] = impl->outgain.dot(impl->delay_line[i]); 140 : 141 2294640 : ++impl->index; 142 2294640 : if(impl->index == max_delay) 143 : { 144 4812 : impl->index = 0; 145 : } 146 : } 147 4222 : } 148 : } 149 : 150 : #endif