summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/ape.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/ape.c')
-rw-r--r--lib/rbcodec/codecs/ape.c70
1 files changed, 45 insertions, 25 deletions
diff --git a/lib/rbcodec/codecs/ape.c b/lib/rbcodec/codecs/ape.c
index 577e7b65e2..a6c5254d45 100644
--- a/lib/rbcodec/codecs/ape.c
+++ b/lib/rbcodec/codecs/ape.c
@@ -155,6 +155,7 @@ enum codec_status codec_run(void)
155 int res; 155 int res;
156 int firstbyte; 156 int firstbyte;
157 size_t resume_offset; 157 size_t resume_offset;
158 enum codec_command_action action;
158 intptr_t param; 159 intptr_t param;
159 160
160 if (codec_init()) { 161 if (codec_init()) {
@@ -162,8 +163,12 @@ enum codec_status codec_run(void)
162 return CODEC_ERROR; 163 return CODEC_ERROR;
163 } 164 }
164 165
166 action = CODEC_ACTION_NULL;
167 param = 0;
168
165 /* Remember the resume position - when the codec is opened, the 169 /* Remember the resume position - when the codec is opened, the
166 playback engine will reset it. */ 170 playback engine will reset it. */
171 elapsedtime = ci->id3->elapsed;
167 resume_offset = ci->id3->offset; 172 resume_offset = ci->id3->offset;
168 173
169 ci->seek_buffer(0); 174 ci->seek_buffer(0);
@@ -213,14 +218,21 @@ enum codec_status codec_run(void)
213 218
214 ape_resume(&ape_ctx, resume_offset, 219 ape_resume(&ape_ctx, resume_offset,
215 &currentframe, &samplesdone, &samplestoskip, &firstbyte); 220 &currentframe, &samplesdone, &samplestoskip, &firstbyte);
216 } else { 221 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
222 }
223 else {
217 currentframe = 0; 224 currentframe = 0;
218 samplesdone = 0; 225 samplesdone = 0;
219 samplestoskip = 0; 226 samplestoskip = 0;
220 firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */ 227 firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
228
229 if (elapsedtime) {
230 /* Resume by simulated seeking */
231 param = elapsedtime;
232 action = CODEC_ACTION_SEEK_TIME;
233 }
221 } 234 }
222 235
223 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
224 ci->set_elapsed(elapsedtime); 236 ci->set_elapsed(elapsedtime);
225 237
226 /* Initialise the buffer */ 238 /* Initialise the buffer */
@@ -247,36 +259,44 @@ frame_start:
247 /* Decode the frame a chunk at a time */ 259 /* Decode the frame a chunk at a time */
248 while (nblocks > 0) 260 while (nblocks > 0)
249 { 261 {
250 enum codec_command_action action = ci->get_command(&param); 262 if (action == CODEC_ACTION_NULL)
263 action = ci->get_command(&param);
251 264
252 if (action == CODEC_ACTION_HALT) 265 if (action != CODEC_ACTION_NULL) {
253 goto done; 266 if (action == CODEC_ACTION_HALT)
267 goto done;
254 268
255 /* Deal with any pending seek requests */ 269 /* Deal with any pending seek requests */
256 if (action == CODEC_ACTION_SEEK_TIME) 270 if (action == CODEC_ACTION_SEEK_TIME)
257 {
258 if (ape_calc_seekpos(&ape_ctx,
259 (param/10) * (ci->id3->frequency/100),
260 &currentframe,
261 &newfilepos,
262 &samplestoskip))
263 { 271 {
264 samplesdone = currentframe * ape_ctx.blocksperframe; 272 if (ape_calc_seekpos(&ape_ctx,
265 273 (param/10) * (ci->id3->frequency/100),
266 /* APE's bytestream is weird... */ 274 &currentframe,
267 firstbyte = 3 - (newfilepos & 3); 275 &newfilepos,
268 newfilepos &= ~3; 276 &samplestoskip))
269 277 {
270 ci->seek_buffer(newfilepos); 278 samplesdone = currentframe * ape_ctx.blocksperframe;
271 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); 279
280 /* APE's bytestream is weird... */
281 firstbyte = 3 - (newfilepos & 3);
282 newfilepos &= ~3;
283
284 ci->seek_buffer(newfilepos);
285 inbuffer = ci->request_buffer(&bytesleft,
286 INPUT_CHUNKSIZE);
287
288 elapsedtime = (samplesdone*10)/
289 (ape_ctx.samplerate/100);
290 ci->set_elapsed(elapsedtime);
291 ci->seek_complete();
292 action = CODEC_ACTION_NULL;
293 goto frame_start; /* Sorry... */
294 }
272 295
273 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
274 ci->set_elapsed(elapsedtime);
275 ci->seek_complete(); 296 ci->seek_complete();
276 goto frame_start; /* Sorry... */
277 } 297 }
278 298
279 ci->seek_complete(); 299 action = CODEC_ACTION_NULL;
280 } 300 }
281 301
282 blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks); 302 blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);