Ruby関連のMastodon/Fediverseアカウント集


言語・処理系

イベント

カンファレンスなど。

コミュニティ

国内

海外

製品

Ruby on Rails

組織

企業

その他

参考

Web Audio API/GainNode: デシベル指定で音量調整

結論としては

// gainNode.gain.value == 1.0 のときの音量を基準(0 dB)として
// -10 dB の音量にする場合の例
const db = -10;
gainNode.gain.value = Math.pow(10, db / 20);

でよさそう。

GainNode.gain.value に指定する値については一つ前の記事で書きましたのでそちらも参照してください。

memo88.hatenablog.com

メモ

対数スケール(dB)から線形スケールへの変換だから Math.pow が出てくるのは分かるけど db / 20 の 20 って何? というあたりは Wikipedia の説明を読むと分かる。

この式ですね。

 \displaylines{
L_V = 10 \log_{10} \left( \frac{{V_\text{out}}^2}{{V_\text{in}}^2} \right) = 10 \log_{10} \left( \frac{V_\text{out}}{V_\text{in}} \right)^2 = 20 \log_{10} \left( \frac{V_\text{out}}{V_\text{in}} \right) \text{dB}
}

音を扱う場合は

  •  V_{ \text{in} }
  •  V_{ \text{out} }

が波形データの振幅に対応するようです。


20 という数は 10 * 2 に分解できて、

10 は単に B(ベル)から dB(デシベル)に変換しているだけ、

2 の方は

一方、電圧や音圧などの交流信号の振幅からデシベルで表す利得  L_V を求める場合、パワーは振幅の2乗に比例すると仮定し、

この「2乗」から来ています(同じく Wikipedia から)。これはこういうものらしいです(この記事では深入りしません)。「波のエネルギー 振幅の2乗」とかで検索するといろいろ出てきます。

具体的な値を見てみる

dB    振幅の比
   0  1.0
  -1  0.8912509381337456
  -2  0.7943282347242815
  -5  0.5623413251903491
 -10  0.31622776601683794
 -20  0.1
 -24  0.06309573444801933
 -40  0.01
 -48  0.003981071705534973
 -60  0.001
 -64  0.000630957344480193
 -80  0.0001
 -96  0.00001584893192461114
-100  0.00001

逆の変換もできます。

const ampRatio = 0.5;
20 * Math.log10(ampRatio); //=> -6.020599913279624 (dB)

Audacity で見てみる

上記の計算で合ってるよね? という確認も兼ねて Audacity の動作も見てみます。

元の波形はこう。振幅 = 1.0 です。このときの音量を基準(0 dB)として変換します。

(メニューバー)エフェクト>音量と圧縮>増幅...
で変換します。

-6.021 (dB) を指定して変換すると振幅が 0.5 倍になる。

-20 (dB) を指定して変換すると振幅が 0.1 倍になる。

合ってますね。

参考

Web Audio API: GainNode.gain.value に指定する値について調べたメモ

MDN の関連ページ(たとえば GainNode: GainNode() コンストラクター - Web API)を見ると

公称の範囲は (-∞,+∞) です。デフォルト値は 1 です。

などと書いてあるのですが、それだけじゃどういう値を指定すればいいのか、指定した値がどのように使われるのかよく分からない……ということで軽く調べてみました。

※ Web Audio API やオーディオ処理一般に詳しい人が書いているわけではありませんので、鵜呑みにせず適宜一次情報に当たるなどしてください。

仕様を見てみる

MDN のページに Web Audio API の仕様ページへリンクがある。 2025-01-19 時点では v1.1。

1.20. The GainNode Interface

https://webaudio.github.io/web-audio-api/#GainNode

Each sample of each channel of the input data of the GainNode MUST be multiplied by the computedValue of the gain AudioParam.

https://g200kg.github.io/web-audio-api-ja/#GainNode

GainNode の入力データの各チャンネルの各サンプルは gain AudioParam の computedValue が乗じられます ( MUST )。

  • 「multiply」「乗じる」とのことなので何かしら乗算に使われるのだな、ということは分かる。
  • computedValue はよく分かりませんでした(computedValue 自体の説明にも目を通したけどよく分からなかった)。
  • (日本語訳ありがとうございます)

ソースも見るとよさそう。

波形が実際にどうなるか見てみる

音を再生して別のアプリや別のPCに繋いで録音して波形を見る……でもよいのですが、 AnalyserNode を使うと GainNode で加工した結果を直にモニターすることができます。 手軽で確実そうなのでこれを使って確認しました。


調査に使ったコード(HTML + JavaScript)は gist に置きました。

https://gist.github.com/sonota88/015f30ffd7d2d4c6dc047d5fe12d62ec


  srcNode
    .connect(gainNode)
    .connect(analyserNode)
    .connect(context.destination)
  ;

のように srcNode => gainNode => analyserNode => destination となるように接続しています。gainNode によって加工された波形データを、そのすぐ後ろに繋いだ analyserNode で取得します。


ブラウザ(Ubuntu 24.04 + Firefox 133.0.3)で実行すると、 analyserNode.getFloatTimeDomainData(...) で取得したデータの波形と各サンプルの値、サンプルの値の最小値・最大値が以下のように表示されます。

1行が1サンプルに対応し、時間の向きは上から下、左端が -1.5, 右端が +1.5。

gainNode.gain.value = 1.0 の場合:

入力となる波形データが -1, 0, -0.5, 0, 0.5, 0, 1, 0 をそれぞれ 4 サンプルずつに伸ばして繰り返すというものなので、それがそのまま analyserNode に渡っていることが確認できます。

中間の gainNode を外して srcNode => analyserNode のように直結させた場合も同じ結果でした。


ちなみに Chrome 131.0.6778.139 では理由は不明ですが以下のような波形になりました。余分な加工が加わらない方が嬉しいので以降は Firefox で試します。


gainNode.gain.value = 0.5 にすると振幅が半分になります。


gainNode.gain.value = 0.1 の場合:


gainNode.gain.value = 0 だと完全に無音になるようです(この場合何も表示されなくなるのでスクリーンショットは省略)。


1 より大きい値を指定した場合(gainNode.gain.value = 1.2):

analyserNode に渡ってきた段階ではクリッピングはされてないようです(Chrome でも同様)。


gainNode.gain.value = -1 のように負の値を指定すると各サンプルの値の正負が反転します。ほんとにただ乗算してるだけっぽいですね。

関連

memo88.hatenablog.com

参考

4. Volume and Loudness (webaudioapi.com)

The main way to affect the loudness of a sound is using GainNodes. As previously mentioned, these nodes have a gain parameter, which acts as a multiplier on the incoming sound buffer. The default gain value is one, which means that the input sound is unaffected. Values between zero and one reduce the loudness, and values greater than one amplify the loudness. Negative gain (values less than zero) inverts the waveform (i.e., the amplitude is flipped).


2024-12-11 Web Audio API 1.1 の日本語訳を公開しました | g200kg Music & Software