Calculate watermark from bitrate and harddisk spinup time.

Use a smaller PCM buffer on targets with 2MB or less ram.
(FS#9703)


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19743 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Björn Stenberg 2009-01-10 21:10:56 +00:00
parent 12b8f8de89
commit 6427d127aa
27 changed files with 85 additions and 121 deletions

View file

@ -56,11 +56,7 @@
#include "albumart.h" #include "albumart.h"
#endif #endif
#if MEM > 1
#define GUARD_BUFSIZE (32*1024) #define GUARD_BUFSIZE (32*1024)
#else
#define GUARD_BUFSIZE (8*1024)
#endif
/* Define LOGF_ENABLE to enable logf output in this file */ /* Define LOGF_ENABLE to enable logf output in this file */
/*#define LOGF_ENABLE*/ /*#define LOGF_ENABLE*/
@ -88,11 +84,9 @@
#endif #endif
/* default point to start buffer refill */ /* default point to start buffer refill */
#define BUFFERING_DEFAULT_WATERMARK (1024*512) #define BUFFERING_DEFAULT_WATERMARK (1024*128)
/* amount of data to read in one read() call */ /* amount of data to read in one read() call */
#define BUFFERING_DEFAULT_FILECHUNK (1024*32) #define BUFFERING_DEFAULT_FILECHUNK (1024*32)
/* point at which the file buffer will fight for CPU time */
#define BUFFERING_CRITICAL_LEVEL (1024*128)
#define BUF_HANDLE_MASK 0x7FFFFFFF #define BUF_HANDLE_MASK 0x7FFFFFFF
@ -173,7 +167,6 @@ enum {
Q_BASE_HANDLE, /* Set the reference handle for buf_useful_data */ Q_BASE_HANDLE, /* Set the reference handle for buf_useful_data */
/* Configuration: */ /* Configuration: */
Q_SET_WATERMARK,
Q_START_FILL, /* Request that the buffering thread initiate a buffer Q_START_FILL, /* Request that the buffering thread initiate a buffer
fill at its earliest convenience */ fill at its earliest convenience */
Q_HANDLE_ADDED, /* Inform the buffering thread that a handle was added, Q_HANDLE_ADDED, /* Inform the buffering thread that a handle was added,
@ -555,7 +548,7 @@ static void update_data_counters(void)
static inline bool buffer_is_low(void) static inline bool buffer_is_low(void)
{ {
update_data_counters(); update_data_counters();
return data_counters.useful < BUFFERING_CRITICAL_LEVEL; return data_counters.useful < (conf_watermark / 2);
} }
/* Buffer data for the given handle. /* Buffer data for the given handle.
@ -1313,8 +1306,7 @@ size_t buf_used(void)
void buf_set_watermark(size_t bytes) void buf_set_watermark(size_t bytes)
{ {
LOGFQUEUE("buffering > Q_SET_WATERMARK %ld", (long)bytes); conf_watermark = bytes;
queue_post(&buffering_queue, Q_SET_WATERMARK, bytes);
} }
static void shrink_buffer_inner(struct memory_handle *h) static void shrink_buffer_inner(struct memory_handle *h)
@ -1386,17 +1378,6 @@ void buffering_thread(void)
base_handle_id = (int)ev.data; base_handle_id = (int)ev.data;
break; break;
case Q_SET_WATERMARK:
LOGFQUEUE("buffering < Q_SET_WATERMARK");
conf_watermark = (size_t)ev.data;
if (conf_watermark < BUFFERING_DEFAULT_FILECHUNK)
{
logf("wmark<chunk %ld<%d",
(long)conf_watermark, BUFFERING_DEFAULT_FILECHUNK);
conf_watermark = BUFFERING_DEFAULT_FILECHUNK;
}
break;
#ifndef SIMULATOR #ifndef SIMULATOR
case SYS_USB_CONNECTED: case SYS_USB_CONNECTED:
LOGFQUEUE("buffering < SYS_USB_CONNECTED"); LOGFQUEUE("buffering < SYS_USB_CONNECTED");

View file

@ -55,8 +55,6 @@ enum codec_status codec_main(void)
unsigned char c = 0; unsigned char c = 0;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, 29); ci->configure(DSP_SET_SAMPLE_DEPTH, 29);

View file

@ -66,7 +66,6 @@ enum codec_status codec_main(void)
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(DSP_SET_SAMPLE_DEPTH, 28); ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track: next_track:
if (codec_init()) { if (codec_init()) {

View file

@ -44,8 +44,6 @@ enum codec_status codec_main(void)
int retval; int retval;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);

View file

@ -147,8 +147,6 @@ enum codec_status codec_main(void)
size_t resume_offset; size_t resume_offset;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
next_track: next_track:

View file

@ -38,9 +38,6 @@ enum codec_status codec_main(void)
char* module; char* module;
int bytesPerSample =2; int bytesPerSample =2;
/* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track: next_track:
if (codec_init()) { if (codec_init()) {
DEBUGF("codec init failed\n"); DEBUGF("codec init failed\n");

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
libdemac - A Monkey's Audio decoder libdemac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -2,7 +2,7 @@
demac - A Monkey's Audio decoder demac - A Monkey's Audio decoder
$Id:$ $Id$
Copyright (C) Dave Chapman 2007 Copyright (C) Dave Chapman 2007

View file

@ -423,8 +423,6 @@ enum codec_status codec_main(void)
int retval; int retval;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1);
next_track: next_track:

View file

@ -1229,9 +1229,6 @@ enum codec_status codec_main(void)
int bytesdone; int bytesdone;
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track: next_track:
if (codec_init()) { if (codec_init()) {
return CODEC_ERROR; return CODEC_ERROR;

View file

@ -47,8 +47,6 @@ enum codec_status codec_main(void)
size_t bytesleft; size_t bytesleft;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1);

View file

@ -1215,9 +1215,6 @@ enum codec_status codec_main(void)
int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */
int nSamplesToRender = 0; int nSamplesToRender = 0;
/* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track: next_track:
if (codec_init()) { if (codec_init()) {
return CODEC_ERROR; return CODEC_ERROR;

View file

@ -559,8 +559,6 @@ enum codec_status codec_main(void)
/* Read the entire file */ /* Read the entire file */
DEBUGF("SPC: request initial buffer\n"); DEBUGF("SPC: request initial buffer\n");
ci->configure(CODEC_SET_FILEBUF_WATERMARK, ci->filesize);
ci->seek_buffer(0); ci->seek_buffer(0);
size_t buffersize; size_t buffersize;
uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize);

View file

@ -228,7 +228,6 @@ enum codec_status codec_main(void)
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(DSP_SET_SAMPLE_DEPTH, 28); ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
next_track: next_track:
if (codec_init()) { if (codec_init()) {

View file

@ -44,8 +44,6 @@ enum codec_status codec_main(void)
int retval; int retval;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_SAMPLE_DEPTH, 28); ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
next_track: next_track:

View file

@ -468,8 +468,6 @@ enum codec_status codec_main(void)
int errcount = 0; int errcount = 0;
/* Generic codec initialisation */ /* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(DSP_SET_SAMPLE_DEPTH, 29); ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
next_track: next_track:

View file

@ -329,14 +329,14 @@ static bool dbg_buffering_thread(void)
bufused = bufsize - pcmbuf_free(); bufused = bufsize - pcmbuf_free();
snprintf(buf, sizeof(buf), "pcm: %7ld/%7ld", (long) bufused, (long) bufsize); snprintf(buf, sizeof(buf), "pcm: %6ld/%ld", (long) bufused, (long) bufsize);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
gui_scrollbar_draw(&screens[SCREEN_MAIN],0, line*8, LCD_WIDTH, 6, gui_scrollbar_draw(&screens[SCREEN_MAIN],0, line*8, LCD_WIDTH, 6,
bufsize, 0, bufused, HORIZONTAL); bufsize, 0, bufused, HORIZONTAL);
line++; line++;
snprintf(buf, sizeof(buf), "alloc: %8ld/%8ld", audio_filebufused(), snprintf(buf, sizeof(buf), "alloc: %6ld/%ld", audio_filebufused(),
(long) filebuflen); (long) filebuflen);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
@ -345,7 +345,7 @@ static bool dbg_buffering_thread(void)
filebuflen, 0, audio_filebufused(), HORIZONTAL); filebuflen, 0, audio_filebufused(), HORIZONTAL);
line++; line++;
snprintf(buf, sizeof(buf), "real: %8ld/%8ld", (long)d.buffered_data, snprintf(buf, sizeof(buf), "real: %6ld/%ld", (long)d.buffered_data,
(long)filebuflen); (long)filebuflen);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
@ -354,7 +354,7 @@ static bool dbg_buffering_thread(void)
line++; line++;
#endif #endif
snprintf(buf, sizeof(buf), "usefl: %8ld/%8ld", (long)(d.useful_data), snprintf(buf, sizeof(buf), "usefl: %6ld/%ld", (long)(d.useful_data),
(long)filebuflen); (long)filebuflen);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
@ -383,7 +383,7 @@ static bool dbg_buffering_thread(void)
{ {
int boostquota = boost_ticks * 1000 / ticks; /* in 0.1 % */ int boostquota = boost_ticks * 1000 / ticks; /* in 0.1 % */
int avgclock = freq_sum * 10 / ticks; /* in 100 kHz */ int avgclock = freq_sum * 10 / ticks; /* in 100 kHz */
snprintf(buf, sizeof(buf), "boost ratio: %3d.%d%% (%2d.%dMHz)", snprintf(buf, sizeof(buf), "boost:%3d.%d%% (%d.%dMHz)",
boostquota/10, boostquota%10, avgclock/10, avgclock%10); boostquota/10, boostquota%10, avgclock/10, avgclock%10);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
} }

