Audio Engine API
音声キャプチャ・再生エンジンの内部API定義。
1. 概要
Audio Engineは以下の責務を持つ:
- オーディオデバイスの列挙・選択
- 音声キャプチャ(入力)
- 音声再生(出力)
- ローカルモニタリング
- サンプルレート変換
- デバイス切断時の自動フォールバック
1.1 自動開始仕様
アプリケーション起動時、オーディオエンジンは自動的に開始される:
- 開始タイミング: Tauriアプリケーションの
setupフック内 - 使用デバイス: システムのデフォルト入力/出力デバイス
- Start/Stopボタン: UIに残すが、デバイス切り替えは即時反映
- 失敗時: エラーログを出力し、ユーザーは手動でデバイスを選択して再試行
1.2 デバイス即時切り替え
デバイス選択UIでデバイスを変更した場合:
- 入力デバイス: 即座にキャプチャストリームを再作成(10-50msの音切れ)
- 出力デバイス: 即座に再生ストリームを再作成(10-50msの音切れ)
- 停止→再開始の操作は不要
1.3 デバイス切断時の自動フォールバック
使用中のデバイスが切断された場合:
- cpalの
StreamError::DeviceNotAvailableを検知 - システムのデフォルトデバイスに自動切り替え
- フロントエンドに
device-disconnectedイベントを送信 - UIにトースト通知を表示
2. モジュール構成
audio/
├── codec.rs # コーデック(PCM, Opus)
├── device.rs # デバイス管理
├── engine.rs # オーディオエンジン(キャプチャ・再生)
├── error.rs # エラー型
├── plc.rs # Packet Loss Concealment
└── resampler.rs # サンプルレート変換(ADR-013)
3. デバイス管理 API
3.1 デバイス列挙
/// 利用可能な入力デバイス一覧を取得
///
/// スレッド: 任意
/// ブロッキング: No
fn list_input_devices() -> Result<Vec<AudioDevice>, AudioError>;
/// 利用可能な出力デバイス一覧を取得
///
/// スレッド: 任意
/// ブロッキング: No
fn list_output_devices() -> Result<Vec<AudioDevice>, AudioError>;
3.2 デバイス情報
struct AudioDevice {
/// デバイス識別子
id: DeviceId,
/// 表示名
name: String,
/// 対応サンプルレート
supported_sample_rates: Vec<u32>,
/// 対応チャンネル数
supported_channels: Vec<u16>,
/// デフォルトデバイスかどうか
is_default: bool,
/// ASIO対応(Windowsのみ)
is_asio: bool,
}
3.3 デバイス選択
/// 入力デバイスを設定
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: Yes(デバイスオープン完了まで)
///
/// # 注意
/// キャプチャ中に呼び出した場合、キャプチャは停止される
fn set_input_device(device_id: DeviceId) -> Result<(), AudioError>;
/// 出力デバイスを設定
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: Yes(デバイスオープン完了まで)
///
/// # 注意
/// 再生中に呼び出した場合、再生は停止される
fn set_output_device(device_id: DeviceId) -> Result<(), AudioError>;
4. キャプチャ API
4.1 設定
struct CaptureConfig {
/// サンプルレート(Hz)
sample_rate: u32,
/// チャンネル数
channels: u16,
/// フレームサイズ(サンプル数)
frame_size: u32,
/// ビット深度
bit_depth: BitDepth,
}
enum BitDepth {
I16,
I24,
F32,
}
4.2 キャプチャ開始・停止
/// 音声キャプチャを開始
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: No(即座にリターン、キャプチャは別スレッドで実行)
///
/// # コールバック
/// キャプチャされた音声データは `on_audio_captured` コールバックで通知される
fn start_capture(config: CaptureConfig) -> Result<(), AudioError>;
/// 音声キャプチャを停止
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: Yes(キャプチャスレッド終了まで)
fn stop_capture() -> Result<(), AudioError>;
4.3 コールバック
/// 音声キャプチャコールバック
///
/// スレッド: リアルタイムオーディオスレッドから呼び出される
///
/// # 制約
/// - メモリアロケーション禁止
/// - ブロッキングI/O禁止
/// - ミューテックスの長時間保持禁止
/// - 処理時間: frame_size / sample_rate 以内(例: 128/48000 = 2.67ms)
fn on_audio_captured(data: &AudioBuffer, timestamp: u64);
5. 再生 API
5.1 設定
struct PlaybackConfig {
/// サンプルレート(Hz)
sample_rate: u32,
/// チャンネル数
channels: u16,
/// フレームサイズ(サンプル数)
frame_size: u32,
/// ビット深度
bit_depth: BitDepth,
}
5.2 再生開始・停止
/// 音声再生を開始
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: No
fn start_playback(config: PlaybackConfig) -> Result<(), AudioError>;
/// 音声再生を停止
///
/// スレッド: 非リアルタイムスレッドから呼び出すこと
/// ブロッキング: Yes
fn stop_playback() -> Result<(), AudioError>;
5.3 音声データ供給
/// 再生用音声データをキューに追加
///
/// スレッド: 任意(ロックフリーキュー使用)
/// ブロッキング: No
///
/// # 戻り値
/// キューに追加できた場合は Ok、キューが満杯の場合は Err
fn enqueue_audio(data: AudioBuffer, timestamp: u64) -> Result<(), AudioError>;
6. ローカルモニタリング API
/// ローカルモニタリングを有効化
///
/// スレッド: 任意
/// ブロッキング: No
///
/// # 動作
/// キャプチャした音声を遅延なしで出力にミックスする
fn enable_local_monitoring() -> Result<(), AudioError>;
/// ローカルモニタリングを無効化
fn disable_local_monitoring() -> Result<(), AudioError>;
/// ローカルモニタリングの音量を設定
///
/// # 引数
/// - volume: 0.0(無音)〜 1.0(最大)
fn set_local_monitoring_volume(volume: f32) -> Result<(), AudioError>;
7. ミキサー API
/// 参加者の音量を設定
///
/// スレッド: 任意(アトミック操作)
/// ブロッキング: No
///
/// # 引数
/// - participant_id: 参加者ID
/// - volume: 0.0(無音)〜 1.0(最大)
fn set_participant_volume(participant_id: ParticipantId, volume: f32);
/// 参加者をミュート
fn mute_participant(participant_id: ParticipantId);
/// 参加者のミュートを解除
fn unmute_participant(participant_id: ParticipantId);
/// マスター音量を設定
fn set_master_volume(volume: f32);
8. バッファ
8.1 AudioBuffer
struct AudioBuffer {
/// サンプルデータ(インターリーブ形式)
data: Vec<f32>,
/// チャンネル数
channels: u16,
/// サンプル数(チャンネルあたり)
samples: u32,
}
8.2 リングバッファ
/// ロックフリーリングバッファ
///
/// 単一プロデューサー・単一コンシューマー(SPSC)
struct RingBuffer<T> {
// ...
}
impl<T> RingBuffer<T> {
/// バッファを作成
fn new(capacity: usize) -> Self;
/// データをプッシュ(プロデューサー側)
/// ブロッキング: No
fn push(&self, item: T) -> Result<(), T>;
/// データをポップ(コンシューマー側)
/// ブロッキング: No
fn pop(&self) -> Option<T>;
/// 現在のアイテム数
fn len(&self) -> usize;
}
9. エラー
pub enum AudioError {
/// デバイスが見つからない
DeviceNotFound(String),
/// デバイスオープン失敗
DeviceOpenFailed(String),
/// サポートされていない設定
UnsupportedConfig(String),
/// ストリームエラー
StreamError(String),
/// バッファオーバーフロー
BufferOverflow,
/// バッファアンダーラン
BufferUnderrun,
/// リサンプリングエラー(ADR-013)
ResamplerError(String),
}
10. リサンプラー API(ADR-013)
ADR-013で決定された受信側リサンプリング戦略を実装するモジュール。
10.1 概要
- 送信側: サンプルレート変換なし(ネイティブレートで送信)
- 受信側: ピアのサンプルレートがローカルと異なる場合のみリサンプリング
- 目的: 低遅延優先、必要な場合のみ変換
10.2 AudioResampler トレイト
/// Trait for audio resampling
pub trait AudioResampler: Send {
/// Process input samples and return resampled output
fn process(&mut self, input: &[f32]) -> Result<Vec<f32>, ResamplerError>;
/// Get the latency introduced by resampling in samples (at output rate)
fn latency_samples(&self) -> usize;
/// Get the latency introduced by resampling in milliseconds
fn latency_ms(&self, output_rate: u32) -> f32;
}
10.3 リサンプラー実装
/// Passthrough resampler for same sample rate (no conversion)
pub struct PassthroughResampler;
/// Fast resampler using rubato for real-time audio
pub struct FastResampler {
input_rate: u32,
output_rate: u32,
chunk_size: usize,
}
impl FastResampler {
/// Create a new fast resampler
///
/// # Arguments
/// * `input_rate` - Input sample rate in Hz
/// * `output_rate` - Output sample rate in Hz
/// * `chunk_size` - Expected input chunk size (frame size)
pub fn new(input_rate: u32, output_rate: u32, chunk_size: usize)
-> Result<Self, ResamplerError>;
}
10.4 ファクトリ関数
/// Create a resampler for the given sample rates
///
/// Returns a PassthroughResampler if input and output rates are the same,
/// otherwise returns a FastResampler.
pub fn create_resampler(
input_rate: u32,
output_rate: u32,
chunk_size: usize,
) -> Result<Box<dyn AudioResampler>, ResamplerError>;
10.5 ResamplerError
pub enum ResamplerError {
/// Resampler creation failed
CreationFailed(String),
/// Resampling failed
ProcessFailed(String),
/// Invalid sample rate
InvalidSampleRate(u32),
}
10.6 サポートされるサンプルレート
| サンプルレート | 説明 |
|---|---|
| 44100 Hz | CD品質 |
| 48000 Hz | 推奨(標準) |
| 96000 Hz | 高品質 |
11. デバイスイベント
11.1 AudioEvent
オーディオストリームで発生するイベント。デバイス切断検知に使用。
/// Events that can occur during audio streaming
#[derive(Debug, Clone)]
pub enum AudioEvent {
/// Input device was disconnected
InputDeviceDisconnected,
/// Output device was disconnected
OutputDeviceDisconnected,
/// Stream error occurred
StreamError(String),
}
11.2 イベント送信の設定
impl AudioEngine {
/// Set event sender for device change notifications
///
/// Thread: Non-realtime thread
/// Must be called before starting capture/playback
pub fn set_event_sender(&mut self, tx: Sender<AudioEvent>);
}
11.3 DeviceEvent(サービスレイヤー)
AudioServiceからフロントエンドへ送信されるイベント。
/// Events sent from the audio thread to notify about device changes
#[derive(Debug, Clone)]
pub enum DeviceEvent {
/// Input device was disconnected and fallback occurred
InputDeviceDisconnected {
/// Device name if fallback succeeded, None if failed
fallback_device: Option<String>,
},
/// Output device was disconnected and fallback occurred
OutputDeviceDisconnected {
/// Device name if fallback succeeded, None if failed
fallback_device: Option<String>,
},
}
11.4 Tauri イベント
フロントエンドへはdevice-disconnectedイベントとしてemitされる:
{
"type": "input" | "output",
"fallback": "default" | null
}
12. スレッドモデル
┌─────────────────────────────────────────────────────────┐
│ Main Thread │
│ (デバイス設定、開始/停止) │
└─────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Capture Thread │ │ Playback Thread │ │ Monitor Thread │
│ (リアルタイム) │ │ (リアルタイム) │ │ (リアルタイム) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ ▲ │
│ │ │
▼ │ │
┌─────────────────────────┴───────────────┘
│ Lock-free Ring Buffer
└─────────────────────────────────────────┘
13. 使用例
// デバイス列挙
let inputs = list_input_devices()?;
let outputs = list_output_devices()?;
// デバイス選択
set_input_device(inputs[0].id)?;
set_output_device(outputs[0].id)?;
// キャプチャ設定
let config = CaptureConfig {
sample_rate: 48000,
channels: 1,
frame_size: 128,
bit_depth: BitDepth::F32,
};
// コールバック設定
set_capture_callback(|data, timestamp| {
// ネットワーク送信キューに追加
network.send_audio(data, timestamp);
});
// 開始
start_capture(config)?;
start_playback(playback_config)?;
enable_local_monitoring()?;
// ... セッション中 ...
// 停止
stop_capture()?;
stop_playback()?;