[vlc-devel] [PATCH] Use waveOutSetVolume to set volume instead of pure software gain

Rémi Denis-Courmont remi at remlab.net
Wed Jan 16 13:21:17 CET 2013


On Wed, 16 Jan 2013 00:47:16 +0100, Denis Charmet <typx at dinauz.org> wrote:
> @@ -111,8 +113,9 @@ struct aout_sys_t
>  
>      uint8_t *p_silence_buffer;              /* buffer we use to play
>      silence */
>  
> -    float soft_gain;
> -    bool soft_mute;
> +    bool b_soft;                            /* Use software gain */
> +    float f_volume;
> +    bool b_mute;

Suboptimal packing.

>      uint8_t chans_to_reorder;              /* do we need channel
>      reordering */
>      uint8_t chan_table[AOUT_CHAN_MAX];
> @@ -126,8 +129,6 @@ struct aout_sys_t
>      vlc_cond_t cond;
>  };
>  
> -#include "volume.h"
> -
> 
/*****************************************************************************
>   * Module descriptor
>  
*****************************************************************************/
> @@ -137,6 +138,9 @@ struct aout_sys_t
>                         "to apply.")
>  #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device")
>  
> +#define VOLUME_TEXT N_("WaveOut audio volume")
> +#define VOLUME_LONGTEXT N_("Use this volume at start of the audio
output")

Use the exact same translated string as other outputs.

> +
>  vlc_module_begin ()
>      set_shortname( "WaveOut" )
>      set_description( N_("Win32 waveOut extension output") )
> @@ -147,7 +151,9 @@ vlc_module_begin ()
>      add_string( "waveout-audio-device", "wavemapper",
>                   DEVICE_TEXT, DEVICE_LONG, false )
>         change_string_cb( ReloadWaveoutDevices )
> -    add_sw_gain( )
> +
> +    add_float( "waveout-volume", 1.0f, VOLUME_TEXT, VOLUME_LONGTEXT,
true
> )
> +         change_float_range(0.0f, 2.0f)
>  
>      add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true
)
>  
> @@ -168,6 +174,9 @@ static int Start( audio_output_t *p_aout,
> audio_sample_format_t *restrict fmt )
>      p_aout->pause = WaveOutPause;
>      p_aout->flush = WaveOutFlush;
>  
> +    /* Default behaviour is to use software gain */
> +    p_aout->sys->b_soft = true;
> +
>      /*
>        check for configured audio device!
>      */
> @@ -273,7 +282,11 @@ static int Start( audio_output_t *p_aout,
> audio_sample_format_t *restrict fmt )
>          aout_FormatPrepare( fmt );
>          p_aout->sys->i_buffer_size = FRAME_SIZE *
fmt->i_bytes_per_frame;
>  
> -        aout_SoftVolumeStart( p_aout );
> +        if( waveoutcaps.dwSupport & WAVECAPS_VOLUME )
> +            p_aout->sys->b_soft = false;
> +
> +        WaveoutVolumeSet( p_aout,
> +                          p_aout->sys->b_mute? 0.0f :
> p_aout->sys->f_volume );

I think setting volume to zero on mute will confuse the state machine a
bit.