View file

@ -42,8 +42,7 @@ enum
enum enum
{ {
CODEC_SET_FILEBUF_WATERMARK = 1, DSP_MYDSP = 1,
DSP_MYDSP,
DSP_SET_FREQUENCY, DSP_SET_FREQUENCY,
DSP_SWITCH_FREQUENCY, DSP_SWITCH_FREQUENCY,
DSP_SET_SAMPLE_DEPTH, DSP_SET_SAMPLE_DEPTH,

View file

@ -48,8 +48,12 @@ static inline int32_t clip_sample_16(int32_t sample)
return sample; return sample;
} }
#if MEMORYSIZE > 2
/* Keep watermark high for iPods at least (2s) */ /* Keep watermark high for iPods at least (2s) */
#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 2) #define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 2)
#else
#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 1) /* 0.25 seconds */
#endif
/* Structure we can use to queue pcm chunks in memory to be played /* Structure we can use to queue pcm chunks in memory to be played
* by the driver code. */ * by the driver code. */
@ -125,7 +129,7 @@ extern unsigned int codec_thread_id;
(pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs)
static bool prepare_insert(size_t length); static bool prepare_insert(size_t length);
static void pcmbuf_under_watermark(void); static void pcmbuf_under_watermark(bool under);
static bool pcmbuf_flush_fillpos(void); static bool pcmbuf_flush_fillpos(void);
#define CALL_IF_EXISTS(function, args...) if (function) function(args) #define CALL_IF_EXISTS(function, args...) if (function) function(args)
@ -194,7 +198,7 @@ static void pcmbuf_set_watermark_bytes(void)
pcmbuf_watermark = (crossfade_enabled && pcmbuf_size) ? pcmbuf_watermark = (crossfade_enabled && pcmbuf_size) ?
/* If crossfading, try to keep the buffer full other than 1 second */ /* If crossfading, try to keep the buffer full other than 1 second */
(pcmbuf_size - (NATIVE_FREQUENCY * 4 * 1)) : (pcmbuf_size - (NATIVE_FREQUENCY * 4 * 1)) :
/* Otherwise, just keep it above 2 second */ /* Otherwise, just use the default */
PCMBUF_WATERMARK; PCMBUF_WATERMARK;
} }
@ -271,7 +275,7 @@ static void boost_codec_thread(bool boost)
} }
#endif /* HAVE_PRIORITY_SCHEDULING */ #endif /* HAVE_PRIORITY_SCHEDULING */
static void pcmbuf_under_watermark(void) static void pcmbuf_under_watermark(bool under)
{ {
/* Only codec thread initiates boost - voice boosts the cpu when playing /* Only codec thread initiates boost - voice boosts the cpu when playing
a clip */ a clip */
@ -279,6 +283,8 @@ static void pcmbuf_under_watermark(void)
if (thread_get_current() == codec_thread_id) if (thread_get_current() == codec_thread_id)
#endif /* SIMULATOR */ #endif /* SIMULATOR */
{ {
if (under)
{
#ifdef HAVE_PRIORITY_SCHEDULING #ifdef HAVE_PRIORITY_SCHEDULING
/* If buffer is critically low, override UI priority, else /* If buffer is critically low, override UI priority, else
set back to the original priority. */ set back to the original priority. */
@ -287,6 +293,12 @@ static void pcmbuf_under_watermark(void)
/* Fill audio buffer by boosting cpu */ /* Fill audio buffer by boosting cpu */
trigger_cpu_boost(); trigger_cpu_boost();
} }
else
{
boost_codec_thread(false);
cancel_cpu_boost();
}
}
/* Disable crossfade if < .5s of audio */ /* Disable crossfade if < .5s of audio */
if (LOW_DATA(2)) if (LOW_DATA(2))
@ -318,8 +330,13 @@ bool pcmbuf_is_lowdata(void)
crossfade_init || crossfade_active) crossfade_init || crossfade_active)
return false; return false;
#if MEMORYSIZE > 2
/* 1 seconds of buffer is low data */ /* 1 seconds of buffer is low data */
return LOW_DATA(4); return LOW_DATA(4);
#else
/* under watermark is low data */
return (pcmbuf_unplayed_bytes < pcmbuf_watermark);
#endif
} }
/* Amount of bytes left in the buffer. */ /* Amount of bytes left in the buffer. */
@ -421,20 +438,18 @@ static void pcmbuf_init_pcmbuffers(void)
static size_t pcmbuf_get_next_required_pcmbuf_size(void) static size_t pcmbuf_get_next_required_pcmbuf_size(void)
{ {
#if MEM > 1
size_t seconds = 1; size_t seconds = 1;
if (crossfade_enabled_pending) if (crossfade_enabled_pending)
seconds += global_settings.crossfade_fade_out_delay seconds += global_settings.crossfade_fade_out_delay
+ global_settings.crossfade_fade_out_duration; + global_settings.crossfade_fade_out_duration;
#if MEMORYSIZE > 2
/* Buffer has to be at least 2s long. */ /* Buffer has to be at least 2s long. */
seconds += 2; seconds += 2;
logf("pcmbuf len: %ld", seconds);
return seconds * (NATIVE_FREQUENCY*4);
#else
return NATIVE_FREQUENCY*2;
#endif #endif
logf("pcmbuf len: %ld", seconds);
return seconds * (NATIVE_FREQUENCY*4); /* 2 channels + 2 bytes/sample */
} }
static char *pcmbuf_calc_audiobuffer_ptr(size_t bufsize) static char *pcmbuf_calc_audiobuffer_ptr(size_t bufsize)
@ -817,8 +832,7 @@ static bool prepare_insert(size_t length)
if (low_latency_mode) if (low_latency_mode)
{ {
/* 1/4s latency. */ /* 1/4s latency. */
if (pcmbuf_unplayed_bytes > NATIVE_FREQUENCY * 4 / 2 if (!LOW_DATA(1) && pcm_is_playing())
&& pcm_is_playing())
return false; return false;
} }
@ -830,11 +844,11 @@ static bool prepare_insert(size_t length)
{ {
trigger_cpu_boost(); trigger_cpu_boost();
/* Pre-buffer 1s. */ /* Pre-buffer up to watermark */
#if MEM <= 1 #if MEMORYSIZE > 2
if (!LOW_DATA(1))
#else
if (!LOW_DATA(4)) if (!LOW_DATA(4))
#else
if (pcmbuf_unplayed_bytes > pcmbuf_watermark)
#endif #endif
{ {
logf("pcm starting"); logf("pcm starting");
@ -842,8 +856,8 @@ static bool prepare_insert(size_t length)
pcmbuf_play_start(); pcmbuf_play_start();
} }
} }
else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark) else
pcmbuf_under_watermark(); pcmbuf_under_watermark(pcmbuf_unplayed_bytes <= pcmbuf_watermark);
return true; return true;
} }
@ -1119,11 +1133,8 @@ void pcmbuf_write_voice_complete(int count)
void pcmbuf_crossfade_enable(bool on_off) void pcmbuf_crossfade_enable(bool on_off)
{ {
#if MEM > 1
/* Next setting to be used, not applied now */ /* Next setting to be used, not applied now */
crossfade_enabled_pending = on_off; crossfade_enabled_pending = on_off;
#endif
(void)on_off;
} }
void pcmbuf_crossfade_enable_finished(void) void pcmbuf_crossfade_enable_finished(void)

