MP3歌词lrc文件读取算法 C语言源程序

合集下载

歌词解析器代码详情

歌词解析器代码详情

歌词解析器代码详情共6个文件,一个文件夹。

Dir目录如下。

驱动器F 中的卷没有标签。

卷的序列号是18A6-FCB5F:\W.E\C语言编程\歌词解析器的目录2013-01-22 16:27.2013-01-22 16:27..2013-01-22 16:27lrc2012-11-19 15:29 9,215 lrc.c2011-12-12 12:17 644 lrc.h2012-09-24 15:18 2,083 main.c2013-01-22 16:27pos3 个文件11,942 字节4 个目录171,449,978,880 可用字节Pos下有文件:console.c console.h resource.h现将所有文件内容罗列于下,自行分开.c.h Main.c#include#include#include#include#include "lrc.h"#include "./pos/console.h"typedef struct time{ //表示日期时间的数据结构char minute;char second;}TIME;TIME m_time; //存储模拟时间char * song_msg[4]; //存储歌曲的信息/************************************************************** ************ 函数功能:歌词解析器整体的控制* 参数:无* 返回值:无*************************************************************** ***********/int main(){int file_length=0; // 存储lrc文件内容的大小char * file_buf=NULL; // 指向malloc的空间,其中存放着lrc 文件中所有的内容char * lrc_text[200]={NULL}; // 指向,按照\r\n 切割后的一行歌词int lrc_line=0; // lrc文件中的行数int i=0;LRC * head=NULL,*p; // head记录歌词链表头int s_time=0; // 模拟时间变量file_buf=read_src_file(&file_length,"./lrc/兰亭序.lrc"); // 从lrc 文件中读出歌词内容lrc_line=strtok_lrc_buf(lrc_text,file_buf); // 按行切割歌曲内容lrc_head_resolve(song_msg,lrc_text); // 切割歌曲信息print_song_message(song_msg); // 显示歌曲信息head=lrc_resolve(lrc_line,lrc_text); // 保存时间:歌词到链表中// print(head); // 遍历链表,用来测试链表// ShellExecute( NULL, NULL, "TTPlayer.exe","兰亭序.mp3",NULL,1); //开启千千静听m_time.second=0;m_time.minute=0;while(1) //每秒钟到链表里面去找相应的歌词,如果找到那么就显示{/** 1.定位光标,显示歌词*/GoToXY(20,5);printf("%02d:%02d",m_time.minute,m_time.second);p=search(head,s_time); //到连表里查找当前时间点对应的歌词,如果有那么就返回歌词的首地址if(p!=NULL){lrc_show(p);}/** 1.运行模拟时间*/Sleep(500); //延时,注意在windows平台Sleep(1);延时1毫秒s_time=s_time+1;++m_time.second;if(m_time.second==60){m_time.second=0;++m_time.minute;if(m_time.minute==60)m_time.minute=0;}}return 0;}/************************************************************** ***************/ lrc.h#ifndef __LRC_H__#define __LRC_H__typedef struct lrc{int time;char lrc_buf[200];struct lrc *next;}LRC;extern char * read_src_file(int *file_length,char *src_file_name);extern int strtok_lrc_buf(char *lrc_text[],char *file_buf);extern void lrc_head_resolve(char *lrc_head_info[],char * lrc_text[]);extern void print_song_message(char * msg_info[]);extern LRC * lrc_resolve(int lrc_line,char * lrc_text[]);extern LRC *InsertList(LRC* head,LRC *lrc_link);extern void print(LRC * head);extern LRC *search (LRC *head,int time);extern void lrc_show(LRC * pi);extern void print_lrc(char * lrc);#endif/************************************************************** ***************/lrc.c#include#include#include#include#include "lrc.h"#include "./pos/console.h"/************************************************************** *********** * 函数功能:读出文件内容* 参数:* file_length:整型指针,此地址中保存文件字节数。

LRC校验算法C语言程序

LRC校验算法C语言程序

LRC校验算法C语言程序LRC(Longitudinal Redundancy Check)校验算法是一种简单的循环冗余校验算法,适用于对简单数据流进行校验。

它通过计算数据流中各字节的异或和,生成一个校验字节。

