summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/resampler.c
diff options
context:
space:
mode:
authorAndree Buschmann <AndreeBuschmann@t-online.de>2011-08-17 22:20:09 +0000
committerAndree Buschmann <AndreeBuschmann@t-online.de>2011-08-17 22:20:09 +0000
commit4d01ace73fdffca366211157b54418516b3a73b6 (patch)
tree8165a373967a826ba67826b60f55911ac344c028 /apps/codecs/libgme/resampler.c
parent4070f4f17b77a030049e146245fc9a399bb68204 (diff)
downloadrockbox-4d01ace73fdffca366211157b54418516b3a73b6.tar.gz
rockbox-4d01ace73fdffca366211157b54418516b3a73b6.zip
Submit a patch to the VGM codec by Mauricio Gama which saves some more RAM through changes of the buffer configuration and an update of the resampler code. Additionally enable VGM for low memory targets and update the manual.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30327 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libgme/resampler.c')
-rw-r--r--apps/codecs/libgme/resampler.c426
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 };
25int const unit = 1 << shift; 25int const unit = 1 << shift;
26 26
27blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ) 27blargg_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
35blargg_err_t Resampler_reset( struct Resampler* this, int pairs ) 35blargg_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
47void Resampler_resize( struct Resampler* this, int pairs ) 50void 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
58static void mix_mono( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) 67void 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
91static void mix_stereo( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) 100sample_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
134static void mix_stereo_no_center( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) 138inline 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
172static 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
210static 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
224static int skip_input( struct Resampler* this, int count ) 152int 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
236static void play_frame_( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out ) 164void 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
288void Resampler_play( struct Resampler* this, long count, dsample_t* out, struct Stereo_Buffer* stereo_buf ) 188void 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}