# 機能設計書 27-ユーザー定義エフェクト解析

## 概要

本ドキュメントは、KSH譜面ファイル内の#define_fxおよび#define_filterディレクティブで定義されたカスタムオーディオエフェクト・フィルターを解析し、ゲーム内エフェクトシステムに登録する機能の設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：K-Shoot MANIAの譜面フォーマットでは、デフォルトの組み込みエフェクト（Retrigger, Gate, Flanger等）に加えて、譜面制作者が独自のエフェクトパラメータを定義できる仕組みがある。これにより、より多彩な音響効果を譜面に組み込むことが可能となる。本機能はこれらのカスタム定義を解析し、ゲーム内のエフェクトシステムに反映する役割を担う。

**機能の利用シーン**：譜面読み込み時のparseKSHChartParamLinesフェーズで#define行がバッファに蓄積され、その後play_audio_effects.hsp内のエフェクト初期化処理でバッファが解析されてuserfx_name[], userfx_params[]等の配列に展開される。

**主要な処理内容**：
1. parseKSHChartParamLinesで"#define_fx"/"#define_filter"行をfxdefbuf_fx/fxdefbuf_filterに蓄積
2. play_audio_effects.hsp内でバッファを解析し、エフェクト種別（FXDEF_FXTYPE_RETR, GATE, BITC等）とパラメータを特定
3. userfx_name[], userfx_params[], userfilter_name[], userfilter_params[]配列にエフェクト定義を格納
4. parseKSHChartBody内でfx-l=/fx-r=行やfiltertype=行でユーザー定義エフェクトを参照
5. userchprm[]配列にパラメータ変化情報を格納

**関連システム・外部連携**：VSTエフェクトDLL群（regawo.dll, flan.dll, pitc.dll, bitc.dll, phas.dll, sich.dll, tstp.dll）と連携してオーディオエフェクトを適用する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | ユーザー定義エフェクトの解析と適用 |

## 機能種別

データ解析 / エフェクト設定

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fxdefbuf_fx | str | No | #define_fx行の蓄積バッファ | 複数行を"\n"で連結 |
| fxdefbuf_filter | str | No | #define_filter行の蓄積バッファ | 複数行を"\n"で連結 |

### 入力データソース

KSH譜面ファイル内の#defineディレクティブ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| userfxnum | int | ユーザー定義エフェクト総数（FX+Filter合算） |
| userfx_name[] | str配列 | エフェクト名（最大256個） |
| userfx_params[][9] | double配列 | エフェクトパラメータ（パラメータ0=種別） |
| userfx_params_enable[][9] | double配列 | パラメータ有効値 |
| userfilternum | int | ユーザー定義フィルター数 |
| userfilter_name[] | str配列 | フィルター名 |
| userfilter_params[][9] | double配列 | フィルターパラメータ |
| userfilter_params_min[][9] | double配列 | フィルターパラメータ最小値 |
| userfilter_params_max[][9] | double配列 | フィルターパラメータ最大値 |

### 出力先

ゲーム内部のグローバル変数群

## 処理フロー

### 処理シーケンス

```
1. parseKSHChartParamLines内
   ├─ "#define_fx "で始まる行をfxdefbuf_fxに蓄積
   └─ "#define_filter "で始まる行をfxdefbuf_filterに蓄積
2. play_audio_effects.hsp内のエフェクト初期化
   ├─ fxdefbuf_fxを行分割して各#define_fx行を解析
   │   ├─ エフェクト名を抽出（userfx_name[]に格納）
   │   ├─ エフェクト種別を判定（type=パラメータ）
   │   └─ 各パラメータ値をfxdef_str2paramで数値化
   └─ fxdefbuf_filterを行分割して各#define_filter行を解析
       ├─ フィルター名を抽出（userfilter_name[]に格納）
       ├─ フィルター種別を判定
       └─ min-max範囲付きパラメータを解析
3. parseKSHChartBody内
   ├─ fx-l=/fx-r=でユーザー定義エフェクト名を照合
   ├─ filtertype=でユーザー定義フィルター名を照合
   └─ チャートパラメータ変化をuserchprm[]に格納
```

### フローチャート

