首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 結合 Bass.dll 實現播放進度顯示與拖曳定位:時間轉換與位置設置全解析

     編輯:Delphi

前言

播放進度條是播放器核心交互元件,涉及「字節位置 ↔ 時間」的雙向轉換。Bass.dll 提供四個關鍵 API 構建完整進度控制:BASS_ChannelGetLength、BASS_ChannelGetPosition、BASS_ChannelBytes2Seconds、BASS_ChannelSeconds2Bytes、BASS_ChannelSetPosition。本文詳細解析其協作邏輯並給出 Delphi 完整實現。

核心 API 對照表

函數用途關鍵參數
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

關鍵代碼實現

1. 開啟檔案:計算總時長並初始化 ScrollBar

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;

2. 計時器更新:顯示當前時間與進度條位置

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;

3. ScrollBar 拖曳定位:秒數轉字節並設置位置

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.

技術細節深度解析

  • QWORD = Int64:Bass 使用 64 位無符號整數表示字節位置,支援超大文件(>4GB)。
  • 精度考量:BASS_ChannelBytes2Seconds 返回 Double,精度可達微秒級,滿足高精度同步需求(如歌詞)。
  • 定位響應:BASS_ChannelSetPosition 為同步阻塞調用,對於本地文件幾乎瞬間完成;網路流可能需緩衝。
  • 模式旗標:BASS_POS_BYTE 是流模式唯一支援的定位單位;MOD 音樂另支援 BASS_POS_MUSIC_ORDER 等。

常見問題與優化

  1. 拖曳卡頓:頻繁觸發 OnScroll 可加入節流邏輯(如僅在 scEndScroll 時定位)。
  2. 進度條閃爍:使用 TTrackBar 替代 TScrollBar 並啟用雙緩衝。
  3. 時間格式化:將秒數轉為 mm:ss 或 hh:mm:ss 顯示更友好。

總結

掌握「字節↔時間」雙向轉換與 BASS_ChannelSetPosition 定位,即可構建流暢、精確的播放進度控制,是播放器開發的核心技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved