1
0
Fork 0
forked from len0rd/rockbox

Fixed a few iriver playback quirks and issues with previous fixes.

Also fixed "TST.." bug when seeking and possible an enhancement to mp3
gapless playback also.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8402 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-01-20 22:02:44 +00:00
parent 57b1ccba2b
commit 0e159f13cf
4 changed files with 91 additions and 40 deletions

View file

@ -101,6 +101,12 @@ enum codec_status codec_start(struct codec_api *api)
ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
/** This label might need to be moved above all the init code, but I don't
* think reiniting the codec is necessary for MPEG. It might even be unwanted
* for gapless playback.
* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
next_track:
ci->memset(&stream, 0, sizeof(struct mad_stream));
ci->memset(&frame, 0, sizeof(struct mad_frame));
ci->memset(&synth, 0, sizeof(struct mad_synth));
@ -114,10 +120,6 @@ enum codec_status codec_start(struct codec_api *api)
frame.overlap = &mad_frame_overlap;
stream.main_data = &mad_main_data;
/* This label might need to be moved above all the init code, but I don't
think reiniting the codec is necessary for MPEG. It might even be unwanted
for gapless playback */
next_track:
file_end = 0;
while (!*ci->taginfo_ready && !ci->stop_codec)
ci->sleep(1);
@ -156,14 +158,21 @@ next_track:
samplesdone = ((int64_t) (ci->seek_time - 1))
* current_frequency / 1000;
newpos = ci->mp3_get_filepos(ci->seek_time-1) +
ci->id3->first_frame_offset;
if (ci->seek_time-1 == 0)
newpos = 0;
else
newpos = ci->mp3_get_filepos(ci->seek_time-1) +
ci->id3->first_frame_offset;
if (!ci->seek_buffer(newpos))
goto next_track;
if (newpos == 0)
samples_to_skip = start_skip;
ci->seek_complete();
if (newpos == 0)
{
ci->id3->elapsed = 0;
goto next_track;
}
}
/* Lock buffers */

View file

