Wave 文件(7): 建立一个空的 Wave 文件(三种方法)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses MMSystem;
//chan: 1 单声道、2 立体声;
//freq: 频率, 取值: 11025, 22050, 44100
//bit : 每个样本的大小, 取值 8、16
function CreateWav1(chan, freq, bit: Word; const FilePath: string): Boolean;
var
h: HMMIO;
ckiRiff, ckiFmt, ckiData: TMMCKInfo;
fmt: TPCMWaveFormat;
begin
//此函数是使用 mmioCreateChunk 函数来分别建立 Wave 文件的每个块.
{初识化相关结构}
ZeroMemory(@ckiRiff, SizeOf(TMMCKInfo));
ckiRiff.cksize := 36; {mmioCreateChunk 函数会自动写上 ckid, 但其 cksize 需要手动给}
ckiRiff.fccType := mmioStringToFOURCC('WAVE', 0);
ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
ckiData.ckid := mmioStringToFOURCC('data', 0);
{指定 Wave 格式}
fmt.wf.wFormatTag := WAVE_FORMAT_PCM;
fmt.wf.nChannels := chan;
fmt.wf.nSamplesPerSec := freq;
fmt.wf.nAvgBytesPerSec := freq * chan * bit div 8;
fmt.wf.nBlockAlign := chan * bit div 8;
fmt.wBitsPerSample := bit;
h := mmioOpen(PChar(FilePath), nil, MMIO_CREATE or MMIO_WRITE);
if h = 0 then Exit(False);
{分别建立 RIFF、fmt、data 块}
if (mmioCreateChunk(h, @ckiRiff, MMIO_CREATERIFF) = MMSYSERR_NOERROR) and
(mmioCreateChunk(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
(mmioWrite(h, PAnsiChar(@fmt), SizeOf(TPCMWaveFormat)) = SizeOf(TPCMWaveFormat)) and
(mmioAscend(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
(mmioCreateChunk(h, @ckiData, 0) = MMSYSERR_NOERROR) then Result := True;
mmioClose(h, 0);
end;
//把 PCM 编码的 WAVE 文件的前 44 个字节看成一个结构来操作:
function CreateWav2(chan, freq, bit: Word; const FilePath: string): Boolean;
type
TWaveHeader = record
Riff_ckid : DWORD;
Riff_cksize : DWORD;
Riff_fccType : DWORD;
fmt_ckid : DWORD;
fmt_cksize : DWORD;
wFormatTag : Word;
nChannels : Word;
nSamplesPerSec : DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign : Word;
wBitsPerSample : Word;
data_ckid : DWORD;
data_cksize : DWORD;
end;
var
wh: TWaveHeader;
hFile: Integer;
begin
wh.Riff_ckid := FOURCC_RIFF;
wh.Riff_cksize := 36;
wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
wh.fmt_cksize := 16;
wh.wFormatTag := WAVE_FORMAT_PCM;
wh.nChannels := chan;
wh.nSamplesPerSec := freq;
wh.nAvgBytesPerSec := freq * chan * bit div 8;
wh.nBlockAlign := chan * bit div 8;
wh.wBitsPerSample := bit;
wh.data_ckid := mmioStringToFOURCC('data', 0);
wh.data_cksize := 0;
hFile := FileCreate(FilePath);
Result := (FileWrite(hFile, wh, SizeOf(TWaveHeader)) <> -1);
FileClose(hFile);
end;
//同上, 只是改用流来写文件
function CreateWav3(chan, freq, bit: Word; const FilePath: string): Boolean;
type
TWaveHeader = record
Riff_ckid : DWORD;
Riff_cksize : DWORD;
Riff_fccType : DWORD;
fmt_ckid : DWORD;
fmt_cksize : DWORD;
wFormatTag : Word;
nChannels : Word;
nSamplesPerSec : DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign : Word;
wBitsPerSample : Word;
data_ckid : DWORD;
data_cksize : DWORD;
end;
var
wh: TWaveHeader;
begin
wh.Riff_ckid := FOURCC_RIFF;
wh.Riff_cksize := 36;
wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
wh.fmt_cksize := 16;
wh.wFormatTag := WAVE_FORMAT_PCM;
wh.nChannels := chan;
wh.nSamplesPerSec := freq;
wh.nAvgBytesPerSec := freq * chan * bit div 8;
wh.nBlockAlign := chan * bit div 8;
wh.wBitsPerSample := bit;
wh.data_ckid := mmioStringToFOURCC('data', 0);
wh.data_cksize := 0;
with TFileStream.Create(FilePath, fmCreate) do begin
Result := (Write(wh, SizeOf(TWaveHeader)) = SizeOf(TWaveHeader));
Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateWav1(1, 11025, 8, 'C:\Temp\X1.wav');
CreateWav2(2, 22050, 16, 'C:\Temp\X2.wav');
CreateWav3(2, 44100, 16, 'C:\Temp\X3.wav');
end;
end.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses MMSystem;
//chan: 1 单声道、2 立体声;
//freq: 频率, 取值: 11025, 22050, 44100
//bit : 每个样本的大小, 取值 8、16
function CreateWav1(chan, freq, bit: Word; const FilePath: string): Boolean;
var
h: HMMIO;
ckiRiff, ckiFmt, ckiData: TMMCKInfo;
fmt: TPCMWaveFormat;
begin
//此函数是使用 mmioCreateChunk 函数来分别建立 Wave 文件的每个块.
{初识化相关结构}
ZeroMemory(@ckiRiff, SizeOf(TMMCKInfo));
ckiRiff.cksize := 36; {mmioCreateChunk 函数会自动写上 ckid, 但其 cksize 需要手动给}
ckiRiff.fccType := mmioStringToFOURCC('WAVE', 0);
ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo));
ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
ZeroMemory(@ckiData, SizeOf(TMMCKInfo));
ckiData.ckid := mmioStringToFOURCC('data', 0);
{指定 Wave 格式}
fmt.wf.wFormatTag := WAVE_FORMAT_PCM;
fmt.wf.nChannels := chan;
fmt.wf.nSamplesPerSec := freq;
fmt.wf.nAvgBytesPerSec := freq * chan * bit div 8;
fmt.wf.nBlockAlign := chan * bit div 8;
fmt.wBitsPerSample := bit;
h := mmioOpen(PChar(FilePath), nil, MMIO_CREATE or MMIO_WRITE);
if h = 0 then Exit(False);
{分别建立 RIFF、fmt、data 块}
if (mmioCreateChunk(h, @ckiRiff, MMIO_CREATERIFF) = MMSYSERR_NOERROR) and
(mmioCreateChunk(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
(mmioWrite(h, PAnsiChar(@fmt), SizeOf(TPCMWaveFormat)) = SizeOf(TPCMWaveFormat)) and
(mmioAscend(h, @ckiFmt, 0) = MMSYSERR_NOERROR) and
(mmioCreateChunk(h, @ckiData, 0) = MMSYSERR_NOERROR) then Result := True;
mmioClose(h, 0);
end;
//把 PCM 编码的 WAVE 文件的前 44 个字节看成一个结构来操作:
function CreateWav2(chan, freq, bit: Word; const FilePath: string): Boolean;
type
TWaveHeader = record
Riff_ckid : DWORD;
Riff_cksize : DWORD;
Riff_fccType : DWORD;
fmt_ckid : DWORD;
fmt_cksize : DWORD;
wFormatTag : Word;
nChannels : Word;
nSamplesPerSec : DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign : Word;
wBitsPerSample : Word;
data_ckid : DWORD;
data_cksize : DWORD;
end;
var
wh: TWaveHeader;
hFile: Integer;
begin
wh.Riff_ckid := FOURCC_RIFF;
wh.Riff_cksize := 36;
wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
wh.fmt_cksize := 16;
wh.wFormatTag := WAVE_FORMAT_PCM;
wh.nChannels := chan;
wh.nSamplesPerSec := freq;
wh.nAvgBytesPerSec := freq * chan * bit div 8;
wh.nBlockAlign := chan * bit div 8;
wh.wBitsPerSample := bit;
wh.data_ckid := mmioStringToFOURCC('data', 0);
wh.data_cksize := 0;
hFile := FileCreate(FilePath);
Result := (FileWrite(hFile, wh, SizeOf(TWaveHeader)) <> -1);
FileClose(hFile);
end;
//同上, 只是改用流来写文件
function CreateWav3(chan, freq, bit: Word; const FilePath: string): Boolean;
type
TWaveHeader = record
Riff_ckid : DWORD;
Riff_cksize : DWORD;
Riff_fccType : DWORD;
fmt_ckid : DWORD;
fmt_cksize : DWORD;
wFormatTag : Word;
nChannels : Word;
nSamplesPerSec : DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign : Word;
wBitsPerSample : Word;
data_ckid : DWORD;
data_cksize : DWORD;
end;
var
wh: TWaveHeader;
begin
wh.Riff_ckid := FOURCC_RIFF;
wh.Riff_cksize := 36;
wh.Riff_fccType := mmioStringToFOURCC('WAVE', 0);
wh.fmt_ckid := mmioStringToFOURCC('fmt', 0);
wh.fmt_cksize := 16;
wh.wFormatTag := WAVE_FORMAT_PCM;
wh.nChannels := chan;
wh.nSamplesPerSec := freq;
wh.nAvgBytesPerSec := freq * chan * bit div 8;
wh.nBlockAlign := chan * bit div 8;
wh.wBitsPerSample := bit;
wh.data_ckid := mmioStringToFOURCC('data', 0);
wh.data_cksize := 0;
with TFileStream.Create(FilePath, fmCreate) do begin
Result := (Write(wh, SizeOf(TWaveHeader)) = SizeOf(TWaveHeader));
Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateWav1(1, 11025, 8, 'C:\Temp\X1.wav');
CreateWav2(2, 22050, 16, 'C:\Temp\X2.wav');
CreateWav3(2, 44100, 16, 'C:\Temp\X3.wav');
end;
end.