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
diff --git a/apps/codec_thread.c b/apps/codec_thread.c
index 13b203e..dc6533d 100644
--- a/apps/codec_thread.c
+++ b/apps/codec_thread.c
@@ -475,7 +475,10 @@
     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 4c4b298..5be7a8c 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(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 @@
 #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 135e632..04de59f 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -367,7 +367,7 @@
             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 975d254..6f3dd80 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -79,12 +79,15 @@
 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 @@
 
 /* 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 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 @@
 #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 @@
             }
         }
 
+#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 @@
 #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 @@
 {
     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 @@
     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 @@
     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 @@
  * 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 @@
     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 @@
     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 @@
         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 @@
         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 @@
         /* 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 @@
     }
     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 @@
     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 @@
         }
     }
 }
-#endif /* HAVE_CROSSFADE */
 
 static void pcmbuf_finish_crossfade_enable(void)
 {
@@ -920,14 +959,6 @@
         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 @@
     
     return same_size;
 }
+#endif /* HAVE_CROSSFADE */
 
 
 /* Voice */
@@ -1100,7 +1132,11 @@
 
 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 747ab31..992eb80 100644
--- a/apps/pcmbuf.h
+++ b/apps/pcmbuf.h
@@ -35,9 +35,11 @@
 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 312a1c8..2c9ca10 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -814,6 +814,7 @@
 }
 #endif
 
+#ifdef HAVE_CROSSFADE
 /* Take necessary steps to enable or disable the crossfade setting */
 void audio_set_crossfade(int enable)
 {
@@ -847,6 +848,7 @@
     if (was_playing)
         audio_play(offset);
 }
+#endif
 
 /* --- Routines called from multiple threads --- */
 
@@ -1919,7 +1921,11 @@
 
             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 @@
     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 b406382..3a1f45f 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -58,9 +58,11 @@
 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 2de4aa8..54fe424 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -964,7 +964,9 @@
     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 eba592a..4ab2d89 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -339,6 +339,7 @@
 #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 @@
     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 */