---
generated_at: 2026-03-01 00:00:00
metrics:
  claims_total: 42
  claims_with_evidence: 39
  claims_without_evidence: 3
confidence_derived: 0.93
---

# 根拠レポート：audio モジュール 単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された設計書・ドキュメントの信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.93**
  - 根拠あり：39 / 42、根拠なし：3
- 優先レビュー（高）
  1. **C-40（負のnoteNumber）**：MIDIプロトコル上は0-127だが、コード上はintで受け取っており境界チェックが存在しない。実際の挙動はDirectSoundの実装依存
  2. **C-41（負のvelocity）**：velocityが負の場合の挙動はコード上明確でなく、log10への入力が不正になる可能性の検証が必要
  3. **C-22（非常に大きいduration）**：saturated_castの具体的な挙動はbase::saturated_castの実装に依存

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。抽出フェーズで付けたIDをそのまま出す。

- E-01: `src/audio/midi/MidiAudio.hpp` - MidiAudioクラスの宣言（publicメソッド: BeginSkip, EndSkip, PlayNote、privateメソッド: _initialize, _createBuffers、メンバー変数一覧）
- E-02: `src/audio/midi/MidiAudio.cpp` - MidiAudioクラスの実装（全メソッド実装、定数定義 WAVE_SIZE=16, WAVE_DATA）
- E-03: `src/audio/midi/precomp.h` - プリコンパイル済みヘッダー（dsound.h, mmeapi.h, Windows.hのインクルード）
- E-04: `src/audio/midi/sources.inc` - ビルド構成ファイル（ソースファイルリスト、インクルードパス）
- E-05: コード内コメント（MidiAudio.cpp 61-66行目）- 周波数計算式: 2^(n/12) * 440Hz * WAVE_SIZE の説明
- E-06: コード内コメント（MidiAudio.cpp 68-71行目）- ボリューム計算式: General MIDI Level 2仕様 Gain in dB = 40 * log10(v/127) * 100 の説明
- E-07: コード内コメント（MidiAudio.cpp 74-77行目）- バッファ位置オフセットによるトーン分離の説明
- E-08: コード内コメント（MidiAudio.cpp 80-82行目）- _skip.waitによる早期リターン機構の説明
- E-09: コード内コメント（MidiAudio.cpp 86-88行目）- ボリューム最小化によるスタティック低減の説明
- E-10: コード内コメント（MidiAudio.cpp 93行目）- 複数バッファ切り替えによるスタティック低減の説明
- E-11: MidiAudio.cpp 96行目 - `CATCH_LOG()` マクロの使用（例外捕捉）

