1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #if CONFIG_CODEC != SWCODEC
39 #include "mp3_playback.h"
43 #include "appevents.h"
54 #endif /* !SIMULATOR */
55 #ifdef HAVE_LCD_BITMAP
57 #endif /* CONFIG_CODEC != SWCODEC */
59 #define MPEG_SWAP_CHUNKSIZE 0x2000
60 #define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we
61 wouldn't be able to see the difference between
62 an empty buffer and a full one. */
63 #define MPEG_LOW_WATER 0x60000
64 #define MPEG_RECORDING_LOW_WATER 0x80000
65 #define MPEG_LOW_WATER_CHUNKSIZE 0x40000
66 #define MPEG_LOW_WATER_SWAP_CHUNKSIZE 0x10000
67 #if (CONFIG_STORAGE & STORAGE_MMC)
68 #define MPEG_PLAY_PENDING_THRESHOLD 0x20000
69 #define MPEG_PLAY_PENDING_SWAPSIZE 0x20000
71 #define MPEG_PLAY_PENDING_THRESHOLD 0x10000
72 #define MPEG_PLAY_PENDING_SWAPSIZE 0x10000
75 #define MPEG_MAX_PRERECORD_SECONDS 30
77 /* For ID3 info and VBR header */
78 #define MPEG_RESERVED_HEADER_SPACE (4096 + 576)
81 extern unsigned long mas_version_code
;
84 #if CONFIG_CODEC == MAS3587F
85 extern enum /* from mp3_playback.c */
90 #endif /* CONFIG_CODEC == MAS3587F */
98 #define MPEG_FF_REWIND 7
99 #define MPEG_FLUSH_RELOAD 8
100 #define MPEG_RECORD 9
101 #define MPEG_INIT_RECORDING 10
102 #define MPEG_INIT_PLAYBACK 11
103 #define MPEG_NEW_FILE 12
104 #define MPEG_PAUSE_RECORDING 13
105 #define MPEG_RESUME_RECORDING 14
106 #define MPEG_NEED_DATA 100
107 #define MPEG_TRACK_CHANGE 101
108 #define MPEG_SAVE_DATA 102
109 #define MPEG_STOP_DONE 103
110 #define MPEG_PRERECORDING_TICK 104
112 /* indicator for MPEG_NEED_DATA */
113 #define GENERATE_UNBUFFER_EVENTS 1
115 /* list of tracks in memory */
116 #define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */
117 #define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1)
123 int load_ahead_index
;
126 static struct trackdata trackdata
[MAX_TRACK_ENTRIES
];
128 static unsigned int current_track_counter
= 0;
131 /* Play time of the previous track */
132 static unsigned long prev_track_elapsed
;
134 static int track_read_idx
= 0;
135 static int track_write_idx
= 0;
136 #endif /* !SIMULATOR */
138 /* Cuesheet support */
139 static struct cuesheet
*curr_cuesheet
= NULL
;
140 static bool checked_for_cuesheet
= false;
142 static const char mpeg_thread_name
[] = "mpeg";
143 static unsigned int mpeg_errno
;
145 static bool playing
= false; /* We are playing an MP3 stream */
146 static bool is_playing
= false; /* We are (attempting to) playing MP3 files */
147 static bool paused
; /* playback is paused */
148 static char* mpeg_audiobuf
; /* the audio buffer */
149 static long audiobuflen
; /* length of the audio buffer */
152 static char mpeg_stack
[DEFAULT_STACK_SIZE
];
153 static struct mp3entry taginfo
;
154 #else /* !SIMULATOR */
155 static struct event_queue mpeg_queue SHAREDBSS_ATTR
;
156 static long mpeg_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
158 static int audiobuf_write
;
159 static int audiobuf_swapwrite
;
160 static long audiobuf_read
;
162 static int mpeg_file
;
164 static bool play_pending
; /* We are about to start playing */
165 static bool play_pending_track_change
; /* When starting play we're starting a new file */
166 static bool filling
; /* We are filling the buffer with data from disk */
167 static bool dma_underrun
; /* True when the DMA has stopped because of
168 slow disk reading (read error, shaking) */
169 static bool mpeg_stop_done
;
171 static int last_dma_tick
= 0;
172 static int last_dma_chunk_size
;
174 static long low_watermark
; /* Dynamic low watermark level */
175 static long low_watermark_margin
= 0; /* Extra time in seconds for watermark */
176 static long lowest_watermark_level
; /* Debug value to observe the buffer
178 #if CONFIG_CODEC == MAS3587F
179 static char recording_filename
[MAX_PATH
]; /* argument to thread */
180 static char delayed_filename
[MAX_PATH
]; /* internal copy of above */
182 static char xing_buffer
[MAX_XING_HEADER_SIZE
];
184 static bool init_recording_done
;
185 static bool init_playback_done
;
186 static bool prerecording
; /* True if prerecording is enabled */
187 static bool is_prerecording
; /* True if we are prerecording */
188 static bool is_recording
; /* We are recording */
191 NOT_SAVING
= 0, /* reasons to save data, sorted by importance */
197 static int rec_frequency_index
; /* For create_xing_header() calls */
198 static int rec_version_index
; /* For create_xing_header() calls */
200 struct prerecord_info
{
202 unsigned long framecount
;
205 static struct prerecord_info prerecord_buffer
[MPEG_MAX_PRERECORD_SECONDS
];
206 static int prerecord_index
; /* Current index in the prerecord buffer */
207 static int prerecording_max_seconds
; /* Max number of seconds to store */
208 static int prerecord_count
; /* Number of seconds in the prerecord buffer */
209 static int prerecord_timeout
; /* The tick count of the next prerecord data
212 static unsigned long record_start_time
; /* Value of current_tick when recording
214 static unsigned long pause_start_time
; /* Value of current_tick when pause was
216 static unsigned long last_rec_time
;
217 static unsigned long num_rec_bytes
;
218 static unsigned long last_rec_bytes
;
219 static unsigned long frame_count_start
;
220 static unsigned long frame_count_end
;
221 static unsigned long saved_header
= 0;
223 /* Shadow MAS registers */
224 unsigned long shadow_encoder_control
= 0;
225 #endif /* CONFIG_CODEC == MAS3587F */
227 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
228 unsigned long shadow_io_control_main
= 0;
229 unsigned long shadow_soft_mute
= 0;
230 unsigned shadow_codec_reg0
;
231 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
233 #ifdef HAVE_RECORDING
234 static const unsigned char empty_id3_header
[] =
236 'I', 'D', '3', 0x03, 0x00, 0x00,
237 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
239 #endif /* HAVE_RECORDING */
242 static int get_unplayed_space(void);
243 static int get_playable_space(void);
244 static int get_unswapped_space(void);
245 #endif /* !SIMULATOR */
247 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
248 static void init_recording(void);
249 static void prepend_header(void);
250 static void update_header(void);
251 static void start_prerecording(void);
252 static void start_recording(void);
253 static void stop_recording(void);
254 static int get_unsaved_space(void);
255 static void pause_recording(void);
256 static void resume_recording(void);
257 #endif /* (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR) */
261 static int num_tracks_in_memory(void)
263 return (track_write_idx
- track_read_idx
) & MAX_TRACK_ENTRIES_MASK
;
267 static void debug_tags(void)
271 for(i
= 0;i
< MAX_TRACK_ENTRIES
;i
++)
273 DEBUGF("%d - %s\n", i
, trackdata
[i
].id3
.path
);
275 DEBUGF("read: %d, write :%d\n", track_read_idx
, track_write_idx
);
276 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
278 #else /* !DEBUG_TAGS */
280 #endif /* !DEBUG_TAGS */
282 static void remove_current_tag(void)
284 if(num_tracks_in_memory() > 0)
286 /* First move the index, so nobody tries to access the tag */
287 track_read_idx
= (track_read_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
288 checked_for_cuesheet
= false;
293 DEBUGF("remove_current_tag: no tracks to remove\n");
297 static void remove_all_non_current_tags(void)
299 track_write_idx
= (track_read_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
303 static void remove_all_tags(void)
305 track_write_idx
= track_read_idx
;
310 static struct trackdata
*get_trackdata(int offset
)
312 if(offset
>= num_tracks_in_memory())
315 return &trackdata
[(track_read_idx
+ offset
) & MAX_TRACK_ENTRIES_MASK
];
317 #endif /* !SIMULATOR */
319 /***********************************************************************/
320 /* audio event handling */
322 #define MAX_EVENT_HANDLERS 10
323 struct event_handlers_table
325 AUDIO_EVENT_HANDLER handler
;
328 static struct event_handlers_table event_handlers
[MAX_EVENT_HANDLERS
];
329 static int event_handlers_count
= 0;
331 void audio_register_event_handler(AUDIO_EVENT_HANDLER handler
, unsigned short mask
)
333 if (event_handlers_count
< MAX_EVENT_HANDLERS
)
335 event_handlers
[event_handlers_count
].handler
= handler
;
336 event_handlers
[event_handlers_count
].mask
= mask
;
337 event_handlers_count
++;
341 /* dispatch calls each handler in the order registered and returns after some
342 handler actually handles the event (the event is assumed to no longer be valid
343 after this, due to the handler changing some condition); returns true if someone
344 handled the event, which is expected to cause the caller to skip its own handling
347 static bool audio_dispatch_event(unsigned short event
, unsigned long data
)
350 for(i
=0; i
< event_handlers_count
; i
++)
352 if ( event_handlers
[i
].mask
& event
)
354 int rc
= event_handlers
[i
].handler(event
, data
);
355 if ( rc
== AUDIO_EVENT_RC_HANDLED
)
363 /***********************************************************************/
365 static void set_elapsed(struct mp3entry
* id3
)
368 if ( id3
->has_toc
) {
369 /* calculate elapsed time using TOC */
371 unsigned int remainder
, plen
, relpos
, nextpos
;
373 /* find wich percent we're at */
374 for (i
=0; i
<100; i
++ )
376 if ( id3
->offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
386 relpos
= id3
->toc
[i
];
390 nextpos
= id3
->toc
[i
+1];
397 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
399 /* set time for this percent (divide before multiply to prevent
400 overflow on long files. loss of precision is negligible on
402 id3
->elapsed
= i
* (id3
->length
/ 100);
404 /* calculate remainder time */
405 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
406 id3
->elapsed
+= (((remainder
* 100) / plen
) *
407 (id3
->length
/ 10000));
410 /* no TOC exists. set a rough estimate using average bitrate */
411 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
412 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
416 /* constant bitrate, use exact calculation */
417 id3
->elapsed
= id3
->offset
/ (id3
->bitrate
/ 8);
420 int audio_get_file_pos(void)
423 struct mp3entry
*id3
= audio_current_track();
429 /* Use the TOC to find the new position */
430 unsigned int percent
, remainder
;
431 int curtoc
, nexttoc
, plen
;
433 percent
= (id3
->elapsed
*100)/id3
->length
;
437 curtoc
= id3
->toc
[percent
];
440 nexttoc
= id3
->toc
[percent
+1];
444 pos
= (id3
->filesize
/256)*curtoc
;
446 /* Use the remainder to get a more accurate position */
447 remainder
= (id3
->elapsed
*100)%id3
->length
;
448 remainder
= (remainder
*100)/id3
->length
;
449 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
450 pos
+= (plen
/100)*remainder
;
454 /* No TOC exists, estimate the new position */
455 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
456 (id3
->elapsed
/ 1000);
459 else if (id3
->bitrate
)
460 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
466 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
468 /* Don't seek right to the end of the file so that we can
469 transition properly to the next song */
470 pos
= id3
->filesize
- id3
->id3v1len
- 1;
472 else if (pos
< (int)id3
->first_frame_offset
)
474 /* skip past id3v2 tag and other leading garbage */
475 pos
= id3
->first_frame_offset
;
480 unsigned long mpeg_get_last_header(void)
484 #else /* !SIMULATOR */
485 unsigned long tmp
[2];
487 /* Read the frame data from the MAS and reconstruct it with the
488 frame sync and all */
489 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_STATUS_1
, tmp
, 2);
490 return 0xffe00000 | ((tmp
[0] & 0x7c00) << 6) | (tmp
[1] & 0xffff);
491 #endif /* !SIMULATOR */
495 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
497 (void)talk_buf
; /* always grab the voice buffer for now */
500 if (buffer_size
) /* special case for talk_init() */
501 return buffer_get_buffer(buffer_size
);
507 /* Send callback events to notify about removing old tracks. */
508 static void generate_unbuffer_events(void)
511 int numentries
= MAX_TRACK_ENTRIES
- num_tracks_in_memory();
512 int cur_idx
= track_write_idx
;
514 for (i
= 0; i
< numentries
; i
++)
516 /* Send an event to notify that track has finished. */
517 send_event(PLAYBACK_EVENT_TRACK_FINISH
, &trackdata
[cur_idx
].id3
);
518 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_ENTRIES_MASK
;
522 /* Send callback events to notify about new tracks. */
523 static void generate_postbuffer_events(void)
526 int numentries
= num_tracks_in_memory();
527 int cur_idx
= track_read_idx
;
529 for (i
= 0; i
< numentries
; i
++)
531 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, &trackdata
[cur_idx
].id3
);
532 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_ENTRIES_MASK
;
536 static void recalculate_watermark(int bitrate
)
539 int time
= storage_spinup_time();
541 /* A bitrate of 0 probably means empty VBR header. We play safe
542 and set a high threshold */
546 bytes_per_sec
= bitrate
* 1000 / 8;
550 /* No drive spins up faster than 3.5s */
555 low_watermark
= ((low_watermark_margin
* HZ
+ time
) *
560 low_watermark
= MPEG_LOW_WATER
;
564 #ifdef HAVE_DISK_STORAGE
565 void audio_set_buffer_margin(int setting
)
567 low_watermark_margin
= setting
; /* in seconds */
571 void audio_get_debugdata(struct audio_debug
*dbgdata
)
573 dbgdata
->audiobuflen
= audiobuflen
;
574 dbgdata
->audiobuf_write
= audiobuf_write
;
575 dbgdata
->audiobuf_swapwrite
= audiobuf_swapwrite
;
576 dbgdata
->audiobuf_read
= audiobuf_read
;
578 dbgdata
->last_dma_chunk_size
= last_dma_chunk_size
;
580 #if CONFIG_CPU == SH7034
581 dbgdata
->dma_on
= (SCR0
& 0x80) != 0;
583 dbgdata
->playing
= playing
;
584 dbgdata
->play_pending
= play_pending
;
585 dbgdata
->is_playing
= is_playing
;
586 dbgdata
->filling
= filling
;
587 dbgdata
->dma_underrun
= dma_underrun
;
589 dbgdata
->unplayed_space
= get_unplayed_space();
590 dbgdata
->playable_space
= get_playable_space();
591 dbgdata
->unswapped_space
= get_unswapped_space();
593 dbgdata
->low_watermark_level
= low_watermark
;
594 dbgdata
->lowest_watermark_level
= lowest_watermark_level
;
598 static void dbg_timer_start(void)
600 /* We are using timer 2 */
602 TSTR
&= ~0x04; /* Stop the timer */
603 TSNC
&= ~0x04; /* No synchronization */
604 TMDR
&= ~0x44; /* Operate normally */
606 TCNT2
= 0; /* Start counting at 0 */
607 TCR2
= 0x03; /* Sysclock/8 */
609 TSTR
|= 0x04; /* Start timer 2 */
612 static int dbg_cnt2us(unsigned int cnt
)
614 return (cnt
* 10000) / (FREQ
/800);
618 static int get_unplayed_space(void)
620 int space
= audiobuf_write
- audiobuf_read
;
622 space
+= audiobuflen
;
626 static int get_playable_space(void)
628 int space
= audiobuf_swapwrite
- audiobuf_read
;
630 space
+= audiobuflen
;
634 static int get_unplayed_space_current_song(void)
638 if (num_tracks_in_memory() > 1)
640 space
= get_trackdata(1)->mempos
- audiobuf_read
;
644 space
= audiobuf_write
- audiobuf_read
;
648 space
+= audiobuflen
;
653 static int get_unswapped_space(void)
655 int space
= audiobuf_write
- audiobuf_swapwrite
;
657 space
+= audiobuflen
;
661 #if CONFIG_CODEC == MAS3587F
662 static int get_unsaved_space(void)
664 int space
= audiobuf_write
- audiobuf_read
;
666 space
+= audiobuflen
;
670 static void drain_dma_buffer(void)
676 while (PBDRH
& 0x80);
680 while (!(PBDRH
& 0x80));
685 static long timing_info_index
= 0;
686 static long timing_info
[1024];
689 void rec_tick (void) __attribute__ ((section (".icode")));
696 if(is_recording
&& (PBDRH
& 0x40))
699 timing_info
[timing_info_index
++] = current_tick
;
702 /* Note: Although this loop is run in interrupt context, further
703 * optimisation will do no good. The MAS would then deliver bad
704 * frames occasionally, as observed in extended experiments. */
706 while (PBDRH
& 0x40) /* We try to read as long as EOD is high */
708 xor_b(0x08, &PADRH
); /* Set PR active, independent of polarity */
711 while (PBDRH
& 0x80) /* Wait until /RTW becomes active */
713 if (--delay
<= 0) /* Bail out if we have to wait too long */
714 { /* i.e. the MAS doesn't want to talk to us */
715 xor_b(0x08, &PADRH
); /* Set PR inactive */
716 goto transfer_end
; /* and get out of here */
720 data
= *(unsigned char *)0x04000000; /* read data byte */
722 xor_b(0x08, &PADRH
); /* Set PR inactive */
724 mpeg_audiobuf
[audiobuf_write
++] = data
;
726 if (audiobuf_write
>= audiobuflen
)
734 timing_info
[timing_info_index
++] = TCNT2
+ (i
<< 16);
735 timing_info_index
&= 0x3ff;
742 if(TIME_AFTER(current_tick
, prerecord_timeout
))
744 prerecord_timeout
= current_tick
+ HZ
;
745 queue_post(&mpeg_queue
, MPEG_PRERECORDING_TICK
, 0);
750 /* Signal to save the data if we are running out of buffer
752 if (audiobuflen
- get_unsaved_space() < MPEG_RECORDING_LOW_WATER
753 && saving_status
== NOT_SAVING
)
755 saving_status
= BUFFER_FULL
;
756 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
761 #endif /* CONFIG_CODEC == MAS3587F */
763 void playback_tick(void)
765 struct trackdata
*ptd
= get_trackdata(0);
768 ptd
->id3
.elapsed
+= (current_tick
- last_dma_tick
) * 1000 / HZ
;
769 last_dma_tick
= current_tick
;
770 audio_dispatch_event(AUDIO_EVENT_POS_REPORT
,
771 (unsigned long)ptd
->id3
.elapsed
);
775 static void reset_mp3_buffer(void)
779 audiobuf_swapwrite
= 0;
780 lowest_watermark_level
= audiobuflen
;
783 /* DMA transfer end interrupt callback */
784 static void transfer_end(unsigned char** ppbuf
, size_t* psize
)
786 if(playing
&& !paused
)
788 int unplayed_space_left
;
789 int space_until_end_of_buffer
;
790 int track_offset
= 1;
791 struct trackdata
*track
;
793 audiobuf_read
+= last_dma_chunk_size
;
794 if(audiobuf_read
>= audiobuflen
)
797 /* First, check if we are on a track boundary */
798 if (num_tracks_in_memory() > 1)
800 if (audiobuf_read
== get_trackdata(track_offset
)->mempos
)
802 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK
, 0) )
804 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
810 unplayed_space_left
= get_unplayed_space();
812 space_until_end_of_buffer
= audiobuflen
- audiobuf_read
;
814 if(!filling
&& unplayed_space_left
< low_watermark
)
817 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
820 if(unplayed_space_left
)
822 last_dma_chunk_size
= MIN(0x2000, unplayed_space_left
);
823 last_dma_chunk_size
= MIN(last_dma_chunk_size
,
824 space_until_end_of_buffer
);
826 /* several tracks loaded? */
827 track
= get_trackdata(track_offset
);
830 /* will we move across the track boundary? */
831 if (( audiobuf_read
< track
->mempos
) &&
832 ((audiobuf_read
+last_dma_chunk_size
) >
835 /* Make sure that we end exactly on the boundary */
836 last_dma_chunk_size
= track
->mempos
- audiobuf_read
;
840 *psize
= last_dma_chunk_size
& 0xffff;
841 *ppbuf
= mpeg_audiobuf
+ audiobuf_read
;
842 track
= get_trackdata(0);
844 track
->id3
.offset
+= last_dma_chunk_size
;
846 /* Update the watermark debug level */
847 if(unplayed_space_left
< lowest_watermark_level
)
848 lowest_watermark_level
= unplayed_space_left
;
852 /* Check if the end of data is because of a hard disk error.
853 If there is an open file handle, we are still playing music.
854 If not, the last file has been loaded, and the file handle is
858 /* Update the watermark debug level */
859 if(unplayed_space_left
< lowest_watermark_level
)
860 lowest_watermark_level
= unplayed_space_left
;
862 DEBUGF("DMA underrun.\n");
867 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK
, 0) )
869 DEBUGF("No more MP3 data. Stopping.\n");
870 queue_post(&mpeg_queue
, MPEG_TRACK_CHANGE
, 0);
874 *psize
= 0; /* no more transfer */
879 static struct trackdata
*add_track_to_tag_list(const char *filename
)
881 struct trackdata
*track
;
882 bool send_nid3_event
;
884 if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES
)
886 DEBUGF("Tag memory is full\n");
890 track
= &trackdata
[track_write_idx
];
892 /* grab id3 tag of new file and
893 remember where in memory it starts */
894 if(mp3info(&track
->id3
, filename
))
899 track
->mempos
= audiobuf_write
;
900 track
->id3
.elapsed
= 0;
901 #ifdef HAVE_LCD_BITMAP
902 if (track
->id3
.title
)
903 lcd_getstringsize(track
->id3
.title
, NULL
, NULL
);
904 if (track
->id3
.artist
)
905 lcd_getstringsize(track
->id3
.artist
, NULL
, NULL
);
906 if (track
->id3
.album
)
907 lcd_getstringsize(track
->id3
.album
, NULL
, NULL
);
910 /* if this track is the next track then let the UI know it can get it */
911 send_nid3_event
= (track_write_idx
== track_read_idx
+ 1);
912 track_write_idx
= (track_write_idx
+1) & MAX_TRACK_ENTRIES_MASK
;
914 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
, NULL
);
919 static int new_file(int steps
)
921 int max_steps
= playlist_amount();
924 struct trackdata
*track
;
925 char name_buf
[MAX_PATH
+1];
926 const char *trackname
;
928 /* Find out how many steps to advance. The load_ahead_index field tells
929 us how many playlist entries it had to skip to get to a valid one.
930 We add those together to find out where to start. */
931 if(steps
> 0 && num_tracks_in_memory() > 1)
933 /* Begin with the song after the currently playing one */
935 while((track
= get_trackdata(i
++)))
937 start
+= track
->load_ahead_index
;
942 trackname
= playlist_peek(start
+ steps
, name_buf
, sizeof(name_buf
));
946 DEBUGF("Loading %s\n", trackname
);
948 mpeg_file
= open(trackname
, O_RDONLY
);
950 DEBUGF("Couldn't open file: %s\n",trackname
);
958 struct trackdata
*track
= add_track_to_tag_list(trackname
);
972 /* skip past id3v2 tag */
974 track
->id3
.first_frame_offset
,
976 track
->id3
.index
= steps
;
977 track
->load_ahead_index
= steps
;
978 track
->id3
.offset
= 0;
981 /* Average bitrate * 1.5 */
982 recalculate_watermark(
983 (track
->id3
.bitrate
* 3) / 2);
985 recalculate_watermark(
991 /* Bail out if no file could be opened */
992 if(abs(steps
) > max_steps
)
994 } while ( mpeg_file
< 0 );
999 static void stop_playing(void)
1001 struct trackdata
*track
;
1003 /* Stop the current stream */
1008 track
= get_trackdata(0);
1010 prev_track_elapsed
= track
->id3
.elapsed
;
1016 generate_unbuffer_events();
1020 static void end_current_track(void) {
1021 struct trackdata
*track
;
1023 play_pending
= false;
1025 mp3_play_pause(false);
1027 track
= get_trackdata(0);
1029 prev_track_elapsed
= track
->id3
.elapsed
;
1033 generate_unbuffer_events();
1039 /* Is this a really the end of playback or is a new playlist starting */
1040 static void check_playlist_end(int direction
)
1042 /* Use the largest possible step size to account for skipped tracks */
1043 int steps
= playlist_amount();
1048 if (playlist_next(steps
) < 0)
1052 static void update_playlist(void)
1054 if (num_tracks_in_memory() > 0)
1056 struct trackdata
*track
= get_trackdata(0);
1057 track
->id3
.index
= playlist_next(track
->id3
.index
);
1061 /* End of playlist? */
1062 check_playlist_end(1);
1065 playlist_update_resume_info(audio_current_track());
1068 static void track_change(void)
1070 DEBUGF("Track change\n");
1072 struct trackdata
*track
= get_trackdata(0);
1073 prev_track_elapsed
= track
->id3
.elapsed
;
1075 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1078 #endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
1080 if (num_tracks_in_memory() > 0)
1082 remove_current_tag();
1085 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, audio_current_track());
1088 current_track_counter
++;
1091 unsigned long audio_prev_elapsed(void)
1093 return prev_track_elapsed
;
1097 void hexdump(const unsigned char *buf
, int len
)
1101 for(i
= 0;i
< len
;i
++)
1103 if(i
&& (i
& 15) == 0)
1107 DEBUGF("%02x ", buf
[i
]);
1113 static void start_playback_if_ready(void)
1117 playable_space
= audiobuf_swapwrite
- audiobuf_read
;
1118 if(playable_space
< 0)
1119 playable_space
+= audiobuflen
;
1121 /* See if we have started playing yet. If not, do it. */
1122 if(play_pending
|| dma_underrun
)
1124 /* If the filling has stopped, and we still haven't reached
1125 the watermark, the file must be smaller than the
1126 watermark. We must still play it. */
1127 if((playable_space
>= MPEG_PLAY_PENDING_THRESHOLD
) ||
1128 !filling
|| dma_underrun
)
1131 if (play_pending
) /* don't do this when recovering from DMA underrun */
1133 generate_postbuffer_events(); /* signal first track as buffered */
1134 if (play_pending_track_change
)
1136 play_pending_track_change
= false;
1137 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, audio_current_track());
1139 play_pending
= false;
1143 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1144 mp3_play_data(mpeg_audiobuf
+ audiobuf_read
, last_dma_chunk_size
, transfer_end
);
1145 dma_underrun
= false;
1149 last_dma_tick
= current_tick
;
1150 mp3_play_pause(true);
1153 /* Tell ourselves that we need more data */
1154 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1159 static bool swap_one_chunk(void)
1161 int free_space_left
;
1164 free_space_left
= get_unswapped_space();
1166 if(free_space_left
== 0 && !play_pending
)
1169 /* Swap in larger chunks when the user is waiting for the playback
1170 to start, or when there is dangerously little playable data left */
1172 amount_to_swap
= MIN(MPEG_PLAY_PENDING_SWAPSIZE
, free_space_left
);
1175 if(get_playable_space() < low_watermark
)
1176 amount_to_swap
= MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE
,
1179 amount_to_swap
= MIN(MPEG_SWAP_CHUNKSIZE
, free_space_left
);
1182 if(audiobuf_write
< audiobuf_swapwrite
)
1183 amount_to_swap
= MIN(audiobuflen
- audiobuf_swapwrite
,
1186 amount_to_swap
= MIN(audiobuf_write
- audiobuf_swapwrite
,
1189 bitswap(mpeg_audiobuf
+ audiobuf_swapwrite
, amount_to_swap
);
1191 audiobuf_swapwrite
+= amount_to_swap
;
1192 if(audiobuf_swapwrite
>= audiobuflen
)
1194 audiobuf_swapwrite
= 0;
1200 static void mpeg_thread(void)
1202 static int pause_tick
= 0;
1203 static unsigned int pause_track
= 0;
1204 struct queue_event ev
;
1206 int free_space_left
;
1207 int unplayed_space_left
;
1211 #if CONFIG_CODEC == MAS3587F
1213 int save_endpos
= 0;
1217 #endif /* CONFIG_CODEC == MAS3587F */
1220 play_pending
= false;
1226 #if CONFIG_CODEC == MAS3587F
1227 if(mpeg_mode
== MPEG_DECODER
)
1229 #endif /* CONFIG_CODEC == MAS3587F */
1232 /* Swap if necessary, and don't block on the queue_wait() */
1233 if(swap_one_chunk())
1235 queue_wait_w_tmo(&mpeg_queue
, &ev
, 0);
1239 /* periodically update resume info */
1240 queue_wait_w_tmo(&mpeg_queue
, &ev
, HZ
/2);
1244 DEBUGF("S R:%x W:%x SW:%x\n",
1245 audiobuf_read
, audiobuf_write
, audiobuf_swapwrite
);
1246 queue_wait(&mpeg_queue
, &ev
);
1249 start_playback_if_ready();
1254 DEBUGF("MPEG_PLAY\n");
1257 /* Silence the A/D input, it may be on because the radio
1259 mas_codec_writereg(6, 0x0000);
1260 #endif /* CONFIG_TUNER */
1262 /* Stop the current stream */
1264 end_current_track();
1266 if ( new_file(0) == -1 )
1273 start_offset
= (int)ev
.data
;
1275 /* mid-song resume? */
1277 struct mp3entry
* id3
= &get_trackdata(0)->id3
;
1278 lseek(mpeg_file
, start_offset
, SEEK_SET
);
1279 id3
->offset
= start_offset
;
1283 /* skip past id3v2 tag */
1285 get_trackdata(0)->id3
.first_frame_offset
,
1290 /* Make it read more data */
1292 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1294 /* Tell the file loading code that we want to start playing
1295 as soon as we have some data */
1296 play_pending
= true;
1297 play_pending_track_change
= true;
1300 current_track_counter
++;
1304 DEBUGF("MPEG_STOP\n");
1309 playlist_update_resume_info(audio_current_track());
1312 mpeg_stop_done
= true;
1316 DEBUGF("MPEG_PAUSE\n");
1317 /* Stop the current stream */
1319 playlist_update_resume_info(audio_current_track());
1322 pause_tick
= current_tick
;
1323 pause_track
= current_track_counter
;
1324 mp3_play_pause(false);
1328 DEBUGF("MPEG_RESUME\n");
1329 /* Continue the current stream */
1334 if ( current_track_counter
== pause_track
)
1335 last_dma_tick
+= current_tick
- pause_tick
;
1337 last_dma_tick
= current_tick
;
1339 mp3_play_pause(true);
1344 DEBUGF("MPEG_NEXT\n");
1345 /* is next track in ram? */
1346 if ( num_tracks_in_memory() > 1 ) {
1347 int unplayed_space_left
, unswapped_space_left
;
1349 /* stop the current stream */
1350 play_pending
= false;
1352 mp3_play_pause(false);
1355 audiobuf_read
= get_trackdata(0)->mempos
;
1356 last_dma_chunk_size
= MIN(0x2000, get_unplayed_space_current_song());
1357 mp3_play_data(mpeg_audiobuf
+ audiobuf_read
, last_dma_chunk_size
, transfer_end
);
1358 dma_underrun
= false;
1359 last_dma_tick
= current_tick
;
1361 unplayed_space_left
= get_unplayed_space();
1362 unswapped_space_left
= get_unswapped_space();
1364 /* should we start reading more data? */
1365 if(!filling
&& (unplayed_space_left
< low_watermark
)) {
1367 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
1368 play_pending
= true;
1369 } else if(unswapped_space_left
&&
1370 unswapped_space_left
> unplayed_space_left
) {
1371 /* Stop swapping the data from the previous file */
1372 audiobuf_swapwrite
= audiobuf_read
;
1373 play_pending
= true;
1377 mp3_play_pause(true);
1381 if (!playlist_check(1))
1384 /* stop the current stream */
1385 end_current_track();
1387 if (new_file(1) < 0) {
1388 DEBUGF("No more files to play\n");
1391 check_playlist_end(1);
1392 current_track_counter
++;
1394 /* Make it read more data */
1396 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1398 /* Tell the file loading code that we want
1399 to start playing as soon as we have some data */
1400 play_pending
= true;
1401 play_pending_track_change
= true;
1404 current_track_counter
++;
1410 DEBUGF("MPEG_PREV\n");
1412 if (!playlist_check(-1))
1415 /* stop the current stream */
1416 end_current_track();
1418 /* Open the next file */
1419 if (new_file(-1) < 0) {
1420 DEBUGF("No more files to play\n");
1423 check_playlist_end(-1);
1424 current_track_counter
++;
1426 /* Make it read more data */
1428 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1430 /* Tell the file loading code that we want to
1431 start playing as soon as we have some data */
1432 play_pending
= true;
1433 play_pending_track_change
= true;
1436 current_track_counter
++;
1441 case MPEG_FF_REWIND
: {
1442 struct mp3entry
*id3
= audio_current_track();
1443 unsigned int oldtime
= id3
->elapsed
;
1444 unsigned int newtime
= (unsigned int)ev
.data
;
1445 int curpos
, newpos
, diffpos
;
1446 DEBUGF("MPEG_FF_REWIND\n");
1448 id3
->elapsed
= newtime
;
1450 newpos
= audio_get_file_pos();
1453 id3
->elapsed
= oldtime
;
1458 curpos
= lseek(mpeg_file
, 0, SEEK_CUR
);
1460 curpos
= id3
->filesize
;
1462 if (num_tracks_in_memory() > 1)
1464 /* We have started loading other tracks that need to be
1466 struct trackdata
*track
;
1469 while((track
= get_trackdata(i
++)))
1471 curpos
+= track
->id3
.filesize
;
1475 diffpos
= curpos
- newpos
;
1477 if(!filling
&& diffpos
>= 0 && diffpos
< audiobuflen
)
1479 int unplayed_space_left
, unswapped_space_left
;
1481 /* We are changing to a position that's already in
1482 memory, so we just move the DMA read pointer. */
1483 audiobuf_read
= audiobuf_write
- diffpos
;
1484 if (audiobuf_read
< 0)
1486 audiobuf_read
+= audiobuflen
;
1489 unplayed_space_left
= get_unplayed_space();
1490 unswapped_space_left
= get_unswapped_space();
1492 /* If unswapped_space_left is larger than
1493 unplayed_space_left, it means that the swapwrite pointer
1494 hasn't yet advanced up to the new location of the read
1495 pointer. We just move it, there is no need to swap
1496 data that won't be played anyway. */
1498 if (unswapped_space_left
> unplayed_space_left
)
1500 DEBUGF("Moved swapwrite\n");
1501 audiobuf_swapwrite
= audiobuf_read
;
1502 play_pending
= true;
1505 if (mpeg_file
>=0 && unplayed_space_left
< low_watermark
)
1507 /* We need to load more data before starting */
1509 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, GENERATE_UNBUFFER_EVENTS
);
1510 play_pending
= true;
1514 /* resume will start at new position */
1515 last_dma_chunk_size
=
1516 MIN(0x2000, get_unplayed_space_current_song());
1517 mp3_play_data(mpeg_audiobuf
+ audiobuf_read
,
1518 last_dma_chunk_size
, transfer_end
);
1519 dma_underrun
= false;
1524 /* Move to the new position in the file and start
1528 if (num_tracks_in_memory() > 1)
1530 /* We have to reload the current track */
1532 remove_all_non_current_tags();
1533 generate_unbuffer_events();
1539 mpeg_file
= open(id3
->path
, O_RDONLY
);
1542 id3
->elapsed
= oldtime
;
1547 if(-1 == lseek(mpeg_file
, newpos
, SEEK_SET
))
1549 id3
->elapsed
= oldtime
;
1554 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1556 /* Tell the file loading code that we want to start playing
1557 as soon as we have some data */
1558 play_pending
= true;
1561 id3
->offset
= newpos
;
1566 case MPEG_FLUSH_RELOAD
: {
1567 int numtracks
= num_tracks_in_memory();
1568 bool reload_track
= false;
1572 /* Reset the buffer */
1573 audiobuf_write
= get_trackdata(1)->mempos
;
1575 /* Reset swapwrite unless we're still swapping current
1577 if (get_unplayed_space() <= get_playable_space())
1578 audiobuf_swapwrite
= audiobuf_write
;
1581 remove_all_non_current_tags();
1582 generate_unbuffer_events();
1584 reload_track
= true;
1586 else if (numtracks
== 1 && mpeg_file
< 0)
1588 reload_track
= true;
1591 if(reload_track
&& new_file(1) >= 0)
1593 /* Tell ourselves that we want more data */
1595 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1601 case MPEG_NEED_DATA
:
1602 free_space_left
= audiobuf_read
- audiobuf_write
;
1604 /* We interpret 0 as "empty buffer" */
1605 if(free_space_left
<= 0)
1606 free_space_left
+= audiobuflen
;
1608 unplayed_space_left
= audiobuflen
- free_space_left
;
1610 /* Make sure that we don't fill the entire buffer */
1611 free_space_left
-= MPEG_HIGH_WATER
;
1613 if (ev
.data
== GENERATE_UNBUFFER_EVENTS
)
1614 generate_unbuffer_events();
1616 /* do we have any more buffer space to fill? */
1617 if(free_space_left
<= 0)
1621 generate_postbuffer_events();
1626 /* Read small chunks while we are below the low water mark */
1627 if(unplayed_space_left
< low_watermark
)
1628 amount_to_read
= MIN(MPEG_LOW_WATER_CHUNKSIZE
,
1631 amount_to_read
= free_space_left
;
1633 /* Don't read more than until the end of the buffer */
1634 amount_to_read
= MIN(audiobuflen
- audiobuf_write
,
1636 #if (CONFIG_STORAGE & STORAGE_MMC)
1637 /* MMC is slow, so don't read too large chunks */
1638 amount_to_read
= MIN(0x40000, amount_to_read
);
1639 #elif MEMORYSIZE == 8
1640 amount_to_read
= MIN(0x100000, amount_to_read
);
1643 /* Read as much mpeg data as we can fit in the buffer */
1648 len
= read(mpeg_file
, mpeg_audiobuf
+ audiobuf_write
,
1653 DEBUGF("time: %d\n", t2
- t1
);
1654 DEBUGF("R: %x\n", len
);
1656 /* Now make sure that we don't feed the MAS with ID3V1
1658 if (len
< amount_to_read
)
1661 static const unsigned char tag
[] = "TAG";
1663 int tagptr
= audiobuf_write
+ len
- 128;
1665 /* Really rare case: entire potential tag wasn't
1666 read in this call AND audiobuf_write < 128 */
1668 tagptr
+= audiobuflen
;
1670 for(i
= 0;i
< 3;i
++)
1672 if(tagptr
>= audiobuflen
)
1673 tagptr
-= audiobuflen
;
1675 if(mpeg_audiobuf
[tagptr
] != tag
[i
])
1686 /* Skip id3v1 tag */
1687 DEBUGF("Skipping ID3v1 tag\n");
1690 /* In the very rare case when the entire tag
1691 wasn't read in this read() len will be < 0.
1692 Take care of this when changing the write
1697 audiobuf_write
+= len
;
1699 if (audiobuf_write
< 0)
1700 audiobuf_write
+= audiobuflen
;
1702 if(audiobuf_write
>= audiobuflen
)
1708 /* Tell ourselves that we want more data */
1709 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1715 DEBUGF("MPEG read error\n");
1723 /* No more data to play */
1724 DEBUGF("No more files to play\n");
1729 /* Tell ourselves that we want more data */
1730 queue_post(&mpeg_queue
, MPEG_NEED_DATA
, 0);
1736 case MPEG_TRACK_CHANGE
:
1741 case SYS_USB_CONNECTED
:
1746 /* Tell the USB thread that we are safe */
1747 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1748 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1750 /* Wait until the USB cable is extracted again */
1751 usb_wait_for_disconnect(&mpeg_queue
);
1753 #endif /* !USB_NONE */
1755 #if CONFIG_CODEC == MAS3587F
1756 case MPEG_INIT_RECORDING
:
1758 init_recording_done
= true;
1760 #endif /* CONFIG_CODEC == MAS3587F */
1764 playlist_update_resume_info(audio_current_track());
1767 #if CONFIG_CODEC == MAS3587F
1771 queue_wait(&mpeg_queue
, &ev
);
1775 if (is_prerecording
)
1779 /* Go back prerecord_count seconds in the buffer */
1780 startpos
= prerecord_index
- prerecord_count
;
1782 startpos
+= prerecording_max_seconds
;
1784 /* Read the position data from the prerecord buffer */
1785 frame_count_start
= prerecord_buffer
[startpos
].framecount
;
1786 startpos
= prerecord_buffer
[startpos
].mempos
;
1788 DEBUGF("Start looking at address %x (%x)\n",
1789 mpeg_audiobuf
+startpos
, startpos
);
1791 saved_header
= mpeg_get_last_header();
1793 mem_find_next_frame(startpos
, &offset
, 1800,
1794 saved_header
, mpeg_audiobuf
,
1797 audiobuf_read
= startpos
+ offset
;
1798 if(audiobuf_read
>= audiobuflen
)
1799 audiobuf_read
-= audiobuflen
;
1801 DEBUGF("New audiobuf_read address: %x (%x)\n",
1802 mpeg_audiobuf
+audiobuf_read
, audiobuf_read
);
1804 level
= disable_irq_save();
1805 num_rec_bytes
= get_unsaved_space();
1810 frame_count_start
= 0;
1812 audiobuf_read
= MPEG_RESERVED_HEADER_SPACE
;
1813 audiobuf_write
= MPEG_RESERVED_HEADER_SPACE
;
1817 DEBUGF("Recording...\n");
1820 /* Wait until at least one frame is encoded and get the
1821 frame header, for later use by the Xing header
1824 saved_header
= mpeg_get_last_header();
1826 /* delayed until buffer is saved, don't open yet */
1827 strcpy(delayed_filename
, recording_filename
);
1833 DEBUGF("MPEG_STOP\n");
1837 /* Save the remaining data in the buffer */
1838 save_endpos
= audiobuf_write
;
1839 saving_status
= STOP_RECORDING
;
1840 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1843 case MPEG_STOP_DONE
:
1844 DEBUGF("MPEG_STOP_DONE\n");
1854 for(i
= 0;i
< 512;i
++)
1856 DEBUGF("%d - %d us (%d bytes)\n",
1858 (timing_info
[i
*2+1] & 0xffff) *
1860 timing_info
[i
*2+1] >> 16);
1867 start_prerecording();
1869 mpeg_stop_done
= true;
1873 /* Bail out when a more important save is happening */
1874 if (saving_status
> NEW_FILE
)
1877 /* Make sure we have at least one complete frame
1878 in the buffer. If we haven't recorded a single
1879 frame within 200ms, the MAS is probably not recording
1880 anything, and we bail out. */
1881 amount_to_save
= get_unsaved_space();
1882 if (amount_to_save
< 1800)
1885 amount_to_save
= get_unsaved_space();
1888 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
,
1889 &frame_count_end
, 1);
1891 last_rec_time
= current_tick
- record_start_time
;
1892 record_start_time
= current_tick
;
1894 pause_start_time
= record_start_time
;
1896 /* capture all values at one point */
1897 level
= disable_irq_save();
1898 save_endpos
= audiobuf_write
;
1899 last_rec_bytes
= num_rec_bytes
;
1903 if (amount_to_save
>= 1800)
1905 /* Now find a frame boundary to split at */
1906 save_endpos
-= 1800;
1907 if (save_endpos
< 0)
1908 save_endpos
+= audiobuflen
;
1910 rc
= mem_find_next_frame(save_endpos
, &offset
, 1800,
1911 saved_header
, mpeg_audiobuf
,
1913 if (!rc
) /* No header found, save whole buffer */
1916 save_endpos
+= offset
;
1917 if (save_endpos
>= audiobuflen
)
1918 save_endpos
-= audiobuflen
;
1920 last_rec_bytes
+= offset
- 1800;
1921 level
= disable_irq_save();
1922 num_rec_bytes
+= 1800 - offset
;
1926 saving_status
= NEW_FILE
;
1927 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
1930 case MPEG_SAVE_DATA
:
1931 if (saving_status
== BUFFER_FULL
)
1932 save_endpos
= audiobuf_write
;
1934 if (mpeg_file
< 0) /* delayed file open */
1936 mpeg_file
= open(delayed_filename
, O_WRONLY
|O_CREAT
, 0666);
1939 panicf("recfile: %d", mpeg_file
);
1942 amount_to_save
= save_endpos
- audiobuf_read
;
1943 if (amount_to_save
< 0)
1944 amount_to_save
+= audiobuflen
;
1946 amount_to_save
= MIN(amount_to_save
,
1947 audiobuflen
- audiobuf_read
);
1948 #if (CONFIG_STORAGE & STORAGE_MMC)
1949 /* MMC is slow, so don't save too large chunks at once */
1950 amount_to_save
= MIN(0x40000, amount_to_save
);
1951 #elif MEMORYSIZE == 8
1952 amount_to_save
= MIN(0x100000, amount_to_save
);
1954 rc
= write(mpeg_file
, mpeg_audiobuf
+ audiobuf_read
,
1958 if (errno
== ENOSPC
)
1960 mpeg_errno
= AUDIOERR_DISK_FULL
;
1962 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
1963 /* will close the file */
1967 panicf("rec wrt: %d", rc
);
1970 audiobuf_read
+= amount_to_save
;
1971 if (audiobuf_read
>= audiobuflen
)
1974 if (audiobuf_read
== save_endpos
) /* all saved */
1976 switch (saving_status
)
1979 rc
= fsync(mpeg_file
);
1981 panicf("rec fls: %d", rc
);
1986 /* Close the current file */
1987 rc
= close(mpeg_file
);
1989 panicf("rec cls: %d", rc
);
1994 /* copy new filename */
1995 strcpy(delayed_filename
, recording_filename
);
1997 frame_count_start
= frame_count_end
;
2000 case STOP_RECORDING
:
2001 queue_post(&mpeg_queue
, MPEG_STOP_DONE
, 0);
2002 /* will close the file */
2008 saving_status
= NOT_SAVING
;
2010 else /* tell ourselves to save the next chunk */
2011 queue_post(&mpeg_queue
, MPEG_SAVE_DATA
, 0);
2015 case MPEG_PRERECORDING_TICK
:
2016 if(!is_prerecording
)
2019 /* Store the write pointer every second */
2020 prerecord_buffer
[prerecord_index
].mempos
= audiobuf_write
;
2021 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
,
2022 &prerecord_buffer
[prerecord_index
].framecount
, 1);
2024 /* Wrap if necessary */
2025 if(++prerecord_index
== prerecording_max_seconds
)
2026 prerecord_index
= 0;
2028 /* Update the number of seconds recorded */
2029 if(prerecord_count
< prerecording_max_seconds
)
2033 case MPEG_INIT_PLAYBACK
:
2034 /* Stop the prerecording */
2038 init_playback_done
= true;
2041 case MPEG_PAUSE_RECORDING
:
2045 case MPEG_RESUME_RECORDING
:
2049 case SYS_USB_CONNECTED
:
2050 /* We can safely go to USB mode if no recording
2052 if((!is_recording
|| is_prerecording
) && mpeg_stop_done
)
2054 /* Even if we aren't recording, we still call this
2055 function, to put the MAS in monitoring mode,
2059 /* Tell the USB thread that we are safe */
2060 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
2061 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2063 /* Wait until the USB cable is extracted again */
2064 usb_wait_for_disconnect(&mpeg_queue
);
2069 #endif /* CONFIG_CODEC == MAS3587F */
2072 #endif /* !SIMULATOR */
2074 struct mp3entry
* audio_current_track(void)
2077 struct mp3entry
*id3
= &taginfo
;
2078 #else /* !SIMULATOR */
2079 if(num_tracks_in_memory())
2081 struct mp3entry
*id3
= &get_trackdata(0)->id3
;
2083 if (!checked_for_cuesheet
&& curr_cuesheet
&& id3
->cuesheet
== NULL
)
2085 checked_for_cuesheet
= true; /* only check once per track */
2086 char cuepath
[MAX_PATH
];
2088 if (look_for_cuesheet_file(id3
->path
, cuepath
) &&
2089 parse_cuesheet(cuepath
, curr_cuesheet
))
2091 id3
->cuesheet
= curr_cuesheet
;
2099 #endif /* !SIMULATOR */
2102 struct mp3entry
* audio_next_track(void)
2106 #else /* !SIMULATOR */
2107 if(num_tracks_in_memory() > 1)
2108 return &get_trackdata(1)->id3
;
2111 #endif /* !SIMULATOR */
2114 #if CONFIG_CODEC == MAS3587F
2116 void audio_init_playback(void)
2118 init_playback_done
= false;
2119 queue_post(&mpeg_queue
, MPEG_INIT_PLAYBACK
, 0);
2121 while(!init_playback_done
)
2126 /****************************************************************************
2127 * Recording functions
2128 ***************************************************************************/
2129 void audio_init_recording(void)
2131 init_recording_done
= false;
2132 queue_post(&mpeg_queue
, MPEG_INIT_RECORDING
, 0);
2134 while(!init_recording_done
)
2138 static void init_recording(void)
2150 /* Init the recording variables */
2151 is_recording
= false;
2152 is_prerecording
= false;
2154 mpeg_stop_done
= true;
2158 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2159 rc
= mas_direct_config_write(MAS_CONTROL
, 0x8c00);
2161 panicf("mas_ctrl_w: %d", rc
);
2163 /* Stop the current application */
2165 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2168 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2171 /* Perform black magic as described by the data sheet */
2172 if((mas_version_code
& 0x0fff) == 0x0102)
2174 DEBUGF("Performing MAS black magic for B2 version\n");
2175 mas_writereg(0xa3, 0x98);
2176 mas_writereg(0x94, 0xfffff);
2178 mas_writemem(MAS_BANK_D1
, 0, &val
, 1);
2179 mas_writereg(0xa3, 0x90);
2182 /* Enable A/D Converters */
2183 shadow_codec_reg0
= 0xcccd;
2184 mas_codec_writereg(0x0, shadow_codec_reg0
);
2186 /* Copy left channel to right (mono mode) */
2187 mas_codec_writereg(8, 0x8000);
2189 /* ADC scale 0%, DSP scale 100%
2190 We use the DSP output for monitoring, because it works with all
2191 sources including S/PDIF */
2192 mas_codec_writereg(6, 0x0000);
2193 mas_codec_writereg(7, 0x4000);
2196 shadow_soft_mute
= 0;
2197 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2199 #ifdef HAVE_SPDIF_OUT
2200 val
= 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
2202 val
= 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
2204 mas_writemem(MAS_BANK_D0
, MAS_D0_INTERFACE_CONTROL
, &val
, 1);
2206 /* Set Demand mode, monitoring OFF and validate all settings */
2207 shadow_io_control_main
= 0x125;
2208 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2210 /* Start the encoder application */
2212 mas_writemem(MAS_BANK_D0
, MAS_D0_APP_SELECT
, &val
, 1);
2215 mas_readmem(MAS_BANK_D0
, MAS_D0_APP_RUNNING
, &val
, 1);
2216 } while(!(val
& 0x40));
2218 /* We have started the recording application with monitoring OFF.
2219 This is because we want to record at least one frame to fill the DMA
2220 buffer, because the silly MAS will not negate EOD until at least one
2221 DMA transfer has taken place.
2222 Now let's wait for some data to be encoded. */
2225 /* Now set it to Monitoring mode as default, saves power */
2226 shadow_io_control_main
= 0x525;
2227 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2229 /* Wait until the DSP has accepted the settings */
2232 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2236 mpeg_mode
= MPEG_ENCODER
;
2238 DEBUGF("MAS Recording application started\n");
2240 /* At this point, all settings are the reset MAS defaults, next thing is to
2241 call mpeg_set_recording_options(). */
2244 void audio_record(const char *filename
)
2248 strlcpy(recording_filename
, filename
, MAX_PATH
);
2250 queue_post(&mpeg_queue
, MPEG_RECORD
, 0);
2253 void audio_pause_recording(void)
2255 queue_post(&mpeg_queue
, MPEG_PAUSE_RECORDING
, 0);
2258 void audio_resume_recording(void)
2260 queue_post(&mpeg_queue
, MPEG_RESUME_RECORDING
, 0);
2263 static void prepend_header(void)
2268 /* Make room for header */
2269 audiobuf_read
-= MPEG_RESERVED_HEADER_SPACE
;
2270 if(audiobuf_read
< 0)
2272 /* Clear the bottom half */
2273 memset(mpeg_audiobuf
, 0, audiobuf_read
+ MPEG_RESERVED_HEADER_SPACE
);
2275 /* And the top half */
2276 audiobuf_read
+= audiobuflen
;
2277 memset(mpeg_audiobuf
+ audiobuf_read
, 0, audiobuflen
- audiobuf_read
);
2281 memset(mpeg_audiobuf
+ audiobuf_read
, 0, MPEG_RESERVED_HEADER_SPACE
);
2283 /* Copy the empty ID3 header */
2284 startpos
= audiobuf_read
;
2285 for(i
= 0; i
< sizeof(empty_id3_header
); i
++)
2287 mpeg_audiobuf
[startpos
++] = empty_id3_header
[i
];
2288 if(startpos
== audiobuflen
)
2293 static void update_header(void)
2296 unsigned long frames
;
2298 if (last_rec_bytes
> 0)
2300 /* Create the Xing header */
2301 fd
= open(delayed_filename
, O_RDWR
);
2303 panicf("rec upd: %d (%s)", fd
, recording_filename
);
2305 frames
= frame_count_end
- frame_count_start
;
2306 /* If the number of recorded frames has reached 0x7ffff,
2307 we can no longer trust it */
2308 if (frame_count_end
== 0x7ffff)
2311 /* saved_header is saved right before stopping the MAS */
2312 framelen
= create_xing_header(fd
, 0, last_rec_bytes
, xing_buffer
,
2313 frames
, last_rec_time
* (1000/HZ
),
2314 saved_header
, NULL
, false,
2315 mpeg_audiobuf
, audiobuflen
);
2317 lseek(fd
, MPEG_RESERVED_HEADER_SPACE
- framelen
, SEEK_SET
);
2318 write(fd
, xing_buffer
, framelen
);
2323 static void start_prerecording(void)
2327 DEBUGF("Starting prerecording\n");
2329 prerecord_index
= 0;
2330 prerecord_count
= 0;
2331 prerecord_timeout
= current_tick
+ HZ
;
2332 memset(prerecord_buffer
, 0, sizeof(prerecord_buffer
));
2335 is_prerecording
= true;
2337 /* Stop monitoring and start the encoder */
2338 shadow_io_control_main
&= ~(1 << 10);
2339 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2340 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2342 /* Wait until the DSP has accepted the settings */
2345 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2348 is_recording
= true;
2349 saving_status
= NOT_SAVING
;
2351 demand_irq_enable(true);
2354 static void start_recording(void)
2360 /* This will make the IRQ handler start recording
2361 for real, i.e send MPEG_SAVE_DATA messages when
2362 the buffer is full */
2363 is_prerecording
= false;
2367 /* If prerecording is off, we need to stop the monitoring
2368 and start the encoder */
2369 shadow_io_control_main
&= ~(1 << 10);
2370 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2371 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2373 /* Wait until the DSP has accepted the settings */
2376 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2380 is_recording
= true;
2381 saving_status
= NOT_SAVING
;
2384 /* Store the current time */
2386 record_start_time
= current_tick
- prerecord_count
* HZ
;
2388 record_start_time
= current_tick
;
2390 pause_start_time
= 0;
2392 demand_irq_enable(true);
2395 static void pause_recording(void)
2397 pause_start_time
= current_tick
;
2399 /* Set the pause bit */
2400 shadow_soft_mute
|= 2;
2401 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2406 static void resume_recording(void)
2410 /* Clear the pause bit */
2411 shadow_soft_mute
&= ~2;
2412 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
, 1);
2414 /* Compensate for the time we have been paused */
2415 if(pause_start_time
)
2418 current_tick
- (pause_start_time
- record_start_time
);
2419 pause_start_time
= 0;
2423 static void stop_recording(void)
2427 /* Let it finish the last frame */
2432 demand_irq_enable(false);
2434 is_recording
= false;
2435 is_prerecording
= false;
2437 last_rec_bytes
= num_rec_bytes
;
2438 mas_readmem(MAS_BANK_D0
, MAS_D0_MPEG_FRAME_COUNT
, &frame_count_end
, 1);
2439 last_rec_time
= current_tick
- record_start_time
;
2441 /* Start monitoring */
2442 shadow_io_control_main
|= (1 << 10);
2443 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
, 1);
2444 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2446 /* Wait until the DSP has accepted the settings */
2449 mas_readmem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &val
,1);
2455 void audio_set_recording_options(struct audio_recording_options
*options
)
2459 is_mpeg1
= (options
->rec_frequency
< 3);
2461 rec_version_index
= is_mpeg1
?3:2;
2462 rec_frequency_index
= options
->rec_frequency
% 3;
2464 shadow_encoder_control
= (options
->rec_quality
<< 17) |
2465 (rec_frequency_index
<< 10) |
2466 ((is_mpeg1
?1:0) << 9) |
2467 (((options
->rec_channels
* 2 + 1) & 3) << 6) |
2468 (1 << 5) /* MS-stereo */ |
2469 (1 << 2) /* Is an original */;
2470 mas_writemem(MAS_BANK_D0
, MAS_D0_ENCODER_CONTROL
, &shadow_encoder_control
,1);
2472 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control
);
2474 #if CONFIG_TUNER & S1A0903X01
2475 /* Store the (unpitched) MAS PLL frequency. Used for avoiding FM
2476 interference with the Samsung tuner. */
2477 if (rec_frequency_index
)
2478 mas_store_pllfreq(24576000);
2480 mas_store_pllfreq(22579000);
2483 shadow_soft_mute
= options
->rec_editable
?4:0;
2484 mas_writemem(MAS_BANK_D0
, MAS_D0_SOFT_MUTE
, &shadow_soft_mute
,1);
2486 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute
);
2488 shadow_io_control_main
= ((1 << 10) | /* Monitoring ON */
2489 ((options
->rec_source
< 2)?1:2) << 8) | /* Input select */
2490 (1 << 5) | /* SDO strobe invert */
2491 ((is_mpeg1
?0:1) << 3) |
2492 (1 << 2) | /* Inverted SIBC clock signal */
2494 mas_writemem(MAS_BANK_D0
, MAS_D0_IO_CONTROL_MAIN
, &shadow_io_control_main
,1);
2496 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main
);
2498 if(options
->rec_source
== AUDIO_SRC_MIC
)
2500 /* Copy left channel to right (mono mode) */
2501 mas_codec_writereg(8, 0x8000);
2505 /* Stereo input mode */
2506 mas_codec_writereg(8, 0);
2509 prerecording_max_seconds
= options
->rec_prerecord_time
;
2510 if(prerecording_max_seconds
)
2512 prerecording
= true;
2513 start_prerecording();
2517 prerecording
= false;
2518 is_prerecording
= false;
2519 is_recording
= false;
2523 /* If use_mic is true, the left gain is used */
2524 void audio_set_recording_gain(int left
, int right
, int type
)
2526 /* Enable both left and right A/D */
2527 shadow_codec_reg0
= (left
<< 12) |
2530 (type
==AUDIO_GAIN_MIC
?0x0008:0) | /* Connect left A/D to mic */
2532 mas_codec_writereg(0x0, shadow_codec_reg0
);
2535 /* try to make some kind of beep, also in recording mode */
2536 void audio_beep(int duration
)
2538 long starttick
= current_tick
;
2540 { /* toggle bit 0 of codec register 0, toggling the DAC off & on.
2541 * While this is still audible even without an external signal,
2542 * it doesn't affect the (pre-)recording. */
2543 mas_codec_writereg(0, shadow_codec_reg0
^ 1);
2544 mas_codec_writereg(0, shadow_codec_reg0
);
2547 while (current_tick
- starttick
< duration
);
2550 void audio_new_file(const char *filename
)
2554 strlcpy(recording_filename
, filename
, MAX_PATH
);
2556 queue_post(&mpeg_queue
, MPEG_NEW_FILE
, 0);
2559 unsigned long audio_recorded_time(void)
2562 return prerecord_count
* HZ
;
2567 return pause_start_time
- record_start_time
;
2569 return current_tick
- record_start_time
;
2575 unsigned long audio_num_recorded_bytes(void)
2584 index
= prerecord_index
- prerecord_count
;
2586 index
+= prerecording_max_seconds
;
2588 num_bytes
= audiobuf_write
- prerecord_buffer
[index
].mempos
;
2590 num_bytes
+= audiobuflen
;
2595 return num_rec_bytes
;
2601 #else /* SIMULATOR */
2603 /* dummies coming up */
2605 void audio_init_playback(void)
2609 unsigned long audio_recorded_time(void)
2614 void audio_beep(int duration
)
2619 void audio_pause_recording(void)
2623 void audio_resume_recording(void)
2627 unsigned long audio_num_recorded_bytes(void)
2632 void audio_record(const char *filename
)
2637 void audio_new_file(const char *filename
)
2643 void audio_set_recording_gain(int left
, int right
, int type
)
2650 void audio_init_recording(void)
2654 void audio_set_recording_options(struct audio_recording_options
*options
)
2659 #endif /* SIMULATOR */
2660 #endif /* CONFIG_CODEC == MAS3587F */
2662 static void audio_reset_buffer(void)
2664 size_t bufsize
; /* dont break strict-aliasing */
2665 talk_buffer_steal(); /* will use the mp3 buffer */
2667 /* release buffer on behalf of any audio_get_buffer() caller,
2668 * non-fatal if there was none */
2669 buffer_release_buffer(0);
2671 mpeg_audiobuf
= buffer_get_buffer(&bufsize
);
2672 audiobuflen
= bufsize
;
2675 void audio_play(long offset
)
2677 audio_reset_buffer();
2679 char name_buf
[MAX_PATH
+1];
2680 const char* trackname
;
2686 trackname
= playlist_peek(steps
, name_buf
, sizeof(name_buf
));
2689 if(mp3info(&taginfo
, trackname
)) {
2690 /* bad mp3, move on */
2691 if(++steps
> playlist_amount())
2695 #ifdef HAVE_MPEG_PLAY
2696 real_mpeg_play(trackname
);
2698 playlist_next(steps
);
2699 taginfo
.offset
= offset
;
2700 set_elapsed(&taginfo
);
2705 #else /* !SIMULATOR */
2707 queue_post(&mpeg_queue
, MPEG_PLAY
, offset
);
2708 #endif /* !SIMULATOR */
2713 void audio_stop(void)
2718 struct trackdata
*track
= get_trackdata(0);
2719 prev_track_elapsed
= track
->id3
.elapsed
;
2721 mpeg_stop_done
= false;
2722 queue_post(&mpeg_queue
, MPEG_STOP
, 0);
2723 while(!mpeg_stop_done
)
2725 #else /* SIMULATOR */
2729 #endif /* SIMULATOR */
2730 /* give voice our entire buffer */
2731 talkbuf_init(mpeg_audiobuf
);
2735 void audio_stop_recording(void)
2740 void audio_hard_stop(void)
2743 /* tell voice we obtain the buffer before freeing */
2744 talk_buffer_steal();
2745 buffer_release_buffer(0);
2748 void audio_pause(void)
2751 queue_post(&mpeg_queue
, MPEG_PAUSE
, 0);
2752 #else /* SIMULATOR */
2756 #endif /* SIMULATOR */
2759 void audio_resume(void)
2762 queue_post(&mpeg_queue
, MPEG_RESUME
, 0);
2763 #else /* SIMULATOR */
2767 #endif /* SIMULATOR */
2770 void audio_next(void)
2773 queue_remove_from_head(&mpeg_queue
, MPEG_NEED_DATA
);
2774 queue_post(&mpeg_queue
, MPEG_NEXT
, 0);
2775 #else /* SIMULATOR */
2776 char name_buf
[MAX_PATH
+1];
2781 file
= playlist_peek(steps
, name_buf
, sizeof(name_buf
));
2784 if(mp3info(&taginfo
, file
)) {
2785 if(++steps
> playlist_amount())
2789 playlist_next(steps
);
2790 current_track_counter
++;
2795 #endif /* SIMULATOR */
2798 void audio_prev(void)
2801 queue_remove_from_head(&mpeg_queue
, MPEG_NEED_DATA
);
2802 queue_post(&mpeg_queue
, MPEG_PREV
, 0);
2803 #else /* SIMULATOR */
2804 char name_buf
[MAX_PATH
+1];
2809 file
= playlist_peek(steps
, name_buf
, sizeof(name_buf
));
2812 if(mp3info(&taginfo
, file
)) {
2816 playlist_next(steps
);
2817 current_track_counter
++;
2822 #endif /* SIMULATOR */
2825 void audio_ff_rewind(long newpos
)
2828 queue_post(&mpeg_queue
, MPEG_FF_REWIND
, newpos
);
2829 #else /* SIMULATOR */
2831 #endif /* SIMULATOR */
2834 void audio_flush_and_reload_tracks(void)
2837 queue_post(&mpeg_queue
, MPEG_FLUSH_RELOAD
, 0);
2838 #endif /* !SIMULATOR*/
2841 int audio_status(void)
2846 ret
|= AUDIO_STATUS_PLAY
;
2849 ret
|= AUDIO_STATUS_PAUSE
;
2851 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2852 if(is_recording
&& !is_prerecording
)
2853 ret
|= AUDIO_STATUS_RECORD
;
2856 ret
|= AUDIO_STATUS_PRERECORD
;
2857 #endif /* CONFIG_CODEC == MAS3587F */
2860 ret
|= AUDIO_STATUS_ERROR
;
2866 unsigned int audio_error(void)
2872 void audio_error_clear(void)
2878 static void mpeg_thread(void)
2880 struct mp3entry
* id3
;
2883 id3
= audio_current_track();
2889 if (id3
->elapsed
>=id3
->length
)
2895 #endif /* SIMULATOR */
2897 void audio_init(void)
2900 /* cuesheet support */
2901 if (global_settings
.cuesheet
)
2902 curr_cuesheet
= (struct cuesheet
*)buffer_alloc(sizeof(struct cuesheet
));
2904 size_t bufsize
; /* don't break strict-aliasing */
2905 mpeg_audiobuf
= buffer_get_buffer(&bufsize
);
2906 audiobuflen
= bufsize
;
2907 /* give voice buffer until we start to play */
2908 talkbuf_init(mpeg_audiobuf
);
2910 queue_init(&mpeg_queue
, true);
2911 #endif /* !SIMULATOR */
2912 create_thread(mpeg_thread
, mpeg_stack
,
2913 sizeof(mpeg_stack
), 0, mpeg_thread_name
2914 IF_PRIO(, PRIORITY_SYSTEM
)
2917 memset(trackdata
, 0, sizeof(trackdata
));
2919 #if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2920 if (HW_MASK
& PR_ACTIVE_HIGH
)
2921 and_b(~0x08, &PADRH
);
2924 #endif /* CONFIG_CODEC == MAS3587F */
2930 #endif /* !SIMULATOR */
2934 #endif /* CONFIG_CODEC != SWCODEC */