下面是一个基于C语言的LRC校验算法程序示例:```c#include <stdio.h>//生成LRC校验字节的函数unsigned char generateLRC(unsigned char *data, int length) unsigned char lrc = 0;for (int i = 0; i < length; i++)lrc ^= data[i];}return lrc;int maiunsigned char data[] = {0x01, 0x02, 0x03, 0x04};int dataLength = sizeof(data) / sizeof(data[0]);unsigned char lrc = generateLRC(data, dataLength);printf("Generated LRC: 0x%02x\n", lrc);return 0;```以上程序中,`generateLRC`函数用于生成LRC校验字节。

它遍历数据流`data`中的每个字节,通过使用异或操作符`^`计算每个字节的异或和,最终生成一个校验字节。

程序的主函数中定义了一个示例数据流`data`,并通过`sizeof`操作符计算数据流的长度。

调用`generateLRC`函数生成LRC校验字节,并将结果打印输出。

你可以根据需要修改示例程序中的数据流`data`,或者将LRC校验算法封装成更灵活的函数,以便在实际应用中使用。

此外,你还可以进一步扩展程序,实现LRC校验的校验功能,即通过比较接收到的数据流的校验字节与计算得到的校验字节来判断数据流是否正确。

C语言课程设计歌曲信息管理源代码

C语言课程设计歌曲信息管理源代码

C语言课程设计歌曲信息管理源代码#include "stdio.h"#include "string.h"#include "conio.h"#include "stdlib.h"struct music_list{char name[10];char singer[25];char ci[25];char qu[25];char zhuanji[25];char fxtime[25];char fxgongsi[25];int flag;};int count=0;const int MAX_COUNT = 100;void new_music(struct music_list musics[]);void delete_music_byname(struct music_list musics[],char* name); void search_music(struct music_list musics[],char*name);void show_all(struct music_list musics[]);int main(){ int choice;char name[10];struct music_list musics[MAX_COUNT];int i;for(i=0;i<MAX_COUNT;i++){musics[i].flag = 0;}T:do{printf("*******************************************************\n");printf("\nselect:1:new music 2:search 3:delete 4:show all 0:Exit\n");printf("*******************************************************\n");printf("please:");scanf("%d",&choice);switch(choice){case 1:new_music(musics);break;case 2:printf("Name:");scanf("%s",name);search_music(musics,name);break;case 3:printf("Name:");scanf("%s",name);delete_music_byname(musics,name);break;case 4:show_all(musics);break;case 0:break;default:choice = 0;}}while(choice !=0);printf("Thanks,Bye!\n");getch();return 0;}void new_music(struct music_list musics[]) {if(count==MAX_COUNT){printf("address list is full!\n");return;}int i,j;for(i=0;i<MAX_COUNT;i++){if(musics[i].flag == 0){j = i;break;}}printf("name:");scanf("%s",musics[j].name);printf("geshou:");scanf("%s",musics[j].singer);printf("zuoci:");scanf("%s",musics[j].ci);printf("zuoqu:");scanf("%s",musics[j].qu);printf("zhuanji:");scanf("%s",musics[j].zhuanji);printf("chubanshijian:");scanf("%s",musics[j].fxtime);printf("chubangongsi:");scanf("%s",musics[j].fxgongsi);musics[j].flag = 1;count++;}void search_music(struct music_list musics[],char*name){int i,j,flag=0;if(count==0){printf("Music list is empty!\n");return;}for(i=0;i<MAX_COUNT;i++){if(strcmp(name,musics[i].name)==0 && musics[i].flag == 1){if(flag == 0) {printf("====================================================== =\n");printf("name\t",musics[i].name);printf("singer\t",musics[i].singer);printf("ci\t",musics[i].ci);printf("qu\t",musics[i].qu);printf("zhuanji\t",musics[i].zhuanji);printf("fxtime\t",musics[i].fxtime);printf("fxgongsi\t",musics[i].fxgongsi);printf("\n==================================================== ===\n");flag=1;}printf("%s\t",musics[i].name);printf("%s\t",musics[i].singer);printf("%s\t",musics[i].ci);printf("%s\t",musics[i].qu);printf("%s\t",musics[i].zhuanji);printf("%s\t",musics[i].fxtime);printf("%s\t\n",musics[i].fxgongsi);}}if(flag!=1){printf("No such a music!");}}void show_all(struct music_list musics[]){if(count==0){printf("Music list is empty!\n");return;}int i,flag=0;;for(i=0;i<MAX_COUNT;i++){if(musics[i].flag == 1){if(flag == 0) {printf("====================================================== =\n");printf("name\t",musics[i].name);printf("singer\t",musics[i].singer);printf("ci\t",musics[i].ci);printf("qu\t",musics[i].qu);printf("zhuanji\t",musics[i].zhuanji);printf("fxtime\t",musics[i].fxtime);printf("\n==================================================== ===\n");flag=1;}printf("%s\t",musics[i].name);printf("%s\t",musics[i].singer);printf("%s\t",musics[i].ci);printf("%s\t",musics[i].qu);printf("%s\t",musics[i].zhuanji);printf("%s\t",musics[i].fxtime);printf("%s\t\n",musics[i].fxgongsi);}}}void delete_music_byname(struct music_list musics[],char* name){int i,j,flag=0;if(count==0){printf("Music list is empty!\n");return;}for(i=0;i<MAX_COUNT;i++){if(strcmp(name,musics[i].name)==0 && musics[i].flag == 1){musics[i].flag = 0;count --;if(flag == 0) {printf("The music \" %s \" was deleted.\n",musics[i].name);printf("====================================================== =\n");printf("name\t",musics[i].name);printf("singer\t",musics[i].singer);printf("ci\t",musics[i].ci);printf("qu\t",musics[i].qu);printf("zhuanji\t",musics[i].zhuanji);printf("fxtime\t",musics[i].fxtime);printf("\n==================================================== ===\n");flag=1;}printf("%s\t",musics[i].name);printf("%s\t",musics[i].singer);printf("%s\t",musics[i].ci);printf("%s\t",musics[i].qu);printf("%s\t",musics[i].zhuanji);printf("%s\t",musics[i].fxtime);printf("%s\t\n",musics[i].fxgongsi);}}if(flag!=1){printf("No such a music!");}}。

