diff --git a/apps/gui/quickscreen.c b/apps/gui/quickscreen.c index 6e50d61511..df295a8a95 100644 --- a/apps/gui/quickscreen.c +++ b/apps/gui/quickscreen.c @@ -419,9 +419,7 @@ bool quick_screen_quick(int button_enter) if (oldshuffle != global_settings.playlist_shuffle && audio_status() & AUDIO_STATUS_PLAY) { -#if CONFIG_CODEC == SWCODEC - dsp_set_replaygain(); -#endif + replaygain_update(); if (global_settings.playlist_shuffle) playlist_randomise(NULL, current_tick, true); else diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index 0f5deedcf9..578a729bb3 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -1420,25 +1420,22 @@ const char *get_token_value(struct gui_wps *gwps, case SKIN_TOKEN_REPLAYGAIN: { + int globtype = global_settings.replaygain_settings.type; int val; - if (global_settings.replaygain_type == REPLAYGAIN_OFF) + + if (globtype == REPLAYGAIN_OFF) val = 1; /* off */ else { - int type; - if (LIKELY(id3)) - type = get_replaygain_mode(id3->track_gain != 0, - id3->album_gain != 0); - else - type = -1; + int type = id3_get_replaygain_mode(id3); if (type < 0) val = 6; /* no tag */ else val = type + 2; - if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE) + if (globtype == REPLAYGAIN_SHUFFLE) val += 2; } diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c index a52a88439e..34f616b9a3 100644 --- a/apps/gui/skin_engine/skin_touchsupport.c +++ b/apps/gui/skin_engine/skin_touchsupport.c @@ -266,9 +266,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, { global_settings.playlist_shuffle = !global_settings.playlist_shuffle; -#if CONFIG_CODEC == SWCODEC - dsp_set_replaygain(); -#endif + replaygain_update(); if (global_settings.playlist_shuffle) playlist_randomise(NULL, current_tick, true); else diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c index d1d999587b..6beda93991 100644 --- a/apps/menus/playback_menu.c +++ b/apps/menus/playback_menu.c @@ -34,6 +34,7 @@ #include "scrobbler.h" #include "audio.h" #include "cuesheet.h" +#include "misc.h" #if CONFIG_CODEC == SWCODEC #include "playback.h" #endif @@ -116,14 +117,20 @@ static int replaygain_callback(int action,const struct menu_item_ex *this_item) switch (action) { case ACTION_EXIT_MENUITEM: /* on exit */ - dsp_set_replaygain(); + replaygain_update(); break; } return action; } -MENUITEM_SETTING(replaygain_noclip, &global_settings.replaygain_noclip ,replaygain_callback); -MENUITEM_SETTING(replaygain_type, &global_settings.replaygain_type ,replaygain_callback); -MENUITEM_SETTING(replaygain_preamp, &global_settings.replaygain_preamp ,replaygain_callback); +MENUITEM_SETTING(replaygain_noclip, + &global_settings.replaygain_settings.noclip, + replaygain_callback); +MENUITEM_SETTING(replaygain_type, + &global_settings.replaygain_settings.type, + replaygain_callback); +MENUITEM_SETTING(replaygain_preamp, + &global_settings.replaygain_settings.preamp, + replaygain_callback); MAKE_MENU(replaygain_settings_menu,ID2P(LANG_REPLAYGAIN),0, Icon_NOICON, &replaygain_type, &replaygain_noclip, &replaygain_preamp); @@ -244,9 +251,8 @@ static int playback_callback(int action,const struct menu_item_ex *this_item) if (old_shuffle == global_settings.playlist_shuffle) break; -#if CONFIG_CODEC == SWCODEC - dsp_set_replaygain(); -#endif + replaygain_update(); + if (global_settings.playlist_shuffle) { playlist_randomise(NULL, current_tick, true); diff --git a/apps/misc.c b/apps/misc.c index 3cb314fc51..3bee0772a6 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -953,6 +953,45 @@ void keyclick_click(bool rawbutton, int action) #endif } } + +/* Return the ReplayGain mode adjusted by other relevant settings */ +static int replaygain_setting_mode(int type) +{ + switch (type) + { + case REPLAYGAIN_SHUFFLE: + type = global_settings.playlist_shuffle ? + REPLAYGAIN_TRACK : REPLAYGAIN_ALBUM; + case REPLAYGAIN_ALBUM: + case REPLAYGAIN_TRACK: + case REPLAYGAIN_OFF: + default: + break; + } + + return type; +} + +/* Return the ReplayGain mode adjusted for display purposes */ +int id3_get_replaygain_mode(const struct mp3entry *id3) +{ + if (!id3) + return -1; + + int type = global_settings.replaygain_settings.type; + type = replaygain_setting_mode(type); + + return (type != REPLAYGAIN_TRACK && id3->album_gain != 0) ? + REPLAYGAIN_ALBUM : (id3->track_gain != 0 ? REPLAYGAIN_TRACK : -1); +} + +/* Update DSP's replaygain from global settings */ +void replaygain_update(void) +{ + struct replaygain_settings settings = global_settings.replaygain_settings; + settings.type = replaygain_setting_mode(settings.type); + dsp_replaygain_set_settings(&settings); +} #endif /* CONFIG_CODEC == SWCODEC */ #endif /* !defined(__PCTOOL__) */ diff --git a/apps/misc.h b/apps/misc.h index 8d0953985d..7ca8d75930 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -149,6 +149,16 @@ typedef bool (*keyclick_callback)(int action, void* data); void keyclick_set_callback(keyclick_callback cb, void* data); /* Produce keyclick based upon button and global settings */ void keyclick_click(bool rawbutton, int action); + +/* Return current ReplayGain mode a file should have (REPLAYGAIN_TRACK or + * REPLAYGAIN_ALBUM) if ReplayGain processing is enabled, or -1 if no + * information present. + */ +struct mp3entry; +int id3_get_replaygain_mode(const struct mp3entry *id3); +void replaygain_update(void); +#else +static inline void replaygain_update(void) {} #endif /* CONFIG_CODEC == SWCODEC */ void push_current_activity(enum current_activity screen); diff --git a/apps/settings.c b/apps/settings.c index d481bc5124..e885beb302 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -978,7 +978,7 @@ void settings_apply(bool read_disk) #ifdef HAVE_CROSSFADE audio_set_crossfade(global_settings.crossfade); #endif - dsp_set_replaygain(); + replaygain_update(); dsp_crossfeed_enable(global_settings.crossfeed); dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain); dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain, diff --git a/apps/settings.h b/apps/settings.h index 071346864c..34cc75b116 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -117,9 +117,6 @@ enum { SORT_INTERPRET_AS_DIGIT, SORT_INTERPRET_AS_NUMBER }; /* recursive dir insert options */ enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK }; -/* replaygain types */ -enum { REPLAYGAIN_TRACK = 0, REPLAYGAIN_ALBUM, REPLAYGAIN_SHUFFLE, REPLAYGAIN_OFF }; - /* show path types */ enum { SHOW_PATH_OFF = 0, SHOW_PATH_CURRENT, SHOW_PATH_FULL }; @@ -325,10 +322,7 @@ struct user_settings #endif /* Replaygain */ - bool replaygain_noclip; /* scale to prevent clips */ - int replaygain_type; /* 0=track gain, 1=album gain, 2=track gain if - shuffle is on, album gain otherwise, 4=off */ - int replaygain_preamp; /* scale replaygained tracks by this */ + struct replaygain_settings replaygain_settings; /* Crossfeed */ bool crossfeed; /* enable crossfeed */ diff --git a/apps/settings_list.c b/apps/settings_list.c index 5f4addea2f..c332b47655 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1353,13 +1353,13 @@ const struct settings_list settings[] = { #if CONFIG_CODEC == SWCODEC /* replay gain */ - CHOICE_SETTING(F_SOUNDSETTING, replaygain_type, LANG_REPLAYGAIN_MODE, - REPLAYGAIN_SHUFFLE, "replaygain type", + CHOICE_SETTING(F_SOUNDSETTING, replaygain_settings.type, + LANG_REPLAYGAIN_MODE, REPLAYGAIN_SHUFFLE, "replaygain type", "track,album,track shuffle,off", NULL, 4, ID2P(LANG_TRACK_GAIN), ID2P(LANG_ALBUM_GAIN), ID2P(LANG_SHUFFLE_GAIN), ID2P(LANG_OFF)), - OFFON_SETTING(F_SOUNDSETTING, replaygain_noclip, LANG_REPLAYGAIN_NOCLIP, - false, "replaygain noclip", NULL), - INT_SETTING_NOWRAP(F_SOUNDSETTING, replaygain_preamp, + OFFON_SETTING(F_SOUNDSETTING, replaygain_settings.noclip, + LANG_REPLAYGAIN_NOCLIP, false, "replaygain noclip", NULL), + INT_SETTING_NOWRAP(F_SOUNDSETTING, replaygain_settings.preamp, LANG_REPLAYGAIN_PREAMP, 0, "replaygain preamp", UNIT_DB, -120, 120, 5, db_format, get_dec_talkid, NULL), diff --git a/lib/rbcodec/dsp/dsp_misc.c b/lib/rbcodec/dsp/dsp_misc.c index a98a7e429e..e8bbeb6f5e 100644 --- a/lib/rbcodec/dsp/dsp_misc.c +++ b/lib/rbcodec/dsp/dsp_misc.c @@ -23,12 +23,16 @@ ****************************************************************************/ #include "config.h" #include "sound.h" -#include "settings.h" #include "fixedpoint.h" #include "replaygain.h" #include "dsp_proc_entry.h" #include "dsp_sample_io.h" #include "dsp_misc.h" +#include "pga.h" +#include "channel_mode.h" +#ifdef HAVE_SW_TONE_CONTROLS +#include "tone_controls.h" +#endif #include /** Firmware callback interface **/ @@ -77,43 +81,37 @@ int dsp_callback(int msg, intptr_t param) } /** Replaygain settings **/ -static struct dsp_replay_gains current_rpgains; +static struct replaygain_settings current_settings; +static struct dsp_replay_gains current_gains; -static void dsp_replaygain_update(const struct dsp_replay_gains *gains) +static void dsp_replaygain_update( + const struct replaygain_settings *settings, + const struct dsp_replay_gains *gains) { - if (gains == NULL) - { - /* Use defaults */ - memset(¤t_rpgains, 0, sizeof (current_rpgains)); - gains = ¤t_rpgains; - } - else - { - current_rpgains = *gains; /* Stash settings */ - } + if (settings != ¤t_settings) + current_settings = *settings; /* Stash settings */ + + if (gains != ¤t_gains) + current_gains = *gains; /* Stash gains */ int32_t gain = PGA_UNITY; - if (global_settings.replaygain_type != REPLAYGAIN_OFF || - global_settings.replaygain_noclip) + if (settings->type != REPLAYGAIN_OFF || settings->noclip) { - bool track_mode = - get_replaygain_mode(gains->track_gain != 0, - gains->album_gain != 0) == REPLAYGAIN_TRACK; + bool track_mode = settings->type == REPLAYGAIN_TRACK && + gains->track_gain != 0; int32_t peak = (track_mode || gains->album_peak == 0) ? - gains->track_peak : gains->album_peak; + gains->track_peak : gains->album_peak; - if (global_settings.replaygain_type != REPLAYGAIN_OFF) + if (settings->type != REPLAYGAIN_OFF) { gain = (track_mode || gains->album_gain == 0) ? gains->track_gain : gains->album_gain; - if (global_settings.replaygain_preamp) + if (settings->preamp != 0) { - int32_t preamp = get_replaygain_int( - global_settings.replaygain_preamp * 10); - + int32_t preamp = get_replaygain_int(settings->preamp * 10); gain = fp_mul(gain, preamp, 24); } } @@ -124,7 +122,7 @@ static void dsp_replaygain_update(const struct dsp_replay_gains *gains) gain = PGA_UNITY; } - if (global_settings.replaygain_noclip && peak != 0 && + if (settings->noclip && peak != 0 && fp_mul(gain, peak, 24) >= PGA_UNITY) { gain = fp_div(PGA_UNITY, peak, 24); @@ -135,28 +133,21 @@ static void dsp_replaygain_update(const struct dsp_replay_gains *gains) pga_enable_gain(PGA_REPLAYGAIN, gain != PGA_UNITY); } -int get_replaygain_mode(bool have_track_gain, bool have_album_gain) +void dsp_replaygain_set_settings(const struct replaygain_settings *settings) { - bool track = false; - - switch (global_settings.replaygain_type) - { - case REPLAYGAIN_TRACK: - track = true; - break; - - case REPLAYGAIN_SHUFFLE: - track = global_settings.playlist_shuffle; - break; - } - - return (!track && have_album_gain) ? - REPLAYGAIN_ALBUM : (have_track_gain ? REPLAYGAIN_TRACK : -1); + dsp_replaygain_update(settings, ¤t_gains); } -void dsp_set_replaygain(void) +void dsp_replaygain_set_gains(const struct dsp_replay_gains *gains) { - dsp_replaygain_update(¤t_rpgains); + if (gains == NULL) + { + /* Set defaults */ + gains = ¤t_gains; + memset((void *)gains, 0, sizeof (*gains)); + } + + dsp_replaygain_update(¤t_settings, gains); } @@ -217,7 +208,7 @@ static intptr_t misc_handler_configure(struct dsp_proc_entry *this, #endif value = (intptr_t)NULL; /* Default gains */ case REPLAYGAIN_SET_GAINS: - dsp_replaygain_update((void *)value); + dsp_replaygain_set_gains((void *)value); break; #ifdef HAVE_PITCHSCREEN diff --git a/lib/rbcodec/dsp/dsp_misc.h b/lib/rbcodec/dsp/dsp_misc.h index 74587cbb0e..e0035457f5 100644 --- a/lib/rbcodec/dsp/dsp_misc.h +++ b/lib/rbcodec/dsp/dsp_misc.h @@ -26,6 +26,22 @@ /* Set the tri-pdf dithered output */ void dsp_dither_enable(bool enable); /* in dsp_sample_output.c */ +enum replaygain_types +{ + REPLAYGAIN_TRACK = 0, + REPLAYGAIN_ALBUM, + REPLAYGAIN_SHUFFLE, + REPLAYGAIN_OFF +}; + +struct replaygain_settings +{ + bool noclip; /* scale to prevent clips */ + int type; /* 0=track gain, 1=album gain, 2=track gain if + shuffle is on, album gain otherwise, 4=off */ + int preamp; /* scale replaygained tracks by this */ +}; + /* Structure used with REPLAYGAIN_SET_GAINS message */ #define REPLAYGAIN_SET_GAINS (DSP_PROC_SETTING+DSP_PROC_MISC_HANDLER) struct dsp_replay_gains @@ -36,8 +52,8 @@ struct dsp_replay_gains long album_peak; }; -int get_replaygain_mode(bool have_track_gain, bool have_album_gain); -void dsp_set_replaygain(void); +void dsp_replaygain_set_settings(const struct replaygain_settings *settings); +void dsp_replaygain_set_gains(const struct dsp_replay_gains *gains); #ifdef HAVE_PITCHSCREEN void sound_set_pitch(int32_t ratio);