home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kompon / d56 / MPEGPLUS.ZIP / MPEGplus / MPEGplus.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-08-02  |  10.4 KB  |  294 lines

  1. { *************************************************************************** }
  2. {                                                                             }
  3. { Audio Tools Library (Freeware)                                              }
  4. { Class TMPEGplus - for manipulating with MPEGplus file information           }
  5. {                                                                             }
  6. { Uses:                                                                       }
  7. {   - Class TID3v1                                                            }
  8. {                                                                             }
  9. { Copyright (c) 2001 by Jurgen Faul                                           }
  10. { E-mail: jfaul@gmx.de                                                        }
  11. { http://jfaul.de/atl                                                         }
  12. {                                                                             }
  13. { Version 1.2 (2 August 2001)                                                 }
  14. {   - Class TID3v1: full support for ID3v1.0 & ID3v1.1 tags (read/write)      }
  15. {   - Some class properties added/changed                                     }
  16. {                                                                             }
  17. { Version 1.1 (26 July 2001)                                                  }
  18. {   - Fixed reading problem by "read only" files                              }
  19. {                                                                             }
  20. { Version 1.0 (23 May 2001)                                                   }
  21. {   - Full support for MPEGplus files (stream versions 4-7)                   }
  22. {   - ID3v1.1 tag supported (read only)                                       }
  23. {                                                                             }
  24. { *************************************************************************** }
  25.  
  26. unit MPEGplus;
  27.  
  28. interface
  29.  
  30. uses
  31.   Classes, SysUtils, ID3v1;
  32.  
  33. const
  34.   { Used with ChannelModeID property }
  35.   MPP_CM_STEREO = 1;                                  { Index for stereo mode }
  36.   MPP_CM_JOINT_STEREO = 2;                      { Index for joint-stereo mode }
  37.  
  38.   { Channel mode names }
  39.   MPP_MODE: array [0..2] of string = ('Unknown', 'Stereo', 'Joint Stereo');
  40.  
  41.   { Used with ProfileID property }
  42.   MPP_PROFILE_THUMB = 1;                             { 'Thumb' (poor) quality }
  43.   MPP_PROFILE_RADIO = 2;                           { 'Radio' (normal) quality }
  44.   MPP_PROFILE_STANDARD = 3;                       { 'Standard' (good) quality }
  45.   MPP_PROFILE_XTREME = 4;                      { 'Xtreme' (very good) quality }
  46.   MPP_PROFILE_INSANE = 5;                      { 'Insane' (excellent) quality }
  47.  
  48.   { Profile names }
  49.   MPP_PROFILE: array [0..5] of string =
  50.     ('Unknown', 'Thumb', 'Radio', 'Standard', 'Xtreme', 'Insane');
  51.  
  52. type
  53.   { Class TMPEGplus }
  54.   TMPEGplus = class(TObject)
  55.     private
  56.       { Private declarations }
  57.       FValid: Boolean;
  58.       FChannelModeID: Byte;
  59.       FFileSize: Cardinal;
  60.       FFrameCount: Cardinal;
  61.       FBitRate: Word;
  62.       FStreamVersion: Byte;
  63.       FProfileID: Byte;
  64.       FTag: TID3v1;
  65.       procedure FResetData;
  66.       function FGetChannelMode: string;
  67.       function FGetBitRate: Word;
  68.       function FGetProfile: string;
  69.       function FGetDuration: Double;
  70.       function FIsCorrupted: Boolean;
  71.     public
  72.       { Public declarations }
  73.       constructor Create;                                     { Create object }
  74.       destructor Destroy; override;                          { Destroy object }
  75.       function ReadFromFile(const FileName: string): Boolean;   { Load header }
  76.       property Valid: Boolean read FValid;             { True if header valid }
  77.       property ChannelModeID: Byte read FChannelModeID;   { Channel mode code }
  78.       property ChannelMode: string read FGetChannelMode;  { Channel mode name }
  79.       property FileSize: Cardinal read FFileSize;         { File size (bytes) }
  80.       property FrameCount: Cardinal read FFrameCount;      { Number of frames }
  81.       property BitRate: Word read FGetBitRate;                     { Bit rate }
  82.       property StreamVersion: Byte read FStreamVersion;      { Stream version }
  83.       property ProfileID: Byte read FProfileID;                { Profile code }
  84.       property Profile: string read FGetProfile;               { Profile name }
  85.       property Tag: TID3v1 read FTag;                              { File tag }
  86.       property Duration: Double read FGetDuration;       { Duration (seconds) }
  87.       property Corrupted: Boolean read FIsCorrupted; { True if file corrupted }
  88.   end;
  89.  
  90. implementation
  91.  
  92. type
  93.   { File header data - for internal use }
  94.   HeaderRecord = record
  95.     ByteArray: array [1..12] of Byte;                    { Data as byte array }
  96.     IntegerArray: array [1..3] of Integer;            { Data as integer array }
  97.     FileSize: Integer;                                            { File size }
  98.   end;
  99.  
  100. { ********************* Auxiliary functions & procedures ******************** }
  101.  
  102. function ReadHeader(const FileName: string; var Header: HeaderRecord): Boolean;
  103. var
  104.   SourceFile: file;
  105.   Transferred: Integer;
  106. begin
  107.   try
  108.     Result := true;
  109.     { Set read-access and open file }
  110.     AssignFile(SourceFile, FileName);
  111.     FileMode := 0;
  112.     Reset(SourceFile, 1);
  113.     { Read header and get file size }
  114.     BlockRead(SourceFile, Header, 12, Transferred);
  115.     Header.FileSize := FileSize(SourceFile);
  116.     CloseFile(SourceFile);
  117.     { if transfer is not complete }
  118.     if Transferred < 12 then Result := false
  119.     else Move(Header.ByteArray, Header.IntegerArray, SizeOf(Header.ByteArray));
  120.   except
  121.     { Error }
  122.     Result := false;
  123.   end;
  124. end;
  125.  
  126. { --------------------------------------------------------------------------- }
  127.  
  128. function GetStreamVersion(const Header: HeaderRecord): Byte;
  129. begin
  130.   { Get MPEGplus stream version }
  131.   if Header.IntegerArray[1] = 120279117 then         { 120279117 = 'MP+' + #7 }
  132.     Result := 7
  133.   else
  134.     case (Header.ByteArray[2] mod 32) div 2 of
  135.       3: Result := 4;
  136.       7: Result := 5;
  137.       11: Result := 6
  138.       else Result := 0;
  139.     end;
  140. end;
  141.  
  142. { --------------------------------------------------------------------------- }
  143.  
  144. function GetChannelModeID(const Header: HeaderRecord): Byte;
  145. begin
  146.   if GetStreamVersion(Header) = 7 then
  147.     { Get channel mode for stream version 7 }
  148.     if (Header.ByteArray[12] mod 128) < 64 then Result := MPP_CM_STEREO
  149.     else Result := MPP_CM_JOINT_STEREO
  150.   else
  151.     { Get channel mode for stream version 4-6 }
  152.     if (Header.ByteArray[3] mod 128) = 0 then Result := MPP_CM_STEREO
  153.     else Result := MPP_CM_JOINT_STEREO;
  154. end;
  155.  
  156. { --------------------------------------------------------------------------- }
  157.  
  158. function GetFrameCount(const Header: HeaderRecord): Cardinal;
  159. begin
  160.   { Get frame count }
  161.   case GetStreamVersion(Header) of
  162.     4: Result := Header.IntegerArray[2] shr 16;
  163.     5..7: Result := Header.IntegerArray[2];
  164.     else Result := 0;
  165.   end;
  166. end;
  167.  
  168. { --------------------------------------------------------------------------- }
  169.  
  170. function GetBitRate(const Header: HeaderRecord): Word;
  171. begin
  172.   { Try to get bit rate }
  173.   case GetStreamVersion(Header) of
  174.     4, 5: Result := Header.IntegerArray[1] shr 23;
  175.     else Result := 0;
  176.   end;
  177. end;
  178.  
  179. { --------------------------------------------------------------------------- }
  180.  
  181. function GetProfileID(const Header: HeaderRecord): Byte;
  182. begin
  183.   Result := 0;
  184.   { Get MPEGplus profile (exists for stream version 7 only) }
  185.   if GetStreamVersion(Header) = 7 then
  186.     case Header.ByteArray[11] of
  187.       128: Result := MPP_PROFILE_THUMB;
  188.       144: Result := MPP_PROFILE_RADIO;
  189.       160: Result := MPP_PROFILE_STANDARD;
  190.       176: Result := MPP_PROFILE_XTREME;
  191.       192: Result := MPP_PROFILE_INSANE;
  192.     end;
  193. end;
  194.  
  195. { ********************** Private functions & procedures ********************* }
  196.  
  197. procedure TMPEGplus.FResetData;
  198. begin
  199.   FValid := false;
  200.   FChannelModeID := 0;
  201.   FFileSize := 0;
  202.   FFrameCount := 0;
  203.   FBitRate := 0;
  204.   FStreamVersion := 0;
  205.   FProfileID := 0;
  206.   FTag.ResetData;
  207. end;
  208.  
  209. { --------------------------------------------------------------------------- }
  210.  
  211. function TMPEGplus.FGetChannelMode: string;
  212. begin
  213.   Result := MPP_MODE[FChannelModeID];
  214. end;
  215.  
  216. { --------------------------------------------------------------------------- }
  217.  
  218. function TMPEGplus.FGetBitRate: Word;
  219. begin
  220.   Result := FBitRate;
  221.   { Calculate bit rate if not given }
  222.   if (Result = 0) and (FFrameCount > 0) then
  223.     if FTag.Exists then
  224.       Result := Round((FFileSize - 128) * 8 * 44.1 / FFRameCount / 1152)
  225.     else
  226.       Result := Round(FFileSize * 8 * 44.1 / FFRameCount / 1152);
  227. end;
  228.  
  229. { --------------------------------------------------------------------------- }
  230.  
  231. function TMPEGplus.FGetProfile: string;
  232. begin
  233.   Result := MPP_PROFILE[FProfileID];
  234. end;
  235.  
  236. { --------------------------------------------------------------------------- }
  237.  
  238. function TMPEGplus.FGetDuration: Double;
  239. begin
  240.   { Calculate duration time }
  241.   Result := FFRameCount * 1152 / 44100;
  242. end;
  243.  
  244. { --------------------------------------------------------------------------- }
  245.  
  246. function TMPEGplus.FIsCorrupted: Boolean;
  247. begin
  248.   { Check for file corruption }
  249.   Result := (FValid) and ((FBitRate < 32) or (FBitRate > 320));
  250. end;
  251.  
  252. { ********************** Public functions & procedures ********************** }
  253.  
  254. constructor TMPEGplus.Create;
  255. begin
  256.   inherited;
  257.   FTag := TID3v1.Create;
  258.   FResetData;
  259. end;
  260.  
  261. { --------------------------------------------------------------------------- }
  262.  
  263. destructor TMPEGplus.Destroy;
  264. begin
  265.   FTag.Free;
  266.   inherited;
  267. end;
  268.  
  269. { --------------------------------------------------------------------------- }
  270.  
  271. function TMPEGplus.ReadFromFile(const FileName: string): Boolean;
  272. var
  273.   Header: HeaderRecord;
  274. begin
  275.   { Reset data and load header from file to variable }
  276.   FResetData;
  277.   Result := ReadHeader(FileName, Header);
  278.   { Process data if loaded and file valid }
  279.   if (Result) and (Header.FileSize > 0) and (GetStreamVersion(Header) > 0) then
  280.   begin
  281.     FValid := true;
  282.     { Fill properties with header data }
  283.     FChannelModeID := GetChannelModeID(Header);
  284.     FFileSize := Header.FileSize;
  285.     FFrameCount := GetFrameCount(Header);
  286.     FBitRate := GetBitRate(Header);
  287.     FStreamVersion := GetStreamVersion(Header);
  288.     FProfileID := GetProfileID(Header);
  289.     FTag.ReadFromFile(FileName);
  290.   end;
  291. end;
  292.  
  293. end.
  294.