Commit 999a7af7 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont Committed by 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 39ee3d11)
(cherry picked from commit a4e7d801)
(cherry picked from commit 0baa0d81)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 22098cd4
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
# include "config.h" # include "config.h"
#endif #endif
#include <math.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
#include <vlc_aout.h> #include <vlc_aout.h>
...@@ -73,6 +75,7 @@ struct aout_sys_t ...@@ -73,6 +75,7 @@ struct aout_sys_t
LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
* takes care of mixing all the * takes care of mixing all the
* secondary buffers into the primary) */ * secondary buffers into the primary) */
LONG volume;
notification_thread_t notif; /* DirectSoundThread id */ notification_thread_t notif; /* DirectSoundThread id */
...@@ -93,6 +96,7 @@ struct aout_sys_t ...@@ -93,6 +96,7 @@ struct aout_sys_t
static int OpenAudio ( vlc_object_t * ); static int OpenAudio ( vlc_object_t * );
static void CloseAudio ( vlc_object_t * ); static void CloseAudio ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * ); static void Play ( audio_output_t *, block_t * );
static int VolumeSet ( audio_output_t *, float, bool );
/* local functions */ /* local functions */
static void Probe ( audio_output_t * ); static void Probe ( audio_output_t * );
...@@ -228,6 +232,7 @@ static int OpenAudio( vlc_object_t *p_this ) ...@@ -228,6 +232,7 @@ static int OpenAudio( vlc_object_t *p_this )
} }
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB ); aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
p_aout->sys->volume = -1;
aout_VolumeNoneInit( p_aout ); aout_VolumeNoneInit( p_aout );
} }
else else
...@@ -282,7 +287,7 @@ static int OpenAudio( vlc_object_t *p_this ) ...@@ -282,7 +287,7 @@ static int OpenAudio( vlc_object_t *p_this )
/* Calculate the frame size in bytes */ /* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format ); aout_FormatPrepare( &p_aout->format );
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE ); 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 */ /* Now we need to setup our DirectSound play notification structure */
...@@ -569,6 +574,34 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer ) ...@@ -569,6 +574,34 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
p_aout->pf_play = aout_PacketPlay; p_aout->pf_play = aout_PacketPlay;
} }
/*****************************************************************************
* 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 * CloseAudio: close the audio device
*****************************************************************************/ *****************************************************************************/
...@@ -792,7 +825,8 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format, ...@@ -792,7 +825,8 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ 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 */ /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
if( i_nb_channels <= 2 ) if( i_nb_channels <= 2 )
...@@ -1031,6 +1065,11 @@ static void* DirectSoundThread( void *data ) ...@@ -1031,6 +1065,11 @@ static void* DirectSoundThread( void *data )
mtime_t mtime = mdate(); mtime_t mtime = mdate();
int i; 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 * Fill in as much audio data as we can in our circular buffer
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment