📄 tcmwavetype.pas
字号:
if (MODDrawSize <> 0) AND (Loop = DrawLoop) then
LoadSize := MODDrawSize //要播放的音频数据的长度
else
LoadSize := LoadMemSize;
//开辟内存
Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
if Buf = NIL then
raise EMMIO.Create('不能分配内存!');
Try
case Dw_Type.FileType of //读音频数
CS_SAVE_PLAY: mmioRead(Dw_Type.hio, Buf, LoadSize);
CS_SAVE_RECORD: FileRead(hFile, Buf^, LoadSize);
end;
if Dw_Type.Length <= LoadMemSize then //假如小于区域长度的最大长度
begin //画区域波形
DrawPartWave(Dw_Type.Flag, Buf, Dw_Type.Length, Dw_Type.DesCanvas,
Dw_Type.DH, Dw_Type.DW, Dw_Type.DesBitMap, DrawLineColor,
DrawBackColor, Draw);
WaveMin := DrawMin;
WaveMax := DrawMax;
SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop * 3, 0);
SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
FileClose(hFile);
Exit;
end;
for i := 0 to (LoadSize div 2 - 1) do
begin //取最大最小值
j := PCMInt(PChar(Buf)+ i * 2)^;
if j > Max then Max := j;
if j < Min then Min := j;
end;
Finally
GloBalFreePtr(Buf);
end;
SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop, 0);
end;
Finally
FileClose(hFile);
end;
WaveMin := Min;
WaveMax := Max;
if Not Draw then
begin
if Dw_Type.FileType = CS_SAVE_RECORD then FileClose(hFile);
SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
Exit;
end;
Max := Max - Min;
Dw_Type.DesBitMap.Canvas.MoveTo(0, Dw_Type.DH div 2);
j := 0;
X := 0;
lmax := 0;
lmin := 32767;
hFile := 0;
case Dw_Type.FileType of //移到文件开始处
CS_SAVE_PLAY: mmioSeek(Dw_Type.hio, Dw_Type.Length, SEEK_END);
CS_SAVE_RECORD: hFile := FileOpen(Dw_Type.FileName, fmOpenRead);
else
hFile := 0;
end;
Try
for Loop := 1 to DrawLoop do
begin
if (MODDrawSize <> 0) AND (Loop = DrawLoop) then
begin
//开辟内存
Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, MODDrawSize));
LoadSize := MODDrawSize; //要播放的音频数据的长度
end
else begin
Buf := PChar(GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, LoadMemSize));
LoadSize := LoadMemSize;
end;
if Buf = NIL then
raise EMMIO.Create('不能分配内存!');
Try
case Dw_Type.FileType of
CS_SAVE_PLAY: mmioRead(Dw_Type.hio, Buf, LoadSize);
CS_SAVE_RECORD: FileRead(hFile, Buf^, LoadSize);
end;
for i := 0 to (LoadSize div 2 - 1 ) do
begin
if j < (Dw_Type.Flag - 1) then //在同一周期内
begin
INC(j);
end
else begin
j := 0;
X := X + 1;
lmax := 0;
lmin := 32767;
end;
if Max <> 0 then
Y := Abs(PCMInt(PChar(Buf) + i * 2)^ - Min) * Dw_Type.DH div Max
else
Y := Dw_Type.DH div 2;
k := 0;
if Y > lmax then
begin
lmax := Y;
k := 1;
end;
if Y < lmin then
begin
lmin := Y;
k := 1;
end;
if k = 1 then
Dw_Type.DesBitMap.Canvas.LineTo(X, Y);
if X > Dw_Type.DW then break;
end;
Finally
GloBalFreePtr(Buf);
end;
SendMessage(Application.MainForm.Handle, CM_DRAWPOSI, DrawLoop + Loop * 2 , 0);
end;
Finally
FileClose(hFile);
end;
//复制图像
BitBlt(Dw_Type.DesCanvas.Handle, 0, 0, Dw_Type.DW, Dw_Type.DH,
Dw_Type.DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
SendMessage(Application.MainForm.Handle, CM_ENDDRAW, 0, 0);
end;
//***********************************************************************//
// //
// 画放音时的动态波形 //
// 参数: //
// Buf : 音频数据指针 //
// Length : 音频数据的长度 //
// DesCanvas : 用来显示波形的目标画布 //
// DH, DW : 目标画布工作区的高度与宽度 //
// Min, Max : 音频数据的最小值与最大值 //
// DrawLineColor : 画波形的颜色 //
// DrawBackColor : 画波形的背景颜色 //
// StartPoi : 开始画波形的位置 //
// DrawLength : 要画的波形的数据的长度 //
// 返回值: 无 //
// //
//***********************************************************************//
procedure HawDrawWave(Buf: PChar; Length: LongInt; DesCanvas: TCanvas;
DH, DW: SmallInt; Min, Max: LongInt; DrawLineColor, DrawBackColor: TColor;
StartPoi: LongInt = 0; DrawLength: LongInt = 0);
Var
i: LongInt;
Y: SmallInt;
DesBitMap: TBitMap;
begin
DesBitMap := TBitMap.Create;
with DesBitMap do //初始化图像对像
begin
Width := DW;
Height := DH;
Canvas.Brush.Color := DrawBackColor;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := DrawLineColor;
Canvas.Pen.Mode := pmCopy;
Canvas.FillRect(Rect(0, 0, DW, DH));
Canvas.MoveTo(0, DH DIV 2);
Canvas.LineTo(DW, DH DIV 2);
end;
if ((Length = 0) or (Buf = NIL)) then
begin
BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
Exit;
end;
if (StartPoi MOD 2) = 1 then
StartPoi := StartPoi + 1;
if StartPoi >= Length then
StartPoi := 2;
if DrawLength div 2 > DW then //开始处
DrawLength := DW * 2;
if (StartPoi + DrawLength) > Length then
DrawLength := Length - StartPoi;
if DrawLength <= 0 then
DrawLength := DW * 2;
Max := Max - Min;
for i := 0 to (DrawLength div 2 -1) do
begin
if Max <> 0 then
Y := Abs(PCMInt(PChar(Buf) + StartPoi + i * 2)^ - Min) * DH div Max
else
Y := 0;
Y := ABS(DH DIV 2 - Y);
if Y >= (DH DIV 2) then
continue;
//画波形
DesBitMap.Canvas.MoveTo(i, DH DIV 2 - Y);
DesBitMap.Canvas.LineTo(i, DH DIV 2 + Y);
if i > DW then break;
end;
//复制图像
BitBlt(DesCanvas.Handle, 0, 0, DW, DH, DesBitMap.Canvas.Handle, 0, 0, SRCCOPY);
DesBitMap.Free;
end;
//***********************************************************************//
// //
// 把指定格式的音频数据转换成另一种指定格式的音频数据 //
// 参数: //
// OldBuf : 要转换的音频数据 //
// OldLen : 转换前的音频数据的长度 //
// Newfmt : 新的波形格式 //
// Oldfmt : 旧的波形格式 //
// NewBuf : 转换后的音频数据 //
// 返回值: //
// 新的音频长度 //
// //
//***********************************************************************//
function ConvertWave(OldBuf: PChar; OldLen: Integer; const Oldfmt: TWAVEFORMATEX;
var NewBuf: PChar; const Newfmt: TWAVEFORMATEX): LongInt;
var
i, j, k: Integer;
Scale: Single;
SamplePos: Single;
LeftPos, RightPos: Integer;
SrcSmall, SrcSmall2: SmallInt;
SrcByte, SrcByte2: Byte;
begin
Scale := Newfmt.nSamplesPerSec / Oldfmt.nSamplesPerSec; //采样比例
i := OldLen div Oldfmt.nBlockAlign; //音频格式块对齐方式
j := Trunc(Newfmt.nSamplesPerSec / Oldfmt.nSamplesPerSec * i);//转换比例
Result := Newfmt.nBlockAlign * j; //新的长度
// GlobalAllocPtr(GMEM_MOVEABLE or GMEM_SHARE, Result);
ReallocMem(NewBuf, Result); //分配内存
SrcByte := 9;
SrcSmall := 0;
SrcByte2 := 0;
SrcSmall2 := 0;
for k := 0 to j - 1 do //数据转换
begin
SamplePos := k / Scale; //新的数据地址
LeftPos := Trunc(SamplePos);
RightPos := LeftPos + 1; //下一个数据
if RightPos > i - 1 then
RightPos := LeftPos;
if Oldfmt.wBitsPerSample = 16 then
begin //采样大小为 16 位
Srcsmall := Round(PCMInt(OldBuf + LeftPos * Oldfmt.nBlockAlign)^ * (1 -
SamplePos + LeftPos) + PCMInt(OldBuf + RightPos * Oldfmt.nBlockAlign)^ *
(SamplePos - LeftPos)); //取高位数据值 (左声道)
if Oldfmt.nChannels > 1 then //双声道
SrcSmall2 := Round(PCMInt(OldBuf + LeftPos * Oldfmt.nBlockAlign + 2)^ *
(1 - SamplePos + LeftPos) + PCMInt(OldBuf + RightPos * Oldfmt.nBlockAlign
+ 2)^ * (SamplePos - LeftPos)) //取低位数据值 (右声道)
else //单声道
SrcSmall2 := SrcSmall;
end
else //8 位
begin //取高位数据值 (左声道)
SrcByte := Round(Byte((OldBuf + LeftPos * Oldfmt.nBlockAlign)^) * (1 - SamplePos + LeftPos)
+ Byte((OldBuf + RightPos * Oldfmt.nBlockAlign)^) * (SamplePos - LeftPos));
if Oldfmt.nChannels > 1 then //双声道
SrcByte2 := Round(Byte((OldBuf + LeftPos * Oldfmt.nBlockAlign + 1)^) * (1 - SamplePos + LeftPos)
+ Byte((OldBuf + RightPos * Oldfmt.nBlockAlign+1)^) * (SamplePos - LeftPos))
else //单声道
SrcByte2 := SrcByte;
end;
//
// 开始数转换
//
if Newfmt.wBitsPerSample = 16 then //新的采样大小为 16 位
if Oldfmt.wBitsPerSample = 8 then //旧的采样大小为 8 位
if Newfmt.nChannels = 1 then //单声道
PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := Bits8To16((SrcByte + SrcByte2) div 2)
else //双声道
PCMlong(NewBuf + k * Newfmt.nBlockAlign)^ := Bits8To16(SrcByte) + (Bits8To16(SrcByte2) shl 16)
else //旧的采样大小为 16 位
if Newfmt.nChannels = 1 then //单声道
PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := (SrcSmall + SrcSmall2) div 2
else //双声道
PCMlong(NewBuf + k * Newfmt.nBlockAlign)^ := SrcSmall+(SrcSmall2 shl 16)
else //新的采样大小为 8 位
if Oldfmt.wBitsPerSample = 8 then //旧的采样大小为 8 位
if Newfmt.nChannels = 1 then //单声道
(NewBuf + k * Newfmt.nBlockAlign)^ := CHR((SrcByte + SrcByte2) div 2)
else //双声道
PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := SrcByte + (SrcByte2 shl 8)
else //旧的采样大小为 16 位
if Newfmt.nChannels = 1 then //单声道
(NewBuf + k * Newfmt.nBlockAlign)^ := CHR(Bits16To8((SrcSmall + SrcSmall2) div 2))
else //双声道
PCMInt(NewBuf + k * Newfmt.nBlockAlign)^ := Bits16To8(SrcSmall) + (Bits16To8(SrcSmall2) shl 8);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -