qfedu-c-level/lyric_analysis/srcs/main.c

150 lines
6.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "./includes/lrc.h"
#include "./includes/console.h"
#include "./includes/start_mplayer.h"
#include "includes/time_delay.h"
int main()
{
// 定义歌曲和歌词文件路径
const char *song_path = "./songs/简单爱.mp3";
const char *lrc_path = "./lrcs/简单爱.lrc";
FILE *lrc_fp = open_lrc_file(lrc_path); // 打开歌词文件
long lrc_size = get_lrc_size(lrc_fp); // 获取并打印歌词文件大小
// printf("歌词大小为: %ld Byte\n", lrc_size);
char *lrc_mem_data = get_lrc_mem_data(lrc_fp); // 获取歌词数据
// mplayer_play(song_path);
// 逐行解析歌词
char *lrc_lines[200] = {NULL}; // 定义歌词行指针数组
int i = 0; // 定义歌词行数
lrc_lines[i] = strtok(lrc_mem_data, "\r\n"); // 将歌词数据按行分割
while (lrc_lines[i] != NULL)
{
// 打印歌词
// time_delay(1); // 延时1秒
// printf("%d.\t%s\n", i, lrc_lines[i]); // 打印歌词
i++; // 行数加1
lrc_lines[i] = strtok(NULL, "\r\n"); // 将剩余行歌词数据按行分割
}
// 分析前 4 行歌词
int rows = i; // 获取歌词总行数
clear_screen(); // 清屏
cusor_hide(); // 隐藏光标
for (int i = 0; i < 4; i++)
{
char tmp[200] = ""; // 定义临时字符串
sscanf(lrc_lines[i], "%*[^:]:%[^]]", tmp); // 从歌词行中提取时间信息, "%*[^:]:%[^]]" 表示跳过第一个冒号,然后读取到第一个右中括号为止的内容
switch (i)
{
case 0:
cusor_moveto(25, 2); // 将光标移动到指定位置
printf("歌曲: %s\n", tmp);
break;
case 1:
cusor_moveto(25, 3); // 将光标移动到指定位置
printf("歌手: %s\n", tmp);
break;
case 2:
cusor_moveto(25, 4); // 将光标移动到指定位置
printf("专辑: %s\n", tmp);
break;
case 3:
cusor_moveto(25, 5); // 将光标移动到指定位置
printf("制作: %s\n", tmp);
break;
default:
break;
}
}
// 逐行分析剩下的歌词,将时间、歌词内容保存到链表中
LRC *head = NULL; // 定义歌词链表头指针
for (int i = 4; i < rows; i++)
{
char *str_lrc = lrc_lines[i]; // 获取歌词行
while (*str_lrc == '[') // 每当遇到'['时,就跳过
str_lrc += 10; // 跳过前面的时间标签
char *str_time = lrc_lines[i]; // 获取歌词行
while (*str_time == '[')
{
//秒级计数
int m = 0, s = 0; // 定义分钟和秒数
sscanf(str_time, "[%d:%d.%*d]", &m, &s); // 从歌词行中提取时间信息
int time = m * 60 + s; // 计算歌词时间点
// // 毫秒级计数 (这里有问题,待解决)
// int m = 0, s = 0, ms = 0; // 定义分钟和秒数和毫秒数
// sscanf(str_time, "[%d:%d.%d]", &m, &s, &ms); // 从歌词行中提取时间信息
// int time = (m * 60 + s) * 1000 + ms; // 计算歌词时间点: 毫秒数转换为秒数, 1000ms = 1s
LRC tmp;
tmp.time = time; // 保存歌词时间点
strcpy(tmp.lrc_buf, str_lrc); // 保存歌词内容
tmp.lrc_cur_num = i; // 保存当前歌词行数
head = insert_lrc_node(head, tmp); // 将歌词节点插入到链表中
str_time += 10; // 跳过前面的时间标签
}
}
// 开始播放歌曲
mplayer_play(song_path); // 启动mplayer播放器播放歌曲
// 逐行打印歌词
int t = 0;
// long t = 0; // 用于毫秒级延时
char buf1[200] = "";
char buf2[200] = "";
char buf3[200] = "";
char buf4[200] = "";
while (1)
{
set_fg_color(COLOR_BLUE); // 设置前景颜色为红色
cusor_moveto(29, 7); // 将光标移动到指定位置
printf("%02d:%02d", t / 60, t % 60); // 打印歌曲播放时间
// 打印歌曲播放时间 (毫秒级延时)
// printf("%02d:%02d", t / (60 * 1000), (t / 1000) % 60);
fflush(stdout); // 刷新输出缓冲区,立即输出
LRC *ret = search_lrc_node(head, t); // 查找歌词节点
if (ret != NULL) // 如果找到歌词节点
{
// 用于歌词滚动轮换
strcpy(buf1, buf2); // 将buf2中的内容复制到buf1中
strcpy(buf2, buf3); // 将buf3中的内容复制到buf2中
strcpy(buf3, buf4); // 将buf4中的内容复制到buf3中
strcpy(buf4, ret->lrc_buf); // 将歌词内容复制到buf4中
cusor_moveto(17, 9); // 将光标移动到指定位置
printf("\033[K"); // 清除从光标到行尾的内容
printf("%s", buf1); // 打印歌词内容
cusor_moveto(17, 10); // 将光标移动到指定位置
printf("\033[K"); // 清除从光标到行尾的内容
printf("%s", buf2); // 打印歌词内容
cusor_moveto(17, 11); // 将光标移动到指定位置
printf("\033[K"); // 清除从光标到行尾的内容
printf("%s", buf3); // 打印歌词内容
set_fg_color(COLOR_RED); // 设置红色前景色
cusor_moveto(17, 12); // 将光标移动到指定位置
printf("\033[K"); // 清除从光标到行尾的内容
printf("%s", buf4); // 打印歌词内容
set_fg_color(COLOR_BLUE);
fflush(stdout); // 刷新输出缓冲区,立即输出
}
time_delay(1); // 延时1秒
t++; // 时间加1
// delay_ms(1); // 延时1毫秒 (毫秒级延时)
// t += 1000; // 时间加1 (1毫秒)
}
// 释放内存,关闭文件
free(lrc_mem_data); // 释放歌词数据内存
return 0;
}