forked from len0rd/rockbox
Some re-desing to buffer filling and track loading code and a few bug
fixes. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6766 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
6b3a14a7fd
commit
431e813532
2 changed files with 124 additions and 113 deletions
201
apps/playback.c
201
apps/playback.c
|
|
@ -71,6 +71,7 @@ static volatile bool paused;
|
||||||
#define CODEC_MPC "/.rockbox/codecs/codecmpc.rock";
|
#define CODEC_MPC "/.rockbox/codecs/codecmpc.rock";
|
||||||
#define CODEC_WAVPACK "/.rockbox/codecs/codecwavpack.rock";
|
#define CODEC_WAVPACK "/.rockbox/codecs/codecwavpack.rock";
|
||||||
|
|
||||||
|
#define AUDIO_FILL_CYCLE (1024*256)
|
||||||
#define AUDIO_DEFAULT_WATERMARK (1024*256)
|
#define AUDIO_DEFAULT_WATERMARK (1024*256)
|
||||||
#define AUDIO_DEFAULT_FILECHUNK (1024*32)
|
#define AUDIO_DEFAULT_FILECHUNK (1024*32)
|
||||||
|
|
||||||
|
|
@ -84,6 +85,7 @@ static volatile bool paused;
|
||||||
#define AUDIO_FLUSH_RELOAD 8
|
#define AUDIO_FLUSH_RELOAD 8
|
||||||
#define AUDIO_CODEC_DONE 9
|
#define AUDIO_CODEC_DONE 9
|
||||||
#define AUDIO_FLUSH 10
|
#define AUDIO_FLUSH 10
|
||||||
|
#define AUDIO_TRACK_CHANGED 11
|
||||||
|
|
||||||
#define CODEC_LOAD 1
|
#define CODEC_LOAD 1
|
||||||
#define CODEC_LOAD_DISK 2
|
#define CODEC_LOAD_DISK 2
|
||||||
|
|
@ -125,6 +127,8 @@ static volatile int codecbufused;
|
||||||
static volatile int buf_ridx;
|
static volatile int buf_ridx;
|
||||||
static volatile int buf_widx;
|
static volatile int buf_widx;
|
||||||
|
|
||||||
|
static int last_peek_offset;
|
||||||
|
|
||||||
/* Track information (count in file buffer, read/write indexes for
|
/* Track information (count in file buffer, read/write indexes for
|
||||||
track ring structure. */
|
track ring structure. */
|
||||||
static int track_count;
|
static int track_count;
|
||||||
|
|
@ -424,6 +428,7 @@ void codec_configure_callback(int setting, void *value)
|
||||||
void codec_track_changed(void)
|
void codec_track_changed(void)
|
||||||
{
|
{
|
||||||
track_changed = true;
|
track_changed = true;
|
||||||
|
// queue_post(&audio_queue, AUDIO_TRACK_CHANGED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield_codecs(void)
|
void yield_codecs(void)
|
||||||
|
|
@ -438,25 +443,22 @@ void yield_codecs(void)
|
||||||
|
|
||||||
void audio_fill_file_buffer(void)
|
void audio_fill_file_buffer(void)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i, size;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
tracks[track_widx].start_pos = ci.curpos;
|
if (current_fd < 0)
|
||||||
logf("Filling buffer...");
|
return ;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((off_t)i < tracks[track_widx].filerem) {
|
size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE);
|
||||||
|
while (i < size) {
|
||||||
/* Give codecs some processing time. */
|
/* Give codecs some processing time. */
|
||||||
yield_codecs();
|
yield_codecs();
|
||||||
|
|
||||||
if (!queue_empty(&audio_queue)) {
|
if (fill_bytesleft == 0)
|
||||||
logf("Filling interrupted");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fill_bytesleft < MIN((unsigned int)conf_filechunk,
|
|
||||||
tracks[track_widx].filerem - i))
|
|
||||||
break ;
|
break ;
|
||||||
rc = MIN(conf_filechunk, codecbuflen - buf_widx);
|
rc = MIN(conf_filechunk, codecbuflen - buf_widx);
|
||||||
|
rc = MIN(rc, (off_t)fill_bytesleft);
|
||||||
rc = read(current_fd, &codecbuf[buf_widx], rc);
|
rc = read(current_fd, &codecbuf[buf_widx], rc);
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
tracks[track_widx].filerem = 0;
|
tracks[track_widx].filerem = 0;
|
||||||
|
|
@ -474,7 +476,8 @@ void audio_fill_file_buffer(void)
|
||||||
codecbufused += i;
|
codecbufused += i;
|
||||||
tracks[track_widx].filerem -= i;
|
tracks[track_widx].filerem -= i;
|
||||||
tracks[track_widx].filepos += i;
|
tracks[track_widx].filepos += i;
|
||||||
logf("Done:%d", tracks[track_widx].available);
|
/*logf("Filled:%d/%d", tracks[track_widx].available,
|
||||||
|
tracks[track_widx].filerem);*/
|
||||||
if (tracks[track_widx].filerem == 0) {
|
if (tracks[track_widx].filerem == 0) {
|
||||||
close(current_fd);
|
close(current_fd);
|
||||||
current_fd = -1;
|
current_fd = -1;
|
||||||
|
|
@ -569,6 +572,7 @@ bool loadcodec(const char *trackname, bool start_play)
|
||||||
size = filesize(fd);
|
size = filesize(fd);
|
||||||
if ((off_t)fill_bytesleft < size + conf_watermark) {
|
if ((off_t)fill_bytesleft < size + conf_watermark) {
|
||||||
logf("Not enough space");
|
logf("Not enough space");
|
||||||
|
fill_bytesleft = 0;
|
||||||
close(fd);
|
close(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -576,11 +580,6 @@ bool loadcodec(const char *trackname, bool start_play)
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < size) {
|
while (i < size) {
|
||||||
yield_codecs();
|
yield_codecs();
|
||||||
if (!queue_empty(&audio_queue)) {
|
|
||||||
logf("Buffering interrupted");
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_n = MIN(conf_filechunk, codecbuflen - buf_widx);
|
copy_n = MIN(conf_filechunk, codecbuflen - buf_widx);
|
||||||
rc = read(fd, &codecbuf[buf_widx], copy_n);
|
rc = read(fd, &codecbuf[buf_widx], copy_n);
|
||||||
|
|
@ -609,7 +608,8 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
int rc, i;
|
int rc, i;
|
||||||
int copy_n;
|
int copy_n;
|
||||||
|
|
||||||
if (track_count >= MAX_TRACK)
|
if (track_count >= MAX_TRACK || tracks[track_widx].filesize != 0
|
||||||
|
|| current_fd >= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
trackname = playlist_peek(peek_offset);
|
trackname = playlist_peek(peek_offset);
|
||||||
|
|
@ -653,13 +653,6 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
//logf("%s", trackname);
|
//logf("%s", trackname);
|
||||||
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
||||||
|
|
||||||
if (!queue_empty(&audio_queue)) {
|
|
||||||
logf("Interrupted!");
|
|
||||||
//ci.stop_codec = true;
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get_metadata(&tracks[track_widx],fd,trackname,v1first)) {
|
if (!get_metadata(&tracks[track_widx],fd,trackname,v1first)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -685,22 +678,11 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
i = tracks[track_widx].start_pos;
|
i = tracks[track_widx].start_pos;
|
||||||
|
size = MIN(size, AUDIO_FILL_CYCLE);
|
||||||
while (i < size) {
|
while (i < size) {
|
||||||
/* Give codecs some processing time to prevent glitches. */
|
/* Give codecs some processing time to prevent glitches. */
|
||||||
yield_codecs();
|
yield_codecs();
|
||||||
|
|
||||||
/* Limit buffering size at first run. */
|
|
||||||
if (conf_bufferlimit && (int)fill_bytesleft >= conf_bufferlimit) {
|
|
||||||
fill_bytesleft = conf_bufferlimit;
|
|
||||||
conf_bufferlimit = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!queue_empty(&audio_queue)) {
|
|
||||||
logf("Buffering interrupted");
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fill_bytesleft == 0)
|
if (fill_bytesleft == 0)
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
|
|
@ -737,7 +719,6 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
if (tracks[track_widx].filerem != 0) {
|
if (tracks[track_widx].filerem != 0) {
|
||||||
current_fd = fd;
|
current_fd = fd;
|
||||||
logf("Partially buf:%d", tracks[track_widx].available);
|
logf("Partially buf:%d", tracks[track_widx].available);
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
logf("Completely buf.");
|
logf("Completely buf.");
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
@ -750,20 +731,13 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_insert_tracks(int offset, bool start_playing, int peek_offset)
|
|
||||||
{
|
|
||||||
fill_bytesleft = codecbuflen - codecbufused;
|
|
||||||
filling = true;
|
|
||||||
while (audio_load_track(offset, start_playing, peek_offset)) {
|
|
||||||
start_playing = false;
|
|
||||||
offset = 0;
|
|
||||||
peek_offset++;
|
|
||||||
}
|
|
||||||
filling = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_play_start(int offset)
|
void audio_play_start(int offset)
|
||||||
{
|
{
|
||||||
|
if (current_fd >= 0) {
|
||||||
|
close(current_fd);
|
||||||
|
current_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK);
|
memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK);
|
||||||
sound_set(SOUND_VOLUME, global_settings.volume);
|
sound_set(SOUND_VOLUME, global_settings.volume);
|
||||||
track_count = 0;
|
track_count = 0;
|
||||||
|
|
@ -773,9 +747,17 @@ void audio_play_start(int offset)
|
||||||
buf_widx = 0;
|
buf_widx = 0;
|
||||||
codecbufused = 0;
|
codecbufused = 0;
|
||||||
pcm_set_boost_mode(true);
|
pcm_set_boost_mode(true);
|
||||||
audio_insert_tracks(offset, true, 0);
|
|
||||||
pcm_set_boost_mode(false);
|
fill_bytesleft = codecbuflen;
|
||||||
|
filling = true;
|
||||||
|
last_peek_offset = 0;
|
||||||
|
if (audio_load_track(offset, true, 0)) {
|
||||||
|
last_peek_offset++;
|
||||||
ata_sleep();
|
ata_sleep();
|
||||||
|
} else {
|
||||||
|
logf("Failure");
|
||||||
|
}
|
||||||
|
pcm_set_boost_mode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_clear_track_entries(void)
|
void audio_clear_track_entries(void)
|
||||||
|
|
@ -791,25 +773,14 @@ void audio_clear_track_entries(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_check_buffer(void)
|
void initialize_buffer_fill(void)
|
||||||
{
|
{
|
||||||
int i;
|
int cur_idx, i;
|
||||||
int cur_idx;
|
|
||||||
|
|
||||||
/* Fill buffer as full as possible for cross-fader. */
|
|
||||||
if (pcm_is_crossfade_enabled() && cur_ti->id3.length > 0
|
|
||||||
&& cur_ti->id3.length - cur_ti->id3.elapsed < 20000 && playing)
|
|
||||||
pcm_set_boost_mode(true);
|
|
||||||
|
|
||||||
/* Start buffer filling as necessary. */
|
|
||||||
if (codecbufused > conf_watermark || !queue_empty(&audio_queue)
|
|
||||||
|| !playing || ci.stop_codec || ci.reload_codec)
|
|
||||||
return ;
|
|
||||||
|
|
||||||
filling = true;
|
|
||||||
pcm_set_boost_mode(true);
|
pcm_set_boost_mode(true);
|
||||||
|
|
||||||
fill_bytesleft = codecbuflen - codecbufused;
|
fill_bytesleft = codecbuflen - codecbufused;
|
||||||
|
tracks[track_widx].start_pos = ci.curpos;
|
||||||
|
|
||||||
/* Calculate real track count after throwing away old tracks. */
|
/* Calculate real track count after throwing away old tracks. */
|
||||||
cur_idx = track_ridx;
|
cur_idx = track_ridx;
|
||||||
|
|
@ -827,6 +798,30 @@ void audio_check_buffer(void)
|
||||||
|
|
||||||
/* Mark all other entries null. */
|
/* Mark all other entries null. */
|
||||||
audio_clear_track_entries();
|
audio_clear_track_entries();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_check_buffer(void)
|
||||||
|
{
|
||||||
|
/* Fill buffer as full as possible for cross-fader. */
|
||||||
|
if (pcm_is_crossfade_enabled() && cur_ti->id3.length > 0
|
||||||
|
&& cur_ti->id3.length - cur_ti->id3.elapsed < 20000 && playing)
|
||||||
|
pcm_set_boost_mode(true);
|
||||||
|
|
||||||
|
/* Start buffer filling as necessary. */
|
||||||
|
if ((codecbufused > conf_watermark || !queue_empty(&audio_queue)
|
||||||
|
|| !playing || ci.stop_codec || ci.reload_codec) && !filling)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
if (!filling) {
|
||||||
|
initialize_buffer_fill();
|
||||||
|
filling = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Limit buffering size at first run. */
|
||||||
|
if (conf_bufferlimit && (int)fill_bytesleft >= conf_bufferlimit) {
|
||||||
|
fill_bytesleft = conf_bufferlimit;
|
||||||
|
conf_bufferlimit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to load remainings of the file. */
|
/* Try to load remainings of the file. */
|
||||||
if (tracks[track_widx].filerem > 0)
|
if (tracks[track_widx].filerem > 0)
|
||||||
|
|
@ -836,18 +831,17 @@ void audio_check_buffer(void)
|
||||||
if (tracks[track_widx].filerem == 0 && tracks[track_widx].filesize != 0) {
|
if (tracks[track_widx].filerem == 0 && tracks[track_widx].filesize != 0) {
|
||||||
if (++track_widx == MAX_TRACK)
|
if (++track_widx == MAX_TRACK)
|
||||||
track_widx = 0;
|
track_widx = 0;
|
||||||
logf("new ti: %d", track_widx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logf("ti: %d", track_widx);
|
|
||||||
/* Load new files to fill the entire buffer. */
|
/* Load new files to fill the entire buffer. */
|
||||||
if (tracks[track_widx].filerem == 0)
|
if (audio_load_track(0, false, last_peek_offset)) {
|
||||||
audio_insert_tracks(0, false, 1);
|
last_peek_offset++;
|
||||||
|
} else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) {
|
||||||
|
filling = false;
|
||||||
pcm_set_boost_mode(false);
|
pcm_set_boost_mode(false);
|
||||||
if (playing)
|
if (playing)
|
||||||
ata_sleep();
|
ata_sleep();
|
||||||
filling = false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_update_trackinfo(void)
|
void audio_update_trackinfo(void)
|
||||||
|
|
@ -890,6 +884,7 @@ void audio_update_trackinfo(void)
|
||||||
|
|
||||||
void audio_change_track(void)
|
void audio_change_track(void)
|
||||||
{
|
{
|
||||||
|
logf("change track");
|
||||||
if (track_ridx == track_widx) {
|
if (track_ridx == track_widx) {
|
||||||
logf("No more tracks");
|
logf("No more tracks");
|
||||||
while (pcm_is_playing())
|
while (pcm_is_playing())
|
||||||
|
|
@ -914,6 +909,9 @@ bool codec_request_next_track_callback(void)
|
||||||
|
|
||||||
/* Advance to next track. */
|
/* Advance to next track. */
|
||||||
if (ci.reload_codec && new_track > 0) {
|
if (ci.reload_codec && new_track > 0) {
|
||||||
|
last_peek_offset--;
|
||||||
|
if (!playlist_check(1))
|
||||||
|
return false;
|
||||||
playlist_next(1);
|
playlist_next(1);
|
||||||
if (++track_ridx == MAX_TRACK)
|
if (++track_ridx == MAX_TRACK)
|
||||||
track_ridx = 0;
|
track_ridx = 0;
|
||||||
|
|
@ -927,6 +925,9 @@ bool codec_request_next_track_callback(void)
|
||||||
|
|
||||||
/* Advance to previous track. */
|
/* Advance to previous track. */
|
||||||
else if (ci.reload_codec && new_track < 0) {
|
else if (ci.reload_codec && new_track < 0) {
|
||||||
|
last_peek_offset++;
|
||||||
|
if (!playlist_check(-1))
|
||||||
|
return false;
|
||||||
playlist_next(-1);
|
playlist_next(-1);
|
||||||
if (--track_ridx < 0)
|
if (--track_ridx < 0)
|
||||||
track_ridx = MAX_TRACK-1;
|
track_ridx = MAX_TRACK-1;
|
||||||
|
|
@ -942,6 +943,9 @@ bool codec_request_next_track_callback(void)
|
||||||
|
|
||||||
/* Codec requested track change (next track). */
|
/* Codec requested track change (next track). */
|
||||||
else {
|
else {
|
||||||
|
last_peek_offset--;
|
||||||
|
if (!playlist_check(1))
|
||||||
|
return false;
|
||||||
playlist_next(1);
|
playlist_next(1);
|
||||||
if (++track_ridx >= MAX_TRACK)
|
if (++track_ridx >= MAX_TRACK)
|
||||||
track_ridx = 0;
|
track_ridx = 0;
|
||||||
|
|
@ -992,19 +996,28 @@ void audio_thread(void)
|
||||||
struct event ev;
|
struct event ev;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
yield_codecs();
|
||||||
audio_check_buffer();
|
audio_check_buffer();
|
||||||
queue_wait_w_tmo(&audio_queue, &ev, 100);
|
queue_wait_w_tmo(&audio_queue, &ev, 0);
|
||||||
switch (ev.id) {
|
switch (ev.id) {
|
||||||
case AUDIO_PLAY:
|
case AUDIO_PLAY:
|
||||||
|
logf("starting...");
|
||||||
ci.stop_codec = true;
|
ci.stop_codec = true;
|
||||||
ci.reload_codec = false;
|
ci.reload_codec = false;
|
||||||
ci.seek_time = 0;
|
ci.seek_time = 0;
|
||||||
pcm_play_stop();
|
//pcm_play_stop();
|
||||||
audio_play_start((int)ev.data);
|
audio_play_start((int)ev.data);
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
case AUDIO_STOP:
|
case AUDIO_STOP:
|
||||||
paused = false;
|
paused = false;
|
||||||
|
filling = false;
|
||||||
|
playing = false;
|
||||||
|
ci.stop_codec = true;
|
||||||
|
if (current_fd >= 0) {
|
||||||
|
close(current_fd);
|
||||||
|
current_fd = -1;
|
||||||
|
}
|
||||||
pcm_play_stop();
|
pcm_play_stop();
|
||||||
pcm_play_pause(true);
|
pcm_play_pause(true);
|
||||||
break ;
|
break ;
|
||||||
|
|
@ -1022,6 +1035,9 @@ void audio_thread(void)
|
||||||
audio_invalidate_tracks();
|
audio_invalidate_tracks();
|
||||||
break ;
|
break ;
|
||||||
|
|
||||||
|
case AUDIO_TRACK_CHANGED:
|
||||||
|
break ;
|
||||||
|
|
||||||
case AUDIO_CODEC_DONE:
|
case AUDIO_CODEC_DONE:
|
||||||
//if (playing)
|
//if (playing)
|
||||||
// audio_change_track();
|
// audio_change_track();
|
||||||
|
|
@ -1156,15 +1172,7 @@ void audio_play(int offset)
|
||||||
void audio_stop(void)
|
void audio_stop(void)
|
||||||
{
|
{
|
||||||
logf("audio_stop");
|
logf("audio_stop");
|
||||||
playing = false;
|
|
||||||
paused = false;
|
|
||||||
ci.stop_codec = true;
|
|
||||||
if (current_fd >= 0) {
|
|
||||||
close(current_fd);
|
|
||||||
current_fd = -1;
|
|
||||||
}
|
|
||||||
queue_post(&audio_queue, AUDIO_STOP, 0);
|
queue_post(&audio_queue, AUDIO_STOP, 0);
|
||||||
pcm_play_pause(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_pause(void)
|
void audio_pause(void)
|
||||||
|
|
@ -1183,37 +1191,36 @@ void audio_resume(void)
|
||||||
//queue_post(&audio_queue, AUDIO_RESUME, 0);
|
//queue_post(&audio_queue, AUDIO_RESUME, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_next(void)
|
static void initiate_track_change(int peek_index)
|
||||||
{
|
{
|
||||||
logf("audio_next");
|
if (!playlist_check(peek_index))
|
||||||
new_track = 1;
|
return ;
|
||||||
|
|
||||||
|
new_track = peek_index;
|
||||||
ci.reload_codec = true;
|
ci.reload_codec = true;
|
||||||
|
|
||||||
/* Detect if disk is spinning.. */
|
/* Detect if disk is spinning.. */
|
||||||
if (filling) {
|
if (filling) {
|
||||||
ci.stop_codec = true;
|
ci.stop_codec = true;
|
||||||
playlist_next(1);
|
playlist_next(peek_index);
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!pcm_crossfade_start()) {
|
else if (!pcm_crossfade_start()) {
|
||||||
pcm_play_stop();
|
//pcm_play_stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio_next(void)
|
||||||
|
{
|
||||||
|
logf("audio_next");
|
||||||
|
initiate_track_change(1);
|
||||||
|
}
|
||||||
|
|
||||||
void audio_prev(void)
|
void audio_prev(void)
|
||||||
{
|
{
|
||||||
logf("audio_prev");
|
logf("audio_prev");
|
||||||
new_track = -1;
|
initiate_track_change(-1);
|
||||||
ci.reload_codec = true;
|
|
||||||
pcm_play_stop();
|
|
||||||
|
|
||||||
if (filling) {
|
|
||||||
ci.stop_codec = true;
|
|
||||||
playlist_next(-1);
|
|
||||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
|
||||||
}
|
|
||||||
//queue_post(&audio_queue, AUDIO_PREV, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_ff_rewind(int newpos)
|
void audio_ff_rewind(int newpos)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "uda1380.h"
|
#include "uda1380.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "logf.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -225,6 +226,7 @@ void pcm_play_stop(void)
|
||||||
if (pcm_playing) {
|
if (pcm_playing) {
|
||||||
uda1380_enable_output(false);
|
uda1380_enable_output(false);
|
||||||
pcm_boost(false);
|
pcm_boost(false);
|
||||||
|
sleep(HZ/16);
|
||||||
dma_stop();
|
dma_stop();
|
||||||
}
|
}
|
||||||
pcmbuf_unplayed_bytes = 0;
|
pcmbuf_unplayed_bytes = 0;
|
||||||
|
|
@ -384,36 +386,38 @@ bool pcm_is_lowdata(void)
|
||||||
|
|
||||||
bool pcm_crossfade_start(void)
|
bool pcm_crossfade_start(void)
|
||||||
{
|
{
|
||||||
//logf("cf:%d", audiobuffer_free / CHUNK_SIZE);
|
if (PCMBUF_SIZE - audiobuffer_free < CHUNK_SIZE * 4 || !crossfade_enabled) {
|
||||||
if (audiobuffer_free > CHUNK_SIZE * 4 || !crossfade_enabled) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
logf("crossfading!");
|
||||||
pcm_boost(true);
|
pcm_boost(true);
|
||||||
crossfade_active = true;
|
crossfade_active = true;
|
||||||
crossfade_pos = audiobuffer_pos;
|
crossfade_pos = audiobuffer_pos;
|
||||||
crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - CHUNK_SIZE * 22)/2;
|
crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - (CHUNK_SIZE * 4))/2;
|
||||||
crossfade_rem = crossfade_amount;
|
crossfade_rem = crossfade_amount;
|
||||||
audiobuffer_fillpos = 0;
|
audiobuffer_fillpos = 0;
|
||||||
|
|
||||||
crossfade_pos -= crossfade_amount*2;
|
crossfade_pos -= crossfade_amount*2;
|
||||||
if (crossfade_pos < 0)
|
if (crossfade_pos < 0)
|
||||||
crossfade_pos = PCMBUF_SIZE + crossfade_pos;
|
crossfade_pos += PCMBUF_SIZE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline
|
static __inline
|
||||||
void crossfade(short *buf, const short *buf2, int length)
|
void crossfade(short *buf, const short *buf2, int length)
|
||||||
{
|
{
|
||||||
while (length--) {
|
int i, size;
|
||||||
*buf = (int)((*buf * ((crossfade_rem)*1000/crossfade_amount))/1000);
|
|
||||||
*buf += (int)((*buf2 * ((crossfade_amount-crossfade_rem)*1000/crossfade_amount))/1000);
|
logf("cfi: %d/%d", length, crossfade_rem);
|
||||||
buf++;
|
size = MIN(length, crossfade_rem);
|
||||||
buf2++;
|
for (i = 0; i < length; i++) {
|
||||||
if (--crossfade_rem <= 0) {
|
/* This is not yet realtime, needs optimizations for crossfade to work. */
|
||||||
|
buf[i] = ((buf[i] * ((crossfade_rem)*1000/crossfade_amount))/1000)
|
||||||
|
+ ((buf2[i] * ((crossfade_amount-crossfade_rem)*1000/crossfade_amount))/1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--crossfade_rem <= 0)
|
||||||
crossfade_active = false;
|
crossfade_active = false;
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool audiobuffer_insert(char *buf, size_t length)
|
bool audiobuffer_insert(char *buf, size_t length)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue