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 39ee3d11eb7da54f58e42bdf2463cbaaa8661456)
(cherry picked from commit a4e7d80196972f8f236219d51e2777c86fcb6aeb)
(cherry picked from commit 0baa0d815b0d00574111af6a0275ee62c316b589)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 22098cd4
......@@ -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 */
......@@ -569,6 +574,34 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
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
*****************************************************************************/
......@@ -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
*/
......
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