📄 unit1.pas
字号:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,MMSystem, ComCtrls, ToolWin;
type
TRiffChuck = record
RiffID:array[0..3] of char; // 'RIFF' 标志
WaveFileSize: longint; // 文件长度
WaveID:array[0..3] of char; // 'WAVE' 标志
end;
TFmtChuck = record
fmtId:array[0..3] of char; // 'fmt '标志 以空格结束(fID[3]:=Chr($20);)
FormatSize: longint; // PCMWAWFORMAT内容长度
wFormatTag: word; // 编码格式(类别为PCM形式的声音数据)
nChannels: word; // 通道数 单声道=1, 双声道=2 }
nSamplesPerSec: longint; // 采样频率 (每秒样本数),表示每个通道的播放速度
nAvgBytesPerSec: longint; // 波形音频数据传送速度(值:通道数X每秒数据位数X每
// 样本的数据位数/8。播放软件利用根据此值估计缓
// 冲区的大小)
nBlockAlign: word; // 数据块的调整数(按字节计算),值为通道数*没样本的数据位值/8。
// 播放软件需要一次处理多个该值大小的字节数据,以便
// 将其值用于缓冲区的调整。
nBitsPerSample: word; // 每样本数据位数,表示每个声道中各个样本的数据位
// 数。如果有多个声道,对每个声道而言,样本大
// 小都一样 8 or 16
end;
TDataChuck = record
dataId: array[0..3]of char; // 'data' 标志
dataSize: longint; // 语音数据长度
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
WaveFile,SoureFile1,SoureFile2:TFileStream;
TestWord:Longint;
ReadPoint,i:integer;
Riff1,Riff2,Riff3:TRiffChuck;
Fmt1,Fmt2,Fmt3:TFmtChuck;
Fmt1others,Fmt2others,Fmt3others:array[0..99] of byte;
Data1,Data2,Data3:TDataChuck;
t1,t2:tdatetime;
FmtisSame:boolean;
begin
t1:=now;
if not fileexists(edit1.Text) then
begin
showmessage('文件一'+edit1.Text+'不存在!');
exit;
end;
if not fileexists(edit2.Text) then
begin
showmessage('文件二'+edit2.Text+'不存在!');
exit;
end;
SoureFile1:=TFileStream.Create(edit1.Text,fmOpenRead or fmShareDenyNone);
//打开声音文件1
SoureFile1.Position:=0;
SoureFile1.read(Riff1,SizeOf(Riff1));
memo1.lines.add('声音文件1');
memo1.lines.add('RIFF 标志: '+Riff1.RiffID);
memo1.lines.add('文件长度: '+inttostr(Riff1.WaveFileSize));
memo1.lines.add('WAVE标志: '+Riff1.WaveID);
SoureFile1.read(Fmt1,SizeOf(Fmt1));
if Fmt1.FormatSize>16 then
begin
for i:=0 to Fmt1.FormatSize-16-1 do SoureFile1.read(Fmt1others[i],sizeof(Fmt1others[i]));
end;
memo1.lines.add('fmt 标志: '+Fmt1.fmtId);
memo1.lines.add('PCMWAWFORMAT内容长度: '+inttostr(Fmt1.FormatSize));
memo1.lines.add('编码格式: '+inttostr(Fmt1.wFormatTag));
memo1.lines.add('通道数: '+inttostr(Fmt1.nChannels));
memo1.lines.add('采样频率: '+inttostr(Fmt1.nSamplesPerSec));
memo1.lines.add('波形音频数据传送速度: '+inttostr(Fmt1.nAvgBytesPerSec));
memo1.lines.add('数据块的调整数: '+inttostr(Fmt1.nBlockAlign));
memo1.lines.add('每样本数据位数: '+inttostr(Fmt1.nBitsPerSample));
readpoint:= SoureFile1.Position;
SoureFile1.Read(testword,sizeof(testword));
while testword<> $61746164 do //找声音数据部分'data'标记
begin
SoureFile1.Position:=readpoint+1;
readpoint:=readpoint+1;
if SoureFile1.Position >= SoureFile1.Size then Break;
SoureFile1.Read(testword,sizeof(testword));
end;
SoureFile1.Position:=SoureFile1.Position-4;
SoureFile1.read(Data1,SizeOf(Data1));
memo1.lines.add('data标志: '+Data1.dataId);
memo1.lines.add('语音数据长度: '+inttostr(Data1.dataSize));
SoureFile2:=TFileStream.Create(edit2.Text,fmOpenRead or fmShareDenyNone);
//打开声音文件2
SoureFile2.Position:=0;
SoureFile2.read(Riff2,SizeOf(Riff2));
memo1.lines.add('');
memo1.lines.add('声音文件2');
memo1.lines.add('RIFF 标志: '+Riff2.RiffID);
memo1.lines.add('文件长度: '+inttostr(Riff2.WaveFileSize));
memo1.lines.add('WAVE标志: '+Riff2.WaveID);
SoureFile2.read(Fmt2,SizeOf(Fmt2));
if Fmt2.FormatSize>16 then
begin
for i:=0 to Fmt2.FormatSize-16-1 do SoureFile2.read(Fmt2others[i],sizeof(Fmt2others[i]));
end;
memo1.lines.add('fmt 标志: '+Fmt2.fmtId);
memo1.lines.add('PCMWAWFORMAT内容长度: '+inttostr(Fmt2.FormatSize));
memo1.lines.add('编码格式: '+inttostr(Fmt2.wFormatTag));
memo1.lines.add('通道数: '+inttostr(Fmt2.nChannels));
memo1.lines.add('采样频率: '+inttostr(Fmt2.nSamplesPerSec));
memo1.lines.add('波形音频数据传送速度: '+inttostr(Fmt2.nAvgBytesPerSec));
memo1.lines.add('数据块的调整数: '+inttostr(Fmt2.nBlockAlign));
memo1.lines.add('每样本数据位数: '+inttostr(Fmt2.nBitsPerSample));
readpoint:= SoureFile2.Position;
SoureFile2.Read(testword,sizeof(testword));
while testword<> $61746164 do //找声音数据部分'data'标记
begin
SoureFile2.Position:=readpoint+1;
readpoint:=readpoint+1;
if SoureFile2.Position >= SoureFile2.Size then Break;
SoureFile2.Read(testword,sizeof(testword));
end;
SoureFile2.Position:=SoureFile2.Position-4;
SoureFile2.read(Data2,SizeOf(Data2));
memo1.lines.add('data标志: '+Data2.dataId);
memo1.lines.add('语音数据长度: '+inttostr(Data2.dataSize));
FmtisSame:=true;
if Fmt1.wFormatTag<>Fmt2.wFormatTag then FmtisSame:=false;
if Fmt1.FormatSize<>Fmt2.FormatSize then FmtisSame:=false;
if Fmt1.nChannels<>Fmt2.nChannels then FmtisSame:=false;
if Fmt1.nSamplesPerSec<>Fmt2.nSamplesPerSec then FmtisSame:=false;
if Fmt1.nAvgBytesPerSec<>Fmt2.nAvgBytesPerSec then FmtisSame:=false;
if Fmt1.nBlockAlign<>Fmt2.nBlockAlign then FmtisSame:=false;
if Fmt1.nBitsPerSample<>Fmt2.nBitsPerSample then FmtisSame:=false;
if FmtisSame=true then
begin
for i:=0 to 99 do
begin
if Fmt1others[i]<>Fmt2others[i] then FmtisSame:=false;
end;
end;
if FmtisSame then
begin
//===================建新WAV文件===================
WaveFile:=TFileStream.Create('new.wav',fmCreate);
Riff3:=Riff1;
Fmt3:=Fmt1;
Fmt3others:= Fmt1others;
Data3:=Data1;
Data3.dataSize:=Data1.dataSize+Data2.dataSize;
Riff3.WaveFileSize:=Data3.dataSize+sizeof(Data3)+Fmt3.Formatsize+8+sizeof(Riff3)-8;
memo1.lines.add('');
memo1.lines.add('合成后的声音文件');
memo1.lines.add('RIFF 标志: '+Riff3.RiffID);
memo1.lines.add('文件长度: '+inttostr(Riff3.WaveFileSize));
memo1.lines.add('WAVE标志: '+Riff3.WaveID);
memo1.lines.add('fmt 标志: '+Fmt3.fmtId);
memo1.lines.add('PCMWAWFORMAT内容长度: '+inttostr(Fmt3.FormatSize));
memo1.lines.add('编码格式: '+inttostr(Fmt3.wFormatTag));
memo1.lines.add('通道数: '+inttostr(Fmt3.nChannels));
memo1.lines.add('采样频率: '+inttostr(Fmt3.nSamplesPerSec));
memo1.lines.add('波形音频数据传送速度: '+inttostr(Fmt3.nAvgBytesPerSec));
memo1.lines.add('数据块的调整数: '+inttostr(Fmt3.nBlockAlign));
memo1.lines.add('每样本数据位数: '+inttostr(Fmt3.nBitsPerSample));
memo1.lines.add('data标志: '+Data3.dataId);
memo1.lines.add('语音数据长度: '+inttostr(Data3.dataSize));
WaveFile.Write(Riff3,SizeOf(Riff3));
WaveFile.Write(Fmt3,SizeOf(Fmt3));
if Fmt1.FormatSize>16 then
begin
for i:=0 to Fmt2.FormatSize-16-1 do WaveFile.Write(Fmt3others[i],sizeof(Fmt3others[i]));
end;
WaveFile.Write(Data3,SizeOf(Data3));
WaveFile.CopyFrom(SoureFile1,Data1.dataSize);
WaveFile.CopyFrom(SoureFile2,Data2.dataSize);
WaveFile.Free;
t2:=now;
memo1.lines.add('合成用时:'+timetostr(t2-t1));
end
else
showmessage('语音文件格式不同,不能合并!');
SoureFile1.Free;
SoureFile2.Free;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -