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。

LRC校验算法C语言程序

LRC校验算法C语言程序

LRC校验算法C语言程序序言近日用到关于LRC检验算法,网上找了很多资料,其描述方式实在不敢恭维,为方便使用者特写下详细的计算过程,希望对你有所帮助。

By 厦大Jacky 20120814LRC校验的数据发送格式起始字符(1个字符)+数据(2n个字符)+校验值(2个字符)+结束字符(2个:回车+换行)。

LRC校验值计算数据(2n个字符)两两组成一个16进制的数值,然后将这些数值相加,将所得加值与256求模,然后用256减去所得模值,得到的数值即为检验值(即:sum%256后取反,再加1)。

范例发送数值:01050BE7FF0009数值分析:-- 起始字符;01050BE7FF00 -- 数据值;09 -- 检验值;其后还有回车换行(未标出)。

数据值拆分:010********* -->0x01 0x05 0x0B 0xE7 0xFF 0x00 求和:0x01+0x05+0x0B+0xE7+0xFF+0x00 =0x01F7;取模,取反:0x1F7%0x100=0xF7 0xF7 取反0x08加1:0x08+1=0x09 (校验值)C语言算法:uchar data[17]={0x3a,0x30,0x31,0x30,0x35,0x00,0x00,0x00,0x00,//no0x00,0x00,0x00,0x00,//status0x00,0x00, //LRCData0x0d,0x0a};//******************************************************* ************************// 语法格式:uchar LRC_Check(uchar *data,uchar length);// 实现功能:LRC数据检测算法程序// 参数:无// 返回值:LRC检验值//******************************************uchar LRC_Check(uchar *data,uchar length){uchar i;uint k;uchar result;uchar lrcdata[length];for(i=1;i<length+1;i++){if(data[i]>0x40)lrcdata[i-1]=data[i]-0x41+10;elselrcdata[i-1]=data[i]-0x30;}k=0;for(i=0;i<length/2;i++){k+=(lrcdata[2*i]*16+lrcdata[2*i+1]);}k=k%256;k=256-k;result=k%256;return result;}。

C语言音频编程深入理解在C语言中处理音频数据的方法

C语言音频编程深入理解在C语言中处理音频数据的方法

C语言音频编程深入理解在C语言中处理音频数据的方法音频处理是计算机科学领域的一个重要研究方向,而C语言作为一门被广泛应用的编程语言,也具备强大的音频编程能力。

本文将深入探讨在C语言中处理音频数据的方法,包括音频的读取与写入、音频格式的转换与处理以及音频信号的分析与处理等方面。

一、音频的读取与写入在C语言中,我们可以使用相关的库函数来实现音频的读取与写入操作。

常用的库函数包括标准C库中的文件读写函数和一些专门用于音频处理的库函数,如libsndfile库、PortAudio库等。

其中,libsndfile 库提供了一些用于读取和写入各种音频文件格式的函数,而PortAudio 库则支持音频的实时输入和输出。

二、音频格式的转换与处理在音频处理中,经常需要对音频进行格式的转换和处理。

C语言中可以使用开源的库,例如libavcodec库、libsox库等来实现音频格式的转换与处理。

这些库提供了丰富的函数和接口,方便我们进行音频数据的采样率转换、音频编码格式的转换、音频通道数的转换以及音频数据的剪切、合并、混音等处理操作。

三、音频信号的分析与处理音频信号的分析与处理是音频编程中的核心内容之一。

C语言提供了丰富的数学计算函数和库,可以用于音频信号的分析与处理。

常见的音频信号处理算法包括快速傅里叶变换(FFT)、数字滤波器设计、降噪、增益调整、均衡器调节等。

我们可以使用C语言中的库函数,如math.h库和dsp.h库等,来实现这些算法,并进行音频信号的频谱分析、时域分析、调音等操作。

四、性能优化与并行处理在大规模的音频处理中,性能优化和并行处理是非常关键的问题。

C语言提供了一些优化功能,如编译器优化选项、循环展开、多线程等机制,可以提高音频处理的效率。

我们可以使用适当的编译器优化选项来加快程序的运行速度,使用多线程或进程来并行处理多个音频任务,以提高整体的处理能力。

总结:C语言在音频编程中具备强大的功能和灵活性。

C语言音频识别音频特征提取和语音识别的方法

C语言音频识别音频特征提取和语音识别的方法

C语言音频识别音频特征提取和语音识别的方法C语言是一种广泛应用于计算机编程的程序设计语言,其功能强大且灵活。

在音频处理领域,C语言也被广泛用于音频特征提取和语音识别。

本文将介绍C语言中实现音频识别的方法,包括音频特征提取和语音识别。

一、音频特征提取音频特征提取是音频识别的重要一步,它将原始音频数据转换为数值特征,以供后续的语音识别算法使用。

以下是几种常用的音频特征提取方法:1. 傅里叶变换(Fourier Transform):傅里叶变换可以将时域信号转换为频域信号,通过分析不同频率的分量来提取音频特征。

在C语言中,可以使用FFT算法实现傅里叶变换。

2. 短时傅里叶变换(Short-Time Fourier Transform,STFT):STFT 是一种将音频信号分割为小片段来进行频谱分析的方法。

通过对每个时间段应用傅里叶变换,可以得到时频谱图。

C语言中可以使用窗函数来实现STFT算法。

3. Mel频率倒谱系数(Mel Frequency Cepstral Coefficients,MFCC):MFCC是一种用于音频和语音识别的特征表示方法。

它首先将音频信号应用STFT,然后对每个频率带的能量进行取对数并进行离散余弦变换,最后选择得分最高的几个系数作为特征向量。

二、语音识别在得到音频数据的特征向量后,可以使用各种机器学习算法来进行语音识别。

以下是几种常用的语音识别方法:1. 隐马尔可夫模型(Hidden Markov Model,HMM):HMM是一种常用的语音识别算法,它将语音信号视为一系列状态的序列,并通过观察发射概率和状态转移概率来计算最可能的状态序列。

在C语言中,可以使用HMM库来实现HMM算法。

2. 高斯混合模型(Gaussian Mixture Model,GMM):GMM是另一种用于语音识别的统计建模方法,它假设每个状态的概率密度函数由多个高斯分布组成。

通过最大似然估计,可以得到每个状态的高斯参数。

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

MP3歌词lrc文件读取算法 C语言源程序
凡是标签,且被冒号分隔的两部分都为非负数,则应认为是时间标签。因此,对于非标 准形式(非“[mm:ss]”)的时间标签也应能识别(如“[0:0]”)。凡是标签,且非时间标 签的,应认为是标识标签。标识名中大小写等价。
·为了向后兼容,应对未定义的新标签作忽略处理。另应对注释标签([:])后的同一行内 容作忽略处理。 应允许一行中存在多个标签,并能正确处理。应能正确处理未排序的标签。
Lrc 歌词文本中含有两类标签:
一是标识标签,其格式为“[标识名:值]”主要包含以下预定义的标签: [ar:歌手名]、[ti:歌曲名]、[al:专辑名]、[by:编辑者(指 lrc 歌词的制作人)]、[offset: 时间补偿值] (其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢 的,但多数的 MP3 可能不会支持这种标签)。
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) {

C读取MP3头部和尾部信息的代码

C读取MP3头部和尾部信息的代码

C读取MP3头部和尾部信息的代码Mp3的文件头长10字节.主要保存ID3、ID3版本和副版本信息,以及Flag和帧长的信息。

Mp3尾部128字节大小的空间中包含了Header(尾部头,4字节),Title(歌曲名称,30字节),Artilst(艺术家30字节),Album(专辑,30字节),Year(发行年份,4字节),Comment (评论,30字节),Conre(?,1字节)需要使用的函数 fseek() fread()代码如下:/*Alias 2008-09-20*/#include <stdio.h>FILE *fp;// Tag_header__Startstruct Tag_header{char Header[3]; // It must be 'ID3'char ver; // The version of ID3char ReVer; // the subversion of ID3char Flag;char Size[4];};// Tag_header__End// Tag_Trailer__Startstruct Tag_Trailer{char Header[3];char Title[30];char Artist[30];char Album[30];char Year[4];char Comment[30];char Cenre[1];};// Tag_GetTrailer__Endstruct Tag_header Mp3Header; struct Tag_Trailer Mp3Trailer;main(){// 01.mp3是我测试时用的MP3的名称fp = fopen("01.mp3","r+");if(fp == NULL){printf("No such file");}else{Tag_GetHeader();Tag_GetTrailer();}printf("\n%s\n",Mp3Trailer.Title); printf("%s\n",Mp3Trailer.Artist); printf("%s\n",Mp3Trailer.Album); printf("%s\n",Mp3Trailer.Year); printf("%s\n",ment); fclose(fp);}void Tag_GetTrailer(){// Get Headerfseek(fp,-128,SEEK_END);fread(Mp3Trailer.Header,3,1,fp);// Get Titlefseek(fp,-125,SEEK_END);fread(Mp3Trailer.Title,30,1,fp);// Get Artistfseek(fp,-95,SEEK_END);fread(Mp3Trailer.Artist,30,1,fp);// Get Albumfseek(fp,-65,SEEK_END);fread(Mp3Trailer.Album,30,1,fp);// Get Yearfseek(fp,-35,SEEK_END);fread(Mp3Trailer.Year,4,1,fp);// Get Commentfseek(fp,-31,SEEK_END);fread(ment,30,1,fp); // Get Cenrefseek(fp,-1,SEEK_END);fread(Mp3Trailer.Cenre,1,1,fp);}void Tag_GetHeader(){// Get ID3 Tagfseek(fp,0,SEEK_SET);fread(Mp3Header.Header,sizeof(Mp3Header.Header),1,fp); // Get ID3 Versionfseek(fp,3,SEEK_CUR);fread(Mp3Header.ver,sizeof(Mp3Header.ver),1,fp);// Get ID3 Revisionfseek(fp,4,SEEK_CUR);fread(Mp3Header.ReVer,sizeof(Mp3Header.ReVer),1,fp);// Get ID3 Flagfseek(fp,5,SEEK_CUR);fread(Mp3Header.Flag,sizeof(Mp3Header.Flag),1,fp);// Get ID3 Sizefseek(fp,6,SEEK_CUR);fread(Mp3Header.Size,sizeof(Mp3Header.Size),1,fp);}。

Android mp3歌词解析源码

Android mp3歌词解析源码

public class LrcProcessor {public ArrayList<ArrayList> process(InputStream inputStream) { //创建两个列表,一个存时间,一个存歌词,加入和读取列表时两个需要同步操作,否则显示混乱//存放时间点数据ArrayList<Integer> timeMills = new ArrayList<Integer>();//存放时间点所对应的歌词ArrayList<String> messages = new ArrayList<String>();//暂存时间点数据,因为有的一行有多个时间,需要先提取所有时间,最后提取歌词ArrayList<Integer> timeTemp = new ArrayList<Integer>();//创建列表ArrayList<ArrayList> lists = new ArrayList<ArrayList>();try {//创建BufferedReader对象InputStreamReader inputReader = newInputStreamReader(inputStream);BufferedReader bufferedReader = newBufferedReader(inputReader);String temp = null;//行数int line = 0;//每一行存在的时间点个数int count = 0;//创建一个正则表达式对象用来匹配“[00:00.00]/[00:00:00]/[00:00]”Pattern p =pile("\\[\\s*[0-9]{1,2}\\s*:\\s*[0-5][0-9]\\s*[\\.:]?\\s*[ 0-9]?[0-9]?\\s*\\]"); //("\\[([^\\]]+)\\]");String result = null;String msg = null;boolean b = true;//一行一行读取while ((temp = bufferedReader.readLine()) != null) {line++;//计算前清零count = 0;//清除暂存列表timeTemp.clear();//对一行进行匹配Matcher m = p.matcher(temp);//如果匹配到字段处理while(m.find()) {count++;//获取匹配到的字段String timeStr = m.group();//根据匹配到的字段计算出时间int timeMill = time2ms(timeStr.substring(1,timeStr.length() - 1));//加入列表timeTemp.add(timeMill);}//如果存在时间点数据if(count > 0){//按从小到大顺序插入时间点数据for(int j = 0; j < timeTemp.size(); j++){//如果列表为空,直接添加if(timeMills.size() == 0){//时间点数据添加到时间列表timeMills.add(timeTemp.get(j));//截取歌词字符串//第一样多一个“]”需特殊处理if(line == 1){msg = temp.substring(10 * count + 1);}else{msg = temp.substring(10 * count);}result = "" + msg;//添加到歌词列表messages.add(result);}//如果时间大于列表中最后一个时间,直接添加到结尾else if(timeTemp.get(j) >timeMills.get(timeMills.size() - 1)){timeMills.add(timeTemp.get(j));if(line == 1){msg = temp.substring(10 * count + 1);}else{msg = temp.substring(10 * count);}result = "" + msg;messages.add(result);}//否则按大小顺序插入else {for(int index = 0; index < timeMills.size();index++){if(timeTemp.get(j) <=timeMills.get(index)){timeMills.add(index, timeTemp.get(j));if(line == 1){msg = temp.substring(10 * count + 1);}else{msg = temp.substring(10 * count);}result = "" + msg;messages.add(index, result);break;}}}}}}//把两个列表加入到同一个列表里lists.add(timeMills);lists.add(messages);} catch (Exception e) {e.printStackTrace();}//返回列表return lists;}/*** 将分钟,秒全部转换成毫秒* @param timeStr* @return*/public int time2ms(String timeStr) {String s[] = timeStr.split(":");int min = Integer.parseInt(s[0]);int sec = 0;int mill = 0;//LRC文件支持三种不同的时间格式//mm:ss.ms//mm:ss:ms//mm:ss//如果格式为mm:ss:msif(s.length > 2){sec = Integer.parseInt(s[1]);mill = Integer.parseInt(s[2]);}else{String ss[] = s[1].split("\\.");//如果格式为mm:ss.msif(ss.length > 1){sec = Integer.parseInt(ss[0]);mill = Integer.parseInt(ss[1]);}//如果格式为mm:sselse{sec = Integer.parseInt(ss[0]);mill = 0;}}return min * 60 * 1000 + sec * 1000 + mill * 10;}}。

C++获取MP3文件信息

C++获取MP3文件信息

获取MP3信息C++源代码使用C++语言获取mp3歌曲的ID3V2文件头,mp3帧信息,和ID3V1文件尾信息。

功能不完全,只是读取mp3的信息,没有别的功能。

//1. MP3Info.h///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /////////////////////// Copy right (C) 2002, Roman Nurik///////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ///////////#ifndef __MP3INFO_H_#define __MP3INFO_H_//#include <AFXTEMPL.H>#include <VECTOR>///////////////////////////////////////////////////////////////////// /////// ID3V2.3///////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /////// 标签头// 在文件的首部顺序记录10 个字节的ID3V2.3 的头部。

MPC LRC歌词播放源码

MPC LRC歌词播放源码
LrcSet(0);
}
else
return -1;
dtxt("停止");
return 0;
}
void IsBegin(int data) ห้องสมุดไป่ตู้
{
if(LrcHead!=NULL)
{
LrcState=LRC_PLAY;
}
LrcNow=P;
}
LrcResume();
}
}
void LrcLoading(int data)
{
char line[255], *ptr=line, *endline;
int32 is_over=FALSE, linelen;
LrcTemp=LrcFileBuf;
LrcFree();
timerstart(LrcTimer.h1, 10, 0, "LrcLoading", 1); //歌词处理
close(fp);
}
else
return -1;
LrcNow=LrcHead;
timerstart(LrcTimer.h2, 50, 0, "LrcCurCB", 1);
}
}
void LrcCurCB(int data)
{
i=CurTimems()/100;
if(LrcNow->time <= i)
typedef struct
{
int32 h1;
int32 h2;
int32 h3;
} lrctimerst;
lrctimerst LrcTimer; //Lrc处理定时器

C++类编写音乐播放器(mp3文件遍历部分)

C++类编写音乐播放器(mp3文件遍历部分)
WIN32_FIND_DATA p;
HANDLE h=FindFirstFile(temp,&p);//使用这个函数可以选定第一个查找到的文件
puts(p.cFileName);//可能是输出查找到的相关文件
fstream fp;
fp.open(strcat(a,p.cFileName),ios::in|ios::ew Mp3file[1];
int l;
char tuozhanming[10]="*.mp3";
l=strlen(a)+strlen(tuozhanming);
char *temp;
temp=new char[l];
sprintf(temp,"%s%s",a,tuozhanming);
cin>>address;
m1.addmanymp3(address);
}
#include<iostream.h>
#include<stdlib.h>
#include<windows.h>
#include <mmsystem.h>
#include<string>
#include<time.h>
#include<fstream.h>
#include<stdio.h>
#pragma comment (lib, "winmm.lib")
fp.seekg(-128L, ios::end);
fp.read(p2->TAG,4);//标签头
fp.read(p2->title,31);//歌名
  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 歌词命为相同的文件名放在同一目录下,用带显示歌词功能的播放器 播放歌曲时歌词就可以同步显示显示,方便查看和学歌。
相关文档
最新文档