C语言音频处理音频读取处理和播放的技巧

C语言音频处理音频读取处理和播放的技巧

C语言音频处理音频读取处理和播放的技巧音频处理是计算机科学领域的一个重要分支,它涉及到音频信号的获取、处理和播放。

在C语言中,可以利用各种库和技巧来实现音频的读取、处理和播放。

本文将介绍一些C语言中常用的音频处理技巧,帮助读者更好地理解和应用音频处理的方法。

一、音频读取技巧1. 使用库文件:C语言中常用的音频读取库文件有libsndfile、libsndfile、PortAudio等。

这些库文件提供了方便的API接口,可以实现从音频文件中读取数据。

2. 了解音频文件格式:在进行音频读取操作前,先要了解所使用的音频文件的格式,比如WAV、MP3、FLAC等。

不同格式的音频文件在存储数据和读取方式上有所不同,需要根据文件格式进行相应的处理。

3. 使用文件指针:通过使用C语言中的文件指针,可以打开音频文件并读取其中的数据。

可以使用fopen()函数打开文件,使用fread()函数读取文件中的数据,并使用fclose()函数关闭文件。

二、音频处理技巧1. 音频采样率的调整:音频采样率是指音频每秒钟采集的样本数,常见的采样率有44.1kHz、48kHz等。

通过控制采样率,可以调整音频的播放速度和音质。

2. 音频音量的调整:通过对音频信号进行放大或缩小的操作,可以调整音频的音量。

可以通过调整音频的幅度或者应用数字信号处理的技术实现音量的调整。

3. 音频滤波:音频滤波是指对音频信号进行滤波处理,去除不需要的频率成分。

可以使用低通滤波器、高通滤波器、带通滤波器等进行音频滤波操作,以改善音频的质量。

三、音频播放技巧1. 使用库文件:在C语言中,可以使用SDL、OpenAL等音频播放库文件来实现音频的播放。

这些库文件提供了方便的接口函数,可以实现音频的播放和控制。

2. 使用多线程:为了保证音频播放的流畅性,在进行音频播放时可以考虑使用多线程。

将音频播放操作放在一个独立的线程中进行,可以避免音频播放对其他操作的阻塞。

C语言同步显示lrc歌词

C语言同步显示lrc歌词

C语言同步显示lrc歌词C语言技术报告班级:学号:姓名:项目说明:1、本程序在VC环境下调试成功环境:需安装千千静听到默认路径下,同时安装vc6.0环境2、本程序完成功能:完成LRC格式歌词的文件读取、解析、结构体创建等,同时在屏幕上将解析出的歌词进行实时显示基本功能实现:1、读取文件,能正确打印到屏幕上。

