c/c++语言开发共享Ubuntu下实现歌词解析

我们要明确目的,实现歌曲歌词同步。 1.将歌词文件一次性去取到内存中。(以周董的“简单爱”为例) a.用fopen打开歌词文件 FILE *fp = fopen(“简单爱.lrc”,"r");(r->只读) b.使用fseek将文件流指针,要定位到文件尾部,ftell或得文件总大小; c.使用rew …

我们要明确目的,实现歌曲歌词同步。

1.将歌词文件一次性去取到内存中。(以周董的“简单爱”为例)

a.用fopen打开歌词文件 file *fp  = fopen(“简单爱.lrc”,”r”);(r->只读)

b.使用fseek将文件流指针,要定位到文件尾部,ftell或得文件总大小;

c.使用rewind 复位文件流指针;

d.根据文件总大小从堆区申请合适的空间;

e.使用fread读取文件%ignore_a_1%到内存中;

 

2.将arr指向的内存数据,按行“rn”切割,并存入字符指针数组 char *buf[128] = {null};

1 strtok函数切割 2 //arr指向内存存储的歌词 3 char *buf[128]={arr,null}; 4 int i=0; 5 //切割 6 while(buf[i++] = strtok(buf[i],"rn"));

已将歌词的每一行 存放 在 指针数组中 注意 记得保存 切割到的行数

3.逐行分析buf[0]代表第0行,buf[n]代表第n行

a.先单独分析前四行

原数据

[ti:简单爱] [ar:周杰伦] [al:范特西] [by:大脸猫]

要得到的结果:

Ubuntu下实现歌词解析

 

 

 

