Skip to content

リファレンス曲に寄せる ​

このページでは、ミックスと市販のリファレンスを比較し、ラウドネスと音色のバランスを計測して、ステレオのまま補正し、もう一度計測します。リファレンス合わせで変わるのは音色とゲインで、アレンジ、演奏、ミックスバランスは変わりません。

用意するもの

  • インストール: pip install libsonare(Python 3.11 以降)。Node のタブには npm install @libraz/libsonare(Node.js 22.12 以降)が必要です。
  • mix.wav: 自分のステレオミックス。このページでは CLI だけでミックスからマスタリングまで が 4 本のテスト用ステムから書き出す、48 kHz のミックスダウン(11.5 秒、553053 フレーム)を使います。
  • reference.wav: 目標にしている市販曲の WAV か MP3。サンプルレートはミックスとそろえるのが理想です。
  • このページの数値を再現するには: このページの reference.wav は、答えのわかる手順にするために mix.wav に EQ のティルトを 1 回かけたものです。sonare mastering-processor mix.wav --processor eq.tilt --params "tiltDb=4" -o reference.wav で同じ組を作れます。

このページで身につくこと ​

このページを読むと、次のことができるようになります。

  • 自分のミックスとリファレンス曲との間のラウドネス差・音色差を、どちらのファイルにも手を付ける前に計測できる。
  • 4 帯域のトーナルバランス偏差を読み、その形がティルトで直せる形なのか、シェルフのペアが要るのか、フルパラメトリック EQ が要るのかを見分けられる。
  • モノラルへ畳んでしまうペアコマンドではなく、ステレオペアを保ったまま補正を適用できる。
  • リファレンス一致で直らないものを、はっきり言える。

全体のスクリプト ​

bash
#!/usr/bin/env bash
set -euo pipefail

# 1. リファレンス自体の特徴をつかむ。
sonare mastering-profile reference.wav --json

# 2. ミックスとリファレンスのラウドネス差を計測する。
sonare mastering-pair-analyze mix.wav --reference reference.wav \
  --analysis match.referenceLoudness --json

# 3. 音色差を帯域ごとに計測する。
sonare mastering-pair-analyze mix.wav --reference reference.wav \
  --analysis match.tonalBalance --json

# 4. 補正はモノラルへ畳まず、ステレオペアのまま適用する。
sonare mastering-processor mix.wav --processor eq.tilt \
  --params "tiltDb=4" -o tilted.wav --json

# 5. 両方の差が詰まったか確認する。
sonare mastering-pair-analyze tilted.wav --reference reference.wav \
  --analysis match.tonalBalance --json
sonare mastering-pair-analyze tilted.wav --reference reference.wav \
  --analysis match.referenceLoudness --json
計測、診断、補正、確認
音声音声音声音声mix.wavreference.wavmastering-profilereferenceLoudnesstonalBalance形を読むeq.tilt(ステレオ)tilted.wav再計測
診断までは計測のみです。ミックスに手を入れるのは 1 回だけで、補正後に再計測することで、当て推量ではなく確かめた補正になります。

ステップ 1 — リファレンス自体の特徴をつかむ ​

比較する前に、リファレンスがそもそも何なのかを調べます。

bash
sonare mastering-profile reference.wav --json
json
{
  "duration_sec": 11.52,
  "bpm": 119.87, "bpm_confidence": 0.54,
  "loudness": { "integrated_lufs": -24.57, "true_peak_db": -1.18,
                "crest_factor_db": 25.56, "lra_lu": 6.90 },
  "spectral": { "centroid_hz": 2978.72, "rolloff_hz": 6168.33,
                "sub_rms_db": -37.94, "low_rms_db": -31.55, "air_rms_db": -43.08 },
  "dynamics": { "short_term_lufs_std": 26.70, "attack_density": 0.52,
                "sustain_ratio": 0.27 },
  "defects": { "measured": false, /* ... */ }
}

