From 9e0953432a3a73cd42e77c804a4557b5337e0d0f Mon Sep 17 00:00:00 2001 From: Jeffrey Goode Date: Tue, 10 Nov 2009 03:46:08 +0000 Subject: [PATCH] Crossfade: carved out crossfade related code with lots of HAVE_CORSSFADE conditionals, eliminated fade buffer on low memory targets git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23597 a1c6a512-1295-4272-9138-f99709370657 --- apps/codec_thread.c | 5 +- apps/menus/playback_menu.c | 10 ++-- apps/menus/settings_menu.c | 2 +- apps/pcmbuf.c | 102 +++++++++++++++++++++++++------------ apps/pcmbuf.h | 2 + apps/playback.c | 10 +++- apps/playback.h | 4 +- apps/settings.c | 2 + apps/settings.h | 2 + 9 files changed, 97 insertions(+), 42 deletions(-) diff --git a/apps/codec_thread.c b/apps/codec_thread.c index 13b203ee30..dc6533dfc9 100644 --- a/apps/codec_thread.c +++ b/apps/codec_thread.c @@ -475,7 +475,10 @@ static void codec_thread(void) while (1) { status = 0; - if (!pcmbuf_is_crossfade_active()) { +#ifdef HAVE_CROSSFADE + if (!pcmbuf_is_crossfade_active()) +#endif + { cancel_cpu_boost(); } diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c index 4c4b29871e..5be7a8ca43 100644 --- a/apps/menus/playback_menu.c +++ b/apps/menus/playback_menu.c @@ -40,7 +40,7 @@ #endif -#if CONFIG_CODEC == SWCODEC +#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_CROSSFADE) static int setcrossfadeonexit_callback(int action,const struct menu_item_ex *this_item) { (void)this_item; @@ -90,19 +90,19 @@ MENUITEM_SETTING(fade_on_stop, &global_settings.fade_on_stop, NULL); MENUITEM_SETTING(party_mode, &global_settings.party_mode, NULL); #if CONFIG_CODEC == SWCODEC +#ifdef HAVE_CROSSFADE /* crossfade submenu */ MENUITEM_SETTING(crossfade, &global_settings.crossfade, setcrossfadeonexit_callback); MENUITEM_SETTING(crossfade_fade_in_delay, - &global_settings.crossfade_fade_in_delay, setcrossfadeonexit_callback); + &global_settings.crossfade_fade_in_delay, NULL); MENUITEM_SETTING(crossfade_fade_in_duration, - &global_settings.crossfade_fade_in_duration, setcrossfadeonexit_callback); + &global_settings.crossfade_fade_in_duration, NULL); MENUITEM_SETTING(crossfade_fade_out_delay, &global_settings.crossfade_fade_out_delay, setcrossfadeonexit_callback); MENUITEM_SETTING(crossfade_fade_out_duration, &global_settings.crossfade_fade_out_duration, setcrossfadeonexit_callback); MENUITEM_SETTING(crossfade_fade_out_mixmode, &global_settings.crossfade_fade_out_mixmode,NULL); -#ifdef HAVE_CROSSFADE MAKE_MENU(crossfade_settings_menu,ID2P(LANG_CROSSFADE),0, Icon_NOICON, &crossfade, &crossfade_fade_in_delay, &crossfade_fade_in_duration, &crossfade_fade_out_delay, &crossfade_fade_out_duration, @@ -187,7 +187,7 @@ MAKE_MENU(playback_settings,ID2P(LANG_PLAYBACK),0, #endif &fade_on_stop, &party_mode, -#if CONFIG_CODEC == SWCODEC && defined(HAVE_CROSSFADE) +#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_CROSSFADE) &crossfade_settings_menu, #endif diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index 135e632479..04de59fe20 100644 --- a/apps/menus/settings_menu.c +++ b/apps/menus/settings_menu.c @@ -367,7 +367,7 @@ static int talk_callback(int action,const struct menu_item_ex *this_item) oldval = global_settings.talk_file_clip; break; case ACTION_EXIT_MENUITEM: -#if CONFIG_CODEC == SWCODEC +#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_CROSSFADE) audio_set_crossfade(global_settings.crossfade); #endif if (this_item == &talk_dir_clip_item) diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 975d254424..6f3dd80ed2 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -79,12 +79,15 @@ static char *pcmbuffer IDATA_ATTR; static size_t pcmbuffer_pos IDATA_ATTR; /* Amount pcmbuffer_pos will be increased.*/ static size_t pcmbuffer_fillpos IDATA_ATTR; -static char *fadebuf IDATA_ATTR; -static char *voicebuf IDATA_ATTR; +/* Gapless playback */ static bool end_of_track IDATA_ATTR; bool track_transition IDATA_ATTR; +#ifdef HAVE_CROSSFADE +/* Crossfade buffer */ +static char *fadebuf IDATA_ATTR; + /* Crossfade related state */ static bool crossfade_enabled; static bool crossfade_enable_request; @@ -94,7 +97,6 @@ static bool crossfade_track_change_started IDATA_ATTR; /* Track the current location for processing crossfade */ static struct chunkdesc *crossfade_chunk IDATA_ATTR; -#ifdef HAVE_CROSSFADE static size_t crossfade_sample IDATA_ATTR; /* Counters for fading in new data */ @@ -111,6 +113,8 @@ static size_t last_chunksize IDATA_ATTR; static size_t pcmbuf_unplayed_bytes IDATA_ATTR; static size_t pcmbuf_watermark IDATA_ATTR; +/* Voice */ +static char *voicebuf IDATA_ATTR; static struct chunkdesc *mix_chunk IDATA_ATTR; static size_t pcmbuf_mix_sample IDATA_ATTR; @@ -133,9 +137,8 @@ extern unsigned int codec_thread_id; #ifdef HAVE_CROSSFADE static void crossfade_start(void); static void flush_crossfade(char *buf, size_t length); -#endif static void pcmbuf_finish_crossfade_enable(void); -static bool pcmbuf_is_crossfade_enabled(void); +#endif /**************************************/ @@ -315,11 +318,13 @@ static bool prepare_insert(size_t length) } } +#ifdef HAVE_CROSSFADE /* Disable crossfade if < .5s of audio */ if (LOW_DATA(2)) { crossfade_active = false; } +#endif } else /* pcm_is_playing */ { @@ -346,13 +351,13 @@ void *pcmbuf_request_buffer(int *count) #ifdef HAVE_CROSSFADE if (crossfade_track_change_started) crossfade_start(); -#endif if (crossfade_active) { *count = MIN(*count, PCMBUF_MIX_CHUNK/4); return fadebuf; } else +#endif { if(prepare_insert(*count << 2)) { @@ -417,9 +422,11 @@ static size_t get_next_required_pcmbuf_size(void) { size_t seconds = 1; +#ifdef HAVE_CROSSFADE if (crossfade_enable_request) - seconds += global_settings.crossfade_fade_out_delay - + global_settings.crossfade_fade_out_duration; + seconds += global_settings.crossfade_fade_out_delay + + global_settings.crossfade_fade_out_duration; +#endif #if MEMORYSIZE > 2 /* Buffer has to be at least 2s long. */ @@ -438,8 +445,12 @@ size_t pcmbuf_init(unsigned char *bufend) write_chunk = (struct chunkdesc *)pcmbuf_bufend - NUM_CHUNK_DESCS(pcmbuf_size); voicebuf = (char *)write_chunk - PCMBUF_MIX_CHUNK; +#ifdef HAVE_CROSSFADE fadebuf = voicebuf - PCMBUF_MIX_CHUNK; pcmbuffer = fadebuf - pcmbuf_size; +#else + pcmbuffer = voicebuf - pcmbuf_size; +#endif init_pcmbuffers(); @@ -447,7 +458,11 @@ size_t pcmbuf_init(unsigned char *bufend) end_of_track = false; track_transition = false; +#ifdef HAVE_CROSSFADE pcmbuf_finish_crossfade_enable(); +#else + pcmbuf_watermark = PCMBUF_WATERMARK; +#endif pcmbuf_play_stop(); @@ -463,6 +478,7 @@ size_t pcmbuf_init(unsigned char *bufend) * last one in the track. */ static void start_gapless_track_change(void) { + logf(" gapless track change"); /* we're starting a track transition */ track_transition = true; @@ -470,13 +486,28 @@ static void start_gapless_track_change(void) end_of_track = true; } -static void start_crossfade_track_change(bool auto_skip) +#ifdef HAVE_CROSSFADE +static bool pcmbuf_is_crossfade_enabled(void) { + if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE) + return global_settings.playlist_shuffle; + + return crossfade_enabled; +} +#endif + +static void start_processed_track_change(bool auto_skip) +{ + logf(" processed track change"); /* Notify the wps that the track change starts now */ audio_post_track_change(false); /* Can't do two crossfades at once and, no fade if pcm is off now */ - if (pcmbuf_is_crossfade_active() || !pcm_is_playing()) + if ( +#ifdef HAVE_CROSSFADE + pcmbuf_is_crossfade_active() || +#endif + !pcm_is_playing()) { pcmbuf_play_stop(); return; @@ -485,7 +516,11 @@ static void start_crossfade_track_change(bool auto_skip) trigger_cpu_boost(); /* Not enough data, or crossfade disabled, flush the old data instead */ - if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode) + if (LOW_DATA(2) || +#ifdef HAVE_CROSSFADE + !pcmbuf_is_crossfade_enabled() || +#endif + low_latency_mode) { /* commit everything to this point and keep going, but... */ commit_chunk(); @@ -494,19 +529,22 @@ static void start_crossfade_track_change(bool auto_skip) return; } +#ifdef HAVE_CROSSFADE /* Don't enable mix mode when skipping tracks manually. */ crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; crossfade_track_change_started = true; +#endif } void pcmbuf_start_track_change(bool auto_skip) { - bool crossfade = false; + bool process = false; /* Manual track change (always crossfade or flush audio). */ if (!auto_skip) - crossfade = true; + process = true; +#ifdef HAVE_CROSSFADE /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */ else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active() && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP) @@ -514,17 +552,18 @@ void pcmbuf_start_track_change(bool auto_skip) if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP) { if (global_settings.playlist_shuffle) - crossfade = true; + process = true; } else - crossfade = true; + process = true; } +#endif - if (crossfade) - /* crossfade to next track */ - start_crossfade_track_change(auto_skip); + if (process) + /* process track change (manual skip or crossfade) */ + start_processed_track_change(auto_skip); else - /* normal gapless playback. */ + /* normal gapless playback */ start_gapless_track_change(); } @@ -573,9 +612,12 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) /* If we've read over the mix chunk while it's still mixing there */ if (pcmbuf_current == mix_chunk) mix_chunk = NULL; + +#ifdef HAVE_CROSSFADE /* If we've read over the crossfade chunk while it's still fading */ if (pcmbuf_current == crossfade_chunk) crossfade_chunk = read_chunk; +#endif } { @@ -636,8 +678,10 @@ void pcmbuf_play_stop(void) } pcmbuffer_pos = 0; pcmbuffer_fillpos = 0; +#ifdef HAVE_CROSSFADE crossfade_track_change_started = false; crossfade_active = false; +#endif flush_pcmbuf = false; DISPLAY_DESC("play_stop"); @@ -664,10 +708,6 @@ static inline int32_t clip_sample_16(int32_t sample) return sample; } -/** - * Low memory targets don't have crossfade, so don't compile crossfade - * specific code in order to save some memory. */ - #ifdef HAVE_CROSSFADE /** * Completely process the crossfade fade out effect with current pcm buffer. @@ -906,7 +946,6 @@ static void flush_crossfade(char *buf, size_t length) } } } -#endif /* HAVE_CROSSFADE */ static void pcmbuf_finish_crossfade_enable(void) { @@ -920,14 +959,6 @@ static void pcmbuf_finish_crossfade_enable(void) PCMBUF_WATERMARK; } -static bool pcmbuf_is_crossfade_enabled(void) -{ - if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE) - return global_settings.playlist_shuffle; - - return crossfade_enabled; -} - bool pcmbuf_is_crossfade_active(void) { return crossfade_active || crossfade_track_change_started; @@ -951,6 +982,7 @@ bool pcmbuf_is_same_size(void) return same_size; } +#endif /* HAVE_CROSSFADE */ /* Voice */ @@ -1100,7 +1132,11 @@ unsigned char * pcmbuf_get_meminfo(size_t *length) bool pcmbuf_is_lowdata(void) { - if (!pcm_is_playing() || pcm_is_paused() || pcmbuf_is_crossfade_active()) + if (!pcm_is_playing() || pcm_is_paused() +#ifdef HAVE_CROSSFADE + || pcmbuf_is_crossfade_active() +#endif + ) return false; #if MEMORYSIZE > 2 diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h index 747ab31537..992eb8063f 100644 --- a/apps/pcmbuf.h +++ b/apps/pcmbuf.h @@ -35,9 +35,11 @@ void pcmbuf_pause(bool pause); void pcmbuf_start_track_change(bool manual_skip); /* Crossfade */ +#ifdef HAVE_CROSSFADE bool pcmbuf_is_crossfade_active(void); void pcmbuf_request_crossfade_enable(bool on_off); bool pcmbuf_is_same_size(void); +#endif /* Voice */ void *pcmbuf_request_voice_buffer(int *count); diff --git a/apps/playback.c b/apps/playback.c index 312a1c8165..2c9ca10311 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -814,6 +814,7 @@ void audio_set_buffer_margin(int setting) } #endif +#ifdef HAVE_CROSSFADE /* Take necessary steps to enable or disable the crossfade setting */ void audio_set_crossfade(int enable) { @@ -847,6 +848,7 @@ void audio_set_crossfade(int enable) if (was_playing) audio_play(offset); } +#endif /* --- Routines called from multiple threads --- */ @@ -1919,7 +1921,11 @@ static void audio_thread(void) case Q_AUDIO_PAUSE: LOGFQUEUE("audio < Q_AUDIO_PAUSE"); - if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active()) + if (!(bool) ev.data && skipped_during_pause +#ifdef HAVE_CROSSFADE + && !pcmbuf_is_crossfade_active() +#endif + ) pcmbuf_play_stop(); /* Flush old track on resume after skip */ skipped_during_pause = false; if (!playing) @@ -2059,8 +2065,10 @@ void audio_init(void) voice_thread_init(); #endif +#ifdef HAVE_CROSSFADE /* Set crossfade setting for next buffer init which should be about... */ pcmbuf_request_crossfade_enable(global_settings.crossfade); +#endif /* initialize the buffering system */ diff --git a/apps/playback.h b/apps/playback.h index b40638247b..3a1f45f6b2 100644 --- a/apps/playback.h +++ b/apps/playback.h @@ -58,9 +58,11 @@ bool audio_is_thread_ready(void); int audio_track_count(void); long audio_filebufused(void); void audio_pre_ff_rewind(void); -void audio_set_crossfade(int type); void audio_skip(int direction); void audio_hard_stop(void); /* Stops audio from serving playback */ +#ifdef HAVE_CROSSFADE +void audio_set_crossfade(int enable); +#endif enum { diff --git a/apps/settings.c b/apps/settings.c index 2de4aa8c71..54fe4244f7 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -964,7 +964,9 @@ void settings_apply(bool read_disk) set_codepage(global_settings.default_codepage); #if CONFIG_CODEC == SWCODEC +#ifdef HAVE_CROSSFADE audio_set_crossfade(global_settings.crossfade); +#endif dsp_set_replaygain(); dsp_set_crossfeed(global_settings.crossfeed); dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain); diff --git a/apps/settings.h b/apps/settings.h index eba592aca8..4ab2d8945d 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -339,6 +339,7 @@ struct user_settings #endif #if CONFIG_CODEC == SWCODEC +#ifdef HAVE_CROSSFADE /* Crossfade */ int crossfade; /* Enable crossfade (0=off, 1=shuffle, 2=trackskip, 3=shuff&trackskip, 4=always) */ @@ -347,6 +348,7 @@ struct user_settings int crossfade_fade_in_duration; /* Fade in duration (0-15s) */ int crossfade_fade_out_duration; /* Fade out duration (0-15s) */ int crossfade_fade_out_mixmode; /* Fade out mode (0=crossfade,1=mix) */ +#endif /* Replaygain */ bool replaygain_noclip; /* scale to prevent clips */