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.