CLI はバインディングの camelCase のプロファイルキーを snake_case で出力します。defects は省略して示しています。--params detectDefects=1 で計測を求めない限り、measured は false で、損傷のフィールドは既定値のままです。これ 1 回で、狙っているファイルのテンポ、ラウドネス、スペクトル形状、ダイナミクスが手に入ります。マスタリングアシスタントが自分のミックスをプロファイリングするのと同じ計測フィールドです。比較に入る前にここを読んでください。ただし注意がひとつあります。mastering-profile はステレオのファイルをモノラルにまとめてから計測する(標準エラー出力にその旨が出ます)ので、-24.57 LUFS はステレオの曲ではなく、モノラルにまとめたもののラウドネスです。ステレオペアとして測ると、このリファレンスは -21.33 LUFS です。ステップ 5 の tilted.wav は同じ音声で、mastering-processor はそれをステレオで報告します。どちらにしても配信基準からすると控えめです。あとで「本当にこのラウドネスまで追うか、音色だけ追うか」を決めるときに効いてきます。

この loudness のフィールドのうち 3 つは、下のメーターが再生中のクリップに対して報告するものと同じです。積分ラウドネス(LUFS)は次のステップでミックスと比較する 1 つの数値、True Peak は上限、LRA はプログラム全体でラウドネスがどれだけ動くかです。LRA の広いリファレンスは、1 つの積分ラウドネス値の裏に大きな動きを隠しています。その値だけを合わせても、ミックスが同じように動くようにはなりません。なお、このダミーのリファレンスでは crest_factor_db(25.56)と short_term_lufs_std(26.70)が、5.5 秒分のリバーブの余韻(ほぼ無音の区間)を含むために大きく出ています。終わり方がきちんと仕上がった実際のリファレンスなら、ずっと低く出ます。

METERS · LOUDNESSIDLE
ラウドネス計測 — LUFS・True Peak・レンジ

バーは再生中の瞬時ラウドネスを追い、パネルは時間ごとのラウドネスです。積分 LUFS は全体を表す一つの数値、True Peak はサンプル間も含むピークの推定値、LRA はラウドネスの動く幅を表します。ウィンドウを切り替えると、速い瞬時メーターと滑らかな短時間メーターを比べられます。どちらもウィンドウが埋まってから値を出すため、短時間の曲線はクリップの 3 秒後から始まります。

ウィンドウ

ステップ 2 — ラウドネス差を計測する ​

人は 2 つの版のうち、音量の大きいほうを良く感じます。ミックスとリファレンスの音量が違うまま耳で音色を判断すると、正しい音色ではなく「大きい音」に向かって調整してしまいます。そこで先にラウドネス差を測り、音色を比べる前にレベルを合わせます。詳しくは ラウドネスマッチング と リファレンストラック を参照してください。

bash
sonare mastering-pair-analyze mix.wav --reference reference.wav \
  --analysis match.referenceLoudness --json
typescript
import { readFileSync } from 'node:fs';
import { Audio, init, masteringPairAnalyze } from '@libraz/libsonare';

await init();
// CLI と同じく、各ファイルをモノラルにまとめて読む
const load = (path: string) => Audio.fromMemory(new Uint8Array(readFileSync(path)));
const mix = load('mix.wav');
const reference = load('reference.wav');
const result = JSON.parse(masteringPairAnalyze({
  analysisName: 'match.referenceLoudness',
  source: mix.data, reference: reference.data,
  sampleRate: mix.sampleRate, referenceSampleRate: reference.sampleRate,
}));
python
import json
import libsonare as sonare
from libsonare import Audio

# CLI と同じく、各ファイルをモノラルにまとめて読む
with Audio.from_file("mix.wav") as m, Audio.from_file("reference.wav") as r:
    mix, reference, sr, ref_sr = m.data, r.data, m.sample_rate, r.sample_rate
result = json.loads(sonare.mastering_pair_analyze(
    "match.referenceLoudness", mix, reference, sr, reference_sample_rate=ref_sr))
