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 = align_ptr( 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 BufRP = Buf + fll;
86
87 LatencyFrac = PrevLatency * 0.5;
88 Latency = (int) LatencyFrac;
89 LatencyFrac -= Latency;
90
91 R8BASSERT( Latency >= 0 );
92
93 R8BCONSOLE( "CDSPHBDownsampler: taps=%i third=%i att=%.1f io=1/2\n",
94 fltt, (int) IsThird, att );
95
96 clear();
97 }
98
99 virtual int getInLenBeforeOutPos( int ReqOutPos ) const
100 {
101 if( Next != R8B_NULL )
102 {
103 ReqOutPos = Next -> getInLenBeforeOutPos( ReqOutPos );
104 }
105
106 return( flo + (int) (( Latency + LatencyFrac + ReqOutPos ) * 2.0 ));
107 }
108
109 virtual int getLatency() const
110 {
111 return( 0 );
112 }
113
114 virtual double getLatencyFrac() const
115 {
116 return( LatencyFrac );
117 }
118
119 virtual int getMaxOutLen( const int MaxInLen ) const
120 {
121 R8BASSERT( MaxInLen >= 0 );
122
123 return(( MaxInLen + 1 ) >> 1 );
124 }
125
126 virtual void clear()
127 {
128 LatencyLeft = Latency;
129 BufLeft = 0;
130 WritePos1 = 0;
131 WritePos2 = 0;
132 ReadPos = flb; // Set "read" position to account for filter's latency.
133
134 memset( &Buf[ ReadPos ], 0,
135 (size_t) ( BufLen - flb ) * sizeof( Buf[ 0 ]));
136
137 memset( &Buf[ BufLenPad + ReadPos ], 0,
138 (size_t) ( BufLen - flb ) * sizeof( Buf[ 0 ]));
139 }
140
141 virtual int process( double* ip, int l, double*& op0 )
142 {
143 R8BASSERT( l >= 0 );
144
145 double* op = op0;
146
147 while( l > 0 )
148 {
149 // Copy new input samples to 2 ring buffers.
150
151 if( WritePos1 != WritePos2 )
152 {
153 // If previous fill was asymmetrical, put a single sample to
154 // the second buffer.
155
156 double* const wp2 = Buf + BufLenPad + WritePos2;
157 *wp2 = *ip;
158
159 if( WritePos2 < flo )
160 {
161 wp2[ BufLen ] = *ip;
162 }
163
164 ip++;
165 WritePos2 = WritePos1;
166 l--;
167 BufLeft++;
168 }
169
170 const int b1 = min(( l + 1 ) >> 1,
171 min( BufLen - WritePos1, flb - BufLeft ));
172
173 const int b2 = b1 - ( b1 * 2 > l );
174
175 double* const wp1 = Buf + WritePos1;
176 double* const wp2 = Buf + BufLenPad + WritePos1;
177 int i;
178
179 for( i = 0; i < b2; i++ )
180 {
181 wp1[ i ] = ip[ 0 ];
182 wp2[ i ] = ip[ 1 ];
183 ip += 2;
184 }
185
186 if( b1 != b2 )
187 {
188 wp1[ b2 ] = *ip;
189 ip++;
190 }
191
192 const int ec = flo - WritePos1;
193
194 if( ec > 0 )
195 {
196 memcpy( wp1 + BufLen, wp1,
197 (size_t) min( b1, ec ) * sizeof( wp1[ 0 ]));
198
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 int c = BufLeft - fl2;
211
212 while( c > 0 )
213 {
214 const int cb = min( c, BufLen - ReadPos );
215 double* const opend = op + cb;
216 ( *convfn )( op, opend, fltp, BufRP + ReadPos );
217
218 op = opend;
219 ReadPos = ( ReadPos + cb ) & BufLenMask;
220 BufLeft -= cb;
221 c -= cb;
222 }
223 }
224
225 int ol = (int) ( op - op0 );
226
227 if( LatencyLeft != 0 )
228 {
229 if( LatencyLeft >= ol )
230 {
231 LatencyLeft -= ol;
232 return( 0 );
233 }
234
235 ol -= LatencyLeft;
236 op0 += LatencyLeft;
237 LatencyLeft = 0;
238 }
239
240 return( ol );
241 }
242
243private:
244 static const int BufLenBits = 10;
250 static const int BufLen = 1 << BufLenBits;
253 static const int BufLenMask = BufLen - 1;
255 static const int FltBufLen = 14;
257 static const int BufLenPad = BufLen + ( FltBufLen * 2 - 1 );
260 double Buf[ BufLenPad * 2 ];
262 double FltBuf[ FltBufLen + 2 ];
264 const double* BufRP;
265 double* fltp;
266 double LatencyFrac;
267 int Latency;
268 int fll;
269 int fl2;
270 int flo;
271 int flb;
272 int LatencyLeft;
273 int BufLeft;
275 int WritePos1;
276 int WritePos2;
278 int ReadPos;
279
280 typedef void( *CConvolveFn )( double* op, double* const opend,
281 const double* const flt, const double* rp1 );
283 CConvolveFn convfn;
284
285#define R8BHBC1( fn ) \
286 static void fn( double* op, double* const opend, const double* const flt, \
287 const double* rp1 ) \
288 { \
289 while( op != opend ) \
290 { \
291 const double* const rp = rp1 + BufLenPad - 1;
292
293#define R8BHBC2 \
294 op++; \
295 rp1++; \
296 } \
297 }
298
299#include "CDSPHBDownsampler.inc"
300
301#undef R8BHBC1
302#undef R8BHBC2
303};
304
305// ---------------------------------------------------------------------------
306
307} // namespace r8b
308
309#endif // R8B_CDSPHBDOWNSAMPLER_INCLUDED
Half-band upsampling class.
#define R8B_NULL
The "null pointer" value, portable between C++11 and earlier C++ versions.
Definition r8bbase.h:101
#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 min(const T &v1, const T &v2)
Returns minimum of two values.
Definition r8bbase.h:1257
T * align_ptr(T *const ptr, const uintptr_t align)
Forces the provided ptr pointer to be aligned to align bytes.
Definition r8bbase.h:273
virtual int process(double *ip, int l, double *&op0)
Performs DSP processing.
Definition CDSPHBDownsampler.h:141
virtual int getInLenBeforeOutPos(int ReqOutPos) const
Returns the number of input samples required to advance to the specified output sample position (so t...
Definition CDSPHBDownsampler.h:99
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:109
virtual void clear()
Clears (resets) the state of this object and returns it to the state after construction.
Definition CDSPHBDownsampler.h:126
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:119
virtual double getLatencyFrac() const
Returns fractional latency, in samples, which is present in the output signal.
Definition CDSPHBDownsampler.h:114
CDSPProcessor * Next
Definition r8bbase.h:652