1 /*****************************************************************************
2 
3         Downsampler2xFpuTpl.hpp
4         Author: Laurent de Soras, 2005
5 
6 --- Legal stuff ---
7 
8 This program is free software. It comes without any warranty, to
9 the extent permitted by applicable law. You can redistribute it
10 and/or modify it under the terms of the Do What The Fuck You Want
11 To Public License, Version 2, as published by Sam Hocevar. See
12 http://sam.zoy.org/wtfpl/COPYING for more details.
13 
14 *Tab=3***********************************************************************/
15 
16 
17 
18 #if defined (hiir_Downsampler2xFpuTpl_CURRENT_CODEHEADER)
19 	#error Recursive inclusion of Downsampler2xFpuTpl code header.
20 #endif
21 #define hiir_Downsampler2xFpuTpl_CURRENT_CODEHEADER
22 
23 #if ! defined (hiir_Downsampler2xFpuTpl_CODEHEADER_INCLUDED)
24 #define hiir_Downsampler2xFpuTpl_CODEHEADER_INCLUDED
25 
26 
27 
28 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
29 
30 #include "hiir/StageProcFpu.h"
31 
32 #include <cassert>
33 
34 
35 
36 namespace hiir
37 {
38 
39 
40 
41 /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
42 
43 
44 
45 /*
46 ==============================================================================
47 Name: set_coefs
48 Description:
49 	Sets filter coefficients. Generate them with the PolyphaseIir2Designer
50 	class.
51 	Call this function before doing any processing.
52 Input parameters:
53 	- coef_arr: Array of coefficients. There should be as many coefficients as
54 		mentioned in the class template parameter.
55 Throws: Nothing
56 ==============================================================================
57 */
58 
59 template <int NC, typename DT>
set_coefs(const double coef_arr[])60 void	Downsampler2xFpuTpl <NC, DT>::set_coefs (const double coef_arr [])
61 {
62 	assert (coef_arr != nullptr);
63 
64 	for (int i = 0; i < NBR_COEFS; ++i)
65 	{
66 		_filter [i + 2]._coef = DataType (coef_arr [i]);
67 	}
68 }
69 
70 
71 
72 /*
73 ==============================================================================
74 Name: process_sample
75 Description:
76 	Downsamples (x2) one pair of samples, to generate one output sample.
77 Input parameters:
78 	- in_ptr: pointer on the two samples to decimate
79 Returns: Samplerate-reduced sample.
80 Throws: Nothing
81 ==============================================================================
82 */
83 
84 template <int NC, typename DT>
process_sample(const DataType in_ptr[2])85 typename Downsampler2xFpuTpl <NC, DT>::DataType	Downsampler2xFpuTpl <NC, DT>::process_sample (const DataType in_ptr [2])
86 {
87 	assert (in_ptr != nullptr);
88 
89 	DataType       spl_0 (in_ptr [1]);
90 	DataType       spl_1 (in_ptr [0]);
91 
92 	StageProcFpu <NBR_COEFS, DataType>::process_sample_pos (
93 		NBR_COEFS, spl_0, spl_1, _filter.data ()
94 	);
95 
96 	return 0.5f * (spl_0 + spl_1);
97 }
98 
99 
100 
101 /*
102 ==============================================================================
103 Name: process_block
104 Description:
105 	Downsamples (x2) a block of samples.
106 	Input and output blocks may overlap, see assert() for details.
107 Input parameters:
108 	- in_ptr: Input array, containing nbr_spl * 2 samples.
109 	- nbr_spl: Number of samples to output, > 0
110 Output parameters:
111 	- out_ptr: Array for the output samples, capacity: nbr_spl samples.
112 Throws: Nothing
113 ==============================================================================
114 */
115 
116 template <int NC, typename DT>
process_block(DataType out_ptr[],const DataType in_ptr[],long nbr_spl)117 void	Downsampler2xFpuTpl <NC, DT>::process_block (DataType out_ptr [], const DataType in_ptr [], long nbr_spl)
118 {
119 	assert (in_ptr != nullptr);
120 	assert (out_ptr != nullptr);
121 	assert (out_ptr <= in_ptr || out_ptr >= in_ptr + nbr_spl * 2);
122 	assert (nbr_spl > 0);
123 
124 	long           pos = 0;
125 	do
126 	{
127 		out_ptr [pos] = process_sample (&in_ptr [pos * 2]);
128 		++pos;
129 	}
130 	while (pos < nbr_spl);
131 }
132 
133 
134 
135 /*
136 ==============================================================================
137 Name: process_sample_split
138 Description:
139 	Split (spectrum-wise) in half a pair of samples. The lower part of the
140 	spectrum is a classic downsampling, equivalent to the output of
141 	process_sample().
142 	The higher part is the complementary signal: original filter response
143 	is flipped from left to right, becoming a high-pass filter with the same
144 	cutoff frequency. This signal is then critically sampled (decimation by 2),
145 	flipping the spectrum: Fs/4...Fs/2 becomes Fs/4...0.
146 Input parameters:
147 	- in_ptr: pointer on the pair of input samples
148 Output parameters:
149 	- low: output sample, lower part of the spectrum (downsampling)
150 	- high: output sample, higher part of the spectrum.
151 Throws: Nothing
152 ==============================================================================
153 */
154 
155 template <int NC, typename DT>
process_sample_split(DataType & low,DataType & high,const DataType in_ptr[2])156 void	Downsampler2xFpuTpl <NC, DT>::process_sample_split (DataType &low, DataType &high, const DataType in_ptr [2])
157 {
158 	assert (in_ptr != nullptr);
159 
160 	DataType       spl_0 = in_ptr [1];
161 	DataType       spl_1 = in_ptr [0];
162 
163 	StageProcFpu <NBR_COEFS, DataType>::process_sample_pos (
164 		NBR_COEFS, spl_0, spl_1, _filter.data ()
165 	);
166 
167 	low  = (spl_0 + spl_1) * 0.5f;
168 	high =  spl_0 - low; // (spl_0 - spl_1) * 0.5f;
169 }
170 
171 
172 
173 /*
174 ==============================================================================
175 Name: process_block_split
176 Description:
177 	Split (spectrum-wise) in half a block of samples. The lower part of the
178 	spectrum is a classic downsampling, equivalent to the output of
179 	process_block().
180 	The higher part is the complementary signal: original filter response
181 	is flipped from left to right, becoming a high-pass filter with the same
182 	cutoff frequency. This signal is then critically sampled (decimation by 2),
183 	flipping the spectrum: Fs/4...Fs/2 becomes Fs/4...0.
184 	Input and output blocks may overlap, see assert() for details.
185 Input parameters:
186 	- in_ptr: Input array, containing nbr_spl * 2 samples.
187 	- nbr_spl: Number of samples for each output, > 0
188 Output parameters:
189 	- out_l_ptr: Array for the output samples, lower part of the spectrum
190 		(downsampling). Capacity: nbr_spl samples.
191 	- out_h_ptr: Array for the output samples, higher part of the spectrum.
192 		Capacity: nbr_spl samples.
193 Throws: Nothing
194 ==============================================================================
195 */
196 
197 template <int NC, typename DT>
process_block_split(DataType out_l_ptr[],DataType out_h_ptr[],const DataType in_ptr[],long nbr_spl)198 void	Downsampler2xFpuTpl <NC, DT>::process_block_split (DataType out_l_ptr [], DataType out_h_ptr [], const DataType in_ptr [], long nbr_spl)
199 {
200 	assert (in_ptr    != nullptr);
201 	assert (out_l_ptr != nullptr);
202 	assert (out_l_ptr <= in_ptr || out_l_ptr >= in_ptr + nbr_spl * 2);
203 	assert (out_h_ptr != nullptr);
204 	assert (out_h_ptr <= in_ptr || out_h_ptr >= in_ptr + nbr_spl * 2);
205 	assert (out_h_ptr != out_l_ptr);
206 	assert (nbr_spl > 0);
207 
208 	long           pos = 0;
209 	do
210 	{
211 		process_sample_split (
212 			out_l_ptr [pos],
213 			out_h_ptr [pos],
214 			&in_ptr [pos * 2]
215 		);
216 		++pos;
217 	}
218 	while (pos < nbr_spl);
219 }
220 
221 
222 
223 /*
224 ==============================================================================
225 Name: clear_buffers
226 Description:
227 	Clears filter memory, as if it processed silence since an infinite amount
228 	of time.
229 Throws: Nothing
230 ==============================================================================
231 */
232 
233 template <int NC, typename DT>
clear_buffers()234 void	Downsampler2xFpuTpl <NC, DT>::clear_buffers ()
235 {
236 	for (int i = 0; i < NBR_COEFS + 2; ++i)
237 	{
238 		_filter [i]._mem = 0;
239 	}
240 }
241 
242 
243 
244 /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
245 
246 
247 
248 /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
249 
250 
251 
252 }  // namespace hiir
253 
254 
255 
256 #endif   // hiir_Downsampler2xFpuTpl_CODEHEADER_INCLUDED
257 
258 #undef hiir_Downsampler2xFpuTpl_CURRENT_CODEHEADER
259 
260 
261 
262 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
263