]> git.sesse.net Git - vlc/commitdiff
aout: cleanup mixer and rename to volume
authorRémi Denis-Courmont <remi@remlab.net>
Tue, 17 Jul 2012 19:47:59 +0000 (22:47 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 17 Jul 2012 19:49:59 +0000 (22:49 +0300)
13 files changed:
include/vlc_aout_volume.h [moved from include/vlc_aout_mixer.h with 76% similarity]
modules/audio_filter/gain.c
modules/audio_mixer/float32.c
modules/audio_mixer/integer.c
po/POTFILES.in
src/Makefile.am
src/audio_output/aout_internal.h
src/audio_output/common.c
src/audio_output/dec.c
src/audio_output/mixer.c [deleted file]
src/audio_output/output.c
src/audio_output/volume.c [new file with mode: 0644]
src/libvlccore.sym

similarity index 76%
rename from include/vlc_aout_mixer.h
rename to include/vlc_aout_volume.h
index b3bf37bb5a3ae1f0c54f0df0ce56760cda291767..051413ba105d5f7ee552679bf7fcd3a053db112c 100644 (file)
@@ -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$
 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
index b137823a63e149865947abe06a982e82bc792fba..68e689a902ccbbd6f57e8a47ff1be70d1010cf9c 100644 (file)
@@ -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 );
 }
index 0e52a64dd54fae7c8c2731cedb6f47ee14ffdf41..912da1598960dd3ee8b2cd5f84bb53f3d38fa799 100644 (file)
@@ -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$
 #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;
 }
index 8d2c3fc8282ed244e77b8ea8789decb18434ee0d..a64862bf9077fec6efa1affa2ce52fd1e21572c9 100644 (file)
 #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;
 }
index d01c9a65dc128abbb18c289060da2765b7ab1008..7114653f73f7ecbcc4185d96d1d23177c9882a55 100644 (file)
@@ -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
index d6d083ec7a0761ce2d0ef4eeaf598e172542ed5a..c6e874ddecedd3ecb1df544438b3ab83637f6cd4 100644 (file)
@@ -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 \
index 463661ff669f2cf1ff390c1dafe6ba7a44b1d87f..86775ed15344b5c54bedbc8a9f6fe660d833d7df 100644 (file)
@@ -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 : */
index f557fcbb4e2de86054e5566959a65830d2a39904..4907ba478167b8335dd4159661e4d7ac329fba51 100644 (file)
@@ -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;
index a4fe78db2b809ec4b6c8ed194f6594a6cfaba76b..0bc2e66d9639f00455f6b3e42d2d932470f892ab 100644 (file)
 
 #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;
-}
diff --git a/src/audio_output/mixer.c b/src/audio_output/mixer.c
deleted file mode 100644 (file)
index 28b3faf..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*****************************************************************************
- * mixer.c : audio output volume operations
- *****************************************************************************
- * Copyright (C) 2002-2004 VLC authors and VideoLAN
- * $Id$
- *
- * Authors: Christophe Massiot <massiot@via.ecp.fr>
- *
- * 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 <stddef.h>
-#include <math.h>
-
-#include <vlc_common.h>
-#include <libvlc.h>
-#include <vlc_modules.h>
-#include <vlc_aout.h>
-#include <vlc_aout_mixer.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
-{
-    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;
-}
index 98d829c18a880024eb8d172e70de758f6f6223ff..e6e57add626869d41677fc2678f2566cce4ceb10 100644 (file)
@@ -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 (file)
index 0000000..afb7e67
--- /dev/null
@@ -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 <stddef.h>
+#include <math.h>
+
+#include <vlc_common.h>
+#include <libvlc.h>
+#include <vlc_modules.h>
+#include <vlc_aout.h>
+#include <vlc_aout_volume.h>
+#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;
+}
index 84491852e05751b4ad994b4f483e2dbed68be086..53ca43d2dcc263d9d48254c782e7a9825066025f 100644 (file)
@@ -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