波形圖是音頻播放器的核心視覺元素,能直觀展示音樂動態範圍。本文詳解如何在 Delphi 中利用 Bass.dll 的解碼流(BASS_STREAM_DECODE)提取峰值數據,並繪製雙聲道波形圖,支援自定義前景/背景顏色。
hs)供播放使用。hs2,旗標 BASS_STREAM_DECODE)專門用於離線提取峰值,不輸出聲音。BASS_ChannelGetLevel 獲取左右聲道峰值,存入動態陣列 Data。Data 繪製位圖。procedure TForm1.Button1Click(Sender: TObject);
var
Mp3Path: AnsiString;
i: Cardinal;
time: Double;
hs2: HSTREAM;
begin
BASS_StreamFree(hs);
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);
bit.Free;
bit := TBitmap.Create;
PaintBox1.Repaint;
{關鍵:建立解碼流提取波形}
hs2 := BASS_StreamCreateFile(False, PAnsiChar(Mp3Path), 0, 0, BASS_STREAM_DECODE);
time := BASS_ChannelBytes2Seconds(hs2, BASS_ChannelGetLength(hs, BASS_POS_BYTE));
{每 20ms 一個峰值點,故總點數 = time * 1000 / 20 = time * 50}
SetLength(Data, Trunc(time * 50 + 1));
for i := 0 to Length(Data) - 1 do
Data[i] := BASS_ChannelGetLevel(hs2); {低 16 位左聲道,高 16 位右聲道}
BASS_StreamFree(hs2);
Draw;
end;
end;
procedure TForm1.Draw;
var
i, ch: Integer;
L, R: SmallInt;
begin
bit.Width := Length(Data);
bit.Height := PaintBox1.Height;
ch := bit.Height div 2; {中心線 Y 座標}
bit.Canvas.Brush.Color := ColorBox1.Selected; {背景色}
bit.Canvas.FillRect(Bounds(0, 0, bit.Width, bit.Height));
bit.Canvas.Pen.Color := ColorBox2.Selected; {前景色}
for i := 0 to Length(Data) - 1 do begin
L := LoWord(Data[i]); {左聲道峰值 0..32767}
R := HiWord(Data[i]); {右聲道峰值 0..32767}
{以中心線為基準,向上畫左聲道,向下畫右聲道}
bit.Canvas.MoveTo(i, ch - Trunc(L / 32768 * ch));
bit.Canvas.LineTo(i, ch + Trunc(R / 32768 * ch));
end;
PaintBox1.Repaint;
end;
procedure TForm1.ColorBox1Change(Sender: TObject);
begin
Draw;
end;
procedure TForm1.ColorBox2Change(Sender: TObject);
begin
Draw;
end;
介面提供兩個 TColorBox 分別設定背景與波形顏色,選擇後即時更新波形圖。

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
PaintBox1: TPaintBox;
Button1: TButton;
Button2: TButton;
Button3: TButton;
ColorBox1: TColorBox;
ColorBox2: TColorBox;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ColorBox1Change(Sender: TObject);
procedure ColorBox2Change(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
private
procedure Draw;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses Bass;
var
hs: HSTREAM;
Data: array of Cardinal;
bit: TBitmap;
{ ... 完整實現代碼 ... }
end.
BASS_ChannelGetLevel 返回 32 位整數,低 16 位為左聲道,高 16 位為右聲道,範圍 0~32767。Data 隨檔案長度自適應,TBitmap 重建避免殘留。可在此基礎上增加:播放進度游標同步、波形圖縮放平移、頻譜圖(FFT)切換等進階功能。