如何改写MP3中的ID3TAG信息???倾家荡产求解(100分)

  • 主题发起人 主题发起人 dngjzx
  • 开始时间 开始时间
D

dngjzx

Unregistered / Unconfirmed
GUEST, unregistred user!
我们知道读取MP3 ID3TAG的方法如下,
声明
type
TID3Tag = packed record // 128 字节
TAGID: array[0..2] of char;
// 3 字节: 必须是TAG
Title: array[0..29] of char;
// 30 字节: 歌曲标题
Artist: array[0..29] of char;
// 30 字节: 歌曲的艺术家
Album: array[0..29] of char;
// 30 字节: 歌曲专辑
Year: array[0..3] of char;
// 4 字节: 出版年
Comment: array[0..29] of char;
// 30 字节: 评论
Genre: byte;
// 1 字节: 种类标识

//读取MP3内部信息的函数
procedure TForm1.GetMP3Info(mp3fileName:string);
var
id3tag: Tid3tag;
mp3file: Tfilestream;
begin

mp3file:=Tfilestream.create(mp3fileName,fmOpenRead);
try
mp3file.position:=mp3file.size-128;
// 跳到id3-tag
mp3file.Read(id3tag,SizeOf(id3tag));
if id3tag.Artist='' then

id3tag.Artist:='未知艺术家';
if id3tag.Title='' then

id3tag.Title:='未知歌曲名';
listview3.AddItem(AnsiReplaceText(id3tag.artist,' ','')+'~'+AnsiReplaceText(id3tag.title,' ',''),nil);
finally
mp3file.free;
end;

end;



但是如何写相关的信息进一个MP3文件呢? (主要用于修改MP3里歌手名和歌曲名),请高手赐教
 
直接拿去用把,封装成类了,如有不解地方可以问我:
{------------------------------------------------------------------------------
Unit name: Mp3Tag
Author: Alex (zqw0117@sina.com)
Update date: 2004.8.7

History:
2005.3.6: 1.更改部分方法名
2.增加 EraseTag 方法
2004.8.7: 第一个版本完成,初步实现所有读写操作功能.

本单元实现对 mp3 后缀信息读取和写入的类。
------------------------------------------------------------------------------}
unit Mp3Tag;

interface

uses
SysUtils, Windows;

const
Mp3TagIdent = 'TAG';

type
TMp3Tag = record
Ident: array[0..2] of char;
Title: array[0..29] of char;
Artist: array[0..29] of char;
Album: array[0..29] of char;
Year: array[0..3] of char;
Comment: array[0..27] of char;
Reserved1: Byte;
Reserved2: Byte;
Reserved3: Byte;
end;


TMp3TagInfoError = (mfeOK, mfeNotMp3FileOrNotExists, mfeOpenFileError, mfeReadFileError,
mfeWriteFileError, mfeEraseFileError, mfeNoTagInfo);

TMp3TagInfo = class(TObject)
private
{ private declarations }
FMp3Tag: TMp3Tag;
FMp3FileName: string;
FModified: Boolean;

function AssureFileName(const AMp3FileName: string): Boolean;

procedure SetMp3FileName(const AValue: string);


function GetIdent: string;
function GetHasTag: Boolean;

function GetTitle: string;
function GetArtist: string;
function GetAlbum: string;
function GetYear: string;
function GetComment: string;
function GetReserved1: Byte;
function GetReserved2: Byte;
function GetReserved3: Byte;

procedure SetTitle(const AValue: string);
procedure SetArtist(const AValue: string);
procedure SetAlbum(const AValue: string);
procedure SetYear(const AValue: string);
procedure SetComment(const AValue: string);
procedure SetReserved1(const AValue: Byte);
procedure SetReserved2(const AValue: Byte);
procedure SetReserved3(const AValue: Byte);

protected
FLastError: TMp3TagInfoError;

public
{ Public declarations }
constructor Create(const AMp3FileName: string);

procedure ReadTag;
function WriteTag: Boolean;
function EraseTag: Boolean;
function GetLastErrorStr: string;
dynamic;

property HasTag: Boolean read GetHasTag;
property Mp3File: string read FMp3FileName write SetMp3FileName;
property Title: string read GetTitle write SetTitle;
property Artist: string read GetArtist write SetArtist;
property Album: string read GetAlbum write SetAlbum;
property Year: string read GetYear write SetYear;
property Comment: string read GetComment write SetComment;
property Reserved1: Byte read GetReserved1 write SetReserved1;
property Reserved2: Byte read GetReserved2 write SetReserved2;
property Reserved3: Byte read GetReserved3 write SetReserved3;
property Modified: Boolean read FModified write FModified;
property LastError: TMp3TagInfoError read FLastError;
end;


implementation


constructor TMp3TagInfo.Create(const AMp3FileName: string);
begin

FLastError := mfeOK;
FMp3FileName := AMp3FileName;
ReadTag;
end;


function TMp3TagInfo.AssureFileName(const AMp3FileName: string): Boolean;
begin