1 int i=0; 2 for(i=0;i<4;i++) 3 { 4     char tmp[128]=""; 5     //[ti:简单爱]  -->sscanf(buf[0],"%*[^:]:%[^]]", tmp);//tmp--简单 6     buf[i];//分析 7 }

b、逐行分析剩下的行 将时间+歌词 一一对应 插入链表

链表节点的设计

1 typedef struct lrc 2 { 3      //数据域 4      int time; 5      char lrc[128]; 6       7      //指针域 8      struct lrc *next;  9 }lrc;    

4.模拟计时器 i++

计时器每走一秒,都会对链表中成员域(time)进行比较,时间相等,则输出成员域歌词(lrc_sentence)

5、滚屏(4行)

//光标定位:(注意)

6、反显 当前歌词为 红色 其他歌词为黑色

7、启动mplayer

 6和7步骤都可以直接调用别人的api接口,现在我贴出代码,只可意会不可言传~~~细品

main.c

 1 #include "lrc.h"  2 #include "console.h"  3 #include "start_mplayer.h"  4 #include <unistd.h>  5   6 int main(int argc, char *argv[])  7 {  8     char *lrc_condent = null;  9     lrc *head = null; 10     char *arr[128]={lrc_condent,null}; 11     int i = 0; 12      13     lrc_condent = read_song_lrc("./lrc/简单爱.lrc"); 14     //printf("%s",lrc_condent); 15     arr[0] = lrc_condent; 16     //切割每一行 17     while(arr[i++] = strtok(arr[i],"rn")); 18  19     head = lrc_handle(arr, head); 20  21      22     mplayer_play("./song/love.mp3"); 23     lrc_print(head); 24      25      26     return 0; 27 }

lrc.c

  1 #include<stdlib.h>   2 #include <unistd.h>   3 #include "lrc.h"   4 #include"console.h"   5 lrc *lrc_create_head()   6 {   7     lrc *head = (lrc*)calloc(1, sizeof(lrc));   8     head->next = null;   9     return head;  10 }  11 //取出歌词  12 char *read_song_lrc(char *lrc_name)  13 {  14     file *fp = fopen(lrc_name,"r");  15     char *lrc_content = null;  16     unsigned long int length;  17     if(fp == null)  18     {  19         perror("fopen");  20         return null;  21     }  22   23     fseek(fp,0,2);  24     length = ftell(fp);  25     rewind(fp);  26     lrc_content = (char *)calloc(1,length);  27     if (lrc_content == null)  28     {  29         perror("calloc");  30         return null;  31     }  32   33     fread(lrc_content,length,1,fp);  34     fclose(fp);  35   36     return lrc_content;  37 }  38 //分割歌词  39 void lrc_strtok(char *lrc_condent)  40 {  41     char *arr[128]={lrc_condent,null};  42     int i = 0;  43   44     while((arr[i++] = strtok(arr[i],"rn")));  45     i= 0;  46     while(arr[i] != null)  47         printf("%sn", arr[i++]);  48 }  49 //顺序插入  50 lrc * lrc_insert(lrc *head, lrc tmp)  51 {  52     //1、给待插入的节点pi 申请 堆区空间  53     lrc *pi = (lrc *)calloc(1,sizeof(lrc));  54     if(pi == null)  55     {  56         perror("calloc");  57         return head;  58     }  59   60     //2、将tmp的内容 赋值给 *pi  61     *pi = tmp;  62     pi->next = null;  63   64     //3、链表节点pi的插入  65     if(head == null)//链表不存在  66     {  67         head = pi;  68         return head;  69     }  70     else//存在  71     {  72         //a、寻找插入点  73         lrc *pb = head, *pf = head;  74         while(pb->time < pi->time && pb->next != null)  75         {  76             pf = pb;  77             pb = pb->next;  78         }  79   80         //b、插入点的判断  81         if(pb->time >= pi->time)//头部 中部插入  82         {  83             if(pb == head)//头部之前插入  84             {  85                 pi->next = head;  86                 head = pi;  87                 return head;  88             }  89             else//中部插入  90             {  91                 pf->next = pi;  92                 pi->next = pb;  93                 return head;  94             }  95         }  96         else//尾部插入  97         {  98             pb->next = pi;  99             return head; 100         } 101     } 102     return head; 103 } 104 //处理歌词 105 lrc * lrc_handle(char *buf[128], lrc *head) 106 { 107     int i = 0; 108     //开头的歌手,编曲等字符串 109     char *song_infor[] = {"ti", "ar", "al", "by"}; 110      111     system("clear"); 112     while(buf[i] != null) 113     { 114         char flag = 0; 115         sscanf(buf[i],"%*c%c", &flag); 116         if(flag >= '0' && flag <= '9')//除了前四行 117         { 118             char *str_lrc = buf[i], *str_time = buf[i]; 119             //每遇到"["判断是否这句歌词出现的次数 120             while(*str_lrc == '[') 121                 str_lrc += 10; 122  123             124             while(*str_time == '[') 125             { 126                 lrc temp; 127                 int minute = 0, second = 0, ms = 0; 128                 //取出每个节点的时分秒 129                 sscanf(str_time, "[%d:%d.%d]", &minute, &second, &ms); 130                 //统一单位到ms 131                 temp.time = minute * 60 + second + ((ms > 50)?1:0);//ms用四舍五入 132                  //把歌词内容赋值到该次链表的lrc_sentence 133                 strcpy(temp.lrc_sentence, str_lrc); 134                 //循环把时间插入链表节点 135                 head = lrc_insert(head, temp); 136                 str_time += 10; 137             } 138         } 139  140         else 141         { 142             //拆分前四行的,拿到歌曲名等 143              144             char tmp[128]=""; 145             sscanf(buf[i], "%*[^:]:%[^]]", tmp); 146             if(i==0) 147             { 148                 cusor_moveto(17,1); 149                 printf("%sn", tmp); 150             } 151             else if(i==1) 152             { 153                 cusor_moveto(17,2); 154                 printf("%sn", tmp); 155             } 156             else if(i==2) 157             { 158                 cusor_moveto(17,3); 159                 printf("%sn", tmp); 160             } 161             else if(i==3) 162             { 163                 cusor_moveto(17,4); 164                 printf("%sn", tmp); 165             } 166         } 167         i++; 168     } 169  170     return head; 171 } 172 //歌词滚屏 173 int times = 0; 174 int screen = 0; 175  176 lrc* lrc_print(lrc *head) 177 { 178     int time=0; 179     char buf1[128]=""; 180     char buf2[128]=""; 181     char buf3[128]=""; 182     char buf4[128]=""; 183     while(1) 184     { 185         //光标定位 186         cusor_moveto(20,6); 187         printf("%02d:%02d",time/60,time%60 ); 188         fflush(stdout); 189  190         lrc *ret = search_link(head, time); 191         if(ret != null) 192         { 193             //滚起来 194             strcpy(buf1,buf2); 195             strcpy(buf2,buf3); 196             strcpy(buf3,buf4); 197             strcpy(buf4, ret->lrc_sentence); 198              199             cusor_moveto(15,8); 200             printf("%s                                       ", buf1); 201  202             cusor_moveto(15,9); 203             printf("%s                                      ", buf2); 204  205             cusor_moveto(15,10); 206             printf("%s                                           ", buf3); 207  208             cusor_moveto(15,11); 209             set_fg_color(color_red); 210             printf("%s                                         ", buf4);//当前歌词 211             set_fg_color(color_black  ); 212             fflush(stdout); 213         } 214         //滚屏显示歌词 215         //第一行 216          217  218         sleep(1); 219         time++; 220     } 221      222 } 223  224 lrc* search_link(lrc *head, int time) 225 { 226     //1、判断链表是否存在 227     if(head == null)//不存在 228     { 229         printf("link not foundn"); 230         return null; 231     } 232     else//链表存在 233     { 234         lrc *pb = head; 235  236         //逐个将节点中的name 和 name比较 如果不相等 pb=pb->next 237         while(pb->time != time && pb->next != null) 238             pb = pb->next; 239  240         //判断是否找到 241         if(pb->time == time)//找到 242             return pb; 243         else//没找到 244             return null; 245     } 246  247     return null; 248 } 249  250 void mplayer_play(char * song_path) 251 { 252     pid_t pid; 253     pid=fork(); 254     if(pid<0) 255     { 256         perror("fork"); 257     } 258     else if(pid==0) 259     { 260         close(1); 261         close(2); 262         execlp("mplayer","mplayer","-slave","-quiet",song_path,null); 263         exit(0); 264     } 265     else; 266 }

lrc.h

 1 #ifndef __lrc_h__  2 #define __lrc_h__  3   4 #include <stdio.h>  5 #include <stdlib.h>  6 #include <string.h>  7   8 typedef struct lrc  9 { 10     int time; 11     char lrc_sentence[128]; 12      13     struct lrc *next; 14 }lrc; 15 //创造链表头 16 lrc *lrc_create_head(void); 17 //顺序插入 18 lrc * lrc_insert(lrc *head, lrc tmp); 19 //读取歌词 20 char *read_song_lrc(char *lrc_name); 21 //切割歌词 22 void lrc_strtok(char *lrc_condent); 23 //处理歌词 24 lrc * lrc_handle(char *buf[128], lrc *head); 25 //遍历歌词 26 lrc* lrc_print(lrc *head); 27 extern lrc* search_link(lrc *head, int time); 28 void mplayer_play(char * song_path); 29  30 #endif

———————-好的,我的第一阶段项目总结完了,写的不好,还请见谅———————-

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/c-cdevelopment/600155.html

(0)
上一篇 2021年5月9日
下一篇 2021年5月9日

精彩推荐