/* AC-3 */
int ac3_size;
uint8_t * ac3_buf;
+
+ double gain_factor;
} hb_sync_audio_t;
typedef struct
syncAudioClose
};
+#define LVL_PLUS1DB 1.122462048
+
static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
{
hb_work_object_t * w;
w->audio->config.out.mixdown), &error );
sync->data.end_of_input = 0;
}
+
+ sync->gain_factor = pow(LVL_PLUS1DB, w->audio->config.out.gain);
+
hb_list_add( job->list_work, w );
}
int64_t start = (int64_t)sync->next_start;
double duration = buf->stop - buf->start;
- if( audio->config.in.samplerate == audio->config.out.samplerate ||
- audio->config.out.codec == HB_ACODEC_AC3_PASS ||
- audio->config.out.codec == HB_ACODEC_DCA_PASS )
- {
- /*
- * If we don't have to do sample rate conversion or this audio is
- * pass-thru just send the input buffer downstream after adjusting
- * its timestamps to make the output stream continuous.
- */
- }
- else
+ if ( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) )
{
- /* Not pass-thru - do sample rate conversion */
- int count_in, count_out;
- hb_buffer_t * buf_raw = buf;
- int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
- sizeof( float );
+ // Audio is not passthru. Check if we need to modify the audio
+ // in any way.
+ if( audio->config.in.samplerate != audio->config.out.samplerate )
+ {
+ /* do sample rate conversion */
+ int count_in, count_out;
+ hb_buffer_t * buf_raw = buf;
+ int channel_count = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown) *
+ sizeof( float );
- count_in = buf_raw->size / channel_count;
- /*
- * When using stupid rates like 44.1 there will always be some
- * truncation error. E.g., a 1536 sample AC3 frame will turn into a
- * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
- * the error will build up over time and eventually the audio will
- * substantially lag the video. libsamplerate will keep track of the
- * fractional sample & give it to us when appropriate if we give it
- * an extra sample of space in the output buffer.
- */
- count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
+ count_in = buf_raw->size / channel_count;
+ /*
+ * When using stupid rates like 44.1 there will always be some
+ * truncation error. E.g., a 1536 sample AC3 frame will turn into a
+ * 1536*44.1/48.0 = 1411.2 sample frame. If we just truncate the .2
+ * the error will build up over time and eventually the audio will
+ * substantially lag the video. libsamplerate will keep track of the
+ * fractional sample & give it to us when appropriate if we give it
+ * an extra sample of space in the output buffer.
+ */
+ count_out = ( duration * audio->config.out.samplerate ) / 90000 + 1;
- sync->data.input_frames = count_in;
- sync->data.output_frames = count_out;
- sync->data.src_ratio = (double)audio->config.out.samplerate /
- (double)audio->config.in.samplerate;
+ sync->data.input_frames = count_in;
+ sync->data.output_frames = count_out;
+ sync->data.src_ratio = (double)audio->config.out.samplerate /
+ (double)audio->config.in.samplerate;
- buf = hb_buffer_init( count_out * channel_count );
- sync->data.data_in = (float *) buf_raw->data;
- sync->data.data_out = (float *) buf->data;
- if( src_process( sync->state, &sync->data ) )
+ buf = hb_buffer_init( count_out * channel_count );
+ sync->data.data_in = (float *) buf_raw->data;
+ sync->data.data_out = (float *) buf->data;
+ if( src_process( sync->state, &sync->data ) )
+ {
+ /* XXX If this happens, we're screwed */
+ hb_log( "sync: audio 0x%x src_process failed", audio->id );
+ }
+ hb_buffer_close( &buf_raw );
+
+ buf->size = sync->data.output_frames_gen * channel_count;
+ duration = (double)( sync->data.output_frames_gen * 90000 ) /
+ audio->config.out.samplerate;
+ }
+ if( audio->config.out.gain > 0.0 )
{
- /* XXX If this happens, we're screwed */
- hb_log( "sync: audio 0x%x src_process failed", audio->id );
+ int count, ii;
+
+ count = buf->size / sizeof(float);
+ for ( ii = 0; ii < count; ii++ )
+ {
+ double sample;
+
+ sample = (double)*(((float*)buf->data)+ii);
+ sample *= sync->gain_factor;
+ if (sample > 0)
+ sample = MIN(sample, 32767.0);
+ else
+ sample = MAX(sample, -32768.0);
+ *(((float*)buf->data)+ii) = sample;
+ }
}
- hb_buffer_close( &buf_raw );
+ else if( audio->config.out.gain < 0.0 )
+ {
+ int count, ii;
- buf->size = sync->data.output_frames_gen * channel_count;
- duration = (double)( sync->data.output_frames_gen * 90000 ) /
- audio->config.out.samplerate;
+ count = buf->size / sizeof(float);
+ for ( ii = 0; ii < count; ii++ )
+ {
+ double sample;
+
+ sample = (double)*(((float*)buf->data)+ii);
+ sample *= sync->gain_factor;
+ *(((float*)buf->data)+ii) = sample;
+ }
+ }
}
buf->frametype = HB_FRAME_AUDIO;
buf->start = start;
static int num_audio_tracks = 0;
static char * mixdowns = NULL;
static char * dynamic_range_compression = NULL;
+static char * audio_gain = NULL;
static char * atracks = NULL;
static char * arates = NULL;
static char * abitrates = NULL;
}
if( mixdowns ) free( mixdowns );
if( dynamic_range_compression ) free( dynamic_range_compression );
+ if( audio_gain ) free( audio_gain );
if( atracks ) free( atracks );
if( arates ) free( arates );
if( abitrates ) free( abitrates );
}
/* Audio DRC */
+ /* Audio Gain */
+ i = 0;
+ if ( audio_gain )
+ {
+ double gain;
+ char * token = strtok(audio_gain, ",");
+ if (token == NULL)
+ token = audio_gain;
+ while ( token != NULL )
+ {
+ gain = atof(token);
+ audio = hb_list_audio_config_item(job->list_audio, i);
+ if( audio != NULL )
+ {
+ audio->out.gain = gain;
+ if( (++i) >= num_audio_tracks )
+ break; /* We have more inputs than audio tracks, oops */
+ }
+ else
+ {
+ fprintf(stderr, "Ignoring gain, no audio tracks\n");
+ }
+ token = strtok(NULL, ",");
+ }
+ }
+ /* Audio Gain */
+
/* Audio Track Names */
i = 0;
if ( anames )
" making soft sounds louder. Range is 1.0 to 4.0\n"
" (too loud), with 1.5 - 2.5 being a useful range.\n"
" Separated by commas for more than one audio track.\n"
+ " --gain <float> Amplify or attenuate audio before encoding. Does\n"
+ " NOT work with audio passthru (copy). Values are in\n"
+ " dB. Negative values attenuate, positive values\n"
+ " amplify. A 1 dB difference is barely audible.\n"
" -A, --aname <string> Audio track name(s),\n"
" Separated by commas for more than one audio track.\n"
"\n"
#define SCAN_ONLY 276
#define MAIN_FEATURE 277
#define MIN_DURATION 278
+ #define AUDIO_GAIN 279
for( ;; )
{
{ "audio", required_argument, NULL, 'a' },
{ "mixdown", required_argument, NULL, '6' },
{ "drc", required_argument, NULL, 'D' },
+ { "gain", required_argument, NULL, AUDIO_GAIN },
{ "subtitle", required_argument, NULL, 's' },
{ "subtitle-forced", optional_argument, NULL, 'F' },
{ "subtitle-burned", optional_argument, NULL, SUB_BURNED },
dynamic_range_compression = strdup( optarg );
}
break;
+ case AUDIO_GAIN:
+ if( optarg != NULL )
+ {
+ audio_gain = strdup( optarg );
+ }
+ break;
case 's':
subtracks = str_split( optarg, ',' );
break;