delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (0)


How to parse a wave file?Component available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Parsing a wave file to access each of its chunks
Product:
Delphi 3.x (or higher)
Category:
Multimedia
Skill Level:
Scoring:
Last Update:
03/28/2002
Search Keys:
delphi delphi3000 article borland vcl code-snippet WAV-file, wave, riff, parsing, sound-file,wav
Times Scored:
4
Visits:
3744
Uploader: Liran Shahar
Company: Com-N-Sense Ltd
Reference: www.com-n-sense.com
Component Download: http://www.com-n-sense.com/ftproot/SignalDisplay.zip
 
Question/Problem/Abstract:
Access each chunk within a wave file is a tricky business but sometime you need to access the actual samples/data to get what you want...so how can that be done?
Answer:



A WAV file is binary file in the RIFF format, RIFF format enables the user to haev multiple information in the same file which can either be used or not.

The information is stored in chunks, each chunk have its type (4 chars) and side (dword) so it can be skipped if you are not interested in the data or to be read from the file.

You can download the demo software that shows wave file in a signal display graph with functions as: paning, zoom, multiple audio channels and more from
http://www.com-n-sense.com/ftproot/SignalDisplay.zip
(the zip file contains the wavefileparser component and signaldisplay component).

The following code parses WAV files into accessable chunks:

(*==============================================================================
          Copyright (C) 2002, All rights reserved, Com-N-Sense Ltd
================================================================================
File: WaveFileParser.pas
Author: Liran Shahar, Com-N-Sense Ltd
Updated: 24/03/2022
Purpose: Parsing wave file into chunks
================================================================================
  24/03/2002, Liran Shahar
  - Initial release.
==============================================================================*)
unit WaveFileParser;

interface

uses
  Sysutils,Classes;

type
  TChunkType = array [1..4] of char;
  
  PChunk = ^TChunk;
  TChunk = packed record
    cType: TChunkType;
    dwSize: cardinal;
    pData: pointer;
  end;

  TcnsWaveFileParser = class(TPersistent)
  private
    FFilename: AnsiString;
    Chunks: TList;
  protected
    procedure SetFilename(AFilename: AnsiString); virtual;
    function GetChunksCount: integer; virtual;
    function GetChunk(Index: integer): PChunk; virtual;
    procedure ProcessFile; virtual;
    procedure ClearChunks; virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    function GetChunkByType(ChunkType: TChunkType): PChunk; virtual;
    property Filename: AnsiString read FFilename write SetFilename;
    property ChunksCount: integer read GetChunksCount;
    property Chunk[Index: integer]: PChunk read GetChunk;
  end;

implementation

const
  RIFF_SIGNATURE = 'RIFF';
  WAVE_SIGNATURE = 'WAVE';

type
  TRIFFHeader = packed record
    cSignature: TChunkType;
    dwSize: cardinal;
    cType: TChunkType;
  end;

constructor TcnsWaveFileParser.Create;
begin
  inherited Create;
  FFilename := '';
  Chunks := TList.Create;
end;

destructor TcnsWaveFileParser.Destroy;
begin
  ClearChunks;
  inherited Destroy;
end;

procedure TcnsWaveFileParser.SetFilename(AFilename: AnsiString);
begin
  if FFilename <> AFilename then
  begin
    ClearChunks;
    FFilename := AFilename;
    ProcessFile;
  end; // if
end;

function TcnsWaveFileParser.GetChunksCount: integer;
begin
  Result := Chunks.Count;
end;

function TcnsWaveFileParser.GetChunk(Index: integer): PChunk;
begin
  Result := nil;
  if (Index > -1) and (Index < Chunks.Count) then Result := Chunks[Index];
end;

procedure TcnsWaveFileParser.ProcessFile;
var
  WaveFile: TFileStream;
  Header: TRIFFHeader;
  Chunk: PChunk;
begin
  try
    WaveFile := TFileStream.Create(FFilename,fmOpenRead + fmShareDenyWrite);
    WaveFile.Read(Header,sizeof(Header));
    if (AnsiCompareText(Header.cSignature,RIFF_SIGNATURE) = 0) and
      (AnsiCompareText(Header.cType,WAVE_SIGNATURE) = 0) then
    begin
      while WaveFile.Position < WaveFile.Size do
      begin
        Chunk := AllocMem(sizeof(TChunk));
        with Chunk^ do
        begin
          WaveFile.Read(cType,sizeof(cType));
          WaveFile.Read(dwSize,sizeof(dwSize));
          pData := AllocMem(dwSize);
          WaveFile.Read(pData^,dwSize);
        end; // with
        Chunks.Add(Chunk);
      end; // while
    end; // if
  finally
    FreeAndNil(WaveFile);
  end;
end;

procedure TcnsWaveFileParser.ClearChunks;
var
  Chunk: PChunk;
begin
  while Chunks.Count > 0 do
  begin
    Chunk := Chunks[0];
    Chunks.Delete(0);                                    
    if assigned(Chunk^.pData) then FreeMem(Chunk^.pData);
    dispose(Chunk);
  end; // while
end;

function TcnsWaveFileParser.GetChunkByType(ChunkType: TChunkType): PChunk;
var
  iIndex: integer;
begin
  Result := nil;
  iIndex := 0;
  while iIndex < Chunks.Count do
    if AnsiCompareText(PChunk(Chunks[iIndex])^.cType,ChunkType) = 0 then
    begin
      Result := Chunks[iIndex];
      break;
    end
    else
      iIndex := iIndex + 1;
end;

end.





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment













 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
C.A. Longen
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)