json
{ "gain_to_match_db": -0.86, "reference_lufs": -24.57, "source_lufs": -23.71 }

ライブラリの呼び出しは同じフィールドを camelCase(gainToMatchDb、referenceLufs、sourceLufs)で返し、ファイルごとに 1 本のモノラル配列を受け取ります。gain_to_match_db は、ソースのラウドネスをリファレンスに合わせるためのゲインです。source_lufs + gain_to_match_db = reference_lufs という関係にあります。ここではミックスがリファレンスより 0.9 dB 大きいので、マイナスの値でそこまで下げることになります。

同じ mix.wav がここでは -23.71、ステップ 5 では -20.49 になる理由

このページの mastering-pair-analyze と mastering-profile の数値は、どれも各ファイルをモノラルにまとめたもので測っています。ステップ 5 の mastering-processor はステレオペアを保ったまま処理し、同じミックスを -20.49 LUFS と報告します。3.21 dB の差はまとめたことによる差で、食い違いではありません。LUFS は両チャンネルのパワーを合計するので、よく似た 2 つのチャンネルを平均して 1 つにすると約 3 dB 下がります(CLI だけでミックスからマスタリングまで のステレオに関する注意を参照)。2 つのファイルは同じようにまとめられているので、信頼できるのはミックスとリファレンスの差である 0.9 dB です。比べるのはモノラル同士かステレオ同士にし、両者を混ぜないでください。

ラウドネスを合わせることと、目標を決めることは別

この数値が言っているのは「ミックスとリファレンスは 0.9 dB 違う」であって、「-24.57 LUFS でマスタリングしろ」ではありません。時代やプラットフォームの違うリファレンスは、いまの配信目標から外れた位置にあることがあります。reference_lufs をそのまま目標値にする前に配信ターゲットを確認してください。

ステップ 3 — 音色差を帯域ごとに計測する ​

bash
sonare mastering-pair-analyze mix.wav --reference reference.wav \
  --analysis match.tonalBalance --json
typescript
// mix、reference はステップ 2 で読み込んだもの
const result = JSON.parse(masteringPairAnalyze({
  analysisName: 'match.tonalBalance',
  source: mix.data, reference: reference.data,
  sampleRate: mix.sampleRate, referenceSampleRate: reference.sampleRate,
}));
python
# mix、reference、sr、ref_sr はステップ 2 で読み込んだもの
result = json.loads(sonare.mastering_pair_analyze(
    "match.tonalBalance", mix, reference, sr, reference_sample_rate=ref_sr))
json
{
  "bands": [
    { "low_hz": 20,    "high_hz": 250,   "reference_db": 17.00,  "source_db": 19.00,  "deviation_db": 2.00 },
    { "low_hz": 250,   "high_hz": 2000,  "reference_db": 5.25,   "source_db": 5.12,    "deviation_db": -0.13 },
    { "low_hz": 2000,  "high_hz": 8000,  "reference_db": -6.03,  "source_db": -8.00,  "deviation_db": -1.97 },
    { "low_hz": 8000,  "high_hz": 20000, "reference_db": -11.13, "source_db": -13.13, "deviation_db": -2.00 }
  ]
}

deviation_db は source_db - reference_db です。プラスならその帯域でミックスのほうが出ているということです。表を上から下へ読むと形ははっきりしています。ミックスは低域が約 2 dB 出すぎ、ローミッドはほぼ揃っていて、2 kHz より上は全体に約 2 dB 足りません。これは 4 つの別々の問題ではなく、1 つの問題が 4 つの窓越しに見えているだけです。

この偏差は絶対的な帯域レベルであり、ラウドネスで正規化されていません。解析は各帯域で全フレームの生のパワーを平均しており、全体のゲインや長さ、末尾の無音を揃える処理はありません。全体が 3 dB 大きいリファレンスなら、どの帯域も -3 dB と出ます。読むのは形(帯域どうしの差)です。あるいは先にゲインを揃えてください(ステップ 2 で測れます)。

