diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 107 |
1 files changed, 63 insertions, 44 deletions
diff --git a/apps/playback.c b/apps/playback.c index 5ed6c5e00c..7688534e07 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -216,6 +216,13 @@ static bool v1first = false; | |||
216 | static void mp3_set_elapsed(struct mp3entry* id3); | 216 | static void mp3_set_elapsed(struct mp3entry* id3); |
217 | int mp3_get_file_pos(void); | 217 | int mp3_get_file_pos(void); |
218 | 218 | ||
219 | #ifdef TIME_CODEC | ||
220 | bool is_filling(void) | ||
221 | { | ||
222 | return filling; | ||
223 | } | ||
224 | #endif | ||
225 | |||
219 | static void do_swap(int idx_old, int idx_new) | 226 | static void do_swap(int idx_old, int idx_new) |
220 | { | 227 | { |
221 | #ifndef SIMULATOR | 228 | #ifndef SIMULATOR |
@@ -287,13 +294,13 @@ static void voice_boost_cpu(bool state) | |||
287 | #define voice_boost_cpu(state) do { } while(0) | 294 | #define voice_boost_cpu(state) do { } while(0) |
288 | #endif | 295 | #endif |
289 | 296 | ||
290 | bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, | 297 | bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2, |
291 | long length) | 298 | size_t length) |
292 | { | 299 | { |
293 | char* src[2]; | 300 | const char* src[2]; |
294 | char *dest; | 301 | char *dest; |
295 | long input_size; | 302 | long input_size; |
296 | long output_size; | 303 | size_t output_size; |
297 | 304 | ||
298 | src[0] = ch1; | 305 | src[0] = ch1; |
299 | src[1] = ch2; | 306 | src[1] = ch2; |
@@ -311,47 +318,50 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, | |||
311 | } | 318 | } |
312 | 319 | ||
313 | while (length > 0) { | 320 | while (length > 0) { |
321 | long est_output_size = dsp_output_size(length); | ||
314 | /* This will prevent old audio from playing when skipping tracks. */ | 322 | /* This will prevent old audio from playing when skipping tracks. */ |
315 | if ((ci.reload_codec || ci.stop_codec) && | 323 | if (current_codec == CODEC_IDX_VOICE) { |
316 | current_codec != CODEC_IDX_VOICE) | 324 | while ((dest = pcmbuf_request_voice_buffer(est_output_size, |
317 | return true; | 325 | &output_size, audio_codec_loaded)) == NULL) |
318 | 326 | sleep(1); | |
319 | while ((dest = pcmbuf_request_buffer(dsp_output_size(length), | 327 | } |
320 | &output_size)) == NULL) { | 328 | else |
321 | sleep(1); | 329 | { |
322 | if ((ci.reload_codec || ci.stop_codec) && | 330 | if (ci.reload_codec || ci.stop_codec) |
323 | current_codec != CODEC_IDX_VOICE) | ||
324 | return true; | 331 | return true; |
332 | |||
333 | while ((dest = pcmbuf_request_buffer(est_output_size, | ||
334 | &output_size)) == NULL) { | ||
335 | sleep(1); | ||
336 | if (ci.reload_codec || ci.stop_codec) | ||
337 | return true; | ||
338 | } | ||
325 | } | 339 | } |
326 | 340 | ||
327 | /* Get the real input_size for output_size bytes, guarding | 341 | /* Get the real input_size for output_size bytes, guarding |
328 | * against resampling buffer overflows. */ | 342 | * against resampling buffer overflows. */ |
329 | input_size = dsp_input_size(output_size); | 343 | input_size = dsp_input_size(output_size); |
330 | if (input_size > length) { | ||
331 | DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld > %ld\n", | ||
332 | output_size, length, input_size, length); | ||
333 | input_size = length; | ||
334 | } | ||
335 | 344 | ||
336 | if (input_size <= 0) { | 345 | if (input_size <= 0) { |
337 | pcmbuf_flush_buffer(0); | ||
338 | DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n", | 346 | DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n", |
339 | output_size, length, input_size); | 347 | output_size, length, input_size); |
340 | /* should we really continue, or should we break? | 348 | /* this cannot happen */ |
341 | * We should probably continue because calling | 349 | break; |
342 | * pcmbuf_flush_buffer(0) will wrap the buffer if it was fully | ||
343 | * filled and so next call to pcmbuf_request_buffer should give | ||
344 | * the requested output_size. */ | ||
345 | continue; | ||
346 | } | 350 | } |
347 | 351 | ||
352 | if ((size_t)input_size > length) { | ||
353 | DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld > %ld\n", | ||
354 | output_size, length, input_size, length); | ||
355 | input_size = length; | ||
356 | } | ||
357 | |||
348 | output_size = dsp_process(dest, src, input_size); | 358 | output_size = dsp_process(dest, src, input_size); |
349 | 359 | ||
350 | /* Hotswap between audio and voice codecs as necessary. */ | 360 | /* Hotswap between audio and voice codecs as necessary. */ |
351 | switch (current_codec) | 361 | switch (current_codec) |
352 | { | 362 | { |
353 | case CODEC_IDX_AUDIO: | 363 | case CODEC_IDX_AUDIO: |
354 | pcmbuf_flush_buffer(output_size); | 364 | pcmbuf_write_complete(output_size); |
355 | if (voice_is_playing && pcmbuf_usage() > 30 | 365 | if (voice_is_playing && pcmbuf_usage() > 30 |
356 | && pcmbuf_mix_usage() < 20) | 366 | && pcmbuf_mix_usage() < 20) |
357 | { | 367 | { |
@@ -368,7 +378,7 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, | |||
368 | || pcmbuf_mix_usage() > 70) | 378 | || pcmbuf_mix_usage() > 70) |
369 | swap_codec(); | 379 | swap_codec(); |
370 | } else { | 380 | } else { |
371 | pcmbuf_flush_buffer(output_size); | 381 | pcmbuf_write_complete(output_size); |
372 | } | 382 | } |
373 | break ; | 383 | break ; |
374 | } | 384 | } |
@@ -379,7 +389,7 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, | |||
379 | return true; | 389 | return true; |
380 | } | 390 | } |
381 | 391 | ||
382 | bool codec_pcmbuf_insert_callback(char *buf, long length) | 392 | bool codec_pcmbuf_insert_callback(const char *buf, size_t length) |
383 | { | 393 | { |
384 | /* TODO: The audiobuffer API should probably be updated, and be based on | 394 | /* TODO: The audiobuffer API should probably be updated, and be based on |
385 | * pcmbuf_insert_split(). | 395 | * pcmbuf_insert_split(). |
@@ -405,9 +415,10 @@ void* get_codec_memory_callback(long *size) | |||
405 | return &audiobuf[0]; | 415 | return &audiobuf[0]; |
406 | } | 416 | } |
407 | 417 | ||
408 | static void pcmbuf_position_callback(int size) ICODE_ATTR; | 418 | static void pcmbuf_position_callback(size_t size) ICODE_ATTR; |
409 | static void pcmbuf_position_callback(int size) { | 419 | static void pcmbuf_position_callback(size_t size) { |
410 | unsigned int time = size * 1000 / 4 / 44100 + prev_ti->id3.elapsed; | 420 | unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY + |
421 | prev_ti->id3.elapsed; | ||
411 | if (time >= prev_ti->id3.length) { | 422 | if (time >= prev_ti->id3.length) { |
412 | pcmbuf_set_position_callback(NULL); | 423 | pcmbuf_set_position_callback(NULL); |
413 | prev_ti->id3.elapsed = prev_ti->id3.length; | 424 | prev_ti->id3.elapsed = prev_ti->id3.length; |
@@ -785,6 +796,13 @@ static void codec_track_changed(void) | |||
785 | queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0); | 796 | queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0); |
786 | } | 797 | } |
787 | 798 | ||
799 | static void pcmbuf_track_changed_callback(void) | ||
800 | { | ||
801 | track_changed = true; | ||
802 | pcmbuf_set_position_callback(NULL); | ||
803 | queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0); | ||
804 | } | ||
805 | |||
788 | /* Give codecs or file buffering the right amount of processing time | 806 | /* Give codecs or file buffering the right amount of processing time |
789 | to prevent pcm audio buffer from going empty. */ | 807 | to prevent pcm audio buffer from going empty. */ |
790 | static void yield_codecs(void) | 808 | static void yield_codecs(void) |
@@ -1529,7 +1547,7 @@ static void audio_update_trackinfo(void) | |||
1529 | /* Gapless playback. */ | 1547 | /* Gapless playback. */ |
1530 | else | 1548 | else |
1531 | { | 1549 | { |
1532 | pcmbuf_add_event(codec_track_changed); | 1550 | pcmbuf_set_event_handler(pcmbuf_track_changed_callback); |
1533 | } | 1551 | } |
1534 | } | 1552 | } |
1535 | 1553 | ||
@@ -1675,15 +1693,17 @@ bool codec_request_next_track_callback(void) | |||
1675 | the core has been requested the codec to be terminated. */ | 1693 | the core has been requested the codec to be terminated. */ |
1676 | return !ci_voice.stop_codec && queue_empty(&voice_codec_queue); | 1694 | return !ci_voice.stop_codec && queue_empty(&voice_codec_queue); |
1677 | } | 1695 | } |
1678 | #ifdef AB_REPEAT_ENABLE | ||
1679 | ab_end_of_track_report(); | ||
1680 | #endif | ||
1681 | |||
1682 | pcmbuf_set_position_callback(pcmbuf_position_callback); | ||
1683 | 1696 | ||
1684 | if (ci.stop_codec || !playing) | 1697 | if (ci.stop_codec || !playing) |
1685 | return false; | 1698 | return false; |
1686 | 1699 | ||
1700 | #ifdef AB_REPEAT_ENABLE | ||
1701 | ab_end_of_track_report(); | ||
1702 | #endif | ||
1703 | |||
1704 | if (!new_track) | ||
1705 | pcmbuf_set_position_callback(pcmbuf_position_callback); | ||
1706 | |||
1687 | logf("Request new track"); | 1707 | logf("Request new track"); |
1688 | 1708 | ||
1689 | /* Advance to next track. */ | 1709 | /* Advance to next track. */ |
@@ -1856,15 +1876,13 @@ void audio_thread(void) | |||
1856 | 1876 | ||
1857 | case Q_AUDIO_PAUSE: | 1877 | case Q_AUDIO_PAUSE: |
1858 | logf("audio_pause"); | 1878 | logf("audio_pause"); |
1859 | pcm_mute(true); | 1879 | pcmbuf_pause(true); |
1860 | pcm_play_pause(false); | ||
1861 | paused = true; | 1880 | paused = true; |
1862 | break ; | 1881 | break ; |
1863 | 1882 | ||
1864 | case Q_AUDIO_RESUME: | 1883 | case Q_AUDIO_RESUME: |
1865 | logf("audio_resume"); | 1884 | logf("audio_resume"); |
1866 | pcm_play_pause(true); | 1885 | pcmbuf_pause(false); |
1867 | pcm_mute(false); | ||
1868 | paused = false; | 1886 | paused = false; |
1869 | break ; | 1887 | break ; |
1870 | 1888 | ||
@@ -2022,8 +2040,9 @@ void codec_thread(void) | |||
2022 | static void reset_buffer(void) | 2040 | static void reset_buffer(void) |
2023 | { | 2041 | { |
2024 | filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; | 2042 | filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; |
2025 | filebuflen = audiobufend - audiobuf - pcmbuf_get_bufsize() | 2043 | filebuflen = audiobufend - audiobuf - MALLOC_BUFSIZE - GUARD_BUFSIZE - |
2026 | - PCMBUF_GUARD - MALLOC_BUFSIZE - GUARD_BUFSIZE; | 2044 | (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK); |
2045 | |||
2027 | 2046 | ||
2028 | if (talk_get_bufsize() && voice_codec_loaded) | 2047 | if (talk_get_bufsize() && voice_codec_loaded) |
2029 | { | 2048 | { |
@@ -2422,7 +2441,7 @@ void audio_set_buffer_margin(int setting) | |||
2422 | /* Set crossfade & PCM buffer length. */ | 2441 | /* Set crossfade & PCM buffer length. */ |
2423 | void audio_set_crossfade(int enable) | 2442 | void audio_set_crossfade(int enable) |
2424 | { | 2443 | { |
2425 | long size; | 2444 | size_t size; |
2426 | bool was_playing = playing; | 2445 | bool was_playing = playing; |
2427 | int offset = 0; | 2446 | int offset = 0; |
2428 | int seconds = 1; | 2447 | int seconds = 1; |