2、切割字符串,正确存到一个结构体数组中。

3、能正确判断歌曲的歌名与演唱者,并打印出来。

4、实现模拟时钟的功能。

5、按顺序将歌词输出。

6、能滚动显示歌词。

7、能与时间匹配突出显示歌词的颜色。

项目流程:1、首先将歌词文件内容通过fopen全部读到一个数组song_word[][]中,然后将歌词内容保存到数组song_word1[][]。

2、通过函数message_song1()判断歌曲的歌名与演唱者,并打印出前4行的歌曲信息。

3、用函数message_song2()和strtok将同一行的歌词和时间一一对应的进行切割,并分别保存在数组lyric[][]和time[][]中,并通过Sleep(1000)将时间标签转换为以s为单位的模拟时钟。

4、在每一秒内对将时钟的时间与歌词前面的时间相比较,如果相等那么就输出当前时间后面的歌词,实现了歌词与时间的同步显示。

5、歌词的前5行依次输出,当歌词大于5行时,用函数MoveText(22,6,20,5,22,5);实现将歌词整块移动并每次显示5行。

7、GoToXY(22,m)和SetText_Color(2)实现将光标定位在当前行并且显示相应的颜色,使已显示的歌词变为白色,而刚出现的歌词变为相应的颜色。

6、在主程序运行时即可启动千千静听ShellExecute( NULL, NULL, "TTPlayer.exe",".\\LRC\\简单爱.mp3",NULL,1);代码:#include#include#include#include#include#include"console.h"//跳转到光标指定位置void GoToXY(int x,int y){HANDLE h1;COORD pos;pos.X=x;pos.Y=y;h1=GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(h1,pos);}//屏幕整块移动//参数:startx、starty:要移动的块的起始坐标// sizex、sizey:块的大小// destx、desty: 目标坐标,即要移动到得位置void MoveText(int startx, int starty, int sizex, int sizey, int destx, int desty) {SMALL_RECT rc = {startx, starty,startx+sizex, starty+sizey};COORD crDest = {destx, desty};CHAR_INFO chFill;HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo(hout, &bInfo);chFill.Attributes = bInfo.wAttributes;chFill.Char.AsciiChar =' ';ScrollConsoleScreenBuffer(hout, &rc, NULL, crDest, &chFill);}/*第一个值为背景色,第二个值为前景色:0 = 黑8 = 灰1 = 蓝9 = 淡蓝2 = 绿 A = 淡绿3 = 湖蓝B = 淡浅绿4 = 红 C = 淡红5 = 紫 D = 淡紫6 = 黄 E = 淡黄7 = 白 F = 亮白*///设置接下来终端显示文本的背景色和文本颜色void SetText_Color(int color){HANDLE hStdout;hStdout = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hStdout,color);}void message_song1(char song[4][100])//切割前四行{int i;char delims[]="[:]";char *result=NULL;char *sign[4]={"歌名","歌手","制作","专辑"};for(i=0;i<4;i++){strtok(song[i],delims);result= strtok(NULL,delims);printf("%s %s\n",sign[i],result);}printf("\n\n");}void message_song2(char song1[100][100],char time[100][100] ,char lyric[100][100] )//切割歌词和时间{int i,j,k1=0,k2=0,min=0,tsec=0,gsec=0,b=6;int flag=0,m=5;char delims1[]="[]";char *result1=NULL;for(j=0;song1[j][0]!='\0';j++){result1=strtok(song1[j],delims1);for(i=0;result1!=NULL;i++){if(i%2==0){strcpy(time[k1],result1);result1=strtok(NULL,delims1);k1++;}if(i%2==1){strcpy(lyric[k2],result1);result1=strtok(NULL,delims1);k2++;}}}j=0;for(i=0;;i++){GoToXY(22,5);printf("The time is:0%d:%d%d ",min,tsec,gsec); Sleep(1000);gsec++;if(gsec==10){tsec++;gsec=0;}if(tsec==6){min++;tsec=0;}for(j=0;j<50;j++){if((min==time[j][1]-48)&&(tsec==time[j][3]-48)&&(gsec==time[j][4]-48)){if(m<10) m+=1;else m=10;GoToXY(22,m);SetText_Color(2);printf("%s\t\t\t\t\n",lyric[j-1]);GoToXY(22,m-1);SetText_Color(7);printf("%s\t\t\t\t\n",lyric[j-2]);flag++;if(flag>=5)MoveText(22,6,20,5,22,5);}}}}void main(){FILE*fp;int i=0;char time[100][100]={0};char lyric[100][100]={0};charinfile[1000]={0},song_word[100][100]={0},song_word1[100][100]={0};char *result=NULL;char delims1[]="\n";ShellExecute( NULL, NULL, "TTPlayer.exe","spring.mp3",NULL,1); //执行千千静听if((fp=fopen("spring.lrc","rb"))==NULL){printf("can not open file\n");exit(0);}while(!feof(fp)){infile[i]=fgetc(fp);i++;}infile[i]='\0';fclose(fp);printf("\n");result=strtok(infile,delims1);for(i=0;result!=NULL;i++){strcpy(song_word[i],result);result++;result=strtok(NULL,delims1);}for(i=0;i<44;i++)strcpy(song_word1[i],song_word[i+4]);message_song1(song_word);message_song2(song_word1,time,lyric);}bug调试:刚开始对切割函数strtok含有多个标识符的使用理解不透彻,经过多次改变标识符观察输出结果,也就正确理解了。

