[vlc-commits] mmdevice: use craptastic software gain

Rémi Denis-Courmont git at videolan.org
Wed Nov 12 21:12:12 CET 2014


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Nov 12 21:03:13 2014 +0200| [5e98fc504ac9c0569ea4d0e00608db7b8088b2dc] | committer: Rémi Denis-Courmont

mmdevice: use craptastic software gain

The same caveats apply as for Windows legacy (and ALSA) outputs:
- Change latency is high and noticeable.
- Change between less than 100% and more than 100% occurs in two steps.
- Non-linear formats are not supported at all.
- Integer formats are prone to clipping/saturation.
- Floating formats may hit Windows peak protection, sounding awful.
In other words, it does not work properly and it never will. This will
be removed once minimum and maximum volumes are exposed properly.

As meager consolation, there are two advantages over endpoint volume:
- The code is much simpler.
- Other audio sessions are not affected.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5e98fc504ac9c0569ea4d0e00608db7b8088b2dc
---

 modules/audio_output/mmdevice.c |   19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/modules/audio_output/mmdevice.c b/modules/audio_output/mmdevice.c
index a7871c5..d9d3573 100644
--- a/modules/audio_output/mmdevice.c
+++ b/modules/audio_output/mmdevice.c
@@ -117,6 +117,7 @@ struct aout_sys_t
 
     LONG refs;
     unsigned ducks;
+    float gain; /**< Current software gain volume */
 
     wchar_t *device; /**< Requested device identifier, NULL if none */
     float volume; /**< Requested volume, negative if none */
@@ -197,9 +198,20 @@ static void Flush(audio_output_t *aout, bool wait)
 static int VolumeSet(audio_output_t *aout, float vol)
 {
     aout_sys_t *sys = aout->sys;
+    float gain = 1.f;
 
     vol = vol * vol * vol; /* ISimpleAudioVolume is tapered linearly. */
+
+    if (vol > 1.f)
+    {
+        gain = vol;
+        vol = 1.f;
+    }
+
+    aout_GainRequest(aout, gain);
+
     EnterCriticalSection(&sys->lock);
+    sys->gain = gain;
     sys->volume = vol;
     WakeConditionVariable(&sys->work);
     LeaveCriticalSection(&sys->lock);
@@ -923,16 +935,13 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
 
             hr = ISimpleAudioVolume_GetMasterVolume(volume, &level);
             if (SUCCEEDED(hr))
-                aout_VolumeReport(aout, cbrtf(level));
+                aout_VolumeReport(aout, cbrtf(level * sys->gain));
             else
                 msg_Err(aout, "cannot get master volume (error 0x%lx)", hr);
 
             level = sys->volume;
             if (level >= 0.f)
             {
-                if (level > 1.f)
-                    level = 1.f;
-
                 hr = ISimpleAudioVolume_SetMasterVolume(volume, level, NULL);
                 if (FAILED(hr))
                     msg_Err(aout, "cannot set master volume (error 0x%lx)",
@@ -1091,6 +1100,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 
     assert (sys->stream == NULL);
     sys->stream = s;
+    aout_GainRequest(aout, sys->gain);
     return 0;
 }
 
@@ -1128,6 +1138,7 @@ static int Open(vlc_object_t *obj)
     sys->ducks = 0;
 
     sys->device = default_device;
+    sys->gain = 1.f;
     sys->volume = -1.f;
     sys->mute = -1;
     InitializeCriticalSection(&sys->lock);



More information about the vlc-commits mailing list