>  
>          p_aout->sys->b_spdif = false;
>      }
> @@ -850,7 +863,14 @@ static int Open(vlc_object_t *obj)
>      aout->sys = sys;
>      aout->start = Start;
>      aout->stop = Stop;
> -    aout_SoftVolumeInit(aout);
> +    aout->volume_set = WaveoutVolumeSet;
> +    aout->mute_set = WaveoutMuteSet;
> +
> +    sys->f_volume = var_InheritFloat(aout, "waveout-volume");
> +    sys->b_mute = var_InheritBool(aout, "mute");
> +
> +    aout_MuteReport(aout, sys->b_mute);
> +    aout_VolumeReport(aout, sys->f_volume );
>  
>      vlc_mutex_init( &sys->lock );
>      vlc_cond_init( &sys->cond );
> @@ -913,7 +933,7 @@ static void WaveOutPause( audio_output_t * p_aout,
> bool pause, mtime_t date)
>  {
>      MMRESULT res;
>      (void) date;
> -    if(pause)
> +    if( pause )
>      {
>          res = waveOutPause( p_aout->sys->h_waveout );
>          if( res != MMSYSERR_NOERROR )

Unrelated cosmetic change.

> @@ -932,3 +952,95 @@ static void WaveOutPause( audio_output_t * p_aout,
> bool pause, mtime_t date)
>          }
>      }
>  }
> +
> +static int WaveoutVolumeSet( audio_output_t *p_aout, float volume )
> +{
> +    aout_sys_t *sys = p_aout->sys;
> +
> +    if( sys->b_soft )
> +    {
> +        float gain = volume * volume * volume;
> +        if ( !sys->b_mute && aout_GainRequest( p_aout, gain ) )
> +            return -1;

This:

> +
> +        sys->f_volume = volume;
> +
> +        if( var_InheritBool( p_aout, "volume-save" ) )
> +            config_PutFloat( p_aout, "waveout-volume", volume );
> +
> +        aout_VolumeReport( p_aout, volume);

...could be factored regardless of b_soft.

> +        return 0;
> +    }
> +
> +    const HWAVEOUT hwo = sys->h_waveout;
> +
> +    uint32_t vol = lroundf( volume * 0xffff.fp0 );
> +
> +    if( !sys->b_mute )
> +    {
> +        if( vol > 0xffff )
> +        {
> +            vol = 0xffff;
> +            /* Apply software gain: volume^3 comes from volume.h */
> +            if( aout_GainRequest( p_aout, volume * volume * volume ) )
> +            {
> +                msg_Err(p_aout, "Couldn't set soft gain to %f", volume
);
> +                volume = 1.0f;
> +            }
> +        }
> +        else if( volume <= 1.0f && sys->f_volume > 1.0f )
> +        {
> +            /* Reset Gain to 1.0f */
> +            if( aout_GainRequest( p_aout, 1.0f ) )
> +                msg_Err(p_aout, "Couldn't set soft gain back to 1.0" );
> +        }

I do not believe that software gain is needed. In all previous VLC
versions, the then maximum VLC volume (400%) was mapped to the maximum
WaveOut volume. You would obtain the same scale with:

> +
> +        MMRESULT r = waveOutSetVolume(hwo, vol | (vol << 16));
> +        if(r != MMSYSERR_NOERROR)
> +        {
> +            msg_Err( p_aout, "waveOutSetVolume failed (%u)", r );
> +            return -1;
> +        }
> +    }
> +
> +    sys->f_volume = volume;
> +
> +    if( var_InheritBool( p_aout, "volume-save" ) )
> +        config_PutFloat( p_aout, "waveout-volume", volume );
> +
> +    aout_VolumeReport( p_aout, volume );
> +    return 0;
> +}
> +
> +static int WaveoutMuteSet( audio_output_t * p_aout, bool mute )
> +{
> +    aout_sys_t *sys = p_aout->sys;
> +
> +    if( sys->b_soft )
> +    {
> +        float gain = sys->f_volume * sys->f_volume * sys->f_volume; 
> +        if ( aout_GainRequest( p_aout, mute ? 0.f : gain ) )
> +            return -1;

This could be factored too...

> +        sys->b_mute = mute;
> +
> +        aout_MuteReport( p_aout, mute);
> +        return 0;
> +    }
> +
> +    const HWAVEOUT hwo = sys->h_waveout;
> +    uint32_t vol = mute ? 0 : lroundf( sys->f_volume * 0xffff.fp0 );
> +
> +    if( vol > 0xffff )
> +        vol = 0xffff;
> +
> +    MMRESULT r = waveOutSetVolume( hwo, vol | ( vol << 16 ) );
> +    if( r != MMSYSERR_NOERROR )
> +    {
> +        msg_Err( p_aout, "waveOutSetVolume failed (%u)", r );
> +        return -1;
> +    }
> +
> +    sys->b_mute = mute;
> +    aout_MuteReport( p_aout, mute );
> +    return 0;
> +}

-- 
Rémi Denis-Courmont
Sent from my collocated server



More information about the vlc-devel mailing list