[vlc-commits] DirectSound: apply volume attenuation with DirectSound

Rémi Denis-Courmont git at videolan.org
Wed Jun 6 23:28:11 CEST 2012


vlc/vlc-2.0 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun May  6 16:34:10 2012 +0300| [999a7af728544436952c0fa6f99ae2c3249cca44] | committer: Jean-Baptiste Kempf

DirectSound: apply volume attenuation with DirectSound

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

(cherry picked from commit 39ee3d11eb7da54f58e42bdf2463cbaaa8661456)
(cherry picked from commit a4e7d80196972f8f236219d51e2777c86fcb6aeb)
(cherry picked from commit 0baa0d815b0d00574111af6a0275ee62c316b589)

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.0.git/?a=commit;h=999a7af728544436952c0fa6f99ae2c3249cca44
---

 modules/audio_output/directx.c |   43 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/modules/audio_output/directx.c b/modules/audio_output/directx.c
index 6945ce8..df3f04c 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,34 @@ 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;
+
+    /* Convert UI volume to linear factor (cube) */
+    vol = vol * vol * vol;
+
+    /* millibels from linear amplification */
+    LONG mb = lroundf(2000.f * log10f(vol));
+
+    /* Clamp to allowed DirectSound range */
+    static_assert( DSBVOLUME_MIN < DSBVOLUME_MAX, "DSBVOLUME_* confused" );
+    if( mb >= DSBVOLUME_MAX )
+        mb = DSBVOLUME_MAX;
+    if( mb <= DSBVOLUME_MIN )
+        mb = DSBVOLUME_MIN;
+
+    InterlockedExchange(&sys->volume, mute ? DSBVOLUME_MIN : mb);
+
+    /* Convert back to UI volume */
+    vol = cbrtf(powf(10.f, ((float)mb) / -2000.f));
+    aout_VolumeHardSet( p_aout, vol, mute );
+    return 0;
+}
+
+/*****************************************************************************
  * CloseAudio: close the audio device
  *****************************************************************************/
 static void CloseAudio( vlc_object_t *p_this )
@@ -792,7 +825,8 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
     dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
-                    | DSBCAPS_GLOBALFOCUS;      /* Allows background playing */
+                    | DSBCAPS_GLOBALFOCUS       /* Allows background playing */
+                    | DSBCAPS_CTRLVOLUME;       /* Allows volume control */
 
     /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
     if( i_nb_channels <= 2 )
@@ -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
          */



More information about the vlc-commits mailing list