mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
Fixed forward next track bugs (still some pause issues though). Added
experimental cross-fader. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6632 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b24549616b
commit
b4bc106efb
4 changed files with 111 additions and 32 deletions
|
@ -68,7 +68,7 @@ static volatile bool paused;
|
|||
#define CODEC_WAV "/.rockbox/codecs/codecwav.rock";
|
||||
|
||||
#define AUDIO_WATERMARK 0x70000
|
||||
#define AUDIO_FILE_CHUNK (1024*256)
|
||||
#define AUDIO_FILE_CHUNK (1024*512)
|
||||
|
||||
#define AUDIO_PLAY 1
|
||||
#define AUDIO_STOP 2
|
||||
|
@ -107,6 +107,9 @@ static const char codec_thread_name[] = "codec";
|
|||
/* Is file buffer currently being refilled? */
|
||||
static volatile bool filling;
|
||||
|
||||
/* Interrupts buffer filling. */
|
||||
static volatile bool interrupt;
|
||||
|
||||
/* Ring buffer where tracks and codecs are loaded. */
|
||||
char *codecbuf;
|
||||
|
||||
|
@ -398,8 +401,8 @@ int probe_file_format(const char *filename)
|
|||
|
||||
void yield_codecs(void)
|
||||
{
|
||||
#ifndef SIMULATOR
|
||||
yield();
|
||||
#ifndef SIMULATOR
|
||||
if (!pcm_is_playing())
|
||||
sleep(5);
|
||||
while (pcm_is_lowdata())
|
||||
|
@ -420,7 +423,7 @@ void audio_fill_file_buffer(void)
|
|||
/* Give codecs some processing time. */
|
||||
yield_codecs();
|
||||
|
||||
if (!playing) {
|
||||
if (interrupt) {
|
||||
logf("Filling interrupted");
|
||||
close(current_fd);
|
||||
current_fd = -1;
|
||||
|
@ -540,7 +543,7 @@ bool loadcodec(const char *trackname, bool start_play)
|
|||
i = 0;
|
||||
while (i < size) {
|
||||
yield_codecs();
|
||||
if (!playing) {
|
||||
if (interrupt) {
|
||||
logf("Buffering interrupted");
|
||||
close(fd);
|
||||
return false;
|
||||
|
@ -610,7 +613,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
|||
logf("%s", trackname);
|
||||
logf("Buffering track:%d/%d", track_widx, track_ridx);
|
||||
|
||||
if (!playing) {
|
||||
if (interrupt) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
@ -717,7 +720,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
|
|||
while (i < size) {
|
||||
/* Give codecs some processing time to prevent glitches. */
|
||||
yield_codecs();
|
||||
if (!playing) {
|
||||
if (interrupt) {
|
||||
logf("Buffering interrupted");
|
||||
close(fd);
|
||||
return false;
|
||||
|
@ -803,8 +806,14 @@ void audio_check_buffer(void)
|
|||
int i;
|
||||
int cur_idx;
|
||||
|
||||
/* Fill buffer as full as possible for cross-fader. */
|
||||
#ifndef SIMULATOR
|
||||
if (cur_ti->id3.length - cur_ti->id3.elapsed < 20000)
|
||||
pcm_set_boost_mode(true);
|
||||
#endif
|
||||
|
||||
/* Start buffer filling as necessary. */
|
||||
if (codecbufused > AUDIO_WATERMARK || !playing)
|
||||
if (codecbufused > AUDIO_WATERMARK || !interrupt)
|
||||
return ;
|
||||
|
||||
filling = true;
|
||||
|
@ -863,6 +872,9 @@ void audio_update_trackinfo(void)
|
|||
buf_ridx += cur_ti->codecsize;
|
||||
if (buf_ridx >= codecbuflen)
|
||||
buf_ridx -= codecbuflen;
|
||||
pcm_crossfade_start();
|
||||
if (!filling)
|
||||
pcm_set_boost_mode(false);
|
||||
} else {
|
||||
buf_ridx -= ci.curpos;
|
||||
codecbufused += ci.curpos;
|
||||
|
@ -978,14 +990,13 @@ void audio_thread(void)
|
|||
queue_wait_w_tmo(&audio_queue, &ev, 0);
|
||||
switch (ev.id) {
|
||||
case AUDIO_PLAY:
|
||||
interrupt = false;
|
||||
ci.stop_codec = true;
|
||||
ci.reload_codec = false;
|
||||
ci.seek_time = 0;
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_stop();
|
||||
pcm_play_pause(true);
|
||||
#endif
|
||||
playing = true;
|
||||
paused = false;
|
||||
audio_play_start((int)ev.data);
|
||||
break ;
|
||||
|
@ -993,8 +1004,8 @@ void audio_thread(void)
|
|||
case AUDIO_STOP:
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_stop();
|
||||
pcm_play_pause(true);
|
||||
#endif
|
||||
paused = false;
|
||||
break ;
|
||||
|
||||
case AUDIO_PAUSE:
|
||||
|
@ -1017,6 +1028,7 @@ void audio_thread(void)
|
|||
ci.stop_codec = true;
|
||||
logf("USB Connection");
|
||||
pcm_play_stop();
|
||||
pcm_play_pause(true);
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
usb_wait_for_disconnect(&audio_queue);
|
||||
break ;
|
||||
|
@ -1076,12 +1088,14 @@ void codec_thread(void)
|
|||
logf("Codec finished");
|
||||
}
|
||||
|
||||
queue_post(&audio_queue, AUDIO_CODEC_DONE, (void *)status);
|
||||
if (playing && !ci.stop_codec && !ci.reload_codec) {
|
||||
audio_change_track();
|
||||
} else if (ci.reload_codec) {
|
||||
interrupt = true;
|
||||
} else {
|
||||
playing = false;
|
||||
}
|
||||
queue_post(&audio_queue, AUDIO_CODEC_DONE, (void *)status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1129,17 +1143,17 @@ bool audio_has_changed_track(void)
|
|||
void audio_play(int offset)
|
||||
{
|
||||
logf("audio_play");
|
||||
playing = false;
|
||||
ci.stop_codec = true;
|
||||
playing = false;
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_pause(true);
|
||||
#endif
|
||||
queue_post(&audio_queue, AUDIO_PLAY, (void *)offset);
|
||||
}
|
||||
|
||||
void audio_stop(void)
|
||||
{
|
||||
logf("audio_stop");
|
||||
if (!playing)
|
||||
return ;
|
||||
|
||||
playing = false;
|
||||
ci.stop_codec = true;
|
||||
if (current_fd) {
|
||||
|
@ -1147,6 +1161,9 @@ void audio_stop(void)
|
|||
current_fd = -1;
|
||||
}
|
||||
queue_post(&audio_queue, AUDIO_STOP, 0);
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_pause(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void audio_pause(void)
|
||||
|
@ -1174,16 +1191,17 @@ void audio_next(void)
|
|||
logf("audio_next");
|
||||
new_track = 1;
|
||||
ci.reload_codec = true;
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_stop();
|
||||
#endif
|
||||
|
||||
/* Detect if disk is spinning.. */
|
||||
if (filling) {
|
||||
playlist_next(1);
|
||||
playing = false;
|
||||
interrupt = true;
|
||||
ci.stop_codec = true;
|
||||
playlist_next(1);
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
} else {
|
||||
#ifndef SIMULATOR
|
||||
pcm_play_stop();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1197,9 +1215,9 @@ void audio_prev(void)
|
|||
#endif
|
||||
|
||||
if (filling) {
|
||||
playlist_next(-1);
|
||||
playing = false;
|
||||
interrupt = true;
|
||||
ci.stop_codec = true;
|
||||
playlist_next(-1);
|
||||
queue_post(&audio_queue, AUDIO_PLAY, 0);
|
||||
}
|
||||
//queue_post(&audio_queue, AUDIO_PREV, 0);
|
||||
|
@ -1377,7 +1395,8 @@ void audio_init(void)
|
|||
- MALLOC_BUFSIZE - GUARD_BUFSIZE;
|
||||
//codecbuflen = 2*512*1024;
|
||||
codecbufused = 0;
|
||||
filling = 0;
|
||||
filling = false;
|
||||
interrupt = false;
|
||||
codecbuf = &audiobuf[MALLOC_BUFSIZE];
|
||||
playing = false;
|
||||
paused = false;
|
||||
|
|
|
@ -381,6 +381,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm)
|
|||
/* Flush the buffer if it is full. */
|
||||
if(OutputPtr==OutputBufferEnd)
|
||||
{
|
||||
rb->yield();
|
||||
#ifdef DEBUG_GAPLESS
|
||||
rb->write(fd, OutputBuffer, OUTPUT_BUFFER_SIZE);
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@ void pcm_play_set_watermark(int numbytes, void (*callback)(int bytes_left));
|
|||
|
||||
void pcm_set_boost_mode(bool state);
|
||||
bool pcm_is_lowdata(void);
|
||||
void pcm_crossfade_start(void);
|
||||
unsigned int audiobuffer_get_latency(void);
|
||||
bool audiobuffer_insert(char *buf, size_t length);
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ static volatile size_t audiobuffer_free;
|
|||
static size_t audiobuffer_fillpos;
|
||||
static bool boost_mode;
|
||||
|
||||
static bool crossfade_active;
|
||||
static int crossfade_pos;
|
||||
static int crossfade_amount;
|
||||
static int crossfade_rem;
|
||||
|
||||
static unsigned char *next_start;
|
||||
static long next_size;
|
||||
|
||||
|
@ -106,6 +111,9 @@ void pcm_boost(bool state)
|
|||
{
|
||||
static bool boost_state = false;
|
||||
|
||||
if (crossfade_active)
|
||||
return ;
|
||||
|
||||
if (state != boost_state) {
|
||||
cpu_boost(state);
|
||||
boost_state = state;
|
||||
|
@ -334,6 +342,7 @@ void pcm_watermark_callback(int bytes_left)
|
|||
|
||||
/* Fill audio buffer by boosting cpu */
|
||||
pcm_boost(true);
|
||||
crossfade_active = false;
|
||||
}
|
||||
|
||||
void pcm_set_boost_mode(bool state)
|
||||
|
@ -373,11 +382,43 @@ bool pcm_is_lowdata(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
void pcm_crossfade_start(void)
|
||||
{
|
||||
if (audiobuffer_free > CHUNK_SIZE * 4) {
|
||||
return ;
|
||||
}
|
||||
pcm_boost(true);
|
||||
crossfade_active = true;
|
||||
crossfade_pos = audiobuffer_pos;
|
||||
crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - CHUNK_SIZE * 22)/2;
|
||||
crossfade_rem = crossfade_amount;
|
||||
audiobuffer_fillpos = 0;
|
||||
|
||||
crossfade_pos -= crossfade_amount*2;
|
||||
if (crossfade_pos < 0)
|
||||
crossfade_pos = PCMBUF_SIZE + crossfade_pos;
|
||||
}
|
||||
|
||||
static __inline
|
||||
void crossfade(short *buf, const short *buf2, int length)
|
||||
{
|
||||
while (length--) {
|
||||
*buf = (int)((*buf * ((crossfade_rem)*1000/crossfade_amount))/1000);
|
||||
*buf += (int)((*buf2 * ((crossfade_amount-crossfade_rem)*1000/crossfade_amount))/1000);
|
||||
buf++;
|
||||
buf2++;
|
||||
if (--crossfade_rem <= 0) {
|
||||
crossfade_active = false;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool audiobuffer_insert(char *buf, size_t length)
|
||||
{
|
||||
size_t copy_n = 0;
|
||||
|
||||
if (audiobuffer_free < length + CHUNK_SIZE) {
|
||||
if (audiobuffer_free < length + CHUNK_SIZE && !crossfade_active) {
|
||||
if (!boost_mode)
|
||||
pcm_boost(false);
|
||||
return false;
|
||||
|
@ -385,20 +426,36 @@ bool audiobuffer_insert(char *buf, size_t length)
|
|||
|
||||
if (!pcm_is_playing() && !pcm_paused) {
|
||||
pcm_boost(true);
|
||||
crossfade_active = false;
|
||||
if (audiobuffer_free < PCMBUF_SIZE - CHUNK_SIZE*2)
|
||||
pcm_play_start();
|
||||
}
|
||||
|
||||
while (length > 0) {
|
||||
if (!crossfade_active) {
|
||||
copy_n = MIN(length, PCMBUF_SIZE - audiobuffer_pos -
|
||||
audiobuffer_fillpos);
|
||||
copy_n = MIN(CHUNK_SIZE, copy_n);
|
||||
|
||||
memcpy(&audiobuffer[audiobuffer_pos+audiobuffer_fillpos],
|
||||
buf, copy_n);
|
||||
buf += copy_n;
|
||||
audiobuffer_free -= copy_n;
|
||||
length -= copy_n;
|
||||
|
||||
} else {
|
||||
copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos);
|
||||
|
||||
crossfade((short *)&audiobuffer[crossfade_pos],
|
||||
(const short *)buf, copy_n/2);
|
||||
buf += copy_n;
|
||||
length -= copy_n;
|
||||
crossfade_pos += copy_n;
|
||||
if (crossfade_pos >= PCMBUF_SIZE)
|
||||
crossfade_pos -= PCMBUF_SIZE;
|
||||
continue ;
|
||||
}
|
||||
|
||||
/* Pre-buffer to meet CHUNK_SIZE requirement */
|
||||
if (copy_n + audiobuffer_fillpos < CHUNK_SIZE && length == 0) {
|
||||
audiobuffer_fillpos += copy_n;
|
||||
|
@ -452,6 +509,7 @@ void pcm_play_start(void)
|
|||
int size;
|
||||
char *start;
|
||||
|
||||
crossfade_active = false;
|
||||
if(!pcm_is_playing())
|
||||
{
|
||||
size = MIN(desc->size, 32768);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue