summaryrefslogtreecommitdiff
path: root/apps/codecs
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
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')
-rw-r--r--apps/codecs/SOURCES2
-rw-r--r--apps/codecs/libgme/resampler.c426
-rw-r--r--apps/codecs/libgme/resampler.h74
-rw-r--r--apps/codecs/libgme/vgm_emu.c59
-rw-r--r--apps/codecs/libgme/vgm_emu.h6
5 files changed, 225 insertions, 342 deletions
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 6862eeda8e..db6e82c75f 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -37,8 +37,8 @@ gbs.c
37hes.c 37hes.c
38nsf.c 38nsf.c
39sgc.c 39sgc.c
40#if MEMORYSIZE > 2
41vgm.c 40vgm.c
41#if MEMORYSIZE > 2
42kss.c 42kss.c
43#endif 43#endif
44 44
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}
diff --git a/apps/codecs/libgme/resampler.h b/apps/codecs/libgme/resampler.h
index 3106b84d35..1d8f86670b 100644
--- a/apps/codecs/libgme/resampler.h
+++ b/apps/codecs/libgme/resampler.h
@@ -4,10 +4,10 @@
4#ifndef RESAMPLER_H 4#ifndef RESAMPLER_H
5#define RESAMPLER_H 5#define RESAMPLER_H
6 6
7#include "blargg_config.h" 7#include "blargg_common.h"
8#include "multi_buffer.h" 8#include "multi_buffer.h"
9 9
10typedef short dsample_t; 10typedef short sample_t;
11 11
12enum { stereo = 2 }; 12enum { stereo = 2 };
13enum { max_buf_size = 3960 }; 13enum { max_buf_size = 3960 };
@@ -15,54 +15,62 @@ enum { max_resampler_size = 5942 };
15enum { write_offset = 8 * stereo }; 15enum { write_offset = 8 * stereo };
16enum { gain_bits = 14 }; 16enum { gain_bits = 14 };
17 17
18struct Resampler { 18struct Resampler {
19 int (*callback)( void*, blip_time_t, int, dsample_t* ); 19 int (*callback)( void*, blip_time_t, int, sample_t* );
20 void* callback_data; 20 void* callback_data;
21 21
22 dsample_t sample_buf [max_buf_size]; 22 int sample_buffer_size;
23 int sample_buf_size; 23 int sample_buf_size;
24 int oversamples_per_frame; 24 int oversamples_per_frame;
25 int buf_pos; 25 int buf_pos;
26 int resampler_size; 26 int resampler_size;
27 int gain_; 27 int gain_;
28 28
29 // Internal resampler 29 int buffer_size;
30 dsample_t buf [max_resampler_size]; 30 int write_pos;
31 int buffer_size; 31
32 32 int pos;
33 int write_pos; 33 int step;
34 int rate_; 34
35 35 int rate_;
36 int pos; 36
37 int step; 37 sample_t sample_buf [max_buf_size];
38 sample_t buf [max_resampler_size]; // Internal resampler
38}; 39};
39 40
40static inline void Resampler_init( struct Resampler* this ) 41static inline void Resampler_init( struct Resampler* this )
41{ 42{
42 this->pos = 0; 43 this->pos = 0;
43 this->write_pos = 0; 44 this->write_pos = 0;
44 this->rate_ = 0; 45 this->rate_ = 0;
46 this->sample_buf_size = 0;
47 this->sample_buffer_size = 0;
48 this->oversamples_per_frame = 0;
45} 49}
46 50
47blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs ); 51blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs );
48void Resampler_resize( struct Resampler* this, int pairs_per_frame ); 52void Resampler_resize( struct Resampler* this, int pairs_per_frame );
49 53void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* );
50void Resampler_play( struct Resampler* this, long count, dsample_t* out, struct Stereo_Buffer* );
51 54
52static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, dsample_t* ), void* user_data ) 55static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, sample_t* ), void* user_data )
53{ 56{
54 this->callback = func; 57 this->callback = func;
55 this->callback_data = user_data; 58 this->callback_data = user_data;
56} 59}
57 60
58blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ); 61blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain );
59 62
60static inline void Resampler_clear( struct Resampler* this ) 63static inline void Resampler_clear( struct Resampler* this )
61{ 64{
62 this->buf_pos = this->sample_buf_size; 65 this->buf_pos = this->sample_buf_size;
66
67 this->pos = 0;
68 this->write_pos = 0;
69}
63 70
64 this->pos = 0; 71static inline int Resampler_rate( struct Resampler* this )
65 this->write_pos = 0; 72{
73 return this->rate_;
66} 74}
67 75
68#endif 76#endif
diff --git a/apps/codecs/libgme/vgm_emu.c b/apps/codecs/libgme/vgm_emu.c
index d599056bca..391bd02d73 100644
--- a/apps/codecs/libgme/vgm_emu.c
+++ b/apps/codecs/libgme/vgm_emu.c
@@ -89,8 +89,7 @@ void Vgm_init( struct Vgm_Emu* this )
89 Synth_init( &this->pcm ); 89 Synth_init( &this->pcm );
90 90
91 Buffer_init( &this->buf ); 91 Buffer_init( &this->buf );
92 Buffer_init( &this->stereo_buf ); 92 Blip_init( &this->blip_buf );
93 this->blip_buf = &this->stereo_buf.bufs [0];
94 93
95 // Init fm chips 94 // Init fm chips
96 Ym2413_init( &this->ym2413 ); 95 Ym2413_init( &this->ym2413 );
@@ -279,7 +278,7 @@ blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_
279 if ( !this->psg_rate ) 278 if ( !this->psg_rate )
280 this->psg_rate = 3579545; 279 this->psg_rate = 3579545;
281 280
282 Buffer_clock_rate( &this->stereo_buf, this->psg_rate ); 281 Blip_set_clock_rate( &this->blip_buf, this->psg_rate );
283 282
284 // Disable FM 283 // Disable FM
285 this->fm_rate = 0; 284 this->fm_rate = 0;
@@ -342,14 +341,14 @@ blargg_err_t setup_fm( struct Vgm_Emu* this )
342{ 341{
343 int fm_rate = 0; 342 int fm_rate = 0;
344 if ( !this->disable_oversampling ) 343 if ( !this->disable_oversampling )
345 this->fm_rate = (this->sample_rate * 3) / 2; // oversample factor = 1.5 344 fm_rate = (this->sample_rate * 3) / 2; // oversample factor = 1.5
346 RETURN_ERR( init_fm( this, &fm_rate ) ); 345 RETURN_ERR( init_fm( this, &fm_rate ) );
347 346
348 if ( uses_fm( this ) ) 347 if ( uses_fm( this ) )
349 { 348 {
350 this->voice_count = 8; 349 this->voice_count = 8;
351 RETURN_ERR( Resampler_setup( &this->resampler, fm_rate, fm_gain, this->sample_rate, this->gain ) ); 350 RETURN_ERR( Resampler_setup( &this->resampler, fm_rate, fm_gain, this->sample_rate, this->gain ) );
352 RETURN_ERR( Resampler_reset( &this->resampler, Buffer_length( &this->stereo_buf ) * this->sample_rate / 1000 ) ); 351 RETURN_ERR( Resampler_reset( &this->resampler, Blip_length( &this->blip_buf ) * this->sample_rate / 1000 ) );
353 Sms_apu_volume( &this->psg, ((this->gain/5)-(this->gain*5)/1000) * fm_gain ); 352 Sms_apu_volume( &this->psg, ((this->gain/5)-(this->gain*5)/1000) * fm_gain );
354 } 353 }
355 else 354 else
@@ -399,7 +398,7 @@ static blargg_err_t play_( struct Vgm_Emu* this, long count, sample_t* out )
399 return 0; 398 return 0;
400 } 399 }
401 400
402 Resampler_play( &this->resampler, count, out, &this->stereo_buf ); 401 Resampler_play( &this->resampler, count, out, &this->blip_buf );
403 return 0; 402 return 0;
404} 403}
405 404
@@ -428,19 +427,16 @@ static inline blip_time_t to_psg_time( struct Vgm_Emu* this, vgm_time_t t )
428 427
429static void write_pcm( struct Vgm_Emu* this, vgm_time_t vgm_time, int amp ) 428static void write_pcm( struct Vgm_Emu* this, vgm_time_t vgm_time, int amp )
430{ 429{
431 if ( this->blip_buf ) 430 check( amp >= 0 );
432 { 431 blip_time_t blip_time = to_psg_time( this, vgm_time );
433 check( amp >= 0 ); 432 int old = this->dac_amp;
434 blip_time_t blip_time = to_psg_time( this, vgm_time ); 433 int delta = amp - old;
435 int old = this->dac_amp; 434 this->dac_amp = amp;
436 int delta = amp - old; 435 Blip_set_modified( &this->blip_buf );
437 this->dac_amp = amp; 436 if ( old >= 0 ) // first write is ignored, to avoid click
438 Blip_set_modified( this->blip_buf ); 437 Synth_offset_inline( &this->pcm, blip_time, delta, &this->blip_buf );
439 if ( old >= 0 ) // first write is ignored, to avoid click 438 else
440 Synth_offset_inline( &this->pcm, blip_time, delta, this->blip_buf ); 439 this->dac_amp |= this->dac_disabled;
441 else
442 this->dac_amp |= this->dac_disabled;
443 }
444} 440}
445 441
446blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time ) 442blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
@@ -514,22 +510,7 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
514 510
515 case cmd_ym2612_port1: 511 case cmd_ym2612_port1:
516 if ( Ym2612_run_until( &this->ym2612, to_fm_time( this, vgm_time ) ) ) 512 if ( Ym2612_run_until( &this->ym2612, to_fm_time( this, vgm_time ) ) )
517 {
518 if ( pos [0] == ym2612_dac_pan_port )
519 {
520 struct Blip_Buffer* blip_buf = NULL;
521 switch ( pos [1] >> 6 )
522 {
523 case 0: blip_buf = NULL; break;
524 case 1: blip_buf = &this->stereo_buf.bufs [2]; break;
525 case 2: blip_buf = &this->stereo_buf.bufs [1]; break;
526 case 3: blip_buf = &this->stereo_buf.bufs [0]; break;
527 }
528 this->blip_buf = blip_buf;
529 }
530
531 Ym2612_write1( &this->ym2612, pos [0], pos [1] ); 513 Ym2612_write1( &this->ym2612, pos [0], pos [1] );
532 }
533 pos += 2; 514 pos += 2;
534 break; 515 break;
535 516
@@ -664,7 +645,7 @@ void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate )
664blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long rate ) 645blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long rate )
665{ 646{
666 require( !this->sample_rate ); // sample rate can't be changed once set 647 require( !this->sample_rate ); // sample rate can't be changed once set
667 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 30 ) ); 648 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) );
668 RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) ); 649 RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) );
669 650
670 // Set bass frequency 651 // Set bass frequency
@@ -712,7 +693,7 @@ void Sound_mute_voices( struct Vgm_Emu* this, int mask )
712 if ( uses_fm( this ) ) 693 if ( uses_fm( this ) )
713 { 694 {
714 for ( i = sms_osc_count; --i >= 0; ) 695 for ( i = sms_osc_count; --i >= 0; )
715 Sms_apu_set_output( &this->psg, i, ( mask & 0x80 ) ? 0 : &this->stereo_buf.bufs [0], NULL, NULL ); 696 Sms_apu_set_output( &this->psg, i, ( mask & 0x80 ) ? 0 : &this->blip_buf, NULL, NULL );
716 if ( Ym2612_enabled( &this->ym2612 ) ) 697 if ( Ym2612_enabled( &this->ym2612 ) )
717 { 698 {
718 Synth_volume( &this->pcm, (mask & 0x40) ? 0 : (int)((long long)(0.1115*FP_ONE_VOLUME) / 256 * fm_gain * this->gain / FP_ONE_VOLUME) ); 699 Synth_volume( &this->pcm, (mask & 0x40) ? 0 : (int)((long long)(0.1115*FP_ONE_VOLUME) / 256 * fm_gain * this->gain / FP_ONE_VOLUME) );
@@ -743,7 +724,7 @@ void Sound_set_tempo( struct Vgm_Emu* this, int t )
743 if ( this->file_begin ) 724 if ( this->file_begin )
744 { 725 {
745 this->vgm_rate = (long) ((44100LL * t) / FP_ONE_TEMPO); 726 this->vgm_rate = (long) ((44100LL * t) / FP_ONE_TEMPO);
746 this->blip_time_factor = (int) (((1LL << blip_time_bits) * Blip_clock_rate( &this->stereo_buf.bufs [0] )) / this->vgm_rate); 727 this->blip_time_factor = (int) (((1LL << blip_time_bits) * Blip_clock_rate( &this->blip_buf )) / this->vgm_rate);
747 //debug_printf( "blip_time_factor: %ld\n", blip_time_factor ); 728 //debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
748 //debug_printf( "vgm_rate: %ld\n", vgm_rate ); 729 //debug_printf( "vgm_rate: %ld\n", vgm_rate );
749 // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only) 730 // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
@@ -761,8 +742,6 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
761 742
762 Sms_apu_reset( &this->psg, get_le16( header( this )->noise_feedback ), header( this )->noise_width ); 743 Sms_apu_reset( &this->psg, get_le16( header( this )->noise_feedback ), header( this )->noise_width );
763 744
764 this->blip_buf = &this->stereo_buf.bufs [0];
765
766 this->dac_disabled = -1; 745 this->dac_disabled = -1;
767 this->pos = this->file_begin + header_size; 746 this->pos = this->file_begin + header_size;
768 this->pcm_data = this->pos; 747 this->pcm_data = this->pos;
@@ -785,7 +764,7 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
785 if ( Ym2612_enabled( &this->ym2612 ) ) 764 if ( Ym2612_enabled( &this->ym2612 ) )
786 Ym2612_reset( &this->ym2612 ); 765 Ym2612_reset( &this->ym2612 );
787 766
788 Buffer_clear( &this->stereo_buf ); 767 Blip_clear( &this->blip_buf, 1 );
789 Resampler_clear( &this->resampler ); 768 Resampler_clear( &this->resampler );
790 } 769 }
791 770
diff --git a/apps/codecs/libgme/vgm_emu.h b/apps/codecs/libgme/vgm_emu.h
index bc04086e9d..773b850a09 100644
--- a/apps/codecs/libgme/vgm_emu.h
+++ b/apps/codecs/libgme/vgm_emu.h
@@ -12,7 +12,6 @@
12#include "ym2612_emu.h" 12#include "ym2612_emu.h"
13#include "sms_apu.h" 13#include "sms_apu.h"
14 14
15typedef short sample_t;
16typedef int vgm_time_t; 15typedef int vgm_time_t;
17typedef int fm_time_t; 16typedef int fm_time_t;
18 17
@@ -85,7 +84,7 @@ struct Vgm_Emu {
85 int dac_amp; 84 int dac_amp;
86 int dac_disabled; // -1 if disabled 85 int dac_disabled; // -1 if disabled
87 86
88 struct Blip_Buffer* blip_buf; 87 struct Blip_Buffer blip_buf;
89 88
90 // general 89 // general
91 long clock_rate_; 90 long clock_rate_;
@@ -124,10 +123,7 @@ struct Vgm_Emu {
124 123
125 struct Sms_Apu psg; 124 struct Sms_Apu psg;
126 struct Blip_Synth pcm; 125 struct Blip_Synth pcm;
127 struct Stereo_Buffer stereo_buf;
128
129 struct Resampler resampler; 126 struct Resampler resampler;
130
131 struct Stereo_Buffer buf; 127 struct Stereo_Buffer buf;
132}; 128};
133 129