播放進度條是播放器核心交互元件,涉及「字節位置 ↔ 時間」的雙向轉換。Bass.dll 提供四個關鍵 API 構建完整進度控制:BASS_ChannelGetLength、BASS_ChannelGetPosition、BASS_ChannelBytes2Seconds、BASS_ChannelSeconds2Bytes、BASS_ChannelSetPosition。本文詳細解析其協作邏輯並給出 Delphi 完整實現。
| 函數 | 用途 | 關鍵參數 |
|---|---|---|
| BASS_ChannelGetLength | 獲取流總長度(字節) | mode = BASS_POS_BYTE |
| BASS_ChannelGetPosition | 獲取當前播放位置(字節) | mode = BASS_POS_BYTE |
| BASS_ChannelBytes2Seconds | 字節位置轉秒數 | pos: QWORD |
| BASS_ChannelSeconds2Bytes | 秒數轉字節位置 | pos: Double |
| BASS_ChannelSetPosition | 設置播放位置 | pos: QWORD, mode = BASS_POS_BYTE |
procedure TForm1.Button1Click(Sender: TObject);
var
Mp3Path: AnsiString;
begin
BASS_StreamFree(hs);
Timer1.Enabled := False;
ScrollBar1.Enabled := False;
OpenDialog1.Filter := 'Mp3 文件(*.mp3)|*.mp3|Wav 文件(*.wav)|*wav';
if OpenDialog1.Execute then
Mp3Path := AnsiString(OpenDialog1.FileName);
hs := BASS_StreamCreateFile(False, PAnsiChar(Mp3Path), 0, 0, 0);
if hs < BASS_ERROR_ENDED then
Caption := '打開失敗'
else begin
Caption := string(Mp3Path);
{總秒數 = 字節總長度 轉 秒}
time := BASS_ChannelBytes2Seconds(hs, BASS_ChannelGetLength(hs, BASS_POS_BYTE));
{ScrollBar 範圍設為毫秒精度}
ScrollBar1.Max := Trunc(time * 1000);
ScrollBar1.Enabled := True;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
s: Double; {當前秒數}
begin
s := BASS_ChannelBytes2Seconds(hs, BASS_ChannelGetPosition(hs, BASS_POS_BYTE));
Caption := Concat(FloatToStr(time), ' / ', FloatToStr(s)); {總時長 / 當前時長}
ScrollBar1.Position := Trunc(s * 1000); {毫秒精度}
end;
procedure TForm1.ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
var
Position: Int64;
begin
{拖曳時先暫停,避免衝突}
Button3.Click; {觸發暫停}
{將 ScrollPos(毫秒) 轉為秒,再轉為字節位置}
Position := BASS_ChannelSeconds2Bytes(hs, ScrollPos / 1000);
BASS_ChannelSetPosition(hs, Position, BASS_POS_BYTE);
Caption := Concat(FloatToStr(time), ' / ', FloatToStr(Position / 1000));
Timer1Timer(nil); {強制刷新一次}
end;
底部水平滾動條顯示播放進度,拖曳滑塊可即時跳轉至任意時間點,標題顯示「總時長 / 當前時長」。

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Timer1: TTimer;
Button1: TButton;
Button2: TButton;
Button3: TButton;
ScrollBar1: TScrollBar;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
procedure FormDestroy(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses Bass;
var
hs: HSTREAM;
time: Double; {樂曲總時間(秒)}
{ ... 完整實現代碼 ... }
end.
BASS_ChannelBytes2Seconds 返回 Double,精度可達微秒級,滿足高精度同步需求(如歌詞)。BASS_ChannelSetPosition 為同步阻塞調用,對於本地文件幾乎瞬間完成;網路流可能需緩衝。BASS_POS_BYTE 是流模式唯一支援的定位單位;MOD 音樂另支援 BASS_POS_MUSIC_ORDER 等。OnScroll 可加入節流邏輯(如僅在 scEndScroll 時定位)。TTrackBar 替代 TScrollBar 並啟用雙緩衝。mm:ss 或 hh:mm:ss 顯示更友好。掌握「字節↔時間」雙向轉換與 BASS_ChannelSetPosition 定位,即可構建流暢、精確的播放進度控制,是播放器開發的核心技能。