📄 unariff.pas
字号:
(*
----------------------------------------------
unaRIFF.pas
Voice Communicator components version 2.5
RIFF handling classes
----------------------------------------------
This source code cannot be used without
proper permission granted to you as a private
person or an entity by the Lake of Soft, Ltd
Visit http://lakeofsoft.com/ for details.
Copyright (c) 2001, 2003 Lake of Soft, Ltd
All rights reserved
----------------------------------------------
created by:
Lake, 20 May 2002
modified by:
Lake, May-Dec 2002
Lake, May 2003
Lake, Aug 2004
----------------------------------------------
*)
{$I unaDef.inc}
unit
unaRIFF;
{DP:UNIT
Resource Interchange File Format wrapper classes
}
interface
uses
Windows, unaTypes, unaClasses
{$IFDEF __SYSUTILS_H_ }
, Math
{$ENDIF}
;
type
// -- --
fourCC = array[0..3] of char;
// -- --
punaRIFFHeader = ^unaRIFFHeader;
unaRIFFHeader = packed record
r_id: fourCC;
r_size: unsigned; // size of data right after this field (including r_type)
r_type: fourCC;
end;
//
// -- unaRIFFChunk --
//
unaRIFile = class;
unaRIFFChunk = class
private
f_offset: unsigned;
f_maxSize: unsigned;
f_isContainer: bool;
f_header: punaRIFFHeader;
f_data: pArray;
//
f_subChunks: unaObjectList;
f_master: unaRIFile;
f_parent: unaRIFFChunk;
//
function getSubChunk(index: unsigned): unaRIFFChunk;
procedure parse();
public
constructor create(master: unaRIFile; parent: unaRIFFChunk; maxSize: unsigned; offset: unsigned = 0);
destructor Destroy(); override;
//
function getSubChunkCount(): unsigned;
function isID(const id: fourCC): bool;
//
property subChunk[index: unsigned]: unaRIFFChunk read getSubChunk; default;
property isContainer: bool read f_isContainer;
property header: punaRIFFHeader read f_header;
property offset: unsigned read f_offset;
property maxSize: unsigned read f_maxSize;
property data: pArray read f_data;
end;
//
// -- unaRIFile --
//
{DP:CLASS
}
unaRIFile = class
private
f_mapFile: unaMappedFile;
f_fileName: wideString;
//
f_data: pArray;
f_dataSize: unsigned;
f_rootChunk: unaRIFFChunk;
//
procedure parse();
function getIsValid(): bool;
public
constructor create(const fileName: wideString; access: unsigned = PAGE_READONLY); overload;
constructor create(data: pointer; len: unsigned); overload;
destructor Destroy(); override;
procedure AfterConstruction(); override;
//
function getPtr(offset: unsigned): pointer;
//
property rootChunk: unaRIFFChunk read f_rootChunk;
property isValid: bool read getIsValid;
property fileName: wideString read f_fileName;
end;
implementation
uses
unaUtils;
{ unaRIFFChunk }
// -- --
constructor unaRIFFChunk.create(master: unaRIFile; parent: unaRIFFChunk; maxSize: unsigned; offset: unsigned);
begin
inherited create();
//
f_master := master;
f_parent := parent;
//
f_offset := offset;
f_header := master.getPtr(offset);
f_data := master.getPtr(offset + 8);
f_maxSize := maxSize;
f_isContainer := (isID('RIFF') or isID('LIST'));
if (isContainer) then begin
f_subChunks := unaObjectList.create();
//
parse();
end;
end;
// -- --
destructor unaRIFFChunk.Destroy();
begin
inherited;
//
freeAndNil(f_subChunks);
end;
// -- --
function unaRIFFChunk.getSubChunk(index: unsigned): unaRIFFChunk;
begin
if (nil <> f_subChunks) then
result := f_subChunks[index]
else
result := nil;
end;
// -- --
function unaRIFFChunk.getSubChunkCount(): unsigned;
begin
if (nil <> f_subChunks) then
result := f_subChunks.count
else
result := 0;
end;
// -- --
function unaRIFFChunk.isID(const id: fourCC): bool;
begin
result := (id = f_header.r_id);
end;
// -- --
procedure unaRIFFChunk.parse();
var
ofs: unsigned;
maxSize: unsigned;
chunk: unaRIFFChunk;
begin
if (isContainer) then begin
//
f_subChunks.clear();
maxSize := min(f_header.r_size + 8, f_maxSize);
//
ofs := 12;
while (ofs + 8 <= maxSize) do begin
//
chunk := unaRIFFChunk.create(f_master, self, maxSize - ofs, f_offset + ofs);
f_subChunks.add(chunk);
inc(ofs, min(chunk.f_header.r_size + 8, chunk.f_maxSize));
ofs := (ofs + 1) and $FFFFFFFE;
end;
end;
end;
{ unaRIFile }
// -- --
constructor unaRIFile.create(const fileName: wideString; access: unsigned);
begin
inherited create();
//
f_mapFile := unaMappedFile.create(fileName, access);
f_data := nil;
f_dataSize := f_mapFile.size;
//
f_fileName := fileName;
end;
// -- --
procedure unaRIFile.AfterConstruction();
begin
inherited;
//
if (12 <= f_dataSize) then
parse();
//
end;
// -- --
constructor unaRIFile.create(data: pointer; len: unsigned);
begin
f_data := data;
f_dataSize := len;
f_mapFile := nil;
//
f_fileName := '';
end;
// -- --
destructor unaRIFile.Destroy();
begin
inherited;
//
freeAndNil(f_rootChunk);
freeAndNil(f_mapFile);
end;
// -- --
function unaRIFile.getIsValid(): bool;
begin
result := (nil <> rootChunk) and (rootChunk.isID('RIFF'));
end;
// -- --
function unaRIFile.getPtr(offset: unsigned): pointer;
begin
if (nil <> f_mapFile) then
result := @f_mapFile.data[offset]
else
result := @f_data[offset];
end;
// -- --
procedure unaRIFile.parse();
begin
freeAndNil(f_rootChunk);
//
if (nil <> f_mapFile) or (nil <> f_data) then
f_rootChunk := unaRIFFChunk.create(self, nil, f_dataSize)
else
f_rootChunk := nil;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -