windows 对音量滑块使用什么对数函数?
What logarithmic function do windows use for the audio volume slider?
我目前正努力在我的 C++ 应用程序中实现音量滑块。
该应用能够控制 windows 混音器的音量,滑块的范围是 0.0f 到 1.0f。
我面临的问题是我的数据库值不等于 windows 正在使用的数据库值。
以下是我使用音量滑块设置的一些值以及生成的 DB 值和 windows 正在使用的值。
下面是我用来计算音频 DB 电平的函数。我在这里做错了什么?
提前致谢!
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);
}
假设如下:
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 -> 0
* 1.0 -> 15
* 0.5 -> 7.5
dB = dBRange * slider;
第三,向上或向下移动范围,使 +15 变为 +5,0 变为 -10。
dB = dB - (dbRange - volumeMaxDB);
最后,您可能希望四舍五入到最接近的 dB 增量。
额外功劳:如果您可以控制滑块的范围,只需将最小值和最大值设置为与 minDB 和 maxDB 相同并完成它。
我找到了解决方案。
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% 的所有内容都不再增加太多的原因。
这里有一篇非常好的文章介绍了为什么您应该避免使用它。
我目前正努力在我的 C++ 应用程序中实现音量滑块。
该应用能够控制 windows 混音器的音量,滑块的范围是 0.0f 到 1.0f。
我面临的问题是我的数据库值不等于 windows 正在使用的数据库值。
以下是我使用音量滑块设置的一些值以及生成的 DB 值和 windows 正在使用的值。
下面是我用来计算音频 DB 电平的函数。我在这里做错了什么?
提前致谢!
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);
}
假设如下:
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 -> 0 * 1.0 -> 15 * 0.5 -> 7.5
dB = dBRange * slider;
第三,向上或向下移动范围,使 +15 变为 +5,0 变为 -10。
dB = dB - (dbRange - volumeMaxDB);
最后,您可能希望四舍五入到最接近的 dB 增量。
额外功劳:如果您可以控制滑块的范围,只需将最小值和最大值设置为与 minDB 和 maxDB 相同并完成它。
我找到了解决方案。
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% 的所有内容都不再增加太多的原因。
这里有一篇非常好的文章介绍了为什么您应该避免使用它。