Commit b97b9eb9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: move replay gain handling to dec and mixer

This had no relations with the audio input anymore. In particular,
there is no need to reinitialize this when the input is restarted.
parent a07a0b5e
...@@ -51,7 +51,6 @@ block_t *aout_FilterBufferNew( filter_t *, int ); ...@@ -51,7 +51,6 @@ block_t *aout_FilterBufferNew( filter_t *, int );
/** an input stream for the audio output */ /** an input stream for the audio output */
struct aout_input_t struct aout_input_t
{ {
vlc_atomic_t multiplier; /**< Replay gain multiplier */
unsigned samplerate; /**< Input sample rate */ unsigned samplerate; /**< Input sample rate */
/* pre-filters */ /* pre-filters */
...@@ -67,9 +66,6 @@ struct aout_input_t ...@@ -67,9 +66,6 @@ struct aout_input_t
mtime_t i_resamp_start_date; mtime_t i_resamp_start_date;
int i_resamp_start_drift; int i_resamp_start_drift;
/* Mixer information */
audio_replay_gain_t replay_gain;
/* If b_error == 1, there is no input pipeline. */ /* If b_error == 1, there is no input pipeline. */
bool b_error; bool b_error;
...@@ -100,7 +96,13 @@ typedef struct ...@@ -100,7 +96,13 @@ typedef struct
vlc_mutex_t lock; vlc_mutex_t lock;
float multiplier; /**< Software volume amplification multiplier */ float multiplier; /**< Software volume amplification multiplier */
struct audio_mixer *mixer; /**< Software volume plugin */ struct audio_mixer *mixer; /**< Software volume plugin */
} volume; /**< Volume and gain management (FIXME: input manager?) */ } volume;
struct
{
vlc_atomic_t multiplier;
audio_replay_gain_t data;
} gain;
audio_sample_format_t mixer_format; audio_sample_format_t mixer_format;
audio_sample_format_t input_format; audio_sample_format_t input_format;
...@@ -134,7 +136,6 @@ int aout_InputNew(audio_output_t *, const audio_sample_format_t *, ...@@ -134,7 +136,6 @@ int aout_InputNew(audio_output_t *, const audio_sample_format_t *,
int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ); int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input );
block_t *aout_InputPlay( audio_output_t *p_aout, aout_input_t *p_input, block_t *aout_InputPlay( audio_output_t *p_aout, aout_input_t *p_input,
block_t *p_buffer, int i_input_rate, date_t * ); block_t *p_buffer, int i_input_rate, date_t * );
float aout_InputGetMultiplier(const aout_input_t *);
/* From filters.c : */ /* From filters.c : */
int aout_FiltersCreatePipeline( vlc_object_t *, filter_t **, int *, int aout_FiltersCreatePipeline( vlc_object_t *, filter_t **, int *,
...@@ -149,6 +150,20 @@ struct audio_mixer *aout_MixerNew(vlc_object_t *, vlc_fourcc_t); ...@@ -149,6 +150,20 @@ struct audio_mixer *aout_MixerNew(vlc_object_t *, vlc_fourcc_t);
#define aout_MixerNew(o, f) aout_MixerNew(VLC_OBJECT(o), f) #define aout_MixerNew(o, f) aout_MixerNew(VLC_OBJECT(o), f)
void aout_MixerDelete(struct audio_mixer *); void aout_MixerDelete(struct audio_mixer *);
void aout_MixerRun(struct audio_mixer *, block_t *, float); void aout_MixerRun(struct audio_mixer *, block_t *, float);
float aout_ReplayGainSelect(vlc_object_t *, const char *,
const audio_replay_gain_t *);
#define aout_ReplayGainSelect(o, s, g) \
aout_ReplayGainSelect(VLC_OBJECT(o), s, g)
static inline void aout_ReplayGainInit(audio_replay_gain_t *restrict d,
const audio_replay_gain_t *restrict s)
{
if (s != NULL)
*d = *s;
else
memset (d, 0, sizeof (*d));
}
/* From output.c : */ /* From output.c : */
int aout_OutputNew( audio_output_t * p_aout, int aout_OutputNew( audio_output_t * p_aout,
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
#include "aout_internal.h" #include "aout_internal.h"
#include "libvlc.h" #include "libvlc.h"
static int ReplayGainCallback (vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void *);
/** /**
* Creates an audio output * Creates an audio output
*/ */
...@@ -83,30 +86,34 @@ int aout_DecNew( audio_output_t *p_aout, ...@@ -83,30 +86,34 @@ int aout_DecNew( audio_output_t *p_aout,
p_input->b_error = true; p_input->b_error = true;
if( p_replay_gain )
p_input->replay_gain = *p_replay_gain;
/* We can only be called by the decoder, so no need to lock /* We can only be called by the decoder, so no need to lock
* p_input->lock. */ * p_input->lock. */
aout_owner_t *owner = aout_owner(p_aout); aout_owner_t *owner = aout_owner(p_aout);
aout_lock( p_aout ); aout_lock( p_aout );
assert (owner->input == NULL);
/* Create the audio output stream */
var_Destroy( p_aout, "audio-device" ); var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "audio-channels" ); var_Destroy( p_aout, "audio-channels" );
/* Recreate the output using the new format. */
owner->input_format = *p_format; owner->input_format = *p_format;
vlc_atomic_set (&owner->restart, 0); vlc_atomic_set (&owner->restart, 0);
if( aout_OutputNew( p_aout, p_format ) < 0 ) if( aout_OutputNew( p_aout, p_format ) < 0 )
goto error; goto error;
/* Allocate a software mixer */
assert (owner->volume.mixer == NULL); assert (owner->volume.mixer == NULL);
owner->volume.mixer = aout_MixerNew (p_aout, owner->mixer_format.i_format); owner->volume.mixer = aout_MixerNew (p_aout, owner->mixer_format.i_format);
aout_ReplayGainInit (&owner->gain.data, p_replay_gain);
var_AddCallback (p_aout, "audio-replay-gain-mode",
ReplayGainCallback, owner);
var_TriggerCallback (p_aout, "audio-replay-gain-mode");
/* Create the audio filtering "input" pipeline */
date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1); date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1);
date_Set (&owner->sync.date, VLC_TS_INVALID); date_Set (&owner->sync.date, VLC_TS_INVALID);
assert (owner->input == NULL);
owner->input = p_input; owner->input = p_input;
aout_InputNew( p_aout, p_format, &owner->mixer_format, p_input, aout_InputNew( p_aout, p_format, &owner->mixer_format, p_input,
p_request_vout ); p_request_vout );
...@@ -133,9 +140,13 @@ void aout_DecDelete( audio_output_t * p_aout ) ...@@ -133,9 +140,13 @@ void aout_DecDelete( audio_output_t * p_aout )
aout_InputDelete (p_aout, input); aout_InputDelete (p_aout, input);
owner->input = NULL; owner->input = NULL;
aout_OutputDelete( p_aout );
mixer = owner->volume.mixer; mixer = owner->volume.mixer;
owner->volume.mixer = NULL; owner->volume.mixer = NULL;
var_DelCallback (p_aout, "audio-replay-gain-mode",
ReplayGainCallback, owner);
aout_OutputDelete( p_aout );
var_Destroy( p_aout, "audio-device" ); var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "audio-channels" ); var_Destroy( p_aout, "audio-channels" );
...@@ -273,9 +284,12 @@ int aout_DecPlay (audio_output_t *p_aout, block_t *p_buffer, int i_input_rate) ...@@ -273,9 +284,12 @@ int aout_DecPlay (audio_output_t *p_aout, block_t *p_buffer, int i_input_rate)
date_Increment (&owner->sync.date, p_buffer->i_nb_samples); date_Increment (&owner->sync.date, p_buffer->i_nb_samples);
/* Mixer */ /* Mixer */
if (owner->volume.mixer != NULL)
{
float amp = owner->volume.multiplier float amp = owner->volume.multiplier
* aout_InputGetMultiplier (p_input); * vlc_atomic_getf (&owner->gain.multiplier);
aout_MixerRun (owner->volume.mixer, p_buffer, amp); aout_MixerRun (owner->volume.mixer, p_buffer, amp);
}
/* Output */ /* Output */
aout_OutputPlay( p_aout, p_buffer ); aout_OutputPlay( p_aout, p_buffer );
...@@ -374,3 +388,14 @@ void aout_TimeReport (audio_output_t *aout, mtime_t ideal) ...@@ -374,3 +388,14 @@ void aout_TimeReport (audio_output_t *aout, mtime_t ideal)
date_Move (&owner->sync.date, delta); date_Move (&owner->sync.date, delta);
} }
} }
static int ReplayGainCallback (vlc_object_t *obj, char const *var,
vlc_value_t oldval, vlc_value_t val, void *data)
{
aout_owner_t *owner = data;
float multiplier = aout_ReplayGainSelect (obj, val.psz_string,
&owner->gain.data);
vlc_atomic_setf (&owner->gain.multiplier, multiplier);
VLC_UNUSED(var); VLC_UNUSED(oldval);
return VLC_SUCCESS;
}
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <assert.h> #include <assert.h>
#include <vlc_input.h> #include <vlc_input.h>
...@@ -43,7 +42,6 @@ ...@@ -43,7 +42,6 @@
#include <vlc_modules.h> #include <vlc_modules.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_filter.h> #include <vlc_filter.h>
#include <vlc_atomic.h>
#include <libvlc.h> #include <libvlc.h>
#include "aout_internal.h" #include "aout_internal.h"
...@@ -56,10 +54,6 @@ static int VisualizationCallback( vlc_object_t *, char const *, ...@@ -56,10 +54,6 @@ static int VisualizationCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int EqualizerCallback( vlc_object_t *, char const *, static int EqualizerCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int ReplayGainCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static float ReplayGainSelect(vlc_object_t *, const char *,
const audio_replay_gain_t *);
static vout_thread_t *RequestVout( void *, static vout_thread_t *RequestVout( void *,
vout_thread_t *, video_format_t *, bool ); vout_thread_t *, video_format_t *, bool );
...@@ -103,13 +97,6 @@ int aout_InputNew( audio_output_t * p_aout, ...@@ -103,13 +97,6 @@ int aout_InputNew( audio_output_t * p_aout,
/* Now add user filters */ /* Now add user filters */
var_AddCallback( p_aout, "visual", VisualizationCallback, p_input ); var_AddCallback( p_aout, "visual", VisualizationCallback, p_input );
var_AddCallback( p_aout, "equalizer", EqualizerCallback, p_input ); var_AddCallback( p_aout, "equalizer", EqualizerCallback, p_input );
var_AddCallback( p_aout, "audio-replay-gain-mode", ReplayGainCallback, p_input );
char *gain = var_InheritString (p_aout, "audio-replay-gain-mode");
vlc_atomic_setf (&p_input->multiplier,
ReplayGainSelect (VLC_OBJECT(p_aout), gain,
&p_input->replay_gain));
free (gain);
psz_filters = var_GetString( p_aout, "audio-filter" ); psz_filters = var_GetString( p_aout, "audio-filter" );
psz_visual = var_GetString( p_aout, "audio-visual"); psz_visual = var_GetString( p_aout, "audio-visual");
...@@ -318,8 +305,6 @@ int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input ) ...@@ -318,8 +305,6 @@ int aout_InputDelete( audio_output_t * p_aout, aout_input_t * p_input )
if ( p_input->b_error ) if ( p_input->b_error )
return 0; return 0;
var_DelCallback (p_aout, "audio-replay-gain-mode", ReplayGainCallback,
p_input);
var_DelCallback (p_aout, "equalizer", EqualizerCallback, p_input); var_DelCallback (p_aout, "equalizer", EqualizerCallback, p_input);
var_DelCallback (p_aout, "visual", VisualizationCallback, p_input); var_DelCallback (p_aout, "visual", VisualizationCallback, p_input);
...@@ -700,63 +685,3 @@ static int EqualizerCallback (vlc_object_t *obj, char const *cmd, ...@@ -700,63 +685,3 @@ static int EqualizerCallback (vlc_object_t *obj, char const *cmd,
aout_InputRequestRestart ((audio_output_t *)obj); aout_InputRequestRestart ((audio_output_t *)obj);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
float aout_InputGetMultiplier (const aout_input_t *input)
{
return vlc_atomic_getf (&input->multiplier);
}
static int ReplayGainCallback (vlc_object_t *obj, char const *var,
vlc_value_t oldval, vlc_value_t val, void *data)
{
aout_input_t *input = data;
float multiplier = ReplayGainSelect (obj, val.psz_string,
&input->replay_gain);
vlc_atomic_setf (&input->multiplier, multiplier);
VLC_UNUSED(var); VLC_UNUSED(oldval);
return VLC_SUCCESS;
}
static float ReplayGainSelect (vlc_object_t *obj, const char *str,
const audio_replay_gain_t *replay_gain)
{
float gain = 0.;
unsigned mode = AUDIO_REPLAY_GAIN_MAX;
if (likely(str != NULL))
{ /* Find selectrf mode */
if (!strcmp (str, "track"))
mode = AUDIO_REPLAY_GAIN_TRACK;
else
if (!strcmp (str, "album"))
mode = AUDIO_REPLAY_GAIN_ALBUM;
/* If the selectrf mode is not available, prefer the other one */
if (mode != AUDIO_REPLAY_GAIN_MAX && !replay_gain->pb_gain[mode])
{
if (replay_gain->pb_gain[!mode])
mode = !mode;
}
}
/* */
if (mode == AUDIO_REPLAY_GAIN_MAX)
return 1.;
if (replay_gain->pb_gain[mode])
gain = replay_gain->pf_gain[mode]
+ var_InheritFloat (obj, "audio-replay-gain-preamp");
else
gain = var_InheritFloat (obj, "audio-replay-gain-default");
float multiplier = pow (10., gain / 20.);
if (replay_gain->pb_peak[mode]
&& var_InheritBool (obj, "audio-replay-gain-peak-protection")
&& replay_gain->pf_peak[mode] * multiplier > 1.0)
multiplier = 1.0f / replay_gain->pf_peak[mode];
return multiplier;
}
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#endif #endif
#include <stddef.h> #include <stddef.h>
#include <math.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <libvlc.h> #include <libvlc.h>
#include <vlc_modules.h> #include <vlc_modules.h>
...@@ -74,6 +76,48 @@ void aout_MixerDelete(audio_mixer_t *mixer) ...@@ -74,6 +76,48 @@ void aout_MixerDelete(audio_mixer_t *mixer)
*/ */
void aout_MixerRun(audio_mixer_t *mixer, block_t *block, float amp) void aout_MixerRun(audio_mixer_t *mixer, block_t *block, float amp)
{ {
if (mixer != NULL)
mixer->mix(mixer, block, amp); mixer->mix(mixer, block, amp);
} }
/*** Replay gain ***/
float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str,
const audio_replay_gain_t *replay_gain)
{
float gain = 0.;
unsigned mode = AUDIO_REPLAY_GAIN_MAX;
if (likely(str != NULL))
{ /* Find selectrf mode */
if (!strcmp (str, "track"))
mode = AUDIO_REPLAY_GAIN_TRACK;
else
if (!strcmp (str, "album"))
mode = AUDIO_REPLAY_GAIN_ALBUM;
/* If the selectrf mode is not available, prefer the other one */
if (mode != AUDIO_REPLAY_GAIN_MAX && !replay_gain->pb_gain[mode])
{
if (replay_gain->pb_gain[!mode])
mode = !mode;
}
}
/* */
if (mode == AUDIO_REPLAY_GAIN_MAX)
return 1.;
if (replay_gain->pb_gain[mode])
gain = replay_gain->pf_gain[mode]
+ var_InheritFloat (obj, "audio-replay-gain-preamp");
else
gain = var_InheritFloat (obj, "audio-replay-gain-default");
float multiplier = pow (10., gain / 20.);
if (replay_gain->pb_peak[mode]
&& var_InheritBool (obj, "audio-replay-gain-peak-protection")
&& replay_gain->pf_peak[mode] * multiplier > 1.0)
multiplier = 1.0f / replay_gain->pf_peak[mode];
return multiplier;
}
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