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.
欢迎沟通及共同进步
QQ:1441299
Email:1441299@qq.com
越折腾越快乐!
分类:
vb
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端