From b94cd05820c38f9d152b36fceb8bd1c55d614942 Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Thu, 11 Aug 2011 17:44:28 -0400 Subject: [PATCH 3/6] rbcodec refactoring: replaygain --- apps/gui/skin_engine/skin_tokens.c | 28 +++++++-- apps/menus/playback_menu.c | 1 + apps/misc.c | 19 ++++++ apps/misc.h | 2 + lib/rbcodec/dsp/dsp.c | 118 +++++++++++++++++------------------- lib/rbcodec/dsp/dsp.h | 9 ++- 6 files changed, 106 insertions(+), 71 deletions(-) diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index ec6f606..eb24667 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -721,6 +721,27 @@ static void format_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size) #endif /* HAVE_LCD_CHARCELLS */ +#if CONFIG_CODEC == SWCODEC +static int get_replaygain_mode(struct mp3entry *id3) +{ + if (UNLIKELY(!id3)) + return -1; + + int type; + bool have_track_gain = id3->track_gain != 0; + bool have_album_gain = id3->album_gain != 0; + + bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK) + || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE) + && global_settings.playlist_shuffle)); + + type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM + : have_track_gain ? REPLAYGAIN_TRACK : -1; + + return type; +} +#endif + /* Don't inline this; it was broken out of get_token_value to reduce stack * usage. */ @@ -1304,12 +1325,7 @@ const char *get_token_value(struct gui_wps *gwps, 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 = get_replaygain_mode(id3); if (type < 0) val = 6; /* no tag */ diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c index 1b1a13a..0087bd3 100644 --- a/apps/menus/playback_menu.c +++ b/apps/menus/playback_menu.c @@ -35,6 +35,7 @@ #include "scrobbler.h" #include "audio.h" #include "cuesheet.h" +#include "misc.h" #if CONFIG_CODEC == SWCODEC #include "playback.h" #endif diff --git a/apps/misc.c b/apps/misc.c index 69c62da..1138642 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -56,6 +56,7 @@ #include "playlist.h" #include "yesno.h" #include "viewport.h" +#include "dsp.h" #include "debug.h" @@ -793,6 +794,24 @@ void setvol(void) settings_save(); } +#if CONFIG_CODEC == SWCODEC +void dsp_set_replaygain(void) +{ + int type; + if (global_settings.replaygain_type == REPLAYGAIN_OFF) + type = RBCODEC_REPLAYGAIN_NONE; + else if (global_settings.replaygain_type == REPLAYGAIN_ALBUM) + type = RBCODEC_REPLAYGAIN_ALBUM; + else if (global_settings.replaygain_type == REPLAYGAIN_TRACK) + type = RBCODEC_REPLAYGAIN_TRACK; + else /* REPLAYGAIN_SHUFFLE */ + type = global_settings.playlist_shuffle ? REPLAYGAIN_TRACK + : REPLAYGAIN_ALBUM; + rbcodec_dsp_set_replaygain(type, global_settings.replaygain_noclip, + global_settings.replaygain_preamp); +} +#endif + char* strrsplt(char* str, int c) { char* s = strrchr(str, c); diff --git a/apps/misc.h b/apps/misc.h index bfe6e5b..d6c55f3 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -78,6 +78,8 @@ void check_bootfile(bool do_rolo); /* check range, set volume and save settings */ void setvol(void); +void dsp_set_replaygain(void); + #ifdef HAVE_LCD_COLOR int hex_to_rgb(const char* hex, int* color); #endif diff --git a/lib/rbcodec/dsp/dsp.c b/lib/rbcodec/dsp/dsp.c index c76bfe9..9aba93a 100644 --- a/lib/rbcodec/dsp/dsp.c +++ b/lib/rbcodec/dsp/dsp.c @@ -233,6 +233,9 @@ static long track_peak; static long album_peak; static long replaygain; static bool crossfeed_enabled; +static int replaygain_type; +static bool replaygain_noclip; +static int replaygain_preamp; #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO]) #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE]) @@ -271,7 +274,6 @@ static int32_t release_gain IBSS_ATTR; /* S7.24 format */ #define UNITY (1L << 24) /* unity gain in S7.24 format */ static void compressor_process(int count, int32_t *buf[]); - /* Clip sample to signed 16 bit range */ static inline int32_t clip_sample_16(int32_t sample) { @@ -1187,6 +1189,52 @@ int dsp_callback(int msg, intptr_t param) } #endif +static void dsp_recalc_replaygain(void) +{ + long gain = 0; + + new_gain = false; + + if ((replaygain_type != RBCODEC_REPLAYGAIN_NONE) || replaygain_noclip) + { + bool track_mode = replaygain_type == RBCODEC_REPLAYGAIN_TRACK; + long peak = (track_mode || !album_peak) ? track_peak : album_peak; + + if (replaygain_type != RBCODEC_REPLAYGAIN_NONE) + { + gain = (track_mode || !album_gain) ? track_gain : album_gain; + + if (replaygain_preamp) + { + long preamp = get_replaygain_int(replaygain_preamp * 10); + gain = (long) (((int64_t) gain * preamp) >> 24); + } + } + + if (gain == 0) + { + /* So that noclip can work even with no gain information. */ + gain = DEFAULT_GAIN; + } + + if (replaygain_noclip && (peak != 0) + && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN)) + { + gain = (((int64_t) DEFAULT_GAIN << 24) / peak); + } + + if (gain == DEFAULT_GAIN) + { + /* Nothing to do, disable processing. */ + gain = 0; + } + } + + /* Store in S7.24 format to simplify calculations. */ + replaygain = gain; + set_gain(&AUDIO_DSP); +} + /* Process and convert src audio to dst based on the DSP configuration, * reading count number of audio samples. dst is assumed to be large * enough; use dsp_output_count() to get the required number. src is an @@ -1208,7 +1256,7 @@ int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count) #endif if (new_gain) - dsp_set_replaygain(); /* Gain has changed */ + dsp_recalc_replaygain(); /* Gain has changed */ /* Perform at least one yield before starting */ yield(); @@ -1483,68 +1531,12 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value) return 1; } -int get_replaygain_mode(bool have_track_gain, bool have_album_gain) +void rbcodec_dsp_set_replaygain(int type, bool noclip, int preamp) { - int type; - - bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK) - || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE) - && global_settings.playlist_shuffle)); - - type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM - : have_track_gain ? REPLAYGAIN_TRACK : -1; - - return type; -} - -void dsp_set_replaygain(void) -{ - long gain = 0; - - new_gain = false; - - if ((global_settings.replaygain_type != REPLAYGAIN_OFF) || - global_settings.replaygain_noclip) - { - bool track_mode = get_replaygain_mode(track_gain != 0, - album_gain != 0) == REPLAYGAIN_TRACK; - long peak = (track_mode || !album_peak) ? track_peak : album_peak; - - if (global_settings.replaygain_type != REPLAYGAIN_OFF) - { - gain = (track_mode || !album_gain) ? track_gain : album_gain; - - if (global_settings.replaygain_preamp) - { - long preamp = get_replaygain_int( - global_settings.replaygain_preamp * 10); - - gain = (long) (((int64_t) gain * preamp) >> 24); - } - } - - if (gain == 0) - { - /* So that noclip can work even with no gain information. */ - gain = DEFAULT_GAIN; - } - - if (global_settings.replaygain_noclip && (peak != 0) - && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN)) - { - gain = (((int64_t) DEFAULT_GAIN << 24) / peak); - } - - if (gain == DEFAULT_GAIN) - { - /* Nothing to do, disable processing. */ - gain = 0; - } - } - - /* Store in S7.24 format to simplify calculations. */ - replaygain = gain; - set_gain(&AUDIO_DSP); + replaygain_type = type; + replaygain_noclip = noclip; + replaygain_preamp = preamp; + dsp_recalc_replaygain(); } /** SET COMPRESSOR diff --git a/lib/rbcodec/dsp/dsp.h b/lib/rbcodec/dsp/dsp.h index 60a8b06..e79b8be 100644 --- a/lib/rbcodec/dsp/dsp.h +++ b/lib/rbcodec/dsp/dsp.h @@ -57,6 +57,12 @@ enum DSP_CROSSFEED }; +enum { + RBCODEC_REPLAYGAIN_NONE, + RBCODEC_REPLAYGAIN_TRACK, + RBCODEC_REPLAYGAIN_ALBUM, +}; + struct dsp_config; int dsp_process(struct dsp_config *dsp, char *dest, @@ -65,8 +71,7 @@ int dsp_input_count(struct dsp_config *dsp, int count); int dsp_output_count(struct dsp_config *dsp, int count); intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value); -int get_replaygain_mode(bool have_track_gain, bool have_album_gain); -void dsp_set_replaygain(void); +void rbcodec_dsp_set_replaygain(int type, bool noclip, int preamp); void dsp_set_crossfeed(bool enable); void dsp_set_crossfeed_direct_gain(int gain); void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, -- 1.7.6