diff options
-rw-r--r-- | apps/pcmbuf.c | 41 | ||||
-rw-r--r-- | apps/playback.c | 241 |
2 files changed, 173 insertions, 109 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index f8fd2af82a..0aaa49f825 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -232,7 +232,7 @@ static inline void pcmbuf_add_chunk(void) | |||
232 | pcmbuf_current->link = NULL; | 232 | pcmbuf_current->link = NULL; |
233 | /* This is single use only */ | 233 | /* This is single use only */ |
234 | pcmbuf_event_handler = NULL; | 234 | pcmbuf_event_handler = NULL; |
235 | if (pcmbuf_read) { | 235 | if (pcmbuf_read != NULL) { |
236 | if (pcmbuf_flush) | 236 | if (pcmbuf_flush) |
237 | { | 237 | { |
238 | pcmbuf_write_end->link = pcmbuf_read->link; | 238 | pcmbuf_write_end->link = pcmbuf_read->link; |
@@ -305,14 +305,14 @@ bool pcmbuf_is_lowdata(void) | |||
305 | /* Amount of bytes left in the buffer. */ | 305 | /* Amount of bytes left in the buffer. */ |
306 | inline size_t pcmbuf_free(void) | 306 | inline size_t pcmbuf_free(void) |
307 | { | 307 | { |
308 | if (pcmbuf_read) | 308 | if (pcmbuf_read != NULL) |
309 | { | 309 | { |
310 | size_t read = (size_t)pcmbuf_read->addr; | 310 | void *read = pcmbuf_read->addr; |
311 | size_t write = | 311 | void *write = &audiobuffer[audiobuffer_pos + audiobuffer_fillpos]; |
312 | (size_t)&audiobuffer[audiobuffer_pos + audiobuffer_fillpos]; | ||
313 | if (read < write) | 312 | if (read < write) |
314 | read += pcmbuf_size; | 313 | return (size_t)(read - write) + pcmbuf_size; |
315 | return read - write; | 314 | else |
315 | return (size_t) (read - write); | ||
316 | } | 316 | } |
317 | return pcmbuf_size; | 317 | return pcmbuf_size; |
318 | } | 318 | } |
@@ -335,7 +335,6 @@ bool pcmbuf_crossfade_init(bool manual_skip) | |||
335 | return false; | 335 | return false; |
336 | } | 336 | } |
337 | 337 | ||
338 | logf("pcmbuf_crossfade_init"); | ||
339 | pcmbuf_boost(true); | 338 | pcmbuf_boost(true); |
340 | 339 | ||
341 | /* Don't enable mix mode when skipping tracks manually. */ | 340 | /* Don't enable mix mode when skipping tracks manually. */ |
@@ -444,10 +443,13 @@ void pcmbuf_play_start(void) | |||
444 | * until dma has been initialized. */ | 443 | * until dma has been initialized. */ |
445 | pcm_mute(true); | 444 | pcm_mute(true); |
446 | 445 | ||
447 | last_chunksize = pcmbuf_read->size; | 446 | if (pcmbuf_read != NULL) |
448 | pcmbuf_unplayed_bytes -= last_chunksize; | 447 | { |
449 | pcm_play_data(pcmbuf_callback, | 448 | last_chunksize = pcmbuf_read->size; |
449 | pcmbuf_unplayed_bytes -= last_chunksize; | ||
450 | pcm_play_data(pcmbuf_callback, | ||
450 | (unsigned char *)pcmbuf_read->addr, last_chunksize); | 451 | (unsigned char *)pcmbuf_read->addr, last_chunksize); |
452 | } | ||
451 | 453 | ||
452 | /* Now unmute the audio. */ | 454 | /* Now unmute the audio. */ |
453 | pcm_mute(false); | 455 | pcm_mute(false); |
@@ -462,7 +464,6 @@ static bool pcmbuf_flush_fillpos(void) | |||
462 | if (audiobuffer_fillpos) { | 464 | if (audiobuffer_fillpos) { |
463 | /* Never use the last buffer descriptor */ | 465 | /* Never use the last buffer descriptor */ |
464 | while (pcmbuf_write == pcmbuf_write_end) { | 466 | while (pcmbuf_write == pcmbuf_write_end) { |
465 | logf("pcmbuf_flush_fillpos no descriptors"); | ||
466 | /* Deboost to let the playback catchup */ | 467 | /* Deboost to let the playback catchup */ |
467 | pcmbuf_boost(false); | 468 | pcmbuf_boost(false); |
468 | /* If this happens, something is being stupid */ | 469 | /* If this happens, something is being stupid */ |
@@ -511,7 +512,7 @@ static void crossfade_process_buffer(size_t fade_in_delay, | |||
511 | fade_out_rem -= block_rem; | 512 | fade_out_rem -= block_rem; |
512 | 513 | ||
513 | /* Fade this block */ | 514 | /* Fade this block */ |
514 | while (block_rem > 0) | 515 | while (block_rem > 0 && fade_out_chunk != NULL) |
515 | { | 516 | { |
516 | /* Fade one sample */ | 517 | /* Fade one sample */ |
517 | short *buf = (short *)(fade_out_chunk->addr); | 518 | short *buf = (short *)(fade_out_chunk->addr); |
@@ -777,7 +778,8 @@ static bool prepare_insert(size_t length) | |||
777 | logf("pcm starting"); | 778 | logf("pcm starting"); |
778 | pcmbuf_play_start(); | 779 | pcmbuf_play_start(); |
779 | } | 780 | } |
780 | } else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark) | 781 | } |
782 | else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark) | ||
781 | pcmbuf_under_watermark(); | 783 | pcmbuf_under_watermark(); |
782 | 784 | ||
783 | return true; | 785 | return true; |
@@ -823,7 +825,12 @@ void* pcmbuf_request_voice_buffer(size_t length, size_t *realsize, bool mix) | |||
823 | { | 825 | { |
824 | if (mix) | 826 | if (mix) |
825 | { | 827 | { |
826 | if (pcmbuf_mix_chunk || pcmbuf_read->link) | 828 | if (pcmbuf_read == NULL) |
829 | { | ||
830 | *realsize = 0; | ||
831 | return NULL; | ||
832 | } | ||
833 | else if (pcmbuf_mix_chunk || pcmbuf_read->link) | ||
827 | { | 834 | { |
828 | *realsize = MIN(length, PCMBUF_MIX_CHUNK); | 835 | *realsize = MIN(length, PCMBUF_MIX_CHUNK); |
829 | return voicebuf; | 836 | return voicebuf; |
@@ -888,7 +895,7 @@ void pcmbuf_beep(unsigned int frequency, size_t duration, int amplitude) | |||
888 | short *pcmbuf_end = (short *)fadebuf; | 895 | short *pcmbuf_end = (short *)fadebuf; |
889 | size_t samples = NATIVE_FREQUENCY / 1000 * duration; | 896 | size_t samples = NATIVE_FREQUENCY / 1000 * duration; |
890 | 897 | ||
891 | if (pcm_is_playing()) | 898 | if (pcm_is_playing() && pcmbuf_read != NULL) |
892 | { | 899 | { |
893 | if (pcmbuf_read->link) | 900 | if (pcmbuf_read->link) |
894 | { | 901 | { |
@@ -971,7 +978,7 @@ void pcmbuf_mix_voice(size_t length) | |||
971 | short *obuf; | 978 | short *obuf; |
972 | size_t chunk_samples; | 979 | size_t chunk_samples; |
973 | 980 | ||
974 | if (!pcmbuf_mix_chunk && pcmbuf_read) | 981 | if (pcmbuf_mix_chunk == NULL && pcmbuf_read != NULL) |
975 | { | 982 | { |
976 | pcmbuf_mix_chunk = pcmbuf_read->link; | 983 | pcmbuf_mix_chunk = pcmbuf_read->link; |
977 | /* Start 1/8s into the next chunk */ | 984 | /* Start 1/8s into the next chunk */ |
diff --git a/apps/playback.c b/apps/playback.c index 33667cc656..d5f2b9024e 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -22,6 +22,8 @@ | |||
22 | /* TODO: Also play, stop ^^ */ | 22 | /* TODO: Also play, stop ^^ */ |
23 | /* TODO: Can use the track changed callback to detect end of track and seek | 23 | /* TODO: Can use the track changed callback to detect end of track and seek |
24 | * in the previous track until this happens */ | 24 | * in the previous track until this happens */ |
25 | /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can | ||
26 | * play whilst audio is paused */ | ||
25 | /* Design: we have prev_ti already, have a conditional for what type of seek | 27 | /* Design: we have prev_ti already, have a conditional for what type of seek |
26 | * to do on a seek request, if it is a previous track seek, skip previous, | 28 | * to do on a seek request, if it is a previous track seek, skip previous, |
27 | * and in the request_next_track callback set the offset up the same way that | 29 | * and in the request_next_track callback set the offset up the same way that |
@@ -39,7 +41,6 @@ | |||
39 | #include "file.h" | 41 | #include "file.h" |
40 | #include "lcd.h" | 42 | #include "lcd.h" |
41 | #include "font.h" | 43 | #include "font.h" |
42 | #include "backlight.h" | ||
43 | #include "button.h" | 44 | #include "button.h" |
44 | #include "kernel.h" | 45 | #include "kernel.h" |
45 | #include "tree.h" | 46 | #include "tree.h" |
@@ -81,10 +82,7 @@ | |||
81 | #include "recording.h" | 82 | #include "recording.h" |
82 | #endif | 83 | #endif |
83 | 84 | ||
84 | static volatile bool audio_codec_loaded; | 85 | #define PLAYBACK_VOICE |
85 | static volatile bool voice_codec_loaded; | ||
86 | static volatile bool playing; | ||
87 | static volatile bool paused; | ||
88 | 86 | ||
89 | 87 | ||
90 | /* default point to start buffer refill */ | 88 | /* default point to start buffer refill */ |
@@ -99,10 +97,10 @@ static volatile bool paused; | |||
99 | 97 | ||
100 | /* macros to enable logf for queues */ | 98 | /* macros to enable logf for queues */ |
101 | #ifdef SIMULATOR | 99 | #ifdef SIMULATOR |
102 | #define LOGF_QUEUES /* Define this for logf output of all queuing */ | 100 | #define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */ |
103 | #endif | 101 | #endif |
104 | 102 | ||
105 | #ifdef LOGF_QUEUES | 103 | #ifdef PLAYBACK_LOGQUEUES |
106 | #define LOGFQUEUE(s) logf("%s", s) | 104 | #define LOGFQUEUE(s) logf("%s", s) |
107 | #else | 105 | #else |
108 | #define LOGFQUEUE(s) | 106 | #define LOGFQUEUE(s) |
@@ -159,6 +157,14 @@ enum { | |||
159 | #endif | 157 | #endif |
160 | #define CODEC_IRAM_SIZE 0xc000 | 158 | #define CODEC_IRAM_SIZE 0xc000 |
161 | 159 | ||
160 | #ifdef PLAYBACK_VOICE | ||
161 | #ifdef SIMULATOR | ||
162 | static unsigned char sim_iram[CODEC_IRAM_SIZE]; | ||
163 | #undef CODEC_IRAM_ORIGIN | ||
164 | #define CODEC_IRAM_ORIGIN sim_iram | ||
165 | #endif | ||
166 | #endif | ||
167 | |||
162 | #ifndef SIMULATOR | 168 | #ifndef SIMULATOR |
163 | extern bool audio_is_initialized; | 169 | extern bool audio_is_initialized; |
164 | #else | 170 | #else |
@@ -170,13 +176,9 @@ static bool audio_is_initialized = false; | |||
170 | static struct mutex mutex_codecthread; | 176 | static struct mutex mutex_codecthread; |
171 | static struct event_queue codec_callback_queue; | 177 | static struct event_queue codec_callback_queue; |
172 | 178 | ||
173 | static struct mp3entry id3_voice; | 179 | static volatile bool audio_codec_loaded; |
174 | 180 | static volatile bool playing; | |
175 | static char *voicebuf; | 181 | static volatile bool paused; |
176 | static size_t voice_remaining; | ||
177 | static bool voice_is_playing; | ||
178 | static void (*voice_getmore)(unsigned char** start, int* size); | ||
179 | static struct thread_entry *voice_thread_p = NULL; | ||
180 | 182 | ||
181 | /* Is file buffer currently being refilled? */ | 183 | /* Is file buffer currently being refilled? */ |
182 | static volatile bool filling IDATA_ATTR; | 184 | static volatile bool filling IDATA_ATTR; |
@@ -197,9 +199,7 @@ size_t filebufused; | |||
197 | static volatile size_t buf_ridx IDATA_ATTR; | 199 | static volatile size_t buf_ridx IDATA_ATTR; |
198 | static volatile size_t buf_widx IDATA_ATTR; | 200 | static volatile size_t buf_widx IDATA_ATTR; |
199 | 201 | ||
200 | #ifndef SIMULATOR | ||
201 | static unsigned char *iram_buf[2]; | 202 | static unsigned char *iram_buf[2]; |
202 | #endif | ||
203 | static unsigned char *dram_buf[2]; | 203 | static unsigned char *dram_buf[2]; |
204 | 204 | ||
205 | /* Step count to the next unbuffered track. */ | 205 | /* Step count to the next unbuffered track. */ |
@@ -209,7 +209,7 @@ static int last_peek_offset; | |||
209 | track ring structure. */ | 209 | track ring structure. */ |
210 | static int track_ridx; | 210 | static int track_ridx; |
211 | static int track_widx; | 211 | static int track_widx; |
212 | static bool track_changed; | 212 | static bool track_changed; /* Audio and codec threads */ |
213 | 213 | ||
214 | /* Partially loaded song's file handle to continue buffering later. */ | 214 | /* Partially loaded song's file handle to continue buffering later. */ |
215 | static int current_fd; | 215 | static int current_fd; |
@@ -218,23 +218,20 @@ static int current_fd; | |||
218 | static size_t fill_bytesleft; | 218 | static size_t fill_bytesleft; |
219 | 219 | ||
220 | /* Track info structure about songs in the file buffer. */ | 220 | /* Track info structure about songs in the file buffer. */ |
221 | static struct track_info tracks[MAX_TRACK]; | 221 | static struct track_info tracks[MAX_TRACK]; /* Audio thread */ |
222 | 222 | ||
223 | /* Pointer to track info structure about current song playing. */ | 223 | /* Pointer to track info structure about current song playing. */ |
224 | static struct track_info *cur_ti; | 224 | static struct track_info *cur_ti; /* Audio and codec threads */ |
225 | static struct track_info *prev_ti; | 225 | static struct track_info *prev_ti; /* Audio and codec threads */ |
226 | 226 | ||
227 | /* Have we reached end of the current playlist. */ | 227 | /* Have we reached end of the current playlist. */ |
228 | static bool playlist_end = false; | 228 | static bool playlist_end = false; /* Audio thread */ |
229 | |||
230 | /* Codec API including function callbacks. */ | ||
231 | extern struct codec_api ci; | ||
232 | extern struct codec_api ci_voice; | ||
233 | 229 | ||
234 | /* Was the skip being executed manual or automatic? */ | 230 | /* Was the skip being executed manual or automatic? */ |
235 | static bool automatic_skip; | 231 | static bool automatic_skip = false; /* Audio and codec threads */ |
236 | static bool dir_skip = false; | 232 | static bool dir_skip = false; /* Audio thread */ |
237 | static bool new_playlist = false; | 233 | static bool new_playlist = false; /* Audio thread */ |
234 | static int wps_offset = 0; | ||
238 | 235 | ||
239 | /* Callback function to call when current track has really changed. */ | 236 | /* Callback function to call when current track has really changed. */ |
240 | void (*track_changed_callback)(struct mp3entry *id3); | 237 | void (*track_changed_callback)(struct mp3entry *id3); |
@@ -250,6 +247,7 @@ static bool v1first = false; | |||
250 | 247 | ||
251 | /* Multiple threads */ | 248 | /* Multiple threads */ |
252 | static const char * get_codec_filename(int enc_spec); | 249 | static const char * get_codec_filename(int enc_spec); |
250 | static void set_filebuf_watermark(int seconds); | ||
253 | 251 | ||
254 | /* Audio thread */ | 252 | /* Audio thread */ |
255 | static struct event_queue audio_queue; | 253 | static struct event_queue audio_queue; |
@@ -257,12 +255,12 @@ static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | |||
257 | static const char audio_thread_name[] = "audio"; | 255 | static const char audio_thread_name[] = "audio"; |
258 | 256 | ||
259 | static void audio_thread(void); | 257 | static void audio_thread(void); |
260 | static void set_filebuf_watermark(int seconds); | ||
261 | static void audio_initiate_track_change(long direction); | 258 | static void audio_initiate_track_change(long direction); |
262 | static bool audio_have_tracks(void); | 259 | static bool audio_have_tracks(void); |
263 | static void audio_reset_buffer(void); | 260 | static void audio_reset_buffer(void); |
264 | 261 | ||
265 | /* Codec thread */ | 262 | /* Codec thread */ |
263 | extern struct codec_api ci; | ||
266 | static struct event_queue codec_queue; | 264 | static struct event_queue codec_queue; |
267 | static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] | 265 | static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] |
268 | IBSS_ATTR; | 266 | IBSS_ATTR; |
@@ -271,6 +269,17 @@ static const char codec_thread_name[] = "codec"; | |||
271 | struct thread_entry *codec_thread_p; | 269 | struct thread_entry *codec_thread_p; |
272 | 270 | ||
273 | /* Voice thread */ | 271 | /* Voice thread */ |
272 | #ifdef PLAYBACK_VOICE | ||
273 | extern struct codec_api ci_voice; | ||
274 | |||
275 | static volatile bool voice_thread_start; | ||
276 | static volatile bool voice_is_playing; | ||
277 | static volatile bool voice_codec_loaded; | ||
278 | static void (*voice_getmore)(unsigned char** start, int* size); | ||
279 | static char *voicebuf; | ||
280 | static size_t voice_remaining; | ||
281 | static struct thread_entry *voice_thread_p = NULL; | ||
282 | |||
274 | static struct event_queue voice_queue; | 283 | static struct event_queue voice_queue; |
275 | static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] | 284 | static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] |
276 | IBSS_ATTR; | 285 | IBSS_ATTR; |
@@ -286,30 +295,39 @@ static void voice_boost_cpu(bool state); | |||
286 | #else | 295 | #else |
287 | #define voice_boost_cpu(state) do { } while(0) | 296 | #define voice_boost_cpu(state) do { } while(0) |
288 | #endif | 297 | #endif |
289 | |||
290 | static void voice_thread(void); | 298 | static void voice_thread(void); |
291 | 299 | ||
300 | #endif /* PLAYBACK_VOICE */ | ||
301 | |||
292 | /* --- External interfaces --- */ | 302 | /* --- External interfaces --- */ |
293 | 303 | ||
294 | void mp3_play_data(const unsigned char* start, int size, | 304 | void mp3_play_data(const unsigned char* start, int size, |
295 | void (*get_more)(unsigned char** start, int* size)) | 305 | void (*get_more)(unsigned char** start, int* size)) |
296 | { | 306 | { |
307 | #ifdef PLAYBACK_VOICE | ||
297 | static struct voice_info voice_clip; | 308 | static struct voice_info voice_clip; |
298 | voice_clip.callback = get_more; | 309 | voice_clip.callback = get_more; |
299 | voice_clip.buf = (char *)start; | 310 | voice_clip.buf = (char *)start; |
300 | voice_clip.size = size; | 311 | voice_clip.size = size; |
301 | logf("mp3 > voice Q_VOICE_STOP"); | 312 | LOGFQUEUE("mp3 > voice Q_VOICE_STOP"); |
302 | queue_post(&voice_queue, Q_VOICE_STOP, 0); | 313 | queue_post(&voice_queue, Q_VOICE_STOP, 0); |
303 | logf("mp3 > voice Q_VOICE_PLAY"); | 314 | LOGFQUEUE("mp3 > voice Q_VOICE_PLAY"); |
304 | queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip); | 315 | queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip); |
305 | voice_is_playing = true; | 316 | voice_thread_start = true; |
306 | voice_boost_cpu(true); | 317 | voice_boost_cpu(true); |
318 | #else | ||
319 | (void) start; | ||
320 | (void) size; | ||
321 | (void) get_more; | ||
322 | #endif | ||
307 | } | 323 | } |
308 | 324 | ||
309 | void mp3_play_stop(void) | 325 | void mp3_play_stop(void) |
310 | { | 326 | { |
311 | logf("mp3 > voice Q_VOICE_STOP"); | 327 | #ifdef PLAYBACK_VOICE |
328 | LOGFQUEUE("mp3 > voice Q_VOICE_STOP"); | ||
312 | queue_post(&voice_queue, Q_VOICE_STOP, 0); | 329 | queue_post(&voice_queue, Q_VOICE_STOP, 0); |
330 | #endif | ||
313 | } | 331 | } |
314 | 332 | ||
315 | bool mp3_pause_done(void) | 333 | bool mp3_pause_done(void) |
@@ -360,8 +378,9 @@ struct mp3entry* audio_current_track(void) | |||
360 | const char *p; | 378 | const char *p; |
361 | static struct mp3entry temp_id3; | 379 | static struct mp3entry temp_id3; |
362 | int cur_idx; | 380 | int cur_idx; |
381 | int offset = ci.new_track + wps_offset; | ||
363 | 382 | ||
364 | cur_idx = track_ridx + ci.new_track; | 383 | cur_idx = track_ridx + offset; |
365 | cur_idx &= MAX_TRACK_MASK; | 384 | cur_idx &= MAX_TRACK_MASK; |
366 | 385 | ||
367 | if (tracks[cur_idx].taginfo_ready) | 386 | if (tracks[cur_idx].taginfo_ready) |
@@ -369,7 +388,7 @@ struct mp3entry* audio_current_track(void) | |||
369 | 388 | ||
370 | memset(&temp_id3, 0, sizeof(struct mp3entry)); | 389 | memset(&temp_id3, 0, sizeof(struct mp3entry)); |
371 | 390 | ||
372 | filename = playlist_peek(ci.new_track); | 391 | filename = playlist_peek(offset); |
373 | if (!filename) | 392 | if (!filename) |
374 | filename = "No file!"; | 393 | filename = "No file!"; |
375 | 394 | ||
@@ -427,10 +446,7 @@ void audio_play(long offset) | |||
427 | } | 446 | } |
428 | else | 447 | else |
429 | { | 448 | { |
430 | if (playing) | 449 | audio_stop(); |
431 | audio_stop(); | ||
432 | |||
433 | playing = true; | ||
434 | LOGFQUEUE("audio > audio Q_AUDIO_PLAY"); | 450 | LOGFQUEUE("audio > audio Q_AUDIO_PLAY"); |
435 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); | 451 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); |
436 | } | 452 | } |
@@ -440,8 +456,6 @@ void audio_stop(void) | |||
440 | { | 456 | { |
441 | LOGFQUEUE("audio > audio Q_AUDIO_STOP"); | 457 | LOGFQUEUE("audio > audio Q_AUDIO_STOP"); |
442 | queue_post(&audio_queue, Q_AUDIO_STOP, 0); | 458 | queue_post(&audio_queue, Q_AUDIO_STOP, 0); |
443 | while (playing || audio_codec_loaded) | ||
444 | yield(); | ||
445 | } | 459 | } |
446 | 460 | ||
447 | void audio_pause(void) | 461 | void audio_pause(void) |
@@ -461,10 +475,21 @@ void audio_next(void) | |||
461 | if (global_settings.beep) | 475 | if (global_settings.beep) |
462 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); | 476 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); |
463 | 477 | ||
464 | /* Should be safe to do outside of thread, that way we get | 478 | if (playlist_check(ci.new_track + wps_offset + 1)) |
465 | * the instant wps response at least. */ | 479 | { |
466 | audio_initiate_track_change(1); | 480 | LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1"); |
467 | // queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1); | 481 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1); |
482 | /* Keep wps fast while our message travels inside deep playback queues. */ | ||
483 | wps_offset++; | ||
484 | track_changed = true; | ||
485 | } | ||
486 | else | ||
487 | { | ||
488 | /* No more tracks. */ | ||
489 | if (global_settings.beep) | ||
490 | pcmbuf_beep(3000, 300, 2500*global_settings.beep); | ||
491 | |||
492 | } | ||
468 | } | 493 | } |
469 | 494 | ||
470 | void audio_prev(void) | 495 | void audio_prev(void) |
@@ -472,8 +497,21 @@ void audio_prev(void) | |||
472 | if (global_settings.beep) | 497 | if (global_settings.beep) |
473 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); | 498 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); |
474 | 499 | ||
475 | audio_initiate_track_change(-1); | 500 | if (playlist_check(ci.new_track + wps_offset - 1)) |
476 | // queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1); | 501 | { |
502 | LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1"); | ||
503 | queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1); | ||
504 | /* Keep wps fast while our message travels inside deep playback queues. */ | ||
505 | wps_offset--; | ||
506 | track_changed = true; | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | /* No more tracks. */ | ||
511 | if (global_settings.beep) | ||
512 | pcmbuf_beep(3000, 300, 2500*global_settings.beep); | ||
513 | |||
514 | } | ||
477 | } | 515 | } |
478 | 516 | ||
479 | void audio_next_dir(void) | 517 | void audio_next_dir(void) |
@@ -598,7 +636,6 @@ void audio_set_crossfade(int enable) | |||
598 | 636 | ||
599 | /* Restart playback. */ | 637 | /* Restart playback. */ |
600 | if (was_playing) { | 638 | if (was_playing) { |
601 | playing = true; | ||
602 | LOGFQUEUE("audio > audio Q_AUDIO_PLAY"); | 639 | LOGFQUEUE("audio > audio Q_AUDIO_PLAY"); |
603 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); | 640 | queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); |
604 | 641 | ||
@@ -619,7 +656,11 @@ void audio_preinit(void) | |||
619 | playing = false; | 656 | playing = false; |
620 | paused = false; | 657 | paused = false; |
621 | audio_codec_loaded = false; | 658 | audio_codec_loaded = false; |
659 | #ifdef PLAYBACK_VOICE | ||
622 | voice_is_playing = false; | 660 | voice_is_playing = false; |
661 | voice_thread_start = false; | ||
662 | voice_codec_loaded = false; | ||
663 | #endif | ||
623 | track_changed = false; | 664 | track_changed = false; |
624 | current_fd = -1; | 665 | current_fd = -1; |
625 | track_buffer_callback = NULL; | 666 | track_buffer_callback = NULL; |
@@ -647,6 +688,7 @@ void audio_init(void) | |||
647 | 688 | ||
648 | void voice_init(void) | 689 | void voice_init(void) |
649 | { | 690 | { |
691 | #ifdef PLAYBACK_VOICE | ||
650 | if (!filebuf) | 692 | if (!filebuf) |
651 | return; /* Audio buffers not yet set up */ | 693 | return; /* Audio buffers not yet set up */ |
652 | 694 | ||
@@ -672,10 +714,12 @@ void voice_init(void) | |||
672 | 714 | ||
673 | while (!voice_codec_loaded) | 715 | while (!voice_codec_loaded) |
674 | yield(); | 716 | yield(); |
717 | #endif | ||
675 | } /* voice_init */ | 718 | } /* voice_init */ |
676 | 719 | ||
677 | void voice_stop(void) | 720 | void voice_stop(void) |
678 | { | 721 | { |
722 | #ifdef PLAYBACK_VOICE | ||
679 | /* Messages should not be posted to voice codec queue unless it is the | 723 | /* Messages should not be posted to voice codec queue unless it is the |
680 | current codec or deadlocks happen. This will be addressed globally soon. | 724 | current codec or deadlocks happen. This will be addressed globally soon. |
681 | -- jhMikeS */ | 725 | -- jhMikeS */ |
@@ -683,14 +727,14 @@ void voice_stop(void) | |||
683 | return; | 727 | return; |
684 | 728 | ||
685 | mp3_play_stop(); | 729 | mp3_play_stop(); |
686 | while (voice_is_playing && !queue_empty(&voice_queue)) | 730 | #endif |
687 | yield(); | ||
688 | } /* voice_stop */ | 731 | } /* voice_stop */ |
689 | 732 | ||
690 | 733 | ||
691 | 734 | ||
692 | /* --- Routines called from multiple threads --- */ | 735 | /* --- Routines called from multiple threads --- */ |
693 | 736 | ||
737 | #ifdef PLAYBACK_VOICE | ||
694 | static void swap_codec(void) | 738 | static void swap_codec(void) |
695 | { | 739 | { |
696 | int my_codec = current_codec; | 740 | int my_codec = current_codec; |
@@ -698,31 +742,34 @@ static void swap_codec(void) | |||
698 | logf("swapping out codec:%d", my_codec); | 742 | logf("swapping out codec:%d", my_codec); |
699 | 743 | ||
700 | /* Save our current IRAM and DRAM */ | 744 | /* Save our current IRAM and DRAM */ |
701 | #ifndef SIMULATOR | ||
702 | memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN, | 745 | memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN, |
703 | CODEC_IRAM_SIZE); | 746 | CODEC_IRAM_SIZE); |
704 | #endif | ||
705 | memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE); | 747 | memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE); |
706 | 748 | ||
749 | /* Release my semaphore */ | ||
750 | mutex_unlock(&mutex_codecthread); | ||
751 | |||
752 | /* Loop until the other codec has locked and run */ | ||
707 | do { | 753 | do { |
708 | /* Release my semaphore and force a task switch. */ | 754 | /* Release my semaphore and force a task switch. */ |
709 | mutex_unlock(&mutex_codecthread); | ||
710 | yield(); | 755 | yield(); |
711 | mutex_lock(&mutex_codecthread); | ||
712 | /* Loop until the other codec has locked and run */ | ||
713 | } while (my_codec == current_codec); | 756 | } while (my_codec == current_codec); |
757 | |||
758 | /* Wait for other codec to unlock */ | ||
759 | mutex_lock(&mutex_codecthread); | ||
760 | |||
761 | /* Take control */ | ||
714 | current_codec = my_codec; | 762 | current_codec = my_codec; |
715 | 763 | ||
716 | /* Reload our IRAM and DRAM */ | 764 | /* Reload our IRAM and DRAM */ |
717 | #ifndef SIMULATOR | ||
718 | memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec], | 765 | memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec], |
719 | CODEC_IRAM_SIZE); | 766 | CODEC_IRAM_SIZE); |
720 | #endif | ||
721 | invalidate_icache(); | 767 | invalidate_icache(); |
722 | memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE); | 768 | memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE); |
723 | 769 | ||
724 | logf("resuming codec:%d", my_codec); | 770 | logf("resuming codec:%d", my_codec); |
725 | } | 771 | } |
772 | #endif | ||
726 | 773 | ||
727 | static void set_filebuf_watermark(int seconds) | 774 | static void set_filebuf_watermark(int seconds) |
728 | { | 775 | { |
@@ -761,6 +808,8 @@ static const char * get_codec_filename(int enc_spec) | |||
761 | 808 | ||
762 | /* --- Voice thread --- */ | 809 | /* --- Voice thread --- */ |
763 | 810 | ||
811 | #ifdef PLAYBACK_VOICE | ||
812 | |||
764 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 813 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
765 | static void voice_boost_cpu(bool state) | 814 | static void voice_boost_cpu(bool state) |
766 | { | 815 | { |
@@ -768,8 +817,8 @@ static void voice_boost_cpu(bool state) | |||
768 | 817 | ||
769 | if (state != voice_cpu_boosted) | 818 | if (state != voice_cpu_boosted) |
770 | { | 819 | { |
771 | cpu_boost(state); | ||
772 | voice_cpu_boosted = state; | 820 | voice_cpu_boosted = state; |
821 | cpu_boost(state); | ||
773 | } | 822 | } |
774 | } | 823 | } |
775 | #endif | 824 | #endif |
@@ -795,7 +844,7 @@ static bool voice_pcmbuf_insert_split_callback( | |||
795 | while ((dest = pcmbuf_request_voice_buffer(est_output_size, | 844 | while ((dest = pcmbuf_request_voice_buffer(est_output_size, |
796 | &output_size, playing)) == NULL) | 845 | &output_size, playing)) == NULL) |
797 | { | 846 | { |
798 | if (playing) | 847 | if (playing && audio_codec_loaded) |
799 | swap_codec(); | 848 | swap_codec(); |
800 | else | 849 | else |
801 | yield(); | 850 | yield(); |
@@ -823,7 +872,7 @@ static bool voice_pcmbuf_insert_split_callback( | |||
823 | if (playing) | 872 | if (playing) |
824 | { | 873 | { |
825 | pcmbuf_mix_voice(output_size); | 874 | pcmbuf_mix_voice(output_size); |
826 | if (pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) | 875 | if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded) |
827 | swap_codec(); | 876 | swap_codec(); |
828 | } | 877 | } |
829 | else | 878 | else |
@@ -902,13 +951,19 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
902 | case Q_AUDIO_PLAY: | 951 | case Q_AUDIO_PLAY: |
903 | LOGFQUEUE("voice < Q_AUDIO_PLAY"); | 952 | LOGFQUEUE("voice < Q_AUDIO_PLAY"); |
904 | if (playing) | 953 | if (playing) |
905 | swap_codec(); | 954 | { |
955 | if (audio_codec_loaded) | ||
956 | swap_codec(); | ||
957 | else | ||
958 | yield(); | ||
959 | } | ||
906 | break; | 960 | break; |
907 | 961 | ||
908 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) | 962 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) |
909 | case Q_ENCODER_RECORD: | 963 | case Q_ENCODER_RECORD: |
910 | LOGFQUEUE("voice < Q_ENCODER_RECORD"); | 964 | LOGFQUEUE("voice < Q_ENCODER_RECORD"); |
911 | swap_codec(); | 965 | if (audio_codec_loaded) |
966 | swap_codec(); | ||
912 | break; | 967 | break; |
913 | #endif | 968 | #endif |
914 | 969 | ||
@@ -940,6 +995,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
940 | 995 | ||
941 | case Q_VOICE_PLAY: | 996 | case Q_VOICE_PLAY: |
942 | LOGFQUEUE("voice < Q_VOICE_PLAY"); | 997 | LOGFQUEUE("voice < Q_VOICE_PLAY"); |
998 | if (!voice_is_playing) | ||
943 | { | 999 | { |
944 | struct voice_info *voice_data; | 1000 | struct voice_info *voice_data; |
945 | voice_is_playing = true; | 1001 | voice_is_playing = true; |
@@ -949,6 +1005,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) | |||
949 | voicebuf = voice_data->buf; | 1005 | voicebuf = voice_data->buf; |
950 | voice_getmore = voice_data->callback; | 1006 | voice_getmore = voice_data->callback; |
951 | } | 1007 | } |
1008 | goto voice_play_clip; | ||
952 | 1009 | ||
953 | case SYS_TIMEOUT: | 1010 | case SYS_TIMEOUT: |
954 | LOGFQUEUE("voice < SYS_TIMEOUT"); | 1011 | LOGFQUEUE("voice < SYS_TIMEOUT"); |
@@ -967,7 +1024,7 @@ voice_play_clip: | |||
967 | voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining); | 1024 | voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining); |
968 | 1025 | ||
969 | /* If this clip is done */ | 1026 | /* If this clip is done */ |
970 | if (!voice_remaining) | 1027 | if (voice_remaining == 0) |
971 | { | 1028 | { |
972 | LOGFQUEUE("voice > voice Q_VOICE_STOP"); | 1029 | LOGFQUEUE("voice > voice Q_VOICE_STOP"); |
973 | queue_post(&voice_queue, Q_VOICE_STOP, 0); | 1030 | queue_post(&voice_queue, Q_VOICE_STOP, 0); |
@@ -1044,6 +1101,7 @@ static void voice_thread(void) | |||
1044 | } | 1101 | } |
1045 | } /* voice_thread */ | 1102 | } /* voice_thread */ |
1046 | 1103 | ||
1104 | #endif /* PLAYBACK_VOICE */ | ||
1047 | 1105 | ||
1048 | /* --- Codec thread --- */ | 1106 | /* --- Codec thread --- */ |
1049 | 1107 | ||
@@ -1097,11 +1155,15 @@ static bool codec_pcmbuf_insert_split_callback( | |||
1097 | 1155 | ||
1098 | pcmbuf_write_complete(output_size); | 1156 | pcmbuf_write_complete(output_size); |
1099 | 1157 | ||
1100 | if (voice_is_playing && pcm_is_playing() && | 1158 | #ifdef PLAYBACK_VOICE |
1101 | pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80) | 1159 | if ((voice_is_playing || voice_thread_start) |
1160 | && pcm_is_playing() && voice_codec_loaded && | ||
1161 | pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80) | ||
1102 | { | 1162 | { |
1163 | voice_thread_start = false; | ||
1103 | swap_codec(); | 1164 | swap_codec(); |
1104 | } | 1165 | } |
1166 | #endif | ||
1105 | 1167 | ||
1106 | length -= input_size; | 1168 | length -= input_size; |
1107 | } | 1169 | } |
@@ -1684,11 +1746,13 @@ static void codec_thread(void) | |||
1684 | case Q_CODEC_LOAD_DISK: | 1746 | case Q_CODEC_LOAD_DISK: |
1685 | LOGFQUEUE("codec < Q_CODEC_LOAD_DISK"); | 1747 | LOGFQUEUE("codec < Q_CODEC_LOAD_DISK"); |
1686 | audio_codec_loaded = true; | 1748 | audio_codec_loaded = true; |
1749 | #ifdef PLAYBACK_VOICE | ||
1687 | if (voice_codec_loaded) | 1750 | if (voice_codec_loaded) |
1688 | { | 1751 | { |
1689 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 1752 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
1690 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 1753 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
1691 | } | 1754 | } |
1755 | #endif | ||
1692 | mutex_lock(&mutex_codecthread); | 1756 | mutex_lock(&mutex_codecthread); |
1693 | current_codec = CODEC_IDX_AUDIO; | 1757 | current_codec = CODEC_IDX_AUDIO; |
1694 | ci.stop_codec = false; | 1758 | ci.stop_codec = false; |
@@ -1711,11 +1775,13 @@ static void codec_thread(void) | |||
1711 | } | 1775 | } |
1712 | 1776 | ||
1713 | audio_codec_loaded = true; | 1777 | audio_codec_loaded = true; |
1778 | #ifdef PLAYBACK_VOICE | ||
1714 | if (voice_codec_loaded) | 1779 | if (voice_codec_loaded) |
1715 | { | 1780 | { |
1716 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); | 1781 | LOGFQUEUE("codec > voice Q_AUDIO_PLAY"); |
1717 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); | 1782 | queue_post(&voice_queue, Q_AUDIO_PLAY, 0); |
1718 | } | 1783 | } |
1784 | #endif | ||
1719 | mutex_lock(&mutex_codecthread); | 1785 | mutex_lock(&mutex_codecthread); |
1720 | current_codec = CODEC_IDX_AUDIO; | 1786 | current_codec = CODEC_IDX_AUDIO; |
1721 | ci.stop_codec = false; | 1787 | ci.stop_codec = false; |
@@ -1729,11 +1795,13 @@ static void codec_thread(void) | |||
1729 | case Q_ENCODER_LOAD_DISK: | 1795 | case Q_ENCODER_LOAD_DISK: |
1730 | LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK"); | 1796 | LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK"); |
1731 | audio_codec_loaded = false; | 1797 | audio_codec_loaded = false; |
1798 | #ifdef PLAYBACK_VOICE | ||
1732 | if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE) | 1799 | if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE) |
1733 | { | 1800 | { |
1734 | LOGFQUEUE("codec > voice Q_ENCODER_RECORD"); | 1801 | LOGFQUEUE("codec > voice Q_ENCODER_RECORD"); |
1735 | queue_post(&voice_queue, Q_ENCODER_RECORD, NULL); | 1802 | queue_post(&voice_queue, Q_ENCODER_RECORD, NULL); |
1736 | } | 1803 | } |
1804 | #endif | ||
1737 | mutex_lock(&mutex_codecthread); | 1805 | mutex_lock(&mutex_codecthread); |
1738 | current_codec = CODEC_IDX_AUDIO; | 1806 | current_codec = CODEC_IDX_AUDIO; |
1739 | ci.stop_codec = false; | 1807 | ci.stop_codec = false; |
@@ -1747,8 +1815,10 @@ static void codec_thread(void) | |||
1747 | LOGFQUEUE("codec < SYS_USB_CONNECTED"); | 1815 | LOGFQUEUE("codec < SYS_USB_CONNECTED"); |
1748 | queue_clear(&codec_queue); | 1816 | queue_clear(&codec_queue); |
1749 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | 1817 | usb_acknowledge(SYS_USB_CONNECTED_ACK); |
1750 | if (voice_codec_loaded) | 1818 | #ifdef PLAYBACK_VOICE |
1819 | if(voice_codec_loaded) | ||
1751 | swap_codec(); | 1820 | swap_codec(); |
1821 | #endif | ||
1752 | usb_wait_for_disconnect(&codec_queue); | 1822 | usb_wait_for_disconnect(&codec_queue); |
1753 | break; | 1823 | break; |
1754 | #endif | 1824 | #endif |
@@ -2199,7 +2269,6 @@ static bool audio_loadcodec(bool start_play) | |||
2199 | ci.id3 = &cur_ti->id3; | 2269 | ci.id3 = &cur_ti->id3; |
2200 | ci.taginfo_ready = &cur_ti->taginfo_ready; | 2270 | ci.taginfo_ready = &cur_ti->taginfo_ready; |
2201 | ci.curpos = 0; | 2271 | ci.curpos = 0; |
2202 | playing = true; | ||
2203 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); | 2272 | LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK"); |
2204 | queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn); | 2273 | queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn); |
2205 | return true; | 2274 | return true; |
@@ -2260,9 +2329,7 @@ static bool audio_loadcodec(bool start_play) | |||
2260 | if (buf_widx >= filebuflen) | 2329 | if (buf_widx >= filebuflen) |
2261 | buf_widx -= filebuflen; | 2330 | buf_widx -= filebuflen; |
2262 | 2331 | ||
2263 | tracks[track_widx].codecsize += rc; | 2332 | tracks[track_widx].codecsize += rc; |
2264 | |||
2265 | audio_yield_codecs(); | ||
2266 | } | 2333 | } |
2267 | 2334 | ||
2268 | tracks[track_widx].has_codec = true; | 2335 | tracks[track_widx].has_codec = true; |
@@ -2941,9 +3008,6 @@ static void audio_stop_playback(void) | |||
2941 | (playlist_end && ci.stop_codec)?NULL:audio_current_track()); | 3008 | (playlist_end && ci.stop_codec)?NULL:audio_current_track()); |
2942 | } | 3009 | } |
2943 | 3010 | ||
2944 | while (voice_is_playing && !queue_empty(&voice_queue)) | ||
2945 | yield(); | ||
2946 | |||
2947 | filebufused = 0; | 3011 | filebufused = 0; |
2948 | playing = false; | 3012 | playing = false; |
2949 | filling = false; | 3013 | filling = false; |
@@ -2968,8 +3032,7 @@ static void audio_play_start(size_t offset) | |||
2968 | #endif | 3032 | #endif |
2969 | 3033 | ||
2970 | /* Wait for any previously playing audio to flush - TODO: Not necessary? */ | 3034 | /* Wait for any previously playing audio to flush - TODO: Not necessary? */ |
2971 | while (audio_codec_loaded) | 3035 | audio_stop_codec_flush(); |
2972 | audio_stop_codec_flush(); | ||
2973 | 3036 | ||
2974 | track_changed = true; | 3037 | track_changed = true; |
2975 | playlist_end = false; | 3038 | playlist_end = false; |
@@ -2977,7 +3040,8 @@ static void audio_play_start(size_t offset) | |||
2977 | playing = true; | 3040 | playing = true; |
2978 | ci.new_track = 0; | 3041 | ci.new_track = 0; |
2979 | ci.seek_time = 0; | 3042 | ci.seek_time = 0; |
2980 | 3043 | wps_offset = 0; | |
3044 | |||
2981 | if (current_fd >= 0) | 3045 | if (current_fd >= 0) |
2982 | { | 3046 | { |
2983 | close(current_fd); | 3047 | close(current_fd); |
@@ -3057,15 +3121,9 @@ static void audio_new_playlist(void) | |||
3057 | 3121 | ||
3058 | static void audio_initiate_track_change(long direction) | 3122 | static void audio_initiate_track_change(long direction) |
3059 | { | 3123 | { |
3060 | if (playlist_check(direction)) | 3124 | playlist_end = false; |
3061 | { | 3125 | ci.new_track += direction; |
3062 | playlist_end = false; | 3126 | wps_offset -= direction; |
3063 | /* Flag track changed immediately so wps can update instantly. | ||
3064 | * No need to wait for disk to spin up or message to travel | ||
3065 | * through the deep queues as this info is only for the wps. */ | ||
3066 | track_changed = true; | ||
3067 | ci.new_track += direction; | ||
3068 | } | ||
3069 | } | 3127 | } |
3070 | 3128 | ||
3071 | static void audio_initiate_dir_change(long direction) | 3129 | static void audio_initiate_dir_change(long direction) |
@@ -3090,10 +3148,8 @@ static void audio_reset_buffer(void) | |||
3090 | /* Allow 2 codecs at end of file buffer */ | 3148 | /* Allow 2 codecs at end of file buffer */ |
3091 | filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); | 3149 | filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); |
3092 | 3150 | ||
3093 | #ifndef SIMULATOR | ||
3094 | iram_buf[0] = &filebuf[filebuflen]; | 3151 | iram_buf[0] = &filebuf[filebuflen]; |
3095 | iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; | 3152 | iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; |
3096 | #endif | ||
3097 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2]; | 3153 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2]; |
3098 | dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE]; | 3154 | dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE]; |
3099 | } | 3155 | } |
@@ -3102,10 +3158,8 @@ static void audio_reset_buffer(void) | |||
3102 | /* Allow for 1 codec at end of file buffer */ | 3158 | /* Allow for 1 codec at end of file buffer */ |
3103 | filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE; | 3159 | filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE; |
3104 | 3160 | ||
3105 | #ifndef SIMULATOR | ||
3106 | iram_buf[0] = &filebuf[filebuflen]; | 3161 | iram_buf[0] = &filebuf[filebuflen]; |
3107 | iram_buf[1] = NULL; | 3162 | iram_buf[1] = NULL; |
3108 | #endif | ||
3109 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE]; | 3163 | dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE]; |
3110 | dram_buf[1] = NULL; | 3164 | dram_buf[1] = NULL; |
3111 | } | 3165 | } |
@@ -3129,7 +3183,10 @@ static void audio_test_track_changed_event(struct mp3entry *id3) | |||
3129 | 3183 | ||
3130 | static void audio_playback_init(void) | 3184 | static void audio_playback_init(void) |
3131 | { | 3185 | { |
3186 | #ifdef PLAYBACK_VOICE | ||
3132 | static bool voicetagtrue = true; | 3187 | static bool voicetagtrue = true; |
3188 | static struct mp3entry id3_voice; | ||
3189 | #endif | ||
3133 | struct event ev; | 3190 | struct event ev; |
3134 | 3191 | ||
3135 | logf("playback api init"); | 3192 | logf("playback api init"); |
@@ -3162,6 +3219,7 @@ static void audio_playback_init(void) | |||
3162 | ci.discard_codec = codec_discard_codec_callback; | 3219 | ci.discard_codec = codec_discard_codec_callback; |
3163 | 3220 | ||
3164 | /* Initialize voice codec api. */ | 3221 | /* Initialize voice codec api. */ |
3222 | #ifdef PLAYBACK_VOICE | ||
3165 | memcpy(&ci_voice, &ci, sizeof(struct codec_api)); | 3223 | memcpy(&ci_voice, &ci, sizeof(struct codec_api)); |
3166 | memset(&id3_voice, 0, sizeof(struct mp3entry)); | 3224 | memset(&id3_voice, 0, sizeof(struct mp3entry)); |
3167 | ci_voice.read_filebuf = voice_filebuf_callback; | 3225 | ci_voice.read_filebuf = voice_filebuf_callback; |
@@ -3182,6 +3240,7 @@ static void audio_playback_init(void) | |||
3182 | ci_voice.id3 = &id3_voice; | 3240 | ci_voice.id3 = &id3_voice; |
3183 | id3_voice.frequency = 11200; | 3241 | id3_voice.frequency = 11200; |
3184 | id3_voice.length = 1000000L; | 3242 | id3_voice.length = 1000000L; |
3243 | #endif | ||
3185 | 3244 | ||
3186 | codec_thread_p = create_thread(codec_thread, codec_stack, | 3245 | codec_thread_p = create_thread(codec_thread, codec_stack, |
3187 | sizeof(codec_stack), | 3246 | sizeof(codec_stack), |
@@ -3288,8 +3347,6 @@ static void audio_thread(void) | |||
3288 | case Q_AUDIO_DIR_SKIP: | 3347 | case Q_AUDIO_DIR_SKIP: |
3289 | LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP"); | 3348 | LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP"); |
3290 | playlist_end = false; | 3349 | playlist_end = false; |
3291 | if (global_settings.beep) | ||
3292 | pcmbuf_beep(5000, 100, 2500*global_settings.beep); | ||
3293 | audio_initiate_dir_change((long)ev.data); | 3350 | audio_initiate_dir_change((long)ev.data); |
3294 | break; | 3351 | break; |
3295 | 3352 | ||