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

aout: cleanup mixer and rename to volume

parent fe08f7fb
/***************************************************************************** /*****************************************************************************
* vlc_aout_mixer.h : audio output mixer interface * vlc_aout_volume.h: audio volume module
***************************************************************************** *****************************************************************************
* Copyright (C) 2002-2009 VLC authors and VideoLAN * Copyright (C) 2002-2009 VLC authors and VideoLAN
* $Id$ * $Id$
...@@ -34,24 +34,19 @@ ...@@ -34,24 +34,19 @@
extern "C" { extern "C" {
#endif #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 VLC_COMMON_MEMBERS
module_t *module; /**< Module handle */
vlc_fourcc_t format; /**< Audio samples format */ 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 #ifdef __cplusplus
} }
#endif #endif
......
...@@ -30,8 +30,9 @@ ...@@ -30,8 +30,9 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_aout_mixer.h> #include <vlc_aout_volume.h>
#include <vlc_filter.h> #include <vlc_filter.h>
#include <vlc_modules.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
...@@ -45,11 +46,11 @@ static block_t *Process ( filter_t *, block_t * ); ...@@ -45,11 +46,11 @@ static block_t *Process ( filter_t *, block_t * );
struct filter_sys_t struct filter_sys_t
{ {
audio_volume_t volume;
float f_gain; float f_gain;
audio_mixer_t* p_mixer; module_t *module;
}; };
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -86,15 +87,17 @@ static int Open( vlc_object_t *p_this ) ...@@ -86,15 +87,17 @@ static int Open( vlc_object_t *p_this )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) ); p_sys = vlc_object_create( p_this, sizeof( *p_sys ) );
if( !p_sys ) if( unlikely( p_sys == NULL ) )
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->p_mixer = aout_MixerNew( p_this, p_filter->fmt_in.audio.i_format ); p_filter->p_sys = p_sys;
if( !p_sys->p_mixer ) 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" ); msg_Warn( p_filter, "unsupported format" );
free( p_sys ); vlc_object_release( &p_sys->volume );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -114,8 +117,7 @@ static block_t *Process( filter_t *p_filter, block_t *p_block ) ...@@ -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; 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; return p_block;
} }
...@@ -129,6 +131,6 @@ static void Close( vlc_object_t *p_this ) ...@@ -129,6 +131,6 @@ static void Close( vlc_object_t *p_this )
filter_t *p_filter = (filter_t*)p_this; filter_t *p_filter = (filter_t*)p_this;
filter_sys_t *p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
aout_MixerDelete( p_sys->p_mixer ); module_unneed( &p_sys->volume, p_sys->module );
free( p_sys ); vlc_object_release( &p_sys->volume );
} }
/***************************************************************************** /*****************************************************************************
* float32.c : precise float32 audio mixer implementation * float32.c : precise float32 audio volume implementation
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 the VideoLAN team * Copyright (C) 2002 the VideoLAN team
* $Id$ * $Id$
...@@ -33,13 +33,13 @@ ...@@ -33,13 +33,13 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_aout_mixer.h> #include <vlc_aout_volume.h>
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int Create( vlc_object_t * ); 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 * Module descriptor
...@@ -47,8 +47,8 @@ static void DoWork( audio_mixer_t *, block_t *, float ); ...@@ -47,8 +47,8 @@ static void DoWork( audio_mixer_t *, block_t *, float );
vlc_module_begin () vlc_module_begin ()
set_category( CAT_AUDIO ) set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_MISC ) set_subcategory( SUBCAT_AUDIO_MISC )
set_description( N_("Float32 audio mixer") ) set_description( N_("Single precision audio volume") )
set_capability( "audio mixer", 10 ) set_capability( "audio volume", 10 )
set_callbacks( Create, NULL ) set_callbacks( Create, NULL )
vlc_module_end () vlc_module_end ()
...@@ -57,19 +57,19 @@ vlc_module_end () ...@@ -57,19 +57,19 @@ vlc_module_end ()
*/ */
static int Create( vlc_object_t *p_this ) 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; return -1;
p_mixer->mix = DoWork; p_volume->amplify = DoWork;
return 0; return 0;
} }
/** /**
* Mixes a new output buffer * 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 ) float f_multiplier )
{ {
if( f_multiplier == 1.0 ) if( f_multiplier == 1.0 )
...@@ -79,5 +79,5 @@ static void DoWork( audio_mixer_t * p_mixer, block_t *p_buffer, ...@@ -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-- ) for( size_t i = p_buffer->i_buffer / sizeof(float); i > 0; i-- )
*(p++) *= f_multiplier; *(p++) *= f_multiplier;
(void) p_mixer; (void) p_volume;
} }
...@@ -25,28 +25,28 @@ ...@@ -25,28 +25,28 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_aout_mixer.h> #include <vlc_aout_volume.h>
static int Activate (vlc_object_t *); static int Activate (vlc_object_t *);
vlc_module_begin () vlc_module_begin ()
set_category (CAT_AUDIO) set_category (CAT_AUDIO)
set_subcategory (SUBCAT_AUDIO_MISC) set_subcategory (SUBCAT_AUDIO_MISC)
set_description (N_("Integer audio mixer")) set_description (N_("Integer audio volume"))
set_capability ("audio mixer", 9) set_capability ("audio volume", 9)
set_callbacks (Activate, NULL) set_callbacks (Activate, NULL)
vlc_module_end () 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) 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: case VLC_CODEC_S16N:
mixer->mix = FilterS16N; vol->amplify = FilterS16N;
break; break;
default: default:
return -1; return -1;
...@@ -54,7 +54,7 @@ static int Activate (vlc_object_t *obj) ...@@ -54,7 +54,7 @@ static int Activate (vlc_object_t *obj)
return 0; 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; int32_t mult = volume * 0x1.p16;
...@@ -83,5 +83,5 @@ static void FilterS16N (audio_mixer_t *mixer, block_t *block, float volume) ...@@ -83,5 +83,5 @@ static void FilterS16N (audio_mixer_t *mixer, block_t *block, float volume)
} }
} }
(void) mixer; (void) vol;
} }
...@@ -68,7 +68,6 @@ src/audio_output/dec.c ...@@ -68,7 +68,6 @@ src/audio_output/dec.c
src/audio_output/filters.c src/audio_output/filters.c
src/audio_output/input.c src/audio_output/input.c
src/audio_output/intf.c src/audio_output/intf.c
src/audio_output/mixer.c
src/audio_output/output.c src/audio_output/output.c
src/config/chain.c src/config/chain.c
src/config/cmdline.c src/config/cmdline.c
......
...@@ -26,7 +26,7 @@ pluginsinclude_HEADERS = \ ...@@ -26,7 +26,7 @@ pluginsinclude_HEADERS = \
../include/vlc_access.h \ ../include/vlc_access.h \
../include/vlc_aout.h \ ../include/vlc_aout.h \
../include/vlc_aout_intf.h \ ../include/vlc_aout_intf.h \
../include/vlc_aout_mixer.h \ ../include/vlc_aout_volume.h \
../include/vlc_arrays.h \ ../include/vlc_arrays.h \
../include/vlc_art_finder.h \ ../include/vlc_art_finder.h \
../include/vlc_atomic.h \ ../include/vlc_atomic.h \
...@@ -384,8 +384,8 @@ SOURCES_libvlc_common = \ ...@@ -384,8 +384,8 @@ SOURCES_libvlc_common = \
audio_output/dec.c \ audio_output/dec.c \
audio_output/filters.c \ audio_output/filters.c \
audio_output/input.c \ audio_output/input.c \
audio_output/mixer.c \
audio_output/output.c \ audio_output/output.c \
audio_output/volume.c \
audio_output/intf.c \ audio_output/intf.c \
osd/osd.c \ osd/osd.c \
osd/osd_text.c \ osd/osd_text.c \
......
...@@ -48,6 +48,8 @@ struct filter_owner_sys_t ...@@ -48,6 +48,8 @@ struct filter_owner_sys_t
aout_input_t *p_input; aout_input_t *p_input;
}; };
typedef struct aout_volume aout_volume_t;
/** an input stream for the audio output */ /** an input stream for the audio output */
struct aout_input_t struct aout_input_t
{ {
...@@ -82,25 +84,13 @@ typedef struct ...@@ -82,25 +84,13 @@ typedef struct
vlc_mutex_t lock; vlc_mutex_t lock;
module_t *module; /**< Output plugin (or NULL if inactive) */ module_t *module; /**< Output plugin (or NULL if inactive) */
aout_input_t *input; aout_input_t *input;
aout_volume_t *volume;
struct struct
{ {
date_t date; date_t date;
} sync; } 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 mixer_format;
audio_sample_format_t input_format; audio_sample_format_t input_format;
...@@ -108,6 +98,12 @@ typedef struct ...@@ -108,6 +98,12 @@ typedef struct
filter_t *filters[AOUT_MAX_FILTERS]; filter_t *filters[AOUT_MAX_FILTERS];
int nb_filters; int nb_filters;
struct
{
float volume;
bool mute;
} soft; /* temporary - TODO: move to output plugins */
vlc_atomic_t restart; vlc_atomic_t restart;
} aout_owner_t; } aout_owner_t;
...@@ -143,21 +139,12 @@ void aout_FiltersDestroyPipeline( filter_t *const *, unsigned ); ...@@ -143,21 +139,12 @@ void aout_FiltersDestroyPipeline( filter_t *const *, unsigned );
void aout_FiltersPlay( filter_t *const *, unsigned, block_t ** ); void aout_FiltersPlay( filter_t *const *, unsigned, block_t ** );
/* From mixer.c : */ /* From mixer.c : */
#define aout_MixerNew(o, f) aout_MixerNew(VLC_OBJECT(o), f) 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)
float aout_ReplayGainSelect(vlc_object_t *, const char *, int aout_volume_SetFormat(aout_volume_t *, vlc_fourcc_t);
const audio_replay_gain_t *); void aout_volume_SetVolume(aout_volume_t *, float);
#define aout_ReplayGainSelect(o, s, g) \ int aout_volume_Amplify(aout_volume_t *, block_t *);
aout_ReplayGainSelect(VLC_OBJECT(o), s, g) void aout_volume_Delete(aout_volume_t *);
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 : */
......
...@@ -61,9 +61,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent ) ...@@ -61,9 +61,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
vlc_mutex_init (&owner->lock); vlc_mutex_init (&owner->lock);
owner->module = NULL; owner->module = NULL;
owner->input = NULL; owner->input = NULL;
owner->volume.amp = 1.f;
owner->volume.mute = false;
owner->volume.mixer = NULL;
aout->pf_play = aout_DecDeleteBuffer; aout->pf_play = aout_DecDeleteBuffer;
aout->volume_set = NULL; aout->volume_set = NULL;
......
...@@ -32,16 +32,12 @@ ...@@ -32,16 +32,12 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_input.h> #include <vlc_input.h>
#include <vlc_atomic.h> #include <vlc_atomic.h>
#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
*/ */
...@@ -99,20 +95,13 @@ int aout_DecNew( audio_output_t *p_aout, ...@@ -99,20 +95,13 @@ int aout_DecNew( audio_output_t *p_aout,
owner->input_format = *p_format; owner->input_format = *p_format;
vlc_atomic_set (&owner->restart, 0); vlc_atomic_set (&owner->restart, 0);
owner->volume = aout_volume_New (p_aout, p_replay_gain);
if( aout_OutputNew( p_aout, p_format ) < 0 ) if( aout_OutputNew( p_aout, p_format ) < 0 )
{ {
ret = -1; ret = -1;
goto error; goto error;
} }
aout_volume_SetFormat (owner->volume, owner->mixer_format.i_format);
/* 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");
/* Create the audio filtering "input" pipeline */ /* 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);
...@@ -123,12 +112,9 @@ int aout_DecNew( audio_output_t *p_aout, ...@@ -123,12 +112,9 @@ int aout_DecNew( audio_output_t *p_aout,
p_request_vout); p_request_vout);
if (owner->input == NULL) if (owner->input == NULL)
{ {
struct audio_mixer *mixer = owner->volume.mixer;
owner->volume.mixer = NULL;
aout_OutputDelete (p_aout); aout_OutputDelete (p_aout);
aout_volume_Delete (owner->volume);
aout_unlock (p_aout); aout_unlock (p_aout);
aout_MixerDelete (mixer);
return -1; return -1;
} }
error: error:
...@@ -143,7 +129,6 @@ void aout_Shutdown (audio_output_t *p_aout) ...@@ -143,7 +129,6 @@ void aout_Shutdown (audio_output_t *p_aout)
{ {
aout_owner_t *owner = aout_owner (p_aout); aout_owner_t *owner = aout_owner (p_aout);
aout_input_t *input; aout_input_t *input;
struct audio_mixer *mixer;
aout_lock( p_aout ); aout_lock( p_aout );
/* Remove the input. */ /* Remove the input. */
...@@ -152,19 +137,12 @@ void aout_Shutdown (audio_output_t *p_aout) ...@@ -152,19 +137,12 @@ void aout_Shutdown (audio_output_t *p_aout)
aout_InputDelete (p_aout, input); aout_InputDelete (p_aout, input);
owner->input = NULL; 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_OutputDelete( p_aout );
aout_volume_Delete (owner->volume);
var_Destroy( p_aout, "audio-device" ); var_Destroy( p_aout, "audio-device" );
var_Destroy( p_aout, "audio-channels" ); var_Destroy( p_aout, "audio-channels" );
aout_unlock( p_aout ); aout_unlock( p_aout );
aout_MixerDelete (mixer);
free (input); free (input);
} }
...@@ -204,14 +182,13 @@ static void aout_CheckRestart (audio_output_t *aout) ...@@ -204,14 +182,13 @@ static void aout_CheckRestart (audio_output_t *aout)
/* Reinitializes the output */ /* Reinitializes the output */
if (restart & AOUT_RESTART_OUTPUT) if (restart & AOUT_RESTART_OUTPUT)
{ {
aout_MixerDelete (owner->volume.mixer);
owner->volume.mixer = NULL;
aout_OutputDelete (aout); aout_OutputDelete (aout);
if (aout_OutputNew (aout, &owner->input_format)) if (aout_OutputNew (aout, &owner->input_format))
{
aout_volume_Delete (owner->volume);
return; /* we are officially screwed */ 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, 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) ...@@ -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); date_Increment (&owner->sync.date, p_buffer->i_nb_samples);
/* Mixer */ /* Mixer */
if (owner->volume.mixer != NULL) aout_volume_Amplify (owner->volume, p_buffer);
{
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);
}
/* Output */ /* Output */
aout_OutputPlay( p_aout, p_buffer ); aout_OutputPlay( p_aout, p_buffer );
...@@ -382,14 +352,3 @@ bool aout_DecIsEmpty (audio_output_t *aout) ...@@ -382,14 +352,3 @@ bool aout_DecIsEmpty (audio_output_t *aout)
aout_unlock (aout); aout_unlock (aout);
return empty; 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;
}
...@@ -275,8 +275,6 @@ void aout_OutputDelete (audio_output_t *aout) ...@@ -275,8 +275,6 @@ void aout_OutputDelete (audio_output_t *aout)
aout->volume_set = NULL; aout->volume_set = NULL;
aout->mute_set = NULL; aout->mute_set = NULL;
owner->module = NULL; owner->module = NULL;
owner->volume.amp = 1.f;
owner->volume.mute = false;
aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters); aout_FiltersDestroyPipeline (owner->filters, owner->nb_filters);
} }
...@@ -339,10 +337,12 @@ static int aout_SoftVolumeSet (audio_output_t *aout, float volume) ...@@ -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 provides a good tradeoff between low and high volume ranges.
* *
* This code is only used for the VLC software mixer. If you change this * 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); 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; return 0;
} }
...@@ -351,8 +351,9 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute) ...@@ -351,8 +351,9 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute)
aout_owner_t *owner = aout_owner (aout); aout_owner_t *owner = aout_owner (aout);
aout_assert_locked (aout); aout_assert_locked (aout);
owner->volume.mute = mute;
aout_MuteReport (aout, mute); aout_MuteReport (aout, mute);
owner->soft.mute = mute;
aout_volume_SetVolume(owner->volume, mute ? 0.f : owner->soft.volume);
return 0; return 0;
} }
...@@ -364,12 +365,15 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute) ...@@ -364,12 +365,15 @@ static int aout_SoftMuteSet (audio_output_t *aout, bool mute)
*/ */
void aout_VolumeSoftInit (audio_output_t *aout) void aout_VolumeSoftInit (audio_output_t *aout)
{ {
aout_owner_t *owner = aout_owner (aout);
long volume = var_GetInteger (aout, "volume"); long volume = var_GetInteger (aout, "volume");
bool mute = var_GetBool (aout, "mute"); bool mute = var_GetBool (aout, "mute");
aout_assert_locked (aout); 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->volume_set = aout_SoftVolumeSet;
aout->mute_set = aout_SoftMuteSet; aout->mute_set = aout_SoftMuteSet;
aout_SoftVolumeSet (aout, volume / (float)AOUT_VOLUME_DEFAULT); aout_SoftVolumeSet (aout, volume / (float)AOUT_VOLUME_DEFAULT);
aout_SoftMuteSet (aout, mute); aout_MuteReport (aout, mute);
} }
/***************************************************************************** /*****************************************************************************
* mixer.c : audio output volume operations * volume.c : audio output volume operations
***************************************************************************** *****************************************************************************
* Copyright (C) 2002-2004 VLC authors and VideoLAN * Copyright (C) 2002-2004 VLC authors and VideoLAN
* $Id$ * Copyright (C) 2011-2012 Rémi Denis-Courmont
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU Lesser General Public License as published by
...@@ -21,9 +19,6 @@ ...@@ -21,9 +19,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/ *****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
...@@ -35,68 +30,119 @@ ...@@ -35,68 +30,119 @@
#include <libvlc.h> #include <libvlc.h>
#include <vlc_modules.h> #include <vlc_modules.h>
#include <vlc_aout.h> #include <vlc_aout.h>
#include <vlc_aout_mixer.h> #include <vlc_aout_volume.h>
#include "aout_internal.h" #include "aout_internal.h"
/* Note: Once upon a time, the audio output volume module was also responsible struct aout_volume
* 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; audio_volume_t object;
} aout_volume_t; audio_replay_gain_t replay_gain;
vlc_atomic_t gain_factor;
float output_factor;
module_t *module;
};
static inline aout_volume_t *vol_priv(audio_mixer_t *volume) static int ReplayGainCallback (vlc_object_t *, char const *,
{ vlc_value_t, vlc_value_t, void *);
return (aout_volume_t *)volume;
}
#undef aout_MixerNew #undef aout_volume_New
/** /**
* Creates a software amplifier. * Creates a software amplifier.
*/ */
audio_mixer_t *aout_MixerNew(vlc_object_t *obj, vlc_fourcc_t format) aout_volume_t *aout_volume_New(vlc_object_t *parent,
const audio_replay_gain_t *gain)
{ {
audio_mixer_t *mixer = vlc_custom_create(obj, sizeof (aout_volume_t), aout_volume_t *vol = vlc_custom_create(parent, sizeof (aout_volume_t),
"volume"); "volume");
if (unlikely(mixer == NULL)) if (unlikely(vol == NULL))
return 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;
mixer->format = format; audio_volume_t *obj = &vol->object;
mixer->mix = NULL; if (vol->module != NULL)
mixer->module = module_need(mixer, "audio mixer", NULL, false); {
if (mixer->module == NULL) if (obj->format == format)
{ {
vlc_object_release(mixer); msg_Dbg (obj, "retaining sample format");
mixer = NULL; return 0;
} }
return mixer; 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. * Destroys a software amplifier.
*/ */
void aout_MixerDelete(audio_mixer_t *mixer) void aout_volume_Delete(aout_volume_t *vol)
{ {
if (mixer == NULL) if (vol == NULL)
return; return;
module_unneed(mixer, mixer->module); audio_volume_t *obj = &vol->object;
vlc_object_release(mixer);
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. * Applies replay gain and software volume to an audio buffer.
*/ */
void aout_MixerRun(audio_mixer_t *mixer, block_t *block, float amp) int aout_volume_Amplify(aout_volume_t *vol, block_t *block)
{ {
mixer->mix(mixer, block, amp); 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 ***/ /*** Replay gain ***/
float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str, static float aout_ReplayGainSelect(vlc_object_t *obj, const char *str,
const audio_replay_gain_t *replay_gain) const audio_replay_gain_t *replay_gain)
{ {
float gain = 0.; float gain = 0.;
...@@ -137,3 +183,14 @@ float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str, ...@@ -137,3 +183,14 @@ float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str,
return multiplier; 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;
}
...@@ -11,9 +11,6 @@ aout_filter_RequestVout ...@@ -11,9 +11,6 @@ aout_filter_RequestVout
aout_FormatPrepare aout_FormatPrepare
aout_FormatPrint aout_FormatPrint
aout_FormatPrintChannels aout_FormatPrintChannels
aout_MixerDelete
aout_MixerNew
aout_MixerRun
aout_VolumeGet aout_VolumeGet
aout_VolumeSet aout_VolumeSet
aout_VolumeUp aout_VolumeUp
......
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