[vlc-devel] [PATCH] Use waveOutSetVolume to set volume instead of pure software gain
Rémi Denis-Courmont
remi at remlab.net
Thu Jan 17 23:20:30 CET 2013
Hello,
You could create/destroy the timer in Open()/Close() and (dis)arm it in
Pause(). Play() can probably be used to poll while not paused.
In the long term, a timer kinda sucks though. On Windows Vista+, reusing
mmdevice would be better. On XP, the timer is probably useless anyway, since
there is no per-application mixer control.
Le jeudi 17 janvier 2013 23:56:24, Denis Charmet a écrit :
> ---
> modules/audio_output/waveout.c | 166
> +++++++++++++++++++++++++++++++++++++--- 1 file changed, 157
> insertions(+), 9 deletions(-)
>
> diff --git a/modules/audio_output/waveout.c
> b/modules/audio_output/waveout.c index 6e72d79..05a67dd 100644
> --- a/modules/audio_output/waveout.c
> +++ b/modules/audio_output/waveout.c
> @@ -82,6 +82,10 @@ static uint32_t findDeviceID(char *);
> static int WaveOutTimeGet(audio_output_t * , mtime_t *);
> static void WaveOutFlush( audio_output_t *, bool);
> static void WaveOutPause( audio_output_t *, bool, mtime_t);
> +static int WaveoutVolumeSet(audio_output_t * p_aout, float volume);
> +static int WaveoutMuteSet(audio_output_t * p_aout, bool mute);
> +
> +static void WaveoutPollVolume( void * );
>
> static const wchar_t device_name_fmt[] = L"%ls ($%x,$%x)";
>
> @@ -107,14 +111,16 @@ struct aout_sys_t
> int i_buffer_size;
>
> int i_rate;
> - bool b_spdif;
>
> uint8_t *p_silence_buffer; /* buffer we use to play
> silence */ +
> + float f_volume;
>
> - float soft_gain;
> - bool soft_mute;
> -
> + bool b_spdif;
> + bool b_mute;
> + bool b_soft; /* Use software gain */
> uint8_t chans_to_reorder; /* do we need channel
> reordering */ +
> uint8_t chan_table[AOUT_CHAN_MAX];
> vlc_fourcc_t format;
>
> @@ -124,10 +130,9 @@ struct aout_sys_t
>
> vlc_mutex_t lock;
> vlc_cond_t cond;
> + vlc_timer_t volume_poll_timer;
> };
>
> -#include "volume.h"
> -
> /*************************************************************************
> **** * Module descriptor
>
> **************************************************************************
> ***/ @@ -137,6 +142,8 @@ struct aout_sys_t
> "to apply.")
> #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device")
>
> +#define VOLUME_TEXT N_("Audio volume")
> +
> vlc_module_begin ()
> set_shortname( "WaveOut" )
> set_description( N_("Win32 waveOut extension output") )
> @@ -147,7 +154,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, NULL, true )
> + change_float_range(0.0f, 2.0f)
>
> add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true )
>
> @@ -168,6 +177,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 +285,13 @@ 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 )
> + {
> + aout_GainRequest( p_aout, 1.0f );
> + p_aout->sys->b_soft = false;
> + }
> +
> + WaveoutMuteSet( p_aout, p_aout->sys->b_mute );
>
> p_aout->sys->b_spdif = false;
> }
> @@ -302,6 +320,15 @@ static int Start( audio_output_t *p_aout,
> audio_sample_format_t *restrict fmt ) p_aout->sys->i_played_length = 0;
> p_aout->sys->p_free_list = NULL;
>
> + /* Create and arm volume polling timer */
> + if( vlc_timer_create( &p_aout->sys->volume_poll_timer,
> + WaveoutPollVolume, p_aout ) )
> + {
> + msg_Err( p_aout, "Couldn't create volume polling timer" );
> + return VLC_ENOMEM;
> + }
> + vlc_timer_schedule( p_aout->sys->volume_poll_timer, false, 1, 200000
> ); +
> return VLC_SUCCESS;
> }
>
> @@ -459,6 +486,8 @@ static void Stop( audio_output_t *p_aout )
> {
> aout_sys_t *p_sys = p_aout->sys;
>
> + vlc_timer_destroy( p_aout->sys->volume_poll_timer );
> +
> /* Before calling waveOutClose we must reset the device */
> MMRESULT result = waveOutReset( p_sys->h_waveout );
> if(result != MMSYSERR_NOERROR)
> @@ -495,6 +524,7 @@ static void Stop( audio_output_t *p_aout )
>
> free( p_sys->p_silence_buffer );
> p_aout->sys->i_played_length = 0;
> + p_sys->b_soft = true;
> }
>
> /*************************************************************************
> **** @@ -850,7 +880,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 );
> @@ -932,3 +969,114 @@ 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;
> + }
> + else
> + {
> + const HWAVEOUT hwo = sys->h_waveout;
> +
> + uint32_t vol = lroundf( volume * 0x7fff.fp0 );
> +
> + if( !sys->b_mute )
> + {
> + if( vol > 0xffff )
> + {
> + vol = 0xffff;
> + volume = 2.0f;
> + }
> +
> + MMRESULT r = waveOutSetVolume( hwo, vol | ( vol << 16 ) );
> + if( r != MMSYSERR_NOERROR )
> + {
> + msg_Err( p_aout, "waveOutSetVolume failed (%u)", r );
> + return -1;
> + }
> + }
> + }
> +
> + vlc_mutex_lock(&p_aout->sys->lock);
> + sys->f_volume = volume;
> +
> + if( var_InheritBool( p_aout, "volume-save" ) )
> + config_PutFloat( p_aout, "waveout-volume", volume );
> +
> + aout_VolumeReport( p_aout, volume );
> + vlc_mutex_unlock(&p_aout->sys->lock);
> +
> + 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;
> + }
> + else
> + {
> +
> + const HWAVEOUT hwo = sys->h_waveout;
> + uint32_t vol = mute ? 0 : lroundf( sys->f_volume * 0x7fff.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;
> + }
> + }
> +
> + vlc_mutex_lock(&p_aout->sys->lock);
> + sys->b_mute = mute;
> + aout_MuteReport( p_aout, mute );
> + vlc_mutex_unlock(&p_aout->sys->lock);
> +
> + return 0;
> +}
> +
> +static void WaveoutPollVolume( void * aout )
> +{
> + audio_output_t * p_aout = (audio_output_t *) aout;
> + uint32_t vol;
> +
> + MMRESULT r = waveOutGetVolume( p_aout->sys->h_waveout, (LPDWORD) &vol
> ); +
> + if( r != MMSYSERR_NOERROR )
> + {
> + msg_Err( p_aout, "waveOutGetVolume failed (%u)", r );
> + return;
> + }
> +
> + float volume = (float) ( vol & UINT32_C( 0xffff ) );
> + volume /= 0x7fff.fp0;
> +
> + vlc_mutex_lock(&p_aout->sys->lock);
> + if( !p_aout->sys->b_mute && volume != p_aout->sys->f_volume )
> + {
> + p_aout->sys->f_volume = volume;
> +
> + if( var_InheritBool( p_aout, "volume-save" ) )
> + config_PutFloat( p_aout, "waveout-volume", volume );
> +
> + aout_VolumeReport( p_aout, volume );
> + }
> + vlc_mutex_unlock(&p_aout->sys->lock);
> +
> + return;
> +}
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list