From 5e2855c5bf351bf9ee028a8659afeee1854f7310 Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Mon, 11 Jul 2011 02:35:21 -0400 Subject: [PATCH] Simplify the codec API and don't always loop MODs. The unused strcasestr callback is removed. Several codecs were using the global_settings pointer to check whether REPEAT_ONE mode was on; this has been replaced with a should_loop callback. The MOD codec has been modified not to restart the file when it reaches the end. This does not affect MOD files that use "position jump" to create an loop of part of the song. Ideally the MOD codec would only follow such loops if should_loop returns 1, but detecting loops is nontrivial. --- apps/codec_thread.c | 7 +++++++ apps/codecs.c | 4 ++-- apps/codecs.h | 11 ++++------- apps/codecs/adx.c | 2 +- apps/codecs/ay.c | 6 +++--- apps/codecs/gbs.c | 4 ++-- apps/codecs/hes.c | 4 ++-- apps/codecs/kss.c | 2 +- apps/codecs/mod.c | 27 +++++++++++++++------------ apps/codecs/nsf.c | 4 ++-- apps/codecs/sgc.c | 2 +- apps/codecs/spc.c | 10 +++++----- apps/codecs/vgm.c | 2 +- apps/plugins/test_codec.c | 9 +++++++-- 14 files changed, 53 insertions(+), 41 deletions(-) diff --git a/apps/codec_thread.c b/apps/codec_thread.c index 945f0b0..7c12620 100644 --- a/apps/codec_thread.c +++ b/apps/codec_thread.c @@ -30,6 +30,7 @@ #include "buffering.h" #include "dsp.h" #include "metadata.h" +#include "settings.h" /* Define LOGF_ENABLE to enable logf output in this file */ /*#define LOGF_ENABLE*/ @@ -402,6 +403,11 @@ static enum codec_command_action } } +static bool codec_should_loop_callback(void) +{ + return global_settings.repeat_mode == REPEAT_ONE; +} + /* Initialize codec API */ void codec_init_codec_api(void) { @@ -418,6 +424,7 @@ void codec_init_codec_api(void) ci.set_offset = audio_codec_update_offset; ci.configure = codec_configure_callback; ci.get_command = codec_get_command_callback; + ci.should_loop = codec_should_loop_callback; } diff --git a/apps/codecs.c b/apps/codecs.c index cd4a9d5..c2efbaa 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -50,6 +50,7 @@ #include "sound.h" #include "splash.h" #include "general.h" +#include "rbpaths.h" #define LOGF_ENABLE #include "logf.h" @@ -97,6 +98,7 @@ struct codec_api ci = { NULL, /* set_offset */ NULL, /* configure */ NULL, /* get_command */ + NULL, /* should_loop */ /* kernel/ system */ #if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE @@ -127,7 +129,6 @@ struct codec_api ci = { memmove, memcmp, memchr, - strcasestr, #if defined(DEBUG) || defined(SIMULATOR) debugf, #endif @@ -136,7 +137,6 @@ struct codec_api ci = { #endif (qsort_func)qsort, - &global_settings, #ifdef RB_PROFILE profile_thread, diff --git a/apps/codecs.h b/apps/codecs.h index e240811..a699711 100644 --- a/apps/codecs.h +++ b/apps/codecs.h @@ -44,7 +44,6 @@ #endif #include "dsp.h" #endif -#include "settings.h" #include "gcc_extensions.h" #include "load_code.h" @@ -75,12 +74,12 @@ #define CODEC_ENC_MAGIC 0x52454E43 /* RENC */ /* increase this every time the api struct changes */ -#define CODEC_API_VERSION 42 +#define CODEC_API_VERSION 43 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define CODEC_MIN_API_VERSION 42 +#define CODEC_MIN_API_VERSION 43 /* reasons for calling codec main entrypoint */ enum codec_entry_call_reason { @@ -145,6 +144,8 @@ struct codec_api { void (*configure)(int setting, intptr_t value); /* Obtain command action on what to do next */ enum codec_command_action (*get_command)(intptr_t *param); + /* Determine whether the loop should be used, if applicable. */ + bool (*should_loop)(void); /* kernel/ system */ #if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE @@ -180,7 +181,6 @@ struct codec_api { void* (*memmove)(void *out, const void *in, size_t n); int (*memcmp)(const void *s1, const void *s2, size_t n); void *(*memchr)(const void *s1, int c, size_t n); - char *(*strcasestr) (const char* phaystack, const char* pneedle); #if defined(DEBUG) || defined(SIMULATOR) void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); @@ -193,9 +193,6 @@ struct codec_api { void (*qsort)(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); - /* The ADX codec accesses global_settings to test for REPEAT_ONE mode */ - struct user_settings* global_settings; - #ifdef RB_PROFILE void (*profile_thread)(void); void (*profstop)(void); diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c index e75e7dc..1318aff 100644 --- a/apps/codecs/adx.c +++ b/apps/codecs/adx.c @@ -239,7 +239,7 @@ enum codec_status codec_run(void) if (bufoff > end_adr-18*channels && looping) { DEBUGF("ADX: loop!\n"); /* check for endless looping */ - if (ci->global_settings->repeat_mode==REPEAT_ONE) { + if (ci->should_loop()) { loop_count=0; fade_count = -1; /* disable fade */ } else { diff --git a/apps/codecs/ay.c b/apps/codecs/ay.c index 48261fb..33b38e5 100644 --- a/apps/codecs/ay.c +++ b/apps/codecs/ay.c @@ -17,8 +17,8 @@ static struct Ay_Emu ay_emu; static void set_codec_track(int t, int multitrack) { Ay_start_track(&ay_emu, t); - /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + /* for loop mode we disable track limits */ + if (!ci->should_loop()) { Track_set_fade(&ay_emu, Track_get_length( &ay_emu, t ) - 4000, 4000); } if (multitrack) ci->set_elapsed(t*1000); /* t is track no to display */ @@ -111,7 +111,7 @@ next_track: ci->seek_complete(); /* Set fade again */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&ay_emu, Track_get_length( &ay_emu, track ) - 4000, 4000); } } diff --git a/apps/codecs/gbs.c b/apps/codecs/gbs.c index 5d31549..743a1d4 100644 --- a/apps/codecs/gbs.c +++ b/apps/codecs/gbs.c @@ -17,8 +17,8 @@ static struct Gbs_Emu gbs_emu; static void set_codec_track(int t) { Gbs_start_track(&gbs_emu, t); - /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + /* for loop mode we disable track limits */ + if (!ci->should_loop()) { Track_set_fade(&gbs_emu, Track_get_length( &gbs_emu, t ), 4000); } ci->set_elapsed(t*1000); /* t is track no to display */ diff --git a/apps/codecs/hes.c b/apps/codecs/hes.c index 8c216ed..9e35fe7 100644 --- a/apps/codecs/hes.c +++ b/apps/codecs/hes.c @@ -17,8 +17,8 @@ static struct Hes_Emu hes_emu; static void set_codec_track(int t) { Hes_start_track(&hes_emu, t); - /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + /* for loop mode we disable track limits */ + if (!ci->should_loop()) { Track_set_fade(&hes_emu, Track_get_length( &hes_emu, t ), 4000); } ci->set_elapsed(t*1000); /* t is track no to display */ diff --git a/apps/codecs/kss.c b/apps/codecs/kss.c index 62dd055..71605c4 100644 --- a/apps/codecs/kss.c +++ b/apps/codecs/kss.c @@ -18,7 +18,7 @@ static void set_codec_track(int t) { Kss_start_track(&kss_emu, t); /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&kss_emu, Track_get_length( &kss_emu, t ), 4000); } ci->set_elapsed(t*1000); /* t is track no to display */ diff --git a/apps/codecs/mod.c b/apps/codecs/mod.c index 3703ecd..2d13f93 100644 --- a/apps/codecs/mod.c +++ b/apps/codecs/mod.c @@ -1155,8 +1155,8 @@ static inline int clip(int i) else return(i); } -STATICIRAM void synthrender(int32_t *renderbuffer, int samplecount) ICODE_ATTR; -void synthrender(int32_t *renderbuffer, int samplecount) +STATICIRAM int synthrender(int32_t *renderbuffer, int samplecount) ICODE_ATTR; +int synthrender(int32_t *renderbuffer, int samplecount) { /* 125bpm equals to 50Hz (= 0.02s) * => one tick = mixingrate/50, @@ -1192,12 +1192,13 @@ void synthrender(int32_t *renderbuffer, int samplecount) if (modplayer.currentline == 64) { modplayer.patterntableposition++; - if (modplayer.patterntableposition >= modsong.songlength) - /* This is for Noise Tracker + if (modplayer.patterntableposition >= modsong.songlength) { + /* For Noise Tracker: * modplayer.patterntableposition = * modsong.songendjumpposition; - * More compatible approach is restart from 0 */ - modplayer.patterntableposition=0; + * However, it's more compatible not to loop. */ + return i; + } modplayer.currentline = 0; } } @@ -1276,6 +1277,8 @@ void synthrender(int32_t *renderbuffer, int samplecount) p_left+=2; p_right+=2; } + + return samplecount; } /* this is the codec entry point */ @@ -1299,7 +1302,7 @@ enum codec_status codec_run(void) size_t n; unsigned char *modfile; int old_patterntableposition; - int bytesdone; + int bytesdone, chunkdone; intptr_t param; if (codec_init()) { @@ -1323,7 +1326,7 @@ enum codec_status codec_run(void) bytesdone = 0; old_patterntableposition = 0; - while (1) { + do { enum codec_command_action action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) @@ -1342,13 +1345,13 @@ enum codec_status codec_run(void) old_patterntableposition=modplayer.patterntableposition; } - synthrender(samples, CHUNK_SIZE/2); + chunkdone = synthrender(samples, CHUNK_SIZE/2); - bytesdone += CHUNK_SIZE; + bytesdone += 2*chunkdone; - ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE/2); + ci->pcmbuf_insert(samples, NULL, chunkdone); - } + } while (chunkdone == CHUNK_SIZE / 2); return CODEC_OK; } diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c index 8899501..b6a749a 100644 --- a/apps/codecs/nsf.c +++ b/apps/codecs/nsf.c @@ -20,7 +20,7 @@ static void set_codec_track(int t, int multitrack) { Nsf_start_track(&nsf_emu, t); /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&nsf_emu, Track_length( &nsf_emu, t ) - 4000, 4000); } if (multitrack) ci->set_elapsed(t*1000); /* t is track no to display */ @@ -109,7 +109,7 @@ next_track: ci->seek_complete(); /* Set fade again */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&nsf_emu, Track_length( &nsf_emu, track ), 4000); } } diff --git a/apps/codecs/sgc.c b/apps/codecs/sgc.c index 2f1f3f8..dc0374c 100644 --- a/apps/codecs/sgc.c +++ b/apps/codecs/sgc.c @@ -23,7 +23,7 @@ static void set_codec_track(int t) { Sgc_start_track(&sgc_emu, t); /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&sgc_emu, Track_get_length( &sgc_emu, t ), 4000); } ci->set_elapsed(t*1000); /* t is track no to display */ diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c index 6b21f9a..8974b8b 100644 --- a/apps/codecs/spc.c +++ b/apps/codecs/spc.c @@ -477,7 +477,7 @@ static int play_track( void ) sampleswritten += WAV_CHUNK_SIZE; /* is track timed? */ - if (ci->global_settings->repeat_mode!=REPEAT_ONE && ci->id3->length) { + if (!ci->should_loop() && ci->id3->length) { unsigned long curtime = sampleswritten*1000LL/SAMPLE_RATE; unsigned long lasttimesample = (sampleswritten-WAV_CHUNK_SIZE); @@ -513,10 +513,10 @@ static int play_track( void ) spc_play_send_samples(samples); - if (ci->global_settings->repeat_mode!=REPEAT_ONE) - ci->set_elapsed(sampleswritten*1000LL/SAMPLE_RATE); - else + if (ci->should_loop()) ci->set_elapsed(0); + else + ci->set_elapsed(sampleswritten*1000LL/SAMPLE_RATE); } EXIT_TIMER(total); @@ -569,7 +569,7 @@ enum codec_status codec_run(void) LoadID666(buffer+0x2e); - if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { + if (!ci->should_loop() && ID666.length==0) { ID666.length=3*60*1000; /* 3 minutes */ ID666.fade=5*1000; /* 5 seconds */ } diff --git a/apps/codecs/vgm.c b/apps/codecs/vgm.c index 9c8619c..b931f8a 100644 --- a/apps/codecs/vgm.c +++ b/apps/codecs/vgm.c @@ -105,7 +105,7 @@ enum codec_status codec_run(void) Vgm_start_track(&vgm_emu); /* for REPEAT_ONE we disable track limits */ - if (ci->global_settings->repeat_mode != REPEAT_ONE) { + if (!ci->should_loop()) { Track_set_fade(&vgm_emu, ci->id3->length - 4000, 4000); } diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index 5c98201..9309f22 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c @@ -509,6 +509,12 @@ static enum codec_command_action get_command(intptr_t *param) (void)param; } +/* Some codecs call this to determine whether they should loop. */ +static bool should_loop(void) +{ + return false; +} + static void set_offset(size_t value) { ci.id3->offset = value; @@ -565,6 +571,7 @@ static void init_ci(void) ci.set_offset = set_offset; ci.configure = configure; ci.get_command = get_command; + ci.should_loop = should_loop; /* --- "Core" functions --- */ @@ -582,7 +589,6 @@ static void init_ci(void) ci.memmove = rb->memmove; ci.memcmp = rb->memcmp; ci.memchr = rb->memchr; - ci.strcasestr = rb->strcasestr; #if defined(DEBUG) || defined(SIMULATOR) ci.debugf = rb->debugf; #endif @@ -591,7 +597,6 @@ static void init_ci(void) #endif ci.qsort = rb->qsort; - ci.global_settings = rb->global_settings; #ifdef RB_PROFILE ci.profile_thread = rb->profile_thread; -- 1.7.6