C语言 解析lrc歌词文件
来源:互联网 发布:淘宝企业店铺年费 编辑:程序博客网 时间:2024/05/16 09:25
LRC文件如上图所示。
格式为 [mm:ss.ms]歌词
但是也有单行多个时间轴的情况,即 [mm:ss.ms][mm:ss.ms]歌词
对于解析来说,比较困难的正是单行多个时间轴的情况。我的解决方法是:
- 对单独一行检索]后没有[的位置,即该行最后一个[]框,将指针指向下一元素,就是这行歌词的第一个字。
- 编写函数将最后一个[]里面mm:ss.ms格式的时间轴化为long的ms。
- 删除最后一个[]及里面的内容,将后面的歌词并上来重新构成该行(整个算法的亮点就在这里)
- 重新检索该行最右边的[],直到没有[]为止
- 开始检索下一行,重复(1)的操作,直到下一行也没有[]为止。
- 整个歌词用链表储存,获取所有时间轴和歌词之后,按时间轴对链表进行排序。
我还只是初学者,代码可能不太规范,请见谅。
//.lrc Analysis//Copyright (c) 2016 Equim. All rights reserved.#include<stdio.h>#include<stdlib.h>#include<string.h>#include<time.h>#include<windows.h>#include<mmsystem.h>#pragma comment(lib, "WINMM.LIB")#define LEN sizeof(lyric)typedef struct _lyric{long timeLine;char verse[256];struct _lyric* next;}lyric;lyric* Head=NULL;long ms(char origin[9])//将mm:ss.ms化为毫秒 {long result=0;result=atoi(origin)*60*1000+atoi(origin+3)*1000+atoi(origin+6)*10;return result;}void OutputLyrics()/* 输出模块 */ {lyric *p;for(p=Head;p!=NULL;p=p->next)printf("%ld >> %s\n",p->timeLine,p->verse);}void Play()/* 播放模块 */ {clock_t e,start;lyric *p;system("mode con cols=150 lines=3");mciSendString("play D:\\C\\Jukebox\\Release\\audio\\ebbandflow.mp3",NULL, 0, 0);mciSendString("setaudio D:\\C\\Jukebox\\Release\\audio\\ebbandflow.mp3 volume to 150",NULL, 0, 0);start=clock();while(1){Sleep(200);e=clock()-start;printf("%ld\t",e);p=Head;while(!(p->next==NULL||(p->next)->timeLine>=e))//检索当前应显示的歌词,要么是最后一句,要么下一句的时间轴在当前时间之后 p=p->next;printf("%ld >> %-130.130s\r",p->timeLine,p->verse);}}int main(){FILE *lrc=fopen("D:\\C\\Jukebox\\Release\\audio\\ebbandflow.lrc","r");char linePointer[256];int i;lyric *p,*q,temp,*tempMin;/*让linePointer指向第一个歌词串*/do{fgets(linePointer,256,lrc);}while(!(linePointer[2]>='0'&&linePointer[2]<='9'));/*对每一行歌词进行操作*/ do{if(linePointer[strlen(linePointer)-1]=='\n')linePointer[strlen(linePointer)-1]='\0';//删除末尾的回车 do{i=0;do{i++;}while(!(linePointer[i-1]==']'&&linePointer[i]!='['));//让i指向最右边的[]右侧]的右边,即指向该行歌词的第一个字 p=(lyric*)malloc(LEN);p->timeLine=ms(linePointer+i-9);strcpy(p->verse,linePointer+i);if(Head==NULL)Head=p;elseq->next=p;q=p;linePointer[i-10]='\0';//删除最后的括号strcat(linePointer,q->verse);//巧妙地接回去便于继续解析 }while(linePointer[0]=='[');//解析到没有括号为止 }while(!(fgets(linePointer,256,lrc)==NULL||linePointer[0]!='['));//到最后一行 q->next=NULL;fclose(lrc);/*按时间轴排序*/ for(p=Head;p!=NULL;p=p->next)//比较笨拙的选择排序,按时间轴从小到大 {tempMin=p;for(q=p->next;q!=NULL;q=q->next)if(tempMin->timeLine>q->timeLine)//找最小的 tempMin=q;//寻找比最小还要小的,用临时指针标记 if(tempMin!=p)//如果确实找到了更小的 {temp=*tempMin;*tempMin=*p;*p=temp;temp.next=tempMin->next;tempMin->next=p->next;p->next=temp.next;}}/*播放测试或打印到屏幕*/ Play();//OutputLyrics();return 0;}
在我这边的环境下目前仅支持ANSI编码的lrc文件(Unicode和UTF-8会变乱码)
同步播放的效果
按条导出的效果
1 0
- C语言 解析lrc歌词文件
- C语言解析lrc文件
- lrc 歌词解析项目
- LRC歌词解析
- Java LRC 歌词解析
- LRC歌词解析
- js解析lrc歌词
- lrc歌词文件
- C语言解析多格式的lrc文件
- MP3制作之LRC歌词文件解析(附:源代码)
- android中解析lrc歌词
- VC++lrc歌词解析类
- VB Lrc歌词解析源码
- iOS解析lrc歌词文档
- oC语言 LRC歌词制作
- 怎样制作Lrc歌词文件
- C++ 分析歌词(LRC)文件
- [open source]Lrc歌词解析器发布
- struts2标签
- facebook审核流程
- android 对话框(一)Dialog
- DBUnit使用心得
- eclipse 重新关联源码方式
- C语言 解析lrc歌词文件
- 数据库 员工管理系统 设计报告
- LeetCode:Maximum Subarray
- Unity 高版本项目 移植到 低版本
- Java ——基础之继承与接口的区别
- git之撤销修改
- github结合TortoiseGit使用sshkey,无需输入账号和密码
- MVC 多语言
- 二叉树中序创建和遍历相关