mixramp: Adjust MixRamp threshold to account for ReplayGain.
This commit is contained in:
parent
eb5208c4f9
commit
0ac5b6e613
@ -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,
|
|||||||
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;
|
|||||||
* @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;
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
} 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,
|
|||||||
* @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,
|
|||||||
* 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)
|
|||||||
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 {
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user