📄 tplaywaveunit.~pas
字号:
//***********************************************************************//
procedure TCMPlayWave.Copy(const StartPoi, Length: Integer);
var
EditLength: LongInt;
TempFile: Integer;
Buf: PChar;
LoopData, i: Integer;
LoopMod: LongInt;
begin
if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
OR (StartPoi < 0) then
Exit;
EditLength := Length;
if (StartPoi + Length) > LongInt(Self.DataLength) then
EditLength := LongInt(Self.DataLength) - StartPoi;
if EditLength <= 0 then
Exit;
//发送开始复制的消息
SendMessage(Application.MainForm.Handle, CM_BEGINCOPY, 0, 0);
if FileExists(Self.CopyDataFileName) then
DeleteFile(Self.CopyDataFileName); //如果备份数据文件已存在
LoopMod := LoadMemSize;
LoopData := EditLength DIV LoadMemSize;
if (EditLength MOD LoadMemSize) <> 0 then
begin
LoopMod := EditLength MOD LoadMemSize;
LoopData := LoopData + 1;
end;
//发送数据处理长度消息
SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, LoopData, 0);
MMioSeek(Self.hio, LongInt(Self.DataLength) - StartPoi, SEEK_END); //把文件指针移到音频数据的指定开始处
//创建临时文件
TempFile := FileCreate(Self.CopyDataFileName);
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
//读取指定长度的数据
if mmioRead(Self.hio, Buf, LoadMemSize) <> LoadMemSize then
raise EMMIO.Create('数据读取错误');
FileWrite(TempFile, Buf^, LoadMemSize); //写入临时文件中
//发送数据处理长度消息
SendMessage(Application.MainForm.Handle, CM_EDITPOI, i, 0);
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
if mmioRead(Self.hio, Buf, LoopMod) <> LoopMod then
raise EMMIO.Create('数据读取错误');
FileWrite(TempFile, Buf^, LoopMod);
SendMessage(Application.MainForm.Handle, CM_EDITPOI, LoopMod, 0);
Finally
GloBalFreePtr(Buf);
end;
end;
Finally
FileClose(TempFile); //关闭文件
end;
Self.PasteDataLength := EditLength; //可用于粘贴的数据的长度
//发送处理完毕的消息
SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
end;
//***********************************************************************//
// //
// 从指定位置删除指定长度的音频数据到剪贴板 //
// 参数: //
// StartPoi : 删除音频数据的起始位置 //
// Length : 音频数据的长度 //
// DrawData : 是否画波形 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Delete(const StartPoi, Length: Integer; DrawData: Boolean);
var
EditLength: LongInt;
Dhio: HMMIO;
ck: TMMCKINFO;
i: Integer;
begin
if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
OR (StartPoi < 0) then
Exit;
EditLength := Length;
if (StartPoi + Length) > LongInt(Self.DataLength) then
EditLength := LongInt(Self.DataLength) - StartPoi;
if EditLength <= 0 then
Exit;
//发送开始处理数据的消息
SendMessage(Application.MainForm.Handle, CM_BEGINDEL, 0, 0);
//确定数据要读取的次数
i := EditLength DIV LoadMemSize;
if (EditLength MOD LoadMemSize) <> 0 then
INC(i);
i := i + (LongInt(Self.DataLength) - (StartPoi + EditLength)) DIV LoadMemSize;
if ((LongInt(Self.DataLength) - (StartPoi + EditLength)) MOD LoadMemSize) <> 0 then
INC(i);
//发送要编辑数据的长度消息
SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, i + 2, 0);
if FileExists(Self.CopyBackFileName) then
DeleteFile(Self.CopyBackFileName); //删除用于备份的文件
//创建成一个新的音频文件 创建 可读可写
Dhio := mmioOpen(PChar(Self.CopyBackFileName), NIL, MMIO_CREATE + MMIO_READWRITE);
if Dhio = 0 then
raise EMMIO.Create('删除数据错');
Try
//波形格式的大小
if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then
ck.cksize := LongInt(Self.DataLength) - Length + 4 + 8 +
SizeOf(Self.pFormat^) - 2 + 8
else
ck.cksize := LongInt(Self.DataLength) - Length + 4 + 8 +
SizeOf(Self.pFormat^) + Self.pFormat^.cbSize + 8;
ck.fccType := mmioStringToFOURCC('WAVE', 0); //创建文件头
if 0 <> mmioCreateChunk(Dhio, @ck, MMIO_CREATERIFF) then
raise EMMIO.Create('删除数据错');
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);
ck.cksize := LongInt(Self.DataLength) - Length;
if 0 <> mmioCreateChunk(Dhio, @ck, 0) then //创建 data 数据块
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;
//把文件指针从当前位置移到要删除数据的结尾处
mmioSeek(Self.hio, Length, SEEK_CUR);
Try //写入数据
Self.WriteWaveData(Dhio, LongInt(Self.DataLength) - (StartPoi + EditLength));
Except
mmioClose(Dhio, 0);
raise EMMIO.Create('删除数据错');
Exit;
end;
Finally
mmioClose(Dhio, 0);
end;
mmioClose(Dhio, 0); //关闭临时音频文件
Self.Stop;
Self.CloseWaveFile; //关闭音频文件
if FileExists(Self.UndoBackFileName) then
DeleteFile(Self.UndoBackFileName); //删除当前用于撤消操作的备份文件
CopyFile(PChar(Self.BackFileName), PChar(Self.UndoBackFileName), TRUE);
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;
//***********************************************************************//
// //
// 从指定位置剪切指定长度的音频数据到剪贴板 //
// 参数: //
// StartPoi : 剪切音频数据的起始位置 //
// Length : 音频数据的长度 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Cut(const StartPoi, Length: Integer);
var
EditLength: LongInt;
begin
if (StartPoi >= LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING)
OR (StartPoi < 0) then
Exit;
EditLength := Length;
if (StartPoi + Length) > LongInt(Self.DataLength) then
EditLength := LongInt(Self.DataLength) - StartPoi;
if EditLength <= 0 then
Exit;
//发送开始剪切的消息
SendMessage(Application.MainForm.Handle, CM_BEGINCUT, 0, 0);
Try
Self.Copy(StartPoi, EditLength); //复制数据
Self.Delete(StartPoi, EditLength); //删除数据
Finally
//处理完毕
SendMessage(Application.MainForm.Handle, CM_EDIEND, 0, 0);
end;
end;
//***********************************************************************//
// //
// 把从指定位置开始的指定长度的数据用剪切板中的数据覆盖掉 //
// 参数: //
// StartPoi : 要覆盖的音频数据的起始位置 //
// Length : 要覆盖的音频数据的长度 //
// DrawData : 是否画波形 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Paste(const StartPoi, Length: LongInt; DrawData: Boolean);
var
EditLength: LongInt;
Dhio: HMMIO;
ck: TMMCKINFO;
TempFile: Integer;
Buf: PChar;
LoopData, i: Integer;
LoopMod: LongInt;
begin
if (StartPoi > LongInt(Self.DataLength)) OR (Self.FNowPlay <> CPSTOPING) OR
(NOT Self.CanPaste) OR (StartPoi < 0) OR (Length < 0) then
Exit;
EditLength := Self.PasteDataLength; //可用于粘贴的数据的长度
if EditLength <= 0 then
Exit;
//发送开始粘贴数据的消息
SendMessage(Application.MainForm.Handle, CM_BEGINPASTE, 0, 0);
//删除数据
Self.Delete(StartPoi, Length, False);
i := EditLength DIV LoadMemSize;
if (EditLength MOD LoadMemSize) <> 0 then
INC(i);
i := i + (LongInt(Self.DataLength) - (StartPoi + EditLength)) DIV LoadMemSize;
if ((LongInt(Self.DataLength) - (StartPoi + EditLength)) MOD LoadMemSize) <> 0 then
INC(i);
//处理进度
SendMessage(Application.MainForm.Handle, CM_EDITLENGTH, i + 2, 0);
//删除临时音频文件
if FileExists(Self.CopyBackFileName) then
DeleteFile(Self.CopyBackFileName);
//新建临时音频文件
Dhio := mmioOpen(PChar(Self.CopyBackFileName), NIL, MMIO_CREATE + MMIO_READWRITE);
if Dhio = 0 then
raise EMMIO.Create('粘贴数据错');
Try //创建音频文件的信息头
if Self.pFormat^.wFormatTag = WAVE_FORMAT_PCM then //波形格式的大小
ck.cksize := LongInt(Self.DataLength) + EditLength + 4 + 8 +
SizeOf(Self.pFormat^) - 2 + 8
else
ck.cksize := LongInt(Self.DataLength) + EditLength + 4 + 8 +
SizeOf(Self.pFormat^) + Self.pFormat^.cbSize + 8;
ck.fccType := mmioStringToFOURCC('WAVE', 0); //创建文件头
if 0 <> mmioCreateChunk(Dhio, @ck, MMIO_CREATERIFF) then
raise EMMIO.Create('粘贴数据错');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -