网页功能: 加入收藏 设为首页 网站搜索  
WMV的歌曲信息
发表日期:2003-05-28作者:[] 出处:  

unit WMAfile;

interface

uses

 Classes, SysUtils;

const

 { Channel modes }

 WMA_CM_UNKNOWN = 0;                        { Unknown }

 WMA_CM_MONO = 1;                           { Mono }

 WMA_CM_STEREO = 2;                         { Stereo }

 { Channel mode names }

 WMA_MODE: array [0..2] of string = ('Unknown', 'Mono', 'Stereo');

type

 { Class TWMAfile }

 TWMAfile = class(TObject)

  private

   { Private declarations }

   FValid: Boolean;

   FFileSize: Integer;

   FChannelModeID: Byte;

   FSampleRate: Integer;

   FDuration: Double;

   FBitRate: Integer;

   FTitle: WideString;

   FArtist: WideString;

   FAlbum: WideString;

   FTrack: Integer;

   FYear: WideString;

   FGenre: WideString;

   FComment: WideString;

   procedure FResetData;

   function FGetChannelMode: string;

  public

   { Public declarations }

   constructor Create;                   { Create object }

   function ReadFromFile(const FileName: string): Boolean;   { Load data }

   property Valid: Boolean read FValid;        { True if valid data }

   property FileSize: Integer read FFileSize;     { File size (bytes) }

   property ChannelModeID: Byte read FChannelModeID;  { Channel mode code }

   property ChannelMode: string read FGetChannelMode; { Channel mode name }

   property SampleRate: Integer read FSampleRate;    { Sample rate (hz) }

   property Duration: Double read FDuration;     { Duration (seconds) }

   property BitRate: Integer read FBitRate;       { Bit rate (kbit) }

   property Title: WideString read FTitle;          { Song title }

   property Artist: WideString read FArtist;         { Artist name }

   property Album: WideString read FAlbum;          { Album name }

   property Track: Integer read FTrack;           { Track number }

   property Year: WideString read FYear;              { Year }

   property Genre: WideString read FGenre;          { Genre name }

   property Comment: WideString read FComment;          { Comment }

 end;

implementation

const

 { Object IDs }

 WMA_HEADER_ID =

  #48#38#178#117#142#102#207#17#166#217#0#170#0#98#206#108;

 WMA_FILE_PROPERTIES_ID =

  #161#220#171#140#71#169#207#17#142#228#0#192#12#32#83#101;

 WMA_STREAM_PROPERTIES_ID =

  #145#7#220#183#183#169#207#17#142#230#0#192#12#32#83#101;

 WMA_CONTENT_DESCRIPTION_ID =

  #51#38#178#117#142#102#207#17#166#217#0#170#0#98#206#108;

 WMA_EXTENDED_CONTENT_DESCRIPTION_ID =

  #64#164#208#210#7#227#210#17#151#240#0#160#201#94#168#80;

 { Max. number of supported comment fields }

 WMA_FIELD_COUNT = 7;

 { Names of supported comment fields }

 WMA_FIELD_NAME: array [1..WMA_FIELD_COUNT] of WideString =

  ('WM/TITLE', 'WM/AUTHOR', 'WM/ALBUMTITLE', 'WM/TRACK', 'WM/YEAR',

   'WM/GENRE', 'WM/DESCRIPTION');

 { Max. number of characters in tag field }

 WMA_MAX_STRING_SIZE = 250;

type

 { Object ID }

 ObjectID = array [1..16] of Char;

 { Tag data }

 TagData = array [1..WMA_FIELD_COUNT] of WideString;

 { File data - for internal use }

 FileData = record

  FileSize: Integer;                  { File size (bytes) }

  MaxBitRate: Integer;                { Max. bit rate (bps) }

  Channels: Word;                   { Number of channels }

  SampleRate: Integer;                  { Sample rate (hz) }

  ByteRate: Integer;                      { Byte rate }

  Tag: TagData;                    { WMA tag information }

 end;

{ ********************* Auxiliary functions & procedures ******************** }

function ReadFieldString(const Source: TStream; DataSize: Word): WideString;

var

 Iterator, StringSize: Integer;

 FieldData: array [1..WMA_MAX_STRING_SIZE * 2] of Byte;

begin

 { Read field data and convert to Unicode string }

 Result := '';

 StringSize := DataSize div 2;

 if StringSize > WMA_MAX_STRING_SIZE then StringSize := WMA_MAX_STRING_SIZE;

 Source.ReadBuffer(FieldData, StringSize * 2);

 Source.Seek(DataSize - StringSize * 2, soFromCurrent);

 for Iterator := 1 to StringSize do

  Result := Result +

   WideChar(FieldData[Iterator * 2 - 1] + (FieldData[Iterator * 2] shl 8));

end;

{ --------------------------------------------------------------------------- }

procedure ReadTagStandard(const Source: TStream; var Tag: TagData);

var

 Iterator: Integer;

 FieldSize: array [1..5] of Word;

 FieldValue: WideString;

begin

 { Read standard tag data }

 Source.ReadBuffer(FieldSize, SizeOf(FieldSize));

 for Iterator := 1 to 5 do

  if FieldSize[Iterator] > 0 then

  begin

   { Read field value }

   FieldValue := ReadFieldString(Source, FieldSize[Iterator]);

   { Set corresponding tag field if supported }

   case Iterator of

    1: Tag[1] := FieldValue;

    2: Tag[2] := FieldValue;

    4: Tag[7] := FieldValue;

   end;

  end;

end;

{ --------------------------------------------------------------------------- }

procedure ReadTagExtended(const Source: TStream; var Tag: TagData);

var

 Iterator1, Iterator2, FieldCount, DataSize, DataType: Word;

 FieldName, FieldValue: WideString;

begin

 { Read extended tag data }

 Source.ReadBuffer(FieldCount, SizeOf(FieldCount));

 for Iterator1 := 1 to FieldCount do

 begin

  { Read field name }

  Source.ReadBuffer(DataSize, SizeOf(DataSize));

  FieldName := ReadFieldString(Source, DataSize);

  { Read value data type }

  Source.ReadBuffer(DataType, SizeOf(DataType));

  { Read field value only if string }

  if DataType = 0 then

  begin

   Source.ReadBuffer(DataSize, SizeOf(DataSize));

   FieldValue := ReadFieldString(Source, DataSize);

  end

  else

   Source.Seek(DataSize, soFromCurrent);

  { Set corresponding tag field if supported }

  for Iterator2 := 1 to WMA_FIELD_COUNT do

   if UpperCase(Trim(FieldName)) = WMA_FIELD_NAME[Iterator2] then

    Tag[Iterator2] := FieldValue;

 end;

end;

{ --------------------------------------------------------------------------- }

procedure ReadObject(const ID: ObjectID; Source: TStream; var Data: FileData);

begin

 { Read data from header object if supported }

 if ID = WMA_FILE_PROPERTIES_ID then

 begin

  { Read file properties }

  Source.Seek(80, soFromCurrent);

  Source.ReadBuffer(Data.MaxBitRate, SizeOf(Data.MaxBitRate));

 end;

 if ID = WMA_STREAM_PROPERTIES_ID then

 begin

  { Read stream properties }

  Source.Seek(60, soFromCurrent);

  Source.ReadBuffer(Data.Channels, SizeOf(Data.Channels));

  Source.ReadBuffer(Data.SampleRate, SizeOf(Data.SampleRate));

  Source.ReadBuffer(Data.ByteRate, SizeOf(Data.ByteRate));

 end;

 if ID = WMA_CONTENT_DESCRIPTION_ID then

 begin

  { Read standard tag data }

  Source.Seek(4, soFromCurrent);

  ReadTagStandard(Source, Data.Tag);

 end;

 if ID = WMA_EXTENDED_CONTENT_DESCRIPTION_ID then

 begin

  { Read extended tag data }

  Source.Seek(4, soFromCurrent);

  ReadTagExtended(Source, Data.Tag);

 end;

end;

{ --------------------------------------------------------------------------- }

function ReadData(const FileName: string; var Data: FileData): Boolean;

var

 Source: TFileStream;

 ID: ObjectID;

 Iterator, ObjectCount, ObjectSize, Position: Integer;

begin

 { Read file data }

 try

  Source := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);

  Data.FileSize := Source.Size;

  { Check for existing header }

  Source.ReadBuffer(ID, SizeOf(ID));

  if ID = WMA_HEADER_ID then

  begin

   Source.Seek(8, soFromCurrent);

   Source.ReadBuffer(ObjectCount, SizeOf(ObjectCount));

   Source.Seek(2, soFromCurrent);

   { Read all objects in header and get needed data }

   for Iterator := 1 to ObjectCount do

   begin

    Position := Source.Position;

    Source.ReadBuffer(ID, SizeOf(ID));

    Source.ReadBuffer(ObjectSize, SizeOf(ObjectSize));

    ReadObject(ID, Source, Data);

    Source.Seek(Position + ObjectSize, soFromBeginning);

   end;

  end;

  Source.Free;

  Result := true;

 except

  Result := false;

 end;

end;

{ --------------------------------------------------------------------------- }

function IsValid(const Data: FileData): Boolean;

begin

 { Check for data validity }

 Result :=

  (Data.MaxBitRate > 0) and (Data.MaxBitRate < 320000) and

  ((Data.Channels = WMA_CM_MONO) or (Data.Channels = WMA_CM_STEREO)) and

  (Data.SampleRate >= 8000) and (Data.SampleRate <= 96000) and

  (Data.ByteRate > 0) and (Data.ByteRate < 40000);

end;

{ --------------------------------------------------------------------------- }

function ExtractTrack(const TrackString: WideString): Integer;

var

 Value, Code: Integer;

begin

 { Extract track from string }

 Result := 0;

 Val(TrackString, Value, Code);

 if Code = 0 then Result := Value;

end;

{ ********************** Private functions & procedures ********************* }

procedure TWMAfile.FResetData;

begin

 { Reset variables }

 FValid := false;

 FFileSize := 0;

 FChannelModeID := WMA_CM_UNKNOWN;

 FSampleRate := 0;

 FDuration := 0;

 FBitRate := 0;

 FTitle := '';

 FArtist := '';

 FAlbum := '';

 FTrack := 0;

 FYear := '';

 FGenre := '';

 FComment := '';

end;

{ --------------------------------------------------------------------------- }

function TWMAfile.FGetChannelMode: string;

begin

 { Get channel mode name }

 Result := WMA_MODE[FChannelModeID];

end;

{ ********************** Public functions & procedures ********************** }

constructor TWMAfile.Create;

begin

 { Create object }

 inherited;

 FResetData;

end;

{ --------------------------------------------------------------------------- }

function TWMAfile.ReadFromFile(const FileName: string): Boolean;

var

 Data: FileData;

begin

 { Reset variables and load file data }

 FResetData;

 FillChar(Data, SizeOf(Data), 0);

 Result := ReadData(FileName, Data);

 { Process data if loaded and valid }

 if Result and IsValid(Data) then

 begin

  FValid := true;

  { Fill properties with loaded data }

  FFileSize := Data.FileSize;

  FChannelModeID := Data.Channels;

  FSampleRate := Data.SampleRate;

  FDuration := Data.FileSize * 8 / Data.MaxBitRate;

  FBitRate := Data.ByteRate * 8 div 1000;

  FTitle := Trim(Data.Tag[1]);

  FArtist := Trim(Data.Tag[2]);

  FAlbum := Trim(Data.Tag[3]);

  FTrack := ExtractTrack(Trim(Data.Tag[4]));

  FYear := Trim(Data.Tag[5]);

  FGenre := Trim(Data.Tag[6]);

  FComment := Trim(Data.Tag[7]);

 end;

end;

end.

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 WMV的歌曲信息
本类热点文章
  DBGrid 应用全书
  DBGrid 应用全书
  TWebBrowser编程简述
  用户界面设计的技巧与技术
  用户界面设计的技巧与技术
  初探Delphi 7 中的插件编程
  获取主板BIOS的信息
  网卡的远程网络唤醒
  Delphi 2006简介(Dexter)
  用Delphi开发数据库程序经验三则
  Delphi面向对象编程的20条规则
  Delphi面向对象编程的20条规则
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00473