Line data Source code
1 : /**
2 : * \file MultipleUniversalFixedDelayLineFilter.cpp
3 : */
4 :
5 : #include "MultipleUniversalFixedDelayLineFilter.h"
6 : #include <ATK/Core/TypeTraits.h>
7 : #include <ATK/Core/Utilities.h>
8 :
9 : #include <cmath>
10 : #include <cstring>
11 : #include <complex>
12 : #include <stdexcept>
13 :
14 : namespace ATK
15 : {
16 : template<class DataType, int nb_channels>
17 : class MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::SUFDLF_Impl
18 : {
19 : public:
20 : std::array<std::vector<DataType>, nb_channels> processed_input;
21 : int64_t index{0};
22 :
23 19 : explicit SUFDLF_Impl(gsl::index max_delay)
24 19 : {
25 : // reset the delay line
26 57 : for (unsigned int channel = 0; channel < nb_channels; ++channel)
27 : {
28 38 : processed_input[channel].assign(max_delay, 0);
29 : }
30 19 : }
31 : };
32 :
33 : template<class DataType, int nb_channels>
34 19 : MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::MultipleUniversalFixedDelayLineFilter(gsl::index max_delay)
35 19 : :Parent(nb_channels, 2 * nb_channels), impl(std::make_unique<SUFDLF_Impl>(max_delay)), max_delay(max_delay)
36 : {
37 19 : delay.fill(max_delay - 1);
38 19 : blend.fill(0);
39 19 : feedback.fill(0);
40 19 : feedforward.fill(0);
41 19 : }
42 :
43 : template<class DataType, int nb_channels>
44 19 : MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::~MultipleUniversalFixedDelayLineFilter()
45 : {
46 19 : }
47 :
48 : template<class DataType, int nb_channels>
49 15 : void MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::set_delay(unsigned int channel, gsl::index delay)
50 : {
51 15 : if (delay == 0)
52 : {
53 1 : throw ATK::RuntimeError("Delay must be strictly positive");
54 : }
55 14 : if (delay >= max_delay)
56 : {
57 1 : throw ATK::RuntimeError("Delay must be less than delay line size");
58 : }
59 :
60 13 : this->delay[channel] = delay;
61 13 : }
62 :
63 : template<class DataType, int nb_channels>
64 1 : gsl::index MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::get_delay(unsigned int channel) const
65 : {
66 1 : return delay[channel];
67 : }
68 :
69 : template<class DataType_, int nb_channels>
70 7 : void MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::set_blend(unsigned int channel, DataType_ blend)
71 : {
72 7 : this->blend[channel] = blend;
73 7 : }
74 :
75 : template<class DataType_, int nb_channels>
76 1 : DataType_ MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::get_blend(unsigned int channel) const
77 : {
78 1 : return blend[channel];
79 : }
80 :
81 : template<class DataType_, int nb_channels>
82 11 : void MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::set_feedback(unsigned int from_channel, unsigned int to_channel, DataType_ feedback)
83 : {
84 11 : if (std::abs(feedback) >= 1)
85 : {
86 2 : throw ATK::RuntimeError("Feedback must be between -1 and 1 to avoid divergence");
87 : }
88 9 : this->feedback[from_channel * nb_channels + to_channel] = feedback;
89 9 : }
90 :
91 : template<class DataType_, int nb_channels>
92 1 : DataType_ MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::get_feedback(unsigned int from_channel, unsigned int to_channel) const
93 : {
94 1 : return feedback[from_channel * nb_channels + to_channel];
95 : }
96 :
97 : template<class DataType_, int nb_channels>
98 15 : void MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::set_feedforward(unsigned int from_channel, unsigned int to_channel, DataType_ feedforward)
99 : {
100 15 : this->feedforward[from_channel * nb_channels + to_channel] = feedforward;
101 15 : }
102 :
103 : template<class DataType_, int nb_channels>
104 1 : DataType_ MultipleUniversalFixedDelayLineFilter<DataType_, nb_channels>::get_feedforward(unsigned int from_channel, unsigned int to_channel) const
105 : {
106 1 : return feedforward[from_channel * nb_channels + to_channel];
107 : }
108 :
109 : template<class DataType, int nb_channels>
110 11 : void MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::full_setup()
111 : {
112 : // reset the delay line
113 33 : for (int channel = 0; channel < nb_channels; ++channel)
114 : {
115 22 : impl->processed_input[channel].assign(max_delay, 0);
116 : }
117 11 : }
118 :
119 : template<class DataType, int nb_channels>
120 2127 : void MultipleUniversalFixedDelayLineFilter<DataType, nb_channels>::process_impl(gsl::index size) const
121 : {
122 1411590 : for (gsl::index i = 0; i < size; ++i)
123 : {
124 4228400 : ATK_VECTORIZE for (gsl::index channel = 0; channel < nb_channels; ++channel)
125 : {
126 2818930 : auto j = impl->index - static_cast<int64_t>(delay[channel]);
127 2818930 : if (j < 0)
128 : {
129 1767510 : j += max_delay;
130 : }
131 2818930 : outputs[nb_channels + channel][i] = impl->processed_input[channel][j];
132 : }
133 4228400 : ATK_VECTORIZE for (gsl::index to_channel = 0; to_channel < nb_channels; ++to_channel)
134 : {
135 2818930 : impl->processed_input[to_channel][impl->index] = converted_inputs[to_channel][i];
136 8456800 : ATK_VECTORIZE for (gsl::index from_channel = 0; from_channel < nb_channels; ++from_channel)
137 : {
138 5637860 : impl->processed_input[to_channel][impl->index] += feedback[from_channel * nb_channels + to_channel] * outputs[nb_channels + from_channel][i];
139 : }
140 : }
141 4228400 : ATK_VECTORIZE for (gsl::index to_channel = 0; to_channel < nb_channels; ++to_channel)
142 : {
143 2818930 : outputs[to_channel][i] = blend[to_channel] * impl->processed_input[to_channel][impl->index];
144 8456800 : ATK_VECTORIZE for (gsl::index from_channel = 0; from_channel < nb_channels; ++from_channel)
145 : {
146 5637860 : outputs[to_channel][i] += feedforward[from_channel * nb_channels + to_channel] * outputs[nb_channels + from_channel][i];
147 : }
148 : }
149 1409470 : ++impl->index;
150 1409470 : if (impl->index == max_delay)
151 : {
152 12890 : impl->index = 0;
153 : }
154 : }
155 2127 : }
156 :
157 : template class MultipleUniversalFixedDelayLineFilter<double, 2>;
158 : template class MultipleUniversalFixedDelayLineFilter<double, 4>;
159 : template class MultipleUniversalFixedDelayLineFilter<double, 8>;
160 :
161 : #if ATK_ENABLE_INSTANTIATION
162 : template class MultipleUniversalFixedDelayLineFilter<float, 2>;
163 : template class MultipleUniversalFixedDelayLineFilter<std::complex<float>, 2>;
164 : template class MultipleUniversalFixedDelayLineFilter<std::complex<double>, 2>;
165 :
166 : template class MultipleUniversalFixedDelayLineFilter<float, 4>;
167 : template class MultipleUniversalFixedDelayLineFilter<std::complex<float>, 4>;
168 : template class MultipleUniversalFixedDelayLineFilter<std::complex<double>, 4>;
169 :
170 : template class MultipleUniversalFixedDelayLineFilter<float, 8>;
171 : template class MultipleUniversalFixedDelayLineFilter<std::complex<float>, 8>;
172 : template class MultipleUniversalFixedDelayLineFilter<std::complex<double>, 8>;
173 : #endif
174 : }
|