1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
50 #include "mp3_playback.h"
65 #ifdef HAVE_LCD_BITMAP
67 #include "peakmeter.h"
77 #include "ata_idle_notify.h"
80 #include "recording.h"
85 #include "menus/eq_menu.h"
88 #define PLAYBACK_VOICE
91 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* point at which the file buffer will fight for CPU time */
96 #define AUDIO_FILEBUF_CRITICAL (1024*128)
97 /* amount of guess-space to allow for codecs that must hunt and peck
98 * for their correct seeek target, 32k seems a good size */
99 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
101 /* macros to enable logf for queues
102 logging on SYS_TIMEOUT can be disabled */
104 /* Define this for logf output of all queuing except SYS_TIMEOUT */
105 #define PLAYBACK_LOGQUEUES
106 /* Define this to logf SYS_TIMEOUT messages */
107 #define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
110 #ifdef PLAYBACK_LOGQUEUES
111 #define LOGFQUEUE logf
113 #define LOGFQUEUE(...)
116 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
117 #define LOGFQUEUE_SYS_TIMEOUT logf
119 #define LOGFQUEUE_SYS_TIMEOUT(...)
123 /* Define one constant that includes recording related functionality */
124 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
125 #define AUDIO_HAVE_RECORDING
133 Q_AUDIO_PRE_FF_REWIND
,
135 Q_AUDIO_REBUFFER_SEEK
,
136 Q_AUDIO_CHECK_NEW_TRACK
,
138 Q_AUDIO_TRACK_CHANGED
,
143 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
,
145 Q_CODEC_REQUEST_COMPLETE
,
146 Q_CODEC_REQUEST_FAILED
,
154 #ifdef AUDIO_HAVE_RECORDING
160 /* As defined in plugins/lib/xxx2wav.h */
162 #define MALLOC_BUFSIZE (512*1024)
163 #define GUARD_BUFSIZE (32*1024)
165 #define MALLOC_BUFSIZE (100*1024)
166 #define GUARD_BUFSIZE (8*1024)
169 /* As defined in plugin.lds */
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
174 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
175 #define CODEC_IRAM_SIZE ((size_t)0x10000)
177 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
178 #define CODEC_IRAM_SIZE ((size_t)0xc000)
181 #ifndef IBSS_ATTR_VOICE_STACK
182 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
185 bool audio_is_initialized
= false;
187 /* Variables are commented with the threads that use them: *
188 * A=audio, C=codec, V=voice. A suffix of - indicates that *
189 * the variable is read but not updated on that thread. */
190 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
192 /* Main state control */
193 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR
= false; /* Codec loaded? (C/A-) */
194 static volatile bool playing NOCACHEBSS_ATTR
= false; /* Is audio playing? (A) */
195 static volatile bool paused NOCACHEBSS_ATTR
= false; /* Is audio paused? (A/C-) */
196 static volatile bool filling IDATA_ATTR
= false; /* Is file buffer refilling? (A/C-) */
198 /* Ring buffer where compressed audio and codecs are loaded */
199 static unsigned char *filebuf
= NULL
; /* Start of buffer (A/C-) */
200 static unsigned char *malloc_buf
= NULL
; /* Start of malloc buffer (A/C-) */
201 /* FIXME: make filebuflen static */
202 size_t filebuflen
= 0; /* Size of buffer (A/C-) */
203 /* FIXME: make buf_ridx (C/A-) */
204 static volatile size_t buf_ridx IDATA_ATTR
= 0; /* Buffer read position (A/C)*/
205 static volatile size_t buf_widx IDATA_ATTR
= 0; /* Buffer write position (A/C-) */
207 /* Possible arrangements of the buffer */
208 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
209 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
210 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
211 static int buffer_state
= BUFFER_STATE_TRASHED
; /* Buffer state */
213 /* Compressed ring buffer helper macros */
214 /* Buffer pointer (p) plus value (v), wrapped if necessary */
215 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
216 /* Buffer pointer (p) minus value (v), wrapped if necessary */
217 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
218 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
219 #define RINGBUF_ADD_CROSS(p1,v,p2) \
220 ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
221 /* Bytes available in the buffer */
222 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
224 /* Track info structure about songs in the file buffer (A/C-) */
226 struct mp3entry id3
; /* TAG metadata */
227 char *codecbuf
; /* Pointer to codec buffer */
228 size_t codecsize
; /* Codec length in bytes */
229 bool has_codec
; /* Does this track have a codec on the buffer */
231 size_t buf_idx
; /* Pointer to the track's buffer */
232 size_t filerem
; /* Remaining bytes of file NOT in buffer */
233 size_t filesize
; /* File total length */
234 size_t start_pos
; /* Position to first bytes of file in buffer */
235 volatile size_t available
; /* Available bytes to read from buffer */
237 bool taginfo_ready
; /* Is metadata read */
239 bool event_sent
; /* Was this track's buffered event sent */
242 static struct track_info tracks
[MAX_TRACK
];
243 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
244 static int track_widx
= 0; /* Track being buffered (A) */
246 static struct track_info
*prev_ti
= NULL
; /* Previous track info pointer (A/C-) */
247 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
249 /* Set by the audio thread when the current track information has updated
250 * and the WPS may need to update its cached information */
251 static bool track_changed
= false;
253 /* Information used only for filling the buffer */
254 /* Playlist steps from playing track to next track to be buffered (A) */
255 static int last_peek_offset
= 0;
256 /* Partially loaded track file handle to continue buffering (A) */
257 static int current_fd
= -1;
259 /* Scrobbler support */
260 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
262 /* Track change controls */
263 static bool automatic_skip
= false; /* Who initiated in-progress skip? (C/A-) */
264 static bool playlist_end
= false; /* Has the current playlist ended? (A) */
265 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
266 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
267 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
268 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
270 /* Callbacks which applications or plugins may set */
271 /* When the playing track has changed from the user's perspective */
272 void (*track_changed_callback
)(struct mp3entry
*id3
) = NULL
;
273 /* When a track has been buffered */
274 void (*track_buffer_callback
)(struct mp3entry
*id3
, bool last_track
) = NULL
;
275 /* When a track's buffer has been overwritten or cleared */
276 void (*track_unbuffer_callback
)(struct mp3entry
*id3
, bool last_track
) = NULL
;
279 static size_t conf_watermark
= 0; /* Level to trigger filebuf fill (A/C) FIXME */
280 static size_t conf_filechunk
= 0; /* Largest chunk the codec accepts (A/C) FIXME */
281 static size_t conf_preseek
= 0; /* Codec pre-seek margin (A/C) FIXME */
282 static size_t buffer_margin
= 0; /* Buffer margin aka anti-skip buffer (A/C-) */
284 static size_t high_watermark
= 0; /* High watermark for rebuffer (A/V/other) */
287 /* Multiple threads */
288 static void set_current_codec(int codec_idx
);
289 /* Set the watermark to trigger buffer fill (A/C) FIXME */
290 static void set_filebuf_watermark(int seconds
);
293 static struct event_queue audio_queue
;
294 static struct queue_sender_list audio_queue_sender_list
;
295 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
296 static const char audio_thread_name
[] = "audio";
298 static void audio_thread(void);
299 static void audio_initiate_track_change(long direction
);
300 static bool audio_have_tracks(void);
301 static void audio_reset_buffer(void);
304 extern struct codec_api ci
;
305 static struct event_queue codec_queue NOCACHEBSS_ATTR
;
306 static long codec_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
308 static const char codec_thread_name
[] = "codec";
309 struct thread_entry
*codec_thread_p
; /* For modifying thread priority later. */
311 static volatile int current_codec IDATA_ATTR
; /* Current codec (normal/voice) */
314 #ifdef PLAYBACK_VOICE
316 extern struct codec_api ci_voice
;
318 static struct thread_entry
*voice_thread_p
= NULL
;
319 static struct event_queue voice_queue NOCACHEBSS_ATTR
;
320 static long voice_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
321 IBSS_ATTR_VOICE_STACK
;
322 static const char voice_thread_name
[] = "voice codec";
324 /* Voice codec swapping control */
325 extern unsigned char codecbuf
[]; /* DRAM codec swap buffer */
328 /* IRAM codec swap buffer for sim*/
329 static unsigned char sim_iram
[CODEC_IRAM_SIZE
];
330 #undef CODEC_IRAM_ORIGIN
331 #define CODEC_IRAM_ORIGIN sim_iram
334 /* iram_buf and dram_buf are either both NULL or both non-NULL */
335 /* Pointer to IRAM buffer for codec swapping */
336 static unsigned char *iram_buf
= NULL
;
337 /* Pointer to DRAM buffer for codec swapping */
338 static unsigned char *dram_buf
= NULL
;
339 /* Parity of swap_codec calls - needed because one codec swapping itself in
340 automatically swaps in the other and the swap when unlocking should not
341 happen if the parity is even.
343 static bool swap_codec_parity
= false; /* true=odd, false=even */
344 /* Mutex to control which codec (normal/voice) is running */
345 static struct mutex mutex_codecthread NOCACHEBSS_ATTR
;
348 static volatile bool voice_thread_start
= false; /* Triggers voice playback (A/V) */
349 static volatile bool voice_is_playing NOCACHEBSS_ATTR
= false; /* Is voice currently playing? (V) */
350 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR
= false; /* Is voice codec loaded (V/A-) */
351 static unsigned char *voicebuf
= NULL
;
352 static size_t voice_remaining
= 0;
355 /* Voice IRAM has been stolen for other use */
356 static bool voice_iram_stolen
= false;
359 static void (*voice_getmore
)(unsigned char** start
, size_t* size
) = NULL
;
362 void (*callback
)(unsigned char **start
, size_t* size
);
366 static void voice_thread(void);
367 static void voice_stop(void);
369 #endif /* PLAYBACK_VOICE */
371 /* --- External interfaces --- */
373 void mp3_play_data(const unsigned char* start
, int size
,
374 void (*get_more
)(unsigned char** start
, size_t* size
))
376 #ifdef PLAYBACK_VOICE
377 static struct voice_info voice_clip
;
378 voice_clip
.callback
= get_more
;
379 voice_clip
.buf
= (unsigned char*)start
;
380 voice_clip
.size
= size
;
381 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
382 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
383 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
384 queue_post(&voice_queue
, Q_VOICE_PLAY
, (intptr_t)&voice_clip
);
385 voice_thread_start
= true;
394 void mp3_play_stop(void)
396 #ifdef PLAYBACK_VOICE
397 queue_remove_from_head(&voice_queue
, Q_VOICE_STOP
);
398 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
399 queue_post(&voice_queue
, Q_VOICE_STOP
, 1);
403 void mp3_play_pause(bool play
)
409 bool mp3_is_playing(void)
411 #ifdef PLAYBACK_VOICE
412 return voice_is_playing
;
418 /* If voice could be swapped out - wait for it to return
419 * Used by buffer claming functions.
421 static void wait_for_voice_swap_in(void)
423 #ifdef PLAYBACK_VOICE
424 if (NULL
== iram_buf
)
427 while (current_codec
!= CODEC_IDX_VOICE
)
429 #endif /* PLAYBACK_VOICE */
432 /* This sends a stop message and the audio thread will dump all it's
433 subsequenct messages */
434 static void audio_hard_stop(void)
437 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
438 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
441 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
443 unsigned char *buf
, *end
;
445 if (audio_is_initialized
)
448 wait_for_voice_swap_in();
449 #ifdef PLAYBACK_VOICE
453 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
455 if (buffer_size
== NULL
)
457 /* Special case for talk_init to use since it already knows it's
459 buffer_state
= BUFFER_STATE_TRASHED
;
463 if (talk_buf
|| buffer_state
== BUFFER_STATE_TRASHED
464 || !talk_voice_required())
466 logf("get buffer: talk, audio");
467 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
468 the talk buffer is not needed because voice isn't being used, or
469 could be BUFFER_STATE_TRASHED already. If state is
470 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
471 without the caller knowing what's going on. Changing certain settings
472 may move it to a worse condition but the memory in use by something
473 else will remain undisturbed.
475 if (buffer_state
!= BUFFER_STATE_TRASHED
)
478 buffer_state
= BUFFER_STATE_TRASHED
;
486 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
487 still BUFFER_STATE_INITIALIZED */
488 /* Skip talk buffer and move pcm buffer to end to maximize available
489 contiguous memory - no audio running means voice will not need the
491 logf("get buffer: audio");
492 buf
= audiobuf
+ talk_get_bufsize();
493 end
= audiobufend
- pcmbuf_init(audiobufend
);
494 buffer_state
= BUFFER_STATE_VOICED_ONLY
;
497 *buffer_size
= end
- buf
;
503 void audio_iram_steal(void)
505 /* We need to stop audio playback in order to use codec IRAM */
508 #ifdef PLAYBACK_VOICE
509 if (NULL
!= iram_buf
)
511 /* Can't already be stolen */
512 if (voice_iram_stolen
)
515 /* Must wait for voice to be current again if it is swapped which
516 would cause the caller's buffer to get clobbered when voice locks
517 and runs - we'll wait for it to lock and yield again then make sure
518 the ride has come to a complete stop */
519 wait_for_voice_swap_in();
522 /* Save voice IRAM but just memcpy - safe to do here since voice
523 is current and no audio codec is loaded */
524 memcpy(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
525 voice_iram_stolen
= true;
529 /* Nothing much to do if no voice */
530 voice_iram_stolen
= false;
534 #endif /* IRAM_STEAL */
536 #ifdef HAVE_RECORDING
537 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
539 /* Don't allow overwrite of voice swap area or we'll trash the
540 swapped-out voice codec but can use whole thing if none */
543 /* Stop audio and voice. Wait for voice to swap in and be clear
544 of pending events to ensure trouble-free operation of encoders */
546 wait_for_voice_swap_in();
547 #ifdef PLAYBACK_VOICE
552 #ifdef PLAYBACK_VOICE
553 /* If no dram_buf, swap space not used and recording gets more
554 memory. Codec swap areas will remain unaffected by the next init
555 since they're allocated at the end of the buffer and their sizes
556 don't change between calls */
559 #endif /* PLAYBACK_VOICE */
562 buffer_state
= BUFFER_STATE_TRASHED
;
564 *buffer_size
= end
- audiobuf
;
566 return (unsigned char *)audiobuf
;
569 bool audio_load_encoder(int afmt
)
572 const char *enc_fn
= get_codec_filename(afmt
| CODEC_TYPE_ENCODER
);
576 audio_remove_encoder();
577 ci
.enc_codec_loaded
= 0; /* clear any previous error condition */
579 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
580 queue_post(&codec_queue
, Q_ENCODER_LOAD_DISK
, (intptr_t)enc_fn
);
582 while (ci
.enc_codec_loaded
== 0)
585 logf("codec loaded: %d", ci
.enc_codec_loaded
);
587 return ci
.enc_codec_loaded
> 0;
592 } /* audio_load_encoder */
594 void audio_remove_encoder(void)
597 /* force encoder codec unload (if currently loaded) */
598 if (ci
.enc_codec_loaded
<= 0)
601 ci
.stop_encoder
= true;
602 while (ci
.enc_codec_loaded
> 0)
605 } /* audio_remove_encoder */
607 #endif /* HAVE_RECORDING */
609 struct mp3entry
* audio_current_track(void)
611 const char *filename
;
613 static struct mp3entry temp_id3
;
615 int offset
= ci
.new_track
+ wps_offset
;
617 cur_idx
= track_ridx
+ offset
;
618 cur_idx
&= MAX_TRACK_MASK
;
620 if (tracks
[cur_idx
].taginfo_ready
)
621 return &tracks
[cur_idx
].id3
;
623 memset(&temp_id3
, 0, sizeof(struct mp3entry
));
625 filename
= playlist_peek(0);
627 filename
= "No file!";
629 #ifdef HAVE_TC_RAMCACHE
630 if (tagcache_fill_tags(&temp_id3
, filename
))
634 p
= strrchr(filename
, '/');
640 strncpy(temp_id3
.path
, p
, sizeof(temp_id3
.path
)-1);
641 temp_id3
.title
= &temp_id3
.path
[0];
646 struct mp3entry
* audio_next_track(void)
648 int next_idx
= track_ridx
;
650 if (!audio_have_tracks())
654 next_idx
&= MAX_TRACK_MASK
;
656 if (!tracks
[next_idx
].taginfo_ready
)
659 return &tracks
[next_idx
].id3
;
662 bool audio_has_changed_track(void)
666 track_changed
= false;
673 void audio_play(long offset
)
677 #ifdef PLAYBACK_VOICE
678 /* Truncate any existing voice output so we don't have spelling
679 * etc. over the first part of the played track */
684 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
685 /* Don't return until playback has actually started */
686 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
689 void audio_stop(void)
692 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
693 /* Don't return until playback has actually stopped */
694 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
697 void audio_pause(void)
699 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
700 /* Don't return until playback has actually paused */
701 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
704 void audio_resume(void)
706 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
707 /* Don't return until playback has actually resumed */
708 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, false);
711 void audio_next(void)
713 if (playlist_check(ci
.new_track
+ wps_offset
+ 1))
715 if (global_settings
.beep
)
716 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
718 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
719 queue_post(&audio_queue
, Q_AUDIO_SKIP
, 1);
720 /* Update wps while our message travels inside deep playback queues. */
722 track_changed
= true;
726 /* No more tracks. */
727 if (global_settings
.beep
)
728 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
732 void audio_prev(void)
734 if (playlist_check(ci
.new_track
+ wps_offset
- 1))
736 if (global_settings
.beep
)
737 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
739 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
740 queue_post(&audio_queue
, Q_AUDIO_SKIP
, -1);
741 /* Update wps while our message travels inside deep playback queues. */
743 track_changed
= true;
747 /* No more tracks. */
748 if (global_settings
.beep
)
749 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
753 void audio_next_dir(void)
755 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
756 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
759 void audio_prev_dir(void)
761 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
762 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
765 void audio_pre_ff_rewind(void)
767 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
768 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
771 void audio_ff_rewind(long newpos
)
773 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
774 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
777 void audio_flush_and_reload_tracks(void)
779 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
780 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
783 void audio_error_clear(void)
785 #ifdef AUDIO_HAVE_RECORDING
786 pcm_rec_error_clear();
790 int audio_status(void)
795 ret
|= AUDIO_STATUS_PLAY
;
798 ret
|= AUDIO_STATUS_PAUSE
;
800 #ifdef HAVE_RECORDING
801 /* Do this here for constitency with mpeg.c version */
802 ret
|= pcm_rec_status();
808 int audio_get_file_pos(void)
813 #ifndef HAVE_FLASH_STORAGE
814 void audio_set_buffer_margin(int setting
)
816 static const int lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
817 buffer_margin
= lookup
[setting
];
818 logf("buffer margin: %ld", buffer_margin
);
819 set_filebuf_watermark(buffer_margin
);
823 /* Take nescessary steps to enable or disable the crossfade setting */
824 void audio_set_crossfade(int enable
)
830 /* Tell it the next setting to use */
831 pcmbuf_crossfade_enable(enable
);
833 /* Return if size hasn't changed or this is too early to determine
834 which in the second case there's no way we could be playing
836 if (pcmbuf_is_same_size())
838 /* This function is a copout and just syncs some variables -
839 to be removed at a later date */
840 pcmbuf_crossfade_enable_finished();
845 was_playing
= playing
;
847 /* Playback has to be stopped before changing the buffer size */
850 /* Store the track resume position */
851 offset
= CUR_TI
->id3
.offset
;
852 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK
));
855 /* Blast it - audio buffer will have to be setup again next time
857 audio_get_buffer(true, &size
);
859 /* Restart playback if audio was running previously */
864 /* --- Routines called from multiple threads --- */
865 static void set_current_codec(int codec_idx
)
867 current_codec
= codec_idx
;
868 dsp_configure(DSP_SWITCH_CODEC
, codec_idx
);
871 #ifdef PLAYBACK_VOICE
872 static void swap_codec(void)
876 /* Swap nothing if no swap buffers exist */
877 if (dram_buf
== NULL
)
879 logf("swap: no swap buffers");
883 my_codec
= current_codec
;
885 logf("swapping out codec: %d", my_codec
);
887 /* Invert this when a codec thread enters and leaves */
888 swap_codec_parity
= !swap_codec_parity
;
890 /* If this is true, an odd number of calls has occurred and there's
891 no codec thread waiting to swap us out when it locks and runs. This
892 occurs when playback is stopped or when just starting playback and
893 the audio thread is loading a codec; parities should always be even
894 on entry when a thread calls this during playback */
895 if (swap_codec_parity
)
897 /* Save our current IRAM and DRAM */
899 if (voice_iram_stolen
)
901 logf("swap: iram restore");
902 voice_iram_stolen
= false;
903 /* Don't swap trashed data into buffer as the voice IRAM will
904 already be swapped out - should _always_ be the case if
905 voice_iram_stolen is true since the voice has been swapped
907 if (my_codec
== CODEC_IDX_VOICE
)
909 logf("voice iram already swapped");
915 memswap128(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
921 memswap128(dram_buf
, codecbuf
, CODEC_SIZE
);
922 /* No cache invalidation needed; it will be done in codec_load_ram
923 or we won't be here otherwise */
926 /* Release my semaphore */
927 mutex_unlock(&mutex_codecthread
);
928 logf("unlocked: %d", my_codec
);
930 /* Loop until the other codec has locked and run */
932 /* Release my semaphore and force a task switch. */
934 } while (my_codec
== current_codec
);
936 /* Wait for other codec to unlock */
937 mutex_lock(&mutex_codecthread
);
940 logf("waiting for lock: %d", my_codec
);
941 set_current_codec(my_codec
);
943 /* Reload our IRAM and DRAM */
944 memswap128(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
945 memswap128(dram_buf
, codecbuf
, CODEC_SIZE
);
948 /* Flip parity again */
949 swap_codec_parity
= !swap_codec_parity
;
951 logf("resuming codec: %d", my_codec
);
954 /* This function is meant to be used by the buffer stealing functions to
955 ensure the codec is no longer active and so voice will be swapped-in
956 before it is called */
957 static void voice_stop(void)
959 /* Must have a voice codec loaded or we'll hang forever here */
960 if (!voice_codec_loaded
)
965 /* Loop until voice empties it's queue, stops and picks up on the new
966 track; the voice thread must be stopped and waiting for messages
968 while (voice_is_playing
|| !queue_empty(&voice_queue
) ||
976 /* Is voice still speaking */
977 /* Unfortunately only reliable when music is not also playing. */
978 static bool is_voice_speaking(void)
980 return is_voice_queued()
982 || (!playing
&& pcm_is_playing());
985 #endif /* PLAYBACK_VOICE */
987 /* Wait for voice to finish speaking. */
988 /* Also only reliable when music is not also playing. */
989 void voice_wait(void)
991 #ifdef PLAYBACK_VOICE
992 while (is_voice_speaking())
997 static void set_filebuf_watermark(int seconds
)
1002 return; /* Audio buffers not yet set up */
1004 bytes
= MAX(CUR_TI
->id3
.bitrate
* seconds
* (1000/8), conf_watermark
);
1005 bytes
= MIN(bytes
, filebuflen
/ 2);
1006 conf_watermark
= bytes
;
1009 const char * get_codec_filename(int cod_spec
)
1013 #ifdef HAVE_RECORDING
1014 /* Can choose decoder or encoder if one available */
1015 int type
= cod_spec
& CODEC_TYPE_MASK
;
1016 int afmt
= cod_spec
& CODEC_AFMT_MASK
;
1018 if ((unsigned)afmt
>= AFMT_NUM_CODECS
)
1019 type
= AFMT_UNKNOWN
| (type
& CODEC_TYPE_MASK
);
1021 fname
= (type
== CODEC_TYPE_ENCODER
) ?
1022 audio_formats
[afmt
].codec_enc_root_fn
:
1023 audio_formats
[afmt
].codec_root_fn
;
1026 (type
== CODEC_TYPE_ENCODER
) ? "Encoder" : "Decoder",
1027 afmt
, fname
? fname
: "<unknown>");
1028 #else /* !HAVE_RECORDING */
1029 /* Always decoder */
1030 if ((unsigned)cod_spec
>= AFMT_NUM_CODECS
)
1031 cod_spec
= AFMT_UNKNOWN
;
1032 fname
= audio_formats
[cod_spec
].codec_root_fn
;
1033 logf("Codec: %d - %s", cod_spec
, fname
? fname
: "<unknown>");
1034 #endif /* HAVE_RECORDING */
1037 } /* get_codec_filename */
1040 /* --- Voice thread --- */
1042 #ifdef PLAYBACK_VOICE
1044 static bool voice_pcmbuf_insert_callback(
1045 const void *ch1
, const void *ch2
, int count
)
1047 const char *src
[2] = { ch1
, ch2
};
1051 int out_count
= dsp_output_count(count
);
1055 while ((dest
= pcmbuf_request_voice_buffer(
1056 &out_count
, playing
)) == NULL
)
1058 if (playing
&& audio_codec_loaded
)
1064 /* Get the real input_size for output_size bytes, guarding
1065 * against resampling buffer overflows. */
1066 inp_count
= dsp_input_count(out_count
);
1071 /* Input size has grown, no error, just don't write more than length */
1072 if (inp_count
> count
)
1075 out_count
= dsp_process(dest
, src
, inp_count
);
1082 pcmbuf_mix_voice(out_count
);
1083 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1088 pcmbuf_write_complete(out_count
);
1094 } /* voice_pcmbuf_insert_callback */
1096 static void* voice_get_memory_callback(size_t *size
)
1098 /* Voice should have no use for this. If it did, we'd have to
1099 swap the malloc buffer as well. */
1104 static void voice_set_elapsed_callback(unsigned int value
)
1109 static void voice_set_offset_callback(size_t value
)
1114 static void voice_configure_callback(int setting
, intptr_t value
)
1116 if (!dsp_configure(setting
, value
))
1118 logf("Illegal key:%d", setting
);
1122 static size_t voice_filebuf_callback(void *ptr
, size_t size
)
1130 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1131 static bool voice_on_voice_stop(bool aborting
, size_t *realsize
)
1133 if (aborting
&& !playing
&& pcm_is_playing())
1135 /* Aborting: Slight hack - flush PCM buffer if
1136 only being used for voice */
1140 if (voice_is_playing
)
1142 /* Clear the current buffer */
1143 voice_is_playing
= false;
1144 voice_getmore
= NULL
;
1145 voice_remaining
= 0;
1148 /* Cancel any automatic boost if no more clips requested. */
1149 if (!playing
|| !voice_thread_start
)
1152 /* Force the codec to think it's changing tracks */
1153 ci_voice
.new_track
= 1;
1156 return true; /* Yes, change tracks */
1162 static void* voice_request_buffer_callback(size_t *realsize
, size_t reqsize
)
1166 if (ci_voice
.new_track
)
1174 if (voice_is_playing
|| playing
)
1176 queue_wait_w_tmo(&voice_queue
, &ev
, 0);
1177 if (!voice_is_playing
&& ev
.id
== SYS_TIMEOUT
)
1178 ev
.id
= Q_AUDIO_PLAY
;
1182 queue_wait(&voice_queue
, &ev
);
1187 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1190 if (audio_codec_loaded
)
1196 #ifdef AUDIO_HAVE_RECORDING
1197 case Q_ENCODER_RECORD
:
1198 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1204 LOGFQUEUE("voice < Q_VOICE_STOP");
1205 if (voice_on_voice_stop(ev
.data
, realsize
))
1209 case SYS_USB_CONNECTED
:
1211 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1212 bool change_tracks
= voice_on_voice_stop(ev
.data
, realsize
);
1213 /* Voice is obviously current so let us swap ourselves away if
1214 playing so audio may stop itself - audio_codec_loaded can
1215 only be true in this case if we're here even if the codec
1216 is only about to load */
1217 if (audio_codec_loaded
)
1219 /* Playback should be finished by now - ack and wait */
1220 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1221 usb_wait_for_disconnect(&voice_queue
);
1228 LOGFQUEUE("voice < Q_VOICE_PLAY");
1229 if (!voice_is_playing
)
1231 /* Set up new voice data */
1232 struct voice_info
*voice_data
;
1234 if (voice_iram_stolen
)
1236 /* Voice is the first to run again and is currently
1238 logf("voice: iram restore");
1239 memcpy(CODEC_IRAM_ORIGIN
, iram_buf
, CODEC_IRAM_SIZE
);
1240 voice_iram_stolen
= false;
1243 /* Must reset the buffer before any playback begins if
1245 if (buffer_state
== BUFFER_STATE_TRASHED
)
1246 audio_reset_buffer();
1248 voice_is_playing
= true;
1249 trigger_cpu_boost();
1250 voice_data
= (struct voice_info
*)ev
.data
;
1251 voice_remaining
= voice_data
->size
;
1252 voicebuf
= voice_data
->buf
;
1253 voice_getmore
= voice_data
->callback
;
1255 goto voice_play_clip
; /* To exit both switch and while */
1258 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1259 goto voice_play_clip
;
1262 LOGFQUEUE("voice < default");
1268 if (voice_remaining
== 0 || voicebuf
== NULL
)
1271 voice_getmore((unsigned char **)&voicebuf
, &voice_remaining
);
1273 /* If this clip is done */
1274 if (voice_remaining
== 0)
1276 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1277 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
1278 /* Force pcm playback. */
1279 if (!pcm_is_playing())
1280 pcmbuf_play_start();
1284 *realsize
= MIN(voice_remaining
, reqsize
);
1290 } /* voice_request_buffer_callback */
1292 static void voice_advance_buffer_callback(size_t amount
)
1294 amount
= MIN(amount
, voice_remaining
);
1296 voice_remaining
-= amount
;
1299 static void voice_advance_buffer_loc_callback(void *ptr
)
1301 size_t amount
= (size_t)ptr
- (size_t)voicebuf
;
1303 voice_advance_buffer_callback(amount
);
1306 static off_t
voice_mp3_get_filepos_callback(int newtime
)
1313 static void voice_do_nothing(void)
1318 static bool voice_seek_buffer_callback(size_t newpos
)
1325 static bool voice_request_next_track_callback(void)
1327 ci_voice
.new_track
= 0;
1331 static void voice_thread(void)
1333 logf("Loading voice codec");
1334 voice_codec_loaded
= true;
1335 mutex_lock(&mutex_codecthread
);
1336 set_current_codec(CODEC_IDX_VOICE
);
1337 dsp_configure(DSP_RESET
, 0);
1338 voice_remaining
= 0;
1339 voice_getmore
= NULL
;
1341 /* FIXME: If we being starting the voice thread without reboot, the
1342 voice_queue could be full of old stuff and we must flush it. */
1343 codec_load_file(get_codec_filename(AFMT_MPA_L3
), &ci_voice
);
1345 logf("Voice codec finished");
1346 voice_codec_loaded
= false;
1347 mutex_unlock(&mutex_codecthread
);
1348 voice_thread_p
= NULL
;
1349 remove_thread(NULL
);
1350 } /* voice_thread */
1352 #endif /* PLAYBACK_VOICE */
1354 /* --- Codec thread --- */
1355 static bool codec_pcmbuf_insert_callback(
1356 const void *ch1
, const void *ch2
, int count
)
1358 const char *src
[2] = { ch1
, ch2
};
1362 int out_count
= dsp_output_count(count
);
1366 /* Prevent audio from a previous track from playing */
1367 if (ci
.new_track
|| ci
.stop_codec
)
1370 while ((dest
= pcmbuf_request_buffer(&out_count
)) == NULL
)
1373 if (ci
.seek_time
|| ci
.new_track
|| ci
.stop_codec
)
1377 /* Get the real input_size for output_size bytes, guarding
1378 * against resampling buffer overflows. */
1379 inp_count
= dsp_input_count(out_count
);
1384 /* Input size has grown, no error, just don't write more than length */
1385 if (inp_count
> count
)
1388 out_count
= dsp_process(dest
, src
, inp_count
);
1393 pcmbuf_write_complete(out_count
);
1395 #ifdef PLAYBACK_VOICE
1396 if ((voice_is_playing
|| voice_thread_start
)
1397 && pcm_is_playing() && voice_codec_loaded
&&
1398 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1400 voice_thread_start
= false;
1409 } /* codec_pcmbuf_insert_callback */
1411 static void* codec_get_memory_callback(size_t *size
)
1413 *size
= MALLOC_BUFSIZE
;
1417 static void codec_pcmbuf_position_callback(size_t size
) ICODE_ATTR
;
1418 static void codec_pcmbuf_position_callback(size_t size
)
1420 /* This is called from an ISR, so be quick */
1421 unsigned int time
= size
* 1000 / 4 / NATIVE_FREQUENCY
+
1422 prev_ti
->id3
.elapsed
;
1424 if (time
>= prev_ti
->id3
.length
)
1426 pcmbuf_set_position_callback(NULL
);
1427 prev_ti
->id3
.elapsed
= prev_ti
->id3
.length
;
1430 prev_ti
->id3
.elapsed
= time
;
1433 static void codec_set_elapsed_callback(unsigned int value
)
1435 unsigned int latency
;
1439 #ifdef AB_REPEAT_ENABLE
1440 ab_position_report(value
);
1443 latency
= pcmbuf_get_latency();
1444 if (value
< latency
)
1445 CUR_TI
->id3
.elapsed
= 0;
1446 else if (value
- latency
> CUR_TI
->id3
.elapsed
||
1447 value
- latency
< CUR_TI
->id3
.elapsed
- 2)
1449 CUR_TI
->id3
.elapsed
= value
- latency
;
1453 static void codec_set_offset_callback(size_t value
)
1455 unsigned int latency
;
1460 latency
= pcmbuf_get_latency() * CUR_TI
->id3
.bitrate
/ 8;
1461 if (value
< latency
)
1462 CUR_TI
->id3
.offset
= 0;
1464 CUR_TI
->id3
.offset
= value
- latency
;
1467 static void codec_advance_buffer_counters(size_t amount
)
1469 buf_ridx
= RINGBUF_ADD(buf_ridx
, amount
);
1470 ci
.curpos
+= amount
;
1471 CUR_TI
->available
-= amount
;
1473 /* Start buffer filling as necessary. */
1474 if (!pcmbuf_is_lowdata() && !filling
)
1476 if (FILEBUFUSED
< conf_watermark
&& playing
&& !playlist_end
)
1478 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1479 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1484 /* copy up-to size bytes into ptr and return the actual size copied */
1485 static size_t codec_filebuf_callback(void *ptr
, size_t size
)
1487 char *buf
= (char *)ptr
;
1491 if (ci
.stop_codec
|| !playing
)
1494 /* The ammount to copy is the lesser of the requested amount and the
1495 * amount left of the current track (both on disk and already loaded) */
1496 copy_n
= MIN(size
, CUR_TI
->available
+ CUR_TI
->filerem
);
1498 /* Nothing requested OR nothing left */
1502 /* Let the disk buffer catch fill until enough data is available */
1503 while (copy_n
> CUR_TI
->available
)
1507 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1508 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1512 if (ci
.stop_codec
|| ci
.new_track
)
1516 /* Copy as much as possible without wrapping */
1517 part_n
= MIN(copy_n
, filebuflen
- buf_ridx
);
1518 memcpy(buf
, &filebuf
[buf_ridx
], part_n
);
1519 /* Copy the rest in the case of a wrap */
1520 if (part_n
< copy_n
) {
1521 memcpy(&buf
[part_n
], &filebuf
[0], copy_n
- part_n
);
1524 /* Update read and other position pointers */
1525 codec_advance_buffer_counters(copy_n
);
1527 /* Return the actual amount of data copied to the buffer */
1529 } /* codec_filebuf_callback */
1531 static void* codec_request_buffer_callback(size_t *realsize
, size_t reqsize
)
1533 size_t short_n
, copy_n
, buf_rem
;
1541 copy_n
= MIN(reqsize
, CUR_TI
->available
+ CUR_TI
->filerem
);
1548 while (copy_n
> CUR_TI
->available
)
1552 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1553 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1557 if (ci
.stop_codec
|| ci
.new_track
)
1564 /* How much is left at the end of the file buffer before wrap? */
1565 buf_rem
= filebuflen
- buf_ridx
;
1567 /* If we can't satisfy the request without wrapping */
1568 if (buf_rem
< copy_n
)
1570 /* How short are we? */
1571 short_n
= copy_n
- buf_rem
;
1573 /* If we can fudge it with the guardbuf */
1574 if (short_n
< GUARD_BUFSIZE
)
1575 memcpy(&filebuf
[filebuflen
], &filebuf
[0], short_n
);
1582 return (char *)&filebuf
[buf_ridx
];
1583 } /* codec_request_buffer_callback */
1585 static int get_codec_base_type(int type
)
1597 static void codec_advance_buffer_callback(size_t amount
)
1599 if (amount
> CUR_TI
->available
+ CUR_TI
->filerem
)
1600 amount
= CUR_TI
->available
+ CUR_TI
->filerem
;
1602 while (amount
> CUR_TI
->available
&& filling
)
1605 if (amount
> CUR_TI
->available
)
1607 intptr_t result
= Q_CODEC_REQUEST_FAILED
;
1611 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1612 result
= queue_send(&audio_queue
, Q_AUDIO_REBUFFER_SEEK
,
1613 ci
.curpos
+ amount
);
1618 case Q_CODEC_REQUEST_FAILED
:
1619 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1620 ci
.stop_codec
= true;
1623 case Q_CODEC_REQUEST_COMPLETE
:
1624 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1628 LOGFQUEUE("codec |< default");
1629 ci
.stop_codec
= true;
1634 codec_advance_buffer_counters(amount
);
1636 codec_set_offset_callback(ci
.curpos
);
1639 static void codec_advance_buffer_loc_callback(void *ptr
)
1641 size_t amount
= (size_t)ptr
- (size_t)&filebuf
[buf_ridx
];
1643 codec_advance_buffer_callback(amount
);
1646 /* Copied from mpeg.c. Should be moved somewhere else. */
1647 static int codec_get_file_pos(void)
1650 struct mp3entry
*id3
= audio_current_track();
1656 /* Use the TOC to find the new position */
1657 unsigned int percent
, remainder
;
1658 int curtoc
, nexttoc
, plen
;
1660 percent
= (id3
->elapsed
*100)/id3
->length
;
1664 curtoc
= id3
->toc
[percent
];
1667 nexttoc
= id3
->toc
[percent
+1];
1671 pos
= (id3
->filesize
/256)*curtoc
;
1673 /* Use the remainder to get a more accurate position */
1674 remainder
= (id3
->elapsed
*100)%id3
->length
;
1675 remainder
= (remainder
*100)/id3
->length
;
1676 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
1677 pos
+= (plen
/100)*remainder
;
1681 /* No TOC exists, estimate the new position */
1682 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
1683 (id3
->elapsed
/ 1000);
1686 else if (id3
->bitrate
)
1687 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
1691 pos
+= id3
->first_frame_offset
;
1693 /* Don't seek right to the end of the file so that we can
1694 transition properly to the next song */
1695 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
1696 pos
= id3
->filesize
- id3
->id3v1len
- 1;
1701 static off_t
codec_mp3_get_filepos_callback(int newtime
)
1705 CUR_TI
->id3
.elapsed
= newtime
;
1706 newpos
= codec_get_file_pos();
1711 static void codec_seek_complete_callback(void)
1713 logf("seek_complete");
1714 if (pcm_is_paused())
1716 /* If this is not a seamless seek, clear the buffer */
1718 dsp_configure(DSP_FLUSH
, 0);
1720 /* If playback was not 'deliberately' paused, unpause now */
1722 pcmbuf_pause(false);
1727 static bool codec_seek_buffer_callback(size_t newpos
)
1731 logf("codec_seek_buffer_callback");
1733 if (newpos
>= CUR_TI
->filesize
)
1734 newpos
= CUR_TI
->filesize
- 1;
1736 difference
= newpos
- ci
.curpos
;
1737 if (difference
>= 0)
1739 /* Seeking forward */
1740 logf("seek: +%d", difference
);
1741 codec_advance_buffer_callback(difference
);
1745 /* Seeking backward */
1746 difference
= -difference
;
1747 if (ci
.curpos
- difference
< 0)
1748 difference
= ci
.curpos
;
1750 /* We need to reload the song. */
1751 if (newpos
< CUR_TI
->start_pos
)
1753 intptr_t result
= Q_CODEC_REQUEST_FAILED
;
1757 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1758 result
= queue_send(&audio_queue
, Q_AUDIO_REBUFFER_SEEK
,
1764 case Q_CODEC_REQUEST_COMPLETE
:
1765 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1768 case Q_CODEC_REQUEST_FAILED
:
1769 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1770 ci
.stop_codec
= true;
1774 LOGFQUEUE("codec |< default");
1779 /* Seeking inside buffer space. */
1780 logf("seek: -%d", difference
);
1781 CUR_TI
->available
+= difference
;
1782 buf_ridx
= RINGBUF_SUB(buf_ridx
, (unsigned)difference
);
1783 ci
.curpos
-= difference
;
1788 static void codec_configure_callback(int setting
, intptr_t value
)
1791 case CODEC_SET_FILEBUF_WATERMARK
:
1792 conf_watermark
= value
;
1793 set_filebuf_watermark(buffer_margin
);
1796 case CODEC_SET_FILEBUF_CHUNKSIZE
:
1797 conf_filechunk
= value
;
1800 case CODEC_SET_FILEBUF_PRESEEK
:
1801 conf_preseek
= value
;
1805 if (!dsp_configure(setting
, value
)) { logf("Illegal key:%d", setting
); }
1809 static void codec_track_changed(void)
1811 automatic_skip
= false;
1812 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1813 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1816 static void codec_pcmbuf_track_changed_callback(void)
1818 pcmbuf_set_position_callback(NULL
);
1819 codec_track_changed();
1822 static void codec_discard_codec_callback(void)
1824 if (CUR_TI
->has_codec
)
1826 CUR_TI
->has_codec
= false;
1827 buf_ridx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->codecsize
);
1831 /* Check if a buffer desync has happened, log it and stop playback. */
1832 if (buf_ridx
!= CUR_TI
->buf_idx
)
1834 int offset
= CUR_TI
->buf_idx
- buf_ridx
;
1835 size_t new_used
= FILEBUFUSED
- offset
;
1837 logf("Buf off :%d=%d-%d", offset
, CUR_TI
->buf_idx
, buf_ridx
);
1838 logf("Used off:%d",FILEBUFUSED
- new_used
);
1840 /* This is a fatal internal error and it's not safe to
1841 * continue playback. */
1842 ci
.stop_codec
= true;
1843 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
1848 static inline void codec_gapless_track_change(void) {
1849 /* callback keeps the progress bar moving while the pcmbuf empties */
1850 pcmbuf_set_position_callback(codec_pcmbuf_position_callback
);
1851 /* set the pcmbuf callback for when the track really changes */
1852 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback
);
1855 static inline void codec_crossfade_track_change(void) {
1856 /* Initiate automatic crossfade mode */
1857 pcmbuf_crossfade_init(false);
1858 /* Notify the wps that the track change starts now */
1859 codec_track_changed();
1862 static void codec_track_skip_done(bool was_manual
)
1864 int crossfade_mode
= global_settings
.crossfade
;
1866 /* Manual track change (always crossfade or flush audio). */
1869 pcmbuf_crossfade_init(true);
1870 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1871 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1873 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1874 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1875 && crossfade_mode
!= CROSSFADE_ENABLE_TRACKSKIP
)
1877 if (crossfade_mode
== CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP
)
1879 if (global_settings
.playlist_shuffle
)
1880 /* shuffle mode is on, so crossfade: */
1881 codec_crossfade_track_change();
1883 /* shuffle mode is off, so do a gapless track change */
1884 codec_gapless_track_change();
1887 /* normal crossfade: */
1888 codec_crossfade_track_change();
1891 /* normal gapless playback. */
1892 codec_gapless_track_change();
1895 static bool codec_load_next_track(void)
1897 intptr_t result
= Q_CODEC_REQUEST_FAILED
;
1899 prev_track_elapsed
= CUR_TI
->id3
.elapsed
;
1902 codec_seek_complete_callback();
1904 #ifdef AB_REPEAT_ENABLE
1905 ab_end_of_track_report();
1908 logf("Request new track");
1910 if (ci
.new_track
== 0)
1913 automatic_skip
= true;
1918 trigger_cpu_boost();
1919 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1920 result
= queue_send(&audio_queue
, Q_AUDIO_CHECK_NEW_TRACK
, 0);
1925 case Q_CODEC_REQUEST_COMPLETE
:
1926 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1927 codec_track_skip_done(!automatic_skip
);
1930 case Q_CODEC_REQUEST_FAILED
:
1931 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1933 ci
.stop_codec
= true;
1937 LOGFQUEUE("codec |< default");
1938 ci
.stop_codec
= true;
1943 static bool codec_request_next_track_callback(void)
1947 if (ci
.stop_codec
|| !playing
)
1950 prev_codectype
= get_codec_base_type(CUR_TI
->id3
.codectype
);
1952 if (!codec_load_next_track())
1955 /* Check if the next codec is the same file. */
1956 if (prev_codectype
== get_codec_base_type(CUR_TI
->id3
.codectype
))
1958 logf("New track loaded");
1959 codec_discard_codec_callback();
1964 logf("New codec:%d/%d", CUR_TI
->id3
.codectype
, prev_codectype
);
1969 static void codec_thread(void)
1977 queue_wait(&codec_queue
, &ev
);
1980 case Q_CODEC_LOAD_DISK
:
1981 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1982 audio_codec_loaded
= true;
1983 #ifdef PLAYBACK_VOICE
1984 /* Don't sent messages to voice codec if it's already swapped
1985 out or it will never get this */
1986 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1988 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1989 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
1991 mutex_lock(&mutex_codecthread
);
1993 set_current_codec(CODEC_IDX_AUDIO
);
1994 ci
.stop_codec
= false;
1995 status
= codec_load_file((const char *)ev
.data
, &ci
);
1996 #ifdef PLAYBACK_VOICE
1997 mutex_unlock(&mutex_codecthread
);
2002 LOGFQUEUE("codec < Q_CODEC_LOAD");
2003 if (!CUR_TI
->has_codec
) {
2004 logf("Codec slot is empty!");
2005 /* Wait for the pcm buffer to go empty */
2006 while (pcm_is_playing())
2008 /* This must be set to prevent an infinite loop */
2009 ci
.stop_codec
= true;
2010 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
2011 queue_post(&codec_queue
, Q_AUDIO_PLAY
, 0);
2015 audio_codec_loaded
= true;
2016 #ifdef PLAYBACK_VOICE
2017 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
2019 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2020 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
2022 mutex_lock(&mutex_codecthread
);
2024 set_current_codec(CODEC_IDX_AUDIO
);
2025 ci
.stop_codec
= false;
2026 wrap
= (size_t)&filebuf
[filebuflen
] - (size_t)CUR_TI
->codecbuf
;
2027 status
= codec_load_ram(CUR_TI
->codecbuf
, CUR_TI
->codecsize
,
2028 &filebuf
[0], wrap
, &ci
);
2029 #ifdef PLAYBACK_VOICE
2030 mutex_unlock(&mutex_codecthread
);
2034 #ifdef AUDIO_HAVE_RECORDING
2035 case Q_ENCODER_LOAD_DISK
:
2036 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2037 audio_codec_loaded
= false; /* Not audio codec! */
2038 #ifdef PLAYBACK_VOICE
2039 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
2041 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2042 queue_post(&voice_queue
, Q_ENCODER_RECORD
, 0);
2044 mutex_lock(&mutex_codecthread
);
2046 logf("loading encoder");
2047 set_current_codec(CODEC_IDX_AUDIO
);
2048 ci
.stop_encoder
= false;
2049 status
= codec_load_file((const char *)ev
.data
, &ci
);
2050 #ifdef PLAYBACK_VOICE
2051 mutex_unlock(&mutex_codecthread
);
2053 logf("encoder stopped");
2055 #endif /* AUDIO_HAVE_RECORDING */
2058 case SYS_USB_CONNECTED
:
2059 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2060 queue_clear(&codec_queue
);
2061 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2062 usb_wait_for_disconnect(&codec_queue
);
2067 LOGFQUEUE("codec < default");
2070 if (audio_codec_loaded
)
2079 audio_codec_loaded
= false;
2083 case Q_CODEC_LOAD_DISK
:
2085 LOGFQUEUE("codec < Q_CODEC_LOAD");
2088 if (ci
.new_track
|| status
!= CODEC_OK
)
2092 logf("Codec failure");
2093 gui_syncsplash(HZ
*2, "Codec failure");
2096 if (!codec_load_next_track())
2098 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2099 /* End of playlist */
2100 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
2106 logf("Codec finished");
2109 /* Wait for the audio to stop playing before
2110 * triggering the WPS exit */
2111 while(pcm_is_playing())
2113 CUR_TI
->id3
.elapsed
=
2114 CUR_TI
->id3
.length
- pcmbuf_get_latency();
2117 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2118 /* End of playlist */
2119 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
2124 if (CUR_TI
->has_codec
)
2126 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2127 queue_post(&codec_queue
, Q_CODEC_LOAD
, 0);
2131 const char *codec_fn
=
2132 get_codec_filename(CUR_TI
->id3
.codectype
);
2133 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2134 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
,
2135 (intptr_t)codec_fn
);
2140 #ifdef AUDIO_HAVE_RECORDING
2141 case Q_ENCODER_LOAD_DISK
:
2142 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2144 if (status
== CODEC_OK
)
2147 logf("Encoder failure");
2148 gui_syncsplash(HZ
*2, "Encoder failure");
2150 if (ci
.enc_codec_loaded
< 0)
2153 logf("Encoder failed to load");
2154 ci
.enc_codec_loaded
= -1;
2156 #endif /* AUDIO_HAVE_RECORDING */
2159 LOGFQUEUE("codec < default");
2166 /* --- Audio thread --- */
2168 static bool audio_filebuf_is_lowdata(void)
2170 return FILEBUFUSED
< AUDIO_FILEBUF_CRITICAL
;
2173 static bool audio_have_tracks(void)
2175 return track_ridx
!= track_widx
|| CUR_TI
->filesize
;
2178 static bool audio_have_free_tracks(void)
2180 if (track_widx
< track_ridx
)
2181 return track_widx
+ 1 < track_ridx
;
2182 else if (track_ridx
== 0)
2183 return track_widx
< MAX_TRACK
- 1;
2188 int audio_track_count(void)
2190 if (audio_have_tracks())
2192 int relative_track_widx
= track_widx
;
2194 if (track_ridx
> track_widx
)
2195 relative_track_widx
+= MAX_TRACK
;
2197 return relative_track_widx
- track_ridx
+ 1;
2203 long audio_filebufused(void)
2205 return (long) FILEBUFUSED
;
2208 /* Count the data BETWEEN the selected tracks */
2209 static size_t audio_buffer_count_tracks(int from_track
, int to_track
)
2212 bool need_wrap
= to_track
< from_track
;
2216 if (++from_track
>= MAX_TRACK
)
2218 from_track
-= MAX_TRACK
;
2222 if (from_track
>= to_track
&& !need_wrap
)
2225 amount
+= tracks
[from_track
].codecsize
+ tracks
[from_track
].filesize
;
2230 static bool audio_buffer_wind_forward(int new_track_ridx
, int old_track_ridx
)
2234 /* Start with the remainder of the previously playing track */
2235 amount
= tracks
[old_track_ridx
].filesize
- ci
.curpos
;
2236 /* Then collect all data from tracks in between them */
2237 amount
+= audio_buffer_count_tracks(old_track_ridx
, new_track_ridx
);
2238 logf("bwf:%ldB", (long) amount
);
2240 if (amount
> FILEBUFUSED
)
2243 /* Wind the buffer to the beginning of the target track or its codec */
2244 buf_ridx
= RINGBUF_ADD(buf_ridx
, amount
);
2249 static bool audio_buffer_wind_backward(int new_track_ridx
, int old_track_ridx
)
2251 /* Available buffer data */
2253 /* Start with the previously playing track's data and our data */
2257 buf_back
= RINGBUF_SUB(buf_ridx
, buf_widx
);
2259 /* If we're not just resetting the current track */
2260 if (new_track_ridx
!= old_track_ridx
)
2262 /* Need to wind to before the old track's codec and our filesize */
2263 amount
+= tracks
[old_track_ridx
].codecsize
;
2264 amount
+= tracks
[new_track_ridx
].filesize
;
2266 /* Rewind the old track to its beginning */
2267 tracks
[old_track_ridx
].available
=
2268 tracks
[old_track_ridx
].filesize
- tracks
[old_track_ridx
].filerem
;
2271 /* If the codec was ever buffered */
2272 if (tracks
[new_track_ridx
].codecsize
)
2274 /* Add the codec to the needed size */
2275 amount
+= tracks
[new_track_ridx
].codecsize
;
2276 tracks
[new_track_ridx
].has_codec
= true;
2279 /* Then collect all data from tracks between new and old */
2280 amount
+= audio_buffer_count_tracks(new_track_ridx
, old_track_ridx
);
2282 /* Do we have space to make this skip? */
2283 if (amount
> buf_back
)
2286 logf("bwb:%ldB",amount
);
2288 /* Rewind the buffer to the beginning of the target track or its codec */
2289 buf_ridx
= RINGBUF_SUB(buf_ridx
, amount
);
2291 /* Reset to the beginning of the new track */
2292 tracks
[new_track_ridx
].available
= tracks
[new_track_ridx
].filesize
;
2297 static void audio_update_trackinfo(void)
2299 ci
.filesize
= CUR_TI
->filesize
;
2300 CUR_TI
->id3
.elapsed
= 0;
2301 CUR_TI
->id3
.offset
= 0;
2302 ci
.id3
= &CUR_TI
->id3
;
2304 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2307 /* Yield to codecs for as long as possible if they are in need of data
2308 * return true if the caller should break to let the audio thread process
2310 static bool audio_yield_codecs(void)
2314 if (!queue_empty(&audio_queue
))
2317 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2318 && !ci
.stop_codec
&& playing
&& !audio_filebuf_is_lowdata())
2325 if (!queue_empty(&audio_queue
))
2332 static void audio_clear_track_entries(bool clear_unbuffered
)
2334 int cur_idx
= track_widx
;
2337 logf("Clearing tracks:%d/%d, %d", track_ridx
, track_widx
, clear_unbuffered
);
2339 /* Loop over all tracks from write-to-read */
2343 cur_idx
&= MAX_TRACK_MASK
;
2345 if (cur_idx
== track_ridx
)
2348 /* If the track is buffered, conditionally clear/notify,
2349 * otherwise clear the track if that option is selected */
2350 if (tracks
[cur_idx
].event_sent
)
2354 /* If there is an unbuffer callback, call it, otherwise,
2355 * just clear the track */
2356 if (track_unbuffer_callback
)
2357 track_unbuffer_callback(&tracks
[last_idx
].id3
, false);
2359 memset(&tracks
[last_idx
], 0, sizeof(struct track_info
));
2363 else if (clear_unbuffered
)
2364 memset(&tracks
[cur_idx
], 0, sizeof(struct track_info
));
2367 /* We clear the previous instance of a buffered track throughout
2368 * the above loop to facilitate 'last' detection. Clear/notify
2369 * the last track here */
2372 if (track_unbuffer_callback
)
2373 track_unbuffer_callback(&tracks
[last_idx
].id3
, true);
2374 memset(&tracks
[last_idx
], 0, sizeof(struct track_info
));
2378 /* FIXME: This code should be made more generic and move to metadata.c */
2379 static void audio_strip_tags(void)
2382 static const unsigned char tag
[] = "TAG";
2383 static const unsigned char apetag
[] = "APETAGEX";
2386 size_t len
, version
;
2388 tag_idx
= RINGBUF_SUB(buf_widx
, 128);
2390 if (FILEBUFUSED
> 128 && tag_idx
> buf_ridx
)
2393 for(i
= 0;i
< 3;i
++)
2395 if(filebuf
[cur_idx
] != tag
[i
])
2398 cur_idx
= RINGBUF_ADD(cur_idx
, 1);
2401 /* Skip id3v1 tag */
2402 logf("Skipping ID3v1 tag");
2404 tracks
[track_widx
].available
-= 128;
2405 tracks
[track_widx
].filesize
-= 128;
2409 /* Check for APE tag (look for the APE tag footer) */
2410 tag_idx
= RINGBUF_SUB(buf_widx
, 32);
2412 if (FILEBUFUSED
> 32 && tag_idx
> buf_ridx
)
2415 for(i
= 0;i
< 8;i
++)
2417 if(filebuf
[cur_idx
] != apetag
[i
])
2420 cur_idx
= RINGBUF_ADD(cur_idx
, 1);
2423 /* Read the version and length from the footer */
2424 version
= filebuf
[tag_idx
+8] | (filebuf
[tag_idx
+9] << 8) |
2425 (filebuf
[tag_idx
+10] << 16) | (filebuf
[tag_idx
+11] << 24);
2426 len
= filebuf
[tag_idx
+12] | (filebuf
[tag_idx
+13] << 8) |
2427 (filebuf
[tag_idx
+14] << 16) | (filebuf
[tag_idx
+15] << 24);
2428 if (version
== 2000)
2429 len
+= 32; /* APEv2 has a 32 byte header */
2432 if (FILEBUFUSED
> len
)
2434 logf("Skipping APE tag (%ldB)", len
);
2435 buf_widx
= RINGBUF_SUB(buf_widx
, len
);
2436 tracks
[track_widx
].available
-= len
;
2437 tracks
[track_widx
].filesize
-= len
;
2442 /* Returns true if a whole file is read, false otherwise */
2443 static bool audio_read_file(size_t minimum
)
2445 bool ret_val
= false;
2447 /* If we're called and no file is open, this is an error */
2450 logf("Bad fd in arf");
2451 /* Give some hope of miraculous recovery by forcing a track reload */
2452 tracks
[track_widx
].filesize
= 0;
2453 /* Stop this buffering run */
2457 trigger_cpu_boost();
2458 while (tracks
[track_widx
].filerem
> 0)
2464 /* copy_n is the largest chunk that is safe to read */
2465 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
2467 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2468 if (RINGBUF_ADD_CROSS(buf_widx
,copy_n
,buf_ridx
) >= 0)
2471 /* rc is the actual amount read */
2472 rc
= read(current_fd
, &filebuf
[buf_widx
], copy_n
);
2476 logf("File ended %ldB early", tracks
[track_widx
].filerem
);
2477 tracks
[track_widx
].filesize
-= tracks
[track_widx
].filerem
;
2478 tracks
[track_widx
].filerem
= 0;
2482 /* How much of the playing track did we overwrite */
2483 if (buf_widx
== CUR_TI
->buf_idx
)
2485 /* Special handling; zero or full overlap? */
2486 if (track_widx
== track_ridx
&& CUR_TI
->available
== 0)
2492 overlap
= RINGBUF_ADD_CROSS(buf_widx
,rc
,CUR_TI
->buf_idx
);
2494 if ((unsigned)rc
> tracks
[track_widx
].filerem
)
2496 logf("Bad: rc-filerem=%ld, fixing", rc
-tracks
[track_widx
].filerem
);
2497 tracks
[track_widx
].filesize
+= rc
- tracks
[track_widx
].filerem
;
2498 tracks
[track_widx
].filerem
= rc
;
2501 /* Advance buffer */
2502 buf_widx
= RINGBUF_ADD(buf_widx
, rc
);
2503 tracks
[track_widx
].available
+= rc
;
2504 tracks
[track_widx
].filerem
-= rc
;
2506 /* If we write into the playing track, adjust it's buffer info */
2509 CUR_TI
->buf_idx
+= overlap
;
2510 CUR_TI
->start_pos
+= overlap
;
2513 /* For a rebuffer, fill at least this minimum */
2514 if (minimum
> (unsigned)rc
)
2516 /* Let the codec process up to the watermark */
2517 /* Break immediately if this is a quick buffer, or there is an event */
2518 else if (minimum
|| audio_yield_codecs())
2520 /* Exit quickly, but don't stop the overall buffering process */
2526 if (tracks
[track_widx
].filerem
== 0)
2528 logf("Finished buf:%ldB", tracks
[track_widx
].filesize
);
2534 track_widx
&= MAX_TRACK_MASK
;
2536 tracks
[track_widx
].filesize
= 0;
2541 logf("%s buf:%ldB", ret_val
?"Quick":"Partially",
2542 tracks
[track_widx
].filesize
- tracks
[track_widx
].filerem
);
2547 static bool audio_loadcodec(bool start_play
)
2554 char codec_path
[MAX_PATH
]; /* Full path to codec */
2556 const char * codec_fn
=
2557 get_codec_filename(tracks
[track_widx
].id3
.codectype
);
2558 if (codec_fn
== NULL
)
2561 tracks
[track_widx
].has_codec
= false;
2565 /* Load the codec directly from disk and save some memory. */
2566 track_ridx
= track_widx
;
2567 ci
.filesize
= CUR_TI
->filesize
;
2568 ci
.id3
= &CUR_TI
->id3
;
2569 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2571 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2572 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (intptr_t)codec_fn
);
2577 /* If we already have another track than this one buffered */
2578 if (track_widx
!= track_ridx
)
2580 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
2582 /* If the previous codec is the same as this one, there is no need
2583 * to put another copy of it on the file buffer */
2584 if (get_codec_base_type(tracks
[track_widx
].id3
.codectype
) ==
2585 get_codec_base_type(tracks
[prev_track
].id3
.codectype
)
2586 && audio_codec_loaded
)
2588 logf("Reusing prev. codec");
2594 codec_get_full_path(codec_path
, codec_fn
);
2596 fd
= open(codec_path
, O_RDONLY
);
2599 logf("Codec doesn't exist!");
2603 tracks
[track_widx
].codecsize
= filesize(fd
);
2605 /* Never load a partial codec */
2606 if (RINGBUF_ADD_CROSS(buf_widx
,tracks
[track_widx
].codecsize
,buf_ridx
) >= 0)
2608 logf("Not enough space");
2613 while (size
< tracks
[track_widx
].codecsize
)
2615 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
2616 rc
= read(fd
, &filebuf
[buf_widx
], copy_n
);
2620 /* This is an error condition, likely the codec file is corrupt */
2621 logf("Partial codec loaded");
2622 /* Must undo the buffer write of the partial codec */
2623 buf_widx
= RINGBUF_SUB(buf_widx
, size
);
2624 tracks
[track_widx
].codecsize
= 0;
2628 buf_widx
= RINGBUF_ADD(buf_widx
, rc
);
2633 tracks
[track_widx
].has_codec
= true;
2636 logf("Done: %ldB", size
);
2641 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2642 static void audio_set_elapsed(struct mp3entry
* id3
)
2644 unsigned long offset
= id3
->offset
> id3
->first_frame_offset
?
2645 id3
->offset
- id3
->first_frame_offset
: 0;
2648 if ( id3
->has_toc
) {
2649 /* calculate elapsed time using TOC */
2651 unsigned int remainder
, plen
, relpos
, nextpos
;
2653 /* find wich percent we're at */
2654 for (i
=0; i
<100; i
++ )
2655 if ( offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
2662 relpos
= id3
->toc
[i
];
2665 nextpos
= id3
->toc
[i
+1];
2669 remainder
= offset
- (relpos
* (id3
->filesize
/ 256));
2671 /* set time for this percent (divide before multiply to prevent
2672 overflow on long files. loss of precision is negligible on
2674 id3
->elapsed
= i
* (id3
->length
/ 100);
2676 /* calculate remainder time */
2677 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
2678 id3
->elapsed
+= (((remainder
* 100) / plen
) *
2679 (id3
->length
/ 10000));
2682 /* no TOC exists. set a rough estimate using average bitrate */
2683 int tpk
= id3
->length
/
2684 ((id3
->filesize
- id3
->first_frame_offset
- id3
->id3v1len
) /
2686 id3
->elapsed
= offset
/ 1024 * tpk
;
2691 /* constant bitrate, use exact calculation */
2692 if (id3
->bitrate
!= 0)
2693 id3
->elapsed
= offset
/ (id3
->bitrate
/ 8);
2697 static bool audio_load_track(int offset
, bool start_play
, bool rebuffer
)
2703 /* Stop buffer filling if there is no free track entries.
2704 Don't fill up the last track entry (we wan't to store next track
2706 if (!audio_have_free_tracks())
2708 logf("No free tracks");
2712 if (current_fd
>= 0)
2714 logf("Nonzero fd in alt");
2721 logf("Buffering track:%d/%d", track_widx
, track_ridx
);
2722 /* Get track name from current playlist read position. */
2723 while ((trackname
= playlist_peek(last_peek_offset
)) != NULL
)
2725 /* Handle broken playlists. */
2726 current_fd
= open(trackname
, O_RDONLY
);
2729 logf("Open failed");
2730 /* Skip invalid entry from playlist. */
2731 playlist_skip_entry(NULL
, last_peek_offset
);
2739 logf("End-of-playlist");
2740 playlist_end
= true;
2744 /* Initialize track entry. */
2745 size
= filesize(current_fd
);
2746 tracks
[track_widx
].filerem
= size
;
2747 tracks
[track_widx
].filesize
= size
;
2748 tracks
[track_widx
].available
= 0;
2750 /* Set default values */
2753 int last_codec
= current_codec
;
2755 set_current_codec(CODEC_IDX_AUDIO
);
2756 conf_watermark
= AUDIO_DEFAULT_WATERMARK
;
2757 conf_filechunk
= AUDIO_DEFAULT_FILECHUNK
;
2758 conf_preseek
= AUDIO_REBUFFER_GUESS_SIZE
;
2759 dsp_configure(DSP_RESET
, 0);
2760 set_current_codec(last_codec
);
2763 /* Get track metadata if we don't already have it. */
2764 if (!tracks
[track_widx
].taginfo_ready
)
2766 if (get_metadata(&(tracks
[track_widx
].id3
),current_fd
,trackname
))
2768 tracks
[track_widx
].taginfo_ready
= true;
2771 track_changed
= true;
2772 playlist_update_resume_info(audio_current_track());
2777 logf("mde:%s!",trackname
);
2779 /* Set filesize to zero to indicate no file was loaded. */
2780 tracks
[track_widx
].filesize
= 0;
2781 tracks
[track_widx
].filerem
= 0;
2785 /* Skip invalid entry from playlist. */
2786 playlist_skip_entry(NULL
, last_peek_offset
);
2787 tracks
[track_widx
].taginfo_ready
= false;
2793 if (cuesheet_is_enabled() && tracks
[track_widx
].id3
.cuesheet_type
== 1)
2795 char cuepath
[MAX_PATH
];
2797 struct cuesheet
*cue
= start_play
? curr_cue
: temp_cue
;
2799 if (look_for_cuesheet_file(trackname
, cuepath
) &&
2800 parse_cuesheet(cuepath
, cue
))
2802 strcpy((cue
)->audio_filename
, trackname
);
2804 cue_spoof_id3(curr_cue
, &tracks
[track_widx
].id3
);
2808 /* Load the codec. */
2809 tracks
[track_widx
].codecbuf
= &filebuf
[buf_widx
];
2810 if (!audio_loadcodec(start_play
))
2812 /* Set filesize to zero to indicate no file was loaded. */
2813 tracks
[track_widx
].filesize
= 0;
2814 tracks
[track_widx
].filerem
= 0;
2818 if (tracks
[track_widx
].codecsize
)
2820 /* No space for codec on buffer, not an error */
2821 tracks
[track_widx
].codecsize
= 0;
2825 /* This is an error condition, either no codec was found, or reading
2826 * the codec file failed part way through, either way, skip the track */
2827 snprintf(msgbuf
, sizeof(msgbuf
)-1, "No codec for: %s", trackname
);
2828 /* We should not use gui_syncplash from audio thread! */
2829 gui_syncsplash(HZ
*2, msgbuf
);
2830 /* Skip invalid entry from playlist. */
2831 playlist_skip_entry(NULL
, last_peek_offset
);
2832 tracks
[track_widx
].taginfo_ready
= false;
2836 tracks
[track_widx
].start_pos
= 0;
2837 set_filebuf_watermark(buffer_margin
);
2838 tracks
[track_widx
].id3
.elapsed
= 0;
2842 switch (tracks
[track_widx
].id3
.codectype
) {
2846 lseek(current_fd
, offset
, SEEK_SET
);
2847 tracks
[track_widx
].id3
.offset
= offset
;
2848 audio_set_elapsed(&tracks
[track_widx
].id3
);
2849 tracks
[track_widx
].filerem
= size
- offset
;
2851 tracks
[track_widx
].start_pos
= offset
;
2855 lseek(current_fd
, offset
, SEEK_SET
);
2856 tracks
[track_widx
].id3
.offset
= offset
;
2857 tracks
[track_widx
].id3
.elapsed
=
2858 tracks
[track_widx
].id3
.length
/ 2;
2859 tracks
[track_widx
].filerem
= size
- offset
;
2861 tracks
[track_widx
].start_pos
= offset
;
2864 case AFMT_OGG_VORBIS
:
2872 tracks
[track_widx
].id3
.offset
= offset
;
2877 logf("alt:%s", trackname
);
2878 tracks
[track_widx
].buf_idx
= buf_widx
;
2880 return audio_read_file(rebuffer
);
2883 static bool audio_read_next_metadata(void)
2890 next_idx
= track_widx
;
2891 if (tracks
[next_idx
].taginfo_ready
)
2894 next_idx
&= MAX_TRACK_MASK
;
2896 if (tracks
[next_idx
].taginfo_ready
)
2900 trackname
= playlist_peek(last_peek_offset
+ 1);
2904 fd
= open(trackname
, O_RDONLY
);
2908 status
= get_metadata(&(tracks
[next_idx
].id3
),fd
,trackname
);
2909 /* Preload the glyphs in the tags */
2912 tracks
[next_idx
].taginfo_ready
= true;
2913 if (tracks
[next_idx
].id3
.title
)
2914 lcd_getstringsize(tracks
[next_idx
].id3
.title
, NULL
, NULL
);
2915 if (tracks
[next_idx
].id3
.artist
)
2916 lcd_getstringsize(tracks
[next_idx
].id3
.artist
, NULL
, NULL
);
2917 if (tracks
[next_idx
].id3
.album
)
2918 lcd_getstringsize(tracks
[next_idx
].id3
.album
, NULL
, NULL
);
2925 /* Send callback events to notify about new tracks. */
2926 static void audio_generate_postbuffer_events(void)
2931 logf("Postbuffer:%d/%d",track_ridx
,track_widx
);
2933 if (audio_have_tracks())
2935 cur_idx
= track_ridx
;
2938 if (!tracks
[cur_idx
].event_sent
)
2940 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2942 /* Mark the event 'sent' even if we don't really send one */
2943 tracks
[last_idx
].event_sent
= true;
2944 if (track_buffer_callback
)
2945 track_buffer_callback(&tracks
[last_idx
].id3
, false);
2949 if (cur_idx
== track_widx
)
2952 cur_idx
&= MAX_TRACK_MASK
;
2955 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2957 tracks
[last_idx
].event_sent
= true;
2958 if (track_buffer_callback
)
2959 track_buffer_callback(&tracks
[last_idx
].id3
, true);
2964 static bool audio_initialize_buffer_fill(bool clear_tracks
)
2966 /* Don't initialize if we're already initialized */
2970 logf("Starting buffer fill");
2972 /* Set the filling flag true before calling audio_clear_tracks as that
2973 * function can yield and we start looping. */
2977 audio_clear_track_entries(false);
2979 /* Save the current resume position once. */
2980 playlist_update_resume_info(audio_current_track());
2985 static void audio_fill_file_buffer(
2986 bool start_play
, bool rebuffer
, size_t offset
)
2988 bool had_next_track
= audio_next_track() != NULL
;
2989 bool continue_buffering
;
2991 /* Must reset the buffer before use if trashed or voice only - voice
2992 file size shouldn't have changed so we can go straight from
2993 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2994 if (buffer_state
!= BUFFER_STATE_INITIALIZED
)
2995 audio_reset_buffer();
2997 if (!audio_initialize_buffer_fill(!start_play
))
3000 /* If we have a partially buffered track, continue loading,
3001 * otherwise load a new track */
3002 if (tracks
[track_widx
].filesize
> 0)
3003 continue_buffering
= audio_read_file(rebuffer
);
3005 continue_buffering
= audio_load_track(offset
, start_play
, rebuffer
);
3007 if (!had_next_track
&& audio_next_track())
3008 track_changed
= true;
3010 /* If we're done buffering */
3011 if (!continue_buffering
)
3013 audio_read_next_metadata();
3015 audio_generate_postbuffer_events();
3024 static void audio_rebuffer(void)
3026 logf("Forcing rebuffer");
3028 /* Stop in progress fill, and clear open file descriptor */
3029 if (current_fd
>= 0)
3036 /* Reset buffer and track pointers */
3037 CUR_TI
->buf_idx
= buf_ridx
= buf_widx
= 0;
3038 track_widx
= track_ridx
;
3039 audio_clear_track_entries(true);
3040 CUR_TI
->available
= 0;
3042 /* Fill the buffer */
3043 last_peek_offset
= -1;
3044 CUR_TI
->filesize
= 0;
3045 CUR_TI
->start_pos
= 0;
3048 if (!CUR_TI
->taginfo_ready
)
3049 memset(&CUR_TI
->id3
, 0, sizeof(struct mp3entry
));
3051 audio_fill_file_buffer(false, true, 0);
3054 static int audio_check_new_track(void)
3056 int track_count
= audio_track_count();
3057 int old_track_ridx
= track_ridx
;
3063 if (playlist_next_dir(ci
.new_track
))
3066 CUR_TI
->taginfo_ready
= false;
3072 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3073 return Q_CODEC_REQUEST_FAILED
;
3080 /* If the playlist isn't that big */
3081 if (!playlist_check(ci
.new_track
))
3083 if (ci
.new_track
>= 0)
3085 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3086 return Q_CODEC_REQUEST_FAILED
;
3088 /* Find the beginning backward if the user over-skips it */
3089 while (!playlist_check(++ci
.new_track
))
3090 if (ci
.new_track
>= 0)
3092 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3093 return Q_CODEC_REQUEST_FAILED
;
3096 /* Update the playlist */
3097 last_peek_offset
-= ci
.new_track
;
3099 if (playlist_next(ci
.new_track
) < 0)
3101 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3102 return Q_CODEC_REQUEST_FAILED
;
3108 new_playlist
= false;
3111 /* Save the old track */
3114 /* Move to the new track */
3115 track_ridx
+= ci
.new_track
;
3116 track_ridx
&= MAX_TRACK_MASK
;
3119 playlist_end
= false;
3121 track_changed
= !automatic_skip
;
3123 /* If it is not safe to even skip this many track entries */
3124 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
3127 CUR_TI
->taginfo_ready
= false;
3132 forward
= ci
.new_track
> 0;
3135 /* If the target track is clearly not in memory */
3136 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
3142 /* The track may be in memory, see if it really is */
3145 if (!audio_buffer_wind_forward(track_ridx
, old_track_ridx
))
3150 int cur_idx
= track_ridx
;
3151 bool taginfo_ready
= true;
3152 bool wrap
= track_ridx
> old_track_ridx
;
3157 cur_idx
&= MAX_TRACK_MASK
;
3158 if (!(wrap
|| cur_idx
< old_track_ridx
))
3161 /* If we hit a track in between without valid tag info, bail */
3162 if (!tracks
[cur_idx
].taginfo_ready
)
3164 taginfo_ready
= false;
3168 tracks
[cur_idx
].available
= tracks
[cur_idx
].filesize
;
3169 if (tracks
[cur_idx
].codecsize
)
3170 tracks
[cur_idx
].has_codec
= true;
3174 if (!audio_buffer_wind_backward(track_ridx
, old_track_ridx
))
3179 CUR_TI
->taginfo_ready
= false;
3185 audio_update_trackinfo();
3186 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3187 return Q_CODEC_REQUEST_COMPLETE
;
3190 static int audio_rebuffer_and_seek(size_t newpos
)
3192 size_t real_preseek
;
3196 /* (Re-)open current track's file handle. */
3197 trackname
= playlist_peek(0);
3198 fd
= open(trackname
, O_RDONLY
);
3201 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3202 return Q_CODEC_REQUEST_FAILED
;
3205 if (current_fd
>= 0)
3209 playlist_end
= false;
3213 /* Clear codec buffer. */
3214 track_widx
= track_ridx
;
3215 tracks
[track_widx
].buf_idx
= buf_widx
= buf_ridx
= 0;
3217 last_peek_offset
= 0;
3219 audio_initialize_buffer_fill(true);
3221 /* This may have been tweaked by the id3v1 code */
3222 CUR_TI
->filesize
=filesize(fd
);
3223 if (newpos
> conf_preseek
)
3225 CUR_TI
->start_pos
= newpos
- conf_preseek
;
3226 lseek(current_fd
, CUR_TI
->start_pos
, SEEK_SET
);
3227 CUR_TI
->filerem
= CUR_TI
->filesize
- CUR_TI
->start_pos
;
3228 real_preseek
= conf_preseek
;
3232 CUR_TI
->start_pos
= 0;
3233 CUR_TI
->filerem
= CUR_TI
->filesize
;
3234 real_preseek
= newpos
;
3237 CUR_TI
->available
= 0;
3239 audio_read_file(real_preseek
);
3241 /* Account for the data we just read that is 'behind' us now */
3242 CUR_TI
->available
-= real_preseek
;
3244 buf_ridx
= RINGBUF_ADD(buf_ridx
, real_preseek
);
3246 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3247 return Q_CODEC_REQUEST_COMPLETE
;
3250 void audio_set_track_buffer_event(void (*handler
)(struct mp3entry
*id3
,
3253 track_buffer_callback
= handler
;
3256 void audio_set_track_unbuffer_event(void (*handler
)(struct mp3entry
*id3
,
3259 track_unbuffer_callback
= handler
;
3262 void audio_set_track_changed_event(void (*handler
)(struct mp3entry
*id3
))
3264 track_changed_callback
= handler
;
3267 unsigned long audio_prev_elapsed(void)
3269 return prev_track_elapsed
;
3272 static void audio_stop_codec_flush(void)
3274 ci
.stop_codec
= true;
3277 while (audio_codec_loaded
)
3280 /* If the audio codec is not loaded any more, and the audio is still
3281 * playing, it is now and _only_ now safe to call this function from the
3283 if (pcm_is_playing())
3285 pcmbuf_pause(paused
);
3288 static void audio_stop_playback(void)
3290 /* If we were playing, save resume information */
3293 struct mp3entry
*id3
= NULL
;
3295 if (!playlist_end
|| !ci
.stop_codec
)
3297 /* Set this early, the outside code yields and may allow the codec
3298 to try to wait for a reply on a buffer wait */
3299 ci
.stop_codec
= true;
3300 id3
= audio_current_track();
3303 /* Save the current playing spot, or NULL if the playlist has ended */
3304 playlist_update_resume_info(id3
);
3306 prev_track_elapsed
= CUR_TI
->id3
.elapsed
;
3308 /* Increment index so runtime info is saved in audio_clear_track_entries().
3309 * Done here, as audio_stop_playback() may be called more than once.
3310 * Don't update runtime unless playback is stopped because of end of playlist.
3311 * Updating runtime when manually stopping a tracks, can destroy autoscores
3317 track_ridx
&= MAX_TRACK_MASK
;
3323 audio_stop_codec_flush();
3326 if (current_fd
>= 0)
3332 /* Mark all entries null. */
3333 audio_clear_track_entries(false);
3336 static void audio_play_start(size_t offset
)
3338 #if INPUT_SRC_CAPS != 0
3339 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
3340 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
3343 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3345 audio_stop_codec_flush();
3347 track_changed
= true;
3348 playlist_end
= false;
3356 if (current_fd
>= 0)
3362 sound_set_volume(global_settings
.volume
);
3363 track_widx
= track_ridx
= 0;
3364 buf_ridx
= buf_widx
= 0;
3366 /* Mark all entries null. */
3367 memset(tracks
, 0, sizeof(struct track_info
) * MAX_TRACK
);
3369 last_peek_offset
= -1;
3371 /* Officially playing */
3372 queue_reply(&audio_queue
, 1);
3374 audio_fill_file_buffer(true, false, offset
);
3376 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3377 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
3381 /* Invalidates all but currently playing track. */
3382 static void audio_invalidate_tracks(void)
3384 if (audio_have_tracks())
3386 last_peek_offset
= 0;
3387 playlist_end
= false;
3388 track_widx
= track_ridx
;
3390 /* Mark all other entries null (also buffered wrong metadata). */
3391 audio_clear_track_entries(true);
3393 /* If the current track is fully buffered, advance the write pointer */
3394 if (tracks
[track_widx
].filerem
== 0)
3395 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
3397 buf_widx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->available
);
3399 audio_read_next_metadata();
3403 static void audio_new_playlist(void)
3405 /* Prepare to start a new fill from the beginning of the playlist */
3406 last_peek_offset
= -1;
3407 if (audio_have_tracks())
3410 skipped_during_pause
= true;
3411 playlist_end
= false;
3412 track_widx
= track_ridx
;
3413 audio_clear_track_entries(true);
3416 track_widx
&= MAX_TRACK_MASK
;
3418 /* Stop reading the current track */
3419 CUR_TI
->filerem
= 0;
3423 /* Mark the current track as invalid to prevent skipping back to it */
3424 CUR_TI
->taginfo_ready
= false;
3426 /* Invalidate the buffer other than the playing track */
3427 buf_widx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->available
);
3430 /* Signal the codec to initiate a track change forward */
3431 new_playlist
= true;
3434 /* Officially playing */
3435 queue_reply(&audio_queue
, 1);
3437 audio_fill_file_buffer(false, true, 0);
3440 static void audio_initiate_track_change(long direction
)
3442 playlist_end
= false;
3443 ci
.new_track
+= direction
;
3444 wps_offset
-= direction
;
3446 skipped_during_pause
= true;
3449 static void audio_initiate_dir_change(long direction
)
3451 playlist_end
= false;
3453 ci
.new_track
= direction
;
3455 skipped_during_pause
= true;
3459 * Layout audio buffer as follows - iram buffer depends on target:
3460 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3462 static void audio_reset_buffer(void)
3464 /* see audio_get_recording_buffer if this is modified */
3465 logf("audio_reset_buffer");
3467 /* If the setup of anything allocated before the file buffer is
3468 changed, do check the adjustments after the buffer_alloc call
3469 as it will likely be affected and need sliding over */
3471 /* Initially set up file buffer as all space available */
3472 malloc_buf
= audiobuf
+ talk_get_bufsize();
3473 /* Align the malloc buf to line size. Especially important to cf
3474 targets that do line reads/writes. */
3475 malloc_buf
= (unsigned char *)(((uintptr_t)malloc_buf
+ 15) & ~15);
3476 filebuf
= malloc_buf
+ MALLOC_BUFSIZE
; /* filebuf line align implied */
3477 filebuflen
= audiobufend
- filebuf
;
3479 /* Allow for codec swap space at end of audio buffer */
3480 if (talk_voice_required())
3482 /* Layout of swap buffer:
3483 * #ifdef IRAM_STEAL (dedicated iram_buf):
3484 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3486 * audiobuf...|dram_buf|iram_buf|audiobufend
3488 #ifdef PLAYBACK_VOICE
3489 /* Check for an absolutely nasty situation which should never,
3490 ever happen - frankly should just panic */
3491 if (voice_codec_loaded
&& current_codec
!= CODEC_IDX_VOICE
)
3493 logf("buffer reset with voice swapped");
3495 /* line align length which line aligns the calculations below since
3496 all sizes are also at least line aligned - needed for memswap128 */
3499 filebuflen
-= CODEC_SIZE
;
3501 filebuflen
-= CODEC_SIZE
+ CODEC_IRAM_SIZE
;
3503 /* Allocate buffers for swapping voice <=> audio */
3504 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3505 and out of the way of buffer usage or else a call to audio_get_buffer
3506 and subsequent buffer use might trash the swap space. A plugin
3507 initializing IRAM after getting the full buffer would present similar
3508 problem. Options include: failing the request if the other buffer
3509 has been obtained already or never allowing use of the voice IRAM
3510 buffer within the audio buffer. Using buffer_alloc basically
3511 implements the second in a more convenient way. */
3512 dram_buf
= filebuf
+ filebuflen
;
3515 /* Allocate voice IRAM swap buffer once */
3516 if (iram_buf
== NULL
)
3518 iram_buf
= buffer_alloc(CODEC_IRAM_SIZE
);
3519 /* buffer_alloc moves audiobuf; this is safe because only the end
3520 * has been touched so far in this function and the address of
3521 * filebuf + filebuflen is not changed */
3522 malloc_buf
+= CODEC_IRAM_SIZE
;
3523 filebuf
+= CODEC_IRAM_SIZE
;
3524 filebuflen
-= CODEC_IRAM_SIZE
;
3527 /* Allocate iram_buf after dram_buf */
3528 iram_buf
= dram_buf
+ CODEC_SIZE
;
3529 #endif /* IRAM_STEAL */
3530 #endif /* PLAYBACK_VOICE */
3534 #ifdef PLAYBACK_VOICE
3535 /* No swap buffers needed */
3541 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3542 filebuflen
-= pcmbuf_init(filebuf
+ filebuflen
) + GUARD_BUFSIZE
;
3544 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3545 will already be line aligned */
3548 /* Set the high watermark as 75% full...or 25% empty :) */
3550 high_watermark
= 3*filebuflen
/ 4;
3553 /* Clear any references to the file buffer */
3554 buffer_state
= BUFFER_STATE_INITIALIZED
;
3556 #ifdef ROCKBOX_HAS_LOGF
3557 /* Make sure everything adds up - yes, some info is a bit redundant but
3558 aids viewing and the sumation of certain variables should add up to
3559 the location of others. */
3562 unsigned char * pcmbuf
= pcmbuf_get_meminfo(&pcmbufsize
);
3563 logf("mabuf: %08X", (unsigned)malloc_buf
);
3564 logf("mabufe: %08X", (unsigned)(malloc_buf
+ MALLOC_BUFSIZE
));
3565 logf("fbuf: %08X", (unsigned)filebuf
);
3566 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
3567 logf("gbuf: %08X", (unsigned)(filebuf
+ filebuflen
));
3568 logf("gbufe: %08X", (unsigned)(filebuf
+ filebuflen
+ GUARD_BUFSIZE
));
3569 logf("pcmb: %08X", (unsigned)pcmbuf
);
3570 logf("pcmbe: %08X", (unsigned)(pcmbuf
+ pcmbufsize
));
3573 logf("dramb: %08X", (unsigned)dram_buf
);
3574 logf("drambe: %08X", (unsigned)(dram_buf
+ CODEC_SIZE
));
3578 logf("iramb: %08X", (unsigned)iram_buf
);
3579 logf("irambe: %08X", (unsigned)(iram_buf
+ CODEC_IRAM_SIZE
));
3586 /* we dont want this rebuffering on targets with little ram
3587 because the disk may never spin down */
3588 static bool ata_fillbuffer_callback(void)
3590 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
, 0);
3595 static void audio_thread(void)
3601 #ifdef PLAYBACK_VOICE
3602 /* Unlock mutex that init stage locks before creating this thread */
3603 mutex_unlock(&mutex_codecthread
);
3605 /* Buffers must be set up by now - should panic - really */
3606 if (buffer_state
!= BUFFER_STATE_INITIALIZED
)
3608 logf("audio_thread start: no buffer");
3611 /* Have to wait for voice to load up or else the codec swap will be
3612 invalid when an audio codec is loaded */
3613 wait_for_voice_swap_in();
3620 queue_wait_w_tmo(&audio_queue
, &ev
, 0);
3621 if (ev
.id
== SYS_TIMEOUT
)
3622 ev
.id
= Q_AUDIO_FILL_BUFFER
;
3626 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
3628 if (playing
&& (ev
.id
== SYS_TIMEOUT
) &&
3629 (FILEBUFUSED
< high_watermark
))
3630 register_ata_idle_func(ata_fillbuffer_callback
);
3636 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
:
3637 /* only fill if the disk is still spining */
3639 if (!ata_disk_is_active())
3642 #endif /* MEM > 8 */
3643 /* else fall through to Q_AUDIO_FILL_BUFFER */
3644 case Q_AUDIO_FILL_BUFFER
:
3645 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3647 if (!playing
|| playlist_end
|| ci
.stop_codec
)
3649 audio_fill_file_buffer(false, false, 0);
3653 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3654 if (playing
&& ev
.data
<= 0)
3655 audio_new_playlist();
3658 audio_stop_playback();
3659 audio_play_start((size_t)ev
.data
);
3664 LOGFQUEUE("audio < Q_AUDIO_STOP");
3666 audio_stop_playback();
3668 queue_clear(&audio_queue
);
3672 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3673 if (!(bool) ev
.data
&& skipped_during_pause
&& !pcmbuf_is_crossfade_active())
3674 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3675 skipped_during_pause
= false;
3678 pcmbuf_pause((bool)ev
.data
);
3679 paused
= (bool)ev
.data
;
3683 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3684 audio_initiate_track_change((long)ev
.data
);
3687 case Q_AUDIO_PRE_FF_REWIND
:
3688 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3694 case Q_AUDIO_FF_REWIND
:
3695 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3698 ci
.seek_time
= (long)ev
.data
+1;
3701 case Q_AUDIO_REBUFFER_SEEK
:
3702 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3703 queue_reply(&audio_queue
, audio_rebuffer_and_seek(ev
.data
));
3706 case Q_AUDIO_CHECK_NEW_TRACK
:
3707 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3708 queue_reply(&audio_queue
, audio_check_new_track());
3711 case Q_AUDIO_DIR_SKIP
:
3712 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3713 playlist_end
= false;
3714 audio_initiate_dir_change(ev
.data
);
3718 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3719 audio_invalidate_tracks();
3722 case Q_AUDIO_TRACK_CHANGED
:
3723 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3724 if (track_changed_callback
)
3725 track_changed_callback(&CUR_TI
->id3
);
3726 track_changed
= true;
3727 playlist_update_resume_info(audio_current_track());
3731 case SYS_USB_CONNECTED
:
3732 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3734 audio_stop_playback();
3735 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3736 usb_wait_for_disconnect(&audio_queue
);
3741 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3745 LOGFQUEUE("audio < default");
3750 #ifdef ROCKBOX_HAS_LOGF
3751 static void audio_test_track_changed_event(struct mp3entry
*id3
)
3755 logf("tce:%s", id3
->path
);
3759 /* Initialize the audio system - called from init() in main.c.
3760 * Last function because of all the references to internal symbols
3762 void audio_init(void)
3764 #ifdef PLAYBACK_VOICE
3765 static bool voicetagtrue
= true;
3766 static struct mp3entry id3_voice
;
3769 /* Can never do this twice */
3770 if (audio_is_initialized
)
3772 logf("audio: already initialized");
3776 logf("audio: initializing");
3778 /* Initialize queues before giving control elsewhere in case it likes
3779 to send messages. Thread creation will be delayed however so nothing
3780 starts running until ready if something yields such as talk_init. */
3781 #ifdef PLAYBACK_VOICE
3782 mutex_init(&mutex_codecthread
);
3783 /* Take ownership of lock to prevent playback of anything before audio
3784 hardware is initialized - audio thread unlocks it after final init
3786 mutex_lock(&mutex_codecthread
);
3788 queue_init(&audio_queue
, true);
3789 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
);
3790 queue_init(&codec_queue
, true);
3794 #ifdef ROCKBOX_HAS_LOGF
3795 audio_set_track_changed_event(audio_test_track_changed_event
);
3798 /* Initialize codec api. */
3799 ci
.read_filebuf
= codec_filebuf_callback
;
3800 ci
.pcmbuf_insert
= codec_pcmbuf_insert_callback
;
3801 ci
.get_codec_memory
= codec_get_memory_callback
;
3802 ci
.request_buffer
= codec_request_buffer_callback
;
3803 ci
.advance_buffer
= codec_advance_buffer_callback
;
3804 ci
.advance_buffer_loc
= codec_advance_buffer_loc_callback
;
3805 ci
.request_next_track
= codec_request_next_track_callback
;
3806 ci
.mp3_get_filepos
= codec_mp3_get_filepos_callback
;
3807 ci
.seek_buffer
= codec_seek_buffer_callback
;
3808 ci
.seek_complete
= codec_seek_complete_callback
;
3809 ci
.set_elapsed
= codec_set_elapsed_callback
;
3810 ci
.set_offset
= codec_set_offset_callback
;
3811 ci
.configure
= codec_configure_callback
;
3812 ci
.discard_codec
= codec_discard_codec_callback
;
3814 /* Initialize voice codec api. */
3815 #ifdef PLAYBACK_VOICE
3816 memcpy(&ci_voice
, &ci
, sizeof(ci_voice
));
3817 memset(&id3_voice
, 0, sizeof(id3_voice
));
3818 ci_voice
.read_filebuf
= voice_filebuf_callback
;
3819 ci_voice
.pcmbuf_insert
= voice_pcmbuf_insert_callback
;
3820 ci_voice
.get_codec_memory
= voice_get_memory_callback
;
3821 ci_voice
.request_buffer
= voice_request_buffer_callback
;
3822 ci_voice
.advance_buffer
= voice_advance_buffer_callback
;
3823 ci_voice
.advance_buffer_loc
= voice_advance_buffer_loc_callback
;
3824 ci_voice
.request_next_track
= voice_request_next_track_callback
;
3825 ci_voice
.mp3_get_filepos
= voice_mp3_get_filepos_callback
;
3826 ci_voice
.seek_buffer
= voice_seek_buffer_callback
;
3827 ci_voice
.seek_complete
= voice_do_nothing
;
3828 ci_voice
.set_elapsed
= voice_set_elapsed_callback
;
3829 ci_voice
.set_offset
= voice_set_offset_callback
;
3830 ci_voice
.configure
= voice_configure_callback
;
3831 ci_voice
.discard_codec
= voice_do_nothing
;
3832 ci_voice
.taginfo_ready
= &voicetagtrue
;
3833 ci_voice
.id3
= &id3_voice
;
3834 id3_voice
.frequency
= 11200;
3835 id3_voice
.length
= 1000000L;
3838 /* initialize the buffer */
3841 /* audio_reset_buffer must to know the size of voice buffer so init
3845 /* Create the threads late now that we shouldn't be yielding again before
3847 codec_thread_p
= create_thread(
3848 codec_thread
, codec_stack
, sizeof(codec_stack
),
3849 codec_thread_name
IF_PRIO(, PRIORITY_PLAYBACK
)
3850 IF_COP(, CPU
, true));
3852 create_thread(audio_thread
, audio_stack
, sizeof(audio_stack
),
3853 audio_thread_name
IF_PRIO(, PRIORITY_BUFFERING
)
3854 IF_COP(, CPU
, false));
3856 #ifdef PLAYBACK_VOICE
3857 /* TODO: Change this around when various speech codecs can be used */
3858 if (talk_voice_required())
3860 logf("Starting voice codec");
3861 queue_init(&voice_queue
, true);
3862 create_thread(voice_thread
, voice_stack
,
3863 sizeof(voice_stack
), voice_thread_name
3864 IF_PRIO(, PRIORITY_PLAYBACK
) IF_COP(, CPU
, false));
3868 /* Set crossfade setting for next buffer init which should be about... */
3869 pcmbuf_crossfade_enable(global_settings
.crossfade
);
3871 /* ...now! Set up the buffers */
3872 audio_reset_buffer();
3874 /* Probably safe to say */
3875 audio_is_initialized
= true;
3877 sound_settings_apply();
3879 eq_hw_enable(global_settings
.eq_hw_enabled
);
3881 #ifndef HAVE_FLASH_STORAGE
3882 audio_set_buffer_margin(global_settings
.buffer_margin
);