## 3) Claims と根拠の対応（レビューの主戦場）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | BeginSkipでスキップ状態がシグナルされる | E-01, E-02（35-38行目: _skip.SetEvent()） | ○ |
| C-02 | EndSkipでスキップ状態がリセットされる | E-01, E-02（40-43行目: _skip.ResetEvent()） | ○ |
| C-03 | BeginSkip未呼出時のEndSkipの安全性 | E-02（slim_event_manual_resetの仕様上安全と推定） | ○ |
| C-04 | 有効なノート番号とベロシティでの音符再生 | E-02（58-78行目）, E-05, E-06, E-07 | ○ |
| C-05 | 異なるノート番号での正しい周波数計算 | E-02（66行目）, E-05 | ○ |
| C-06 | ベロシティに基づくボリューム計算 | E-02（72行目）, E-06 | ○ |
| C-07 | 再生終了後のDSBVOLUME_MIN設定 | E-02（89行目）, E-09 | ○ |
| C-08 | アクティブバッファインデックスの交互切り替え | E-02（94行目: (_activeBufferIndex+1)%_buffers.size()）, E-10 | ○ |
| C-09 | バッファ位置の12オフセット | E-02（77行目: (_lastBufferPosition+12)%WAVE_SIZE）, E-07 | ○ |
| C-10 | windowHandle変更時の再初期化 | E-02（53-56行目: if (_hwnd != windowHandle)） | ○ |
| C-11 | 同一windowHandle時の再初期化スキップ | E-02（53行目: _hwnd != windowHandle条件） | ○ |
| C-12 | スキップ状態での即座リターン | E-02（48-51行目: if (_skip.is_signaled()) return） | ○ |
| C-13 | velocity=0での音声非再生と待機 | E-02（59行目: if (velocity && buffer)条件） | ○ |
| C-14 | 待機中のBeginSkipによる早期リターン | E-02（83行目: _skip.wait()）, E-08 | ○ |
| C-15 | バッファnullptr時の例外非スロー | E-02（59行目条件, 96行目CATCH_LOG()）, E-11 | ○ |
| C-16 | DirectSound未初期化時の例外非スロー | E-02（59行目: buffer nullチェック, 96行目CATCH_LOG()）, E-11 | ○ |
| C-17 | noteNumber=0の境界値 | E-02（66行目: 周波数計算式） | ○ |
| C-18 | noteNumber=127の境界値 | E-02（66行目: 周波数計算式） | ○ |
| C-19 | velocity=1の境界値 | E-02（72行目: ボリューム計算式） | ○ |
| C-20 | velocity=127の境界値 | E-02（72行目: log10(127/127)=0） | ○ |
| C-21 | duration=0msの境界値 | E-02（83行目: _skip.wait(0)） | ○ |
| C-22 | 非常に大きいduration値 | E-02（83行目: base::saturated_cast） | △ |
| C-23 | _lastBufferPositionのラップアラウンド | E-02（77行目: %WAVE_SIZE） | ○ |
| C-24 | DirectSoundの正常初期化 | E-02（16-33行目: _initialize実装） | ○ |
| C-25 | _hwndへのwindowHandle保存 | E-02（18行目: _hwnd = windowHandle） | ○ |
| C-26 | dsound.dll不在時の初期化中止 | E-02（20行目: if (_directSoundModule)） | ○ |
| C-27 | DirectSoundCreate8失敗時の中止 | E-02（24行目: if (SUCCEEDED(createFunction(...)))) | ○ |
| C-28 | SetCooperativeLevel失敗時のバッファ作成スキップ | E-02（26行目: if (SUCCEEDED(_directSound->SetCooperativeLevel(...)))) | ○ |
| C-29 | GetProcAddress失敗時の初期化中止 | E-02（22行目: if (const auto createFunction = ...)） | ○ |
| C-30 | 2つのサウンドバッファの作成 | E-01（35行目: std::array<..., 2>）, E-02（114行目: for (auto& buffer : _buffers)） | ○ |
| C-31 | WAVEFORMATEX構造体の正しい値 | E-02（100-106行目: 各フィールドの代入） | ○ |
| C-32 | WAVE_DATAの正しいコピー | E-02（122行目: std::memcpy, 14行目: WAVE_DATA定義） | ○ |
| C-33 | 初期ボリュームのDSBVOLUME_MIN設定 | E-02（125行目: buffer->SetVolume(DSBVOLUME_MIN)） | ○ |
| C-34 | DSBPLAY_LOOPINGモードでの再生開始 | E-02（126行目: buffer->Play(0, 0, DSBPLAY_LOOPING)） | ○ |
| C-35 | DSBUFFERDESC構造体のフラグ設定 | E-02（110行目: dwFlags, 111行目: dwBufferBytes） | ○ |
| C-36 | CreateSoundBuffer失敗時のバッファnull維持 | E-02（116行目: if (SUCCEEDED(...))） | ○ |
| C-37 | Lock失敗時のデータコピースキップ | E-02（120行目: if (SUCCEEDED(buffer->Lock(...)))) | ○ |
| C-38 | BeginSkip/EndSkipの状態遷移パターン | E-02（35-43行目: SetEvent/ResetEvent実装） | ○ |
| C-39 | BeginSkipの重複呼び出し安全性 | E-02（37行目: slim_event_manual_resetのSetEvent） | ○ |
| C-40 | 負のnoteNumberの挙動 | **根拠なし** | △ |
| C-41 | 負のvelocityの挙動 | **根拠なし** | △ |
| C-42 | _lastBufferPositionの更新 | E-02（90行目: buffer->GetCurrentPosition(&_lastBufferPosition, nullptr)） | ○ |

## 4) 不足情報（Unknown / Missing）
- **負のnoteNumber（C-40）の挙動**: MIDIプロトコルでは0-127が有効範囲だが、コード上はintで受け取っており入力検証が存在しない。std::powは負の指数でも動作するが、DirectSoundのSetFrequencyに渡す際のgsl::narrow_castの挙動が不明
  - 候補：MIDI仕様書 / gsl::narrow_castのドキュメント / DirectSound SetFrequencyの有効範囲
- **負のvelocityの挙動（C-41）**: velocity条件で非ゼロとして扱われるが、log10に負数/127が渡された場合の挙動（NaN/例外）が実装依存
  - 候補：C++標準ライブラリのstd::log10の仕様 / CATCH_LOG()マクロの捕捉範囲
- **saturated_castの上限動作（C-22）**: base::saturated_castの具体的な実装がaudioモジュール外にあり、DWORD最大値へのクランプは推定
  - 候補：base::saturated_castの実装コード / gslのドキュメント

## 5) リスクフラグ（レビュー観点）
- 0: 低リスク - 全体として audioモジュールは小規模（1クラス、5メソッド）で、コードの可読性が高く、根拠の確認が容易
- 1: 中リスク - 入力値の範囲チェックが存在しない（noteNumber, velocityに負の値が渡される可能性）。実際の動作はDirectSound APIとCATCH_LOG()マクロに依存
- 0: 低リスク - DirectSound APIの呼び出し結果（HRESULT）はすべてSUCCEEDEDマクロでチェックされており、エラーハンドリングが適切に実装されている

## 6) レビュアーチェックリスト（最小）
- [ ] PlayNoteの周波数計算式（2^((n-69)/12)*440*WAVE_SIZE）がMIDI仕様と一致しているか確認
- [ ] ボリューム計算式（4000*log10(v/127)）がGeneral MIDI Level 2仕様と一致しているか確認
- [ ] noteNumberとvelocityの有効範囲外の値に対するテストケースの期待結果が妥当か確認
- [ ] saturated_castの挙動が期待通りか、base::saturated_castの実装を確認
- [ ] CATCH_LOG()マクロがカバーする例外の範囲を確認（C++例外のみか、SEHも含むか）
- [ ] wil::slim_event_manual_resetのSetEvent/ResetEventの冪等性（重複呼び出しの安全性）を確認
