I am currently struggling with the implementation of my audio volume slider in my c++ app.
The app is able to control the windows mixer volume level and the slider has the range 0.0f to 1.0f.
The problem I am facing is that my DB values aren't equal to the DB values windows is using.
Here are some values I set with my volume slider with the resulting DB values and the ones windows is using.
Below is the function I use for calculating the audio DB level. What am I doing wrong here?
Thank you in advance!
if (this->m_useAudioEndpointVolume)
{
const float slider_min = 0.0f;
const float slider_max = 1.0f;
const float logBase = 10;
m_ignoreAudioValue = TRUE;
if (volume >= 1.0f) {
volume = 1.0f;
}
if (volume <= 0.0f) {
volume = 0.0f;
}
float pfLevelMinDB = 0;
float pfLevelMaxDB = 0;
float pfVolumeIncrementDB = 0;
m_pEndpointVolume->GetVolumeRange(&pfLevelMinDB, &pfLevelMaxDB, &pfVolumeIncrementDB);
// Logarithmic formula for audio volume
// Volume = log(((Slider.Value-Slider.Min)*(B-1))/(Slider.Max-Slider.Min) + 1)/log(B) * (Volume.Max - Volume.Min) + Volume.Min
float calcVolume = log(((volume - slider_min)*(logBase - 1)) / (slider_max - slider_min) + 1) / log(logBase) * (pfLevelMaxDB - pfLevelMinDB) + pfLevelMinDB;
if (volume == 0.0f) {
m_pEndpointVolume->SetMute(TRUE, NULL);
}
else
{
m_pEndpointVolume->SetMute(FALSE, NULL);
}
float currentValue = 0.0f;
m_pEndpointVolume->GetMasterVolumeLevel(¤tValue);
// Todo: The calculation has to be logarithmic
m_pEndpointVolume->SetMasterVolumeLevel(calcVolume, NULL);
}
I found the solution.
The IAudioEndpointVolume has the function SetMasterVolumeLevelScalar. This function uses the range from 0.0 to 1.0 regarding to the MSDN documentation so you don't need to implement a logarithmic function yourself. Seems like I overlooked this one.
Here's the current code sample I am using in case someone will need it in the future.
float pLevel = 0.0f;
m_pEndpointVolume->GetMasterVolumeLevelScalar(&pLevel);
// We have to set this first to TRUE to an avoid unnecessary callback
m_ignoreAudioValue = TRUE;
// Set the scalar value
// https://msdn.microsoft.com/de-de/library/windows/desktop/dd368062(v=vs.85).aspx
m_pEndpointVolume->SetMasterVolumeLevelScalar(sliderValue, NULL);
// We have to set this again to TRUE to avoid an unnecessary callback
// because the SetMasterVolumeLevelScalar triggers the OnNotify event
// and this causes the m_ignoreAudioValue to be FALSE again.
m_ignoreAudioValue = TRUE;
// If the value is higher the 0.0 unmute the master volume.
m_pEndpointVolume->SetMute(sliderValue > 0.0f ? FALSE : TRUE, NULL);
m_pEndpointVolume->GetMasterVolumeLevelScalar(&pLevel);
Edit:
It seems like Windows is using a linear volume slider. Thats the reason why 2% in Windows feels still too loud and everything above 50% isn't much of an increase anymore.
Here's a really good article about it why you should avoid it.