```mermaid
flowchart TD
    A[譜面ファイル読み込み] --> B[#define行をバッファに蓄積]
    B --> C[fxdefbuf_fx解析]
    C --> D{エフェクト種別判定}
    D --> E[Retrigger]
    D --> F[Gate]
    D --> G[BitCrusher]
    D --> H[Wobble]
    D --> I[TapeStop]
    D --> J[Echo]
    D --> K[PitchShift]
    D --> L[その他]
    E --> M[パラメータ格納]
    F --> M
    G --> M
    H --> M
    I --> M
    J --> M
    K --> M
    L --> M
    M --> N[fxdefbuf_filter解析]
    N --> O[フィルターパラメータ格納]
    O --> P[parseKSHChartBodyでの参照]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-27-01 | エフェクト種別 | FXDEF_FXTYPE_RETR/GATE/BITC/WOBB/TSTP/ECHO/PITC/FLAN/PHAS/SICH/AUDIの11種別をサポート | #define_fx解析時 |
| BR-27-02 | 最大定義数 | ユーザー定義エフェクトは最大256個まで | userfx_name配列サイズ |
| BR-27-03 | パラメータインデックス0 | userfx_params[n][0]はエフェクト種別を格納 | 全エフェクト |
| BR-27-04 | フィルター範囲指定 | フィルターはmin-max範囲付きパラメータをサポート | #define_filter解析時 |
| BR-27-05 | 動的パラメータ変化 | userchprm[]で譜面中のパラメータ変化を記録 | parseKSHChartBody内 |

### 計算ロジック

fxdef_str2param関数によりエフェクトパラメータの文字列値を数値に変換する。パラメータ種別に応じて異なる変換ロジックが適用される。

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

本機能ではデータベース操作は発生しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 未知のエフェクト種別 | type=に未知の値が指定された場合 | デフォルト値で処理続行 |
| - | パラメータ不足 | 必要なパラメータが省略された場合 | デフォルト値を使用 |

### リトライ仕様

リトライは行わない。

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

トランザクション管理は不要。

## パフォーマンス要件

ユーザー定義エフェクトの数は通常数個〜十数個程度であり、解析処理は即時完了する。

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

ユーザー定義エフェクトはVSTプラグインDLLに渡されるパラメータを含むが、DLLファイルは予め用意されたもののみが使用される。

## 備考

- userfxnumにはFXとFilter両方の数が合算される。userfxnum - userfilternumがFXの数、userfilternumがFilterの数となる。
- userfx_fl[]配列で実際に使用されるエフェクトのみにフラグが立てられ、未使用のエフェクトDLLの読み込みを避ける最適化に使用される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ユーザー定義エフェクト関連の変数初期化 |

**主要処理フロー**:
- **94-108行目**: userfxnum, userfx_name[], userfx_params[], userfilternum, userfilter_name[], userfilter_params[]等の初期化

#### Step 2: #define行の蓄積

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | parseKSHChartParamLines内の#define蓄積 |

**主要処理フロー**:
- **827-828行目**: "#define_fx "で始まる行をfxdefbuf_fxに蓄積
- **831-832行目**: "#define_filter "で始まる行をfxdefbuf_filterに蓄積

#### Step 3: エフェクト定義の解析

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_audio_effects.hsp | `src/scene/play/play_audio_effects.hsp` | fxdefbuf解析とエフェクト登録 |

**主要処理フロー**:
- **25行目**: FXDEF_FXTYPEMAX+1回ループでエフェクト種別ごとのパラメータ解析
- **52-60行目**: fxdef_str2paramでパラメータ文字列を数値に変換
- **96行目**: フィルター定義の解析

#### Step 4: 譜面本体での参照

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | parseKSHChartBody内でのユーザー定義エフェクト参照 |

**主要処理フロー**:
- **1002-1008行目**: filtertype=でユーザー定義フィルター名を照合
- **1052-1093行目**: fx-l=/fx-r=でユーザー定義エフェクト名を照合
- **1256-1353行目**: チャートパラメータ変化のuserchprm[]への格納

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

```
play_init
    |
    +-- parseKSHChartParamLines
    |     +-- "#define_fx" -> fxdefbuf_fx蓄積 (827行目)
    |     +-- "#define_filter" -> fxdefbuf_filter蓄積 (831行目)
    |
    +-- エフェクト初期化 (play_audio_effects.hsp)
    |     +-- fxdefbuf_fx解析 -> userfx_name[], userfx_params[]
    |     +-- fxdefbuf_filter解析 -> userfilter_name[], userfilter_params[]
    |     +-- fxdef_str2param() (パラメータ変換)
    |
    +-- parseKSHChartBody
          +-- userfx_name照合 (1052行目)
          +-- userfilter_name照合 (1002行目)
          +-- userchprm[]格納 (1256行目)
```

### データフロー図

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

#define_fx行 -----> fxdefbuf_fx蓄積
                         |
                    行分割・解析 -----> userfx_name[]
                         |              userfx_params[]
                         |
#define_filter行 -> fxdefbuf_filter蓄積
                         |
                    行分割・解析 -----> userfilter_name[]
                         |              userfilter_params[]
                         |
fx-l=/fx-r=行 ----> userfx_name照合 -> fx[]配列（エフェクト割当）
                         |
filtertype=行 ----> userfilter_name照合 -> anafil[]配列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ソース | #define蓄積（827-833行目）、エフェクト参照（1002-1353行目） |
| play_audio_effects.hsp | `src/scene/play/play_audio_effects.hsp` | ソース | エフェクト定義解析とDSP設定 |
| play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ソース | 変数初期化（94-108行目） |
