diff options
Diffstat (limited to 'apps/codecs/libgme/resampler.c')
-rw-r--r-- | apps/codecs/libgme/resampler.c | 426 |
1 files changed, 163 insertions, 263 deletions
diff --git a/apps/codecs/libgme/resampler.c b/apps/codecs/libgme/resampler.c index a69a92cc53..e2e0734fc9 100644 --- a/apps/codecs/libgme/resampler.c +++ b/apps/codecs/libgme/resampler.c | |||
@@ -25,294 +25,194 @@ enum { shift = 14 }; | |||
25 | int const unit = 1 << shift; | 25 | int const unit = 1 << shift; |
26 | 26 | ||
27 | blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ) | 27 | blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ) |
28 | { | 28 | { |
29 | this->gain_ = (int)( ((1LL << gain_bits) * fm_gain * gain) / FP_ONE_GAIN ); | 29 | this->gain_ = (int)( ((1LL << gain_bits) * fm_gain * gain) / FP_ONE_GAIN ); |
30 | this->step = (int)( ((1LL << shift) * fm_rate) / rate + 1); | 30 | this->step = (int)( ((1LL << shift) * fm_rate) / rate + 1); |
31 | this->rate_ = this->step; | 31 | this->rate_ = this->step; |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | blargg_err_t Resampler_reset( struct Resampler* this, int pairs ) | 35 | blargg_err_t Resampler_reset( struct Resampler* this, int pairs ) |
36 | { | 36 | { |
37 | // expand allocations a bit | 37 | // expand allocations a bit |
38 | Resampler_resize( this, pairs ); | 38 | this->sample_buffer_size = (pairs + (pairs >> 2)) * 2; |
39 | this->resampler_size = this->oversamples_per_frame + (this->oversamples_per_frame >> 2); | 39 | Resampler_resize( this, pairs ); |
40 | 40 | this->resampler_size = this->oversamples_per_frame + (this->oversamples_per_frame >> 2); | |
41 | this->buffer_size = this->resampler_size; | 41 | |
42 | this->pos = 0; | 42 | this->buffer_size = this->resampler_size; |
43 | this->write_pos = 0; | 43 | this->pos = 0; |
44 | return 0; | 44 | this->write_pos = 0; |
45 | |||
46 | Resampler_clear( this ); | ||
47 | return 0; | ||
45 | } | 48 | } |
46 | 49 | ||
47 | void Resampler_resize( struct Resampler* this, int pairs ) | 50 | void Resampler_resize( struct Resampler* this, int pairs ) |
48 | { | 51 | { |
49 | int new_sample_buf_size = pairs * 2; | 52 | int new_sample_buf_size = pairs * 2; |
50 | if ( this->sample_buf_size != new_sample_buf_size ) | 53 | if ( this->sample_buf_size != new_sample_buf_size ) |
51 | { | 54 | { |
52 | this->sample_buf_size = new_sample_buf_size; | 55 | if ( new_sample_buf_size > this->sample_buffer_size ) |
53 | this->oversamples_per_frame = (int) ((pairs * this->rate_ * 2LL) / unit) + 2; | 56 | { |
54 | Resampler_clear( this ); | 57 | check(false); |
55 | } | 58 | return; |
59 | } | ||
60 | |||
61 | this->sample_buf_size = new_sample_buf_size; | ||
62 | this->oversamples_per_frame = (int) ((pairs * this->rate_ * 2LL) / unit) + 2; | ||
63 | Resampler_clear( this ); | ||
64 | } | ||
56 | } | 65 | } |
57 | 66 | ||
58 | static void mix_mono( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) | 67 | void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t out_ [] ) |
59 | { | 68 | { |
60 | int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); | 69 | int const bass = BLIP_READER_BASS( *blip_buf ); |
61 | BLIP_READER_BEGIN( sn, stereo_buf->bufs [0] ); | 70 | BLIP_READER_BEGIN( sn, *blip_buf ); |
62 | 71 | ||
63 | int count = this->sample_buf_size >> 1; | 72 | int count = this->sample_buf_size >> 1; |
64 | BLIP_READER_ADJ_( sn, count ); | 73 | BLIP_READER_ADJ_( sn, count ); |
65 | 74 | ||
66 | typedef dsample_t stereo_dsample_t [2]; | 75 | typedef sample_t stereo_dsample_t [2]; |
67 | stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; | 76 | stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; |
68 | stereo_dsample_t const* BLARGG_RESTRICT in = | 77 | stereo_dsample_t const* BLARGG_RESTRICT in = |
69 | (stereo_dsample_t const*) this->sample_buf + count; | 78 | (stereo_dsample_t const*) this->sample_buf + count; |
70 | int offset = -count; | 79 | int offset = -count; |
71 | int const gain = this->gain_; | 80 | int const gain = this->gain_; |
72 | do | 81 | do |
73 | { | 82 | { |
74 | int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16); | 83 | int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16); |
75 | BLIP_READER_NEXT_IDX_( sn, bass, offset ); | 84 | BLIP_READER_NEXT_IDX_( sn, bass, offset ); |
76 | 85 | ||
77 | int l = (in [offset] [0] * gain >> gain_bits) + s; | 86 | int l = (in [offset] [0] * gain >> gain_bits) + s; |
78 | int r = (in [offset] [1] * gain >> gain_bits) + s; | 87 | int r = (in [offset] [1] * gain >> gain_bits) + s; |
79 | 88 | ||
80 | BLIP_CLAMP( l, l ); | 89 | BLIP_CLAMP( l, l ); |
81 | out [offset] [0] = (blip_sample_t) l; | 90 | out [offset] [0] = (blip_sample_t) l; |
82 | 91 | ||
83 | BLIP_CLAMP( r, r ); | 92 | BLIP_CLAMP( r, r ); |
84 | out [offset] [1] = (blip_sample_t) r; | 93 | out [offset] [1] = (blip_sample_t) r; |
85 | } | 94 | } |
86 | while ( ++offset ); | 95 | while ( ++offset ); |
87 | 96 | ||
88 | BLIP_READER_END( sn, stereo_buf->bufs [0] ); | 97 | BLIP_READER_END( sn, *blip_buf ); |
89 | } | 98 | } |
90 | 99 | ||
91 | static void mix_stereo( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) | 100 | sample_t const* resample_( struct Resampler* this, sample_t** out_, |
101 | sample_t const* out_end, sample_t const in [], int in_size ) | ||
92 | { | 102 | { |
93 | int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); | 103 | in_size -= write_offset; |
94 | BLIP_READER_BEGIN( snc, stereo_buf->bufs [0] ); | 104 | if ( in_size > 0 ) |
95 | BLIP_READER_BEGIN( snl, stereo_buf->bufs [1] ); | 105 | { |
96 | BLIP_READER_BEGIN( snr, stereo_buf->bufs [2] ); | 106 | sample_t* BLARGG_RESTRICT out = *out_; |
97 | 107 | sample_t const* const in_end = in + in_size; | |
98 | int count = this->sample_buf_size >> 1; | 108 | |
99 | BLIP_READER_ADJ_( snc, count ); | 109 | int const step = this->step; |
100 | BLIP_READER_ADJ_( snl, count ); | 110 | int pos = this->pos; |
101 | BLIP_READER_ADJ_( snr, count ); | 111 | |
102 | 112 | // TODO: IIR filter, then linear resample | |
103 | typedef dsample_t stereo_dsample_t [2]; | 113 | // TODO: detect skipped sample, allowing merging of IIR and resample? |
104 | stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; | 114 | |
105 | stereo_dsample_t const* BLARGG_RESTRICT in = | 115 | do |
106 | (stereo_dsample_t const*) this->sample_buf + count; | 116 | { |
107 | int offset = -count; | 117 | #define INTERP( i, out )\ |
108 | int const gain = this->gain_; | 118 | out = (in [0 + i] * (unit - pos) + ((in [2 + i] + in [4 + i] + in [6 + i]) << shift) +\ |
109 | do | 119 | in [8 + i] * pos) >> (shift + 2); |
110 | { | 120 | |
111 | int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16); | 121 | int out_0; |
112 | int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16); | 122 | INTERP( 0, out_0 ) |
113 | int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16); | 123 | INTERP( 1, out [0] = out_0; out [1] ) |
114 | BLIP_READER_NEXT_IDX_( snc, bass, offset ); | 124 | out += stereo; |
115 | BLIP_READER_NEXT_IDX_( snl, bass, offset ); | 125 | |
116 | BLIP_READER_NEXT_IDX_( snr, bass, offset ); | 126 | pos += step; |
117 | 127 | in += ((unsigned) pos >> shift) * stereo; | |
118 | int l = (in [offset] [0] * gain >> gain_bits) + sl + sc; | 128 | pos &= unit - 1; |
119 | int r = (in [offset] [1] * gain >> gain_bits) + sr + sc; | 129 | } |
120 | 130 | while ( in < in_end && out < out_end ); | |
121 | BLIP_CLAMP( l, l ); | 131 | |
122 | out [offset] [0] = (blip_sample_t) l; | 132 | this->pos = pos; |
123 | 133 | *out_ = out; | |
124 | BLIP_CLAMP( r, r ); | 134 | } |
125 | out [offset] [1] = (blip_sample_t) r; | 135 | return in; |
126 | } | ||
127 | while ( ++offset ); | ||
128 | |||
129 | BLIP_READER_END( snc, stereo_buf->bufs [0] ); | ||
130 | BLIP_READER_END( snl, stereo_buf->bufs [1] ); | ||
131 | BLIP_READER_END( snr, stereo_buf->bufs [2] ); | ||
132 | } | 136 | } |
133 | 137 | ||
134 | static void mix_stereo_no_center( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) | 138 | inline int resample_wrapper( struct Resampler* this, sample_t out [], int* out_size, |
139 | sample_t const in [], int in_size ) | ||
135 | { | 140 | { |
136 | int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); | 141 | assert( Resampler_rate( this ) ); |
137 | BLIP_READER_BEGIN( snl, stereo_buf->bufs [1] ); | ||
138 | BLIP_READER_BEGIN( snr, stereo_buf->bufs [2] ); | ||
139 | |||
140 | int count = this->sample_buf_size >> 1; | ||
141 | BLIP_READER_ADJ_( snl, count ); | ||
142 | BLIP_READER_ADJ_( snr, count ); | ||
143 | |||
144 | typedef dsample_t stereo_dsample_t [2]; | ||
145 | stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; | ||
146 | stereo_dsample_t const* BLARGG_RESTRICT in = | ||
147 | (stereo_dsample_t const*) this->sample_buf + count; | ||
148 | int offset = -count; | ||
149 | int const gain = this->gain_; | ||
150 | do | ||
151 | { | ||
152 | int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16); | ||
153 | int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16); | ||
154 | BLIP_READER_NEXT_IDX_( snl, bass, offset ); | ||
155 | BLIP_READER_NEXT_IDX_( snr, bass, offset ); | ||
156 | |||
157 | int l = (in [offset] [0] * gain >> gain_bits) + sl; | ||
158 | int r = (in [offset] [1] * gain >> gain_bits) + sr; | ||
159 | |||
160 | BLIP_CLAMP( l, l ); | ||
161 | out [offset] [0] = (blip_sample_t) l; | ||
162 | |||
163 | BLIP_CLAMP( r, r ); | ||
164 | out [offset] [1] = (blip_sample_t) r; | ||
165 | } | ||
166 | while ( ++offset ); | ||
167 | |||
168 | BLIP_READER_END( snl, stereo_buf->bufs [1] ); | ||
169 | BLIP_READER_END( snr, stereo_buf->bufs [2] ); | ||
170 | } | ||
171 | 142 | ||
172 | static dsample_t const* resample_( struct Resampler* this, dsample_t** out_, | 143 | sample_t* out_ = out; |
173 | dsample_t const* out_end, dsample_t const in [], int in_size ) | 144 | int result = resample_( this, &out_, out + *out_size, in, in_size ) - in; |
174 | { | 145 | assert( out_ <= out + *out_size ); |
175 | in_size -= write_offset; | 146 | assert( result <= in_size ); |
176 | if ( in_size > 0 ) | ||
177 | { | ||
178 | dsample_t* BLIP_RESTRICT out = *out_; | ||
179 | dsample_t const* const in_end = in + in_size; | ||
180 | |||
181 | int const step = this->step; | ||
182 | int pos = this->pos; | ||
183 | |||
184 | // TODO: IIR filter, then linear resample | ||
185 | // TODO: detect skipped sample, allowing merging of IIR and resample? | ||
186 | |||
187 | do | ||
188 | { | ||
189 | #define INTERP( i, out )\ | ||
190 | out = (in [0 + i] * (unit - pos) + ((in [2 + i] + in [4 + i] + in [6 + i]) << shift) +\ | ||
191 | in [8 + i] * pos) >> (shift + 2); | ||
192 | |||
193 | int out_0; | ||
194 | INTERP( 0, out_0 ) | ||
195 | INTERP( 1, out [0] = out_0; out [1] ) | ||
196 | out += stereo; | ||
197 | |||
198 | pos += step; | ||
199 | in += ((unsigned) pos >> shift) * stereo; | ||
200 | pos &= unit - 1; | ||
201 | } | ||
202 | while ( in < in_end && out < out_end ); | ||
203 | |||
204 | this->pos = pos; | ||
205 | *out_ = out; | ||
206 | } | ||
207 | return in; | ||
208 | } | ||
209 | 147 | ||
210 | static inline int resample_wrapper( struct Resampler* this, dsample_t out [], int* out_size, | 148 | *out_size = out_ - out; |
211 | dsample_t const in [], int in_size ) | 149 | return result; |
212 | { | ||
213 | assert( Resampler_rate( this ) ); | ||
214 | |||
215 | dsample_t* out_ = out; | ||
216 | int result = resample_( this, &out_, out + *out_size, in, in_size ) - in; | ||
217 | assert( out_ <= out + *out_size ); | ||
218 | assert( result <= in_size ); | ||
219 | |||
220 | *out_size = out_ - out; | ||
221 | return result; | ||
222 | } | 150 | } |
223 | 151 | ||
224 | static int skip_input( struct Resampler* this, int count ) | 152 | int skip_input( struct Resampler* this, int count ) |
225 | { | 153 | { |
226 | this->write_pos -= count; | 154 | this->write_pos -= count; |
227 | if ( this->write_pos < 0 ) // occurs when downsampling | 155 | if ( this->write_pos < 0 ) // occurs when downsampling |
228 | { | 156 | { |
229 | count += this->write_pos; | 157 | count += this->write_pos; |
230 | this->write_pos = 0; | 158 | this->write_pos = 0; |
231 | } | 159 | } |
232 | memmove( this->buf, &this->buf [count], this->write_pos * sizeof this->buf [0] ); | 160 | memmove( this->buf, &this->buf [count], this->write_pos * sizeof this->buf [0] ); |
233 | return count; | 161 | return count; |
234 | } | 162 | } |
235 | 163 | ||
236 | static void play_frame_( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out ) | 164 | void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t* out ) |
237 | { | 165 | { |
238 | long pair_count = this->sample_buf_size >> 1; | 166 | int pair_count = this->sample_buf_size >> 1; |
239 | blip_time_t blip_time = Blip_count_clocks( &stereo_buf->bufs [0], pair_count ); | 167 | blip_time_t blip_time = Blip_count_clocks( blip_buf, pair_count ); |
240 | int sample_count = this->oversamples_per_frame - this->write_pos + resampler_extra; | 168 | int sample_count = this->oversamples_per_frame - this->write_pos + resampler_extra; |
241 | 169 | ||
242 | int new_count = this->callback( this->callback_data, blip_time, sample_count, &this->buf [this->write_pos] ); | 170 | int new_count = this->callback( this->callback_data, blip_time, sample_count, &this->buf [this->write_pos] ); |
243 | assert( new_count < resampler_size ); | 171 | assert( new_count < this->resampler_size ); |
244 | 172 | ||
245 | Buffer_end_frame( stereo_buf, blip_time ); | 173 | Blip_end_frame( blip_buf, blip_time ); |
246 | /* Blip_end_frame( &stereo_buf->bufs [0], blip_time ); */ | 174 | assert( Blip_samples_avail( blip_buf ) == pair_count ); |
247 | assert( Blip_samples_avail( &stereo_buf->bufs [0] ) == pair_count * 2 ); | 175 | |
248 | 176 | this->write_pos += new_count; | |
249 | this->write_pos += new_count; | 177 | assert( (unsigned) this->write_pos <= this->buffer_size ); |
250 | assert( (unsigned) this->write_pos <= this->buffer_size ); | 178 | |
251 | 179 | int count = this->sample_buf_size; | |
252 | new_count = this->sample_buf_size; | 180 | if ( count ) |
253 | if ( new_count ) | 181 | skip_input( this, resample_wrapper( this, this->sample_buf, &count, this->buf, this->write_pos ) ); |
254 | skip_input( this, resample_wrapper( this, this->sample_buf, &new_count, this->buf, this->write_pos ) ); | 182 | assert( count == this->sample_buf_size ); |
255 | assert( new_count == (long) this->sample_buf_size ); | 183 | |
256 | 184 | mix_samples( this, blip_buf, out ); | |
257 | int bufs_used = stereo_buf->stereo_added | stereo_buf->was_stereo; | 185 | Blip_remove_samples( blip_buf, pair_count ); |
258 | if ( bufs_used <= 1 ) { | ||
259 | mix_mono( this, stereo_buf, out ); | ||
260 | Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); | ||
261 | Blip_remove_silence( &stereo_buf->bufs [1], pair_count ); | ||
262 | Blip_remove_silence( &stereo_buf->bufs [2], pair_count ); | ||
263 | } | ||
264 | else if ( bufs_used & 1 ) { | ||
265 | mix_stereo( this, stereo_buf, out ); | ||
266 | Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); | ||
267 | Blip_remove_samples( &stereo_buf->bufs [1], pair_count ); | ||
268 | Blip_remove_samples( &stereo_buf->bufs [2], pair_count ); | ||
269 | } | ||
270 | else { | ||
271 | mix_stereo_no_center( this, stereo_buf, out ); | ||
272 | Blip_remove_silence( &stereo_buf->bufs [0], pair_count ); | ||
273 | Blip_remove_samples( &stereo_buf->bufs [1], pair_count ); | ||
274 | Blip_remove_samples( &stereo_buf->bufs [2], pair_count ); | ||
275 | } | ||
276 | |||
277 | // to do: this might miss opportunities for optimization | ||
278 | if ( !Blip_samples_avail( &stereo_buf->bufs [0] ) ) | ||
279 | { | ||
280 | stereo_buf->was_stereo = stereo_buf->stereo_added; | ||
281 | stereo_buf->stereo_added = 0; | ||
282 | } | ||
283 | |||
284 | /* mix_mono( this, stereo_buf, out ); | ||
285 | Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); */ | ||
286 | } | 186 | } |
287 | 187 | ||
288 | void Resampler_play( struct Resampler* this, long count, dsample_t* out, struct Stereo_Buffer* stereo_buf ) | 188 | void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* blip_buf ) |
289 | { | 189 | { |
290 | // empty extra buffer | 190 | // empty extra buffer |
291 | long remain = this->sample_buf_size - this->buf_pos; | 191 | int remain = this->sample_buf_size - this->buf_pos; |
292 | if ( remain ) | 192 | if ( remain ) |
293 | { | 193 | { |
294 | if ( remain > count ) | 194 | if ( remain > count ) |
295 | remain = count; | 195 | remain = count; |
296 | count -= remain; | 196 | count -= remain; |
297 | memcpy( out, &this->sample_buf [this->buf_pos], remain * sizeof *out ); | 197 | memcpy( out, &this->sample_buf [this->buf_pos], remain * sizeof *out ); |
298 | out += remain; | 198 | out += remain; |
299 | this->buf_pos += remain; | 199 | this->buf_pos += remain; |
300 | } | 200 | } |
301 | 201 | ||
302 | // entire frames | 202 | // entire frames |
303 | while ( count >= (long) this->sample_buf_size ) | 203 | while ( count >= this->sample_buf_size ) |
304 | { | 204 | { |
305 | play_frame_( this, stereo_buf, out ); | 205 | play_frame_( this, blip_buf, out ); |
306 | out += this->sample_buf_size; | 206 | out += this->sample_buf_size; |
307 | count -= this->sample_buf_size; | 207 | count -= this->sample_buf_size; |
308 | } | 208 | } |
309 | 209 | ||
310 | // extra | 210 | // extra |
311 | if ( count ) | 211 | if ( count ) |
312 | { | 212 | { |
313 | play_frame_( this, stereo_buf, this->sample_buf ); | 213 | play_frame_( this, blip_buf, this->sample_buf ); |
314 | this->buf_pos = count; | 214 | this->buf_pos = count; |
315 | memcpy( out, this->sample_buf, count * sizeof *out ); | 215 | memcpy( out, this->sample_buf, count * sizeof *out ); |
316 | out += count; | 216 | out += count; |
317 | } | 217 | } |
318 | } | 218 | } |