# 機能設計書 59-サウンドデバイス

## 概要

本ドキュメントは、FreeBSDにおけるオーディオデバイスドライバの設計を記述する。サウンドサブシステムはPCM（Pulse Code Modulation）フレームワークを中心に、各種オーディオハードウェアドライバとミキサー、仮想チャネル（vchan）機能を提供する。

### 本機能の処理概要

サウンドデバイスドライバは、FreeBSD独自のPCMサウンドフレームワークを用いて、オーディオハードウェアの制御と音声データの入出力を管理する。OSS（Open Sound System）互換のAPIを提供し、ユーザ空間アプリケーションからの音声再生・録音を実現する。

**業務上の目的・背景**：マルチメディアアプリケーション、VoIP、音声通知等にオーディオ出力/入力が必要である。FreeBSDのサウンドシステムはvchan（仮想チャネル）により複数アプリケーションからの同時音声出力をサポートし、ソフトウェアミキシングを提供する。

**機能の利用シーン**：音楽/動画再生、VoIP通話、システム通知音、オーディオ録音、USBオーディオデバイスの利用、HDMIオーディオ出力。

**主要な処理内容**：
1. サウンドデバイスの検出・初期化（PCI/ISA/USB）
2. PCMチャネル管理（再生/録音）
3. 仮想チャネル（vchan）によるソフトウェアミキシング
4. サンプルレート変換（feeder）
5. フォーマット変換（feeder chain）
6. ミキサー制御（ボリューム、バランス等）
7. sndstat（/dev/sndstat）による状態表示
8. OSS互換ioctl処理
9. MIDIサポート
10. sysctl経由のパラメータ管理

**関連システム・外部連携**：USBオーディオドライバ（sys/dev/sound/usb/）、PCIオーディオドライバ（sys/dev/sound/pci/）、HDMIオーディオ（DRMドライバ連携）。

**権限による制御**：/dev/dsp*デバイスノードへのアクセス権限により制御。通常はaudioグループのメンバーがアクセス可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （カーネルドライバのため関連画面なし） | - | - |

## 機能種別

デバイスドライバ / オーディオI/O / ミキシング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| PCMデータ | buffer | Yes | 音声サンプルデータ | 有効なPCMフォーマット |
| サンプルレート | int | Yes | サンプリング周波数(Hz) | 8000-192000 |
| チャネル数 | int | Yes | モノラル/ステレオ等 | 1-8 |
| ビット深度 | int | Yes | サンプルあたりのビット数 | 8/16/24/32 |
| ミキサーコマンド | ioctl | No | ボリューム制御等 | 有効なOSS mixer ioctl |

### 入力データソース

- /dev/dsp*デバイスノード（音声データの書き込み）
- ioctl（フォーマット設定、ミキサー制御）
- sysctl（hw.snd.*パラメータ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| オーディオ出力 | audio signal | DAC経由のアナログ/デジタル音声出力 |
| 録音データ | PCM buffer | ADC経由のデジタル音声データ |
| sndstat情報 | text | サウンドデバイス状態情報 |

### 出力先

- オーディオハードウェア（DAC → スピーカー/ヘッドフォン）
- /dev/dsp*（録音データの読み出し）
- /dev/sndstat（状態情報）
- sysctl（hw.snd.*統計情報）

## 処理フロー

### 処理シーケンス

```
1. デバイス検出
   └─ PCI/ISA/USBバスからオーディオデバイスを検出
2. PCMデバイス初期化
   └─ チャネル作成、フィーダーチェーン構築
3. デバイスオープン
   └─ /dev/dsp*のopen()でチャネル確保
4. フォーマット設定
   └─ SNDCTL_DSP_SETFMT等のioctlでPCMフォーマット設定
5. データ転送
   └─ write()でPCMデータをバッファに書き込み
6. フィーダー処理
   └─ サンプルレート変換、フォーマット変換
7. DMA転送
   └─ ハードウェアバッファへのDMA転送
8. 割り込み処理
   └─ DMA完了割り込みでバッファ更新
```

### フローチャート

