2 * File: $RCSfile: Header.pas,v $
3 * Revision: $Revision: 1.1.1.1 $
4 * Version : $Id: Header.pas,v 1.1.1.1 2002/04/21 12:57:16 fobmagog Exp $
5 * Author: $Author: fobmagog $
6 * Homepage: http://delphimpeg.sourceforge.net/
7 * Kol translation by Thaddy de Koning
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 Windows
, Kol
, KolCRC
, KolBitStream
, KolBitReserve
;
33 TVersion
= (MPEG2_LSF
, MPEG1
);
34 TMode
= (Stereo
, JointStereo
, DualChannel
, SingleChannel
);
35 TSampleFrequency
= (FourtyFourPointOne
, FourtyEight
, ThirtyTwo
, Unknown
);
38 FREQUENCIES
: array[TVersion
, TSampleFrequency
] of cardinal = ((22050, 24000, 16000, 1),
39 (44100, 48000, 32000, 1));
42 // Class for extraction information from a frame header:
44 THeader
= object(Tobj
)
47 FProtectionBit
: cardinal;
48 FBitrateIndex
: cardinal;
49 FPaddingBit
: cardinal;
50 FModeExtension
: cardinal;
53 FSampleFrequency
: TSampleFrequency
;
54 FNumberOfSubbands
: cardinal;
55 FIntensityStereoBound
: cardinal;
58 FInitialSync
: boolean;
60 FOffset
: PCardinalArray
;
65 function GetFrequency
: cardinal;
66 function GetChecksums
: boolean;
67 function GetChecksumOK
: boolean;
68 function GetPadding
: boolean;
71 property Version
: TVersion read FVersion
;
72 property Layer
: cardinal read FLayer
;
73 property BitrateIndex
: cardinal read FBitrateIndex
;
74 property SampleFrequency
: TSampleFrequency read FSampleFrequency
;
75 property Frequency
: cardinal read GetFrequency
;
76 property Mode
: TMode read FMode
;
77 property Checksums
: boolean read GetChecksums
;
78 property Copyright
: boolean read FCopyright
;
79 property Original
: boolean read FOriginal
;
80 property ChecksumOK
: boolean read GetChecksumOK
;
81 // compares computed checksum with stream checksum
82 property Padding
: boolean read GetPadding
;
83 property Slots
: cardinal read FNumSlots
;
84 property ModeExtension
: cardinal read FModeExtension
;
85 property NumberOfSubbands
: cardinal read FNumberOfSubbands
;
86 // returns the number of subbands in the current frame
87 property IntensityStereoBound
: cardinal read FIntensityStereoBound
;
88 // (Layer II joint stereo only)
89 // returns the number of subbands which are in stereo mode,
90 // subbands above that limit are in intensity stereo mode
93 destructor Destroy
; virtual;
95 function ReadHeader(Stream
: PBitStream
; var CRC
: PCRC16
): boolean;
96 // read a 32-bit header from the bitstream
98 function Bitrate
: cardinal;
100 function CalculateFrameSize
: cardinal;
103 function StreamSeek(Stream
: PBitStream
; SeekPos
: cardinal): boolean;
104 function MaxNumberOfFrames(Stream
: PBitStream
): integer;
105 function MinNumberOfFrames(Stream
: PBitStream
): integer;
107 function MSPerFrame
: single; // milliseconds per frame, for time display
108 function TotalMS(Stream
: PBitStream
): single;
111 function Newheader
: PHeader
;
118 BITRATES
: array[TVersion
, 0..2, 0..15] of
119 cardinal = (((0 {free format}, 32000, 48000, 56000, 64000, 80000, 96000,
120 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, 0),
121 (0 {free format}, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000,
122 80000, 96000, 112000, 128000, 144000, 160000, 0),
123 (0 {free format}, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000,
124 80000, 96000, 112000, 128000, 144000, 160000, 0)),
125 ((0 {free format}, 32000, 64000, 96000, 128000, 160000, 192000, 224000,
126 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0),
127 (0 {free format}, 32000, 48000, 56000, 64000, 80000, 96000, 112000,
128 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0),
129 (0 {free format}, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
130 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0))
133 function THeader
.Bitrate
: cardinal;
135 Result
:= BITRATES
[FVersion
, FLayer
- 1, FBitrateIndex
];
138 // calculates framesize in bytes excluding header size
139 function THeader
.CalculateFrameSize
: cardinal;
141 Val1
, Val2
: cardinal;
145 FFramesize
:= (12 * BITRATES
[FVersion
, 0, FBitrateIndex
]) div FREQUENCIES
[FVersion
,
148 if (FPaddingBit
<> 0) then
151 FFrameSize
:= FFrameSize
shl 2; // one slot is 4 bytes long
157 FFrameSize
:= (144 * BITRATES
[FVersion
, FLayer
- 1, FBitrateIndex
]) div
158 FREQUENCIES
[FVersion
, FSampleFrequency
];
160 if (FVersion
= MPEG2_LSF
) then
161 FFrameSize
:= FFrameSize
shr 1;
163 if (FPaddingBit
<> 0) then
169 if (FVersion
= MPEG1
) then
171 if (FMode
= SingleChannel
) then
176 if (FProtectionBit
<> 0) then
181 FNumSlots
:= FFramesize
- Val1
- Val2
- 4;
186 if (FMode
= SingleChannel
) then
191 if (FProtectionBit
<> 0) then
196 FNumSlots
:= FFramesize
- Val1
- Val2
- 4;
204 dec(FFrameSize
, 4); // subtract header size
206 Result
:= FFrameSize
;
209 function newHeader
: pHeader
;
218 FInitialSync
:= False;
222 destructor THeader
.Destroy
;
224 if (FOffset
<> nil) then
230 function THeader
.GetChecksumOK
: boolean;
232 Result
:= (FChecksum
= FCRC
.Checksum
);
235 function THeader
.GetChecksums
: boolean;
237 Result
:= (FProtectionBit
= 0);
240 function THeader
.GetFrequency
: cardinal;
242 Result
:= FREQUENCIES
[FVersion
, FSampleFrequency
];
245 function THeader
.GetPadding
: boolean;
247 Result
:= (FPaddingBit
<> 0);
250 // Returns the maximum number of frames in the stream
251 function THeader
.MaxNumberOfFrames(Stream
: PBitStream
): integer;
253 Result
:= Stream
.FileSize
div (FFrameSize
+ 4 - FPaddingBit
);
256 // Returns the minimum number of frames in the stream
257 function THeader
.MinNumberOfFrames(Stream
: PBitStream
): integer;
259 Result
:= Stream
.FileSize
div (FFrameSize
+ 5 - FPaddingBit
);
263 MSPerFrameArray
: array[0..2, TSampleFrequency
] of single = ((8.707483, 8.0, 12.0, 0),
264 (26.12245, 24.0, 36.0, 0),
265 (26.12245, 24.0, 36.0, 0));
267 function THeader
.MSPerFrame
: single;
269 Result
:= MSperFrameArray
[FLayer
- 1, FSampleFrequency
];
272 function THeader
.ReadHeader(Stream
: PBitStream
; var CRC
: PCRC16
): boolean;
274 HeaderString
, ChannelBitrate
: cardinal;
275 max
, cf
, lf
, i
: integer;
278 if (not FInitialSync
) then
280 if (not Stream
.GetHeader(@HeaderString
, INITIAL_SYNC
)) then
283 FVersion
:= TVersion((HeaderString
shr 19) and 1);
284 FSampleFrequency
:= TSampleFrequency((HeaderString
shr 10) and 3);
285 if (FSampleFrequency
= Unknown
) then
287 // report error - not supported header
291 Stream
.SetSyncWord(HeaderString
and $FFF80CC0);
293 FInitialSync
:= True;
297 if (not Stream
.GetHeader(@HeaderString
, STRICT_SYNC
)) then
303 FLayer
:= 4 - (HeaderString
shr 17) and 3;
304 FProtectionBit
:= (HeaderString
shr 16) and 1;
305 FBitrateIndex
:= (HeaderString
shr 12) and $F;
306 FPaddingBit
:= (HeaderString
shr 9) and 1;
307 FMode
:= TMode((HeaderString
shr 6) and 3);
308 FModeExtension
:= (HeaderString
shr 4) and 3;
310 if (FMode
= JointStereo
) then
311 FIntensityStereoBound
:= (FModeExtension
shl 2) + 4
313 FIntensityStereoBound
:= 0; // should never be used
315 FCopyright
:= ((HeaderString
shr 3) and 1 <> 0);
316 FOriginal
:= ((HeaderString
shr 2) and 1 <> 0);
318 // calculate number of subbands:
320 FNumberOfSubbands
:= 32
323 ChannelBitrate
:= FBitrateIndex
;
325 // calculate bitrate per channel:
326 if (FMode
<> SingleChannel
) then
327 if (ChannelBitrate
= 4) then
330 dec(ChannelBitrate
, 4);
332 if ((ChannelBitrate
= 1) or (ChannelBitrate
= 2)) then
334 if (FSampleFrequency
= ThirtyTwo
) then
335 FNumberOfSubbands
:= 12
337 FNumberOfSubbands
:= 8;
341 if ((FSampleFrequency
= FourtyEight
) or ((ChannelBitrate
>= 3) and
342 (ChannelBitrate
<= 5))) then
343 FNumberOfSubbands
:= 27
345 FNumberOfSubbands
:= 30;
349 if (FIntensityStereoBound
> FNumberOfSubbands
) then
350 FIntensityStereoBound
:= FNumberOfSubbands
;
352 // calculate framesize and nSlots
356 if (not Stream
.ReadFrame(FFrameSize
)) then
361 if (FProtectionBit
= 0) then
363 // frame contains a crc checksum
364 FChecksum
:= Stream
.GetBits(16);
368 FCRC
.AddBits(HeaderString
, 16);
375 if (FSampleFrequency
= FourtyFourPointOne
) then
377 if (FOffset
= nil) then
379 max
:= MaxNumberOfFrames(Stream
);
380 FOffset
:= AllocMem(Max
* sizeof(cardinal));
382 for i
:= 0 to max
- 1 do
386 cf
:= Stream
.CurrentFrame
;
387 lf
:= Stream
.LastFrame
;
388 if ((cf
> 0) and (cf
= lf
)) then
389 FOffset
[cf
] := FOffset
[cf
- 1] + FPaddingBit
391 FOffset
[0] := FPaddingBit
;
398 // Stream searching routines
399 function THeader
.StreamSeek(Stream
: PBitStream
;
400 SeekPos
: cardinal): boolean;
402 if (FSampleFrequency
= FourtyFourPointOne
) then
403 Result
:= Stream
.SeekPad(SeekPos
, FFrameSize
- FPaddingBit
, PObj(@Self
), FOffset
)
405 Result
:= Stream
.Seek(SeekPos
, FFrameSize
);
408 function THeader
.TotalMS(Stream
: PBitStream
): single;
410 Result
:= MaxNumberOfFrames(Stream
) * MSPerFrame
;