diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/codecmpa.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/apps/plugins/codecmpa.c b/apps/plugins/codecmpa.c index 86211df566..b152f2cb3e 100644 --- a/apps/plugins/codecmpa.c +++ b/apps/plugins/codecmpa.c | |||
@@ -172,7 +172,8 @@ const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE; | |||
172 | 172 | ||
173 | mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR; | 173 | mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR; |
174 | unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR; | 174 | unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR; |
175 | 175 | /* TODO: what latency does layer 1 have? */ | |
176 | int mpeg_latency[3] = { 0, 481, 529 }; | ||
176 | #ifdef USE_IRAM | 177 | #ifdef USE_IRAM |
177 | extern char iramcopy[]; | 178 | extern char iramcopy[]; |
178 | extern char iramstart[]; | 179 | extern char iramstart[]; |
@@ -185,6 +186,7 @@ extern char iramend[]; | |||
185 | enum plugin_status plugin_start(struct plugin_api* api, void* parm) | 186 | enum plugin_status plugin_start(struct plugin_api* api, void* parm) |
186 | { | 187 | { |
187 | struct codec_api *ci = (struct codec_api *)parm; | 188 | struct codec_api *ci = (struct codec_api *)parm; |
189 | struct mp3info *info; | ||
188 | int Status=0; | 190 | int Status=0; |
189 | size_t size; | 191 | size_t size; |
190 | int file_end; | 192 | int file_end; |
@@ -199,6 +201,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
199 | #endif | 201 | #endif |
200 | int i; | 202 | int i; |
201 | int yieldcounter = 0; | 203 | int yieldcounter = 0; |
204 | int stop_skip, start_skip; | ||
202 | 205 | ||
203 | /* Generic plugin inititialisation */ | 206 | /* Generic plugin inititialisation */ |
204 | 207 | ||
@@ -220,7 +223,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
220 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); | 223 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); |
221 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); | 224 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); |
222 | 225 | ||
223 | next_track: | ||
224 | memset(&Stream, 0, sizeof(struct mad_stream)); | 226 | memset(&Stream, 0, sizeof(struct mad_stream)); |
225 | memset(&Frame, 0, sizeof(struct mad_frame)); | 227 | memset(&Frame, 0, sizeof(struct mad_frame)); |
226 | memset(&Synth, 0, sizeof(struct mad_synth)); | 228 | memset(&Synth, 0, sizeof(struct mad_synth)); |
@@ -235,6 +237,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
235 | memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); | 237 | memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); |
236 | Frame.overlap = &mad_frame_overlap; | 238 | Frame.overlap = &mad_frame_overlap; |
237 | Stream.main_data = &mad_main_data; | 239 | Stream.main_data = &mad_main_data; |
240 | /* This label might need to be moved above all the init code, but I don't | ||
241 | think reiniting the codec is necessary for MPEG. It might even be unwanted | ||
242 | for gapless playback */ | ||
243 | next_track: | ||
238 | 244 | ||
239 | #ifdef DEBUG_GAPLESS | 245 | #ifdef DEBUG_GAPLESS |
240 | if (first) | 246 | if (first) |
@@ -243,7 +249,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
243 | fd = rb->open("/second.pcm", O_WRONLY | O_CREAT); | 249 | fd = rb->open("/second.pcm", O_WRONLY | O_CREAT); |
244 | first = false; | 250 | first = false; |
245 | #endif | 251 | #endif |
246 | 252 | ||
253 | info = ci->mp3data; | ||
247 | first_frame = false; | 254 | first_frame = false; |
248 | file_end = 0; | 255 | file_end = 0; |
249 | OutputPtr = OutputBuffer; | 256 | OutputPtr = OutputBuffer; |
@@ -254,9 +261,29 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
254 | 261 | ||
255 | ci->request_buffer(&size, ci->id3->first_frame_offset); | 262 | ci->request_buffer(&size, ci->id3->first_frame_offset); |
256 | ci->advance_buffer(size); | 263 | ci->advance_buffer(size); |
264 | |||
265 | if (info->enc_delay >= 0 && info->enc_padding >= 0) { | ||
266 | stop_skip = info->enc_padding - mpeg_latency[info->layer]; | ||
267 | if (stop_skip < 0) stop_skip = 0; | ||
268 | start_skip = info->enc_delay + mpeg_latency[info->layer]; | ||
269 | } else { | ||
270 | stop_skip = 0; | ||
271 | /* We want to skip this amount anyway */ | ||
272 | start_skip = mpeg_latency[info->layer]; | ||
273 | } | ||
257 | 274 | ||
258 | samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; | 275 | /* NOTE: currently this doesn't work, the below calculated samples_count |
259 | samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; | 276 | seems to be right, but sometimes libmad just can't supply us with |
277 | all the data we need... */ | ||
278 | if (info->frame_count) { | ||
279 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, | ||
280 | it's probably not correct at all for MPEG2 and layer 1 */ | ||
281 | samplecount = info->frame_count*1152 - (start_skip + stop_skip); | ||
282 | samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; | ||
283 | } else { | ||
284 | samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; | ||
285 | samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; | ||
286 | } | ||
260 | /* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount); | 287 | /* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount); |
261 | rb->splash(0, true, buf2); | 288 | rb->splash(0, true, buf2); |
262 | rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length); | 289 | rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length); |
@@ -304,7 +331,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
304 | /* This makes the codec to support partially corrupted files too. */ | 331 | /* This makes the codec to support partially corrupted files too. */ |
305 | if (file_end == 30) | 332 | if (file_end == 30) |
306 | break ; | 333 | break ; |
307 | 334 | ||
308 | /* Fill the buffer */ | 335 | /* Fill the buffer */ |
309 | Stream.error = 0; | 336 | Stream.error = 0; |
310 | file_end++; | 337 | file_end++; |
@@ -345,18 +372,22 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
345 | //} | 372 | //} |
346 | 373 | ||
347 | /* Convert MAD's numbers to an array of 16-bit LE signed integers */ | 374 | /* Convert MAD's numbers to an array of 16-bit LE signed integers */ |
348 | for(i=0;i<Synth.pcm.length;i++) | 375 | /* We skip start_skip number of samples here, this should only happen for |
376 | very first frame in the stream. */ | ||
377 | /* TODO: possible for start_skip to exceed one frames worth of samples? */ | ||
378 | for (i = start_skip;i<Synth.pcm.length;i++) | ||
349 | { | 379 | { |
380 | start_skip = 0; /* not very elegant, and might want to keep this value */ | ||
350 | samplesdone++; | 381 | samplesdone++; |
351 | //if (ci->mp3data->padding > 0) { | 382 | //if (ci->mp3data->padding > 0) { |
352 | // ci->mp3data->padding--; | 383 | // ci->mp3data->padding--; |
353 | // continue ; | 384 | // continue ; |
354 | //} | 385 | //} |
355 | if (!first_frame) { | 386 | /*if (!first_frame) { |
356 | if (detect_silence(Synth.pcm.samples[0][i])) | 387 | if (detect_silence(Synth.pcm.samples[0][i])) |
357 | continue ; | 388 | continue ; |
358 | first_frame = true; | 389 | first_frame = true; |
359 | } | 390 | }*/ |
360 | 391 | ||
361 | /* Left channel */ | 392 | /* Left channel */ |
362 | Sample=scale(Synth.pcm.samples[0][i],&d0); | 393 | Sample=scale(Synth.pcm.samples[0][i],&d0); |