Result := (AMp3FileName <> '') and (FileExists(AMp3FileName)) and
(SameText(ExtractFileExt(AMp3FileName), '.mp3'));
end;


procedure TMp3TagInfo.ReadTag;
var
iFileHandle: Integer;
iReadLen: Integer;
begin

FillChar(FMp3Tag, SizeOf(FMp3Tag), #0);
//make sure the file name is *.mp3 & it exists
if not AssureFileName(FMp3FileName) then

begin

FLastError := mfeNotMp3FileOrNotExists;
Exit;
end;


iFileHandle := FileOpen(FMp3FileName, fmOpenRead or fmShareDenyWrite);
if (iFileHandle < 0) then

begin

FLastError := mfeOpenFileError;
Exit;
end;

try
FileSeek(iFileHandle, -SizeOf(FMp3Tag), 2);

iReadLen := FileRead(iFileHandle, FMp3Tag, SizeOf(FMp3Tag));
if (iReadLen < SizeOf(FMp3Tag)) then

begin

FLastError := mfeReadFileError;

FillChar(FMp3Tag, SizeOf(FMp3Tag), #0);
Exit;
end;


if HasTag then

begin

FLastError := mfeOK;
FModified := False;
end
else

begin

FLastError := mfeNoTagInfo;
FillChar(FMp3Tag, SizeOf(FMp3Tag), #0);
end;

finally
if (iFileHandle > 0) then

FileClose(iFileHandle);
end;

end;


procedure TMp3TagInfo.SetMp3FileName(const AValue: string);
begin

if (AValue <> FMp3FileName) then

begin

FMp3FileName := AValue;
ReadTag;
end;

end;


function TagArrayToStr(const A: Array of Char;
Index: Integer;
const Count: Integer): string;
var
C: Integer;
begin

Result := '';
C := 0;
while C < Countdo

begin

Result := Result + A[Index];
Inc(C);
Inc(Index);
end;

end;


function TMp3TagInfo.GetIdent: string;
begin

Result := TagArrayToStr(FMp3Tag.Ident, 0, 3);
end;


function TMp3TagInfo.GetHasTag: Boolean;
begin

Result := SameText(GetIdent, Mp3TagIdent);
end;


function TMp3TagInfo.GetTitle: string;
begin

Result := TrimRight(TagArrayToStr(FMp3Tag.Title, 0, 30));
end;


function TMp3TagInfo.GetArtist: string;
begin

Result := TrimRight(TagArrayToStr(FMp3Tag.Artist, 0, 30));
end;


function TMp3TagInfo.GetAlbum: string;
begin

Result := TrimRight(TagArrayToStr(FMp3Tag.Album, 0, 30));
end;


function TMp3TagInfo.GetYear: string;
begin

Result := TrimRight(TagArrayToStr(FMp3Tag.Year, 0, 4));
end;


function TMp3TagInfo.GetComment: string;
begin

Result := TrimRight(TagArrayToStr(FMp3Tag.Comment, 0, 28));
end;


function TMp3TagInfo.GetReserved1: Byte;
begin

Result := FMp3Tag.Reserved1;
end;


function TMp3TagInfo.GetReserved2: Byte;
begin

Result := FMp3Tag.Reserved2;
end;


function TMp3TagInfo.GetReserved3: Byte;
begin

Result := FMp3Tag.Reserved3;
end;



procedure StrToTagArray(var A: Array of Char;
const S: string;
const ArrayMaxLength: Integer);
var
aIndex, sIndex, strLen: Integer;
begin

aIndex := Low(A);
sIndex := 1;
strLen := Length(S);
while aIndex < ArrayMaxLengthdo

begin

if sIndex <= strLen then
A[aIndex] := S[sIndex]
else
A[aIndex] := #0;
Inc(aIndex);Inc(sIndex);
end;

end;


procedure TMp3TagInfo.SetTitle(const AValue: string);
begin

if Title <> Copy(AValue, 1, 30) then

begin

StrToTagArray(FMp3Tag.Title, AValue, 30);
FModified := True;
end;

end;


procedure TMp3TagInfo.SetArtist(const AValue: string);
begin

if Artist <> Copy(AValue, 1, 30) then

begin

StrToTagArray(FMp3Tag.Artist, AValue, 30);
FModified := True;
end;

end;


procedure TMp3TagInfo.SetAlbum(const AValue: string);
begin

if Album <> Copy(AValue, 1, 30) then

begin

StrToTagArray(FMp3Tag.Album, AValue, 30);
FModified := True;
end;

end;


procedure TMp3TagInfo.SetYear(const AValue: string);
begin

if Year <> Copy(AValue, 1, 4) then

begin

StrToTagArray(FMp3Tag.Year, AValue, 4);
FModified := True;
end;

end;


procedure TMp3TagInfo.SetComment(const AValue: string);
begin

if Comment <> Copy(AValue, 1, 28) then

begin

StrToTagArray(FMp3Tag.Year, AValue, 28);
FModified := True;
end;

end;


procedure TMp3TagInfo.SetReserved1(const AValue: Byte);
begin

if Reserved1 <> AValue then

begin

FMp3Tag.Reserved1 := AValue;
FModified := True;
end;

end;


procedure TMp3TagInfo.SetReserved2(const AValue: Byte);
begin

if Reserved2 <> AValue then

begin

FMp3Tag.Reserved2 := AValue;
FModified := True;
end;

end;


procedure TMp3TagInfo.SetReserved3(const AValue: Byte);
begin

if Reserved3 <> AValue then

begin

FMp3Tag.Reserved3 := AValue;
FModified := True;
end;

end;


function TMp3TagInfo.WriteTag: Boolean;
var
iFileHandle: Integer;
iFileAttr: Integer;
iReadLen: Integer;
bFailTurnbackTag: Boolean;
begin

Result := False;
bFailTurnbackTag := False;
//make sure the file name is *.mp3 & it exists
if not AssureFileName(FMp3FileName) then

begin

FLastError := mfeNotMp3FileOrNotExists;
Exit;
end;

iFileAttr := FileGetAttr(FMp3FileName);
try
FileSetAttr(FMp3FileName, faArchive);
iFileHandle := FileOpen(FMp3FileName, fmOpenWrite or fmShareDenyWrite);
if (iFileHandle < 0) then

begin

FLastError := mfeOpenFileError;
Exit;
end;

try
{
如果文件本身有 Tag 的话,就Seek到Tag位置重新写入,就是改写;
否则,就 Seek 到文件末尾,给 mp3 文件增加一个 Tag。

}
if HasTag then

FileSeek(iFileHandle, -SizeOf(FMp3Tag), 2)
else

begin

FileSeek(iFileHandle, 0, 2);
FMp3Tag.Ident := Mp3TagIdent;
// 由于没有 Ident ,写入的时候必须手工添加
bFailTurnbackTag := True;
end;

iReadLen := FileWrite(iFileHandle, FMp3Tag, SizeOf(FMp3Tag));
if (iReadLen < SizeOf(FMp3Tag)) then

begin

FLastError := mfeWriteFileError;
// 如果写入失败,将写入前手工添加的 Ident 去除
if bFailTurnbackTag then
StrToTagArray(FMp3Tag.Ident, '', 3);
Exit;
end;

FModified := False;
FLastError := mfeOK;
Result := True;
finally
if (iFileHandle > 0) then

FileClose(iFileHandle);
end;

finally
FileSetAttr(FMp3FileName, iFileAttr);
end;

end;


function TMp3TagInfo.GetLastErrorStr: string;
begin

case FLastError of
mfeNotMp3FileOrNotExists: Result := '文件不是 .mp3 扩展名,或文件不存在';
mfeOpenFileError: Result := '打开文件错误';
mfeReadFileError: Result := '读取文件失败';
mfeWriteFileError: Result := '写入文件失败';
mfeEraseFileError: Result := '擦除 Tag 失败';
mfeNoTagInfo: Result := '无 Tag 信息';
else

Result := '';
end;

end;


function TMp3TagInfo.EraseTag: Boolean;
var
iFileHandle: Integer;
iFileAttr: Integer;
bFailTurnbackTag: Boolean;
begin

Result := False;
if not AssureFileName(FMp3FileName) then

begin

FLastError := mfeNotMp3FileOrNotExists;
Exit;
end;

iFileAttr := FileGetAttr(FMp3FileName);
try
FileSetAttr(FMp3FileName, faArchive);
iFileHandle := FileOpen(FMp3FileName, fmOpenWrite or fmShareDenyWrite);
if (iFileHandle < 0) then

begin

FLastError := mfeOpenFileError;
Exit;
end;

try
{
检查是否有 Tag 信息,如果有才擦除
}
if HasTag then

begin

FileSeek(iFileHandle, -SizeOf(FMp3Tag), 2);
Result := SetEndOfFile(iFileHandle);
if Reuslt then
FLastError := mfeOK
else
FLastError := mfeEraseFileError;
ReadTag
end
else
FLastError := mfeNoTagInfo;
finally
if (iFileHandle > 0) then

FileClose(iFileHandle);
end;

finally
FileSetAttr(FMp3FileName, iFileAttr);
end;

end;


end.
 
好像正是我需要的,请教我如何使用这样的一段代码?
是不是在我的程序里调用这个单元文件呢?
能说一下具体的调用方法吗? 我是小菜请谅解
 
首先,uses Mp3Tag;
然后写下面的代码
var
MTag: TMp3TagInfo;
begin

MTag := TMp3TagInfo.Create('c:/abc.mp3');
try
MTag.Artist := '你需要的歌唱家';
MTag.Title := '你需要的标题';
//......
MTag.WriteTag;
//写入
finally
MTag.Free;
end;

end;
 
[:D]强烈感谢,以上代码在WinXP+D7上通过(有一个地方的reslut请改为result),接分,再次感谢热心帮助![:D]
 
后退
顶部