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

Denis Charmet typx at dinauz.org
Tue Jan 15 01:48:42 CET 2013


---
 modules/audio_output/waveout.c |   76 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/modules/audio_output/waveout.c b/modules/audio_output/waveout.c
index 6e72d79..e3d58b8 100644
--- a/modules/audio_output/waveout.c
+++ b/modules/audio_output/waveout.c
@@ -82,6 +82,8 @@ 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 const wchar_t device_name_fmt[] = L"%ls ($%x,$%x)";
 
@@ -273,7 +275,18 @@ 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 );
+        WAVEOUTCAPS caps;
+        if( waveOutGetDevCaps( p_aout->sys->i_wave_device_id, 
+                               &caps,
+                               sizeof( WAVEOUTCAPS ) ) == MMSYSERR_NOERROR &&
+            caps.dwSupport & WAVECAPS_VOLUME )
+        {
+            p_aout->volume_set = WaveoutVolumeSet;
+            p_aout->mute_set = WaveoutMuteSet;
+            WaveoutVolumeSet( p_aout, p_aout->sys->soft_gain );
+        }
+        else
+            aout_SoftVolumeStart( p_aout );
 
         p_aout->sys->b_spdif = false;
     }
@@ -913,7 +926,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 )
@@ -932,3 +945,62 @@ 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;
+    const HWAVEOUT hwo = sys->h_waveout;
+
+    uint32_t vol = lroundf( volume * 0xffff.fp0 );
+
+    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->soft_gain > 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" );
+    }
+
+    if( !sys->soft_mute )
+    {
+        MMRESULT r = waveOutSetVolume(hwo, vol | (vol << 16));
+        if(r != MMSYSERR_NOERROR)
+        {
+            msg_Err( p_aout, "waveOutSetVolume failed (%u)", r );
+            return -1;
+        }
+    }
+    sys->soft_gain = 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;
+    const HWAVEOUT hwo = sys->h_waveout;
+    uint32_t vol = mute ? 0 : lroundf( sys->soft_gain * 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->soft_mute = mute;
+    aout_MuteReport( p_aout, mute );
+    return 0;
+}
-- 
1.7.10.4




More information about the vlc-devel mailing list