```mermaid
flowchart TD
    A[デバイス検出] --> B[PCMデバイス初期化]
    B --> C[vchan初期化]
    C --> D[デバイスオープン /dev/dsp]
    D --> E[フォーマット設定 ioctl]
    E --> F[PCMデータ書き込み]
    F --> G[feeder chain処理]
    G --> H{変換必要?}
    H -->|Yes| I[サンプルレート/フォーマット変換]
    H -->|No| J[DMAバッファに転送]
    I --> J
    J --> K[DMA転送実行]
    K --> L{DMA完了割り込み}
    L --> M[バッファ位置更新]
    M --> F
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | vchanソフトウェアミキシング | 複数アプリケーションからの同時再生をvchanでミキシング | 複数プロセスが同時にdspを使用 |
| BR-59-02 | ソフトフォーマット報告 | hw.snd.report_soft_formats=1でソフトウェアエミュレーションフォーマットも報告 | デフォルト有効 |
| BR-59-03 | レイテンシ設定 | hw.snd.latencyでバッファレイテンシを制御 | 低レイテンシ要求時 |

### 計算ロジック

バッファサイズ計算: サンプルレート x チャネル数 x バイト/サンプル x レイテンシ係数。

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

該当なし（カーネルドライバ）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EBUSY | デバイスビジー | 排他アクセス時に他プロセスが使用中 | vchan有効化または待機 |
| EINVAL | 不正パラメータ | サポートされないフォーマット/レート | 対応フォーマットに変更 |
| EIO | I/Oエラー | ハードウェアエラー | デバイスリセット |

### リトライ仕様

DMAアンダーラン/オーバーラン時はバッファを再初期化して継続。

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

該当なし（ストリーミング処理）。

## パフォーマンス要件

- 低レイテンシ再生: 最小バッファレイテンシでの音声出力（数ミリ秒）
- サンプルレート変換: リアルタイム処理可能な計算量
- vchanミキシング: CPU負荷最小でのソフトウェアミキシング

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

- /dev/dsp*のデバイスノード権限による制御
- オーディオ録音はプライバシーに関わるため、適切なアクセス制御が重要

## 備考

- FreeBSDのサウンドシステムはOSS互換APIを提供
- vchan機能により仮想チャネル経由の同時再生をサポート
- feeder chainアーキテクチャによるモジュラーなフォーマット変換
- Christos Margiolisにより2024-2025年に大幅な改善が行われた

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sound.h | `sys/dev/sound/pcm/sound.h` | PCMサウンドフレームワークの基本構造体定義 |

**読解のコツ**: sound.hの**39-77行目**にカーネルヘッダのインクルードがあり、sys/soundcard.h（OSS互換定義）が**68行目**でインクルードされている。**78-80行目**にpcm_channel、pcm_feeder、snd_dbufの前方宣言がある。

#### Step 2: チャネル管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | channel.c | `sys/dev/sound/pcm/channel.c` | PCMチャネルのコア実装 |

**主要処理フロー**:
1. **45-47行目**: report_soft_formats, report_soft_matrix - sysctlパラメータ
2. **53行目**: chn_latency = CHN_LATENCY_DEFAULT - レイテンシデフォルト値
3. **55-60行目**: sysctl_hw_snd_latency() - レイテンシsysctlハンドラ

#### Step 3: 仮想チャネルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | vchan.c | `sys/dev/sound/pcm/vchan.c` | 仮想チャネル（ソフトウェアミキシング） |

#### Step 4: sndstatを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sndstat.c | `sys/dev/sound/sndstat.c` | /dev/sndstat状態表示 |

#### Step 5: ハードウェアドライバを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | pci/ | `sys/dev/sound/pci/` | PCI接続オーディオドライバ群 |
| 5-2 | usb/ | `sys/dev/sound/usb/` | USBオーディオドライバ |

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

```
ユーザ空間アプリケーション
    |
    +-- open(/dev/dsp) → chn_open() [channel.c]
    +-- write()        → chn_write() [channel.c]
    |                      +-- feeder_chain処理
    |                      +-- sndbuf_feed() → DMAバッファ
    +-- ioctl()        → chn_ioctl() [channel.c]
    |                      +-- SNDCTL_DSP_SETFMT
    |                      +-- SNDCTL_DSP_SPEED
    +-- read()         → chn_read() [channel.c] (録音)

vchan (仮想チャネル) [vchan.c]
    +-- vchan_mix() → 複数チャネルのミキシング
        +-- feeder_chain → ハードウェアチャネル

driver.c (デバイスドライバ登録)
    +-- pcm_register() / pcm_unregister()
```

### データフロー図

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

PCMデータ    ────▶ chn_write()                ────▶ feeder chain
(/dev/dsp)         チャネルバッファ                     ↓
                                               フォーマット変換
                                               サンプルレート変換
                                                     ↓
                                               vchan ミキシング
                                                     ↓
                                               DMAバッファ ──▶ DAC ──▶ スピーカー

ADC ──▶ DMAバッファ ──▶ feeder chain ──▶ chn_read() ──▶ PCMデータ
(マイク入力)                                            (/dev/dsp)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sound.h | `sys/dev/sound/pcm/sound.h` | ヘッダ | PCMフレームワーク定義 |
| channel.c | `sys/dev/sound/pcm/channel.c` | ソース | チャネル管理 |
| vchan.c | `sys/dev/sound/pcm/vchan.c` | ソース | 仮想チャネル |
| driver.c | `sys/dev/sound/driver.c` | ソース | ドライバ登録 |
| sndstat.c | `sys/dev/sound/sndstat.c` | ソース | sndstat状態表示 |
| sndstat.h | `sys/dev/sound/sndstat.h` | ヘッダ | sndstat定義 |
| pci/ | `sys/dev/sound/pci/` | ディレクトリ | PCI オーディオドライバ |
| usb/ | `sys/dev/sound/usb/` | ディレクトリ | USBオーディオドライバ |
| isa/ | `sys/dev/sound/isa/` | ディレクトリ | ISAオーディオドライバ |
| midi/ | `sys/dev/sound/midi/` | ディレクトリ | MIDIサポート |
| dummy.c | `sys/dev/sound/dummy.c` | ソース | ダミーオーディオデバイス |
