audio-design について
ミキサーのルーティングやアダプティブミュージックを設計する、汎用的なゲーム音響スキルです。バスミキシング、サイドチェイン、効果音の変化、ビート同期を扱い、エンジン固有のAPIは対象外です。
主な機能
- 01バスルーティングとデシベル音量調整
- 02音声競合時のサイドチェインダッキング
- 03アダプティブミュージックのレイヤーと遷移
- 04効果音のピッチとサンプルの変化
- 05ビート同期イベント
活用シーン
- 01バスごとに音楽、効果音、環境音、音声を調整
- 02台詞や重要な効果音の間、音楽を下げる
- 03戦闘の強さに応じて音楽を変化
- 04反復する効果音に変化を付け、イベントをビートに同期
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill audio-designインストール後、Claude Code で/audio-designを入力して読み込まれたか確認します。
同梱ファイルreferences/adaptive-music.md
詳細
オーディオ設計
ゲームオーディオは、ミキシンググラフと音楽システムで構成されます。すべてのサウンドを少数のバスに通して、グループごとに音量を調整し、エフェクトを適用できるようにします。音楽は1つのトラックをループさせるのではなく、レイヤー化や再シーケンスによってプレイに反応させます。このスキルでは、幅広く使える手法を解説します。具体的な API には、godot-audio、Unity の AudioMixer、またはミドルウェア(FMOD/Wwise)を使用してください。
使用する場面
- バス/ミキサーのレイアウトを設計し、グループの音量を設定し、グループにエフェクト(リバーブ、コンプレッション、EQ)を適用するときに使用します。
- ダッキング(サイドチェイン)を使って、セリフや衝撃音に合わせて音楽/環境音の音量を下げるときに使用します。
- 戦闘/探索の激しさに応じて変化するアダプティブミュージックを構築するときに使用します。
- 効果音のバリエーション(ピッチ/サンプルのランダム化)を追加し、イベントをビートに同期させるときに使用します。
使用しない場面: エンジン固有のオーディオノード/ストリームを扱う場合は、godot-audio またはエンジンのオーディオスキルを使用してください。読み込み/ストリーミングとアセットのインポートは、エンジン側の機能です。バス音量を操作する UI スライダーについては、エンジンの UI スキルを参照してください。
基本的なワークフロー
- サウンドごとではなく、バスを配置します。 一般的なツリーは、
Master ← {Music, SFX, Ambience, UI, Voice}です。すべてのサウンドをバスにルーティングし、プレイヤーの設定スライダーをバス音量に対応させます。何百ものクリップの音量を手作業で設定しないでください。 - リニア値ではなく、デシベルを使います。 人間が感じる音量は対数的です。音量コントロールとオートメーションは dB で扱い、変換は端点でのみ行います。
- ヘッドルームを確保します。 クリッピングを避けるため、Master のピークが 0 dBFS 未満になるようにミックスします(多くのゲームでは、-14~-16 LUFS 前後などを目標音量にします)。
- サイドチェインコンプレッサー(または音量オートメーション)で、競合する音源をダッキングします。 ボイス/重要な効果音が再生されると音楽バスの音量が下がり、その後回復します。
- 音楽をアダプティブにします。 垂直方向のレイヤー化(ステムのフェードイン/アウト)、および/または水平方向の再シーケンス(音楽上の区切りでセグメントを切り替え)を使います。リファレンスを参照してください。
- 小さなランダムなピッチ/音量の変化とサンプルプールを使って、繰り返される効果音に変化を加えます。 足音や打撃音が機械的に聞こえるのを防げます。
- 実際の出力環境で確認します。 ヘッドフォンとスピーカーで聴き、ミックスのバランスが取れていること、ダッキングが聞き取れるものの音量が不自然に揺れないこと、音楽の切り替えがビートに合っていることを確認します。エディターのメーターだけで判断しないでください。
パターン
1. バスルーティングと dB ゲイン
# Route sounds to named buses; control GROUPS, not individual clips.
sfx_player.bus = "SFX"
music_player.bus = "Music"
# Map a 0..1 settings slider to decibels (linear_to_db), the perceptual unit.
func set_bus_volume(bus_name: String, slider01: float) -> void:
var idx := AudioServer.get_bus_index(bus_name)
var db := linear_to_db(clamp(slider01, 0.0001, 1.0)) # 0 -> silence, 1 -> 0 dB
AudioServer.set_bus_volume_db(idx, db)
# RIGHT: slider -> dB via linear_to_db. WRONG: assigning slider01 straight as dB
# (a "0.5" would be only +0.5 dB — almost no change — and 0 would be 0 dB, full).
2. サイドチェインによるダッキング(ボイスに合わせて音楽の音量を下げる)
# A compressor on the MUSIC bus, keyed by the VOICE bus, lowers music while
# dialogue plays, then releases. This is "sidechain ducking".
# Setup (engine-specific): add a compressor effect to the Music bus and set its
# sidechain to the Voice bus. Then tune:
# threshold: level on Voice that triggers ducking (e.g. -30 dB)
# ratio: how hard to duck (e.g. 8:1 for a clear dip)
# attack: fast (~10 ms) so music gets out of the way promptly
# release: slow (~300-500 ms) so it recovers smoothly, not pumping
# No-middleware alternative: tween the Music bus volume down on voice start and
# back up on voice end.
func duck_music(active: bool) -> void:
var target_db := -12.0 if active else 0.0
create_tween().tween_method(
func(v): set_bus_volume_db("Music", v), current_music_db, target_db, 0.25)
3. 効果音のバリエーション(「マシンガン」のような繰り返しを防ぐ)
# Randomize pitch slightly and pick from a sample pool so repeats feel organic.
func play_varied(samples: Array, bus := "SFX") -> void:
var p := AudioStreamPlayer.new()
p.stream = samples[randi() % samples.size()] # rotate through several takes
p.bus = bus
p.pitch_scale = randf_range(0.94, 1.06) # +/- ~6% pitch wobble
add_child(p); p.play()
p.finished.connect(p.queue_free) # clean up one-shots
4. ビート同期イベント(音楽のグリッドにクオンタイズする)
# Schedule gameplay/visuals on musical time, not frame time, so they land on beat.
const BPM := 120.0
var seconds_per_beat := 60.0 / BPM
func current_beat(playback_position_sec: float) -> int:
return int(playback_position_sec / seconds_per_beat)
# Quantize an action to the NEXT beat boundary instead of firing immediately.
func time_until_next_beat(pos: float) -> float:
return seconds_per_beat - fmod(pos, seconds_per_beat)
# Drive timing from the audio playback clock, which is steadier than frame delta.
注意点
- スライダーの値を dB として扱わないでください。 音量は対数的です。
0..1の値はlinear_to_dbで変換し(戻す場合はdb_to_linearを使用します)、リニアスライダーを生の振幅に適用すると、最下部近くまで動かさないと変化を感じにくくなります。 - バスを使わず、クリップごとに音量を設定すると、全体のバランス調整ができなくなり、セーブデータ/設定も肥大化します。 バスでミックスしてください。
- Master をクリッピングさせないでください。 サウンドを合算すると 0 dBFS を超えて歪みます。ヘッドルームを確保し、リミッターはミキサーとしてではなく安全策として Master に配置してください。
- ダッキングのポンピングに注意してください。 リリースが速すぎたりレシオが高すぎたりすると、音楽の音量が目立って揺れます。リリースを長くし、レシオを下げてください。
- ゲーム全体で1つの音楽トラックをループさせると、単調に感じられます。 状態に応じて変化するレイヤーやセグメントを使用してください(リファレンスを参照)。
- フレーム時間に基づいてビートを同期させないでください。
deltaはずれていきます。音楽のタイミングにはオーディオ再生位置を読み取り、出力レイテンシーも考慮してください。 - ワンショットプレイヤーを無制限に生成しないでください。 AudioStreamPlayers を解放せずに生成すると、リークが発生します。
finished時に解放するか、小規模なプールを使用してください。
リファレンス
references/adaptive-music.md— 垂直方向のレイヤー化と水平方向の再シーケンス、切り替えタイミング(小節/クオンタイズ)、スティンガー、強度のマッピング、クロスフェード。
関連スキル
godot-audio— Godot でのバス、AudioStreamPlayer、エフェクト、ビート同期。input-systems— 入力アクションからオーディオをトリガーします。physics-tuning— 衝突イベントを打撃音に連動させます。platformer、roguelike— オーディオフィードバックがゲームの手触りを左右するジャンル。
コメント
Markdown 対応