首页 > 开发 > 综合 > 正文

从MP3中提取歌曲信息(C#)

2024-07-21 02:18:24
字体:
来源:转载
供稿:网友
从mp3中提取歌曲信息



一首mp3歌曲除了音乐信息外,还包含了如歌名、演唱者等信息,当我们用winamp软件听音乐时,播放清单就自动将这些信息读出来。大部分人都喜欢从网上下载音乐,但下载下来的mp3文件名都是文件上传系统自动取名的,和歌曲本身根本不相符,所以,给用户带来了很大的麻烦。但是,懒人有懒人的做法,我们何不自己写一个程序,将歌曲信息自动读出来并为mp3文件自动更名呢?



下面我就以c#为工具,把开发过程写出来。



一首mp3的额外信息存放在文件的最后面,共占128个字节,其中包括以下的内容(我们定义一个结构说明):

public struct mp3info

{

public string identify;//tag,三个字节

public string title;//歌曲名,30个字节

public string artist;//歌手名,30个字节

public string album;//所属唱片,30个字节

public string year;//年,4个字符

public string comment;//注释,28个字节



public char reserved1;//保留位,一个字节

public char reserved2;//保留位,一个字节

public char reserved3;//保留位,一个字节

}



所以,我们只要把mp3文件的最后128个字节分段读出来并保存到该结构里就可以了。函数定义如下:

/// <summary>

/// 获取mp3文件最后128个字节

/// </summary>

/// <param name="filename">文件名</param>

/// <returns>返回字节数组</returns>

private byte[] getlast128(string filename)

{

filestream fs = new filestream(filename,filemode.open,fileaccess.read);

stream stream = fs;



stream.seek(-128,seekorigin.end);



const int seekpos = 128;

int rl = 0;

byte[] info = new byte[seekpos];

rl = stream.read(info,0,seekpos);



fs.close();

stream.close();



return info;

}



再对上面返回的字节数组分段取出,并保存到mp3info结构中返回。

/// <summary>

/// 获取mp3歌曲的相关信息

/// </summary>

/// <param name = "info">从mp3文件中截取的二进制信息</param>

/// <returns>返回一个mp3info结构</returns>

private mp3info getmp3info(byte[] info)

{

mp3info mp3info = new mp3info();



string str = null;

int i;

int position = 0;//循环的起始值

int currentindex = 0;//info的当前索引值

//获取tag标识

for(i = currentindex;i<currentindex+3;i++)

{

str = str+(char)info[i];



position++;

}

currentindex = position;

mp3info.identify = str;



//获取歌名

str = null;

byte[] byttitle = new byte[30];//将歌名部分读到一个单独的数组中

int j = 0;

for(i = currentindex;i<currentindex+30;i++)

{

byttitle[j] = info[i];

position++;

j++;

}

currentindex = position;

mp3info.title = this.bytetostring(byttitle);



//获取歌手名

str = null;

j = 0;

byte[] bytartist = new byte[30];//将歌手名部分读到一个单独的数组中

for(i = currentindex;i<currentindex+30;i++)

{

bytartist[j] = info[i];

position++;

j++;

}

currentindex = position;

mp3info.artist = this.bytetostring(bytartist);



//获取唱片名

str = null;

j = 0;

byte[] bytalbum = new byte[30];//将唱片名部分读到一个单独的数组中

for(i = currentindex;i<currentindex+30;i++)

{

bytalbum[j] = info[i];

position++;

j++;

}

currentindex = position;

mp3info.album = this.bytetostring(bytalbum);



//获取年

str = null;

j = 0;

byte[] bytyear = new byte[4];//将年部分读到一个单独的数组中

for(i = currentindex;i<currentindex+4;i++)

{

bytyear[j] = info[i];

position++;

j++;

}

currentindex = position;

mp3info.year = this.bytetostring(bytyear);



//获取注释

str = null;

j = 0;

byte[] bytcomment = new byte[28];//将注释部分读到一个单独的数组中

for(i = currentindex;i<currentindex+25;i++)

{

bytcomment[j] = info[i];

position++;

j++;

}

currentindex = position;

mp3info.comment = this.bytetostring(bytcomment);



//以下获取保留位

mp3info.reserved1 = (char)info[++position];

mp3info.reserved2 = (char)info[++position];

mp3info.reserved3 = (char)info[++position];



return mp3info;

}

上面程序用到下面的方法:

/// <summary>

/// 将字节数组转换成字符串

/// </summary>

/// <param name = "b">字节数组</param>

/// <returns>返回转换后的字符串</returns>

private string bytetostring(byte[] b)

{

encoding enc = encoding.getencoding("gb2312");

string str = enc.getstring(b);

str = str.substring(0,str.indexof('/0') >= 0 ? str.indexof('/0') : str.length);//去掉无用字符



return str;

}



改名怎么办呢?我们按(演唱者)歌名 的格式对歌曲进行改名,程序如下:

/// <summary>

/// 更改文件名

/// </summary>

/// <param name="filepath">文件名</param>

/// <returns></returns>

private bool rename(string filepath)

{

if(file.exists(filepath))

{

mp3info mp3info = new mp3info();

mp3info = this.getmp3info(this.getlast128(filepath));//读出文件信息



mp3info.artist = this.deletenotvalue(mp3info.artist);

mp3info.title = this.deletenotvalue(mp3info.title);



if(mp3info.artist.trim().length==0)

{

mp3info.artist="未命名";

}



if(mp3info.title.trim().length==0)

{

mp3info.title="未知名歌曲";

}



try

{

//更名

file.move(filepath,filepath.substring(0,filepath.tolower().lastindexof("//")).trim() + "//" + "(" + mp3info.artist.trim() + ")" +mp3info.title.trim() + ".mp3");

return true;

}

catch(exception)

{

return false;

}

}

else

{

return false;

}

}



呵,思路就是这样了,如果有问题或者需要源码请发邮件至:[email protected]索取。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表