Commit 0ac5b6e6 authored by Tim Phipps's avatar Tim Phipps Committed by Avuton Olrich

mixramp: Adjust MixRamp threshold to account for ReplayGain.

parent eb5208c4
...@@ -91,6 +91,7 @@ static float mixramp_interpolate(char *ramp_list, float required_db) ...@@ -91,6 +91,7 @@ static float mixramp_interpolate(char *ramp_list, float required_db)
unsigned cross_fade_calc(float duration, float total_time, unsigned cross_fade_calc(float duration, float total_time,
float mixramp_db, float mixramp_delay, float mixramp_db, float mixramp_delay,
float replay_gain_db, float replay_gain_prev_db,
char *mixramp_start, char *mixramp_prev_end, char *mixramp_start, char *mixramp_prev_end,
const struct audio_format *af, const struct audio_format *af,
const struct audio_format *old_format, const struct audio_format *old_format,
...@@ -113,10 +114,9 @@ unsigned cross_fade_calc(float duration, float total_time, ...@@ -113,10 +114,9 @@ unsigned cross_fade_calc(float duration, float total_time,
if (isnan(mixramp_delay) || !(mixramp_start) || !(mixramp_prev_end)) { if (isnan(mixramp_delay) || !(mixramp_start) || !(mixramp_prev_end)) {
chunks = (chunks_f * duration + 0.5); chunks = (chunks_f * duration + 0.5);
} else { } else {
/* Calculate mixramp overlap. /* Calculate mixramp overlap. */
* FIXME factor in ReplayGain for both songs. */ mixramp_overlap = mixramp_interpolate(mixramp_start, mixramp_db - replay_gain_db)
mixramp_overlap = mixramp_interpolate(mixramp_start, mixramp_db) + mixramp_interpolate(mixramp_prev_end, mixramp_db - replay_gain_prev_db);
+ mixramp_interpolate(mixramp_prev_end, mixramp_db);
if (!isnan(mixramp_overlap) && (mixramp_delay <= mixramp_overlap)) { if (!isnan(mixramp_overlap) && (mixramp_delay <= mixramp_overlap)) {
chunks = (chunks_f * (mixramp_overlap - mixramp_delay)); chunks = (chunks_f * (mixramp_overlap - mixramp_delay));
g_debug("will overlap %d chunks, %fs", chunks, g_debug("will overlap %d chunks, %fs", chunks,
......
...@@ -30,6 +30,8 @@ struct music_chunk; ...@@ -30,6 +30,8 @@ struct music_chunk;
* @param total_time total_time the duration of the new song * @param total_time total_time the duration of the new song
* @param mixramp_db the current mixramp_db setting * @param mixramp_db the current mixramp_db setting
* @param mixramp_delay the current mixramp_delay setting * @param mixramp_delay the current mixramp_delay setting
* @param replay_gain_db the ReplayGain adjustment used for this song
* @param replay_gain_prev_db the ReplayGain adjustment used on the last song
* @param mixramp_start the next songs mixramp_start tag * @param mixramp_start the next songs mixramp_start tag
* @param mixramp_prev_end the last songs mixramp_end setting * @param mixramp_prev_end the last songs mixramp_end setting
* @param af the audio format of the new song * @param af the audio format of the new song
...@@ -40,6 +42,7 @@ struct music_chunk; ...@@ -40,6 +42,7 @@ struct music_chunk;
*/ */
unsigned cross_fade_calc(float duration, float total_time, unsigned cross_fade_calc(float duration, float total_time,
float mixramp_db, float mixramp_delay, float mixramp_db, float mixramp_delay,
float replay_gain_db, float replay_gain_prev_db,
char *mixramp_start, char *mixramp_prev_end, char *mixramp_start, char *mixramp_prev_end,
const struct audio_format *af, const struct audio_format *af,
const struct audio_format *old_format, const struct audio_format *old_format,
......
...@@ -114,6 +114,7 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, ...@@ -114,6 +114,7 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
struct replay_gain_info rgi; struct replay_gain_info rgi;
char *mixramp_start; char *mixramp_start;
char *mixramp_end; char *mixramp_end;
float replay_gain_db = 0;
switch (block->type) { switch (block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
...@@ -122,10 +123,11 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, ...@@ -122,10 +123,11 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if (flac_parse_replay_gain(&rgi, block)) if (flac_parse_replay_gain(&rgi, block))
decoder_replay_gain(data->decoder, &rgi); replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
if (flac_parse_mixramp(&mixramp_start, &mixramp_end, block)) { if (flac_parse_mixramp(&mixramp_start, &mixramp_end, block)) {
g_debug("setting mixramp_tags"); g_debug("setting mixramp_tags");
decoder_mixramp(data->decoder, mixramp_start, mixramp_end); decoder_mixramp(data->decoder, replay_gain_db,
mixramp_start, mixramp_end);
} }
if (data->tag != NULL) if (data->tag != NULL)
......
...@@ -446,13 +446,16 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, ...@@ -446,13 +446,16 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
struct replay_gain_info rgi; struct replay_gain_info rgi;
char *mixramp_start; char *mixramp_start;
char *mixramp_end; char *mixramp_end;
float replay_gain_db = 0;
if (parse_id3_replay_gain_info(&rgi, id3_tag)) { if (parse_id3_replay_gain_info(&rgi, id3_tag)) {
decoder_replay_gain(data->decoder, &rgi); replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
data->found_replay_gain = true; data->found_replay_gain = true;
} }
if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) { if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) {
g_debug("setting mixramp_tags"); g_debug("setting mixramp_tags");
decoder_mixramp(data->decoder, mixramp_start, mixramp_end); decoder_mixramp(data->decoder, replay_gain_db,
mixramp_start, mixramp_end);
} }
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "buffer.h" #include "buffer.h"
#include "pipe.h" #include "pipe.h"
#include "chunk.h" #include "chunk.h"
#include "replay_gain_config.h"
#include <glib.h> #include <glib.h>
...@@ -403,10 +404,11 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is, ...@@ -403,10 +404,11 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
return cmd; return cmd;
} }
void float
decoder_replay_gain(struct decoder *decoder, decoder_replay_gain(struct decoder *decoder,
const struct replay_gain_info *replay_gain_info) const struct replay_gain_info *replay_gain_info)
{ {
float return_db = 0;
assert(decoder != NULL); assert(decoder != NULL);
if (replay_gain_info != NULL) { if (replay_gain_info != NULL) {
...@@ -414,6 +416,13 @@ decoder_replay_gain(struct decoder *decoder, ...@@ -414,6 +416,13 @@ decoder_replay_gain(struct decoder *decoder,
if (++serial == 0) if (++serial == 0)
serial = 1; serial = 1;
if (REPLAY_GAIN_OFF != replay_gain_mode) {
return_db = 20.0 * log10f(
replay_gain_tuple_scale(
&replay_gain_info->tuples[replay_gain_mode],
replay_gain_preamp));
}
decoder->replay_gain_info = *replay_gain_info; decoder->replay_gain_info = *replay_gain_info;
decoder->replay_gain_serial = serial; decoder->replay_gain_serial = serial;
...@@ -426,16 +435,19 @@ decoder_replay_gain(struct decoder *decoder, ...@@ -426,16 +435,19 @@ decoder_replay_gain(struct decoder *decoder,
} }
} else } else
decoder->replay_gain_serial = 0; decoder->replay_gain_serial = 0;
return return_db;
} }
void void
decoder_mixramp(struct decoder *decoder, decoder_mixramp(struct decoder *decoder, float replay_gain_db,
char *mixramp_start, char *mixramp_end) char *mixramp_start, char *mixramp_end)
{ {
assert(decoder != NULL); assert(decoder != NULL);
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
assert(dc != NULL); assert(dc != NULL);
dc->replay_gain_db = replay_gain_db;
dc_mixramp_start(dc, mixramp_start); dc_mixramp_start(dc, mixramp_start);
dc_mixramp_end(dc, mixramp_end); dc_mixramp_end(dc, mixramp_end);
} }
...@@ -152,8 +152,9 @@ decoder_tag(struct decoder *decoder, struct input_stream *is, ...@@ -152,8 +152,9 @@ decoder_tag(struct decoder *decoder, struct input_stream *is,
* @param decoder the decoder object * @param decoder the decoder object
* @param rgi the replay_gain_info object; may be NULL to invalidate * @param rgi the replay_gain_info object; may be NULL to invalidate
* the previous replay gain values * the previous replay gain values
* @return the replay gain adjustment used
*/ */
void float
decoder_replay_gain(struct decoder *decoder, decoder_replay_gain(struct decoder *decoder,
const struct replay_gain_info *replay_gain_info); const struct replay_gain_info *replay_gain_info);
...@@ -161,11 +162,12 @@ decoder_replay_gain(struct decoder *decoder, ...@@ -161,11 +162,12 @@ decoder_replay_gain(struct decoder *decoder,
* Store MixRamp tags. * Store MixRamp tags.
* *
* @param decoder the decoder object * @param decoder the decoder object
* @param replay_gain_db the ReplayGain adjustment used for this song
* @param mixramp_start the mixramp_start tag; may be NULL to invalidate * @param mixramp_start the mixramp_start tag; may be NULL to invalidate
* @param mixramp_end the mixramp_end tag; may be NULL to invalidate * @param mixramp_end the mixramp_end tag; may be NULL to invalidate
*/ */
void void
decoder_mixramp(struct decoder *decoder, decoder_mixramp(struct decoder *decoder, float replay_gain_db,
char *mixramp_start, char *mixramp_end); char *mixramp_start, char *mixramp_end);
#endif #endif
...@@ -38,6 +38,8 @@ dc_init(struct decoder_control *dc) ...@@ -38,6 +38,8 @@ dc_init(struct decoder_control *dc)
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->command = DECODE_COMMAND_NONE; dc->command = DECODE_COMMAND_NONE;
dc->replay_gain_db = 0;
dc->replay_gain_prev_db = 0;
dc->mixramp_start = NULL; dc->mixramp_start = NULL;
dc->mixramp_end = NULL; dc->mixramp_end = NULL;
dc->mixramp_prev_end = NULL; dc->mixramp_prev_end = NULL;
......
...@@ -90,6 +90,8 @@ struct decoder_control { ...@@ -90,6 +90,8 @@ struct decoder_control {
*/ */
struct music_pipe *pipe; struct music_pipe *pipe;
float replay_gain_db;
float replay_gain_prev_db;
char *mixramp_start; char *mixramp_start;
char *mixramp_end; char *mixramp_end;
char *mixramp_prev_end; char *mixramp_prev_end;
......
...@@ -438,6 +438,8 @@ decoder_task(gpointer arg) ...@@ -438,6 +438,8 @@ decoder_task(gpointer arg)
dc_mixramp_start(dc, NULL); dc_mixramp_start(dc, NULL);
dc_mixramp_prev_end(dc, dc->mixramp_end); dc_mixramp_prev_end(dc, dc->mixramp_end);
dc->mixramp_end = NULL; /* Don't free, it's copied above. */ dc->mixramp_end = NULL; /* Don't free, it's copied above. */
dc->replay_gain_prev_db = dc->replay_gain_db;
dc->replay_gain_db = 0;
/* fall through */ /* fall through */
......
...@@ -895,6 +895,8 @@ static void do_play(struct decoder_control *dc) ...@@ -895,6 +895,8 @@ static void do_play(struct decoder_control *dc)
cross_fade_calc(pc.cross_fade_seconds, dc->total_time, cross_fade_calc(pc.cross_fade_seconds, dc->total_time,
pc.mixramp_db, pc.mixramp_db,
pc.mixramp_delay_seconds, pc.mixramp_delay_seconds,
dc->replay_gain_db,
dc->replay_gain_prev_db,
dc->mixramp_start, dc->mixramp_start,
dc->mixramp_prev_end, dc->mixramp_prev_end,
&dc->out_audio_format, &dc->out_audio_format,
......
...@@ -115,14 +115,16 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, ...@@ -115,14 +115,16 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder,
return DECODE_COMMAND_NONE; return DECODE_COMMAND_NONE;
} }
void float
decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info) G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info)
{ {
return 0.0;
} }
void void
decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED float replay_gain_db,
char *mixramp_start, char *mixramp_end) char *mixramp_start, char *mixramp_end)
{ {
g_free(mixramp_start); g_free(mixramp_start);
......
...@@ -136,14 +136,16 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, ...@@ -136,14 +136,16 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder,
return DECODE_COMMAND_NONE; return DECODE_COMMAND_NONE;
} }
void float
decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder, decoder_replay_gain(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info) G_GNUC_UNUSED const struct replay_gain_info *replay_gain_info)
{ {
return 0.0;
} }
void void
decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder, decoder_mixramp(G_GNUC_UNUSED struct decoder *decoder,
G_GNUC_UNUSED float replay_gain_db,
char *mixramp_start, char *mixramp_end) char *mixramp_start, char *mixramp_end)
{ {
g_free(mixramp_start); g_free(mixramp_start);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment