diff options
author | jstebbins <[email protected]> | 2012-08-01 23:05:00 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2012-08-01 23:05:00 +0000 |
commit | ad257c9dac38fe3f7502b1058247b4458465c0a8 (patch) | |
tree | c142e7b68aa0406b64e77a7f844b0622172fc5c9 | |
parent | dbec0d898d37f3b9a1fed8158543115fbdb3ce91 (diff) |
libhb: Allow control of audio mix normalization
Since switching to libavresample for audio mixing, our output
volume levels have been reduced because libavresample
does mix level normalization by default. This change
applies a patch to libav to allow us to disable this behavior
and adds a new field to hb_audio_config_t to allow the
hb frontends to control this feature.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4884 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | contrib/ffmpeg/A06-mix-normalization.patch | 39 | ||||
-rw-r--r-- | libhb/audio_resample.c | 21 | ||||
-rw-r--r-- | libhb/audio_resample.h | 4 | ||||
-rw-r--r-- | libhb/common.c | 3 | ||||
-rw-r--r-- | libhb/common.h | 1 | ||||
-rw-r--r-- | libhb/decavcodec.c | 3 | ||||
-rw-r--r-- | libhb/declpcm.c | 3 | ||||
-rw-r--r-- | libhb/encavcodecaudio.c | 2 | ||||
-rw-r--r-- | test/test.c | 48 |
9 files changed, 112 insertions, 12 deletions
diff --git a/contrib/ffmpeg/A06-mix-normalization.patch b/contrib/ffmpeg/A06-mix-normalization.patch new file mode 100644 index 000000000..06fb2754c --- /dev/null +++ b/contrib/ffmpeg/A06-mix-normalization.patch @@ -0,0 +1,39 @@ +diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c +index 2c2a356..25f9f98 100644 +--- a/libavresample/audio_mix.c ++++ b/libavresample/audio_mix.c +@@ -327,7 +327,9 @@ int ff_audio_mix_init(AVAudioResampleContext *avr) + avr->out_channel_layout, + avr->center_mix_level, + avr->surround_mix_level, +- avr->lfe_mix_level, 1, matrix_dbl, ++ avr->lfe_mix_level, ++ avr->normalize_mix_level, ++ matrix_dbl, + avr->in_channels, + avr->matrix_encoding); + if (ret < 0) { +diff --git a/libavresample/internal.h b/libavresample/internal.h +index 7b7648f..006b6fd 100644 +--- a/libavresample/internal.h ++++ b/libavresample/internal.h +@@ -45,6 +45,7 @@ struct AVAudioResampleContext { + double center_mix_level; /**< center mix level */ + double surround_mix_level; /**< surround mix level */ + double lfe_mix_level; /**< lfe mix level */ ++ int normalize_mix_level; /**< enable mix level normalization */ + int force_resampling; /**< force resampling */ + int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */ + int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */ +diff --git a/libavresample/options.c b/libavresample/options.c +index 02e1f86..e7e0c27 100644 +--- a/libavresample/options.c ++++ b/libavresample/options.c +@@ -47,6 +47,7 @@ static const AVOption options[] = { + { "center_mix_level", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM }, + { "surround_mix_level", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_DOUBLE, { M_SQRT1_2 }, -32.0, 32.0, PARAM }, + { "lfe_mix_level", "LFE Mix Level", OFFSET(lfe_mix_level), AV_OPT_TYPE_DOUBLE, { 0.0 }, -32.0, 32.0, PARAM }, ++ { "normalize_mix_level", "Normalize Mix Level", OFFSET(normalize_mix_level), AV_OPT_TYPE_INT, { 1 }, 0, 1, PARAM }, + { "force_resampling", "Force Resampling", OFFSET(force_resampling), AV_OPT_TYPE_INT, { 0 }, 0, 1, PARAM }, + { "filter_size", "Resampling Filter Size", OFFSET(filter_size), AV_OPT_TYPE_INT, { 16 }, 0, 32, /* ??? */ PARAM }, + { "phase_shift", "Resampling Phase Shift", OFFSET(phase_shift), AV_OPT_TYPE_INT, { 10 }, 0, 30, /* ??? */ PARAM }, diff --git a/libhb/audio_resample.c b/libhb/audio_resample.c index 3f67da87c..ea09b38a2 100644 --- a/libhb/audio_resample.c +++ b/libhb/audio_resample.c @@ -13,20 +13,23 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fmt, uint64_t output_channel_layout, - enum AVMatrixEncoding matrix_encoding) + enum AVMatrixEncoding matrix_encoding, + int normalize_mix_level) { hb_audio_resample_t *resample = malloc(sizeof(hb_audio_resample_t)); if (resample == NULL) return NULL; - resample->out.sample_fmt = output_sample_fmt; - resample->out.sample_size = av_get_bytes_per_sample(output_sample_fmt); - resample->out.channel_layout = output_channel_layout; - resample->out.channels = + resample->out.sample_fmt = output_sample_fmt; + resample->out.sample_size = + av_get_bytes_per_sample(output_sample_fmt); + resample->out.channel_layout = output_channel_layout; + resample->out.channels = av_get_channel_layout_nb_channels(output_channel_layout); - resample->out.matrix_encoding = matrix_encoding; - resample->resample_needed = 0; - resample->avresample = NULL; + resample->out.matrix_encoding = matrix_encoding; + resample->out.normalize_mix_level = normalize_mix_level; + resample->resample_needed = 0; + resample->avresample = NULL; return resample; } @@ -72,6 +75,8 @@ int hb_audio_resample_update(hb_audio_resample_t *resample, resample->out.channel_layout, 0); av_opt_set_int(resample->avresample, "matrix_encoding", resample->out.matrix_encoding, 0); + av_opt_set_int(resample->avresample, "normalize_mix_level", + resample->out.normalize_mix_level, 0); } else if (resample_changed) { diff --git a/libhb/audio_resample.h b/libhb/audio_resample.h index 5982905e6..4b1586e73 100644 --- a/libhb/audio_resample.h +++ b/libhb/audio_resample.h @@ -39,6 +39,7 @@ typedef struct int channels; int linesize; int sample_size; + int normalize_mix_level; uint64_t channel_layout; enum AVSampleFormat sample_fmt; enum AVMatrixEncoding matrix_encoding; @@ -52,7 +53,8 @@ typedef struct */ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fmt, uint64_t output_channel_layout, - enum AVMatrixEncoding matrix_encoding); + enum AVMatrixEncoding matrix_encoding, + int normalize_mix_level); /* Update an hb_audio_resample_t, setting the input sample characteristics. * diff --git a/libhb/common.c b/libhb/common.c index 13a2e1d95..9ff9f44a3 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -1637,6 +1637,7 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg) audiocfg->out.mixdown = HB_INVALID_AMIXDOWN; audiocfg->out.dynamic_range_compression = 0; audiocfg->out.gain = 0; + audiocfg->out.normalize_mix_level = 0; audiocfg->out.name = NULL; } @@ -1684,6 +1685,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) audio->config.out.mixdown = HB_AMIXDOWN_NONE; audio->config.out.dynamic_range_compression = 0; audio->config.out.gain = 0; + audio->config.out.normalize_mix_level = 0; audio->config.out.compression_level = -1; audio->config.out.quality = HB_INVALID_AUDIO_QUALITY; } @@ -1698,6 +1700,7 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg) audio->config.out.dynamic_range_compression = audiocfg->out.dynamic_range_compression; audio->config.out.mixdown = audiocfg->out.mixdown; audio->config.out.gain = audiocfg->out.gain; + audio->config.out.normalize_mix_level = audiocfg->out.normalize_mix_level; } if (audiocfg->out.name && *audiocfg->out.name) { diff --git a/libhb/common.h b/libhb/common.h index 5b2fc08fa..1650f8002 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -452,6 +452,7 @@ struct hb_audio_config_s float compression_level; /* Output compression level (encoder-specific) */ double dynamic_range_compression; /* Amount of DRC applied to this track */ double gain; /* Gain (in dB), negative is quieter */ + int normalize_mix_level; /* mix level normalization (boolean) */ char * name; /* Output track name */ } out; diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 17f814d61..934f7611e 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -192,7 +192,8 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job ) int mode; uint64_t layout = hb_ff_mixdown_xlat(w->audio->config.out.mixdown, &mode); - pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode); + pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode, + w->audio->config.out.normalize_mix_level); if (pv->resample == NULL) { hb_error("decavcodecaInit: hb_audio_resample_init() failed"); diff --git a/libhb/declpcm.c b/libhb/declpcm.c index e48bf5db7..0d4e449d1 100644 --- a/libhb/declpcm.c +++ b/libhb/declpcm.c @@ -164,7 +164,8 @@ static int declpcmInit( hb_work_object_t * w, hb_job_t * job ) int mode; uint64_t layout = hb_ff_mixdown_xlat(w->audio->config.out.mixdown, &mode); - pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode); + pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode, + w->audio->config.out.normalize_mix_level); if (pv->resample == NULL) { hb_error("declpcmInit: hb_audio_resample_init() failed"); diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c index 28eb0d9ae..ef5297cca 100644 --- a/libhb/encavcodecaudio.c +++ b/libhb/encavcodecaudio.c @@ -119,7 +119,7 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job) // sample_fmt conversion pv->resample = hb_audio_resample_init(context->sample_fmt, context->channel_layout, - AV_MATRIX_ENCODING_NONE); + AV_MATRIX_ENCODING_NONE, 0); if (hb_audio_resample_update(pv->resample, AV_SAMPLE_FMT_FLT, context->channel_layout, context->channels)) { diff --git a/test/test.c b/test/test.c index 5d61b579c..b59534d44 100644 --- a/test/test.c +++ b/test/test.c @@ -71,6 +71,7 @@ static int allowed_audio_copy = -1; static char * mixdowns = NULL; static char * dynamic_range_compression = NULL; static char * audio_gain = NULL; +static char ** normalize_mix_level = NULL; static char * atracks = NULL; static char * arates = NULL; static char ** abitrates = NULL; @@ -2096,6 +2097,41 @@ static int HandleEvents( hb_handle_t * h ) } /* Audio Gain */ + /* Audio Mix Normalization */ + i = 0; + int norm = 0; + if( normalize_mix_level ) + { + for ( i = 0; normalize_mix_level[i] != NULL && i < num_audio_tracks; i++ ) + { + char * token = normalize_mix_level[i]; + norm = atoi(token); + audio = hb_list_audio_config_item(job->list_audio, i); + + if( audio != NULL ) + { + audio->out.normalize_mix_level = norm; + } + else + { + fprintf(stderr, "Ignoring normalization %d, no audio tracks\n", norm); + } + } + } + if (i < num_audio_tracks && i == 1) + { + /* We have fewer inputs than audio tracks, + * and we only have one input, use + * that for all tracks. + */ + for (; i < num_audio_tracks; i++) + { + audio = hb_list_audio_config_item(job->list_audio, i); + audio->out.normalize_mix_level = norm; + } + } + /* Audio Mix Normalization */ + /* Audio Track Names */ if ( anames ) { @@ -2883,6 +2919,10 @@ static void ShowHelp() " Separated by commas for more than one audio track.\n" " (mono/stereo/dpl1/dpl2/6ch, default: up to 6ch for ac3,\n" " up to dpl2 for other encoders)\n" + " --normalize-mix Normalize audio mix levels to prevent clipping.\n" + " <string> Separated by commas for more than one audio track.\n" + " 0 = Disable Normalization (default)\n" + " 1 = Enable Normalization\n" " -R, --arate Set audio samplerate(s) (" ); for( i = 0; i < hb_audio_rates_count; i++ ) { @@ -3186,6 +3226,7 @@ static int ParseOptions( int argc, char ** argv ) #define X264_PRESET 284 #define X264_TUNE 285 #define H264_LEVEL 286 + #define NORMALIZE_MIX 287 for( ;; ) { @@ -3212,6 +3253,7 @@ static int ParseOptions( int argc, char ** argv ) { "markers", optional_argument, NULL, 'm' }, { "audio", required_argument, NULL, 'a' }, { "mixdown", required_argument, NULL, '6' }, + { "normalize-mix", required_argument, NULL, NORMALIZE_MIX }, { "drc", required_argument, NULL, 'D' }, { "gain", required_argument, NULL, AUDIO_GAIN }, { "subtitle", required_argument, NULL, 's' }, @@ -3430,6 +3472,12 @@ static int ParseOptions( int argc, char ** argv ) audio_gain = strdup( optarg ); } break; + case NORMALIZE_MIX: + if( optarg != NULL ) + { + normalize_mix_level = str_split( optarg, ',' ); + } + break; case 's': subtracks = str_split( optarg, ',' ); break; |