跳到主要內容
Flow

音訊

音訊輸出的實作。時鐘與同步見 engine.md,格式見 codecs.md。

FlowAVAudio 以 AVAudioOutputFactory 註冊 AudioOutput,由 AVAudioEngine 實作。

音訊圖

  • 正常速度:AVAudioSourceNode(interleaved Float32)直接接輸出,不經 mixer;音量由核心的 AudioRenderSource 套用。
  • 倍速:才接入 AVAudioUnitTimePitch(保持音高)。即使 bypass 它每個 IO 週期仍要 deinterleave 與 interleave,故只在倍速時留在圖中。
  • 格式:取樣率跟隨裝置,唯一的重取樣在解碼器(非即時執行緒);最多雙聲道,由解碼器 downmix。
  • 格式變更:裝置的取樣率或聲道數改變時,output 以 AudioRenderSource.outputFormatDidChange() 通知核心,通知前後仍以舊格式輸出、由 output unit 轉換。核心停止輸出、以 AudioOutput.updateFormat() 取得新格式,重建 PCM ring 與音訊解碼器,並從播放位置以 .exact seek 重新解碼(同解碼策略)。AVAudioSourceNode 會從建立時的格式轉換,故換格式時重建。

Render

  • render block 不捕捉任何值,經 RenderSlots 找到 RenderState,Swift 不在 render 執行緒做參照計數。
  • 只呼叫 AudioRenderSource、讀 atomic 與運算:無鎖、無配置、無 log 與 signpost(硬即時,見執行緒分級)。
  • 限制只在 render callback 內;Core Audio 每個 IO 週期在 callback 外自行上鎖一次,屬正常。
  • 量測 callback 時把時間戳寫入 ring buffer,由其他執行緒發 signpost。

裝置與延遲

  • IO 緩衝:1024 frames(預設的兩倍),IO 週期與其固定成本減半;多出的 10 ms 由延遲補償,只有暫停與音量變慢。依裝置範圍夾限,每次啟動重新套用。
  • 延遲:裝置、串流、safety offset、IO 緩衝,倍速時另加 time-stretch;啟動與裝置變更時重新查詢。
  • 裝置變更:引擎自行停止後在新裝置上重啟;格式不同時見格式變更。停止期間換的裝置在 start 時檢查。

生命週期

  • 暫停:engine.stop(),釋放 IO 資源。不用 pause():恢復後 host time 從暫停處繼續,落後暫停的時長。
  • 切換速度、flush:引擎停止時改圖或重設 time-stretch,再重啟;sample time 歸零,由核心重新錨定時鐘。
  • 預熱:模組啟用時背景建立一次 output unit,先付載入 audio HAL 與 plug-in 的成本(M4 Max 約 65 ms),不開裝置 IO(PERF-02)。