Wave 文件(4): 获取 Wave 文件主块与子块的信息
有两个相关的结构体: TMMIOInfo、TMMCKInfo.
TMMIOInfo 是多媒体文件打开后的状态信息, mmioOpen 函数的第二个参数就是这个结构的指针.
现在先用到了 TMMCKInfo, 这是文件内部 "块" 的信息, 构成如下:
查找 "块" 需要通过 mmioDescend、mmioAscend 两个函数.
mmioAscend 是从子块跳出;
mmioDescend 是进入到子块; 进入子块是需要指定子块的 ckid 和父块信息;
mmioDescend 也用来查找主块(RIFF), 此时需要很少的信息就可以找到主块.
测试代码:
TMMIOInfo 是多媒体文件打开后的状态信息, mmioOpen 函数的第二个参数就是这个结构的指针.
现在先用到了 TMMCKInfo, 这是文件内部 "块" 的信息, 构成如下:
TMMCKInfo = record ckid: FOURCC; {块标识} cksize: DWORD; {块大小} fccType: FOURCC; {格式类型标识} dwDataOffset: DWORD; {偏移地址} dwFlags: DWORD; {附加信息} end;
查找 "块" 需要通过 mmioDescend、mmioAscend 两个函数.
mmioAscend 是从子块跳出;
mmioDescend 是进入到子块; 进入子块是需要指定子块的 ckid 和父块信息;
mmioDescend 也用来查找主块(RIFF), 此时需要很少的信息就可以找到主块.
测试代码:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} uses MMSystem; const FilePath = 'C:\WINDOWS\Media\Windows XP 启动.wav'; //获取 RIFF 块的信息 procedure TForm1.Button1Click(Sender: TObject); var hFile: HMMIO; ckiRIFF: TMMCKInfo; begin //清空 ckiRIFF 结构体; 有些函数使用前要求必须清空, 即使不要求也还是清空的好. FillChar(ckiRIFF, SizeOf(TMMCKInfo), 0); {局部变量在清空前有垃圾数据} //打开文件, 获取句柄 hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ); //获取 RIFF 块的信息 mmioDescend(hFile, {文件句柄} @ckiRIFF, {块信息结构的指针, 用于获取块的信息} nil, {这父块的结构信息, RIFF 没有父块, 无需指定} MMIO_FINDRIFF {如果是查询子块这里的标志是 MMIO_FINDCHUNK} ); {返回 0 表示查找成功, 这里忽略了验证} //以下是查证获取到的信息 ShowMessageFmt('%d, %d, %d, %d, %d', [ckiRIFF.ckid, ckiRIFF.cksize, ckiRIFF.fccType, ckiRIFF.dwDataOffset, ckiRIFF.dwFlags ]); {1179011410, 424636, 1163280727, 8, 0} if ckiRIFF.ckid = FOURCC_RIFF then ShowMessage('是 RIFF'); if ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0) then ShowMessage('是 WAVE'); //关闭 mmioClose(hFile, 0); end; //获取子块的信息 procedure TForm1.Button2Click(Sender: TObject); var hFile: HMMIO; ckiRIFF,ckiSub: TMMCKInfo; n: Integer; begin //清空准备接受信息的结构 FillChar(ckiRIFF, SizeOf(TMMCKInfo), 0); FillChar(ckiSub, SizeOf(TMMCKInfo), 0); hFile := mmioOpen(PChar(FilePath), nil, MMIO_READ); //先获取主块(RIFF)信息 mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF); //获取 fmt 子块信息 ckiSub.ckid := mmioStringToFOURCC('fmt', 0); if mmioDescend(hFile, @ckiSub, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR then begin ShowMessageFmt('%d, %d, %d, %d, %d', [ckiSub.ckid, ckiSub.cksize, ckiSub.fccType, ckiSub.dwDataOffset, ckiSub.dwFlags]); end; //如果继续查找需要跳出子块; 下面将从偏移地址 20 跳到 36 处 mmioAscend(hFile, @ckiSub, 0); {其第三个参数一直是 0, 是备用参数} //获取 data 子块信息 ckiSub.ckid := mmioStringToFOURCC('data', 0); if mmioDescend(hFile, @ckiSub, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR then begin ShowMessageFmt('%d, %d, %d, %d, %d', [ckiSub.ckid, ckiSub.cksize, ckiSub.fccType, ckiSub.dwDataOffset, ckiSub.dwFlags]); end; mmioClose(hFile, 0); 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客户端