annotate src/Input/console/Fir_Resampler.h @ 0:13389e613d67 trunk

[svn] - initial import of audacious-plugins tree (lots to do)
author nenolod
date Mon, 18 Sep 2006 01:11:49 -0700
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
1
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
2 // Finite impulse response (FIR) resampler with adjustable FIR size
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
3
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
4 // Game_Music_Emu 0.3.0
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
5
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
6 #ifndef FIR_RESAMPLER_H
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
7 #define FIR_RESAMPLER_H
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
8
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
9 #include "blargg_common.h"
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
10 #include <string.h>
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
11
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
12 class Fir_Resampler_ {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
13 public:
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
14
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
15 // Use Fir_Resampler<width> (below)
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
16
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
17 // Set input/output resampling ratio and optionally low-pass rolloff and gain.
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
18 // Returns actual ratio used (rounded to internal precision).
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
19 double time_ratio( double factor, double rolloff = 0.999, double gain = 1.0 );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
20
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
21 // Current input/output ratio
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
22 double ratio() const { return ratio_; }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
23
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
24 // Input
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
25
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
26 typedef short sample_t;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
27
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
28 // Resize and clear input buffer
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
29 blargg_err_t buffer_size( int );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
30
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
31 // Clear input buffer. At least two output samples will be available after
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
32 // two input samples are written.
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
33 void clear();
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
34
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
35 // Number of input samples that can be written
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
36 int max_write() const { return buf.end() - write_pos; }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
37
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
38 // Pointer to place to write input samples
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
39 sample_t* buffer() { return write_pos; }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
40
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
41 // Notify resampler that 'count' input samples have been written
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
42 void write( long count );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
43
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
44 // Number of input samples in buffer
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
45 int written() const { return write_pos - &buf [write_offset]; }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
46
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
47 // Skip 'count' input samples. Returns number of samples actually skipped.
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
48 int skip_input( long count );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
49
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
50 // Output
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
51
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
52 // Number of extra input samples needed until 'count' output samples are available
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
53 int input_needed( long count ) const;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
54
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
55 // Number of output samples available
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
56 int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
57
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
58 public:
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
59 ~Fir_Resampler_();
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
60 protected:
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
61 enum { stereo = 2 };
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
62 enum { max_res = 32 };
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
63 blargg_vector<sample_t> buf;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
64 sample_t* write_pos;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
65 int res;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
66 int imp;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
67 int const width_;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
68 int const write_offset;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
69 unsigned long skip_bits;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
70 int step;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
71 int input_per_cycle;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
72 double ratio_;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
73 sample_t* impulses;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
74
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
75 Fir_Resampler_( int width, sample_t* );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
76 int avail_( long input_count ) const;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
77 };
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
78
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
79 // Width is number of points in FIR. Must be even and 4 or more. More points give
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
80 // better quality and rolloff effectiveness, and take longer to calculate.
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
81 template<int width>
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
82 class Fir_Resampler : public Fir_Resampler_ {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
83 BOOST_STATIC_ASSERT( width >= 4 && width % 2 == 0 );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
84 short impulses [max_res] [width];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
85 public:
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
86 Fir_Resampler() : Fir_Resampler_( width, impulses [0] ) { }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
87
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
88 // Read at most 'count' samples. Returns number of samples actually read.
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
89 typedef short sample_t;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
90 int read( sample_t* out, long count );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
91 };
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
92
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
93 // End of public interface
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
94
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
95 inline void Fir_Resampler_::write( long count )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
96 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
97 write_pos += count;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
98 assert( write_pos <= buf.end() );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
99 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
100
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
101 template<int width>
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
102 int Fir_Resampler<width>::read( sample_t* out_begin, long count )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
103 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
104 sample_t* out = out_begin;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
105 const sample_t* in = buf.begin();
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
106 sample_t* end_pos = write_pos;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
107 unsigned long skip = skip_bits >> this->imp;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
108 sample_t const* imp = impulses [this->imp];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
109 int remain = res - this->imp;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
110 int const step = this->step;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
111
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
112 count >>= 1;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
113
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
114 if ( end_pos - in >= width * stereo )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
115 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
116 end_pos -= width * stereo;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
117 do
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
118 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
119 count--;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
120
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
121 // accumulate in extended precision
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
122 long l = 0;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
123 long r = 0;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
124
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
125 const sample_t* i = in;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
126 if ( count < 0 )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
127 break;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
128
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
129 for ( int n = width / 2; n; --n )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
130 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
131 int pt0 = imp [0];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
132 l += pt0 * i [0];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
133 r += pt0 * i [1];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
134 int pt1 = imp [1];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
135 imp += 2;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
136 l += pt1 * i [2];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
137 r += pt1 * i [3];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
138 i += 4;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
139 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
140
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
141 remain--;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
142
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
143 l >>= 15;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
144 r >>= 15;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
145
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
146 in += (skip * stereo) & stereo;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
147 skip >>= 1;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
148 in += step;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
149
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
150 if ( !remain )
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
151 {
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
152 imp = impulses [0];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
153 skip = skip_bits;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
154 remain = res;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
155 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
156
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
157 out [0] = l;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
158 out [1] = r;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
159 out += 2;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
160 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
161 while ( in <= end_pos );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
162 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
163
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
164 this->imp = res - remain;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
165
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
166 int left = write_pos - in;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
167 write_pos = &buf [left];
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
168 memmove( buf.begin(), in, left * sizeof *in );
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
169
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
170 return out - out_begin;
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
171 }
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
172
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
173 #endif
13389e613d67 [svn] - initial import of audacious-plugins tree (lots to do)
nenolod
parents:
diff changeset
174