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#ifndef R8B_CDSPHBDOWNSAMPLER_INCLUDED
16#define R8B_CDSPHBDOWNSAMPLER_INCLUDED
17
18#include "CDSPHBUpsampler.h"
19
20namespace r8b {
21
30{
31public:
46 CDSPHBDownsampler( const double ReqAtten, const int SteepIndex,
47 const bool IsThird, const double PrevLatency )
48 {
49 static const CConvolveFn FltConvFn[ 14 ] = {
50 &CDSPHBDownsampler :: convolve1, &CDSPHBDownsampler :: convolve2,
51 &CDSPHBDownsampler :: convolve3, &CDSPHBDownsampler :: convolve4,
52 &CDSPHBDownsampler :: convolve5, &CDSPHBDownsampler :: convolve6,
53 &CDSPHBDownsampler :: convolve7, &CDSPHBDownsampler :: convolve8,
54 &CDSPHBDownsampler :: convolve9, &CDSPHBDownsampler :: convolve10,
55 &CDSPHBDownsampler :: convolve11, &CDSPHBDownsampler :: convolve12,
56 &CDSPHBDownsampler :: convolve13,
57 &CDSPHBDownsampler :: convolve14 };
58
59 const double* fltp0;
60 int fltt;
61 double att;
62
63 if( IsThird )
64 {
65 CDSPHBUpsampler :: getHBFilterThird( ReqAtten, SteepIndex, fltp0,
66 fltt, att );
67 }
68 else
69 {
70 CDSPHBUpsampler :: getHBFilter( ReqAtten, SteepIndex, fltp0, fltt,
71 att );
72 }
73
74 // Copy obtained filter to address-aligned buffer.
75
76 fltp = alignptr( FltBuf, 16 );
77 memcpy( fltp, fltp0, fltt * sizeof( fltp[ 0 ]));
78
79 convfn = FltConvFn[ fltt - 1 ];
80 fll = fltt;
81 fl2 = fltt - 1;
82 flo = fll + fl2;
83 flb = BufLen - fll;
84 BufRP1 = Buf1 + fll;
85 BufRP2 = Buf2 + fll - 1;
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( const int ReqOutPos ) const
100 {
101 return( flo + (int) (( Latency + LatencyFrac + ReqOutPos ) * 2.0 ));
102 }
103
104 virtual int getLatency() const
105 {
106 return( 0 );
107 }
108
109 virtual double getLatencyFrac() const
110 {
111 return( LatencyFrac );
112 }
113
114 virtual int getMaxOutLen( const int MaxInLen ) const
115 {
116 R8BASSERT( MaxInLen >= 0 );
117
118 return(( MaxInLen + 1 ) >> 1 );
119 }
120
121 virtual void clear()
122 {
123 LatencyLeft = Latency;
124 BufLeft = 0;
125 WritePos1 = 0;
126 WritePos2 = 0;
127 ReadPos = flb; // Set "read" position to account for filter's latency.
128
129 memset( &Buf1[ ReadPos ], 0, ( BufLen - flb ) * sizeof( Buf1[ 0 ]));
130 memset( &Buf2[ ReadPos ], 0, ( BufLen - flb ) * sizeof( Buf2[ 0 ]));
131 }
132
133 virtual int process( double* ip, int l, double*& op0 )
134 {
135 R8BASSERT( l >= 0 );
136
137 double* op = op0;
138
139 while( l > 0 )
140 {
141 // Copy new input samples to 2 ring buffers.
142
143 if( WritePos1 != WritePos2 )
144 {
145 // If previous fill was asymmetrical, put a single sample to
146 // Buf2.
147
148 double* const wp2 = Buf2 + WritePos2;
149 *wp2 = *ip;
150
151 if( WritePos2 < flo )
152 {
153 wp2[ BufLen ] = *ip;
154 }
155
156 ip++;
157 WritePos2 = WritePos1;
158 l--;
159 BufLeft++;
160 }
161
162 const int b1 = min(( l + 1 ) >> 1,
163 min( BufLen - WritePos1, flb - BufLeft ));
164
165 const int b2 = b1 - ( b1 * 2 > l );
166
167 double* wp1 = Buf1 + WritePos1;
168 double* wp2 = Buf2 + WritePos1;
169 double* const ipe = ip + b2 * 2;
170
171 while( ip != ipe )
172 {
173 *wp1 = ip[ 0 ];
174 *wp2 = ip[ 1 ];
175 wp1++;
176 wp2++;
177 ip += 2;
178 }
179
180 if( b1 != b2 )
181 {
182 *wp1 = *ip;
183 ip++;
184 }
185
186 const int ec = flo - WritePos1;
187
188 if( ec > 0 )
189 {
190 wp1 = Buf1 + WritePos1;
191 memcpy( wp1 + BufLen, wp1, min( b1, ec ) * sizeof( wp1[ 0 ]));
192 wp2 = Buf2 + WritePos1;
193 memcpy( wp2 + BufLen, wp2, min( b2, ec ) * sizeof( wp2[ 0 ]));
194 }
195
196 WritePos1 = ( WritePos1 + b1 ) & BufLenMask;
197 WritePos2 = ( WritePos2 + b2 ) & BufLenMask;
198 l -= b1 + b2;
199 BufLeft += b2;
200
201 // Produce output.
202
203 const int c = BufLeft - fl2;
204
205 if( c > 0 )
206 {
207 double* const opend = op + c;
208 ( *convfn )( op, opend, fltp, BufRP1, BufRP2, ReadPos );
209
210 op = opend;
211 ReadPos = ( ReadPos + c ) & BufLenMask;
212 BufLeft -= c;
213 }
214 }
215
216 int ol = (int) ( op - op0 );
217
218 if( LatencyLeft != 0 )
219 {
220 if( LatencyLeft >= ol )
221 {
222 LatencyLeft -= ol;
223 return( 0 );
224 }
225
226 ol -= LatencyLeft;
227 op0 += LatencyLeft;
228 LatencyLeft = 0;
229 }
230
231 return( ol );
232 }
233
234private:
235 static const int BufLenBits = 10;
241 static const int BufLen = 1 << BufLenBits;
244 static const int BufLenMask = BufLen - 1;
246 double Buf1[ BufLen + 27 ];
248 double Buf2[ BufLen + 27 ];
250 double FltBuf[ 14 + 2 ];
252 const double* BufRP1;
253 const double* BufRP2;
254 double* fltp;
255 double LatencyFrac;
256 int Latency;
257 int fll;
258 int fl2;
259 int flo;
260 int flb;
261 int LatencyLeft;
262 int BufLeft;
264 int WritePos1;
265 int WritePos2;
267 int ReadPos;
268
269 typedef void( *CConvolveFn )( double* op, double* const opend,
270 const double* const flt, const double* const rp01,
271 const double* const rp02, int rpos );
273 CConvolveFn convfn;
274
275#define R8BHBC1( fn ) \
276 static void fn( double* op, double* const opend, const double* const flt, \
277 const double* const rp01, const double* const rp02, int rpos ) \
278 { \
279 while( op != opend ) \
280 { \
281 const double* const rp1 = rp01 + rpos; \
282 const double* const rp = rp02 + rpos;
283
284#define R8BHBC2 \
285 rpos = ( rpos + 1 ) & BufLenMask; \
286 op++; \
287 } \
288 }
289
290#include "CDSPHBDownsampler.inc"
291
292#undef R8BHBC1
293#undef R8BHBC2
294};
295
296// ---------------------------------------------------------------------------
297
298} // namespace r8b
299
300#endif // R8B_CDSPHBDOWNSAMPLER_INCLUDED
Half-band upsampling class.
#define R8BASSERT(e)
Definition: r8bconf.h:27
#define R8BCONSOLE(...)
Definition: r8bconf.h:40
The "r8brain-free-src" library namespace.
Definition: CDSPBlockConvolver.h:21
T * alignptr(T *const ptr, const uintptr_t align)
Definition: r8bbase.h:279
T min(const T &v1, const T &v2)
Definition: r8bbase.h:1063
Half-band downsampler class.
Definition: CDSPHBDownsampler.h:30
virtual int getInLenBeforeOutPos(const int ReqOutPos) const
Definition: CDSPHBDownsampler.h:99
virtual int process(double *ip, int l, double *&op0)
Definition: CDSPHBDownsampler.h:133
CDSPHBDownsampler(const double ReqAtten, const int SteepIndex, const bool IsThird, const double PrevLatency)
Definition: CDSPHBDownsampler.h:46
virtual int getLatency() const
Definition: CDSPHBDownsampler.h:104
virtual void clear()
Definition: CDSPHBDownsampler.h:121
virtual int getMaxOutLen(const int MaxInLen) const
Definition: CDSPHBDownsampler.h:114
virtual double getLatencyFrac() const
Definition: CDSPHBDownsampler.h:109
The base virtual class for DSP processing algorithms.
Definition: CDSPProcessor.h:32