@ -229,7 +229,8 @@ bool pcmbuf_is_lowdata(void)
bool pcmbuf_crossfade_init(void)
{
if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8 || !crossfade_enabled
if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8
|| !pcmbuf_is_crossfade_enabled()
|| crossfade_active || crossfade_init) {
pcmbuf_flush_audio();
return false;

View file

@ -653,7 +653,7 @@ void codec_seek_complete_callback(void)
{
/* assume we're called from non-voice codec, as they shouldn't seek */
ci.seek_time = 0;
pcmbuf_flush_audio();
pcmbuf_play_stop();
}
bool codec_seek_buffer_callback(off_t newpos)
@ -1288,6 +1288,15 @@ static void audio_clear_track_entries(bool buffered_only)
}
}
static void stop_codec_flush(void)
{
ci.stop_codec = true;
pcmbuf_play_stop();
while (audio_codec_loaded)
yield();
pcmbuf_play_stop();
}
static void audio_stop_playback(bool resume)
{
logf("stop_playback:%d", resume);
@ -1296,14 +1305,11 @@ static void audio_stop_playback(bool resume)
playlist_update_resume_info(resume ? audio_current_track() : NULL);
playing = false;
filling = false;
ci.stop_codec = true;
stop_codec_flush();
if (current_fd >= 0) {
close(current_fd);
current_fd = -1;
}
pcmbuf_play_stop();
while (audio_codec_loaded)
yield();
track_count = 0;
/* Mark all entries null. */
@ -1478,16 +1484,26 @@ static void audio_update_trackinfo(void)
ci.curpos = 0;
cur_ti->start_pos = 0;
ci.taginfo_ready = (bool *)&cur_ti->taginfo_ready;
if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()) {
/* Manual track change (always crossfade or flush audio). */
if (new_track)
{
pcmbuf_crossfade_init();
codec_track_changed();
} else {
pcmbuf_add_event(codec_track_changed);
}
/* Manual track change. */
if (new_track)
/* Automatic track change with crossfade. */
else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active())
{
pcmbuf_crossfade_init();
codec_track_changed();
}
/* Gapless playback. */
else
{
pcmbuf_add_event(codec_track_changed);
}
}
enum {
@ -1497,7 +1513,7 @@ enum {
};
/* Should handle all situations. */
static int skip_next_track(void)
static int skip_next_track(bool inside_codec_thread)
{
logf("skip next");
/* Manual track skipping. */
@ -1529,10 +1545,16 @@ static int skip_next_track(void)
ci.reload_codec = true;
/* Stop playback if manual track change. */
if (new_track != 0 && !pcmbuf_is_crossfade_enabled())
pcmbuf_play_stop();
{
if (inside_codec_thread)
pcmbuf_play_stop();
else
stop_codec_flush();
}
else if (pcmbuf_is_crossfade_enabled())
pcmbuf_crossfade_init();
/* Don't flush buffer */
queue_post(&audio_queue, AUDIO_PLAY, (bool *)false);
queue_post(&audio_queue, AUDIO_PLAY, 0);
return SKIP_OK_DISK;
}
@ -1552,7 +1574,7 @@ static int skip_next_track(void)
return SKIP_OK_RAM;
}
static int skip_previous_track(void)
static int skip_previous_track(bool inside_codec_thread)
{
logf("skip previous");
last_peek_offset++;
@ -1566,10 +1588,14 @@ static int skip_previous_track(void)
ci.reload_codec = true;
/* Stop playback. */
/* FIXME: Only stop playback if disk is not spinning! */
if (!pcmbuf_is_crossfade_enabled())
if (pcmbuf_is_crossfade_enabled())
pcmbuf_crossfade_init();
else if (inside_codec_thread)
pcmbuf_play_stop();
else
stop_codec_flush();
queue_post(&audio_queue, AUDIO_PLAY, (bool *)true);
queue_post(&audio_queue, AUDIO_PLAY, 0);
return SKIP_OK_DISK;
}
@ -1583,6 +1609,7 @@ static int skip_previous_track(void)
cur_ti->available = cur_ti->filesize;
if (buf_ridx < 0)
buf_ridx += filebuflen;
audio_update_trackinfo();
return SKIP_OK_RAM;
@ -1595,7 +1622,7 @@ static void audio_change_track(void)
if (!ci.reload_codec)
{
if (skip_next_track() == SKIP_FAIL)
if (skip_next_track(false) == SKIP_FAIL)
{
logf("No more tracks");
while (pcm_is_playing())
@ -1607,8 +1634,8 @@ static void audio_change_track(void)
ci.reload_codec = false;
/* Needed for fast skipping. */
//if (cur_ti->codecsize > 0)
// queue_post(&codec_queue, CODEC_LOAD, 0);
if (cur_ti->codecsize > 0)
queue_post(&codec_queue, CODEC_LOAD, 0);
}
bool codec_request_next_track_callback(void)
@ -1629,13 +1656,13 @@ bool codec_request_next_track_callback(void)
/* Advance to next track. */
if (new_track >= 0 || !ci.reload_codec) {
if (skip_next_track() != SKIP_OK_RAM)
if (skip_next_track(true) != SKIP_OK_RAM)
return false;
}
/* Advance to previous track. */
else {
if (skip_previous_track() != SKIP_OK_RAM)
if (skip_previous_track(true) != SKIP_OK_RAM)
return false;
}
@ -1654,7 +1681,7 @@ bool codec_request_next_track_callback(void)
if (cur_ti->codecsize == 0)
{
logf("Loading from disk [2]...");
queue_post(&audio_queue, AUDIO_PLAY, (bool *)(new_track != 0));
queue_post(&audio_queue, AUDIO_PLAY, 0);
}
else
ci.reload_codec = true;
@ -1692,12 +1719,15 @@ static void initiate_track_change(int peek_index)
{
/* Detect if disk is spinning or already loading. */
if (filling || ci.reload_codec || !audio_codec_loaded) {
queue_post(&audio_queue, AUDIO_PLAY, (bool *)true);
if (pcmbuf_is_crossfade_enabled())
pcmbuf_crossfade_init();
else
pcmbuf_play_stop();
ci.stop_codec = true;
queue_post(&audio_queue, AUDIO_PLAY, 0);
} else {
new_track = peek_index;
ci.reload_codec = true;
if (!pcmbuf_is_crossfade_enabled())
pcmbuf_flush_audio();
}
codec_track_changed();
@ -1771,14 +1801,10 @@ void audio_thread(void)
ci.reload_codec = false;
ci.seek_time = 0;
/* Only flush audio if it has been requested. */
if ((bool)ev.data)
pcmbuf_crossfade_init();
while (audio_codec_loaded)
yield();
audio_play_start((int)ev.data);
playlist_update_resume_info(audio_current_track());
/* If there are no tracks in the playlist, then the playlist
@ -2091,6 +2117,18 @@ bool audio_has_changed_track(void)
void audio_play(int offset)
{
logf("audio_play");
if (pcmbuf_is_crossfade_enabled())
{
ci.stop_codec = true;
sleep(1);
pcmbuf_crossfade_init();
}
else
{
stop_codec_flush();
pcmbuf_play_stop();
}
queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
}

View file

@ -221,6 +221,9 @@ void pcm_play_stop(void)
void pcm_play_pause(bool play)
{
if (!pcm_playing)
return ;
if(pcm_paused && play && next_size)
{
logf("unpause");