# 機能設計書 17-プレビューBGM再生

## 概要

本ドキュメントは、K-Shoot MANIA の選曲画面における「プレビューBGM再生」機能の設計を記述する。選曲中に楽曲のプレビューBGMを自動フェードで再生する機能である。

### 本機能の処理概要

本機能は、選曲画面でカーソルが楽曲上に停止した際、一定時間(200ms)経過後に楽曲のプレビュー音声をBASS Audio Libraryを使用して自動再生する。再生開始時にフェードイン、プレビュー区間終了時にフェードアウトし、区間終了後はループ再生する。選曲BGMとのクロスフェードも行う。

**業務上の目的・背景**：選曲画面で楽曲の音を聴くことで、プレイヤーが楽曲を聴覚的に識別・確認でき、選曲体験が向上する。特に初見の楽曲パックを探索する際に有用。

**機能の利用シーン**：選曲画面で楽曲エントリにカーソルを合わせ、200ms以上停止した際に自動的にプレビュー再生が開始される。カーソルを移動すると現在のプレビューが停止し、新しい楽曲のプレビューが開始される。

**主要な処理内容**：
1. カーソル停止判定(200ms経過後に再生開始)
2. BASS_StreamCreateFileまたはBASS_StreamCreateURLによる音声ストリーム作成
3. プレビュー開始位置の設定(minfo.selnow.levmn2.2)
4. フェードイン再生(500ms)とマスターボリューム適用
5. 選曲BGMのフェードアウト(250ms)
6. プレビュー区間終了時のフェードアウト(500ms)
7. ループ再生(区間終了 or 曲末到達で再度再生開始)
8. ボリュームエフェクト(BASS_FXSetParameters)とコンプレッサー適用

**関連システム・外部連携**：BASS Audio Library(bass.dll)。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | BASS_StreamCreateFile/BASS_StreamCreateURLによるプレビューBGM再生・フェードイン/アウト制御(mpid変数) |

## 機能種別

オーディオ再生処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| minfostr.selnow.levmn2.0 | string | Yes | 楽曲フォルダパス | - |
| minfostr.selnow.levmn2.7 | string | Yes | プレビュー音声ファイルパスまたはURL | - |
| minfo.selnow.levmn2.2 | int | Yes | プレビュー開始位置(ms) | 0以上 |
| minfo.selnow.levmn2.3 | int | Yes | プレビュー再生長(ms、0=全曲) | 0以上 |
| minfo.selnow.levmn2.4 | int | Yes | プレビューボリューム(x10) | 0以上 |
| mastervol | int | Yes | マスターボリューム(0-100) | 0-100 |

### 入力データソース

- 楽曲フォルダ内の音声ファイル(OGG/MP3/WAV)
- HTTP URLストリーミング(minfostr.selnow.levmn2.7がhttp:で始まる場合)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| mpid | int | BASS Audio Libraryのストリームハンドル |
| mfl | int | プレビュー再生状態(0:停止, 1:再生中, 2:ループ待ち) |

### 出力先

- オーディオ出力: スピーカー/ヘッドフォンからのプレビューBGM再生

## 処理フロー

### 処理シーケンス

```
1. カーソル移動検出: csongp != 現在の楽曲パス の場合
   └─ 現在のプレビューストリーム解放(BASS_StreamFree mpid)、mfl=0
2. カーソル停止200ms経過 かつ mfl=0 かつ 楽曲エントリ(minfo>=0 かつ <4)
   a. 楽曲フォルダへchdir
   b. URLの場合: BASS_StreamCreateURL
   c. ファイルの場合: fileExists確認後 BASS_StreamCreateFile
   d. ストリーム長取得(BASS_ChannelGetLength_ms)
   e. プレビュー開始位置設定(BASS_ChannelSetPosition_ms)
   f. ボリューム初期値0設定(BASS_ChannelSetAttribute)
   g. ボリュームエフェクト設定(BASS_FXSetParameters)
   h. コンプレッサー設定(BASS_FXSetParameters)
   i. フェードイン(BASS_ChannelSlideAttribute、500ms)
   j. 選曲BGMフェードアウト(BASS_ChannelSlideAttribute、250ms)
   k. 再生開始(BASS_ChannelPlay)、mfl=1
3. ループ待ち(mfl=2)からの再開
   └─ 200ms + 250ms経過後、再度プレビュー開始位置から再生
4. 再生中(mfl=1)の区間終了判定
   a. プレビュー区間終了2000ms前からフェードアウト(500ms)
   b. 区間終了 or 曲末到達でmfl=2(ループ待ち)
5. 非楽曲エントリ選択時
   └─ 選曲BGMフェードイン(500ms)
```

### フローチャート

```mermaid
flowchart TD
    A[カーソル移動検出] --> B{楽曲変更?}
    B -->|Yes| C[BASS_StreamFree mpid / mfl=0]
    B -->|No| D{mfl状態?}
    C --> D
    D -->|mfl=0 かつ 200ms経過| E{楽曲エントリ?}
    E -->|Yes| F{URL?}
    F -->|Yes| G[BASS_StreamCreateURL]
    F -->|No| H[BASS_StreamCreateFile]
    G --> I[再生設定・フェードイン・再生開始 mfl=1]
    H --> I
    E -->|No| J[選曲BGMフェードイン]
    D -->|mfl=1| K{区間終了近い?}
    K -->|Yes 2000ms前| L[フェードアウト開始]
    L --> M{区間終了?}
    M -->|Yes| N[mfl=2 ループ待ち]
    K -->|No| O[再生継続]
    D -->|mfl=2 かつ 250ms経過| P[再度フェードイン再生 mfl=1]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-17-1 | 再生待機時間 | カーソル停止後200ms経過で再生開始 | カーソル移動停止時 |
| BR-17-2 | フェードイン | 500msかけてボリュームをフェードイン | 再生開始時 |
| BR-17-3 | フェードアウト | プレビュー区間終了2000ms前から500msフェードアウト | 区間終了前 |
| BR-17-4 | BGMクロスフェード | プレビュー再生時に選曲BGMを250msフェードアウト | プレビュー再生開始時 |
| BR-17-5 | ループ再生 | 区間終了後はmfl=2を経由して再度開始位置から再生 | 区間終了またはトラック末尾到達時 |
| BR-17-6 | URL対応 | プレビューパスがhttp:で始まる場合はストリーミングURL再生 | URLパス指定時 |
| BR-17-7 | コンプレッサー | ゲイン18dB、スレッショルド-24dB、比率100:1のコンプレッサーを適用 | 常時 |

### 計算ロジック

プレビューボリュームの計算:
```
ボリュームFX値 = minfo.selnow.levmn2.4 / 10.0 / 100.0
再生ボリューム = mastervol / 100.0
```

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

本機能ではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル不在 | プレビュー音声ファイルが存在しない場合 | fileExists確認でスキップ、選曲BGMを継続 |
| - | ストリーム作成失敗 | BASS_StreamCreateFileが失敗した場合 | mfl=0のまま(再生しない) |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

- BASS Audio Libraryによるストリーミング再生のため、メモリ消費は最小限
- 0x20000フラグ(BASS_STREAM_DECODE不使用)による通常ストリーミング

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

- HTTPストリーミングURL対応のため、外部URLへのアクセスが発生する可能性がある

## 備考

- mpid変数は選曲画面全体で1つのプレビューストリームを管理する
- ストリーム解放(BASS_StreamFree)はカーソル移動時・シーン遷移時に実行される
- コンプレッサーパラメータ: fGain=18.0, fThreshold=-24.0, fRatio=100.0, fAttack=1.0, fRelease=0.01

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.hsp | `src/scene/select.hsp` | mpid(ストリームハンドル)、mfl(再生状態0/1/2)、mlength(曲長ms)、csongp(前回楽曲パス)の変数を理解 |
| 1-2 | select.hsp | `src/scene/select.hsp` | minfo.*.levmn2.2(開始位置)、minfo.*.levmn2.3(再生長)、minfo.*.levmn2.4(ボリューム)のプレビュー設定 |

**読解のコツ**: BASS Audio Libraryの関数はBASS_で始まる。BASS_ChannelSlideAttributeはボリュームの時間変化(フェード)を設定する関数。

#### Step 2: プレビュー再生ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | 2468-2525行目のプレビューBGM制御ブロック |

**主要処理フロー**:
1. **2468-2470行目**: 楽曲変更時のストリーム解放
2. **2475-2503行目**: 200ms停止後の新規再生開始
3. **2477-2484行目**: URL/ファイルの判定と読み込み
4. **2486行目**: 曲長取得(BASS_ChannelGetLength_ms)
5. **2488-2502行目**: 再生位置設定・ボリューム/コンプレッサー設定・フェードイン・再生
6. **2505-2513行目**: ループ待ち(mfl=2)からの再開処理
7. **2515-2523行目**: 再生中の区間終了判定とフェードアウト

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

```
選曲画面メインループ (毎フレーム)
    |
    +-- [楽曲変更検出] (2468行目)
    |       +-- BASS_StreamFree(mpid)
    |
    +-- [新規再生] (2475行目, mfl=0 かつ 200ms経過)
    |       +-- BASS_StreamCreateURL / BASS_StreamCreateFile
    |       +-- BASS_ChannelGetLength_ms
    |       +-- BASS_ChannelSetPosition_ms
    |       +-- BASS_ChannelSetAttribute (ボリューム0)
    |       +-- BASS_ChannelSetFX (ボリュームFX)
    |       +-- BASS_FXSetParameters (ボリューム値)
    |       +-- BASS_ChannelSetFX (コンプレッサー)
    |       +-- BASS_FXSetParameters (コンプレッサー値)
    |       +-- BASS_ChannelSlideAttribute (フェードイン500ms)
    |       +-- BASS_ChannelSlideAttribute (BGMフェードアウト250ms)
    |       +-- BASS_ChannelPlay
    |
    +-- [ループ再開] (2505行目, mfl=2 かつ 250ms経過)
    |       +-- BASS_ChannelSetPosition_ms
    |       +-- BASS_ChannelSlideAttribute (フェードイン)
    |       +-- BASS_ChannelPlay
    |
    +-- [区間終了判定] (2515行目, mfl=1)
            +-- BASS_ChannelGetPosition_ms
            +-- 2000ms前: BASS_ChannelSlideAttribute (フェードアウト500ms)
            +-- 終了時: mfl=2
```

### データフロー図

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

songs/[パス]/preview.ogg -------> BASS_StreamCreateFile -----> mpid(ストリーム)
http://url/preview.ogg ---------> BASS_StreamCreateURL ------> mpid(ストリーム)
                                       |
minfo.*.levmn2.2(開始位置) ------> BASS_ChannelSetPosition_ms
minfo.*.levmn2.4(ボリューム) ----> BASS_FXSetParameters
mastervol(マスター音量) ---------> BASS_ChannelSlideAttribute -> オーディオ出力
                                       |
timenow(時間経過) --------------> フェードイン/アウト制御 ----> ボリューム変化
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | プレビューBGM再生制御(2468-2525行目) |
| bass.as | `src/bass.as` | ソース | BASS Audio Library HSPバインディング |
| bass.dll | `lib/bass.dll` | DLL | BASS Audio Libraryランタイム |
