📄 tplaywaveunit.~pas
字号:
//***********************************************************************//
// //
// 放音单元 //
// 单元名: TPlayWaveUnit //
// 功能: 放音、对音频进行编辑操作 //
// 实现方法: 采用音频底层操作 //
// 特点: 放音的同时显示波形并可对音频数据进行编辑 //
// 日期: 2003 年 1月 13日 //
// //
//***********************************************************************//
unit TPlayWaveUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, MMSystem, ExtCtrls,
Forms, Dialogs, TCMWaveType, ComCtrls;
Type
TCMPlayWave = Class
private
{ Private declarations }
FFileName: PChar;
hio: HMMIO; //当前打开的音频文件句柄
hwo: HWAVEOUT; //设备句柄
MODInt: LongInt; //最后的( 少于指定长度 )数据长度
PlaySize: LongInt; //要播放的数据的长度
pFormat: PWAVEFORMATEX; //波形格式结构
hFormat: THANDLE; //波形格式结构句柄
PlayLoop: Integer; //分段播放的总段数
DataLength: DWORD; //音频数据的总长度
GotoPosition: DWORD; //从指定位置开始播放
FirstData: PChar; //双缓存数据指针
NextData: PChar; //双缓存数据指针
SetMemTime: TTimer; //用于读取数据
PlayDataLength: DWORD; //要播放的音频数据的总长度
PasteDataLength: LongInt; //可用于粘贴的数据的长度
CopyDataFileName: String; //保存可用于粘贴的数据的临时文件
CopyBackFileName: String; //进行音频编辑时, 用于保存临时数据的文件
UndoBackFileName: String; //用于保存最后一次编辑前的音频数据的临时文件
BackFileName: String; //打开一个音频文件后, 用于放音的临时文件
FNowPlay: TCMPlaying; //当前处于何种操作状态下
FDesBMP: TBitMap; //画波形用的源位图对像
FDrawWave: TPaintBox; //用于显示波形的目标画布对像
WaveMin, WaveMax: LongInt; //波形的最小与最大数据值
FDetachLength: LongInt; //句子个数
FPosition: DWORD; //当前播放位置
FCanUndo: Boolean; //当前能否进行撤消操作
FShowDrawWave: Boolean; //是否显示波形
FShowMessageParBar: TProgressBar; //用于显示进度的进度条
FDrawBackColor: TColor; //波形背景色
FDrawLineColor: TColor; //波形颜色
FWaveLoop: TWaveLoopNotifyEvent;
FWavePlayKM: byte;
procedure PlayWave; //放音子过程
procedure SetFileName(const Value: String);
function GetFileName: String;
function OpenFileName(Name: PChar; Draw: Boolean = TRUE): Boolean;
procedure SetDesBMP(const Value: TBitMap);
procedure SetDrawWave(const Value: TPaintBox);
procedure SetPlayMem(Sender: TObject);
procedure SDTime(Sender: TObject);
procedure WriteWaveData(Dhio: HMMIO; Length: Integer); //读取数据过程
procedure CloseWaveFile;
function GetCanPaste: Boolean;
function GetMaxVal: Longint;
procedure SetShowDrawWave(const Value: Boolean);
procedure SetShowMessageParBar(const Value: TProgressBar);
procedure SetDrawBackColor(const Value: TColor);
procedure SetDrawLineColor(const Value: TColor);
procedure SetWaveLoop(const Value: TWaveLoopNotifyEvent);
procedure ShowPoistrator(WaveEvent: TWaveLoopEventType; Max, Min, Position: DWORD);
procedure SetWavePlayKM(const Value: byte);
public
{ Public declarations }
constructor Create; overload; //构造器
destructor Destroy; override; //析构器
procedure Free; //释放
procedure New;
procedure Play(const Start: DWORD = 0; const Length: DWORD = 0);
procedure Stop;
procedure Pause;
procedure Restart;
procedure CloseWave;
procedure DrawShowWave;
procedure Save(const NewFileName: String; const StartPoi: LongInt = 0;
const SaveLength: LongInt = 0);
procedure Copy(const StartPoi, Length: LongInt);
procedure Cut(const StartPoi, Length: LongInt);
procedure Paste(const StartPoi, Length: LongInt; DrawData: Boolean = TRUE);
procedure Delete(const StartPoi, Length: LongInt; DrawData: Boolean = TRUE);
procedure Undo(DrawData: Boolean = TRUE);
property FileName: String read GetFileName write SetFileName;
property NowPlay: TCMPlaying read FNowPlay;
function IntToWaveLength(const Position: Integer): LongInt;
procedure SetMinMaxData;
procedure SetWaveFile(const Value: String);
procedure IntToWaveTime(const Length: LongInt; var Time: TCM_Wave_Time);
property DrawWave: TPaintBox read FDrawWave write SetDrawWave;
property DesBMP: TBitMap read FDesBMP write SetDesBMP;
property Position: DWORD read FPosition;
property WaveLength: DWORD read DataLength;
property CanUndo: Boolean read FCanUndo;
property CanPaste: Boolean read GetCanPaste;
property MaxVal: LongInt read GetMaxVal;
property ShowDrawWave: Boolean read FShowDrawWave write SetShowDrawWave default TRUE;
property ShowMessageParBar: TProgressBar read FShowMessageParBar write SetShowMessageParBar;
property DrawLineColor: TColor read FDrawLineColor write SetDrawLineColor;
property DrawBackColor: TColor read FDrawBackColor write SetDrawBackColor;
property WaveLoopEvent: TWaveLoopNotifyEvent read FWaveLoop write SetWaveLoop;
property WavePlayKM: byte read FWavePlayKM write SetWavePlayKM default 100;
end;
implementation
//***********************************************************************//
// //
// TCMPlayWave 的实现部分 //
// //
//***********************************************************************//
{ TCMPlayWave }
//***********************************************************************//
// //
// 构造器 //
// //
//***********************************************************************//
constructor TCMPlayWave.Create;
function FindTempFile(const FindFileName: String): String;
var
i: Integer;
TempStr: String;
begin
i := 0;
While TRUE do
begin //查找文件
if Not FileExists(FindFileName + IntToStr(i) + '.tmp') then
begin
TempStr := FindFileName + IntToStr(i) + '.tmp';
break;
end;
INC(i);
end;
Result := TempStr
end;
var
TempDir: array[0..255] of Char; //Windows 操作系统的临时路径
Tem: Integer;
const
CopyDataTempFile = 'CMCopyDataWave';
CopyBackTempFile = 'CMCopyBackWave';
BackTempFile = 'CMBackWave';
UndoTempFile = 'CMUndoBackWave';
begin
if WaveOutGetNumDevs() = 0 then
raise EMMIO.Create('找不到音频设备!');
inherited Create;
GetTempPath(255, @TempDir); //取得操作系统的临时目录
//可用于粘贴的数据
Self.CopyDataFileName := FindTempFile(StrPas(TempDir) + CopyDataTempFile);
//用于编辑操作的临时文件
Self.CopyBackFileName := FindTempFile(StrPas(TempDir) + CopyBackTempFile);
//备份文件,用于编辑、播放等操作
Self.BackFileName := FindTempFile(StrPas(TempDir) + BackTempFile);
//编辑操作前的文件的备份
Self.UndoBackFileName := FindTempFile(StrPas(TempDir) + UndoTempFile);
//创建文件
Tem := FileCreate(Self.CopyDataFileName);
FileClose(Tem);
Tem := FileCreate(Self.CopyBackFileName);
FileClose(Tem);
Tem := FileCreate(Self.BackFileName);
FileClose(Tem);
Tem := FileCreate(Self.UndoBackFileName);
FileClose(Tem);
Self.FFileName := NIL;
//用于控制播放时显示波形的周期
Self.SetMemTime := TTimer.Create(Application);
Self.SetMemTime.Enabled := False;
Self.SetMemTime.Interval := 1;
Self.SetMemTime.Tag := 1;
Self.SetMemTime.OnTimer := Self.SetPlayMem;
Self.FCanUndo := False;
Self.FNowPlay := CPNONE;
Self.FShowDrawWave := True;
Self.PasteDataLength := 0; //可用于粘贴的数据的长度
Self.DataLength := 0;
Self.FDetachLength := 0;
Self.FDrawBackColor := clWhite; //波形背景颜色
Self.FDrawLineColor := clBlue; //波形颜色
Self.FirstData := NIL;
Self.NextData := NIL;
Self.FDesBMP := NIL;
Self.FDrawWave := NIL;
end;
//***********************************************************************//
// //
// 析构器 //
// //
//***********************************************************************//
destructor TCMPlayWave.Destroy;
begin
Self.Stop; //停目播放
Self.CloseWave; //关闭文件
//删除临时文件
if FileExists(Self.CopyDataFileName) then
DeleteFile(Self.CopyDataFileName);
if FileExists(Self.CopyBackFileName) then
DeleteFile(Self.CopyBackFileName);
if FileExists(Self.UndoBackFileName) then
DeleteFile(Self.UndoBackFileName);
if FileExists(Self.BackFileName) then
DeleteFile(Self.BackFileName);
inherited;
end;
//***********************************************************************//
// //
// 释放 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Free;
begin
if Self <> NIL then
Self.Destroy;
end;
//***********************************************************************//
// //
// 取当前音频文件名 //
// 参数: 无 //
// 返回值: //
// 当前音频文件名 //
// //
//***********************************************************************//
function TCMPlayWave.GetFileName: String;
begin
Result := String(Self.FFileName);
end;
//***********************************************************************//
// //
// 设置当前音频文件名 //
// 参数: //
// Value : 文件名 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.SetFileName(const Value: String);
var
WaveFmt: TWAVEFORMATEX;
begin
if NOT FileExists(Value) then
raise EMMIO.Create('找不到文件');
Self.Stop;
Self.CloseWave;
//设置进度
if Assigned(Self.WaveLoopEvent) then
Self.WaveLoopEvent(WA_EN_OPENFILE, 100, 0, 0);
if Self.ShowMessageParBar <> NIL then
begin
Self.ShowMessageParBar.Max := 100;
Self.ShowMessageParBar.Position := 10;
end;
if Assigned(Self.WaveLoopEvent) then
Self.WaveLoopEvent(WA_EN_OPENFILE, 100, 0, 10);
//删除文件
if FileExists(Self.BackFileName) then
DeleteFile(Self.BackFileName);
if Self.ShowMessageParBar <> NIL then
begin
Self.ShowMessageParBar.Position := 20;
end;
if Assigned(Self.WaveLoopEvent) then
Self.WaveLoopEvent(WA_EN_OPENFILE, 100, 0, 20);
if Self.OpenFileName(PChar(Value), False) then
begin
WaveFmt := Self.pFormat^;
WaveFmt.nChannels := 1; //单声道
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -