# 機能設計書 20-空間オーディオ（2D/3D）

## 概要

本ドキュメントは、Godotエンジンにおける空間オーディオ機能の設計仕様を記述する。空間オーディオ機能は、AudioStreamPlayer2D/AudioStreamPlayer3Dノードを使用して、2D/3D空間内での音源位置に基づいた距離減衰、パンニング、ドップラー効果などを実現する機能である。

### 本機能の処理概要

**業務上の目的・背景**：ゲーム開発において、音がどこから聞こえるかという空間情報は、プレイヤーの没入感と状況認識を大きく左右する。敵の足音が背後から聞こえる、遠くの爆発音が減衰して聞こえる、車が通り過ぎる時のドップラー効果など、空間オーディオはリアリティの向上に不可欠である。

**機能の利用シーン**：
- 敵やNPCの足音・声（位置特定）
- 環境音（滝、機械など）の空間配置
- 移動する音源のドップラー効果（車両、弾丸）
- Area2D/3Dによるリバーブ効果
- 距離に応じた音量減衰

**主要な処理内容**：
1. リスナー位置の取得（Camera/AudioListener）
2. 音源との距離計算と減衰適用
3. パンニング計算（左右/サラウンド）
4. ドップラー効果の計算（3Dのみ）
5. Area2D/3Dによるバスオーバーライド
6. リバーブ効果の適用（3Dのみ）

**関連システム・外部連携**：
- AudioServer：オーディオミキシング
- AudioListener2D/3D：リスナー位置の管理
- Camera2D/3D：デフォルトリスナー
- Area2D/3D：オーディオバスオーバーライド

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 2Dエディタ | 主画面 | 2D空間オーディオの設定・プレビュー |
| 4 | 3Dエディタ | 主画面 | 3D空間オーディオの設定・プレビュー |

## 機能種別

オーディオ再生 / 空間シミュレーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| stream | Ref<AudioStream> | No | 再生するオーディオストリーム | 有効なAudioStreamリソース |
| volume_db | float | No | 音量（dB） | NaNでないこと |
| max_distance | float | No | 最大減衰距離（px/m） | 正の値 |
| attenuation | float | No | 減衰曲線（2D）/ 減衰モデル（3D） | - |
| panning_strength | float | No | パンニング強度 | 0以上 |
| area_mask | uint32_t | No | エリアマスク（バスオーバーライド用） | 2Dのみ |
| unit_size | float | No | 単位サイズ（3D減衰計算用） | 3Dのみ |
| doppler_tracking | DopplerTracking | No | ドップラー追跡モード | 3Dのみ |

### 入力データソース

- AudioStreamリソースファイル
- エディタでのプロパティ設定
- スクリプトからの動的設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| is_playing | bool | 再生中かどうか |
| playback_position | float | 現在の再生位置（秒） |
| volume_vector | Vector<AudioFrame> | 各チャンネルの音量 |

### 出力先

- AudioServer（空間処理済みオーディオ）
- 指定されたオーディオバス（またはAreaオーバーライドバス）

## 処理フロー

### 処理シーケンス（2D）

```
1. NOTIFICATION_INTERNAL_PHYSICS_PROCESSで更新
   └─ _update_panning()呼び出し
2. リスナー位置の取得
   └─ AudioListener2DまたはViewport中央
3. 距離計算と減衰適用
   └─ multiplier = pow(1 - dist/max_distance, attenuation)
4. パンニング計算
   └─ pan = relative_position.x / screen_size.x
5. Areaバスオーバーライドチェック
   └─ _get_actual_bus()
6. 音量ベクトルをAudioServerに適用
   └─ set_playback_bus_exclusive()
```

### フローチャート

