Skip to content

リアルタイム安全性

「リアルタイム安全」とは、同じ libsonare の DSP を、ライブの音声コールバック内でグリッチなく動かせる性質です。オンにする機能ではなく、音声経路が決して破ってはならない規則の集まりです。本ページはその規則と、libsonare がどう守るかを説明します。ストリーミング API は リアルタイムとストリーミング を参照してください。

音声コールバックには締め切りがある

音声は高優先度スレッド上でブロック単位で届き、各ブロックはスピーカーが必要とするに — しばしば数ミリ秒以内に — 埋めなければなりません。一度でもその締め切りを逃すと、聞こえるクリック・ポップ・ドロップアウトになります。つまりコールバックには厳しいリアルタイム締め切りがあり、所要時間が無制限になり得るものはコールバック内で禁じられます。

コールバック内で禁じられること

禁止事項音声を壊す理由
メモリ確保(new/malloc予測できない時間ブロックし得る
ロック/ミューテックス他スレッド待ちで止まり得る
ファイル/ネットワーク I/Oレイテンシが無制限
無制限の処理全般1 回の超過で締め切りを逃す

規律はこうです — 遅い作業(確保、ファイル読み込み、セットアップ)はコールバックので済ませ、コールバックは事前に作ったバッファを読んで処理するだけにします。

libsonare が安全を保つ方法

libsonare のリアルタイム経路は、コールバックの規則を次の方法で守ります。

技法意味
バッファの事前確保音声ブロックごとのメモリ確保を避ける
ロックフリーなパラメータ更新UI からの変更で音声スレッドを止めない
パラメータスムージング値の変化でクリックを出さない
デノーマル対策減衰時の極小浮動小数点値による CPU スパイクを避ける

これらにより、同じ DSP コードをオフラインでもライブでも動かせます。

AudioWorklet

ブラウザではリアルタイム音声は AudioWorklet で動きます。これはメインスレッドとは別の、音声処理専用のコンテキストです。

想定する流れは次の通りです。

  1. メインスレッドでオブジェクトを準備する。
  2. 準備済みの処理を AudioWorklet へ渡す。
  3. Worklet 内ではメモリ確保をせずにブロックを処理する。

サイトはこの経路を SAB フリーで動かします。つまり SharedArrayBuffer を使わないため、特別な COOP/COEP ヘッダは不要です。

libsonare がリアルタイム安全性をどう実装するか

ミキサーのストリップ・バス、RealtimeEngineStreamAnalyzer は、リアルタイム安全なコアを共有します。主な要素は次のとおりです。

  • 事前確保バッファ(ブロックごとの再利用向けの Mixer.createRealtimeBuffer() を含む)
  • ロックフリーなパラメータ変更
  • デノーマル対策
  • クリックなしの変化のためのパラメータスムーザー
  • 並列経路をそろえるプラグインディレイ補償

スレッドをまたぐ必要のある状態は、ロックフリーチャンネルで移され、直接読むのではなくテレメトリとして公開されます。そのため同じ DSP が、オフラインレンダリングでもブラウザの AudioWorklet 内でも、コード変更なしに動きます。

関連: リアルタイムとストリーミング, ストリーミング解析, リアルタイムエンジン, ブラウザ内ローカル処理