# 機能設計書 42-音量制御

## 概要

本ドキュメントは、K-ShootMania における楽曲ボリュームとマスターボリュームの調整機能の設計を記述する。プレイ画面、タイトル画面、選曲画面、リザルト画面等の全シーンにおいて、音声出力のボリュームを統一的に制御する機能である。

### 本機能の処理概要

**業務上の目的・背景**：音楽ゲームではプレイヤーの聴覚体験が重要であり、各楽曲固有のボリューム設定とプレイヤーが指定するマスターボリュームを組み合わせた適切な音量管理が必要である。楽曲ごとのボリューム差を吸収し、かつプレイヤーの好みに応じた音量調整を可能にするために本機能が存在する。

**機能の利用シーン**：全シーン（タイトル画面、選曲画面、プレイ画面、リザルト画面、コースリザルト画面、オプション設定画面）において音声再生時に利用される。特にプレイ画面では、楽曲ボリューム（csongvol）とマスターボリューム（mastervol）を乗算した値がリアルタイムに適用される。

**主要な処理内容**：
1. config.iniからマスターボリューム設定値（mastervol）を読み込む
2. 譜面ファイルの`mvol=`パラメータから楽曲ボリューム（csongvol）を取得する
3. csongvol>100の場合、BASS_ChannelSetFXでVolume FXエフェクトを適用して増幅する
4. BASS_ChannelSetAttributeでチャンネルのボリューム属性を`double(csongvol)/100*mastervol/100`に設定する
5. 各シーンのBGM・SE・プレビュー音にもmastervol設定を適用する

**関連システム・外部連携**：BASS Audio Library（bass.dll）のBASS_ChannelSetAttribute API

**権限による制御**：特になし。マスターボリュームはオプション設定画面で0-100%の範囲で5%刻みに設定可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | タイトル画面 | 参照画面 | BASS_ChannelSetAttributeによるタイトルBGM・SE再生時のマスターボリューム適用 |
| 3 | 曲選択画面 | 参照画面 | BGM・SE・プレビュー音のマスターボリューム適用 |
| 5 | ゲームプレイ画面 | 主画面 | csongvol/mastervolによる楽曲ボリューム・マスターボリュームの調整 |
| 6 | リザルト画面 | 参照画面 | リザルトBGMのマスターボリューム適用 |
| 7 | コースリザルト画面 | 参照画面 | コースリザルトBGMのマスターボリューム適用 |
| 8 | オプション設定画面 | 設定画面 | mastervol変数による0-100%範囲でのマスターボリューム調整（5%刻み） |

## 機能種別

リアルタイムオーディオ制御処理 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| mastervol | 整数 | Yes | マスターボリューム（0-100） | 0以上100以下、5%刻み |
| csongvol | 整数 | Yes | 楽曲ボリューム | 正の整数。100超の場合VolumeFXで補正 |
| dirvol | 整数 | Yes | ディレクトリボリューム倍率（0-100） | 0以上100以下 |

### 入力データソース

- config.ini: マスターボリューム（`#mastervol:`）
- 譜面ファイル（.ksh）: 楽曲ボリューム（`mvol=`パラメータ）
- オプション設定画面: マスターボリュームのユーザー変更

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 音声チャンネルボリューム | float | BASS_ChannelSetAttributeに設定されるボリューム値（0.0-1.0） |

### 出力先

- BASSオーディオエンジンの各チャンネルへのボリューム設定

## 処理フロー

### 処理シーケンス

```
1. 初期化時のマスターボリューム読み込み
   └─ config.iniから mastervol を読み込み（kshootmania.hsp）
2. 譜面読み込み時の楽曲ボリューム取得
   └─ mvol=パラメータから csongvol を計算: csongvol = int(mvol) * dirvol / 100
3. ボリュームFX適用判定
   └─ csongvol > 100 の場合: BASS_ChannelSetFXでVolume FXを設定し、csongvolを100にリセット
4. 毎フレームのボリューム適用
   └─ BASS_ChannelSetAttribute(チャンネル, 2, double(csongvol)/100 * mastervol/100)
5. SE・BGMへの適用
   └─ 各SE/BGM再生時に BASS_ChannelSetAttribute(チャンネル, 2, double(mastervol)/100)
```

### フローチャート

