⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit1.pas

📁 用Delphi实现语音合并程序
💻 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 + -