📄 tplaywaveunit.~pas
字号:
//发送暂停消息
SendMessage(Application.MainForm.Handle, CM_PLAYPAUSE, 0, 0);
WaveOutPause(hwo); //暂停播放
Self.FNowPlay := CPPAUSEING; //设置播放状态
end;
//***********************************************************************//
// //
// 恢复播放 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Restart;
begin
if Self.NowPlay <> CPPAUSEING then //如果不是暂停状态下
Exit;
WaveOutRestart(hwo); //恢复播放
FNowPlay := CPPLAYING; //设置播放状态
//发送恢复播放的消息
SendMessage(Application.MainForm.Handle, CM_PLAYREST, 0, 0);
end;
//***********************************************************************//
// //
// 停止播放 //
// 参数: 无 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Stop;
begin
if Self.FNowPlay = CPNONE then //没有任何状态
Exit;
if Self.FNowPlay = CPPLAYING then
WaveOutReset(Self.hwo); //停止播放
Self.FNowPlay := CPSTOPING; //设置状态
end;
//***********************************************************************//
// //
// 设置画波形用的源位图对像 //
// 参数: //
// Value : 源位图对像 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.SetDesBMP(const Value: TBitMap);
begin
FDesBMP := Value;
end;
//***********************************************************************//
// //
// 设置用于显示波形的目标画布对像 //
// 参数: //
// Value : 目标画布对像 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.SetDrawWave(const Value: TPaintBox);
begin
FDrawWave := Value;
end;
//***********************************************************************//
// //
// 把从指定位置开始,指定长度的音频数据保存到指定文件中 //
// 参数: //
// NewFileName : 要保存的目标文件 //
// StartPoi : 要保存的音频数据的起始位置 //
// SaveLength : 要保存的音频数据的长度 ( 0 为全部保存 ) //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.Save(const NewFileName: String; const StartPoi,
SaveLength: Integer);
var
TRecordHdr: TWAVEFORMATEX; //波形格式
begin
if (Self.NowPlay <> CPSTOPING) OR (hio = 0) OR (NewFileName = '') then
Exit;
//保存到文件
if Self.DataLength = 0 then
begin
//设置音频文件头
TRecordHdr.wFormatTag := WAVE_FORMAT_PCM; //格式类型
TRecordHdr.nChannels := 1; //声道数据
TRecordHdr.nSamplesPerSec := 22050; //采样频率
TRecordHdr.nAvgBytesPerSec := 44100; //平均数据传输率
TRecordHdr.wBitsPerSample := 16; //采样数据的大小
TRecordHdr.nBlockAlign := 2; //块对齐方式
TRecordHdr.cbSize := 0; //加在本结构后的格式数据的大小
Wave_SaveFile(NewFileName, '', 0, TRecordHdr, 0, CS_SAVE_NEW);
end else
Wave_SaveFile(NewFileName, '', DataLength, pFormat^, hio, CS_SAVE_PLAY, StartPoi, SaveLength);
end;
//***********************************************************************//
// //
// 把指定整数转换从在音频中的位置 //
// 参数: //
// Position : 要转换的整数 //
// 返回值: //
// 在音频中的位置 //
// //
//***********************************************************************//
function TCMPlayWave.IntToWaveLength(const Position: Integer): LongInt;
var
Flag: Integer;
begin
//音频显示周期
Flag := Integer(Self.DataLength) DIV 2 DIV Self.DrawWave.ClientWidth + 1;
if Flag <= 0 then Flag := 1;
Result := Position * Flag * 2; //返回长度
end;
//***********************************************************************//
// //
// 打开指定的音频文件 ( 载入内存 ) //
// 参数: //
// Name : 要打开的文件名 //
// Draw : 是否画波形 //
// 返回值: //
// 是否打开成功 //
// //
//***********************************************************************//
function TCMPlayWave.OpenFileName(Name: PChar; Draw: Boolean): Boolean;
var
mmckinfoParent, mmckinfoSubchunk: MMCKINFO;//音频信息头
dwfmtSize: DWORD;
DrawAll: TDrawWave_Type; //波形结构体
begin
Self.MODInt := 0;
Self.PlaySize := 0;
//打开音频文件 只读 以缓冲区方式打开
Self.hio := mmioOpen(Name, NIL, MMIO_READ or MMIO_ALLOCBUF);
if Self.hio = 0 then
raise EMMIO.Create('打不开文件或文件不存在!');
Try
//寻找 RIFF 块的类型标志,以确定是 WAV 文件
mmckinfoParent.fccType := mmioStringToFOURCC('WAVE', 0);
if mmioDescend(Self.hio, @mmckinfoParent, NIL, MMIO_FINDRIFF) <> 0 then
raise EMMIO.Create('不是WAVE文件!');
//寻找 fmt 子块,以确定是 WAV 文件并找出一些音频文件的数据
mmckinfoSubchunk.ckid := mmioStringToFOURCC('fmt', 0);
if mmioDescend(Self.hio, @mmckinfoSubchunk, @mmckinfoParent, MMIO_FINDCHUNK) <> 0 then
raise EMMIO.Create('不是WAVE文件!');
//音频信息头的大小
dwFmtSize := mmckinfoSubchunk.cksize;
//锁定内存
Self.hFormat := LocalAlloc(LMEM_MOVEABLE, LOWORD(dwFmtSize));
if Self.hFormat = 0 then
raise EMMIO.Create('不能分配内存!');
try //开辟内存
Self.pFormat := PWAVEFORMATEX(LocalLock(Self.hFormat));
if Self.pFormat = NIL then
raise EMMIO.Create('不能锁定内存!');
//读取音频信息头( 音频格式 )
if mmioRead(Self.hio, PChar(Self.pFormat), dwFmtSize) <> LongInt(dwFmtSize) then
raise EMMIO.Create('读格式错!');
//确定是否为指定格式类型
if Self.pFormat^.wFormatTag <> WAVE_FORMAT_PCM then
raise EMMIO.Create('波形音频不是PCM格式音频!');
//打开音频输出设备
if WaveOutOpen(@Self.hwo, WAVE_MAPPER, Self.pFormat, 0, 0, WAVE_FORMAT_QUERY) <> 0 then
raise EMMIO.Create('波形音频输出设备不支持该格式!');
//把文件指针移到 data 数据块的开始处
mmioAscend(Self.hio, @mmckinfoSubchunk, 0);
//查找 data 数据块
mmckinfoSubchunk.ckid := mmioStringToFOURCC('data', 0);
if mmioDescend(Self.hio, @mmckinfoSubchunk, @mmckinfoParent, MMIO_FINDCHUNK) <> 0 then
raise EMMIO.Create('找不到数据块!');
//音频数据的长度
Self.DataLength := mmckinfoSubchunk.cksize;
if Self.DataLength = 0 then
begin //音频数据的长度为0
LocalUnlock(Self.hFormat); //解锁内存块
LocalFree(Self.hFormat); //释放内存块
mmioClose(Self.hio, 0); //关闭文件
end;
Finally
end;
Finally
end;
if Self.DataLength = 0 then
begin
with Self.FDesBMP do
begin
Canvas.Brush.Color := Self.DrawBackColor;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := Self.DrawLineColor;
Canvas.Pen.Mode := pmCopy;
Canvas.FillRect(Rect(0, 0, Self.FDrawWave.ClientWidth, Self.FDrawWave.ClientHeight));
end;
BitBlt(Self.FDrawWave.Canvas.Handle, 0, 0, Self.FDrawWave.ClientWidth,
Self.FDrawWave.ClientHeight, Self.FDesBMP.Canvas.Handle, 0, 0, SRCCOPY);
Application.MessageBox('文件长度为零!', '提示', MB_OK + MB_ICONINFORMATION);
SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
end;
if (Self.FDrawWave <> NIL) AND (Self.FDesBMP <> NIL) AND Draw AND Self.FShowDrawWave
and (Self.DataLength <> 0) 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.DesCanvas := Self.FDrawWave.Canvas;
DrawAll.DH := Self.FDrawWave.ClientHeight;
DrawAll.DW := Self.FDrawWave.ClientWidth;
DrawAll.DesBitMap := Self.FDesBMP;
DrawAllWave(DrawAll, Self.WaveMin, Self.WaveMax, Self.FDrawLineColor, Self.FDrawBackColor);
end;
Self.FCanUndo := False; //不能进行撤消操作
Result := True; //打开成功
end;
//***********************************************************************//
// //
// 向指定的音频文件写入指定长度的音频数据 //
// 参数: //
// Dhio : 音频文件的句柄 //
// Length : 音频数据的长度 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure TCMPlayWave.WriteWaveData(Dhio: HMMIO; Length: LongInt);
var
LoopData, i: Integer;
LoopMod: LongInt;
Buf: PChar;
begin
if Length <= 0 then
Exit;
LoopMod := LoadMemSize;
LoopData := Length DIV LoadMemSize;
if (Length MOD LoadMemSize) <> 0 then
begin
LoopMod := Length MOD LoadMemSize;
LoopData := LoopData + 1;
end;
//分配内存块
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('数据错');
//写入到指定的音频文件中
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
if mmioRead(Self.hio, Buf, LoopMod) <> LoopMod then
raise EMMIO.Create('数据错');
if mmioWrite(Dhio, Buf, LoopMod) <> LoopMod then
raise EMMIO.Create('数据错');
SendMessage(Application.MainForm.Handle, CM_EDITPOI, 0, 1);
Finally
GloBalFreePtr(Buf);
end;
end;
end;
//***********************************************************************//
// //
// 从指定位置复制指定长度的音频数据到剪贴板 //
// 参数: //
// StartPoi : 复制音频数据的起始位置 //
// Length : 音频数据的长度 //
// 返回值: 无 //
// //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -