r8brain-free-src
High-quality pro audio sample rate converter library
 
Loading...
Searching...
No Matches
CDSPHBDownsampler.h
Go to the documentation of this file.
1//$ nobt
2//$ nocpp
3
15
16#ifndef R8B_CDSPHBDOWNSAMPLER_INCLUDED
17#define R8B_CDSPHBDOWNSAMPLER_INCLUDED
18
19#include "CDSPHBUpsampler.h"
20
21namespace r8b {
22
29
30class CDSPHBDownsampler : public CDSPProcessor
31{
32public:
46
47 CDSPHBDownsampler( const double ReqAtten, const int SteepIndex,
48 const bool IsThird, const double PrevLatency )
49 {
50 static const CConvolveFn FltConvFn[ 14 ] = {
51 &CDSPHBDownsampler :: convolve1, &CDSPHBDownsampler :: convolve2,
52 &CDSPHBDownsampler :: convolve3, &CDSPHBDownsampler :: convolve4,
53 &CDSPHBDownsampler :: convolve5, &CDSPHBDownsampler :: convolve6,
54 &CDSPHBDownsampler :: convolve7, &CDSPHBDownsampler :: convolve8,
55 &CDSPHBDownsampler :: convolve9, &CDSPHBDownsampler :: convolve10,
56 &CDSPHBDownsampler :: convolve11, &CDSPHBDownsampler :: convolve12,
57 &CDSPHBDownsampler :: convolve13,
58 &CDSPHBDownsampler :: convolve14 };
59
60 const double* fltp0;
61 int fltt;
62 double att;
63
64 if( IsThird )
65 {
66 CDSPHBUpsampler :: getHBFilterThird( ReqAtten, SteepIndex, fltp0,
67 fltt, att );
68 }
69 else
70 {
71 CDSPHBUpsampler :: getHBFilter( ReqAtten, SteepIndex, fltp0, fltt,
72 att );
73 }
74
75 // Copy obtained filter to address-aligned buffer.
76
77 fltp = alignptr( FltBuf, 16 );
78 memcpy( fltp, fltp0, (size_t) fltt * sizeof( fltp[ 0 ]));
79
80 convfn = FltConvFn[ fltt - 1 ];
81 fll = fltt;
82 fl2 = fltt - 1;
83 flo = fll + fl2;
84 flb = BufLen - fll;
85 BufRP1 = Buf1 + fll;
86 BufRP2 = Buf2 + fll - 1;
87
88 LatencyFrac = PrevLatency * 0.5;
89 Latency = (int) LatencyFrac;
90 LatencyFrac -= Latency;
91
92 R8BASSERT( Latency >= 0 );
93
94 R8BCONSOLE( "CDSPHBDownsampler: taps=%i third=%i att=%.1f io=1/2\n",
95 fltt, (int) IsThird, att );
96
97 clear();
98 }
99
100 virtual int getInLenBeforeOutPos( const int ReqOutPos ) const
101 {
102 return( flo + (int) (( Latency + LatencyFrac + ReqOutPos ) * 2.0 ));
103 }
104
105 virtual int getLatency() const
106 {
107 return( 0 );
108 }
109
110 virtual double getLatencyFrac() const
111 {
112 return( LatencyFrac );
113 }
114
115 virtual int getMaxOutLen( const int MaxInLen ) const
116 {
117 R8BASSERT( MaxInLen >= 0 );
118
119 return(( MaxInLen + 1 ) >> 1 );
120 }
121
122 virtual void clear()
123 {
124 LatencyLeft = Latency;
125 BufLeft = 0;
126 WritePos1 = 0;
127 WritePos2 = 0;
128 ReadPos = flb; // Set "read" position to account for filter's latency.
129
130 memset( &Buf1[ ReadPos ], 0,
131 (size_t) ( BufLen - flb ) * sizeof( Buf1[ 0 ]));
132
133 memset( &Buf2[ ReadPos ], 0,
134 (size_t) ( BufLen - flb ) * sizeof( Buf2[ 0 ]));
135 }
136
137 virtual int process( double* ip, int l, double*& op0 )
138 {
139 R8BASSERT( l >= 0 );
140
141 double* op = op0;
142
143 while( l > 0 )
144 {
145 // Copy new input samples to 2 ring buffers.
146
147 if( WritePos1 != WritePos2 )
148 {
149 // If previous fill was asymmetrical, put a single sample to
150 // Buf2.
151
152 double* const wp2 = Buf2 + WritePos2;
153 *wp2 = *ip;
154
155 if( WritePos2 < flo )
156 {
157 wp2[ BufLen ] = *ip;
158 }
159
160 ip++;
161 WritePos2 = WritePos1;
162 l--;
163 BufLeft++;
164 }
165
166 const int b1 = min(( l + 1 ) >> 1,
167 min( BufLen - WritePos1, flb - BufLeft ));
168
169 const int b2 = b1 - ( b1 * 2 > l );
170
171 double* wp1 = Buf1 + WritePos1;
172 double* wp2 = Buf2 + WritePos1;
173 double* const ipe = ip + b2 * 2;
174
175 while( ip != ipe )
176 {
177 *wp1 = ip[ 0 ];
178 *wp2 = ip[ 1 ];
179 wp1++;
180 wp2++;
181 ip += 2;
182 }
183
184 if( b1 != b2 )
185 {
186 *wp1 = *ip;
187 ip++;
188 }
189
190 const int ec = flo - WritePos1;
191
192 if( ec > 0 )
193 {
194 wp1 = Buf1 + WritePos1;
195 memcpy( wp1 + BufLen, wp1,
196 (size_t) min( b1, ec ) * sizeof( wp1[ 0 ]));
197
198 wp2 = Buf2 + WritePos1;
199 memcpy( wp2 + BufLen, wp2,
200 (size_t) min( b2, ec ) * sizeof( wp2[ 0 ]));
201 }
202
203 WritePos1 = ( WritePos1 + b1 ) & BufLenMask;
204 WritePos2 = ( WritePos2 + b2 ) & BufLenMask;
205 l -= b1 + b2;
206 BufLeft += b2;
207
208 // Produce output.
209
210 const int c = BufLeft - fl2;
211
212 if( c > 0 )
213 {
214 double* const opend = op + c;
215 ( *convfn )( op, opend, fltp, BufRP1, BufRP2, ReadPos );
216
217 op = opend;
218 ReadPos = ( ReadPos + c ) & BufLenMask;
219 BufLeft -= c;
220 }
221 }
222
223 int ol = (int) ( op - op0 );
224
225 if( LatencyLeft != 0 )
226 {
227 if( LatencyLeft >= ol )
228 {
229 LatencyLeft -= ol;
230 return( 0 );
231 }
232
233 ol -= LatencyLeft;
234 op0 += LatencyLeft;
235 LatencyLeft = 0;
236 }
237
238 return( ol );
239 }
240
241private:
242 static const int BufLenBits = 10;
248 static const int BufLen = 1 << BufLenBits;
251 static const int BufLenMask = BufLen - 1;
253 double Buf1[ BufLen + 27 ];
255 double Buf2[ BufLen + 27 ];
257 double FltBuf[ 14 + 2 ];
259 const double* BufRP1;
260 const double* BufRP2;
261 double* fltp;
262 double LatencyFrac;
263 int Latency;
264 int fll;
265 int fl2;
266 int flo;
267 int flb;
268 int LatencyLeft;
269 int BufLeft;
271 int WritePos1;
272 int WritePos2;
274 int ReadPos;
275
276 typedef void( *CConvolveFn )( double* op, double* const opend,
277 const double* const flt, const double* const rp01,
278 const double* const rp02, int rpos );
280 CConvolveFn convfn;
281
282#define R8BHBC1( fn ) \
283 static void fn( double* op, double* const opend, const double* const flt, \
284 const double* const rp01, const double* const rp02, int rpos ) \
285 { \
286 while( op != opend ) \
287 { \
288 const double* const rp1 = rp01 + rpos; \
289 const double* const rp = rp02 + rpos;
290
291#define R8BHBC2 \
292 rpos = ( rpos + 1 ) & BufLenMask; \
293 op++; \
294 } \
295 }
296
297#include "CDSPHBDownsampler.inc"
298
299#undef R8BHBC1
300#undef R8BHBC2
301};
302
303// ---------------------------------------------------------------------------
304
305} // namespace r8b
306
307#endif // R8B_CDSPHBDOWNSAMPLER_INCLUDED
Half-band upsampling class.
#define R8BASSERT(e)
Assertion macro used to check for certain run-time conditions. By default, no action is taken if asse...
Definition r8bconf.h:28
#define R8BCONSOLE(...)
Console output macro, used to output various resampler status strings, including filter design parame...
Definition r8bconf.h:41
The "r8brain-free-src" library namespace.
Definition CDSPBlockConvolver.h:22
T * alignptr(T *const ptr, const uintptr_t align)
Forces the provided ptr pointer to be aligned to align bytes.
Definition r8bbase.h:256
T min(const T &v1, const T &v2)
Returns minimum of two values.
Definition r8bbase.h:1079
virtual int getInLenBeforeOutPos(const int ReqOutPos) const
Returns the number of input samples required to advance to the specified output sample position (so t...
Definition CDSPHBDownsampler.h:100
virtual int process(double *ip, int l, double *&op0)
Performs DSP processing.
Definition CDSPHBDownsampler.h:137
CDSPHBDownsampler(const double ReqAtten, const int SteepIndex, const bool IsThird, const double PrevLatency)
Initalizes the half-band downsampler.
Definition CDSPHBDownsampler.h:47
virtual int getLatency() const
Return the latency, in samples, which is present in the output signal.
Definition CDSPHBDownsampler.h:105
virtual void clear()
Clears (resets) the state of this object and returns it to the state after construction.
Definition CDSPHBDownsampler.h:122
virtual int getMaxOutLen(const int MaxInLen) const
Returns the maximal length of the output buffer required when processing the MaxInLen number of input...
Definition CDSPHBDownsampler.h:115
virtual double getLatencyFrac() const
Returns fractional latency, in samples, which is present in the output signal.
Definition CDSPHBDownsampler.h:110