歌词文件lrc的解析类(目前在WINCE下使用)
2010-04-29 10:06
423 查看
用到歌词显示就写了一个歌词解析类,与大家共同分享。
贴出头文件:
贴出源文件:
贴出头文件:
/******************************************************************** created: 2009/10/30 created: 30:10:2009 10:17 filename: f:/工作_ZWF(090511)/TCC89X/PT4321/mylrcfile/BnvLrcHanderW.h file path: f:/工作_ZWF(090511)/TCC89X/PT4321/mylrcfile file base: BnvLrcHander file ext: h author: zhangwf purpose: 从原先代码中提取出歌词分析读取的类,使得结构更加清晰,便于 以后的修改与维护 修改: 修改为支持UNICODE格式的 使用方法: 1、设置歌词路径名SetFilePathName,或者设置音乐文件路径名(默认为歌词和歌曲同目录且名字相同) 2、根据当前播放时间值通过GetLyricLineItem接口获得当前需要显示的歌词项 3、如果还需要显示该行前的或后的行的歌词,则可以通过上述函数带出的索引值index, 向前或向后通过GetLyricLineItem函数获取歌词项,来显示。 4、当然也可以通过GetLyricLineCounts获取所有歌词项,通过GetLyricLineItem获取每一项进行比较显示歌词。 *********************************************************************/ #ifndef _BNV_LRC_HANDER_W_H_ #define _BNV_LRC_HANDER_W_H_ ////////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <algorithm> #include <string> #include <vector> using namespace std; ////////////////////////////////////////////////////////////////////////// // 定义歌词中的一项结构 typedef struct _LRC_ITEM_ { wstring Time; wstring Context; }LRCITEM; ////////////////////////////////////////////////////////////////////////// class BnvLrcHanderW { public: // 接口函数 // 设置音乐文件路径名(默认为歌词与歌曲同名且在同一个路径下) BOOL SetMusicFilePathName(const wchar_t *filePathName); // 设置歌词文件路径名 BOOL SetLrcFilePathName(const wchar_t *filePathName); // 得到歌词行数 int GetLyricLineCounts(); // 得到具体行的歌词项,lineIndex从0开始(歌词已经按时间由小到大排列) BOOL GetLyricLineItem(LRCITEM &lineItem, int lineIndex); // 根据时间值得到歌词项(时间格式分钟、秒、毫秒) BOOL GetLyricLineItem(LRCITEM &lineItem, int *itemIndex, int minutes, int seconds=0, int millisecond=0); // playTime的格式必须为mm:ss.fff,也就是(分钟:秒.毫秒) BOOL GetLyricLineItem(LRCITEM &lineItem, int *itemIndex, wstring playTime); // 是否得到歌词信息 BOOL GetLrcSuccess(); // 得到歌曲的其他信息 wstring GetArtist(); wstring GetTitle(); wstring GetAlbum(); wstring GetByBody(); int GetTimeOffset(); // 时间偏移值暂时没有使用 public: BnvLrcHanderW(); ~BnvLrcHanderW(); private: // 私有函数 // 解析歌词文件 BOOL PerseLrcFile(const wchar_t *filePathName); // 清空上次记录 void ClearLrcInfo(); // 操作列表的函数 void AddToList(const LRCITEM &curLrcItem); void ClearList(); int GetListSize(); // 清除一项里的内容 void ClearLrcItem(LRCITEM &curItem); private: wstring m_strArtist; // [ar:艺人名] wstring m_strTitle; // [ti:曲名] wstring m_strAlbum; // [al:专辑名] wstring m_strByBody; // [by:编辑者] int m_nOffset; // [offset:时间补偿值]其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的 // 定义存放解析到歌词的列表 vector<LRCITEM> m_LyricList; BOOL m_blHaveLrc; // 记录是否加载到歌词文件 }; ////////////////////////////////////////////////////////////////////////// #endif
贴出源文件:
/******************************************************************** created: 2009/10/30 created: 30:10:2009 10:17 filename: f:/工作_ZWF(090511)/TCC89X/PT4321/mylrcfile/BnvLrcHanderWW.cpp file path: f:/工作_ZWF(090511)/TCC89X/PT4321/mylrcfile file base: BnvLrcHanderW file ext: cpp author: zhangwf purpose: 从原先代码中提取出歌词分析读取的类,使得结构更加清晰,便于 以后的修改与维护 修改: 修改为支持UNICODE格式的 *********************************************************************/ #include "BnvLrcHanderW.h" #include <Windows.h> ////////////////////////////////////////////////////////////////////////// bool MinFirstW(LRCITEM a, LRCITEM b) //比较大小 { return a.Time < b.Time; } ////////////////////////////////////////////////////////////////////////// BnvLrcHanderW::BnvLrcHanderW() { // 初始化 ClearLrcInfo(); } BnvLrcHanderW::~BnvLrcHanderW() { // 清除内容 ClearLrcInfo(); } ////////////////////////////////////////////////////////////////////////// BOOL BnvLrcHanderW::PerseLrcFile(const wchar_t *filePathName) { // 清空上次数据 ClearLrcInfo(); // 参数有效性 if (filePathName == NULL) { return FALSE; } // 打开歌词文件失败 wfstream filestr; filestr.open(filePathName, ios_base::in); if (!filestr.is_open()) { return FALSE; } // 分析歌词文件 wstring lineData = L""; // 读取一行的内容 wstring itemContext = L""; // 该行的歌词内容 wstring tagInfo = L""; // 【】标签中的内容 size_t preTag; // 找到【的位置 size_t endTag; // 找到】的位置 size_t pointPos; // 找到:的位置 LRCITEM lineItem; // 得到该行的歌词信息 while (!filestr.eof()) { // 读取一行 lineData = L""; getline(filestr, lineData); // 查找‘]’,一行标签中可以含有过个时间标签 while (lineData.find(L"]") != wstring::npos) { // 从最后找"]",此后就是歌词内容了 endTag = lineData.rfind(L"]", wstring::npos); itemContext = lineData.substr(endTag+1); // 从开始找"["和"]",确定标签中的信息 preTag = lineData.find(L"["); endTag = lineData.find(L"]"); tagInfo = lineData.substr(preTag+1, endTag-preTag-1); // 改变该行的值向后查找 lineData = lineData.substr(endTag+1); // 分析标签内容 if (tagInfo.find(L"al:") != wstring::npos) { pointPos = tagInfo.find(L":"); m_strAlbum = tagInfo.substr(pointPos+1); } else if(tagInfo.find(L"ar:") != wstring::npos) { pointPos = tagInfo.find(L":"); m_strArtist = tagInfo.substr(pointPos+1); } else if(tagInfo.find(L"ti:") != wstring::npos) { pointPos = tagInfo.find(L":"); m_strTitle = tagInfo.substr(pointPos+1); } else if (tagInfo.find(L"by:") != wstring::npos) { pointPos = tagInfo.find(L":"); m_strByBody = tagInfo.substr(pointPos+1); } else if (tagInfo.find(L"offset:") != wstring::npos) { pointPos = tagInfo.find(L":"); m_nOffset = _wtol(tagInfo.substr(pointPos+1).c_str()); } // 是时间标签,添加歌词到列表 else { lineItem.Time = tagInfo; lineItem.Context = itemContext; AddToList(lineItem); } } } // 关闭文件并排序 filestr.close(); sort(m_LyricList.begin(), m_LyricList.end(), MinFirstW); m_blHaveLrc = TRUE; // 加载到歌词 return TRUE; } // 清空上次记录 void BnvLrcHanderW::ClearLrcInfo() { m_blHaveLrc = FALSE; // 没有歌词 // 清空list内容 ClearList(); // 清空其他内容 m_strArtist = L""; m_strTitle = L""; m_strByBody = L""; m_strAlbum = L""; m_nOffset = 0; } // 添加一项到列表中 void BnvLrcHanderW::AddToList(const LRCITEM &curLrcItem) { m_LyricList.push_back(curLrcItem); } // 清空列表内容 void BnvLrcHanderW::ClearList() { m_LyricList.clear(); while (!m_LyricList.empty()) { m_LyricList.pop_back(); } } // 获得列表项的数量 int BnvLrcHanderW::GetListSize() { return (int)m_LyricList.size(); } // 清除一项里的内容 void BnvLrcHanderW::ClearLrcItem(LRCITEM &curItem) { curItem.Time = L""; curItem.Context = L""; } ////////////////////////////////////////////////////////////////////////// // 接口函数 BOOL BnvLrcHanderW::SetLrcFilePathName(const wchar_t *filePathName) { return PerseLrcFile(filePathName); } // 设置音乐文件路径名(默认为歌词与歌曲同名且在同一个路径下) BOOL BnvLrcHanderW::SetMusicFilePathName(const wchar_t *filePathName) { // 清除上次歌词 ClearLrcInfo(); // 参数有效性 if (filePathName == NULL) { return FALSE; } // 根据音乐文件名获取歌词文件名 wchar_t lrcFilePathName[514]; memset(lrcFilePathName, 0, sizeof(lrcFilePathName)); wsprintf(lrcFilePathName, L"%s", filePathName); // 从后向前找‘.’的位置 int pathLen = wcslen(lrcFilePathName); int dotPos = pathLen-1; while (dotPos >= 0) { if (lrcFilePathName[dotPos] == L'.') { break; } dotPos--; } // 没有找到.的位置 if (dotPos < 0) { return FALSE; } // 路径太长 if (dotPos+4 >= sizeof(lrcFilePathName)) { return FALSE; } // '.'后的位置替换为.lrc lrcFilePathName[dotPos+1] = L'l'; lrcFilePathName[dotPos+2] = L'r'; lrcFilePathName[dotPos+3] = L'c'; lrcFilePathName[dotPos+4] = L'/0'; // 解析歌词文件 return PerseLrcFile(lrcFilePathName); } // 得到歌词行数 int BnvLrcHanderW::GetLyricLineCounts() { return GetListSize(); } // 得到具体行的歌词项,lineIndex从0开始 BOOL BnvLrcHanderW::GetLyricLineItem(LRCITEM &lineItem, int lineIndex) { // 参数有效性 if (lineIndex<0 || lineIndex>=GetListSize()) { return FALSE; } // 得到该项 ClearLrcItem(lineItem); lineItem = m_LyricList.at(lineIndex); return TRUE; } // 得到歌曲的其他信息 wstring BnvLrcHanderW::GetArtist() { return m_strArtist; } wstring BnvLrcHanderW::GetTitle() { return m_strTitle; } wstring BnvLrcHanderW::GetAlbum() { return m_strAlbum; } wstring BnvLrcHanderW::GetByBody() { return m_strByBody; } int BnvLrcHanderW::GetTimeOffset() { return m_nOffset; } /******************************************************************** 函数名:GetLyricLineItem 作者:zhangwf 日期:2009/10/30 功能:根据时间值得到歌词项(时间格式分钟、秒、毫秒) 参数:lineItem 带出歌词项(输出) itemIndex 带出歌词项在列表中的索引(输出) minutes 分钟数 seconds 秒数 millisecond 毫秒数 返回:类型() 修改记录: *********************************************************************/ BOOL BnvLrcHanderW::GetLyricLineItem(LRCITEM &lineItem, int *itemIndex, int minutes, int seconds, int millisecond) { // 参数有效性 if (minutes<0 || seconds<0 || millisecond<0) { return FALSE; } // 清除内容 ClearLrcItem(lineItem); // 得到当前时间字符串 wchar_t curTime[32]; wsprintf(curTime, L"%02d:%02d.%03d", minutes, seconds, millisecond); wstring playTime(L""); playTime.append(curTime); // 取得歌词行数 int itemCounts = GetListSize(); if (itemCounts <= 0) { return FALSE; } // 在除去最后一项中遍历找出当前符合条件的歌词 for (int index=0; index<itemCounts-1; index++) { if (m_LyricList.at(index).Time<=playTime && playTime<m_LyricList.at(index+1).Time) { lineItem = m_LyricList.at(index); if (itemIndex != NULL) { *itemIndex = index; } return TRUE; } } // 没有找到,看最后一项是否要找的歌词 if (m_LyricList.at(itemCounts-1).Time <= playTime) { lineItem = m_LyricList.at(itemCounts-1); if (itemIndex != NULL) { *itemIndex = itemCounts-1; } return TRUE; } // 没有找到合适的 return FALSE; } /******************************************************************** 函数名:GetLyricLineItem 作者:zhangwf 日期:2009/10/30 功能:根据时间获得当前播放的歌词项 参数:lineItem 带出歌词项(输出) itemIndex 带出歌词项在列表中的索引(输出) playTime的格式必须为mm:ss.fff,也就是(分钟:秒.毫秒) 返回:类型() 修改记录: *********************************************************************/ BOOL BnvLrcHanderW::GetLyricLineItem(LRCITEM &lineItem, int *itemIndex, wstring playTime) { // 清除内容 ClearLrcItem(lineItem); // 取得歌词行总数 int itemCounts = GetListSize(); if (itemCounts <= 0) { return FALSE; } // 在除去最后一项中遍历找出当前符合条件的歌词 for (int index=0; index<itemCounts-1; index++) { if (m_LyricList.at(index).Time<=playTime && playTime<m_LyricList.at(index+1).Time) { lineItem = m_LyricList.at(index); if (itemIndex != NULL) { *itemIndex = index; } return TRUE; } } // 没有找到,看最后一项是否要找的歌词 if (m_LyricList.at(itemCounts-1).Time <= playTime) { lineItem = m_LyricList.at(itemCounts-1); if (itemIndex != NULL) { *itemIndex = itemCounts-1; } return TRUE; } // 没有找到合适的 return FALSE; } /******************************************************************** 函数名:GetLrcSuccess 作者:zhangwf 日期:2009/11/02 功能:是否得到歌词信息,在音乐播放界面需要判断是否有歌词信息,否则显示ID3信息 参数: 返回:类型() 修改记录: *********************************************************************/ BOOL BnvLrcHanderW::GetLrcSuccess() { return m_blHaveLrc; }
相关文章推荐
- Java使用正则表达式解析LRC歌词文件
- JavaScript解析lrc文件音乐歌词
- C#解析Lrc歌词文件过程详解
- 使用vim制作lrc歌词文件 [原创]
- JavaScript解析lrc文件音乐歌词
- ios开发学习--歌词处理--解析lrc文件
- c#解析Lrc歌词文件
- JavaScript解析lrc文件音乐歌词
- C语言 LRC歌词文件解析
- C语言 解析lrc歌词文件
- MP3制作之LRC歌词文件解析(附:源代码)
- android开发--mp3播放器项目源代码(xml文件解析,.lrc,.mp3文件下载,同时显示歌词)
- C语言 解析lrc歌词文件
- c#解析Lrc歌词文件
- C语言 解析lrc歌词文件
- C++中使用std::regex提取lrc歌词文件
- 歌词文件LRC的解析,可用于音乐播放器实现歌词同步操作
- 封装的文件操作函数接口(目前使用在WINCE上)
- C语言 解析lrc歌词文件
- JavaScript解析lrc文件音乐歌词