📄 tplaywaveunit.~pas
字号:
ck.ckid := mmioStringToFOURCC('fmt', 0);; //创建 fmt 块
if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then
ck.cksize := SizeOf(Self.pFormat^) - 2 //fmt 块的大小
else
ck.cksize := SizeOf(Self.pFormat^) + Self.pFormat^.cbSize;
if 0 <> mmioCreateChunk(Dhio, @ck, 0) then //创建
raise EMMIO.Create('粘贴数据错');
mmioWrite(Dhio, PChar(Self.pFormat), ck.cksize);
ck.ckid := mmioStringToFOURCC('data', 0); //创建 data 数据块
ck.cksize := LongInt(Self.DataLength) + EditLength;
if 0 <> mmioCreateChunk(Dhio, @ck, 0) then
raise EMMIO.Create('粘贴数据错');
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 1, 0);
//移到音频数据开始处
mmioSeek(Self.hio, Self.DataLength, SEEK_END);
Try
Self.WriteWaveData(Dhio, StartPoi); //写入数据
Except
mmioClose(Dhio, 0);
raise EMMIO.Create('粘贴数据错');
Exit;
end;
//打开剪切板数据文件
TempFile := FileOpen(Self.CopyDataFileName, fmOpenRead);
if TempFile = 0 then
raise EMMIO.Create('粘贴数据错');
//把剪切板文件中的数据写入音频文件中
LoopMod := LoadMemSize;
LoopData := EditLength DIV LoadMemSize;
if (EditLength MOD LoadMemSize) <> 0 then
begin
LoopMod := EditLength MOD LoadMemSize;
LoopData := LoopData + 1;
end;
Try
Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
if Buf = NIL then
EMMIO.Create('不能分配内存');
Try
for i := 1 to LoopData - 1 do
begin
FileRead(TempFile, Buf^, LoadMemSize); //读指定大小的数据
if mmioWrite(Dhio, Buf, LoadMemSize) <> LoadMemSize then
raise EMMIO.Create('粘贴数据错');
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
end;
Finally
GloBalFreePtr(Buf);
end;
if LoopMod > 0 then
begin
Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoopMod));
if Buf = NIL then
EMMIO.Create('不能分配内存');
Try
FileRead(TempFile, Buf^, LoopMod);
//写入到音频文件中
if mmioWrite(Dhio, Buf, LoopMod) <> LoopMod then
raise EMMIO.Create('粘贴数据错');
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
Finally
GloBalFreePtr(Buf);
end;
end;
Finally
FileClose(TempFile); //关闭文件
end;
Try //把余下的数据写入到音频文件中
Self.WriteWaveData(Dhio, LongInt(Self.DataLength) - StartPoi);
Except
mmioClose(Dhio, 0);
raise EMMIO.Create('粘贴数据错');
Exit;
end;
Finally
mmioClose(Dhio, 0);
end;
Self.Stop;
Self.CloseWaveFile; //关闭音频文件
if Length > 0 then
begin
if FileExists(Self.UndoBackFileName) then
DeleteFile(Self.UndoBackFileName); //删除用于撤消的备份文件
//把当前的音频文件复制成用于撤消的备份文件
CopyFile(PChar(Self.BackFileName), PChar(Self.UndoBackFileName), TRUE);
end;
//删除备份文件
DeleteFile(Self.BackFileName);
//把处理后的文件复制成备份文件
CopyFile(PChar(Self.CopyBackFileName), PChar(Self.BackFileName), TRUE);
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
//打开备份文件
if Self.OpenFileName(PChar(Self.BackFileName), DrawData) then
Self.FNowPlay := CPSTOPING;
Self.FCanUndo := TRUE; //可以撤消
SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
end;
//***********************************************************************//
// //
// 撤消编辑操作 //
// 参数: //
// DrawData : 是否画波形 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Undo(DrawData: Boolean);
begin
if (NOT Self.FCanUndo) OR (Self.NowPlay <> CPSTOPING) then
Exit;
SendMessage(Application.MainForm.Handle, CM_BEGINUNDO, 0, 0);
SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, 3, 0);
Self.Stop;
Self.CloseWaveFile; //关闭音频文件
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
if FileExists(Self.BackFileName) then
DeleteFile(Self.BackFileName); //删除备份文件
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
//把用于撤消操作的文件复制成备份文件
CopyFile(PChar(Self.UndoBackFileName), PChar(Self.BackFileName), TRUE);
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
//打开备份文件
if Self.OpenFileName(PChar(Self.BackFileName), DrawData) then
Self.FNowPlay := CPSTOPING;
if FileExists(Self.UndoBackFileName) then
DeleteFile(Self.UndoBackFileName); //删除撤消文件
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
Self.FCanUndo := False;
SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
end;
//***********************************************************************//
// //
// 关闭打开的音频文件 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.CloseWaveFile;
begin
if NowPlay <> CPSTOPING then //不是停止状态
Exit;
LocalUnlock(hFormat); //解锁内存
LocalFree(hFormat); //释放音频信息头
mmioClose(hio, 0); //半闭音频输出设备
Self.hio := 0;
Self.DataLength := 0;
FNowPlay := CPNONE; //当前没有状态
end;
//***********************************************************************//
// //
// 关闭音频 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.CloseWave;
begin
if Self.FFileName = NIL then
Exit;
Self.Stop; //停止播放
Self.CloseWaveFile; //关闭打开的音频文件
Self.DataLength := 0;
Self.FFileName := NIL;
Self.FCanUndo := False;
end;
//***********************************************************************//
// //
// 返回当前能否进行粘贴操作 //
// 参数: 无 //
// 返回值: //
// 当前能否进行撤消操作 //
// //
//***********************************************************************//
function TCMPlayWave.GetCanPaste: Boolean;
begin
//剪切板中的数据的长度大于 0 并且剪切板文件存在
Result := ((Self.PasteDataLength > 0) AND (FileExists(Self.CopyDataFileName)));
end;
//***********************************************************************//
// //
// 新建一个空的音频文件 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.New;
var
TRecordHdr: TWAVEFORMATEX; //波形格式
begin
if Self.NowPlay <> CPNONE then
Exit;
//设置音频文件头
TRecordHdr.wFormatTag := WAVE_FORMAT_PCM; //格式类型
TRecordHdr.nChannels := 1; //声道数据
TRecordHdr.nSamplesPerSec := 8000; //采样频率
TRecordHdr.nAvgBytesPerSec := 16000; //平均数据传输率
TRecordHdr.wBitsPerSample := 16; //采样数据的大小
TRecordHdr.nBlockAlign := 2; //块对齐方式
TRecordHdr.cbSize := 0; //加在本结构后的格式数据的大小
Wave_SaveFile(Self.BackFileName, '', 0, TRecordHdr, 0, CS_SAVE_NEW);
end;
//***********************************************************************//
// //
// 把一个整数转换成时间格式 //
// 参数: //
// Length : 指定的整数 //
// Time : 用于返回的时间格式 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.IntToWaveTime(const Length: LongInt; var Time: TCM_Wave_Time);
var
i: LongInt;
begin
Time.Hour := 0; //小时
Time.Minute := 0; //分
Time.Second := 0; //秒
Time.Heroism := 0; //毫秒
Try
if Self.pFormat = NIL then
Exit;
Time.Heroism := Length MOD LongInt(Self.pFormat^.nAvgBytesPerSec);
i := Length DIV LongInt(Self.pFormat^.nAvgBytesPerSec);
Time.Second := i MOD 60;
Time.Minute := i DIV 60;
Time.Hour := Time.Minute DIV 60;
Time.Minute := Time.Minute MOD 60;
Time.Heroism := (Time.Heroism * 100) DIV Self.pFormat^.nAvgBytesPerSec;
Except
Time.Hour := 0;
Time.Minute := 0;
Time.Second := 0;
Time.Heroism := 0;
Application.MessageBox('时间格式转换错误!', '系统错误', MB_OK + MB_ICONERROR);
end;
end;
//***********************************************************************//
// //
// 取音频数据的最大振幅 //
// 参数: 无 //
// 返回值: //
// 音频数据的最大振幅 //
// //
//***********************************************************************//
function TCMPlayWave.GetMaxVal: Longint;
begin
Result := ABS(Self.WaveMax - Self.WaveMin);
end;
//***********************************************************************//
// //
// 显示波形 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.DrawShowWave;
var
DrawAll: TDrawWave_Type;
begin
if (Self.FDrawWave <> NIL) AND (Self.FDesBMP <> NIL) then
begin
DrawAll.FileType := CS_SAVE_PLAY;
DrawAll.hio := Self.hio;
DrawAll.Flag := Integer(Self.DataLength) DIV 2 DIV Self.FDrawWave.ClientWidth + 1;
if DrawAll.Flag <= 0 then DrawAll.Flag := 1;
DrawAll.FileName := '';
DrawAll.Length := Self.DataLength;
DrawAll.Des
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -