⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unariff.pas

📁 Voice Commnucation Components for Delphi
💻 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 + -