MP3c语言源代码

MP3c语言源代码
static HANDLE hSlider;
static MCI_PLAY_PARMS mciPlay;
static MCI_OPEN_PARMS mciOpen;
static MCI_DGV_SETAUDIO_PARMS mciSetAudioPara;
memset(FileName, 0, sizeof(FileName) );
FileNames.hInstance = NULL ;
FileNames.lpstrFilter = szFilter ;
FileNames.lpstrCustomFilter = NULL ;
FileNames.nMaxCustFilter = 0 ;
}
c[7+i+j]=a[7];
c[8+i+j]=a[8];
memcpy(szFilter, c,100);
FileNames.lStructSize = sizeof (OPENFILENAME) ;
FileNames.hwndOwner = hwnd ;
FileNames.nFilterIndex = 0 ;
FileNames.lpstrFile = szFileName ;
FileNames.nMaxFile = MAX_PATH ;
FileNames.lpstrFileTitle = szTitleName ;
return 0;
}
mciSetAudioPara.dwValue = iPosition*10;
mciSendCommand(mciOpen.wDeviceID, MCI_SETAUDIO, MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM,(DWORD)(LPVOID)&mciSetAudioPara);

lrc歌词读取和排序算法 (1)

lrc歌词读取和排序算法 (1)

LRC歌词读取和排序算法已有 14280 次阅读2008-6-5 15:41代码写了其实挺久了,现在突然想起来,鼓励自己下下,呵呵代码是为了给SPCE3200做一个微型mp3播放器而做的。

界面仿千千静听,使用软件解码器解mp3,滚动条、文件列表,基本功能差不多都有了,后来突然想到为它增加歌词显示,这样才算比较完整。

所以就开始要写lrc的解释程序了。

之前对lrc有一点了解,知道它最主要的就是用时间标签表达每一句歌词需要显示的时间。

