summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c107
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;
216static void mp3_set_elapsed(struct mp3entry* id3); 216static void mp3_set_elapsed(struct mp3entry* id3);
217int mp3_get_file_pos(void); 217int mp3_get_file_pos(void);
218 218
219#ifdef TIME_CODEC
220bool is_filling(void)
221{
222 return filling;
223}
224#endif
225
219static void do_swap(int idx_old, int idx_new) 226static 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
290bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, 297bool 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
382bool codec_pcmbuf_insert_callback(char *buf, long length) 392bool 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
408static void pcmbuf_position_callback(int size) ICODE_ATTR; 418static void pcmbuf_position_callback(size_t size) ICODE_ATTR;
409static void pcmbuf_position_callback(int size) { 419static 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
799static 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. */
790static void yield_codecs(void) 808static 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)
2022static void reset_buffer(void) 2040static 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. */
2423void audio_set_crossfade(int enable) 2442void 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;