id3 for wma(100分)

  • 主题发起人 主题发起人 qdpingping
  • 开始时间 开始时间
Q

qdpingping

Unregistered / Unconfirmed
GUEST, unregistred user!
如何获取及修改wma文件的ID3信息? 或者提供有效的关于wma文件的ID3信息格式的相关资料就给分。不够再加分!
 
WMV的歌曲信息

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:do
uble;

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:do
uble 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 StringSizedo


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 5do


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 FieldCountdo


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_COUNTdo


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 ObjectCountdo


begin


Position := Source.Position;

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

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

ReadObject(ID, Source, Data);

Source.Seek(Position + ObjectSize, soFrombegin
ning);

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 &amp;
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 &amp;
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.



 
您有可执行程序吗?可以给我一份吗?我得信箱是:qingdaopoing@163.com. 多谢了
 
呵呵,我试了一下,可以呀! 不过好像还有点小问题,像专辑名,时间,类别还是读不出来,不过已经很感谢了。我再试试修改一下?您还有什么好的建议吗?给分了,多谢了。顺便问一下,有关于ogg的资料吗?
 
没有那个资料了,我都想找
 
不过我试了一上午,怎么专辑名,时间,类别,Track 就是读不出来?好像只要是扩展的就是不行,只有标准形式才可以,怎么办?
 
还有还有,有关于写wma文件id3的相关资料吗?
等我找到ogg文件id3的资料,给你一份!呵呵
 
后退
顶部