所以,lrc解释程序的最主要任务就是分析时间标签,然后将实际的歌词拿出来~~~看代码吧:#include <string.h>#include "lrc.h"#define isnumeric(a) (((a >= '0') && (a <= '9')) ? 1 : 0)void CopyLrcInfo(LRC_INFO *DstInfo, LRC_INFO *SrcInfo){DstInfo->Time = SrcInfo->Time;DstInfo->Prev = SrcInfo->Prev;DstInfo->Next = SrcInfo->Next;strcpy(DstInfo->LrcText, SrcInfo->LrcText);}LRC_INFO *GetFirstOfList(LRC_QUEUE *List){return &List->List[List->First];}u16_t InsertList(LRC_QUEUE *List, u32_t Time, char LrcText[]) {int InsertPos = -1;u16_t i;LRC_INFO *lp = &List->List[List->Last];if(List->Length == 0){List->List[0].Time = Time;strcpy(List->List[0].LrcText, LrcText);List->List[0].Prev = (void*)0;List->List[0].Next = (void*)0;List->First = 0;List->Last = 0;List->Length = 1;InsertPos = 0;}else{for(i = List->Length; i != 0; i--){if(lp->Time <= Time){if(i == List->Length){List->Last = List->Length;lp->Next = &List->List[List->Length];List->List[List->Length].Prev = lp;List->List[List->Length].Next = (void*)0;// List->First = List->Length;// lp->Prev = &List->List[List->Length];// List->List[List->Length].Prev = (void*)0;// List->List[List->Length].Next = lp;}else{LRC_INFO *temp = lp->Next;lp->Next = &List->List[List->Length];List->List[List->Length].Prev = lp;List->List[List->Length].Next = temp;temp->Prev = &List->List[List->Length];}List->List[List->Length].Time = Time;strcpy(List->List[List->Length].LrcText, LrcText);InsertPos = (List->Length = List->Length + 1);break;}else if(i == 1){List->First = List->Length;lp->Prev = &List->List[List->Length];List->List[List->Length].Prev = (void*)0;List->List[List->Length].Next = lp;List->List[List->Length].Time = Time;strcpy(List->List[List->Length].LrcText, LrcText);InsertPos = (List->Length = List->Length + 1);// List->Last = List->Length;// lp->Next = &List->List[List->Length];// List->List[List->Length].Prev = lp;// List->List[List->Length].Next = (void*)0;// List->List[List->Length].Time = Time;// strcpy(List->List[List->Length].LrcText, LrcText); // InsertPos = (List->Length = List->Length + 1);}lp = lp->Prev;}}return InsertPos;}u32_t GetLrcInfo(char *LrcFile, u32_t FileSize, LRC_QUEUE *List) {s32_t ōffsetTime = 0;u32_t CurOffset = 0;u32_t CurTime = 0;u32_t TempOffset;int Flag = 0;memset(List, 0, sizeof(*List));// List->Length = 0;// List->First = 0;// List->Last = 0;// List->List[0].Prev = (void*)0;// List->List[0].Next = (void*)0;do {if(LrcFile[CurOffset++] == '['){if(Flag == 0)if(strncmp(&LrcFile[CurOffset], "offset:", 7) == 0){CurOffset += 7;if(LrcFile[CurOffset] == '-'){Flag = -1;}elseFlag = 1;while(LrcFile[CurOffset] != ']'){OffsetTime *= 10;OffsetTime += LrcFile[CurOffset++] - '0';}OffsetTime = OffsetTime / 10 * Flag;}if(isnumeric(LrcFile[CurOffset])){char *lrc;Flag = 1;CurTime = (((LrcFile[CurOffset] - '0') * 10 + (LrcFile[CurOffset + 1] - '0')) * 60 +((LrcFile[CurOffset + 3] - '0') * 10 + LrcFile[CurOffset + 4] - '0')) * 100;CurOffset += 5;if(LrcFile[CurOffset] == '.'){CurTime += (LrcFile[CurOffset + 1] - '0') * 10 + LrcFile[CurOffset + 2] - '0';}CurOffset++;TempOffset = CurOffset;while((LrcFile[TempOffset] == '[') && isnumeric(LrcFile[TempOffset + 1])){while((LrcFile[TempOffset] != ']') && (TempOffset < FileSize))TempOffset++;TempOffset++;}lrc = &LrcFile[TempOffset];while((LrcFile[TempOffset] != 0x0d) && (LrcFile[TempOffset] != 0x0a) && (TempOffset < FileSize))TempOffset++;LrcFile[TempOffset] = '\0';InsertList(List, CurTime + OffsetTime, lrc);}// else// {// while(LrcFile[CurOffset++] != ']');// }}} while(CurOffset < FileSize);return 0;}头文件:#ifndef __LRC_H__#define __LRC_H__#define MAX_LINE 128#define MAX_LINE_LEN 255typedef int s32_t;typedef unsigned int u32_t;typedef unsigned short u16_t;typedef unsigned char u8_t;typedef struct _LRC_INFO {u32_t Time;char LrcText[MAX_LINE_LEN];struct _LRC_INFO *Prev;struct _LRC_INFO *Next;} LRC_INFO;typedef struct {LRC_INFO List[MAX_LINE];u16_t Length;u16_t First;u16_t Last;} LRC_QUEUE;u32_t GetLrcInfo(char *LrcFile, u32_t FileSize, LRC_QUEUE *List);LRC_INFO *GetFirstOfList(LRC_QUEUE *List);#endif代码主体部分用来从lrc数据的开头开始解析时间标签,检测到一个标签就将对应的歌词提取出来,并放入一个链表中。

用于读取LRC同步歌词的类

用于读取LRC同步歌词的类

用于读取LRC同步歌词的类用于读取LRC同步歌词的类今天心情不错,用FLASH写了一个用于读取LRC同步歌词的类,只要25行代码,完全用是用FLASH的字符串操作来分析标签的.。