```mermaid
flowchart TD
    A[config.ini読み込み] --> B[mastervol取得]
    C[譜面ファイル読み込み] --> D[mvol=パラメータ取得]
    D --> E[csongvol = mvol * dirvol / 100]
    E --> F{csongvol > 100?}
    F -->|Yes| G[Volume FXエフェクト適用]
    G --> H[csongvol = 100に補正]
    F -->|No| I[そのまま使用]
    H --> J[毎フレーム: ボリューム設定]
    I --> J
    B --> J
    J --> K[BASS_ChannelSetAttribute]
    K --> L[vol = csongvol/100 * mastervol/100]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | ボリューム計算式 | 最終ボリューム = csongvol/100 * mastervol/100 | プレイ画面での楽曲再生時 |
| BR-42-02 | ボリューム超過補正 | csongvol>100の場合、Volume FXエフェクトで増幅しcsongvolを100にリセット | 譜面のmvolが100超の場合 |
| BR-42-03 | マスターボリューム範囲 | mastervol は 0-100 の範囲で5%刻み | オプション設定画面 |
| BR-42-04 | SE用ボリューム | SEにはmastervolのみ適用（csongvolは適用しない） | キー音、スラム音等 |

### 計算ロジック

- プレイ画面楽曲: `double(csongvol) / 100 * mastervol / 100`
- SE・キー音: `double(mastervol) / 100`
- キー音（play_utils.hsp）: `double(mastervol) / 100`
- スラム音: `double(canvol) / 100 * stat1 / 25 * mastervol / 100 * dirvol / 100`

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

本機能ではデータベース操作は発生しない。config.iniファイルへの設定保存のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 設定値不正 | mastervolが範囲外の場合 | config.ini読み込み時にデフォルト値を使用 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ボリューム変更は1フレーム以内に反映されること

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

特になし。

## 備考

- BASS_ChannelSetAttributeの第2引数=2はBASS_ATTRIB_VOLに対応する
- BASS_ChannelSlideAttributeを使用するとフェードイン/フェードアウトが可能（タイトルBGMのフェードアウト等で使用）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bass.as | `src/bass.as` | BASS_ChannelSetAttribute（30行目）とBASS_ChannelSlideAttribute（31行目）の関数宣言。第2引数の属性ID=2がボリュームを示す |

**読解のコツ**: HSPの`float`型引数がBASSライブラリの浮動小数点ボリューム値（0.0-1.0）に対応する。

#### Step 2: 設定値の読み込みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshootmania.hsp | `kshootmania.hsp` | config.iniからのmastervol読み込み |

**主要処理フロー**:
1. **config.ini解析部**: `#mastervol:`パラメータからmastervol変数に値を設定

#### Step 3: 楽曲ボリュームの取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | 譜面パラメータからcsongvolを取得 |

**主要処理フロー**:
- **234行目**: `csongvol=100*dirvol/100` でデフォルト値を設定
- **617行目**: `csongvol=int(strmid(d.cnt,5,5))*dirvol/100` で`mvol=`パラメータからcsongvolを計算
- **843行目**: `csongvol=csongvol*6/10` autoモード時の音量補正

#### Step 4: ボリューム適用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_init.hsp | `src/scene/play/play_init.hsp` | csongvol>100時のVolumeFX適用 |
| 4-2 | play_audio_effects.hsp | `src/scene/play/play_audio_effects.hsp` | 毎フレームのボリューム制御 |

**主要処理フロー**:
- **play_init.hsp 77-92行目**: csongvol>100の場合、BASS_ChannelSetFX(0x10003)でVolume FXを設定し、volfxパラメータにcsongvol/100を設定後、csongvolを100にリセット
- **play_audio_effects.hsp 868行目**: `BASS_ChannelSetAttribute mid.stat1,2,double(csongvol)/100*mastervol/100` でアクティブトラックにボリューム適用

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

```
kshootmania.hsp (config.ini読み込み)
    |
    +-- mastervol変数設定
    |
start_play (play_init.hsp)
    |
    +-- loadKSHChartFile
    |       +-- csongvol = mvol * dirvol / 100
    |
    +-- csongvol > 100 判定
    |       +-- BASS_ChannelSetFX(0x10003) -> VolumeFX
    |       +-- csongvol = 100
    |
    +-- on_update_play (毎フレーム)
            +-- processAudioEffects
                    +-- BASS_ChannelSetAttribute(mid, 2, csongvol/100*mastervol/100)
```

### データフロー図

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

config.ini                  mastervol読み込み                 mastervol変数
  #mastervol:80 --------->

譜面ファイル(.ksh)          csongvol計算                     csongvol変数
  mvol=80 ---------------> csongvol = 80 * dirvol/100

mastervol + csongvol -----> BASS_ChannelSetAttribute ------> 音声出力ボリューム
                            vol = csongvol/100 * mastervol/100
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshootmania.hsp | `kshootmania.hsp` | ソース | config.iniからのmastervol読み込みとBASSエンジン初期化 |
| play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ソース | 譜面からcsongvol取得 |
| play_init.hsp | `src/scene/play/play_init.hsp` | ソース | csongvol>100時のVolumeFX適用 |
| play_audio_effects.hsp | `src/scene/play/play_audio_effects.hsp` | ソース | 毎フレームのボリューム適用 |
| play_audio.hsp | `src/scene/play/play_audio.hsp` | ソース | レーザースラム音等のボリューム適用 |
| play_splash_screen.hsp | `src/scene/play/play_splash_screen.hsp` | ソース | スプラッシュ画面でのボリューム設定 |
| play_button_note.hsp | `src/scene/play/play_button_note.hsp` | ソース | ボタンノートSE再生時のmastervol適用 |
| play_utils.hsp | `src/scene/play/play_utils.hsp` | ソース | SE再生時のmastervol適用 |
| bass.as | `src/bass.as` | ソース | BASS API バインディング |
| option.hsp | `src/scene/option.hsp` | ソース | マスターボリューム設定UI |
