前段時間仔細研究了一下音量曲線的問題。眾所周知,人耳對聲音強度的感知不是線性,而是具有對數關係。所以理想的音量曲線應該是音量級數調節與音量大小的對數成線性關係。即:
-20lg(y) = a * (x - b)
假設音量級數為M,則有: x = M 時 -20lg(y) = 0dB ==> b = M
由此得到: -20lg(y) = a * (x - M)
假設最大音量範圍為N dB, 則有: x = 0時, -20lg(y) = -NdB ==> a = N / M
由此得: -20lg(y) = (N/M) * (x - M)
從上面的計算,我們得到兩個有趣的係數:
- a = N / M
- a * ln(10) / 20
閱讀Android代碼發現M = 100, N = 50
由此得到: a = 0.5 a * ln(10) / 20 = 0.5 * 2.302585093 / 20
以下是Android中用於計算音量的函數:
// convert volume steps to natural log scale
// change this value to change volume scaling
static const float dBPerStep = 0.5f;
// shouldn't need to touch these
static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;
static const float dBConvertInverse = 1.0f / dBConvert;
float AudioSystem::linearToLog(int volume)
{
// float v = volume ? exp(float(100 - volume) * dBConvert) : 0;
// LOGD("linearToLog(%d)=%f", volume, v);
// return v;
return volume ? exp(float(100 - volume) * dBConvert) : 0;
}