4 帯域より細かく見たい場合は、match.tonalBalanceLogBands が同じ偏差を対数間隔の 32 帯域で返します。match.matchEqCurve は帯域サマリーではなく周波数応答の補正カーブそのものを返します。リファレンス一致のブラウザデモが直接使っているのはこの形です。

ステップ 4 — ティルトか、シェルフか、フル EQ か ​

片端でプラス、もう片端でマイナスへなめらかに振れ、ゼロを一度だけ横切る偏差はティルトです。1 つのピボットを境に、低域側と高域側が逆方向に動く形です。それはまさに eq.tilt の仕事で、tiltDb のつまみ 1 つと pivotHz(既定 1000 Hz)を mastering-processor 経由で適用します。

ティルト量は両端の帯域から読み取れます。低域は約 -2 dB、高域は約 +2 dB 必要なので、tiltDb ≈ (低域の偏差) - (高域の偏差) = 2.00 - (-2.00) = 4.0 です。ある帯域から別の帯域を引くと、全体のラウドネスがすべての帯域に加える一様なずれが相殺されます。ティルト量を決めるのが絶対値ではなく形なのは、そのためです。これは出発点であって最終解ではありません。ステップ 6 で計算を信じるのではなく確認するのが、この手順全体の要点です。

下のデモは完成したミックスに対して tilt を動かします。スペクトルがピボットを軸に傾き、低域側と高域側が逆方向に動きます。

PARAM SWEEP · TILT EQIDLE
チルト EQ — スペクトル全体を一度に整える

チルト EQ は、固定したミッドレンジのピボット(橙色の線)を軸に、おおまかな音色バランスを傾けます。プラス方向は高域を持ち上げ低域を削って明るく、マイナス方向はその逆で温かくします。レンダーごとにピークを同じ高さへ揃えているためプラス方向でもクリップしませんが、揃えているのはピークであってラウドネスではないので、知覚上の音量は設定によって変わります。ドラッグすると、平均スペクトルがピボットを軸にシーソーのように傾くのが見えます。用途は広い範囲の補正です。特定の共鳴を抑えたいときは、チルトではなく狭いバンドを使ってください。

試聴対象
再生中に切り替えると、選んだ音を先頭から再生します。処理後
チルト
6 dB

補正に使える処理は 3 つあり、偏差の形でどれを使うかが決まります。

偏差の形処理主なパラメータこの素材での結果
ゼロを一度だけ横切る、なめらかな 1 つの振れeq.tilttiltDb、pivotHz(既定 1000 Hz)4 帯域すべて 0.00 dB
低域側と高域側でピボットが違う補正。たとえば 250 Hz 以下を削り、持ち上げは 8 kHz より上だけにしたい場合eq.shelvinglowFrequencyHz、lowGainDb、highFrequencyHz、highGainDblowFrequencyHz=250, lowGainDb=-2, highFrequencyHz=2000, highGainDb=2 で 0.28 / 0.11 / -0.13 / -0.001 dB
1 つの帯域の中にある狭いディップやピーク。1 つのピボットでも 2 つのシェルフでも切り出せない形eq.equalizer(最大 24 バンド。各バンドはピーク、シェルフ、ティルトのいずれか)band0.* から band23.*使用せず

2 つのシェルフでは連続した 1 本の傾斜を正確には再現できないため、eq.shelving はティルトより少し収まりが悪くなります。

この素材の偏差はきれいなティルト型なので、eq.tilt が適切な選択であり、このページもそれで通します。

ステップ 5 — ステレオペアのまま適用する ​

bash
sonare mastering-processor mix.wav --processor eq.tilt \
  --params "tiltDb=4" -o tilted.wav --json
json
{ "processor": "eq.tilt", "input_lufs": -20.49, "output_lufs": -21.33,
  "applied_gain_db": 0.0, "sample_rate": 48000, "output": "tilted.wav",
  "stereo": true }

