1 { *************************************************************************** }
3 { Audio Tools Library (Freeware) }
4 { Class TWAVfile - for extracting information from WAV file header }
6 { Copyright (c) 2001,2002 by Jurgen Faul }
7 { E-mail: jfaul@gmx.de }
8 { http://jfaul.de/atl }
10 { Version 1.2 (14 January 2002) }
11 { - Fixed bug with calculating of duration }
12 { - Some class properties added/changed }
14 { Version 1.1 (9 October 2001) }
15 { - Fixed bug with WAV header detection }
17 { Version 1.0 (31 July 2001) }
18 { - Info: channel mode, sample rate, bits per sample, file size, duration }
20 { Ïîðòèðîâàíî â KOL - Ìàòâååâ äìèòðèé }
22 { *************************************************************************** }
32 WAV_FORMAT_UNKNOWN
= 'Unknown';
33 WAV_FORMAT_PCM
= 'Windows PCM';
34 WAV_FORMAT_ADPCM
= 'Microsoft ADPCM';
35 WAV_FORMAT_ALAW
= 'A-LAW';
36 WAV_FORMAT_MULAW
= 'MU-LAW';
37 WAV_FORMAT_DVI_IMA_ADPCM
= 'DVI/IMA ADPCM';
38 WAV_FORMAT_MP3
= 'MPEG Layer III';
40 { Used with ChannelModeID property }
41 WAV_CM_MONO
= 1; { Index for mono mode }
42 WAV_CM_STEREO
= 2; { Index for stereo mode }
44 { Channel mode names }
45 WAV_MODE
: array [0..2] of string = ('Unknown', 'Mono', 'Stereo');
51 { Private declarations }
55 FSampleRate
: Cardinal;
56 FBytesPerSecond
: Cardinal;
59 FSampleNumber
: Integer;
63 function FGetFormat
: string;
64 function FGetChannelMode
: string;
65 function FGetDuration
: Double;
68 { Public declarations }
69 function ReadFromFile(const FileName
: string): Boolean; { Load header }
70 property Valid
: Boolean read FValid
; { True if header valid }
71 property FormatID
: Word read FFormatID
; { Format type code }
72 property Format
: string read FGetFormat
; { Format type name }
73 property ChannelNumber
: Byte read FChannelNumber
; { Number of channels }
74 property ChannelMode
: string read FGetChannelMode
; { Channel mode name }
75 property SampleRate
: Cardinal read FSampleRate
; { Sample rate (hz) }
76 property BytesPerSecond
: Cardinal read FBytesPerSecond
; { Bytes/second }
77 property BlockAlign
: Word read FBlockAlign
; { Block alignment }
78 property BitsPerSample
: Byte read FBitsPerSample
; { Bits/sample }
79 property HeaderSize
: Word read FHeaderSize
; { Header size (bytes) }
80 property FileSize
: Cardinal read FFileSize
; { File size (bytes) }
81 property Duration
: Double read FGetDuration
; { Duration (seconds) }
84 function NewWAV
: PWAV
;
89 DATA_CHUNK
= 'data'; { Data chunk ID }
92 { WAV file header data }
93 WAVRecord
= packed record
95 RIFFHeader
: array [1..4] of Char; { Must be "RIFF" }
96 FileSize
: Integer; { Must be "RealFileSize - 8" }
97 WAVEHeader
: array [1..4] of Char; { Must be "WAVE" }
98 { Format information }
99 FormatHeader
: array [1..4] of Char; { Must be "fmt " }
100 FormatSize
: Integer; { Format size }
101 FormatID
: Word; { Format type code }
102 ChannelNumber
: Word; { Number of channels }
103 SampleRate
: Integer; { Sample rate (hz) }
104 BytesPerSecond
: Integer; { Bytes/second }
105 BlockAlign
: Word; { Block alignment }
106 BitsPerSample
: Word; { Bits/sample }
107 DataHeader
: array [1..4] of Char; { Can be "data" }
108 SampleNumber
: Integer; { Number of samples (optional) }
111 function NewWAV
: PWAV
;
117 { ********************* Auxiliary functions & procedures ******************** }
120 function ReadWAV(const FileName
: string; var WAVData
: WAVRecord
): Boolean;
126 { Set read-access and open file }
127 SourceFile
:= NewReadFileStream(FileName
);
130 FillChar(WAVData
, 40, 0);
131 SourceFile
.Read(WAVData
, 40);
132 { Read number of samples if exists }
133 if WAVData
.DataHeader
<> DATA_CHUNK
then
135 SourceFile
.Seek(WAVData
.FormatSize
+ 28, spBegin
);
136 SourceFile
.Read(WAVData
.SampleNumber
, 4);
147 { --------------------------------------------------------------------------- }
149 function HeaderIsValid(const WAVData
: WAVRecord
): Boolean;
152 { Header validation }
153 if WAVData
.RIFFHeader
<> 'RIFF' then Result
:= false;
154 if WAVData
.WAVEHeader
<> 'WAVE' then Result
:= false;
155 if WAVData
.FormatHeader
<> 'fmt ' then Result
:= false;
156 if (WAVData
.ChannelNumber
<> WAV_CM_MONO
) and
157 (WAVData
.ChannelNumber
<> WAV_CM_STEREO
) then Result
:= false;
160 { ********************** Private functions & procedures ********************* }
162 procedure TWAV
.FResetData
;
169 FBytesPerSecond
:= 0;
177 { --------------------------------------------------------------------------- }
179 function TWAV
.FGetFormat
: string;
181 { Get format type name }
183 1: Result
:= WAV_FORMAT_PCM
;
184 2: Result
:= WAV_FORMAT_ADPCM
;
185 6: Result
:= WAV_FORMAT_ALAW
;
186 7: Result
:= WAV_FORMAT_MULAW
;
187 17: Result
:= WAV_FORMAT_DVI_IMA_ADPCM
;
188 85: Result
:= WAV_FORMAT_MP3
;
194 { --------------------------------------------------------------------------- }
196 function TWAV
.FGetChannelMode
: string;
198 { Get channel mode name }
199 Result
:= WAV_MODE
[FChannelNumber
];
202 { --------------------------------------------------------------------------- }
204 function TWAV
.FGetDuration
: Double;
210 if (FSampleNumber
= 0) and (FBytesPerSecond
> 0) then
211 Result
:= (FFileSize
- FHeaderSize
) / FBytesPerSecond
;
212 if (FSampleNumber
> 0) and (FSampleRate
> 0) then
213 Result
:= FSampleNumber
/ FSampleRate
;
217 { ********************** Public functions & procedures ********************** }
219 procedure TWAV
.InitFields
;
224 { --------------------------------------------------------------------------- }
226 function TWAV
.ReadFromFile(const FileName
: string): Boolean;
230 { Reset and load header data from file to variable }
233 FillChar(WAVData
, SizeOf(WAVData
), 0);
234 Result
:= ReadWAV(FileName
, WAVData
);
235 { Process data if loaded and header valid }
236 if (Result
) and (HeaderIsValid(WAVData
)) then
239 { Fill properties with header data }
240 FFormatID
:= WAVData
.FormatID
;
241 FChannelNumber
:= WAVData
.ChannelNumber
;
242 FSampleRate
:= WAVData
.SampleRate
;
243 FBytesPerSecond
:= WAVData
.BytesPerSecond
;
244 FBlockAlign
:= WAVData
.BlockAlign
;
245 FBitsPerSample
:= WAVData
.BitsPerSample
;
246 FSampleNumber
:= WAVData
.SampleNumber
;
247 if WAVData
.DataHeader
= DATA_CHUNK
then FHeaderSize
:= 44
248 else FHeaderSize
:= WAVData
.FormatSize
+ 40;
249 FFileSize
:= WAVData
.FileSize
+ 8;
250 if FHeaderSize
> FFileSize
then FHeaderSize
:= FFileSize
;