Skip to content

播放引擎

播放引擎的契約是忠於來源:解碼使用者的原始位元組,以來源自身速率播放,並保留發行版本結構。本頁是其背後的規格。

所有解碼都由 FFmpeg 在行程內完成,於每個平台上皆然:FLAC、MP3、APE、ALAC、AAC、PCM(WAV/AIFF)、Ogg Vorbis、Opus、WavPack 與 DSD 是匯入接受的格式;無論 FFmpeg 從位元組回報什麼,而不是副檔名,才是記錄中的編解碼器。樣本會以 32-bit float 進入輸出階段;樣本格式轉換是唯一執行的轉換。

輸出使用平台的原生音訊 API(桌面與 iOS 透過 cpal 使用 Core Audio,Android 使用 AAudio)。輸出串流會設定為來源的取樣率與聲道數:96 kHz 檔案會以 96 kHz 播放。沒有重新取樣階段。預設輸出裝置在每次建立串流時解析,因此播放會跟隨系統裝置切換。在 Android 上,硬體支援的編解碼器可完全繞過 FFmpeg 進行 offloaded decoding。

播放不需要整個檔案。音訊會透過 sparse buffer 讀取,視需要從本機檔案、快取或雲端抓取位元組範圍;跳轉會把目標樣本映射到位元組位置,因此跳入尚未抓取的區域會從那裡開始抓取。Fetch arbiter 會把正在播放曲目的讀取優先於預載,因此即將播放的曲目永遠不會延遲目前曲目。

曲目不是檔案;它是一個或多個檔案上有序樣本區段的清單,在匯入時由 CUE sheet 或檔案自身範圍建立。這個表示法承載每種光碟形狀:每曲一檔、整張光碟在一個映像檔中、pregap 位於某個檔案結尾與另一個檔案開頭,以及有損擷取切成每曲一檔。

Pregap 區段會被標記。當曲目有 pregap(index 00,包含隱藏曲目音訊)時,播放會從 pregap 進入該曲目,而時鐘顯示曲目時間:位置會固定在零,直到曲目本體開始;顯示的長度不包含 pregap,符合 CD 播放器行為。

下一首曲目會在目前曲目播放時開啟並緩衝。當兩者共用取樣率與聲道數時,引擎會在即時音訊 callback 內串接它們:串流不會停止,邊界精確到樣本。當格式不同時,串流會重建,這本來就是格式變更會讓邊界可聽見的情況。

匯入會在解碼驗證 pass 中測量 integrated loudness(EBU R128)與 true peak,依曲目與專輯記錄。Replay gain 會在播放時由這些測量衍生,永遠不寫入檔案:目標為 −18 LUFS,並加上限制使 true peak 不會 clip,可依曲目或專輯套用,並在無間隔邊界正常切換。該模式目前沒有設定 UI,預設關閉;可在資料庫 config file 中設定。

曲目清單帶有其面與碟結構,當使用者啟用面與面之間暫停時,引擎可在面邊界停住並顯示繼續提示。這個停住是播放服務狀態,不是已解碼的靜音,因此恢復會立即發生。