確認すべきは "stereo": true です。mastering-processor はソースファイル自体のチャンネル数からエントリポイントを決めます。ステレオの mix.wav なら、eq.tilt に限らずどのソロプロセッサでも自動的にステレオ経路を通ります。フラグを覚えておく必要はありません。

mastering-pair-processor はモノラルへ畳む。mastering-processor は畳まない

ペア系コマンドは別のコード経路で、無条件にダウンミックスします。

bash
sonare mastering-pair-processor mix.wav --processor match.applyMatchEq \
  --reference reference.wav -o matched.wav --json
# warning: 2-channel input is downmixed to mono by this CLI command
# {"processor": "match.applyMatchEq", "input_lufs": -23.71, "output_lufs": -24.51, ...}

matched.wav は channels: 1 で出てきます。matched.wav に対して match.tonalBalance を測り直すと、カーブフィット自体の精度は高く 0.29 / 0.004 / -0.001 / -0.07 dB まで収束します。ただしその精度と引き換えにモノラルファイルになっています。

CLI 上で match.applyMatchEq を使うのは、納品物が本当にモノラルのとき、たとえばポッドキャストや音声トラックのときです。ステレオの納品物では、上のように形の合った単体プロセッサを mastering-processor 経由で使うか、ライブラリを直接呼び出します。mastering_pair_process() は、1 回の呼び出しにつき 1 本のフラット配列しか取りません。そのため、左チャンネルをリファレンスの左チャンネルに対して 1 回、右チャンネルを右チャンネルに対してもう 1 回呼びます。こうすると、リファレンス一致のブラウザデモと同じやり方で、チャンネルを保ったままフィット済みのカーブが得られます。呼び出しの形は Python API を参照してください。

ステップ 6 — 収束を確認する ​

bash
sonare mastering-pair-analyze tilted.wav --reference reference.wav \
  --analysis match.tonalBalance --json
# 4 帯域すべての deviation_db が 0.00

sonare mastering-pair-analyze tilted.wav --reference reference.wav \
  --analysis match.referenceLoudness --json
# {"gain_to_match_db": 0, "reference_lufs": -24.57, "source_lufs": -24.57}

この素材では、音色の補正がラウドネスの差まで一緒に詰めてくれました。ただしこれはこの素材固有の事情であって、一般則ではありません。ここでの reference.wav は mix.wav にたった 1 つの編集、EQ ティルトを掛けただけの差分です。ラウドネスの計測カーブは周波数に対して平坦ではないため、スペクトルを傾けるだけでラウドネス値も一緒に動きます。その 1 つの編集を打ち消したことで、両方の効果が同時に解消されました。一般には、音色を合わせてもラウドネスが合うとは限りません。LUFS の計測に含まれる K 特性(K-weighting)が周波数によって重みを変えるため(LUFS を参照)、音色を動かすと LUFS の値も動くからです。正しい順番は「音色を補正してから、その結果に対して match.referenceLoudness を測り直す」ことです。手つかずのミックスに対してではありません。EQ をかけたあとは、必ずラウドネスを測り直してください。

リファレンス一致で直せないもの ​

合わせたカーブが動かすのは音色であって、判断ではない

このページで扱っているのは EQ とゲインの調整だけです。アレンジ、演奏、ミックスバランスにはいっさい触れません。サビが持ち上がらない、ダブリングしたギターがボーカルを埋めている、アレンジがリファレンスより薄い。そうした問題は、音色を合わせても直りません。同じ薄いミックス、同じ埋もれたボーカルが、少し明るくなるだけです。リファレンス一致がはっきり述べているとおり、リファレンスは較正するものであって、移植するものではありません。マッチングが薄いトラックを密度の高いトラックへ寄せすぎて、そのトラック自身の個性が失われ始めたら、直すのはマッチングを強めることではなく弱めることです。

次に読むもの ​