Index: apps/pcmbuf.c =================================================================== --- apps/pcmbuf.c (revision 19610) +++ apps/pcmbuf.c (working copy) @@ -27,7 +27,6 @@ #include #include "pcmbuf.h" #include "pcm.h" -#include "logf.h" #ifndef SIMULATOR #include "cpu.h" #endif @@ -40,6 +39,15 @@ #include "dsp.h" #include "thread.h" +#if 0 +#define LOGF_ENABLE +#include "logf.h" +#define LOGME(_string_) logf(_string_ " unplayed:%d abufpos:%d afillpos:%d", pcmbuf_unplayed_bytes, audiobuffer_pos, audiobuffer_fillpos) +#else +#include "logf.h" +#define LOGME(_foo_) +#endif + /* Clip sample to signed 16 bit range */ static inline int32_t clip_sample_16(int32_t sample) { @@ -48,8 +56,7 @@ return sample; } -/* Keep watermark high for iPods at least (2s) */ -#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 4 * 2) +#define PCMBUF_WATERMARK (NATIVE_FREQUENCY * 1) /* 0.25 seconds */ /* Structure we can use to queue pcm chunks in memory to be played * by the driver code. */ @@ -138,6 +145,7 @@ static void pcmbuf_callback(unsigned char** start, size_t* size) ICODE_ATTR; static void pcmbuf_callback(unsigned char** start, size_t* size) { + //logf(">>pcmbuf_callback: %d unplayed bytes", pcmbuf_unplayed_bytes); { struct pcmbufdesc *pcmbuf_current = pcmbuf_read; /* Take the finished buffer out of circulation */ @@ -182,6 +190,7 @@ CALL_IF_EXISTS(pcmbuf_event_handler); } } + //logf("<>pcmbuf_add_chunk:"); + pcmbuf_write = pcmbuf_current->link; /* Fill in the values in the new buffer chunk */ pcmbuf_current->addr = &audiobuffer[audiobuffer_pos]; @@ -243,6 +255,8 @@ audiobuffer_pos -= pcmbuf_size; audiobuffer_fillpos = 0; + + LOGME("<>pcmbuf_under_watermark:"); /* Only codec thread initiates boost - voice boosts the cpu when playing a clip */ #ifndef SIMULATOR @@ -318,8 +333,7 @@ crossfade_init || crossfade_active) return false; - /* 1 seconds of buffer is low data */ - return LOW_DATA(4); + return (pcmbuf_unplayed_bytes < pcmbuf_watermark); } /* Amount of bytes left in the buffer. */ @@ -421,20 +435,14 @@ static size_t pcmbuf_get_next_required_pcmbuf_size(void) { -#if MEM > 1 size_t seconds = 1; if (crossfade_enabled_pending) seconds += global_settings.crossfade_fade_out_delay + global_settings.crossfade_fade_out_duration; - /* Buffer has to be at least 2s long. */ - seconds += 2; - logf("pcmbuf len: %ld", seconds); - return seconds * (NATIVE_FREQUENCY*4); -#else - return NATIVE_FREQUENCY*2; -#endif + logf("pcmbuf len: %d", seconds); + return seconds * (NATIVE_FREQUENCY*4); /* 2 channels + 2 bytes/sample */ } static char *pcmbuf_calc_audiobuffer_ptr(size_t bufsize) @@ -513,6 +521,8 @@ */ static bool pcmbuf_flush_fillpos(void) { + LOGME(">>pcmbuf_flush_fillpos:"); + if (audiobuffer_fillpos) { /* Never use the last buffer descriptor */ while (pcmbuf_write == pcmbuf_write_end) { @@ -817,8 +827,7 @@ if (low_latency_mode) { /* 1/4s latency. */ - if (pcmbuf_unplayed_bytes > NATIVE_FREQUENCY * 4 / 2 - && pcm_is_playing()) + if (!LOW_DATA(1) && pcm_is_playing()) return false; } @@ -830,26 +839,27 @@ { trigger_cpu_boost(); - /* Pre-buffer 1s. */ -#if MEM <= 1 - if (!LOW_DATA(1)) -#else - if (!LOW_DATA(4)) -#endif + /* Pre-buffer up to watermark */ + if (pcmbuf_unplayed_bytes > pcmbuf_watermark) { logf("pcm starting"); if (!(audio_status() & AUDIO_STATUS_PAUSE)) pcmbuf_play_start(); } } - else if (pcmbuf_unplayed_bytes <= pcmbuf_watermark) - pcmbuf_under_watermark(); + else { + if (pcmbuf_unplayed_bytes <= pcmbuf_watermark) + pcmbuf_under_watermark(); + } + return true; } void* pcmbuf_request_buffer(int *count) { + //logf("pcmbuf_request_buffer: %d unplayed bytes", pcmbuf_unplayed_bytes); + if (crossfade_init) crossfade_start(); @@ -1119,11 +1129,8 @@ void pcmbuf_crossfade_enable(bool on_off) { -#if MEM > 1 /* Next setting to be used, not applied now */ crossfade_enabled_pending = on_off; -#endif - (void)on_off; } void pcmbuf_crossfade_enable_finished(void) Index: apps/pcmbuf.h =================================================================== --- apps/pcmbuf.h (revision 19610) +++ apps/pcmbuf.h (working copy) @@ -21,18 +21,12 @@ #ifndef PCMBUF_H #define PCMBUF_H -#if MEM > 1 #define PCMBUF_TARGET_CHUNK 32768 /* This is the target fill size of chunks on the pcm buffer */ #define PCMBUF_MINAVG_CHUNK 24576 /* This is the minimum average size of chunks on the pcm buffer (or we run out of buffer descriptors, which is 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 this to the DMA */ #define PCMBUF_MIX_CHUNK 8192 /* This is the maximum size of one packet Index: apps/dsp.h =================================================================== --- apps/dsp.h (revision 19610) +++ apps/dsp.h (working copy) @@ -42,8 +42,7 @@ enum { - CODEC_SET_FILEBUF_WATERMARK = 1, - DSP_MYDSP, + DSP_MYDSP = 1, DSP_SET_FREQUENCY, DSP_SWITCH_FREQUENCY, DSP_SET_SAMPLE_DEPTH, Index: apps/playback.c =================================================================== --- apps/playback.c (revision 19610) +++ apps/playback.c (working copy) @@ -88,14 +88,12 @@ #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 * for their correct seeek target, 32k seems a good size */ #define AUDIO_REBUFFER_GUESS_SIZE (1024*32) /* Define LOGF_ENABLE to enable logf output in this file */ -/*#define LOGF_ENABLE*/ +/* #define LOGF_ENABLE */ #include "logf.h" /* macros to enable logf for queues @@ -160,20 +158,12 @@ STATE_FINISHED, /* all remaining tracks are fully buffered */ }; -#if MEM > 1 #define MAX_TRACK 128 -#else -#define MAX_TRACK 32 -#endif #define MAX_TRACK_MASK (MAX_TRACK-1) /* As defined in plugins/lib/xxx2wav.h */ -#if MEM > 1 #define GUARD_BUFSIZE (32*1024) -#else -#define GUARD_BUFSIZE (8*1024) -#endif /* As defined in plugin.lds */ #if defined(CPU_PP) @@ -275,11 +265,13 @@ */ static bool codec_requested_stop = false; +#ifdef HAVE_DISK_STORAGE static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ +#endif /* Multiple threads */ -/* Set the watermark to trigger buffer fill (A/C) FIXME */ -static void set_filebuf_watermark(int seconds, size_t max); +/* Set the watermark to trigger buffer fill (A/C) */ +static void set_filebuf_watermark(void); /* Audio thread */ static struct event_queue audio_queue SHAREDBSS_ATTR; @@ -795,7 +787,7 @@ static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600}; buffer_margin = lookup[setting]; logf("buffer margin: %ld", (long)buffer_margin); - set_filebuf_watermark(buffer_margin, 0); + set_filebuf_watermark(); } #endif @@ -841,16 +833,35 @@ /* --- 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) return; /* Audio buffers not yet set up */ - bytes = seconds?MAX(curtrack_id3.bitrate * seconds * (1000/8), max):max; - bytes = MIN(bytes, filebuflen / 2); +#ifdef HAVE_FLASH_STORAGE + int seconds = 1; +#else + int seconds; + int spinup = ata_spinup_time(); + if (spinup) + seconds = (spinup / HZ) + 1.5; + 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); + logf("fwmark: %d", bytes); } const char *get_codec_filename(int cod_spec) @@ -1104,10 +1115,6 @@ static void codec_configure_callback(int setting, intptr_t value) { switch (setting) { - case CODEC_SET_FILEBUF_WATERMARK: - set_filebuf_watermark(buffer_margin, value); - break; - default: if (!dsp_configure(ci.dsp, setting, value)) { logf("Illegal key:%d", setting); } @@ -1222,7 +1229,7 @@ return false; default: - LOGFQUEUE("codec |< default"); + LOGFQUEUE("codec |< default (result: %lx)", result); ci.stop_codec = true; codec_requested_stop = true; return false; @@ -1315,7 +1322,7 @@ #endif /* AUDIO_HAVE_RECORDING */ default: - LOGFQUEUE("codec < default"); + LOGFQUEUE("codec < default (event: %lx)", ev.id); } if (audio_codec_loaded) @@ -1498,6 +1505,8 @@ /* Update track info after successful a codec track change */ static void audio_update_trackinfo(void) { + logf("audio_update_trackinfo()"); + /* Load the curent track's metadata into curtrack_id3 */ if (CUR_TI->id3_hid >= 0) copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid)); @@ -1623,6 +1632,8 @@ const char *trackname; int fd = -1; + logf("audio_load_track(%d,%s)",offset,start_play?"true":"false"); + if (track_load_started) { /* There is already a track load in progress, so track_widx hasn't been incremented yet. Loading another track would overwrite the one that @@ -1684,7 +1695,7 @@ /* Set default values */ if (start_play) { - buf_set_watermark(AUDIO_DEFAULT_WATERMARK); + buf_set_watermark(filebuflen/2); dsp_configure(ci.dsp, DSP_RESET, 0); track_changed = true; playlist_update_resume_info(audio_current_track()); @@ -1697,6 +1708,8 @@ if (tracks[track_widx].id3_hid < 0) { + struct buffering_debug d; + buffering_get_debugdata(&d); /* Buffer is full. */ get_metadata(&lasttrack_id3, fd, trackname); last_peek_offset--; @@ -1953,6 +1966,8 @@ int i, idx; bool forward; + logf("audio_check_new_track()"); + /* Now it's good time to send track finish events. */ send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3); if (dir_skip) @@ -2198,10 +2213,6 @@ /* Officially playing */ queue_reply(&audio_queue, 1); -#ifdef HAVE_DISK_STORAGE - set_filebuf_watermark(buffer_margin, 0); -#endif - audio_fill_file_buffer(true, offset); add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback); @@ -2389,6 +2400,7 @@ case Q_AUDIO_FILL_BUFFER: LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data); audio_fill_file_buffer((bool)ev.data, 0); + set_filebuf_watermark(); break; case Q_AUDIO_FINISH_LOAD: @@ -2497,7 +2509,7 @@ break; default: - LOGFQUEUE("audio < default"); + LOGFQUEUE("audio < default (event: %lx)", ev.id); break; } /* end switch */ } /* end while */ Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 19610) +++ apps/buffering.c (working copy) @@ -56,14 +56,10 @@ #include "albumart.h" #endif -#if MEM > 1 #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*/ +/*#define LOGF_ENABLE */ #include "logf.h" /* macros to enable logf for queues @@ -91,8 +87,6 @@ #define BUFFERING_DEFAULT_WATERMARK (1024*512) /* amount of data to read in one read() call */ #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 @@ -555,7 +549,7 @@ static inline bool buffer_is_low(void) { update_data_counters(); - return data_counters.useful < BUFFERING_CRITICAL_LEVEL; + return data_counters.useful < (conf_watermark / 2); } /* Buffer data for the given handle. @@ -1313,8 +1307,7 @@ void buf_set_watermark(size_t bytes) { - LOGFQUEUE("buffering > Q_SET_WATERMARK %ld", (long)bytes); - queue_post(&buffering_queue, Q_SET_WATERMARK, bytes); + conf_watermark = bytes; } static void shrink_buffer_inner(struct memory_handle *h) @@ -1389,12 +1382,6 @@ case Q_SET_WATERMARK: LOGFQUEUE("buffering < Q_SET_WATERMARK"); conf_watermark = (size_t)ev.data; - if (conf_watermark < BUFFERING_DEFAULT_FILECHUNK) - { - logf("wmarkconfigure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); next_track: Index: apps/codecs/ape.c =================================================================== --- apps/codecs/ape.c (revision 19610) +++ apps/codecs/ape.c (working copy) @@ -147,8 +147,6 @@ size_t resume_offset; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); next_track: Index: apps/codecs/aiff.c =================================================================== --- apps/codecs/aiff.c (revision 19610) +++ apps/codecs/aiff.c (working copy) @@ -66,7 +66,6 @@ /* Generic codec initialisation */ ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); next_track: if (codec_init()) { Index: apps/codecs/aac.c =================================================================== --- apps/codecs/aac.c (revision 19610) +++ apps/codecs/aac.c (working copy) @@ -55,8 +55,6 @@ unsigned char c = 0; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_SAMPLE_DEPTH, 29); Index: apps/codecs/spc.c =================================================================== --- apps/codecs/spc.c (revision 19610) +++ apps/codecs/spc.c (working copy) @@ -559,8 +559,6 @@ /* Read the entire file */ DEBUGF("SPC: request initial buffer\n"); - ci->configure(CODEC_SET_FILEBUF_WATERMARK, ci->filesize); - ci->seek_buffer(0); size_t buffersize; uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); Index: apps/codecs/alac.c =================================================================== --- apps/codecs/alac.c (revision 19610) +++ apps/codecs/alac.c (working copy) @@ -44,8 +44,6 @@ int retval; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); Index: apps/codecs/mod.c =================================================================== --- apps/codecs/mod.c (revision 19610) +++ apps/codecs/mod.c (working copy) @@ -1229,9 +1229,6 @@ int bytesdone; - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - - next_track: if (codec_init()) { return CODEC_ERROR; Index: apps/codecs/sid.c =================================================================== --- apps/codecs/sid.c (revision 19610) +++ apps/codecs/sid.c (working copy) @@ -1215,9 +1215,6 @@ int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ int nSamplesToRender = 0; - /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - next_track: if (codec_init()) { return CODEC_ERROR; Index: apps/codecs/shorten.c =================================================================== --- apps/codecs/shorten.c (revision 19610) +++ apps/codecs/shorten.c (working copy) @@ -47,8 +47,6 @@ size_t bytesleft; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); Index: apps/codecs/asap.c =================================================================== --- apps/codecs/asap.c (revision 19610) +++ apps/codecs/asap.c (working copy) @@ -38,9 +38,6 @@ char* module; int bytesPerSample =2; - /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - next_track: if (codec_init()) { DEBUGF("codec init failed\n"); Index: apps/codecs/wma.c =================================================================== --- apps/codecs/wma.c (revision 19610) +++ apps/codecs/wma.c (working copy) @@ -468,8 +468,6 @@ int errcount = 0; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_SAMPLE_DEPTH, 29); next_track: Index: apps/codecs/wavpack.c =================================================================== --- apps/codecs/wavpack.c (revision 19610) +++ apps/codecs/wavpack.c (working copy) @@ -44,8 +44,6 @@ int retval; /* Generic codec initialisation */ - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); - ci->configure(DSP_SET_SAMPLE_DEPTH, 28); next_track: Index: apps/codecs/wav.c =================================================================== --- apps/codecs/wav.c (revision 19610) +++ apps/codecs/wav.c (working copy) @@ -228,7 +228,6 @@ /* Generic codec initialisation */ ci->configure(DSP_SET_SAMPLE_DEPTH, 28); - ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); next_track: if (codec_init()) {