【Unity】【C#】音量設定用にデシベル(dB)変換をする 
2022/06/20 Mon [edit]
これも VRM Live Viewer の音量設定を作ったときのメモ。
Unity には AudioMixer という複数の音量(Master, Music, SE, ...等)をミキシングして出力できる便利な機能があるのだけれど、設定する値は 0~1f ではなく、デシベル[dB](-80dB~0dB) なんだよね。
デシベル変換はググればいくらでも出てくるけど、定型処理なら拡張メソッドにしておくと楽なので、いつものように簡単に定義しておいたもの。
あと AudioMixer 使う際に気になる事があったので、少しばかり工夫してる。
(参考)デシベルのすすめ (KAYAC engineers' blog)
(※) Unity 2020.3.34f1 / Windows11(x64) で確認
■音量(0~1f) → デシベル(-80~0dB) に変換する
●音量(0~1f) → デシベル(-80~0dB) に変換する
using UnityEngine;
namespace Exsample
{
public static partial class Extensions //※クラス名は任意
{
//無音とみなすデジベル(dB) や音量
const float DECIBEL_MIN = -80f; //この dB 以下をミュート(音無し)とする
const float DECIBEL_MUTE = DECIBEL_MIN * 10; //単位: dB (-80dB だと僅かに聞こえる気がするので、とりあえず10倍してる)
const float VOLUME_MIN = 0.0001f; //この volume 以下をミュート(音無し)とする
/// <summary>
/// 音量(0~1f) → デシベル(-80(-800)~0dB) に変換
/// ※ただし、volume ≤ 0.0001f のとき -800 [db] を返す
/// (参考) https://techblog.kayac.com/linear-vs-decibel
/// </summary>
/// <param name="volume">0~1f</param>
/// <returns>-80(-800)~0 [dB]</returns>
public static float ToDecibel(this float volume)
{
if (volume <= VOLUME_MIN) //0.0001f を最小値とする
return DECIBEL_MUTE; //-800dB (-80dB だと僅かに聞こえる気がするので、とりあえず10倍してる)
var db = 20 * Mathf.Log10(volume);
return Mathf.Clamp(db, DECIBEL_MUTE, 0f);
}
}
}
参考資料そのままだが、冒頭に書いた「少しばかり工夫してる」とは、最小値 (0.0001) 以下では DECIBEL_MUTE (-800dB) を返すところで、AudioMixer の Threshold のデフォ値(-80dB) 付近だと、わずかに音が聞こえる気がするからだ。もちろん Threshold の値を上げても良いが、毎回調整するのは面倒なので(笑)、とりま 10倍した値(-800dB)を返すようにしてる。これをそのまま AudioMixer.SetFloat に当ててやれば、確実に無音(ミュート)できる。
(参考)デシベルのすすめ (KAYAC engineers' blog)
アプリではわかりやすいように音量を 0~100(%) 表記してるが、やはり定型処理となるので、以下のような簡単な拡張メソッド(.NET 4.x)を作るのも良いだろう。
//音量(0~100%) → デシベル(-80(-800)~0dB) に変換
public static float PercentToDecibel(this float per) => ToDecibel(per * 0.01f);
■デシベル(-80~0dB) → 音量(0~1f) に変換する
●デシベル(-80~0dB) → 音量(0~1f) に変換する
using UnityEngine;
namespace Exsample
{
public static partial class Extensions //※クラス名は任意
{
/// <summary>
/// デシベル(-80~0dB) → 音量(0~1f) に変換
/// (参考) https://techblog.kayac.com/linear-vs-decibel
/// </summary>
/// <param name="decibel">-80~0dB</param>
/// <returns>0~1f</returns>
public static float FromDecibel(this float decibel)
{
if (decibel <= DECIBEL_MIN) //-80dB を最小値とする
return 0f;
return Mathf.Pow(10f, decibel / 20f);
}
}
}
これも参考資料そのままなので、詳細はそちらを参考にして欲しい。
(参考)デシベルのすすめ (KAYAC engineers' blog)
これも少し手を加えたのは、-80dB を引数に与えると 0.0001 の計算値になるので、強制的に 0 (無音) にしている所。この方が実用的で使いやすかっただけのこと。
例えば簡単にテストすると、以下のような結果になる。
var volMin = 0f;
var volMax = 1f;
var volOverMin = -1f;
var volOverMax = 2f;
//volume (0~1f) → dB (-80(-800)~0dB) 変換
var dBMin = volMin.ToDecibel();
var dBMax = volMax.ToDecibel();
var dBOverMin = volOverMin.ToDecibel();
var dBOverMax = volOverMax.ToDecibel();
Debug.Log($"volMin = {volMin}, ToDecibel = {dBMin}");
Debug.Log($"volMax = {volMax}, ToDecibel = {dBMax}");
Debug.Log($"volOverMin = {volOverMin}, ToDecibel = {dBOverMin}");
Debug.Log($"volOverMax = {volOverMax}, ToDecibel = {dBOverMax}");
//dB (-80(-800)~0dB) → volume (0~1f) 変換
var dBMinToVol = dBMin.FromDecibel();
var dBMaxToVol = dBMax.FromDecibel();
var dBOverMinToVol = dBOverMin.FromDecibel();
var dBOverMaxToVol = dBOverMax.FromDecibel();
Debug.Log($"dBMin FromDecibel = {dBMinToVol}");
Debug.Log($"dBMax FromDecibel = {dBMaxToVol}");
Debug.Log($"dBOverMin FromDecibel = {dBOverMinToVol}");
Debug.Log($"dBOverMax FromDecibel = {dBOverMaxToVol}");
volMax = 1, ToDecibel = 0
volOverMin = -1, ToDecibel = -800
volOverMax = 2, ToDecibel = 0
dBMin FromDecibel = 0
dBMax FromDecibel = 1
dBOverMin FromDecibel = 0
dBOverMax FromDecibel = 1
(関連記事)
【Unity】【C#】HDR Color を計算(変換)する
【Unity】【C#】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換
【C#】文字列 → float (浮動小数点) 変換でエラーが出るときは…
| h o m e |