#include "LyricParser.h" #include "sys_config.h" #include #include #include #include #include #include #define ENABLE_PRINT_INFO 1 #define ENABLE_DEBUG 1 #if ENABLE_PRINT_INFO #define static_print_info(...) sys_ui_log_i(__VA_ARGS__) // 一般信息打印宏控制 #define static_print_warn(...) sys_ui_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_ui_log_e(__VA_ARGS__) // 错误信息打印一般常开 #if ENABLE_DEBUG #define static_print_debug(...) sys_ui_log_d(__VA_ARGS__) // 调试信息打印一般常开 #else #define static_print_debug(...) #endif #else #define static_print_info(...) #define static_print_warn(...) #define static_print_error(...) #endif // clang-format off static const std::string MetaData[7][2] = { {"ti", "title"}, {"al", "album"}, {"ar", "artist"}, {"au", "author"}, {"by", "creator"}, {"re", "encoder"}, {"ve", "encoder_version"} }; // clang-format on bool LrcParser::parseLrc(const std::string &lrcFile) { currentIndex_ = 0; lrcData_.clear(); lyrics_.clear(); std::ifstream fin; fin.open(lrcFile, std::ios_base::in); if (!fin.is_open()) { static_print_error("LRC Can't open file %s", lrcFile.c_str()); return false; } std::stringstream buffer; buffer << fin.rdbuf(); lrcData_ = buffer.str(); fin.close(); if (lrcData_.empty()) { static_print_error("LRC file is empty"); return false; } // 先读取头部 size_t index = parseHeader(); if (index == lrcData_.length()) { static_print_error("No lyrics_ text"); return false; } lrcData_.erase(0, index); std::string line = readLine(); while (!line.empty()) { parseLine(line); line = readLine(); } duration_ = (--lyrics_.end())->first; readIndex_ = lyrics_.begin(); return true; } LyricPacket LrcParser::readPacket() { LyricPacket packet; if (readIndex_ != lyrics_.end()) { packet.pts = readIndex_->first; packet.lyric = readIndex_->second; readIndex_++; } return packet; } bool LrcParser::seek(int64_t timestamp) { auto end = --lyrics_.end(); for (readIndex_ = lyrics_.begin(); readIndex_ != end; readIndex_++) { if (readIndex_->first > timestamp) { if (readIndex_ != lyrics_.begin()) { readIndex_--; } return true; } } return false; } int64_t LrcParser::duration() const { return duration_; } size_t LrcParser::parseHeader() { size_t offset = 0; size_t length = lrcData_.length(); if (offset >= length) return offset; while (offset < length) { std::string meta, data; if (lrcData_.at(offset) == '[') { while (++offset < length && lrcData_.at(offset) != ':') { if (lrcData_.at(offset) >= 'a' && lrcData_.at(offset) <= 'z') meta += lrcData_.at(offset); else return offset - 1; } while (++offset < length && lrcData_.at(offset) != ']') { data += lrcData_.at(offset); } } offset++; } return offset; } void LrcParser::parseLine(const std::string &line) { std::regex pattern("\\[(\\d+):(\\d+).(\\d+)\\](.*)"); std::smatch matches; if (std::regex_search(line, matches, pattern)) { int64_t minute = std::stoi(matches[1].str()) * 60 * 1000; int64_t second = std::stoi(matches[2].str()) * 1000; int64_t millisecond = matches[3].str().length() == 3 ? std::stoi(matches[3].str()) : std::stoi(matches[3].str()) * 10; int64_t pts = minute + second + millisecond; std::string data = matches[4].str(); lyrics_[pts] = data; } } std::string LrcParser::readLine() { size_t length = lrcData_.length(); std::string line; while (currentIndex_ < length) { if (lrcData_.at(currentIndex_) == '\n') { currentIndex_++; break; } else { line += lrcData_.at(currentIndex_); currentIndex_++; } } return line; }