下面就是这个类:package LRC{public class readlrc {public function readlrcastime(mp3playtime:Number,gc:String):String { var qsd:int;//起始点var fhz:String;for (var j:int=0; j < gc.length; j ) {if (gc.charCodeAt(j) == 58) {if (int(gc.slice(j - 2,j)) * 60 int(gc.slice(j 1,j 3)) == mp3playtime) {var i:int=0;do {i ;if (gc.charCodeAt(j i) == 93) {qsd=j i;}if (gc.charCodeAt(j i) == 13) {fhz=gc.slice(qsd 1,j i);}} while (gc.charCodeAt(j i) != 13&&j i<gc.length);}}}return fhz;}}}将此文件保存为readlrc.as。

注意:一定要把此AS文件放入一个名为LRC的文件夹中,才可以使用。

下面就用一个小示例来说明如何用这个类,新建一个AS文件,写入以下代码:package {import flash.display.MovieClip;import flash.events.Event;import .URLLoader;import .URLRequest;import flash.media.Sound;import flash.media.SoundChannel;import flash.system.System;import flash.text.T extField;import LRC.readlrc;public class mp3 extends MovieClip {private var lrcreq:URLRequest=new URLRequest("日不落.lrc");private var mp3url:URLRequest=new URLRequest("日不落.mp3");private var mymp3:Sound=new Sound();private var channel:SoundChannel=new SoundChannel();private var lrcurl:URLLoader=new URLLoader();private var tbgc:String;private var mylrc:readlrc=new readlrc();eCodePage=true;public function mp3() {mymp3.load(mp3url);channel=mymp3.play();lrcurl.load(lrcreq);lrcurl.addEventListener(PLETE,loaded);}private function enterframe(event:Event) {try {gc_txt.text=mylrc.readlrcastime(int(channel.position/1000),t bgc);} catch (error:Error) {//}}private function loaded(event:Event) {tbgc=String(event.target.data);addEventListener(Event.ENTER_FRAME,enterframe);}}}保存此文件为mp3.as。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
return FALSE;
4
}
fseek(fp, sizeof(WCHAR), SEEK_SET); WCHAR wstr[MAX_LYRIC_LINE_LEN]; do {
if (!ReadALineW(fp, wstr, MAX_LYRIC_LINE_LEN, readlen)) break;
__forceinline BOOL ReadALineW(FILE *fp, WCHAR *buff, INT bufflen, INT &readlen);
__forceinline void AnalyseLineW(WCHAR *szLine, INT nLength); __forceinline BOOL CheckTagW(WCHAR *szText); __forceinline LONG GetStartTimeW(WCHAR *szTime);
__forceinline DWORD Find(DWORD dwTime); matched the time };
// return the line ID
-----------------------------------------------------Lyric.cpp----------------------------------------------------#include "Lyric.h"
二是时间标签,形式为“[mm:ss]”或“[mm:ss.fff]”(分钟数:秒数:毫秒数),时间标 签需位于某行歌词中的句首部分,一行歌词可以包含多个时间标签(比如歌词中的迭句部 分)。当歌曲播放到达某一时间点时,MP3 就会寻找对应的时间标签并显示标签后面的歌词 文本,这样就完成了“歌词同步”的功能。
return m_LyricList[dwTotalItem-1].dwStartTime; } }
// If lUserOffset > 0:
2
BOOL GetItemByID(DWORD dwItemID, LineLyri lyric data
by dwItemID
DWORD GetTimeByID(DWORD dwItemID);
// Get the lyric's start
fclose(fp);
m_bValid = TRUE;
return TRUE; }
void CLyric::UnLoad() {
m_bValid = FALSE; m_csArtist.Empty(); m_csTitle.Empty(); m_csAlbum.Empty(); m_csBy.Empty(); m_lOffset = 0;
return FALSE; }
WORD wUnicode_tag = 0; DWORD dwReadLen = 0; try {
dwReadLen = fread((void *)&wUnicode_tag, sizeof(WCHAR), 1, fp); } catch (...) {
printf("CLyric::Load: fread Exception: %s!\r\n", szFileName); fclose(fp); return FALSE; } if (dwReadLen != 1) { printf("CLyric::Load: read file %s failed!\r\n", szFileName); fclose(fp); return FALSE; } if (wUnicode_tag == 0xfeff) // unicode file { fclose(fp); fp = _tfopen(szFileName, _T("rb")); if (fp == NULL) {
m_csArtist; m_csTitle; m_csAlbum; m_csBy; m_lOffset; m_csKey;
// Lead time of the lyric
public: BOOL Load(LPCWSTR szFileName, LONG lUserOffset = 0);
ahead; if < 0: put off void UnLoad();
5
m_csKey.Empty(); m_LyricList.RemoveAll(); m_dwLineNum = 0; m_bAnalyseTag = TRUE; m_lUserOffset = 0; }
BOOL CLyric::GetItemByID(DWORD dwItemID, LineLyric &lyric) {
time by dwItemID
LONG GetItemIDByTime(DWORD dwTime, DWORD dwStartLineID = 0);// Search
the line index by time(in milliseconds) begin at nStartLineID
DWORD GetTotalNum() { return m_dwLineNum; }
Lrc 歌词文本中含有两类标签:
一是标识标签,其格式为“[标识名:值]”主要包含以下预定义的标签: [ar:歌手名]、[ti:歌曲名]、[al:专辑名]、[by:编辑者(指 lrc 歌词的制作人)]、[offset: 时间补偿值] (其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢 的,但多数的 MP3 可能不会支持这种标签)。
#define MAX_LYRIC_LINE_LEN #define MAX_LYRIC_LEN #define MAX_LYRIC_LINE_NUM #define MAX_LYRIC_TIME_LEN
512 128
5000 30
CLyric::CLyric() {
m_bValid = FALSE; m_lUserOffset = 0; }
■ 标识标签(ID-tags)
其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。 [ar:艺人名] [ti:曲名] [al:专辑名] [by:编者(指编辑 LRC 歌词的人)] [offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显 示快慢的。分钟:秒.毫秒]歌词 用记事本按照上述格式写好后,将拓展名改为 lrc 即可做出该文件.LRC 歌词是一种通过编辑
if (dwItemID < (DWORD)m_LyricList.GetSize()) {
lyric = m_LyricList[dwItemID]; return TRUE; } else { return FALSE; } }
DWORD CLyric::GetTimeByID(DWORD dwItemID) {
if (readlen <= 0) continue;
AnalyseLineW(wstr, readlen); } while (m_dwLineNum < MAX_LYRIC_LINE_NUM); } else { fseek(fp, 0L, SEEK_SET); CHAR str[MAX_LYRIC_LINE_LEN]; do {
{
DWORD dwStartTime; // The unit is millisecond
CString
csLyric;
} LineLyric, *PLineLyric;
class CLyric { public:
CLyric(); ~CLyric();
CString CString CString CString LONG CString
BOOL IsValid() { return m_bValid; }
private:
BOOL
m_bValid;
CArray<LineLyric> m_LyricList;
DWORD m_dwLineNum;
BOOL
m_bAnalyseTag;
LONG
m_lUserOffset;
__forceinline BOOL ReadALine(FILE *fp, CHAR *buff, INT bufflen, INT &readlen); __forceinline void AnalyseLine(CHAR *szLine, INT nLength); __forceinline BOOL CheckTag(CHAR *szText); __forceinline LONG GetStartTime(CHAR *szTime);
DWORD dwTotalItem = (DWORD)m_LyricList.GetSize(); if (dwTotalItem == 0)
return 0;
if (dwItemID < dwTotalItem) {
return m_LyricList[dwItemID].dwStartTime; } else {
Lrc 歌词文件格式说明
扩展名为 Lrc 格式的文件,是 MP3 播放器唯一能够识别的歌词文件,在 MP3 数码播放器 或千千静听中可以区同步显示歌词。
它是一种包含着“[*:*]”形式的“标签(tag)”的、基于纯文本的歌词专用格式。最早 由郭祥祥先生(Djohan)提出并在其程序中得到应用。这种歌词文件既可以用来实现卡拉 OK 功能(需要专门程序),又能以普通的文字处理软件查看、编辑。当然,实际操作时通常是 用专门的 LRC 歌词编辑软件进行高效编辑的。
1
器把歌词按歌曲歌词出现的时间编辑成一个文件,在播放歌曲时同步依次显示出来的一种歌 词文件。把歌曲和 LRC 歌词命为相同的文件名放在同一目录下,用带显示歌词功能的播放器 播放歌曲时歌词就可以同步显示显示,方便查看和学歌。
相关文档
最新文档