1 // Finite impulse response (FIR) resampler with adjustable FIR size
2
3 // $package
4 #ifndef FIR_RESAMPLER_H
5 #define FIR_RESAMPLER_H
6
7 #include "Resampler.h"
8
9 template<int width>
10 class Fir_Resampler;
11
12 // Use one of these typedefs
13 typedef Fir_Resampler< 8> Fir_Resampler_Fast;
14 typedef Fir_Resampler<16> Fir_Resampler_Norm;
15 typedef Fir_Resampler<24> Fir_Resampler_Good;
16
17 // Implementation
18 class Fir_Resampler_ : public Resampler {
19 protected:
20 virtual blargg_err_t set_rate_( double );
21 virtual void clear_();
22
23 protected:
24 enum { stereo = 2 };
25 enum { max_res = 32 }; // TODO: eliminate and keep impulses on freestore?
26 sample_t const* imp;
27 int const width_;
28 sample_t* impulses;
29
30 Fir_Resampler_( int width, sample_t [] );
31 };
32
33 // Width is number of points in FIR. More points give better quality and
34 // rolloff effectiveness, and take longer to calculate.
35 template<int width>
36 class Fir_Resampler : public Fir_Resampler_ {
37 enum { min_width = (width < 4 ? 4 : width) };
38 enum { adj_width = min_width / 4 * 4 + 2 };
39 enum { write_offset = adj_width * stereo };
40 short impulses [max_res * (adj_width + 2)];
41 public:
Fir_Resampler()42 Fir_Resampler() : Fir_Resampler_( adj_width, impulses ) { }
43
44 protected:
45 virtual sample_t const* resample_( sample_t**, sample_t const*, sample_t const [], int );
46 };
47
48 template<int width>
resample_(sample_t ** out_,sample_t const * out_end,sample_t const in[],int in_size)49 Resampler::sample_t const* Fir_Resampler<width>::resample_( sample_t** out_,
50 sample_t const* out_end, sample_t const in [], int in_size )
51 {
52 in_size -= write_offset;
53 if ( in_size > 0 )
54 {
55 sample_t* BLARGG_RESTRICT out = *out_;
56 sample_t const* const in_end = in + in_size;
57 sample_t const* imp = this->imp;
58
59 do
60 {
61 // accumulate in extended precision
62 int pt = imp [0];
63 int l = pt * in [0];
64 int r = pt * in [1];
65 if ( out >= out_end )
66 break;
67 for ( int n = (adj_width - 2) / 2; n; --n )
68 {
69 pt = imp [1];
70 l += pt * in [2];
71 r += pt * in [3];
72
73 // pre-increment more efficient on some RISC processors
74 imp += 2;
75 pt = imp [0];
76 r += pt * in [5];
77 in += 4;
78 l += pt * in [0];
79 }
80 pt = imp [1];
81 l += pt * in [2];
82 r += pt * in [3];
83
84 // these two "samples" after the end of the impulse give the
85 // proper offsets to the next input sample and next impulse
86 in = (sample_t const*) ((char const*) in + imp [2]); // some negative value
87 imp = (sample_t const*) ((char const*) imp + imp [3]); // small positive or large negative
88
89 out [0] = sample_t (l >> 15);
90 out [1] = sample_t (r >> 15);
91 out += 2;
92 }
93 while ( in < in_end );
94
95 this->imp = imp;
96 *out_ = out;
97 }
98 return in;
99 }
100
101 #endif
102