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:
parent
57b1ccba2b
commit
0e159f13cf
4 changed files with 91 additions and 40 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
100
apps/playback.c
100
apps/playback.c
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue