changeset 4237:8f6956130372

initial Replay Gain support
author Eugene Zagidullin <e.asphyx@gmail.com>
date Sat, 02 Feb 2008 01:53:15 +0300
parents 1ab015fe2ade
children 75ea2083e744
files src/audacious/Makefile src/audacious/output.c src/audacious/plugin.h src/audacious/ui_preferences.c src/libSAD/dither.c
diffstat 5 files changed, 103 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/audacious/Makefile	Thu Jan 31 21:43:51 2008 +0300
+++ b/src/audacious/Makefile	Sat Feb 02 01:53:15 2008 +0300
@@ -134,6 +134,7 @@
        images/playback.png					\
        images/playlist.png					\
        images/plugins.png					\
+       images/replay_gain.png					\
        ui/equalizer.ui						\
        ui/mainwin.ui						\
        ui/playlist.ui						\
--- a/src/audacious/output.c	Thu Jan 31 21:43:51 2008 +0300
+++ b/src/audacious/output.c	Sat Feb 02 01:53:15 2008 +0300
@@ -142,6 +142,8 @@
   }
 }
 
+static void apply_replaygain_info (ReplayGainInfo *rg_info);
+
 static SAD_sample_format
 sadfmt_from_afmt(AFormat fmt)
 {
@@ -332,6 +334,12 @@
 static SAD_dither_t *sad_state_from_float = NULL;
 static void *sad_out_buf = NULL;
 static int sad_out_buf_length = 0;
+static ReplayGainInfo replay_gain_info = {
+    .track_gain = 0.0,
+    .track_peak = 0.0,
+    .album_gain = 0.0,
+    .album_peak = 0.0,
+};
 
 static void
 freeSAD()
@@ -347,19 +355,19 @@
 {
     gint ret;
     OutputPlugin *op;
-    ConfigDb *db;
     AUDDBG("\n");
 
     AFormat output_fmt;
     int bit_depth;
     SAD_buffer_format input_sad_fmt;
     SAD_buffer_format output_sad_fmt;
-    
-    db = cfg_db_open();
 
 #ifdef USE_SRC
     gboolean src_enabled;
     gint src_rate, src_type;
+    ConfigDb *db;
+    
+    db = cfg_db_open();
     
     if (cfg_db_get_bool(db, NULL, "enable_src", &src_enabled) == FALSE)
       src_enabled = FALSE;
@@ -394,10 +402,12 @@
           src_enabled = FALSE;
         }
       }
+    
+    cfg_db_close(db);
 #endif
     
-    if (cfg_db_get_int(db, NULL, "output_bit_depth", &bit_depth) == FALSE) bit_depth = 16;
-    cfg_db_close(db);
+    /*if (cfg_db_get_int(db, NULL, "output_bit_depth", &bit_depth) == FALSE) bit_depth = 16;*/
+    bit_depth = cfg.output_bit_depth;
 
     AUDDBG("bit depth: %d\n", bit_depth);
     output_fmt = (bit_depth == 24) ? FMT_S24_NE : FMT_S16_NE; /* no reason to support other output formats --asphyx */
@@ -451,7 +461,7 @@
         fmt = output_fmt;
     } else
 #endif /* USE_SRC */
-    if (output_fmt != fmt) {
+    {   /* needed for RG processing !*/
         AUDDBG("initializing dithering engine for direct conversion\n");
 
         input_sad_fmt.sample_format = sadfmt_from_afmt(fmt);
@@ -476,6 +486,9 @@
 
         fmt = output_fmt;
     }
+
+    if(replay_gain_info.album_peak != 0.0 || replay_gain_info.track_peak != 0.0)
+        apply_replaygain_info(&replay_gain_info);
     
     op = get_current_output_plugin();
 
@@ -530,6 +543,12 @@
     freeSRC();
 #endif
     freeSAD();
+    
+    AUDDBG("clearing RG settings\n");
+    replay_gain_info.track_gain = 0.0;
+    replay_gain_info.track_peak = 0.0;
+    replay_gain_info.album_gain = 0.0;
+    replay_gain_info.album_peak = 0.0;
 
     /* Do not close if there are still songs to play and the user has 
      * not requested a stop.  --nenolod
@@ -727,9 +746,57 @@
     }
 }
 
-/* called by input plugin when RG info available */
+/* called by input plugin when RG info available --asphyx */
 void
 output_set_replaygain_info (InputPlayback *pb, ReplayGainInfo *rg_info)
 {
- /*stub*/
+    replay_gain_info = *rg_info;
+    apply_replaygain_info(rg_info);
 }
+
+static void
+apply_replaygain_info (ReplayGainInfo *rg_info)
+{
+    SAD_replaygain_mode mode;
+    SAD_replaygain_info info;
+    /*ConfigDb *db;*/
+    gboolean rg_enabled;
+    gboolean album_mode;
+    SAD_dither_t *active_state;
+
+
+    if(sad_state == NULL && sad_state_from_float == NULL) {
+        AUDDBG("SAD not initialized!\n");
+        return;
+    }
+    
+    rg_enabled = cfg.enable_replay_gain;
+    album_mode = cfg.replay_gain_album;
+    mode.clipping_prevention = cfg.enable_clipping_prevention;
+    mode.hard_limit = cfg.enable_hard_limiter;
+    
+    if(!rg_enabled) return;
+
+    mode.mode = album_mode ? SAD_RG_ALBUM : SAD_RG_TRACK;
+    mode.preamp = 0.0; /*FIXME*/
+
+    info.present = TRUE;
+    info.track_gain = rg_info->track_gain;
+    info.track_peak = rg_info->track_peak;
+    info.album_gain = rg_info->album_gain;
+    info.album_peak = rg_info->album_peak;
+
+    AUDDBG("Applying Replay Gain settings:\n");
+    AUDDBG("* mode:                %s\n",     mode.mode == SAD_RG_ALBUM ? "album" : "track");
+    AUDDBG("* clipping prevention: %s\n",     mode.clipping_prevention ? "yes" : "no");
+    AUDDBG("* hard limit:          %s\n",     mode.hard_limit ? "yes" : "no");
+    AUDDBG("* preamp:              %+f dB\n", mode.preamp);
+    AUDDBG("Replay Gain info for current track:\n");
+    AUDDBG("* track gain:          %+f dB\n", info.track_gain);
+    AUDDBG("* track peak:          %f\n",     info.track_peak);
+    AUDDBG("* album gain:          %+f dB\n", info.album_gain);
+    AUDDBG("* album peak:          %f\n",     info.album_peak);
+    
+    active_state = sad_state != NULL ? sad_state : sad_state_from_float;
+    SAD_dither_apply_replaygain(active_state, &info, &mode);
+}
--- a/src/audacious/plugin.h	Thu Jan 31 21:43:51 2008 +0300
+++ b/src/audacious/plugin.h	Sat Feb 02 01:53:15 2008 +0300
@@ -1080,7 +1080,8 @@
     void (*pass_audio) (InputPlayback *, AFormat, gint, gint, gpointer, gint *);
 
     /* added in Audacious 1.5 */
-    void (*set_replaygain_info) (InputPlayback *, ReplayGainInfo *); /* called by input plugin when RG info available --asphyx */
+    /* called by input plugin when RG info available --asphyx */
+    void (*set_replaygain_info) (InputPlayback *, ReplayGainInfo *);
 };
 
 struct _InputPlugin {
--- a/src/audacious/ui_preferences.c	Thu Jan 31 21:43:51 2008 +0300
+++ b/src/audacious/ui_preferences.c	Sat Feb 02 01:53:15 2008 +0300
@@ -127,6 +127,7 @@
 static Category categories[] = {
     {DATA_DIR "/images/appearance.png",   N_("Appearance")},
     {DATA_DIR "/images/audio.png",        N_("Audio")},
+    {DATA_DIR "/images/replay_gain.png",  N_("Replay Gain")},
     {DATA_DIR "/images/connectivity.png", N_("Connectivity")},
     {DATA_DIR "/images/mouse.png",        N_("Mouse")},
     {DATA_DIR "/images/playback.png",     N_("Playback")},
@@ -218,6 +219,9 @@
         N_("When checked, Audacious will detect file formats based by extension. Only files with extensions of supported formats will be loaded."), FALSE},
     {WIDGET_LABEL, N_("<b>Bit Depth</b>"), NULL, NULL, NULL, FALSE},
     {WIDGET_CUSTOM, NULL, NULL, NULL, NULL, TRUE, ui_preferences_bit_depth},
+};
+    
+static PreferencesWidget replay_gain_page_widgets[] = {
     {WIDGET_LABEL, N_("<b>Replay Gain</b>"), NULL, NULL, NULL, FALSE},
     {WIDGET_CHK_BTN, N_("Enable Replay Gain"), &cfg.enable_replay_gain, NULL, NULL, FALSE},
     {WIDGET_RADIO_BTN, N_("Use track gain/peak"), &cfg.replay_gain_track, NULL, NULL, TRUE},
@@ -1982,6 +1986,20 @@
 }
 
 static void
+create_replay_gain_category(void)
+{
+    GtkWidget *rg_page_vbox;
+    GtkWidget *widgets_vbox;
+
+    rg_page_vbox = gtk_vbox_new (FALSE, 0);
+    gtk_container_add (GTK_CONTAINER (category_notebook), rg_page_vbox);
+
+    widgets_vbox = gtk_vbox_new (FALSE, 0);
+    create_widgets(GTK_BOX(widgets_vbox), replay_gain_page_widgets, G_N_ELEMENTS(replay_gain_page_widgets));
+    gtk_box_pack_start (GTK_BOX (rg_page_vbox), widgets_vbox, TRUE, TRUE, 0);
+}
+
+static void
 create_playlist_category(void)
 {
     GtkWidget *playlist_page_vbox;
@@ -2997,6 +3015,7 @@
 
     create_appearence_category();
     create_audio_category();
+    create_replay_gain_category();
     create_connectivity_category();
     create_mouse_category();
     create_playback_category();
--- a/src/libSAD/dither.c	Thu Jan 31 21:43:51 2008 +0300
+++ b/src/libSAD/dither.c	Sat Feb 02 01:53:15 2008 +0300
@@ -457,6 +457,11 @@
     case SAD_RG_TRACK:
       scale = db2scale(rg_info->track_gain);
       peak = rg_info->track_peak;
+      if (peak == 0.0) {
+        scale = db2scale(rg_info->album_gain); // fallback to per-album mode
+	peak = rg_info->album_peak;
+	DEBUG_MSG("f: SAD_dither_apply_replaygain: fallback to album mode\n",0);
+      }
       break;
     case SAD_RG_NONE:
       scale = -1.0;
@@ -464,7 +469,7 @@
   
   if (scale != -1.0 && peak != 0.0) {
     DEBUG_MSG("f: SAD_dither_apply_replaygain: applying\n",0);
-    scale *= mode->preamp;
+    scale *= db2scale(mode->preamp);
     // Clipping prevention
     if(mode->clipping_prevention) {
 #ifdef DEBUG