[vlc-devel] [PATCH] DirectSound: apply volume attenuation with DirectSound

Rémi Denis-Courmont remi at remlab.net
Sun May 6 15:34:10 CEST 2012


This should keep the volume latency under 20 ms. This will break
amplification as DirectSound is only capable of attenuation.

This patch compiles but is otherwise entirely untested.
---
 modules/audio_output/directx.c |   41 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/modules/audio_output/directx.c b/modules/audio_output/directx.c
index 4cd8c99..7b36f97 100644
--- a/modules/audio_output/directx.c
+++ b/modules/audio_output/directx.c
@@ -29,6 +29,8 @@
 # include "config.h"
 #endif
 
+#include <math.h>
+
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_aout.h>
@@ -73,6 +75,7 @@ struct aout_sys_t
     LPDIRECTSOUNDBUFFER p_dsbuffer;   /* the sound buffer we use (direct sound
                                        * takes care of mixing all the
                                        * secondary buffers into the primary) */
+    LONG                volume;
 
     notification_thread_t notif;                  /* DirectSoundThread id */
 
@@ -93,6 +96,7 @@ struct aout_sys_t
 static int  OpenAudio  ( vlc_object_t * );
 static void CloseAudio ( vlc_object_t * );
 static void Play       ( audio_output_t *, block_t * );
+static int  VolumeSet  ( audio_output_t *, float, bool );
 
 /* local functions */
 static void Probe             ( audio_output_t * );
@@ -228,6 +232,7 @@ static int OpenAudio( vlc_object_t *p_this )
         }
 
         aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
+        p_aout->sys->volume = -1;
         aout_VolumeNoneInit( p_aout );
     }
     else
@@ -282,7 +287,7 @@ static int OpenAudio( vlc_object_t *p_this )
         /* Calculate the frame size in bytes */
         aout_FormatPrepare( &p_aout->format );
         aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
-        aout_VolumeSoftInit( p_aout );
+        aout_VolumeHardInit( p_aout, VolumeSet, true );
     }
 
     /* Now we need to setup our DirectSound play notification structure */
@@ -570,6 +575,35 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
 }
 
 /*****************************************************************************
+ * VolumeSet: change audio device volume
+ *****************************************************************************/
+static int VolumeSet( audio_output_t *p_aout, float vol, bool mute )
+{
+    aout_sys_t *sys = p_aout->sys;
+    LONG volume;
+    float f = vol;
+
+    if( mute )
+        f = 0.;
+    /* Convert UI volume percentage to linear factor (cube) */
+    f = f * f * f;
+
+    /* "DirectSound does not support amplification." -- MSDN */
+    if( f > 1. )
+        f = 1.;
+
+    /* millibels from linear amplification */
+    if( f <= powf(10., DSBVOLUME_MIN / -2000.) )
+        volume = DSBVOLUME_MIN;
+    else
+        volume = lroundf(-2000. * log10f(f));
+
+    InterlockedExchange(&sys->volume, volume);
+    aout_VolumeHardSet( p_aout, vol, mute );
+    return 0;
+}
+
+/*****************************************************************************
  * CloseAudio: close the audio device
  *****************************************************************************/
 static void CloseAudio( vlc_object_t *p_this )
@@ -1031,6 +1065,11 @@ static void* DirectSoundThread( void *data )
         mtime_t mtime = mdate();
         int i;
 
+        /* Update volume if required */
+        LONG volume = InterlockedExchange( &p_aout->sys->volume, -1 );
+        if( unlikely(volume != -1) )
+            IDirectSoundBuffer_SetVolume( p_aout->sys->p_dsbuffer, volume );
+
         /*
          * Fill in as much audio data as we can in our circular buffer
          */
-- 
1.7.10




More information about the vlc-devel mailing list