```mermaid
flowchart TD
    A[NOTIFICATION_INTERNAL_PHYSICS_PROCESS] --> B[_update_panning]
    B --> C[World2D/3D取得]
    C --> D[リスナー位置取得]
    D --> E[距離計算]
    E --> F{dist > max_distance?}
    F -->|Yes| G[音量0でスキップ]
    F -->|No| H[減衰計算]
    H --> I[パンニング計算]
    I --> J[volume_vector更新]
    J --> K[_get_actual_bus]
    K --> L{Areaオーバーライド?}
    L -->|Yes| M[Area指定バスを使用]
    L -->|No| N[デフォルトバスを使用]
    M --> O[set_playback_bus_exclusive]
    N --> O
    O --> P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 距離減衰 | max_distanceを超えると音量0 | 常時 |
| BR-02 | エリアオーバーライド | Area2D/3Dでis_overriding_audio_busがtrueの場合、そのバスを使用 | エリア内にいる場合 |
| BR-03 | リスナー優先 | AudioListener2D/3Dが存在すればそれを優先、なければCamera/Viewport中央 | 常時 |

### 計算ロジック

2D減衰計算:
```cpp
float dist = global_pos.distance_to(listener_in_global);
if (dist > max_distance) continue;
float multiplier = Math::pow(1.0f - dist / max_distance, attenuation);
multiplier *= Math::db_to_linear(internal->volume_db);
```

2Dパンニング計算:
```cpp
float pan = relative_to_listener.x / screen_size.x;
pan = CLAMP(pan, -1, 1);
pan *= panning_strength * cached_global_panning_strength * 0.5f;
pan = CLAMP(pan + 0.5, 0.0, 1.0);
float l = 1.0 - pan;
float r = pan;
```

3D減衰モデル:
- INVERSE_DISTANCE: 1 / (distance/unit_size)
- INVERSE_SQUARE_DISTANCE: 1 / (distance/unit_size)^2
- LOGARITHMIC: -20 * log(distance/unit_size)

## データベース操作仕様

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | エラー | max_distanceが0以下 | 正の値を設定 |
| - | エラー | panning_strengthが負 | 0以上を設定 |

### リトライ仕様

なし

## トランザクション仕様

なし

## パフォーマンス要件

- 空間計算は物理フレームごとに実行
- 複数Viewportがある場合、各Viewportのリスナーに対して計算

## セキュリティ考慮事項

特になし

## 備考

- 2Dのmax_distanceデフォルト: 2000px
- 3Dのunit_sizeデフォルト: 10m
- 3D減衰モデル: INVERSE_DISTANCE, INVERSE_SQUARE_DISTANCE, LOGARITHMIC, DISABLED

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

AudioStreamPlayer2D/3Dの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | audio_stream_player_2d.h | `scene/2d/audio_stream_player_2d.h` | 2D空間オーディオのメンバ変数 |
| 1-2 | audio_stream_player_3d.h | `scene/3d/audio_stream_player_3d.h` | 3D空間オーディオのメンバ変数 |

**読解のコツ**: 2Dはmax_distance、attenuation、panning_strengthが主要パラメータ。3DはさらにATTENUATION_MODEL、doppler_tracking、unit_sizeが追加される。

#### Step 2: パンニング計算を理解する

_update_panning関数を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | audio_stream_player_2d.cpp | `scene/2d/audio_stream_player_2d.cpp` | _update_panning関数 |

**主要処理フロー**:
1. **118-121行目**: stream/active チェック
2. **126-134行目**: volume_vector初期化
3. **138-184行目**: 各Viewportに対するパンニング計算
4. **165-166行目**: 減衰計算
5. **168-183行目**: パンニング計算とvolume_vector更新

#### Step 3: エリアバスオーバーライドを理解する

_get_actual_bus関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | audio_stream_player_2d.cpp | `scene/2d/audio_stream_player_2d.cpp` | _get_actual_bus関数 |

**主要処理フロー**:
- **81-115行目**: _get_actual_bus - エリアオーバーライドチェック
- **89-99行目**: intersect_pointでエリア検出
- **100-111行目**: is_overriding_audio_busチェックとバス名取得

#### Step 4: 3D固有機能を理解する

3Dの減衰モデルとドップラー効果を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | audio_stream_player_3d.cpp | `scene/3d/audio_stream_player_3d.cpp` | _get_attenuation_db関数 |

### プログラム呼び出し階層図

```
AudioStreamPlayer2D::_notification(NOTIFICATION_INTERNAL_PHYSICS_PROCESS)
    │
    ├─ AudioStreamPlayer2D::_update_panning()
    │      │
    │      ├─ World2D::get_viewports()
    │      │
    │      ├─ AudioListener2D::get_global_position() [or Viewport center]
    │      │
    │      └─ 距離減衰 + パンニング計算
    │
    ├─ AudioStreamPlayer2D::_get_actual_bus()
    │      │
    │      └─ PhysicsDirectSpaceState2D::intersect_point() [Area検出]
    │
    └─ AudioServer::set_playback_bus_exclusive()
```

### データフロー図

```
[入力]                    [処理]                         [出力]

音源位置（global_pos）
       │
       ▼
リスナー位置 ──────────▶ _update_panning()
       │                      │
       ▼                      ▼
  距離計算              減衰計算
       │                      │
       ▼                      ▼
max_distance            multiplier
attenuation                   │
                              ▼
                        パンニング計算
                              │
                              ▼
                        volume_vector ──────▶ AudioServer
                              │
                              ▼
                        空間処理済み出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| audio_stream_player_2d.cpp | `scene/2d/audio_stream_player_2d.cpp` | ソース | 2D空間オーディオ実装 |
| audio_stream_player_2d.h | `scene/2d/audio_stream_player_2d.h` | ヘッダ | 2D空間オーディオ定義 |
| audio_stream_player_3d.cpp | `scene/3d/audio_stream_player_3d.cpp` | ソース | 3D空間オーディオ実装 |
| audio_stream_player_3d.h | `scene/3d/audio_stream_player_3d.h` | ヘッダ | 3D空間オーディオ定義 |
| audio_listener_2d.cpp | `scene/2d/audio_listener_2d.cpp` | ソース | 2Dリスナー |
| audio_listener_3d.cpp | `scene/3d/audio_listener_3d.cpp` | ソース | 3Dリスナー |
| velocity_tracker_3d.cpp | `scene/3d/velocity_tracker_3d.cpp` | ソース | ドップラー用速度追跡 |
