Windows用于音量滑块的对数函数是什么?

时间:2018-01-09 10:25:09

标签: c++ windows audio volume

我目前正在努力在我的c ++应用程序中实现音频音量滑块。

该应用程序可以控制Windows混音器音量级别,滑块的范围为0.0f至1.0f。

我面临的问题是我的数据库值不等于Windows正在使用的数据库值。

以下是我使用音量滑块设置的一些值,其中包含生成的数据库值以及正在使用的窗口。

enter image description here

以下是我用于计算音频数据库级别的功能。我在这里做错了什么?

提前谢谢!

    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(&currentValue);

        // Todo: The calculation has to be logarithmic
        m_pEndpointVolume->SetMasterVolumeLevel(calcVolume, NULL);
    }

2 个答案:

答案 0 :(得分:1)

假设如下:

volumeMaxDB =  +5
volumeMinDB = -10
incrementDB = 5

对我来说,这表明滑块看起来像下面的ascii艺术。我还假设我的假设映射到滑块UI的比例。

        dB        Slider
     |  +5   <=>   1.0
     |   0
     -  -5
     |  -10  <=>   0.0

首先,以dB为单位计算总音量范围(例如-10到+5为15 dB)

dBRange = abs(volumeMaxDB) + abs(volumeMinDB);

其次,将当前滑块位置dB值0缩放为dBRange。这给出了以下映射 * 0.0 - &gt; 0 * 1.0 - &gt; 15 * 0.5 - &gt; 7.5

dB = dBRange * slider;

第三,向上或向下移动范围,使+15变为+5,0变为-10。

dB = dB - (dbRange - volumeMaxDB);

最后,您可能希望舍入到最接近的dB增量。

额外的功劳:如果您可以控制滑块的范围,只需将min和max值设置为与minDB和maxDB相同,就可以简化生活方式用它。

答案 1 :(得分:0)

我找到了解决方案。

IAudioEndpointVolume 具有 SetMasterVolumeLevelScalar 功能。对于MSDN文档,此函数使用0.0到1.0的范围,因此您不需要自己实现对数函数。 好像我忽略了这个。

这是我正在使用的当前代码示例,以防将来有人需要它。

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);

修改

似乎Windows正在使用线性音量滑块。这就是为什么Windows中的2%感觉仍然太大而且50%以上的所有内容都不再增加的原因。

这是一篇非常好的文章,说明为什么要避免它。

Volume Controls