大家平时长时间打代码的时候肯定会感到疲惫和乏味,这个时候一边播放自己喜欢的音乐,一边继续打代码,心情自然也愉快很多。大家平常应该会用QQ音乐、网易云音乐或者酷狗音乐等音乐APP来听歌,想不想拥有属于自己的音乐播放器。这篇文章教大家实现歌词解析功能
可用与qt界面应
1.mainwindow.cpp
需要添加的头文件和对应的定义变量
#include <QDir>
int s1=0;//保存歌曲下标
int s2=0;//最大歌曲数减一
char *s[N]={NULL};//存放歌曲名字
char *lry[N]={NULL};//存放歌词名字
char *song[N]={NULL};//存放歌曲路径
char *a[4]={NULL};//存放歌词前四句信息
第一步:读取存放歌曲的目录文件,将歌曲名字存入数组
代码实现:这里通过 opendir读取目录里的文件信息
以下代码将目录下的歌曲名字存入到数组 S[] 里面
void directory()//歌曲名字存入 s[N]
{
DIR *dir=opendir("/home/vboxuser/QT/qt/ceshi1/mymplayer/song");
if(dir==NULL)
{
perror("opendir");
}
struct dirent *dirp;
while(1)
{
dirp=readdir(dir);
if(dirp==NULL)
{
break;
}
else if(dirp->d_type==DT_REG)
{
s[s1]=(char*)malloc(32);//存放歌曲的名字
strcpy(s[s1],dirp->d_name);
s1++;
}
else{}
}
s2=s1-1;
s1=0;
closedir(dir);
}
第二步 :读取歌词文件目录
通过对比歌曲数组的排放顺序,将歌词放入数组
void song_lry()//歌词信息对于歌曲数组存进lry
{
DIR *dir=opendir("/home/vboxuser/QT/qt/ceshi1/mymplayer/lyrics");
if(dir==NULL)
{
perror("opendir");
}
struct dirent *dirp;
while(1)//遍历该目录下的所有的文件
{ dirp=readdir(dir);
if(dirp==NULL)
{
break;
}
else if (dirp->d_type==DT_REG)
{ for(int i=0;i<=s2;i++)//开始对比 歌曲数组S里的名字是否对应
{
char *str1=(char*)malloc(32);
bzero(str1,0);
strcpy(str1,s[i]);
char *str2=(char*)malloc(32);
bzero(str2,0);
strcpy(str2,dirp->d_name);
char *str3=NULL;
str3=strtok(str1,".");
char *str4=NULL;
str4=strtok(str2,".");
if(strcmp(str3,str4)==0)
{ lry[i]=(char*)malloc(32);
strcpy(lry[i],dirp->d_name);
}
}
}
else{;}
}
closedir(dir);
}
以上功能实现了将歌曲和歌词按相同顺序放入不同的数组,这样在实现音乐播放器的时候可以让歌曲与对应的歌词更好的同步
2.songfiel.h
1.定义歌词解析函数
这里我们在.h文件里定义了一个类,然后用QList容器定义了一个lrc类型的容器
#ifndef SONGFIEL_H
#define SONGFIEL_H
#include<QString>
#include<QList>
class lrcd
{
public:
int time;
QString name;
lrcd();
lrcd(float time,QString name)
{
this->time=time;
this->name=name;
}
//解析歌词
};
extern void lyrics_parse(QList<lrcd> *h, char *buff);
extern void lyrics_line(FILE * fp ,QList<lrcd> *h,char *buff[]);
extern void myprintf(QList<lrcd> *h);
class songfiel
{
public:
songfiel();
};
#endif
2.将歌词文件传入和容器传入函数
这里的a使用来保存歌词的歌手,歌曲名字,专辑名的数组
void song_er()
{
h=new QList<lrcd>;
char buf_fd[64]="";
sprintf(buf_fd,"/home/vboxuser/QT/qt/ceshi1/mymplayer/lyrics/%s",lry[now]);
FILE *fp;
if((fp = fopen(buf_fd, "a+")) == NULL)
{
perror("fail to fopen\n");
}
//循环清空容器
int a1=h->size();
for(int j=0;j<a1;j++)
{
h->removeAt(0);
}
lyrics_line(fp,h,a); //解析歌词
}
3.songfiel.cpp
1.歌词解析
将歌曲中的信息和歌词内容分别提取到不同的地方再进行解析
void lyrics_line(FILE * fp ,QList<lrcd> *h,char *buff[])
{
char buf[128] = "";
char *buff1[4]={NULL};
int i=0;
while(fgets(buf, sizeof(buf), fp)!=NULL)
{
char *p = buf;
int n=0;
while(*p != '[')
{
p++;
n++;
if(n==20)
{
break;
}
}
//存入字符串及容器
while(*p == '[')
{
if(((*(p+1)>=48)&&(*(p+1)<=57)) && ((*(p+2)>=48)&&(*(p+2)<=57)))//判断是否为歌词内容
{
lyrics_parse(h, buf);//传入到歌词内容与歌词时间分离函数
break;
}
else
{
p=p+4;
char *str3=NULL;
str3= (char *)malloc(32);
sscanf(p, "%s", str3);
strtok(str3,"]");
buff[i] = (char *)malloc(32);
sscanf(str3,"%s", buff[i]);
i++;
break;
}
}
}
}
2.歌词文字和时间分离函数
将分割的时间和歌词文字分别存入到容器,以便后续使用
void lyrics_parse(QList<lrcd> *h, char *buff)
{
int min;
float sec;
float t[10] = {0};
int i = 0;
char *p = buff;
int n=0;
while(*p != '[')
{
p++;
n++;
if(n==20)
{
break;
}
}
//解析时间
while(*p == '[')
{
sscanf(p, "[%d:%f", &min, &sec);
t[i] = 60 * min + sec;
p = p + 10;
i++;
}
//将时间和歌词保存在链表中
int j;
for(j = 0; j < i; j++)
{
if(*p!='\0'&& *p!='\n')
{
h->push_back(lrcd(t[j],p));
}
else
{
continue;
}
}
}
3.检验函数---容器的遍历
void myprintf(QList<lrcd> *h)
{
QList<lrcd>::iterator it=h->begin();
for (;it != h->end(); ++it)
{
// 对当前元素进行操作,例如打印时间和文本
qDebug() << "Time: " << (*it).time << ", Text: " << (*it).name;
}
}