diff --git a/include/vlc_aout_mixer.h b/include/vlc_aout_volume.h similarity index 76% rename from include/vlc_aout_mixer.h rename to include/vlc_aout_volume.h index b3bf37bb5a..051413ba10 100644 --- a/include/vlc_aout_mixer.h +++ b/include/vlc_aout_volume.h @@ -1,5 +1,5 @@ /***************************************************************************** - * vlc_aout_mixer.h : audio output mixer interface + * vlc_aout_volume.h: audio volume module ***************************************************************************** * Copyright (C) 2002-2009 VLC authors and VideoLAN * $Id$ @@ -34,24 +34,19 @@ extern "C" { #endif -typedef struct audio_mixer audio_mixer_t; +typedef struct audio_volume audio_volume_t; -/** - * audio output mixer +/** + * Audio volume */ -struct audio_mixer +struct audio_volume { VLC_COMMON_MEMBERS - module_t *module; /**< Module handle */ vlc_fourcc_t format; /**< Audio samples format */ - void (*mix)(audio_mixer_t *, block_t *, float); /**< Amplifier */ + void (*amplify)(audio_volume_t *, block_t *, float); /**< Amplifier */ }; -VLC_API audio_mixer_t *aout_MixerNew(vlc_object_t *, vlc_fourcc_t) VLC_USED; -VLC_API void aout_MixerDelete(audio_mixer_t *); -VLC_API void aout_MixerRun(audio_mixer_t *, block_t *, float); - #ifdef __cplusplus } #endif diff --git a/modules/audio_filter/gain.c b/modules/audio_filter/gain.c index b137823a63..68e689a902 100644 --- a/modules/audio_filter/gain.c +++ b/modules/audio_filter/gain.c @@ -30,8 +30,9 @@ #include #include -#include +#include #include +#include #include @@ -45,11 +46,11 @@ static block_t *Process ( filter_t *, block_t * ); struct filter_sys_t { + audio_volume_t volume; float f_gain; - audio_mixer_t* p_mixer; + module_t *module; }; - /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -86,15 +87,17 @@ static int Open( vlc_object_t *p_this ) return VLC_EGENERIC; } - p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) ); - if( !p_sys ) + p_sys = vlc_object_create( p_this, sizeof( *p_sys ) ); + if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; - p_sys->p_mixer = aout_MixerNew( p_this, p_filter->fmt_in.audio.i_format ); - if( !p_sys->p_mixer ) + p_filter->p_sys = p_sys; + p_sys->volume.format = p_filter->fmt_in.audio.i_format; + p_sys->module = module_need( &p_sys->volume, "audio volume", NULL, false ); + if( p_sys->module == NULL ) { msg_Warn( p_filter, "unsupported format" ); - free( p_sys ); + vlc_object_release( &p_sys->volume ); return VLC_EGENERIC; } @@ -114,8 +117,7 @@ static block_t *Process( filter_t *p_filter, block_t *p_block ) { filter_sys_t *p_sys = p_filter->p_sys; - aout_MixerRun( p_sys->p_mixer, p_block, p_sys->f_gain ); - + p_sys->volume.amplify( &p_sys->volume, p_block, p_sys->f_gain ); return p_block; } @@ -129,6 +131,6 @@ static void Close( vlc_object_t *p_this ) filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys = p_filter->p_sys; - aout_MixerDelete( p_sys->p_mixer ); - free( p_sys ); + module_unneed( &p_sys->volume, p_sys->module ); + vlc_object_release( &p_sys->volume ); } diff --git a/modules/audio_mixer/float32.c b/modules/audio_mixer/float32.c index 0e52a64dd5..912da15989 100644 --- a/modules/audio_mixer/float32.c +++ b/modules/audio_mixer/float32.c @@ -1,5 +1,5 @@ /***************************************************************************** - * float32.c : precise float32 audio mixer implementation + * float32.c : precise float32 audio volume implementation ***************************************************************************** * Copyright (C) 2002 the VideoLAN team * $Id$ @@ -33,13 +33,13 @@ #include #include #include -#include +#include /***************************************************************************** * Local prototypes *****************************************************************************/ static int Create( vlc_object_t * ); -static void DoWork( audio_mixer_t *, block_t *, float ); +static void DoWork( audio_volume_t *, block_t *, float ); /***************************************************************************** * Module descriptor @@ -47,8 +47,8 @@ static void DoWork( audio_mixer_t *, block_t *, float ); vlc_module_begin () set_category( CAT_AUDIO ) set_subcategory( SUBCAT_AUDIO_MISC ) - set_description( N_("Float32 audio mixer") ) - set_capability( "audio mixer", 10 ) + set_description( N_("Single precision audio volume") ) + set_capability( "audio volume", 10 ) set_callbacks( Create, NULL ) vlc_module_end () @@ -57,19 +57,19 @@ vlc_module_end () */ static int Create( vlc_object_t *p_this ) { - audio_mixer_t *p_mixer = (audio_mixer_t *)p_this; + audio_volume_t *p_volume = (audio_volume_t *)p_this; - if (p_mixer->format != VLC_CODEC_FL32) + if (p_volume->format != VLC_CODEC_FL32) return -1; - p_mixer->mix = DoWork; + p_volume->amplify = DoWork; return 0; } /** * Mixes a new output buffer */ -static void DoWork( audio_mixer_t * p_mixer, block_t *p_buffer, +static void DoWork( audio_volume_t *p_volume, block_t *p_buffer, float f_multiplier ) { if( f_multiplier == 1.0 ) @@ -79,5 +79,5 @@ static void DoWork( audio_mixer_t * p_mixer, block_t *p_buffer, for( size_t i = p_buffer->i_buffer / sizeof(float); i > 0; i-- ) *(p++) *= f_multiplier; - (void) p_mixer; + (void) p_volume; } diff --git a/modules/audio_mixer/integer.c b/modules/audio_mixer/integer.c index 8d2c3fc828..a64862bf90 100644 --- a/modules/audio_mixer/integer.c +++ b/modules/audio_mixer/integer.c @@ -25,28 +25,28 @@ #include #include #include -#include +#include static int Activate (vlc_object_t *); vlc_module_begin () set_category (CAT_AUDIO) set_subcategory (SUBCAT_AUDIO_MISC) - set_description (N_("Integer audio mixer")) - set_capability ("audio mixer", 9) + set_description (N_("Integer audio volume")) + set_capability ("audio volume", 9) set_callbacks (Activate, NULL) vlc_module_end () -static void FilterS16N (audio_mixer_t *, block_t *, float); +static void FilterS16N (audio_volume_t *, block_t *, float); static int Activate (vlc_object_t *obj) { - audio_mixer_t *mixer = (audio_mixer_t *)obj; + audio_volume_t *vol = (audio_volume_t *)obj; - switch (mixer->format) + switch (vol->format) { case VLC_CODEC_S16N: - mixer->mix = FilterS16N; + vol->amplify = FilterS16N; break; default: return -1; @@ -54,7 +54,7 @@ static int Activate (vlc_object_t *obj) return 0; } -static void FilterS16N (audio_mixer_t *mixer, block_t *block, float volume) +static void FilterS16N (audio_volume_t *vol, block_t *block, float volume) { int32_t mult = volume * 0x1.p16; @@ -83,5 +83,5 @@ static void FilterS16N (audio_mixer_t *mixer, block_t *block, float volume) } } - (void) mixer; + (void) vol; } diff --git a/po/POTFILES.in b/po/POTFILES.in index d01c9a65dc..7114653f73 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -68,7 +68,6 @@ src/audio_output/dec.c src/audio_output/filters.c src/audio_output/input.c src/audio_output/intf.c -src/audio_output/mixer.c src/audio_output/output.c src/config/chain.c src/config/cmdline.c diff --git a/src/Makefile.am b/src/Makefile.am index d6d083ec7a..c6e874ddec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ pluginsinclude_HEADERS = \ ../include/vlc_access.h \ ../include/vlc_aout.h \ ../include/vlc_aout_intf.h \ - ../include/vlc_aout_mixer.h \ + ../include/vlc_aout_volume.h \ ../include/vlc_arrays.h \ ../include/vlc_art_finder.h \ ../include/vlc_atomic.h \ @@ -384,8 +384,8 @@ SOURCES_libvlc_common = \ audio_output/dec.c \ audio_output/filters.c \ audio_output/input.c \ - audio_output/mixer.c \ audio_output/output.c \ + audio_output/volume.c \ audio_output/intf.c \ osd/osd.c \ osd/osd_text.c \ diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index 463661ff66..86775ed153 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -48,6 +48,8 @@ struct filter_owner_sys_t aout_input_t *p_input; }; +typedef struct aout_volume aout_volume_t; + /** an input stream for the audio output */ struct aout_input_t { @@ -82,25 +84,13 @@ typedef struct vlc_mutex_t lock; module_t *module; /**< Output plugin (or NULL if inactive) */ aout_input_t *input; + aout_volume_t *volume; struct { date_t date; } sync; - struct - { - float amp; /**< Software volume amplification */ - bool mute; /**< Software mute */ - struct audio_mixer *mixer; /**< Software volume plugin */ - } volume; - - struct - { - vlc_atomic_t multiplier; - audio_replay_gain_t data; - } gain; - audio_sample_format_t mixer_format; audio_sample_format_t input_format; @@ -108,6 +98,12 @@ typedef struct filter_t *filters[AOUT_MAX_FILTERS]; int nb_filters; + struct + { + float volume; + bool mute; + } soft; /* temporary - TODO: move to output plugins */ + vlc_atomic_t restart; } aout_owner_t; @@ -143,21 +139,12 @@ void aout_FiltersDestroyPipeline( filter_t *const *, unsigned ); void aout_FiltersPlay( filter_t *const *, unsigned, block_t ** ); /* From mixer.c : */ -#define aout_MixerNew(o, f) aout_MixerNew(VLC_OBJECT(o), f) - -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)); -} +aout_volume_t *aout_volume_New(vlc_object_t *, const audio_replay_gain_t *); +#define aout_volume_New(o, g) aout_volume_New(VLC_OBJECT(o), g) +int aout_volume_SetFormat(aout_volume_t *, vlc_fourcc_t); +void aout_volume_SetVolume(aout_volume_t *, float); +int aout_volume_Amplify(aout_volume_t *, block_t *); +void aout_volume_Delete(aout_volume_t *); /* From output.c : */ diff --git a/src/audio_output/common.c b/src/audio_output/common.c index f557fcbb4e..4907ba4781 100644 --- a/src/audio_output/common.c +++ b/src/audio_output/common.c @@ -61,9 +61,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent ) vlc_mutex_init (&owner->lock); owner->module = NULL; owner->input = NULL; - owner->volume.amp = 1.f; - owner->volume.mute = false; - owner->volume.mixer = NULL; aout->pf_play = aout_DecDeleteBuffer; aout->volume_set = NULL; diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c index a4fe78db2b..0bc2e66d96 100644 --- a/src/audio_output/dec.c +++ b/src/audio_output/dec.c @@ -32,16 +32,12 @@ #include #include -#include #include #include #include "aout_internal.h" #include "libvlc.h" -static int ReplayGainCallback (vlc_object_t *, char const *, - vlc_value_t, vlc_value_t, void *); - /** * Creates an audio output */ @@ -99,20 +95,13 @@ int aout_DecNew( audio_output_t *p_aout, owner->input_format = *p_format; vlc_atomic_set (&owner->restart, 0); + owner->volume = aout_volume_New (p_aout, p_replay_gain); if( aout_OutputNew( p_aout, p_format ) < 0 ) { ret = -1; goto error; } - - /* Allocate a software mixer */ - assert (owner->volume.mixer == NULL); - 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"); + aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format); /* Create the audio filtering "input" pipeline */ date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1); @@ -123,12 +112,9 @@ int aout_DecNew( audio_output_t *p_aout, p_request_vout); if (owner->input == NULL) { - struct audio_mixer *mixer = owner->volume.mixer; - - owner->volume.mixer = NULL; aout_OutputDelete (p_aout); + aout_volume_Delete (owner->volume); aout_unlock (p_aout); - aout_MixerDelete (mixer); return -1; } error: @@ -143,7 +129,6 @@ void aout_Shutdown (audio_output_t *p_aout) { aout_owner_t *owner = aout_owner (p_aout); aout_input_t *input; - struct audio_mixer *mixer; aout_lock( p_aout ); /* Remove the input. */ @@ -152,19 +137,12 @@ void aout_Shutdown (audio_output_t *p_aout) aout_InputDelete (p_aout, input); owner->input = NULL; - mixer = owner->volume.mixer; - owner->volume.mixer = NULL; - - var_DelCallback (p_aout, "audio-replay-gain-mode", - ReplayGainCallback, owner); - aout_OutputDelete( p_aout ); + aout_volume_Delete (owner->volume); var_Destroy( p_aout, "audio-device" ); var_Destroy( p_aout, "audio-channels" ); aout_unlock( p_aout ); - - aout_MixerDelete (mixer); free (input); } @@ -204,14 +182,13 @@ static void aout_CheckRestart (audio_output_t *aout) /* Reinitializes the output */ if (restart & AOUT_RESTART_OUTPUT) { - aout_MixerDelete (owner->volume.mixer); - owner->volume.mixer = NULL; aout_OutputDelete (aout); - if (aout_OutputNew (aout, &owner->input_format)) + { + aout_volume_Delete (owner->volume); return; /* we are officially screwed */ - owner->volume.mixer = aout_MixerNew (aout, - owner->mixer_format.i_format); + } + aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format); } owner->input = aout_InputNew (aout, &owner->input_format, @@ -308,14 +285,7 @@ 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); /* Mixer */ - if (owner->volume.mixer != NULL) - { - float amp = 0.f; - if (!owner->volume.mute) - amp = owner->volume.amp - * vlc_atomic_getf (&owner->gain.multiplier); - aout_MixerRun (owner->volume.mixer, p_buffer, amp); - } + aout_volume_Amplify (owner->volume, p_buffer); /* Output */ aout_OutputPlay( p_aout, p_buffer ); @@ -382,14 +352,3 @@ bool aout_DecIsEmpty (audio_output_t *aout) aout_unlock (aout); return empty; } - -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; -} diff --git a/src/audio_output/mixer.c b/src/audio_output/mixer.c deleted file mode 100644 index 28b3fafa3b..0000000000 --- a/src/audio_output/mixer.c +++ /dev/null @@ -1,139 +0,0 @@ -/***************************************************************************** - * mixer.c : audio output volume operations - ***************************************************************************** - * Copyright (C) 2002-2004 VLC authors and VideoLAN - * $Id$ - * - * Authors: Christophe Massiot - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -/***************************************************************************** - * Preamble - *****************************************************************************/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include "aout_internal.h" - -/* Note: Once upon a time, the audio output volume module was also responsible - * for mixing multiple audio inputs together. Hence it was called mixer. - * Nowadays, there is only ever a single input per module instance, so this has - * become a misnomer. */ - -typedef struct aout_volume -{ - audio_mixer_t volume; -} aout_volume_t; - -static inline aout_volume_t *vol_priv(audio_mixer_t *volume) -{ - return (aout_volume_t *)volume; -} - -#undef aout_MixerNew -/** - * Creates a software amplifier. - */ -audio_mixer_t *aout_MixerNew(vlc_object_t *obj, vlc_fourcc_t format) -{ - audio_mixer_t *mixer = vlc_custom_create(obj, sizeof (aout_volume_t), - "volume"); - if (unlikely(mixer == NULL)) - return NULL; - - mixer->format = format; - mixer->mix = NULL; - mixer->module = module_need(mixer, "audio mixer", NULL, false); - if (mixer->module == NULL) - { - vlc_object_release(mixer); - mixer = NULL; - } - return mixer; -} - -/** - * Destroys a software amplifier. - */ -void aout_MixerDelete(audio_mixer_t *mixer) -{ - if (mixer == NULL) - return; - - module_unneed(mixer, mixer->module); - vlc_object_release(mixer); -} - -/** - * Applies replay gain and software volume to an audio buffer. - */ -void aout_MixerRun(audio_mixer_t *mixer, block_t *block, float 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; -} diff --git a/src/audio_output/output.c b/src/audio_output/output.c index 98d829c18a..e6e57add62 100644 --- a/src/audio_output/output.c +++ b/src/audio_output/output.c @@ -275,8 +275,6 @@ void aout_OutputDelete (audio_output_t *aout) aout->volume_set = NULL; aout->mute_set = NULL; owner->module = NULL; - owner->volume.amp = 1.f; - owner->volume.mute = false; aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters); } @@ -339,10 +337,12 @@ static int aout_SoftVolumeSet (audio_output_t *aout, float volume) * This provides a good tradeoff between low and high volume ranges. * * This code is only used for the VLC software mixer. If you change this - * formula, be sure to update the aout_VolumeHardInit()-based plugins also. + * formula, be sure to update the volume-capable plugins also. */ - owner->volume.amp = volume * volume * volume; aout_VolumeReport (aout, volume); + volume = volume * volume * volume; + owner->soft.volume = volume; + aout_volume_SetVolume(owner->volume, owner->soft.mute ? 0.f : volume); return 0; } @@ -351,8 +351,9 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute) aout_owner_t *owner = aout_owner (aout); aout_assert_locked (aout); - owner->volume.mute = mute; aout_MuteReport (aout, mute); + owner->soft.mute = mute; + aout_volume_SetVolume(owner->volume, mute ? 0.f : owner->soft.volume); return 0; } @@ -364,12 +365,15 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute) */ void aout_VolumeSoftInit (audio_output_t *aout) { + aout_owner_t *owner = aout_owner (aout); long volume = var_GetInteger (aout, "volume"); bool mute = var_GetBool (aout, "mute"); aout_assert_locked (aout); + /* volume depends on mute and vice versa... bootstrapping mute is easier */ + owner->soft.mute = mute; aout->volume_set = aout_SoftVolumeSet; aout->mute_set = aout_SoftMuteSet; aout_SoftVolumeSet (aout, volume / (float)AOUT_VOLUME_DEFAULT); - aout_SoftMuteSet (aout, mute); + aout_MuteReport (aout, mute); } diff --git a/src/audio_output/volume.c b/src/audio_output/volume.c new file mode 100644 index 0000000000..afb7e6778f --- /dev/null +++ b/src/audio_output/volume.c @@ -0,0 +1,196 @@ +/***************************************************************************** + * volume.c : audio output volume operations + ***************************************************************************** + * Copyright (C) 2002-2004 VLC authors and VideoLAN + * Copyright (C) 2011-2012 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include "aout_internal.h" + +struct aout_volume +{ + audio_volume_t object; + audio_replay_gain_t replay_gain; + vlc_atomic_t gain_factor; + float output_factor; + module_t *module; +}; + +static int ReplayGainCallback (vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void *); + +#undef aout_volume_New +/** + * Creates a software amplifier. + */ +aout_volume_t *aout_volume_New(vlc_object_t *parent, + const audio_replay_gain_t *gain) +{ + aout_volume_t *vol = vlc_custom_create(parent, sizeof (aout_volume_t), + "volume"); + if (unlikely(vol == NULL)) + return NULL; + vol->module = NULL; + vol->output_factor = 1.f; + + //audio_volume_t *obj = &vol->object; + + /* Gain */ + if (gain != NULL) + memcpy(&vol->replay_gain, gain, sizeof (vol->replay_gain)); + else + memset(&vol->replay_gain, 0, sizeof (vol->replay_gain)); + + var_AddCallback(parent, "audio-replay-gain-mode", + ReplayGainCallback, vol); + var_TriggerCallback(parent, "audio-replay-gain-mode"); + + return vol; +} + +/** + * Selects the current sample format for software amplification. + */ +int aout_volume_SetFormat(aout_volume_t *vol, vlc_fourcc_t format) +{ + if (unlikely(vol == NULL)) + return -1; + + audio_volume_t *obj = &vol->object; + if (vol->module != NULL) + { + if (obj->format == format) + { + msg_Dbg (obj, "retaining sample format"); + return 0; + } + msg_Dbg (obj, "changing sample format"); + module_unneed(obj, vol->module); + } + + obj->format = format; + vol->module = module_need(obj, "audio volume", NULL, false); + if (vol->module == NULL) + return -1; + return 0; +} + +/** + * Destroys a software amplifier. + */ +void aout_volume_Delete(aout_volume_t *vol) +{ + if (vol == NULL) + return; + + audio_volume_t *obj = &vol->object; + + if (vol->module != NULL) + module_unneed(obj, vol->module); + var_DelCallback(obj->p_parent, "audio-replay-gain-mode", + ReplayGainCallback, vol); + vlc_object_release(obj); +} + +void aout_volume_SetVolume(aout_volume_t *vol, float factor) +{ + if (unlikely(vol == NULL)) + return; + + vol->output_factor = factor; +} + +/** + * Applies replay gain and software volume to an audio buffer. + */ +int aout_volume_Amplify(aout_volume_t *vol, block_t *block) +{ + if (unlikely(vol == NULL) || vol->module == NULL) + return -1; + + float amp = vol->output_factor + * vlc_atomic_getf (&vol->gain_factor); + + vol->object.amplify(&vol->object, block, amp); + return 0; +} + +/*** Replay gain ***/ +static 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; +} + +static int ReplayGainCallback (vlc_object_t *obj, char const *var, + vlc_value_t oldval, vlc_value_t val, void *data) +{ + aout_volume_t *vol = data; + float multiplier = aout_ReplayGainSelect(obj, val.psz_string, + &vol->replay_gain); + vlc_atomic_setf (&vol->gain_factor, multiplier); + VLC_UNUSED(var); VLC_UNUSED(oldval); + return VLC_SUCCESS; +} diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 84491852e0..53ca43d2dc 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -11,9 +11,6 @@ aout_filter_RequestVout aout_FormatPrepare aout_FormatPrint aout_FormatPrintChannels -aout_MixerDelete -aout_MixerNew -aout_MixerRun aout_VolumeGet aout_VolumeSet aout_VolumeUp