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
* $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
......
......@@ -30,8 +30,9 @@
#include <vlc_common.h>
#include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_aout_volume.h>
#include <vlc_filter.h>
#include <vlc_modules.h>
#include <vlc_plugin.h>
......@@ -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 );
}
/*****************************************************************************
* 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 <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_aout_volume.h>
/*****************************************************************************
* 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;
}
......@@ -25,28 +25,28 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_aout_volume.h>
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;
}
......@@ -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
......
......@@ -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 \
......
......@@ -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 : */
......
......@@ -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;
......
......@@ -32,16 +32,12 @@
#include <vlc_common.h>
#include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_input.h>
#include <vlc_atomic.h>
#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;
}
......@@ -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);
}
/*****************************************************************************
* mixer.c : audio output volume operations
* volume.c : audio output volume operations
*****************************************************************************
* Copyright (C) 2002-2004 VLC authors and VideoLAN
* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* 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
......@@ -21,9 +19,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
......@@ -35,69 +30,120 @@
#include <libvlc.h>
#include <vlc_modules.h>
#include <vlc_aout.h>
#include <vlc_aout_mixer.h>
#include <vlc_aout_volume.h>
#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
struct aout_volume
{
audio_mixer_t volume;
} aout_volume_t;
audio_volume_t object;
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)
{
return (aout_volume_t *)volume;
}
static int ReplayGainCallback (vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void *);
#undef aout_MixerNew
#undef aout_volume_New
/**
* 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),
"volume");
if (unlikely(mixer == NULL))
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;
mixer->format = format;
mixer->mix = NULL;
mixer->module = module_need(mixer, "audio mixer", NULL, false);
if (mixer->module == NULL)
audio_volume_t *obj = &vol->object;
if (vol->module != NULL)
{
vlc_object_release(mixer);
mixer = NULL;
if (obj->format == format)
{
msg_Dbg (obj, "retaining sample format");
return 0;
}
msg_Dbg (obj, "changing sample format");
module_unneed(obj, vol->module);
}
return mixer;
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_MixerDelete(audio_mixer_t *mixer)
void aout_volume_Delete(aout_volume_t *vol)
{
if (mixer == NULL)
if (vol == NULL)
return;
module_unneed(mixer, mixer->module);
vlc_object_release(mixer);
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.
*/
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 ***/
float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str,
const audio_replay_gain_t *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;
......@@ -137,3 +183,14 @@ float (aout_ReplayGainSelect)(vlc_object_t *obj, const char *str,
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
aout_FormatPrepare
aout_FormatPrint
aout_FormatPrintChannels
aout_MixerDelete
aout_MixerNew
aout_MixerRun
aout_VolumeGet
aout_VolumeSet
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