View file

@ -21,18 +21,12 @@
#ifndef PCMBUF_H #ifndef PCMBUF_H
#define PCMBUF_H #define PCMBUF_H
#if MEM > 1
#define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks #define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks
on the pcm buffer */ on the pcm buffer */
#define PCMBUF_MINAVG_CHUNK 24576 /* This is the minimum average size of #define PCMBUF_MINAVG_CHUNK 24576 /* This is the minimum average size of
chunks on the pcm buffer (or we run out chunks on the pcm buffer (or we run out
of buffer descriptors, which is of buffer descriptors, which is
non-fatal) */ non-fatal) */
#else
#define PCMBUF_TARGET_CHUNK 16384
#define PCMBUF_MINAVG_CHUNK 12288
#endif
#define PCMBUF_MIN_CHUNK 4096 /* We try to never feed a chunk smaller than #define PCMBUF_MIN_CHUNK 4096 /* We try to never feed a chunk smaller than
this to the DMA */ this to the DMA */
#define PCMBUF_MIX_CHUNK 8192 /* This is the maximum size of one packet #define PCMBUF_MIX_CHUNK 8192 /* This is the maximum size of one packet

View file

@ -88,8 +88,6 @@
#define PLAYBACK_VOICE #define PLAYBACK_VOICE
/* default point to start buffer refill */
#define AUDIO_DEFAULT_WATERMARK (1024*512)
/* amount of guess-space to allow for codecs that must hunt and peck /* amount of guess-space to allow for codecs that must hunt and peck
* for their correct seeek target, 32k seems a good size */ * for their correct seeek target, 32k seems a good size */
#define AUDIO_REBUFFER_GUESS_SIZE (1024*32) #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
@ -162,20 +160,12 @@ enum filling_state {
STATE_FINISHED, /* all remaining tracks are fully buffered */ STATE_FINISHED, /* all remaining tracks are fully buffered */
}; };
#if MEM > 1
#define MAX_TRACK 128 #define MAX_TRACK 128
#else
#define MAX_TRACK 32
#endif
#define MAX_TRACK_MASK (MAX_TRACK-1) #define MAX_TRACK_MASK (MAX_TRACK-1)
/* As defined in plugins/lib/xxx2wav.h */ /* As defined in plugins/lib/xxx2wav.h */
#if MEM > 1
#define GUARD_BUFSIZE (32*1024) #define GUARD_BUFSIZE (32*1024)
#else
#define GUARD_BUFSIZE (8*1024)
#endif
/* As defined in plugin.lds */ /* As defined in plugin.lds */
#if defined(CPU_PP) #if defined(CPU_PP)
@ -277,11 +267,13 @@ static bool track_load_started = false;
*/ */
static bool codec_requested_stop = false; static bool codec_requested_stop = false;
#ifdef HAVE_DISK_STORAGE
static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
#endif
/* Multiple threads */ /* Multiple threads */
/* Set the watermark to trigger buffer fill (A/C) FIXME */ /* Set the watermark to trigger buffer fill (A/C) */
static void set_filebuf_watermark(int seconds, size_t max); static void set_filebuf_watermark(void);
/* Audio thread */ /* Audio thread */
static struct event_queue audio_queue SHAREDBSS_ATTR; static struct event_queue audio_queue SHAREDBSS_ATTR;
@ -797,7 +789,7 @@ void audio_set_buffer_margin(int setting)
static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600}; static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
buffer_margin = lookup[setting]; buffer_margin = lookup[setting];
logf("buffer margin: %ld", (long)buffer_margin); logf("buffer margin: %ld", (long)buffer_margin);
set_filebuf_watermark(buffer_margin, 0); set_filebuf_watermark();
} }
#endif #endif
@ -843,16 +835,35 @@ void audio_set_crossfade(int enable)
/* --- Routines called from multiple threads --- */ /* --- Routines called from multiple threads --- */
static void set_filebuf_watermark(int seconds, size_t max) static void set_filebuf_watermark(void)
{ {
size_t bytes;
if (!filebuf) if (!filebuf)
return; /* Audio buffers not yet set up */ return; /* Audio buffers not yet set up */
bytes = seconds?MAX(curtrack_id3.bitrate * seconds * (1000/8), max):max; #ifdef HAVE_FLASH_STORAGE
bytes = MIN(bytes, filebuflen / 2); int seconds = 1;
#else
int seconds;
int spinup = ata_spinup_time();
if (spinup)
seconds = (spinup / HZ) + 1;
else
seconds = 3;
#endif
/* bitrate of last track in buffer dictates watermark */
struct mp3entry* id3 = NULL;
if (tracks[track_widx].taginfo_ready)
id3 = bufgetid3(tracks[track_widx].id3_hid);
else
id3 = bufgetid3(tracks[track_widx-1].id3_hid);
if (!id3) {
logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
return;
}
size_t bytes = id3->bitrate * (1000/8) * seconds;
buf_set_watermark(bytes); buf_set_watermark(bytes);
logf("fwmark: %d", bytes);
} }
const char *get_codec_filename(int cod_spec) const char *get_codec_filename(int cod_spec)
@ -1106,10 +1117,6 @@ static bool codec_seek_buffer_callback(size_t newpos)
static void codec_configure_callback(int setting, intptr_t value) static void codec_configure_callback(int setting, intptr_t value)
{ {
switch (setting) { switch (setting) {
case CODEC_SET_FILEBUF_WATERMARK:
set_filebuf_watermark(buffer_margin, value);
break;
default: default:
if (!dsp_configure(ci.dsp, setting, value)) if (!dsp_configure(ci.dsp, setting, value))
{ logf("Illegal key:%d", setting); } { logf("Illegal key:%d", setting); }
@ -1709,7 +1716,7 @@ static bool audio_load_track(size_t offset, bool start_play)
/* Set default values */ /* Set default values */
if (start_play) if (start_play)
{ {
buf_set_watermark(AUDIO_DEFAULT_WATERMARK); buf_set_watermark(filebuflen/2);
dsp_configure(ci.dsp, DSP_RESET, 0); dsp_configure(ci.dsp, DSP_RESET, 0);
track_changed = true; track_changed = true;
playlist_update_resume_info(audio_current_track()); playlist_update_resume_info(audio_current_track());
@ -2223,10 +2230,6 @@ static void audio_play_start(size_t offset)
/* Officially playing */ /* Officially playing */
queue_reply(&audio_queue, 1); queue_reply(&audio_queue, 1);
#ifdef HAVE_DISK_STORAGE
set_filebuf_watermark(buffer_margin, 0);
#endif
audio_fill_file_buffer(true, offset); audio_fill_file_buffer(true, offset);
add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback); add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
@ -2358,11 +2361,13 @@ static void audio_reset_buffer(void)
/* Subtract whatever the pcm buffer says it used plus the guard buffer */ /* Subtract whatever the pcm buffer says it used plus the guard buffer */
const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE; const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE;
#ifdef DEBUG #ifdef DEBUG
if(pcmbuf_size > filebuflen) if(pcmbuf_size > filebuflen)
panicf("Not enough memory for pcmbuf_init() : %d > %d", panicf("Not enough memory for pcmbuf_init() : %d > %d",
(int)pcmbuf_size, (int)filebuflen); (int)pcmbuf_size, (int)filebuflen);
#endif #endif
filebuflen -= pcmbuf_size; filebuflen -= pcmbuf_size;
/* Make sure filebuflen is a longword multiple after adjustment - filebuf /* Make sure filebuflen is a longword multiple after adjustment - filebuf
@ -2414,6 +2419,7 @@ static void audio_thread(void)
case Q_AUDIO_FILL_BUFFER: case Q_AUDIO_FILL_BUFFER:
LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data); LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
audio_fill_file_buffer((bool)ev.data, 0); audio_fill_file_buffer((bool)ev.data, 0);
set_filebuf_watermark();
break; break;
case Q_AUDIO_FINISH_LOAD: case Q_AUDIO_FINISH_LOAD: