diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 87adbea..4954dd4 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -20,7 +20,7 @@ name: License Header Check -# 触发机制:Push 到主干,或者提交 Pull Request 时触发 +# trigger mechanism: on push to main branch or on pull request on: push: branches: [ "main", "master" ] @@ -45,15 +45,15 @@ jobs: - name: Run License Check run: | echo "🔍 Checking for license headers..." - # 关键命令: - # -check: 只检查不修改,有问题返回非0 - # -ignore: 必须和本地脚本保持一致,忽略 third_party - # 注意:这里不需要指定 -c Owner 或 -l License,因为 -check 只看"有没有"头注释,不严格比对内容 - - if ! addlicense -check -ignore "third_party/**" -ignore ".git/**" .; then + # Key command: + # -check: only check, do not modify, return non-zero if issues found + # -ignore: must be consistent with the local script, ignore .git + # Note: No need to specify -c Owner or -l License, because -check only checks for presence of headers, not their exact content + + if ! addlicense -check -ignore ".git/**" .; then echo "❌ FAILED: Some files are missing license headers." - echo "👉 Please run './scripts/universal_copyright_v3.1.sh' locally to fix it." + echo "👉 Please run 'add_copyright.sh' locally to fix it." exit 1 fi - + echo "✅ SUCCESS: All files have license headers." diff --git a/CHANGELOG.md b/CHANGELOG.md index 80887b6..b369f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [v0.5.1] - 2025-12-27 + +### 🧹 Refactor & Style (重构与规范) +* **Global Internationalization**: Completed a full pass over the codebase to translate all non-English comments (Chinese) into English. This covers: + * `apps/` + * `libs/asr_engine` + * `libs/network` + * `libs/utils` + * `third_party/` +* **Code Cleanup**: Removed deprecated legacy logger files (`logger-old.c`, `logger-old.h`) from `libs/utils` to reduce technical debt. + +### 👥 Contributors +* @PotterWhite + ## [v0.5.0] - 2025-12-27 **RK3588s Platform Support & NPU Integration** @@ -106,3 +120,5 @@ This release represents the consolidation of the entire ArcForge development his [0.5.0]: https://github.com/potterwhite/ArcForge/tags/v0.5.0 +[0.5.1]: https://github.com/potterwhite/ArcForge/tags/v0.5.1 + diff --git a/apps/asr/client/src/main-client.cpp b/apps/asr/client/src/main-client.cpp index ecf6294..19eecd9 100644 --- a/apps/asr/client/src/main-client.cpp +++ b/apps/asr/client/src/main-client.cpp @@ -20,8 +20,8 @@ #include "ASREngine/wav-reader/wav-reader.h" #include "Network/client/client.h" -#include "Utils/logger/logger.h" // 引入日志库 -#include "Utils/logger/worker/consolesink.h" // 仅在配置时需要 +#include "Utils/logger/logger.h" +#include "Utils/logger/worker/consolesink.h" #include "Utils/logger/worker/filesink.h" #include @@ -33,25 +33,21 @@ #include using namespace arcforge::embedded; -// using namespace arcforge::embedded::network_socket; -// 假设 kcurrent_lib_name 在此编译单元中可用 -// 这里我们定义一个临时的,实际项目中可能来自别处 const std::string_view kcurrent_app_name = "test-client"; const std::string ksocket_path = "/tmp/soCket.paTh"; const int ksample_rate = 16000; -const int CHUNK_DURATION_MS = 800; // 毫秒, 每次处理和sleep的时长 +const int CHUNK_DURATION_MS = 800; // milliseconds -// --- 全局用于信号处理 --- +// --- kill signal capture --- // static bool g_stop_signal_received = false; -static std::atomic g_stop_signal_received(false); // 修改后的代码 +static std::atomic g_stop_signal_received(false); void SignalHandler(int signal_num) { g_stop_signal_received = true; std::ostringstream oss; oss << "\nInterrupt signal (" << signal_num << ") received. Shutting down..."; - // 使用 Logger 而不是 cerr arcforge::embedded::utils::Logger::GetInstance().Warning(oss.str(), kcurrent_app_name); } @@ -66,32 +62,27 @@ bool isRelease() { } int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { - // 在主程序中,通常我们会配置 Logger。 - // 如果没有特殊配置,它会使用默认的 ConsoleSink。 // auto& logger = arcforge::embedded::utils::Logger::GetInstance(); // logger.setLevel(arcforge::embedded::utils::LoggerLevel::kdebug); //***************************************************** // logger level configuration - // 获取 Logger 实例 + // obtain logger unique instance auto& logger = arcforge::embedded::utils::Logger::GetInstance(); - // 1. 设置日志级别 (例如,只记录 Warning 及以上) + // 1. Configure logger level if (isRelease() == true) { logger.setLevel(arcforge::embedded::utils::LoggerLevel::kinfo); } else { logger.setLevel(arcforge::embedded::utils::LoggerLevel::kdebug); } - // 2. 配置输出目标 (Sink) - logger.ClearSinks(); // 清空默认的控制台输出 - logger.AddSink(std::make_shared( - "/root/my_app_client.log")); // 添加一个文件输出 + // 2. Configure output targets (Sinks) + logger.ClearSinks(); + logger.AddSink( + std::make_shared("/root/my_app_client.log")); logger.AddSink(std::make_shared()); - // // ... 你的其他应用程序代码 ... - // logger.Warning("Application has started."); - //---------------------------------- if (argc < 2) { @@ -116,12 +107,12 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { // connect to server network_socket::SocketReturnValue retval_flag = client.connectToServer(); if (retval_flag > network_socket::SocketReturnValue::ksuccess) { - arcforge::embedded::utils::Logger::GetInstance().Error("Client failed to connect to server.", - kcurrent_app_name); + arcforge::embedded::utils::Logger::GetInstance().Error( + "Client failed to connect to server.", kcurrent_app_name); exit(1); } - // --- 2. 打开 WAV 文件 --- + // --- 2. Open wav file --- ai_asr::WavReader reader; if (!reader.Open(wav_filepath, ksample_rate, 1 /*expected channels*/)) { std::ostringstream oss; @@ -141,12 +132,12 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { } const size_t samples_per_chunk = static_cast((ksample_rate * CHUNK_DURATION_MS) / 1000); - std::vector audio_chunk; // 用于存储从WAV读取的样本 + std::vector audio_chunk; - // --- 3. 循环处理 --- + // --- 3. Processing with conditional loop --- while ((g_stop_signal_received == false) && (reader.Eof() == false)) { - // 在每次循环开始时,我们作为调用者,主动准备好一块足够大的内存。 - // 这确保了无论 ReadSamples 的实现如何,我们提供的缓冲区总是安全的。 + // At the start of each loop, as the caller, we proactively prepare a sufficiently large memory block. + // This ensures that regardless of how ReadSamples is implemented, the buffer we provide is always safe. audio_chunk.resize(samples_per_chunk); size_t samples_read = reader.ReadSamples(audio_chunk, samples_per_chunk); @@ -155,14 +146,15 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { { std::ostringstream oss; oss << "main-client.cpp: size of audio_chunk=" << audio_chunk.size(); - arcforge::embedded::utils::Logger::GetInstance().Debug(oss.str(), kcurrent_app_name); + arcforge::embedded::utils::Logger::GetInstance().Debug(oss.str(), + kcurrent_app_name); } - //【关键步骤】根据实际读取的样本数,精确地截断 vector。 - // 这保证了我们发送给服务器的数据不多不少,正好是 samples_read 个样本。 - // 即使 ReadSamples 内部没有 resize,这行代码也能保证正确性。 - // 即使 ReadSamples 内部已经 resize 了,这行代码也只是做一次无害的重复操作。 - // 这就是防御性编程:不依赖对方,自己保证正确。 + // [key step] Precisely truncate the vector according to the actual number of samples read. + // This ensures that the data we send to the server is neither more nor less than samples_read samples. + // Even if ReadSamples does not resize internally, this line of code ensures correctness. + // Even if ReadSamples has already resized internally, this line of code is just a harmless redundant operation. + // This is defensive programming: do not rely on the other party, ensure correctness yourself. if (samples_read < audio_chunk.size()) { audio_chunk.resize(samples_read); } @@ -186,25 +178,16 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { } // } } - - // else if (!reader.Eof()) { - // // ReadSamples返回0但不是EOF,可能只是暂时没数据或很小的读取 - // // 短暂等待,避免忙等 - // std::this_thread::sleep_for(std::chrono::milliseconds(5)); // 短暂等待 - // arcforge::embedded::utils::Logger::GetInstance().Debug("read more wav samples", kcurrent_app_name); - // continue; // 重新尝试读取 - // } - } // end of while() if (g_stop_signal_received) { arcforge::embedded::utils::Logger::GetInstance().Info("\nProcessing stopped by user.", - kcurrent_app_name); + kcurrent_app_name); } else { arcforge::embedded::utils::Logger::GetInstance().Info( "\nEnd of WAV file reached in main loop.", kcurrent_app_name); //----------------------------------------------------- - // 发送一个空的音频块作为EOF标记 + // send EOF marker (an empty chunk) std::vector empty_chunk; client.sendFloat(empty_chunk); arcforge::embedded::utils::Logger::GetInstance().Info( diff --git a/apps/asr/server/include/asr-task-sherpa.h b/apps/asr/server/include/asr-task-sherpa.h index 9f8cfde..d80cdc7 100644 --- a/apps/asr/server/include/asr-task-sherpa.h +++ b/apps/asr/server/include/asr-task-sherpa.h @@ -31,9 +31,9 @@ #include "Utils/logger/logger.h" enum class ASRTaskStatus { - kIdle = 0x01, // 空闲:没有正在处理的任务 - kRunning = 0x02, // 运行中:一个任务正在被线程执行 - kCompleted = 0x03, // 已完成:任务成功结束,可以被清理 + kIdle = 0x01, // idle: task is created but not yet started + kRunning = 0x02, // running: a task is being executed by a thread + kCompleted = 0x03, // task finished successfully and can be cleaned up // kUnhired = 0x01, //means worker is not hired // kHiredWorking = 0x02, //means worker has been hired and actually working // kHiredCompleted = 0x03, // means worker has been hired and finished his job @@ -70,7 +70,7 @@ class ASRTaskSherpa { // std::mutex mutex_; std::mutex client_mutex_; std::unique_ptr client_ = nullptr; - std::atomic finished_flag_{false}; // 初始化为 false + std::atomic finished_flag_{false}; // arcforge::embedded::ai_asr::SherpaConfig sherpa_config_; }; diff --git a/apps/asr/server/src/asr-task-sherpa.cpp b/apps/asr/server/src/asr-task-sherpa.cpp index 135e61a..d9eb65d 100644 --- a/apps/asr/server/src/asr-task-sherpa.cpp +++ b/apps/asr/server/src/asr-task-sherpa.cpp @@ -22,10 +22,10 @@ #include "Utils/logger/logger.h" #include "common-types.h" -// --- 配置 --- -// Sherpa-ONNX 模型路径 (根据你的实际路径修改) -// 你使用的是rknn模型,需要确保provider正确设置为"rknn" -// 我这里先用通用zipformer示例路径,请务必替换成你RK3588的rknn模型路径! +// --- Config --- +// sherpa-onnx model paths +// **** pls modify these paths according to your actual model locations **** +// **** also ensure the provider is set to "rknn" for RK3588 if you are using RKNN **** const std::string ENCODER_PATH = "/home/asr/models/sherpa-onnx-rk3588-streaming-zipformer-bilingual-zh-en-2023-02-20/" "encoder.rknn"; @@ -39,7 +39,7 @@ const std::string TOKENS_PATH = "/home/asr/models/sherpa-onnx-rk3588-streaming-zipformer-bilingual-zh-en-2023-02-20/" "tokens.txt"; -const std::string PROVIDER = "rknn"; // **** 修改为 "rknn" 如果你在RK3588上运行 **** +const std::string PROVIDER = "rknn"; // --num-threads=1 to select RKNN_NPU_CORE_AUTO // --num-threads=0 to select RKNN_NPU_CORE_0 // --num-threads=-1 to select RKNN_NPU_CORE_1 @@ -78,7 +78,7 @@ bool ASRTaskSherpa::isCompleted() const { } bool ASRTaskSherpa::init() { - // --- 1. 初始化 ASR 引擎 --- + // --- 1. Init ASR Engine --- arcforge::embedded::ai_asr::SherpaConfig config = arcforge::embedded::ai_asr::SherpaConfig::Builder() .setFirstEncoderPath(ENCODER_PATH) @@ -108,30 +108,29 @@ void ASRTaskSherpa::run() { arcforge::embedded::utils::Logger::GetInstance().Info( "Worker thread started for a new client."); - // 主循环,由原子标志位 stop_flag_ 控制 while (stop_flag_ == false) { std::vector audio_chunk; arcforge::embedded::network_socket::SocketReturnValue retval; - // --- 步骤 1: 安全地接收数据 --- - // 在访问 client_ 之前,必须加锁。 - // 这个锁会保护整个 receiveFloat 调用,确保在接收期间,主线程不会 reset client_。 + // step 1: Safely receive data + // Before accessing client_, we must lock. + // Must protect the entire receiveFloat call to ensure that the main thread does not reset client_ during reception. { std::lock_guard lock(client_mutex_); - // 再次检查 client_,因为它可能在两次循环之间被 stop_me() 销毁 + // check again for client_ because it might have been destroyed by stop_me() between loops if (!client_) { - // 如果 client_ 没了,说明被要求停止,直接退出循环 + // if client_ is null, it means we are asked to stop, so just exit the loop break; } - // 在锁的保护下调用阻塞的 IO 方法 + // This call may block for a long time, but we must hold the lock to prevent client_ from being reset. retval = client_->receiveFloat(audio_chunk); - } // 锁在此处自动释放 + } - // --- 步骤 2: 处理接收结果 --- - // 如果接收不成功(包括被 stop_me 中断),则退出循环 + // --- Step 2: Process received data --- + // if (receive failed, including being interrupted by stop_me), exit the loop if (retval != arcforge::embedded::network_socket::SocketReturnValue::ksuccess) { std::string reason; switch (retval) { @@ -173,132 +172,45 @@ void ASRTaskSherpa::run() { } arcforge::embedded::utils::Logger::GetInstance().Info( "Exiting worker thread. Reason: " + reason); - break; // 退出 while 循环 + break; } - // --- 步骤 3: ASR 处理 (这部分是纯计算,不需要锁) --- + // --- Step 3: ASR processing (this is pure computation, no locking needed) --- asr_engine_.ProcessAudioChunk(audio_chunk); std::string recognized_text = asr_engine_.GetCurrentText(); - // --- 步骤 4: 安全地发送结果 --- - // 同样,在访问 client_ 之前加锁 + // --- Step 4: Safely send result --- + // Similarly, lock before accessing client_ { std::lock_guard lock(client_mutex_); if (!client_) { arcforge::embedded::utils::Logger::GetInstance().Warning( "Client connection was closed before sending result."); - break; // 退出 while 循环 + break; } retval = client_->sendString(recognized_text); - } // 锁在此处自动释放 + } - // 如果发送失败,也退出循环 + // if send failed, exit the loop if (retval != arcforge::embedded::network_socket::SocketReturnValue::ksuccess) { arcforge::embedded::utils::Logger::GetInstance().Error( "Failed to send string data, exiting worker thread."); break; } - // --- 步骤 5: 重置 ASR 流 (不需要锁) --- + // --- Step 5: Reset ASR stream (no locking needed) --- asr_engine_.ResetStream(); } - // --- 循环结束后的统一清理工作 --- + // universal cleanup after loop exit finished_flag_ = true; arcforge::embedded::utils::Logger::GetInstance().Info( "ASRTaskSherpa run loop finished, worker thread is now exiting."); } -// void ASRTaskSherpa::run() { -// while (1) { -// if (stop_flag_ == true) { -// arcforge::embedded::utils::Logger::GetInstance().Debug( -// "ASRTaskSherpa class run() return right now", kcurrent_app_name); -// break; - -// } else { -// // std::stringstream ss; -// // ss << std::this_thread::get_id() << ": " -// // << "wow, ASRTaskSherpa::run() 20000 again!"; -// // arcforge::embedded::utils::Logger::GetInstance().Debug(ss.str()); -// // i = 0; - -// // std::this_thread::sleep_for(std::chrono::milliseconds(1000)); -// //-------------------------------------------------------------- -// // --- 3. 循环处理 --- -// if (client_ == nullptr) { -// arcforge::embedded::utils::Logger::GetInstance().Error( -// "ASRTaskSherpa`s client_ is nullptr"); - -// continue; -// } - -// //---------------------------------- -// // means we have data now -// std::vector audio_chunk; -// arcforge::embedded::network_socket::SocketReturnValue retval = -// client_->receiveFloat(audio_chunk); -// if (retval > arcforge::embedded::network_socket::SocketReturnValue::ksuccess) { -// arcforge::embedded::utils::Logger::GetInstance().Debug( -// arcforge::embedded::network_socket::SocketReturnValueToString(retval)); - -// if (retval == -// arcforge::embedded::network_socket::SocketReturnValue::kpeer_abnormally_closed) { -// std::stringstream ss; -// ss << std::this_thread::get_id() << ": " -// << "Peer abnormally closed, terminate myself."; -// arcforge::embedded::utils::Logger::GetInstance().Warning(ss.str()); - -// // return; -// break; -// } - -// arcforge::embedded::utils::Logger::GetInstance().Error( -// "SocketServer (via client_connection) failed to receive " -// "float data.\n drop this packet ", -// kcurrent_app_name); -// continue; -// } - -// // judge if meet eof(end of file) -// if (retval == arcforge::embedded::network_socket::SocketReturnValue::keof) { -// arcforge::embedded::utils::Logger::GetInstance().Debug("Received EOF from client", -// kcurrent_app_name); -// break; -// } - -// asr_engine_.ProcessAudioChunk(audio_chunk); - -// std::string recognized_text = asr_engine_.GetCurrentText(); -// std::ostringstream oss; -// oss << "Segmentsss " << recognized_text; -// arcforge::embedded::utils::Logger::GetInstance().Debug(oss.str(), kcurrent_app_name); -// retval = client_->sendString(recognized_text); -// if (retval > arcforge::embedded::network_socket::SocketReturnValue::ksuccess) { - -// arcforge::embedded::utils::Logger::GetInstance().Error( -// "SocketServer (via client_connection) failed to send std::string data.\n " -// "just goto next", -// kcurrent_app_name); -// continue; -// } - -// // reset stream -// asr_engine_.ResetStream(); - -// arcforge::embedded::utils::Logger::GetInstance().Debug( -// "+++++last statement of this round of loop\n", kcurrent_app_name); -// } -// } - -// // 循环结束后的清理工作 -// finished_flag_ = true; // <--- 循环正常结束后也要设置标志 -// arcforge::embedded::utils::Logger::GetInstance().Info( -// "ASRTaskSherpa run loop finished(finished flag has been set to true)."); -// } -// stop_me() 的最终线程安全版本 +// stop_me() final thread-safe version void ASRTaskSherpa::stop_me() { stop_flag_ = true; std::lock_guard lock(client_mutex_); @@ -306,8 +218,3 @@ void ASRTaskSherpa::stop_me() { client_.reset(); } } -// void ASRTaskSherpa::stop_me() { -// stop_flag_ = true; -// arcforge::embedded::utils::Logger::GetInstance().Info( -// "ASRTaskSherpa has set stop flag, infinite loop will be notified at its next run."); -// } diff --git a/apps/asr/server/src/main-server.cpp b/apps/asr/server/src/main-server.cpp index 838861f..20da29c 100644 --- a/apps/asr/server/src/main-server.cpp +++ b/apps/asr/server/src/main-server.cpp @@ -21,14 +21,12 @@ #include "pch.h" #include "Utils/logger/logger.h" -#include "Utils/logger/worker/consolesink.h" // 仅在配置时需要 +#include "Utils/logger/worker/consolesink.h" #include "Utils/logger/worker/filesink.h" #include "acceptor.h" #include "common-types.h" -// --- 全局用于信号处理 --- -// static bool g_stop_signal_received = false; -static std::atomic g_stop_signal_received(false); // 修改后的代码 +static std::atomic g_stop_signal_received(false); void SignalHandler(int signal_num) { g_stop_signal_received = true; @@ -52,32 +50,30 @@ bool isRelease() { int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { - // 设置Ctrl+C信号处理器 signal(SIGINT, SignalHandler); signal(SIGTERM, SignalHandler); //***************************************************** // logger level configuration - // 获取 Logger 实例 + // obtain logger unique instance auto& logger = arcforge::embedded::utils::Logger::GetInstance(); // std::cout << "[main] sizeof(arcforge::embedded::utils::FileSink) = " // << sizeof(arcforge::embedded::utils::FileSink) ; - // 1. 设置日志级别 (例如,只记录 Warning 及以上) + // 1. Configure logger level if (isRelease() == true) { logger.setLevel(arcforge::embedded::utils::LoggerLevel::kinfo); } else { logger.setLevel(arcforge::embedded::utils::LoggerLevel::kdebug); } - // 2. 配置输出目标 (Sink) - logger.ClearSinks(); // 清空默认的控制台输出 - logger.AddSink(std::make_shared( - "/root/my_app_client.log")); // 添加一个文件输出 + // 2. Configure output targets (Sinks) + logger.ClearSinks(); + logger.AddSink( + std::make_shared("/root/my_app_client.log")); logger.AddSink(std::make_shared()); - // // ... 你的其他应用程序代码 ... logger.Info("Application has started."); // socket path initialize @@ -86,7 +82,6 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { acceptor->setSocketPath(ksocket_path); acceptor->init(); - // --- 3. 循环处理 --- while (1) { if (g_stop_signal_received == true) { logger.Warning("main() will send stop signal to Acceptor."); @@ -98,7 +93,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { acceptor->process(); } } - // Recognizer 对象会在 main 结束时自动调用析构函数进行清理 + // recognizer will be cleaned up automatically when main ends std::stringstream ss; ss << std::this_thread::get_id() << ": " diff --git a/cmake/ArcFunctions.cmake b/cmake/ArcFunctions.cmake index 14fd200..3826c85 100644 --- a/cmake/ArcFunctions.cmake +++ b/cmake/ArcFunctions.cmake @@ -455,10 +455,10 @@ function(arc_install_library target_name include_dir) # 8. Install Export list (Targets.cmake) # It will sync all Target information into files install( - EXPORT ${target_name} # <-- 告诉 CMake 我们要安装哪个导出集 - FILE "${FULL_PACKAGE_NAME}Targets.cmake" # 生成的 .cmake 文件名 - NAMESPACE "${PROJECT_NAMESPACE}::" # (推荐) 为目标添加命名空间,避免冲突 - DESTINATION "${INSTALL_CONFIG_DIR}" # 标准的安装路径 + EXPORT ${target_name} # <-- Tell CMake which export set we want to install + FILE "${FULL_PACKAGE_NAME}Targets.cmake" # Name of the generated .cmake file + NAMESPACE "${PROJECT_NAMESPACE}::" # (Recommended) Add a namespace to targets to avoid conflicts + DESTINATION "${INSTALL_CONFIG_DIR}" # Standard installation path for config files ) message(STATUS "[Configuration] Configured install rules for lib: ${target_name}") diff --git a/libs/asr_engine/include/ASREngine/common/system-info.h b/libs/asr_engine/include/ASREngine/common/system-info.h index 7564d25..6d97872 100644 --- a/libs/asr_engine/include/ASREngine/common/system-info.h +++ b/libs/asr_engine/include/ASREngine/common/system-info.h @@ -28,8 +28,8 @@ namespace embedded { namespace asr { /** - * @brief 获取 ASR 库的编译时版本字符串。 - * @return 一个格式为 "major.minor.patch" 的字符串。 + * @brief Obtain ASR library version string. + * @return A string in the format "major.minor.patch". */ std::string get_asr_library_version(); diff --git a/libs/asr_engine/include/ASREngine/recognizer/impl/recognizer-impl.h b/libs/asr_engine/include/ASREngine/recognizer/impl/recognizer-impl.h index cdfc5d8..e835e7d 100644 --- a/libs/asr_engine/include/ASREngine/recognizer/impl/recognizer-impl.h +++ b/libs/asr_engine/include/ASREngine/recognizer/impl/recognizer-impl.h @@ -20,7 +20,7 @@ * SOFTWARE. */ -// 文件: recognizer/impl/recognizer-impl.h +// libs/asr_engine/include/ASREngine/recognizer/impl/recognizer-impl.h #pragma once #include "ASREngine/pch.h" @@ -28,12 +28,8 @@ // #include // #include -// 向前声明你自己的配置类,因为 Impl 需要它 -#include "ASREngine/recognizer/recognizer-config.h" // << 注意路径,相对于 impl 目录调整 - // 或者更常见的做法是在 CMake 中配置 include 路径 - // 使得可以直接 #include "recognizer-config.h" +#include "ASREngine/recognizer/recognizer-config.h" -// 向前声明 Sherpa-ONNX 的内部类型 namespace sherpa_onnx { namespace cxx { class OnlineRecognizer; @@ -48,20 +44,19 @@ namespace ai_asr { class RecognizerImpl { public: RecognizerImpl(); - ~RecognizerImpl(); // 确保在 .cpp 中定义 + ~RecognizerImpl(); bool Initialize(const SherpaConfig& user_config); void ProcessAudioChunk(const std::vector& audio_chunk); void InputFinished(); - std::string GetCurrentText() ; + std::string GetCurrentText(); bool IsEndpoint() const; void ResetStream(); int GetExpectedSampleRate() const; - // 禁止拷贝和赋值 RecognizerImpl(const RecognizerImpl&) = delete; RecognizerImpl& operator=(const RecognizerImpl&) = delete; - // 允许移动 (如果需要) + RecognizerImpl(RecognizerImpl&&) noexcept; RecognizerImpl& operator=(RecognizerImpl&&) noexcept; @@ -71,9 +66,8 @@ class RecognizerImpl { std::unique_ptr recognizer_ptr_; std::unique_ptr stream_ptr_; - // 其他成员变量 std::string last_displayed_text_; - int expected_sample_rate_ = 16000; // 默认值或从配置初始化 + int expected_sample_rate_ = 16000; }; } // namespace ai_asr diff --git a/libs/asr_engine/include/ASREngine/recognizer/recognizer.h b/libs/asr_engine/include/ASREngine/recognizer/recognizer.h index 37b9080..8cf207e 100644 --- a/libs/asr_engine/include/ASREngine/recognizer/recognizer.h +++ b/libs/asr_engine/include/ASREngine/recognizer/recognizer.h @@ -22,20 +22,20 @@ #pragma once -#include "ASREngine/recognizer/recognizer-config.h" // 你的干净配置 -#include "ASREngine/pch.h" #include "ASREngine/common/common-types.h" +#include "ASREngine/pch.h" +#include "ASREngine/recognizer/recognizer-config.h" // #include -// #include // 确保 string/vector/memory 这些公共接口用到的被包含 +// #include // #include namespace arcforge { namespace embedded { namespace ai_asr { -// 向前声明 PIMPL 实现类 -class RecognizerImpl; // <--- 关键 +// forward declaration of the PIMPL implementation class +class RecognizerImpl; class Recognizer { public: diff --git a/libs/asr_engine/include/ASREngine/vad/impl/vad-impl.h b/libs/asr_engine/include/ASREngine/vad/impl/vad-impl.h index 6cf4160..4f5eb6d 100644 --- a/libs/asr_engine/include/ASREngine/vad/impl/vad-impl.h +++ b/libs/asr_engine/include/ASREngine/vad/impl/vad-impl.h @@ -65,10 +65,10 @@ class VADImpl { int GetSampleRate() const { return expected_sample_rate_; } - // 禁止拷贝和赋值 + VADImpl(const VADImpl&) = delete; VADImpl& operator=(const VADImpl&) = delete; - // 允许移动 (如果需要) + VADImpl(VADImpl&&) noexcept; VADImpl& operator=(VADImpl&&) noexcept; diff --git a/libs/asr_engine/include/ASREngine/wav-reader/wav-reader.h b/libs/asr_engine/include/ASREngine/wav-reader/wav-reader.h index 24e5073..e6a6bf4 100644 --- a/libs/asr_engine/include/ASREngine/wav-reader/wav-reader.h +++ b/libs/asr_engine/include/ASREngine/wav-reader/wav-reader.h @@ -22,8 +22,8 @@ #pragma once -#include "ASREngine/pch.h" #include "ASREngine/common/common-types.h" +#include "ASREngine/pch.h" namespace arcforge { namespace embedded { @@ -37,8 +37,6 @@ class WavReader { int expected_channels = 1); void Close(); - // 读取指定数量的样本到float向量 (归一化到 -1.0 到 1.0) - // 返回实际读取的样本数 size_t ReadSamples(std::vector& out_samples, size_t num_samples_to_read); bool IsOpened() const { return is_opened_; } bool Eof() const { return eof_ || !wav_file_.is_open(); } @@ -54,12 +52,11 @@ class WavReader { int sample_rate_ = 0; int channels_ = 0; int bits_per_sample_ = 0; - // size_t data_chunk_pos_ = 0; // PCM数据块在文件中的起始位置 + std::streamoff data_chunk_pos_ = 0; - size_t data_chunk_size_ = 0; // PCM数据块的大小 (字节) + size_t data_chunk_size_ = 0; size_t bytes_read_from_data_chunk_ = 0; - // 简化的WAV头解析 bool ParseWavHeader(int expected_sample_rate, int expected_channels); }; } // namespace ai_asr diff --git a/libs/asr_engine/src/common/CMakeLists.txt b/libs/asr_engine/src/common/CMakeLists.txt index 1111e5b..7fad84e 100644 --- a/libs/asr_engine/src/common/CMakeLists.txt +++ b/libs/asr_engine/src/common/CMakeLists.txt @@ -22,31 +22,11 @@ # src/common/CMakeLists.txt # -# 列出这个模块的源文件 (如果有 .cpp 文件) set(COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/common-types.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/system-info.cpp" ) -#[[ -# 列出这个模块提供的头文件 (供父级 CMakeLists.txt 用于安装或接口包含) -set(COMMON_PUBLIC_HEADERS - "${INCLUDE_DIR}/ASR/common/common-types.h" -) - -# 将源文件列表设置到父作用域,以便顶层 CMakeLists.txt 可以使用它 -set(LIB_SOURCES ${LIB_SOURCES} ${COMMON_SOURCES} PARENT_SCOPE) # 如果有 COMMON_SOURCES -set(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${COMMON_PUBLIC_HEADERS} PARENT_SCOPE) - -install(FILES ${COMMON_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/common) - -# # 将 version.cpp 添加到源文件列表中 -# list(APPEND LIB_SOURCES - -# # ... 您在 common 目录下的其他 .cpp 文件 -# ) -]] - target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SOURCES} diff --git a/libs/asr_engine/src/common/system-info.cpp b/libs/asr_engine/src/common/system-info.cpp index a23ffc3..28aac31 100644 --- a/libs/asr_engine/src/common/system-info.cpp +++ b/libs/asr_engine/src/common/system-info.cpp @@ -18,35 +18,30 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// 关键:包含由 CMake 在第 3 步生成的头文件 +// IMPORTANT: Import from CMakeLists.txt externally #include "system-info.h" namespace arcforge { namespace embedded { namespace asr { -// 定义一个全局常量,以确保版本字符串被编译进二进制文件, -// 这样 'strings' 命令就能找到它。 -// const char* g_internal_version_string_for_binary_scan = VERSION_STRING; - -// 实现公共接口函数 std::string get_asr_library_version() { - // 使用 CMake 生成的宏返回版本字符串 + return VERSION_STRING; } std::string get_asr_library_author() { - // 使用 CMake 生成的宏返回版本字符串 + return AUTHOR_NAME; } std::string get_asr_library_author_email() { - // 使用 CMake 生成的宏返回版本字符串 + return AUTHOR_EMAIL; } std::string get_asr_library_build_timestamp() { - // 使用 CMake 生成的宏返回版本字符串 + return BUILD_TIMESTAMP; } } // namespace asr diff --git a/libs/asr_engine/src/recognizer/CMakeLists.txt b/libs/asr_engine/src/recognizer/CMakeLists.txt index 3b37bc5..e840f9a 100644 --- a/libs/asr_engine/src/recognizer/CMakeLists.txt +++ b/libs/asr_engine/src/recognizer/CMakeLists.txt @@ -27,24 +27,6 @@ set(RECOGNIZER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/recognizer-config.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/impl/recognizer-impl.cpp") -#[[ -set(RECOGNIZER_PUBLIC_HEADERS "${INCLUDE_DIR}/ASR/recognizer/recognizer.h" - "${INCLUDE_DIR}/ASR/recognizer/recognizer-config.h") - -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${RECOGNIZER_SOURCES} - PARENT_SCOPE) -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${RECOGNIZER_PUBLIC_HEADERS} - PARENT_SCOPE) - -install(FILES ${RECOGNIZER_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/recognizer) -# 如果 该 模块有特定的包含目录或编译定义,可以在这里设置给一个目标属性变量 target_include_directories( ${PARENT_LIBRARY_TARGET} PRIVATE -# some_vad_internal_include ) 但通常是父级聚合后统一设置给最终的库目标。 或者更简单地,父级通过 -# $ 来收集。 对于简单的源文件聚合,直接上报列表更常见。 -]] - target_sources(${PROJECT_NAME} PRIVATE ${RECOGNIZER_SOURCES} diff --git a/libs/asr_engine/src/recognizer/impl/recognizer-impl.cpp b/libs/asr_engine/src/recognizer/impl/recognizer-impl.cpp index f705e14..bb397fd 100644 --- a/libs/asr_engine/src/recognizer/impl/recognizer-impl.cpp +++ b/libs/asr_engine/src/recognizer/impl/recognizer-impl.cpp @@ -18,45 +18,37 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// 文件: recognizer/impl/recognizer-impl.cpp +// libs/asr_engine/src/recognizer/impl/recognizer-impl.cpp #include "ASREngine/recognizer/impl/recognizer-impl.h" #include "Utils/logger/logger.h" -// 在这里包含所有必需的 sherpa-onnx 头文件 -#include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API - -// 如果 recognizer-config.h 不在默认的 include 路径,也需要正确包含 -// #include "recognizer/recognizer-config.h" (如果上一层CMakeLists.txt已添加src为include目录则可能不需要) +#include "sherpa-onnx/c-api/cxx-api.h" namespace arcforge { namespace embedded { namespace ai_asr { -using namespace sherpa_onnx::cxx; // 可以方便地使用 OnlineRecognizer 等 +using namespace sherpa_onnx::cxx; RecognizerImpl::RecognizerImpl() { arcforge::embedded::utils::Logger::GetInstance().Info("RecognizerImpl object constructed.", - kcurrent_lib_name); - // expected_sample_rate_ 已经在头文件中给了默认值 + kcurrent_lib_name); } -// 析构函数的定义需要在这里,因为 unique_ptr 等需要完整类型 RecognizerImpl::~RecognizerImpl() { // std::ostringstream oss; // oss << "RecognizerImpl cleaned up."; arcforge::embedded::utils::Logger::GetInstance().Info("RecognizerImpl cleaned up.", - kcurrent_lib_name); + kcurrent_lib_name); } -// 移动构造 RecognizerImpl::RecognizerImpl(RecognizerImpl&& other) noexcept : recognizer_ptr_(std::move(other.recognizer_ptr_)), stream_ptr_(std::move(other.stream_ptr_)), last_displayed_text_(std::move(other.last_displayed_text_)), expected_sample_rate_(other.expected_sample_rate_) {} -// 移动赋值 RecognizerImpl& RecognizerImpl::operator=(RecognizerImpl&& other) noexcept { if (this != &other) { recognizer_ptr_ = std::move(other.recognizer_ptr_); @@ -68,14 +60,8 @@ RecognizerImpl& RecognizerImpl::operator=(RecognizerImpl&& other) noexcept { } bool RecognizerImpl::Initialize(const SherpaConfig& sherpa_config) { - OnlineRecognizerConfig config; // 这是 sherpa_onnx::cxx::OnlineRecognizerConfig - - // 从你的 SherpaConfig 映射到 sherpa_onnx::OnlineRecognizerConfig - // 注意:sherpa-onnx 的 OnlineRecognizer::Create 接收的是 OnlineRecognizerConfig - // 而不是 OnlineRecognizer 对象本身。所以之前的 make_unique(OnlineRecognizer::Create(config)) - // 可能需要调整为直接创建 OnlineRecognizer。 + OnlineRecognizerConfig config; - // 我将基于你 Recognizer::Initialize 中的逻辑来填充 config config.model_config.transducer.encoder = sherpa_config.getFirstEncoderPath(); config.model_config.transducer.decoder = sherpa_config.getSecondDecoderPath(); config.model_config.transducer.joiner = sherpa_config.getThirdJoinerPath(); @@ -89,9 +75,7 @@ bool RecognizerImpl::Initialize(const SherpaConfig& sherpa_config) { config.model_config.debug = false; } - // 这里假设你的 SherpaConfig 有一个方法获取期望的采样率,或者它被硬编码 - // 我们已经在成员中初始化了 expected_sample_rate_,可以用它或从配置中覆盖 - config.feat_config.sample_rate = expected_sample_rate_; // 或者从 sherpa_config 获取 + config.feat_config.sample_rate = expected_sample_rate_; config.rule1_min_trailing_silence = sherpa_config.getSeventhRule1MinTrailingSilence(); config.rule2_min_trailing_silence = sherpa_config.getEighthRule2MinTrailingSilence(); @@ -113,7 +97,6 @@ bool RecognizerImpl::Initialize(const SherpaConfig& sherpa_config) { *********************************************************/ recognizer_ptr_ = std::make_unique(OnlineRecognizer::Create(config)); - // 检查 reset 后是否有效 if (recognizer_ptr_->Get() == nullptr) { // std::cerr << "Failed to create OnlineRecognizer (internal pointer is null)."; arcforge::embedded::utils::Logger::GetInstance().Error( @@ -136,14 +119,14 @@ bool RecognizerImpl::Initialize(const SherpaConfig& sherpa_config) { arcforge::embedded::utils::Logger::GetInstance().Error( "Failed to create OnlineStream (internal pointer is null).", kcurrent_lib_name); - recognizer_ptr_.reset(); // 清理已创建的 recognizer + recognizer_ptr_.reset(); stream_ptr_.reset(); return false; } arcforge::embedded::utils::Logger::GetInstance().Info("Sherpa-ONNX Stream (Impl) created.", - kcurrent_lib_name); + kcurrent_lib_name); } catch (const std::exception& e) { std::ostringstream oss_catch; @@ -159,7 +142,7 @@ bool RecognizerImpl::Initialize(const SherpaConfig& sherpa_config) { void RecognizerImpl::ProcessAudioChunk(const std::vector& audio_chunk) { if (!stream_ptr_ || !recognizer_ptr_) { arcforge::embedded::utils::Logger::GetInstance().Error("ASR (Impl) not initialized.", - kcurrent_lib_name); + kcurrent_lib_name); return; } if (audio_chunk.empty()) { @@ -178,7 +161,7 @@ void RecognizerImpl::ProcessAudioChunk(const std::vector& audio_chunk) { } void RecognizerImpl::InputFinished() { - if (stream_ptr_ && recognizer_ptr_) { // 检查recognizer_ptr_也很有用 + if (stream_ptr_ && recognizer_ptr_) { stream_ptr_->InputFinished(); while (recognizer_ptr_->IsReady(stream_ptr_.get())) { recognizer_ptr_->Decode(stream_ptr_.get()); @@ -209,9 +192,9 @@ bool RecognizerImpl::IsEndpoint() const { void RecognizerImpl::ResetStream() { if (recognizer_ptr_ && stream_ptr_) { - // 使用 sherpa-onnx 提供的 Reset 方法重置流,效率更高 + recognizer_ptr_->Reset(stream_ptr_.get()); - last_displayed_text_.clear(); // 清空上一句话的结果 + last_displayed_text_.clear(); arcforge::embedded::utils::Logger::GetInstance().Info( "[ASR Stream Reset (Impl) for new utterance]", kcurrent_lib_name); @@ -220,7 +203,6 @@ void RecognizerImpl::ResetStream() { arcforge::embedded::utils::Logger::GetInstance().Error( "Cannot reset stream, recognizer or stream not initialized.", kcurrent_lib_name); } - } int RecognizerImpl::GetExpectedSampleRate() const { diff --git a/libs/asr_engine/src/recognizer/recognizer-config.cpp b/libs/asr_engine/src/recognizer/recognizer-config.cpp index c7ec71c..3511f42 100644 --- a/libs/asr_engine/src/recognizer/recognizer-config.cpp +++ b/libs/asr_engine/src/recognizer/recognizer-config.cpp @@ -19,7 +19,7 @@ // SOFTWARE. #include "ASREngine/recognizer/recognizer-config.h" -#include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API +#include "sherpa-onnx/c-api/cxx-api.h" namespace arcforge { namespace embedded { diff --git a/libs/asr_engine/src/recognizer/recognizer.cpp b/libs/asr_engine/src/recognizer/recognizer.cpp index e8c7aa0..cf3c287 100644 --- a/libs/asr_engine/src/recognizer/recognizer.cpp +++ b/libs/asr_engine/src/recognizer/recognizer.cpp @@ -18,34 +18,21 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// 文件: recognizer/recognizer.cpp -#include "ASREngine/recognizer/impl/recognizer-impl.h" // 包含PIMPL实现类的头文件 (注意路径) -#include "ASREngine/recognizer/recognizer.h" // 包含你更新后的公共头文件 (recognizer.h) +// libs/asr_engine/src/recognizer/recognizer.cpp +#include "ASREngine/recognizer/recognizer.h" +#include "ASREngine/recognizer/impl/recognizer-impl.h" #include "Utils/logger/logger.h" -// !! 不再需要在这里包含 的头文件 -// !! 也不再需要 using namespace sherpa_onnx::cxx; - namespace arcforge { namespace embedded { namespace ai_asr { -// 构造函数: 创建 PIMPL 对象 -Recognizer::Recognizer() : impl_(std::make_unique()) { - // 原来的 cout "Recognizer object constructed..." 应该移到 RecognizerImpl 的构造函数中 - // 或者如果你希望接口层也有日志,可以保留,但通常 Impl 构造时打日志更合适 -} +Recognizer::Recognizer() : impl_(std::make_unique()) {} -// 析构函数: 默认实现即可,std::unique_ptr 会自动处理 impl_ 的销毁 -// 重要的是这个定义要放在 .cpp 文件中,这样编译器在销毁 impl_ 时能看到 RecognizerImpl 的完整定义 -Recognizer::~Recognizer() { - // 原来的 cout "Recognizer cleaned up..." 应该移到 RecognizerImpl 的析构函数中 -} +Recognizer::~Recognizer() {} -// 移动构造函数 (通常对于 PIMPL 是需要的) Recognizer::Recognizer(Recognizer&& other) noexcept : impl_(std::move(other.impl_)) {} -// 移动赋值运算符 (通常对于 PIMPL 是需要的) Recognizer& Recognizer::operator=(Recognizer&& other) noexcept { if (this != &other) { impl_ = std::move(other.impl_); @@ -53,38 +40,25 @@ Recognizer& Recognizer::operator=(Recognizer&& other) noexcept { return *this; } -// 所有公共方法都委托给 impl_ 对象 bool Recognizer::Initialize(const SherpaConfig& config) { - // 在调用 Initialize 之前,impl_ 应该已经被构造函数创建好了。 - // 如果构造函数可能失败并使 impl_ 为空,你需要错误处理。 - // 但 std::make_unique 如果失败会抛 bad_alloc,所以通常 impl_ 不会是空的,除非移动后。 if (!impl_) { - // 这是一个异常情况,可能源于一个被移动的 Recognizer 对象 - // 或者在未来如果构造函数变得更复杂。 - // 对于基本情况,构造函数会确保 impl_ 有效。 - // 可以考虑重新创建一个,或者抛出异常,或者返回false。 - // 为简单起见,这里假设 impl_ 有效,或者 Initialize 会处理。 - // 如果之前的 Recognizer 对象被移动了,impl_ 就会是 nullptr。 - // 调用 Initialize 的前提是对象是有效的。 - // 如果一个 Recognizer 对象被移动了,它的状态就是空的,不应该再调用方法。 - // 或者,如果允许在空 impl_ 上调用 Initialize,那么就需要在这里创建: - // impl_ = std::make_unique(); // 如果允许 Initialize “重新激活” - arcforge::embedded::utils::Logger::GetInstance().Error( "Recognizer::Initialize called on a moved-from or uninitialized object's PIMPL.", kcurrent_lib_name); + return false; } + return impl_->Initialize(config); } void Recognizer::ProcessAudioChunk(const std::vector& audio_chunk) { - if (impl_) { // 总是在访问指针前检查是个好习惯 + if (impl_) { impl_->ProcessAudioChunk(audio_chunk); } else { arcforge::embedded::utils::Logger::GetInstance().Error( "Recognizer::ProcessAudioChunk called on a null PIMPL.", kcurrent_lib_name); - // 或者抛出异常 std::runtime_error("Recognizer not initialized or moved-from"); + // std::runtime_error("Recognizer not initialized or moved-from"); } } @@ -104,7 +78,7 @@ std::string Recognizer::GetCurrentText() const { arcforge::embedded::utils::Logger::GetInstance().Error( "Recognizer::GetCurrentText called on a null PIMPL.", kcurrent_lib_name); - return ""; // 返回空字符串或抛异常 + return ""; } bool Recognizer::IsEndpoint() const { @@ -114,7 +88,7 @@ bool Recognizer::IsEndpoint() const { arcforge::embedded::utils::Logger::GetInstance().Error( "Recognizer::IsEndpoint called on a null PIMPL.", kcurrent_lib_name); - return false; // 返回 false 或抛异常 + return false; } void Recognizer::ResetStream() { @@ -134,9 +108,8 @@ int Recognizer::GetExpectedSampleRate() const { arcforge::embedded::utils::Logger::GetInstance().Error( "Recognizer::GetExpectedSampleRate called on a null PIMPL.", kcurrent_lib_name); - // 返回一个表示错误/未初始化的值,或者默认值 - // 这个默认值应该与 RecognizerImpl 中未初始化时的返回值一致,或根据业务逻辑决定 - return kdefault_sample_rate; // 例如,返回一个通用的默认采样率 + + return kdefault_sample_rate; } } // namespace ai_asr diff --git a/libs/asr_engine/src/vad/CMakeLists.txt b/libs/asr_engine/src/vad/CMakeLists.txt index d8b36f1..c3e993a 100644 --- a/libs/asr_engine/src/vad/CMakeLists.txt +++ b/libs/asr_engine/src/vad/CMakeLists.txt @@ -19,30 +19,11 @@ # SOFTWARE. # -# sherpa-lib/src/vad/CMakeLists.txt +# libs/asr_engine/src/vad/CMakeLists.txt # set(VAD_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/vad.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/vad-config.cpp") -#[[ -set(VAD_PUBLIC_HEADERS "${INCLUDE_DIR}/ASR/vad/vad.h" - "${INCLUDE_DIR}/ASR/vad/vad-config.h") - -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${VAD_SOURCES} - PARENT_SCOPE) -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${VAD_PUBLIC_HEADERS} - PARENT_SCOPE) - -install(FILES ${VAD_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/vad) - -# 如果 vad 模块有特定的包含目录或编译定义,可以在这里设置给一个目标属性变量 target_include_directories( ${PARENT_LIBRARY_TARGET} -# PRIVATE some_vad_internal_include ) 但通常是父级聚合后统一设置给最终的库目标。 或者更简单地,父级通过 -# $ 来收集。 对于简单的源文件聚合,直接上报列表更常见。 -]] - target_sources(${PROJECT_NAME} PRIVATE ${VAD_SOURCES} diff --git a/libs/asr_engine/src/vad/impl/vad-impl.cpp b/libs/asr_engine/src/vad/impl/vad-impl.cpp index 15ebb9d..6986270 100644 --- a/libs/asr_engine/src/vad/impl/vad-impl.cpp +++ b/libs/asr_engine/src/vad/impl/vad-impl.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API +#include "sherpa-onnx/c-api/cxx-api.h" #include "vad.h" namespace arcforge { diff --git a/libs/asr_engine/src/vad/vad-config.cpp b/libs/asr_engine/src/vad/vad-config.cpp index 56e23d4..4cbe710 100644 --- a/libs/asr_engine/src/vad/vad-config.cpp +++ b/libs/asr_engine/src/vad/vad-config.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API +#include "sherpa-onnx/c-api/cxx-api.h" #include "ASREngine/vad/vad-config.h" namespace arcforge { diff --git a/libs/asr_engine/src/vad/vad.cpp b/libs/asr_engine/src/vad/vad.cpp index 2bc0bfb..804cb8f 100644 --- a/libs/asr_engine/src/vad/vad.cpp +++ b/libs/asr_engine/src/vad/vad.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API +#include "sherpa-onnx/c-api/cxx-api.h" #include "ASREngine/vad/vad.h" namespace arcforge { diff --git a/libs/asr_engine/src/wav-reader/CMakeLists.txt b/libs/asr_engine/src/wav-reader/CMakeLists.txt index ce4603a..1ec431d 100644 --- a/libs/asr_engine/src/wav-reader/CMakeLists.txt +++ b/libs/asr_engine/src/wav-reader/CMakeLists.txt @@ -19,25 +19,11 @@ # SOFTWARE. # -# sherpa-lib/src/wav-reader/CMakeLists.txt +# libs/asr_engine/src/wav-reader/CMakeLists.txt # set(WAV_READER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/wav-reader.cpp") -#[[ -set(WAV_READER_PUBLIC_HEADERS "${INCLUDE_DIR}/ASR/wav-reader/wav-reader.h") - -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${WAV_READER_SOURCES} - PARENT_SCOPE) -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${WAV_READER_PUBLIC_HEADERS} - PARENT_SCOPE) - -install(FILES ${WAV_READER_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/wav-reader) -]] - target_sources(${PROJECT_NAME} PRIVATE ${WAV_READER_SOURCES} diff --git a/libs/asr_engine/src/wav-reader/wav-reader-backup.cpp b/libs/asr_engine/src/wav-reader/wav-reader-backup.cpp deleted file mode 100644 index e9595f0..0000000 --- a/libs/asr_engine/src/wav-reader/wav-reader-backup.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright (c) 2025 PotterWhite -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "ASREngine/wav-reader/wav-reader.h" -#include "Utils/logger/logger.h" - -namespace arcforge { -namespace embedded { -namespace ai_asr { -// Helper to read little-endian values (保持不变,这个很好) -template -T read_le(std::istream& is) { - T val; - is.read(reinterpret_cast(&val), sizeof(T)); - return val; -} - -WavReader::WavReader() {} // 默认构造函数 - -WavReader::~WavReader() { - Close(); -} - -bool WavReader::Open(const std::string& filepath, int expected_sample_rate, int expected_channels) { - if (is_opened_) { - Close(); - } - wav_file_.open(filepath, std::ios::binary); - if (!wav_file_) { - std::ostringstream oss; - oss << "Error opening WAV file: " << filepath; - arcforge::embedded::utils::Logger::GetInstance().Error(oss.str(), kcurrent_lib_name); - - return false; - } - - if (!ParseWavHeader(expected_sample_rate, expected_channels)) { - wav_file_.close(); - return false; - } - - // data_chunk_pos_ 是 std::streamoff,seekg 参数类型是 std::streamoff 或 std::streampos - // 这里不需要转换,本身是匹配的。原来的警告可能是因为 data_chunk_pos_ 之前被声明为 size_t? - // 确认 data_chunk_pos_ 在 .h 中是 std::streamoff。 - wav_file_.seekg(data_chunk_pos_, std::ios::beg); // 定位到数据块开始 - // 为了更明确,如果 data_chunk_pos_ 是 size_t,可以这样: - // wav_file_.seekg(static_cast(data_chunk_pos_), std::ios::beg); // <-- line 35 - - if (!wav_file_) { - arcforge::embedded::utils::Logger::GetInstance().Error( - "Error seeking to data chunk in WAV file.", kcurrent_lib_name); - - wav_file_.close(); - return false; - } - bytes_read_from_data_chunk_ = 0; - is_opened_ = true; - eof_ = false; - - std::ostringstream oss; - oss << "WAV file opened: " << filepath << "\n" - << " Sample Rate: " << sample_rate_ << " Hz (Expected: " << expected_sample_rate << ")\n" - << " Channels: " << channels_ << " (Expected: " << expected_channels << ")\n" - << " Bits/Sample: " << bits_per_sample_ << "\n" - << " Data chunk size: " << data_chunk_size_ << " bytes"; - - // 调用 Logger 的 MultiLineLog 方法,它可以自动按行分割 - arcforge::embedded::utils::Logger::GetInstance().MultiLineLog( - arcforge::embedded::utils::LoggerLevel::kinfo, oss.str(), kcurrent_lib_name); - // std::cout << "WAV file opened: " << filepath << std::endl; - // std::cout << " Sample Rate: " << sample_rate_ << " Hz (Expected: " << expected_sample_rate - // << ")" << std::endl; - // std::cout << " Channels: " << channels_ << " (Expected: " << expected_channels << ")" - // << std::endl; - // std::cout << " Bits/Sample: " << bits_per_sample_ << std::endl; - // std::cout << " Data chunk size: " << data_chunk_size_ << " bytes" << std::endl; - return true; -} - -void WavReader::Close() { - if (wav_file_.is_open()) { - wav_file_.close(); - - arcforge::embedded::utils::Logger::GetInstance().Info("WAV file closed.", kcurrent_lib_name); - } - is_opened_ = false; - eof_ = true; // 在关闭时,逻辑上也是文件末尾 -} - -bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) { - char buffer[4]; - // RIFF chunk - wav_file_.read(buffer, 4); - if (!wav_file_ || std::memcmp(buffer, "RIFF", 4) != 0) { // 增加对 read 失败的检查 - // std::cerr << "Not a RIFF file or read error\n"; - arcforge::embedded::utils::Logger::GetInstance().Error("Not a RIFF file or read error\n", - kcurrent_lib_name); - return false; - } - read_le(wav_file_); - wav_file_.read(buffer, 4); - if (!wav_file_ || std::memcmp(buffer, "WAVE", 4) != 0) { - std::cerr << "Not a WAVE file or read error\n"; - arcforge::embedded::utils::Logger::GetInstance().Error("Not a RIFF file or read error\n", - kcurrent_lib_name); - return false; - } - - bool fmt_found = false; - while (wav_file_.read(buffer, 4)) { - uint32_t sub_chunk_size = read_le(wav_file_); - if (!wav_file_) { - std::cerr << "Read error after sub-chunk ID\n"; - arcforge::embedded::utils::Logger::GetInstance().Error("Not a RIFF file or read error\n", - kcurrent_lib_name); - return false; - } - - if (std::memcmp(buffer, "fmt ", 4) == 0) { - fmt_found = true; - uint16_t audio_format = read_le(wav_file_); - if (!wav_file_) { - std::cerr << "Read error (audio_format)\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - channels_ = static_cast(read_le(wav_file_)); // uint16_t to int (安全) - if (!wav_file_) { - std::cerr << "Read error (channels)\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - - // sample_rate_ 是 int, read_le 返回 uint32_t - uint32_t sr_u32 = read_le(wav_file_); // <-- line 87 原警告处 - if (!wav_file_) { - std::cerr << "Read error (sample_rate)\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - if (sr_u32 > static_cast(std::numeric_limits::max())) { // 检查溢出 - std::cerr << "Sample rate value too large for int type.\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - sample_rate_ = static_cast(sr_u32); // 明确转换 - - read_le(wav_file_); // Byte rate - read_le(wav_file_); // Block align - bits_per_sample_ = - static_cast(read_le(wav_file_)); // uint16_t to int (安全) - if (!wav_file_) { - std::cerr << "Read error (bits_per_sample)\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - - if (audio_format != 1) { - std::cerr << "Not PCM format in WAV\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - if (sample_rate_ != expected_sample_rate) { - std::cerr << "Warning: WAV sample rate (" << sample_rate_ - << ") differs from expected (" << expected_sample_rate - << "). Output might be incorrect.\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - } - if (channels_ <= 0) { // 增加对声道数的有效性检查 - std::cerr << "Invalid number of channels: " << channels_ << "\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - if (channels_ != expected_channels && - expected_channels != 0) { // 允许 expected_channels 为0表示不检查 - std::cerr << "Warning: WAV channels (" << channels_ << ") differs from expected (" - << expected_channels << "). Will use first channel if multi-channel.\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - } - if (bits_per_sample_ != 16) { - std::cerr << "WAV not 16-bit. Only 16-bit PCM is supported.\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - - // uint32_t 通常大于16,这里用 streamoff 做 seek 偏移量 - if (sub_chunk_size > 16) { // 16 is sizeof(common PCM fmt sub-chunk data part) - std::streamoff offset = static_cast(sub_chunk_size) - 16; - wav_file_.seekg(offset, std::ios::cur); - if (!wav_file_) { - std::cerr << "Seek error past fmt chunk\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - } - break; - } else { - wav_file_.seekg(static_cast(sub_chunk_size), std::ios::cur); - if (!wav_file_) { - std::cerr << "Seek error past other chunk\n"; - arcforge::embedded::utils::Logger::GetInstance().Error( - "Not a RIFF file or read error\n", kcurrent_lib_name); - return false; - } - } - } - if (!fmt_found) { - std::cerr << "\"fmt \" chunk not found or read error before finding it.\n"; - arcforge::embedded::utils::Logger::GetInstance().Error("Not a RIFF file or read error\n", - kcurrent_lib_name); - return false; - } - - bool data_found = false; - while (wav_file_.read(buffer, 4)) { - uint32_t sub_chunk_size_data_u32 = read_le(wav_file_); - if (!wav_file_) { - std::cerr << "Read error after data sub-chunk ID\n"; - return false; - } - - if (std::memcmp(buffer, "data", 4) == 0) { - data_found = true; - // data_chunk_pos_ 是 std::streamoff, tellg() 返回 std::streampos (可以隐式转为 streamoff) - data_chunk_pos_ = wav_file_.tellg(); - // 如果 data_chunk_pos_ 声明为 size_t: - // data_chunk_pos_ = static_cast( - // wav_file_.tellg()); // <-- line 132 (假设 data_chunk_pos_ 是 size_t) - - // 如果是 std::streamoff 则不需要cast - data_chunk_size_ = - static_cast(sub_chunk_size_data_u32); // uint32_t to size_t (安全) - break; - } else { - wav_file_.seekg(static_cast(sub_chunk_size_data_u32), std::ios::cur); - if (!wav_file_) { - std::cerr << "Seek error past other chunk (while searching data)\n"; - return false; - } - } - } - if (!data_found) { - std::cerr << "\"data\" chunk not found or read error before finding it.\n"; - return false; - } - return true; -} - -size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_samples_to_read) { - if (!is_opened_ || eof_) { - out_samples.clear(); - return 0; - } - if (bits_per_sample_ == 0 || channels_ == 0) { // 防御除零 - std::cerr << "Error: bits_per_sample or channels is zero." << std::endl; - out_samples.clear(); - eof_ = true; - return 0; - } - - // 所有涉及大小计算的都尽量用 size_t - size_t bytes_per_sample_all_channels = static_cast(bits_per_sample_ / 8 * channels_); - if (bytes_per_sample_all_channels == 0) { // 进一步防御 - std::cerr << "Error: bytes_per_sample_all_channels is zero." << std::endl; - out_samples.clear(); - eof_ = true; - return 0; - } - - size_t max_samples_remaining_in_chunk = 0; - if (data_chunk_size_ >= - bytes_read_from_data_chunk_) { // 确保减法不溢出 (虽然都是size_t理论上ok) - max_samples_remaining_in_chunk = (data_chunk_size_ - bytes_read_from_data_chunk_) / - bytes_per_sample_all_channels; // <-- line 155 - } else { - // Should not happen if logic is correct, but defensive. - std::cerr << "Warning: bytes_read_from_data_chunk_ exceeds data_chunk_size_." << std::endl; - } - - size_t actual_samples_to_read = std::min(num_samples_to_read, max_samples_remaining_in_chunk); - - if (actual_samples_to_read == 0) { - eof_ = true; - out_samples.clear(); - return 0; - } - - out_samples.resize(actual_samples_to_read); // 用 size_t - std::vector temp_s16_buffer(actual_samples_to_read * - static_cast(channels_)); // <-- line 166 - - size_t bytes_to_read = actual_samples_to_read * bytes_per_sample_all_channels; // <-- line 169 - // (bits_per_sample_/8) 也用size_t - wav_file_.read( - reinterpret_cast(temp_s16_buffer.data()), - static_cast(bytes_to_read)); // read 的第二个参数是 std::streamsize - - if (!wav_file_ && !wav_file_.eof()) { // 检查读取错误(非EOF) - std::cerr << "Error reading WAV data." << std::endl; - out_samples.clear(); - eof_ = true; - return 0; - } - - size_t bytes_just_read = - static_cast(wav_file_.gcount()); // <-- line 170, gcount() 返回 streamsize - size_t samples_just_read_per_channel = 0; - if (bytes_per_sample_all_channels > 0) { - samples_just_read_per_channel = - bytes_just_read / bytes_per_sample_all_channels; // <-- line 171 - } - - bytes_read_from_data_chunk_ += bytes_just_read; - - if (samples_just_read_per_channel < actual_samples_to_read) { - eof_ = true; - out_samples.resize(samples_just_read_per_channel); - if (samples_just_read_per_channel == 0 && bytes_just_read > 0) { - std::cerr << "Warning: Read 0 samples but " << bytes_just_read - << " bytes. Possible partial sample read or end of data chunk." << std::endl; - } - } - - if (static_cast(channels_) == - 0) { // 再次检查 channels_,虽然 ParseWavHeader 应该已经保证 - std::cerr << "Error: channels_ is zero before processing samples." << std::endl; - out_samples.clear(); // 清空,因为无法处理 - return 0; - } - - for (size_t i = 0; i < samples_just_read_per_channel; ++i) { - // temp_s16_buffer[i * static_cast(channels_)] // <-- line 186 - out_samples[i] = - static_cast(temp_s16_buffer[i * static_cast(channels_)]) / 32768.0f; - } - - if (bytes_read_from_data_chunk_ >= data_chunk_size_) { - eof_ = true; - } - if (wav_file_.eof()) { // 文件流的 EOF 状态也检查 - eof_ = true; - } - - return samples_just_read_per_channel; -} - -// 假设 WavReader.h 中有: -// int channels_; -// int sample_rate_; -// int bits_per_sample_; -// std::streamoff data_chunk_pos_; // 或者 size_t data_chunk_pos_; -// size_t data_chunk_size_; -// size_t bytes_read_from_data_chunk_; -// bool is_opened_; -// bool eof_; -// std::ifstream wav_file_; -} // namespace ai_asr -} // namespace embedded -} // namespace arcforge \ No newline at end of file diff --git a/libs/asr_engine/src/wav-reader/wav-reader.cpp b/libs/asr_engine/src/wav-reader/wav-reader.cpp index 6689912..97849ee 100644 --- a/libs/asr_engine/src/wav-reader/wav-reader.cpp +++ b/libs/asr_engine/src/wav-reader/wav-reader.cpp @@ -25,7 +25,7 @@ namespace arcforge { namespace embedded { namespace ai_asr { -// Helper to read little-endian values (保持不变,这个很好) +// Helper to read little-endian values template T read_le(std::istream& is) { T val; @@ -33,7 +33,7 @@ T read_le(std::istream& is) { return val; } -WavReader::WavReader() {} // 默认构造函数 +WavReader::WavReader() {} WavReader::~WavReader() { Close(); @@ -56,12 +56,7 @@ bool WavReader::Open(const std::string& filepath, int expected_sample_rate, int return false; } - // data_chunk_pos_ 是 std::streamoff,seekg 参数类型是 std::streamoff 或 std::streampos - // 这里不需要转换,本身是匹配的。原来的警告可能是因为 data_chunk_pos_ 之前被声明为 size_t? - // 确认 data_chunk_pos_ 在 .h 中是 std::streamoff。 - wav_file_.seekg(data_chunk_pos_, std::ios::beg); // 定位到数据块开始 - // 为了更明确,如果 data_chunk_pos_ 是 size_t,可以这样: - // wav_file_.seekg(static_cast(data_chunk_pos_), std::ios::beg); // <-- line 35 + wav_file_.seekg(data_chunk_pos_, std::ios::beg); if (!wav_file_) { arcforge::embedded::utils::Logger::GetInstance().Error( @@ -88,26 +83,27 @@ bool WavReader::Open(const std::string& filepath, int expected_sample_rate, int void WavReader::Close() { if (wav_file_.is_open()) { wav_file_.close(); - arcforge::embedded::utils::Logger::GetInstance().Info("WAV file closed.", kcurrent_lib_name); + arcforge::embedded::utils::Logger::GetInstance().Info("WAV file closed.", + kcurrent_lib_name); } is_opened_ = false; - eof_ = true; // 在关闭时,逻辑上也是文件末尾 + eof_ = true; } bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) { char buffer[4]; // RIFF chunk wav_file_.read(buffer, 4); - if (!wav_file_ || std::memcmp(buffer, "RIFF", 4) != 0) { // 增加对 read 失败的检查 + if (!wav_file_ || std::memcmp(buffer, "RIFF", 4) != 0) { arcforge::embedded::utils::Logger::GetInstance().Error("Not a RIFF file or read error", - kcurrent_lib_name); + kcurrent_lib_name); return false; } read_le(wav_file_); wav_file_.read(buffer, 4); if (!wav_file_ || std::memcmp(buffer, "WAVE", 4) != 0) { arcforge::embedded::utils::Logger::GetInstance().Error("Not a WAVE file or read error", - kcurrent_lib_name); + kcurrent_lib_name); return false; } @@ -116,7 +112,7 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) uint32_t sub_chunk_size = read_le(wav_file_); if (!wav_file_) { arcforge::embedded::utils::Logger::GetInstance().Error("Read error after sub-chunk ID", - kcurrent_lib_name); + kcurrent_lib_name); return false; } @@ -125,43 +121,41 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) uint16_t audio_format = read_le(wav_file_); if (!wav_file_) { arcforge::embedded::utils::Logger::GetInstance().Error("Read error (audio_format)", - kcurrent_lib_name); + kcurrent_lib_name); return false; } - channels_ = static_cast(read_le(wav_file_)); // uint16_t to int (安全) + channels_ = static_cast(read_le(wav_file_)); if (!wav_file_) { arcforge::embedded::utils::Logger::GetInstance().Error("Read error (channels)", - kcurrent_lib_name); + kcurrent_lib_name); return false; } - // sample_rate_ 是 int, read_le 返回 uint32_t - uint32_t sr_u32 = read_le(wav_file_); // <-- line 87 原警告处 + uint32_t sr_u32 = read_le(wav_file_); if (!wav_file_) { arcforge::embedded::utils::Logger::GetInstance().Error("Read error (sample_rate)", - kcurrent_lib_name); + kcurrent_lib_name); return false; } - if (sr_u32 > static_cast(std::numeric_limits::max())) { // 检查溢出 + if (sr_u32 > static_cast(std::numeric_limits::max())) { arcforge::embedded::utils::Logger::GetInstance().Error( "Sample rate value too large for int type.", kcurrent_lib_name); return false; } - sample_rate_ = static_cast(sr_u32); // 明确转换 + sample_rate_ = static_cast(sr_u32); read_le(wav_file_); // Byte rate read_le(wav_file_); // Block align - bits_per_sample_ = - static_cast(read_le(wav_file_)); // uint16_t to int (安全) + bits_per_sample_ = static_cast(read_le(wav_file_)); if (!wav_file_) { - arcforge::embedded::utils::Logger::GetInstance().Error("Read error (bits_per_sample)", - kcurrent_lib_name); + arcforge::embedded::utils::Logger::GetInstance().Error( + "Read error (bits_per_sample)", kcurrent_lib_name); return false; } if (audio_format != 1) { arcforge::embedded::utils::Logger::GetInstance().Error("Not PCM format in WAV", - kcurrent_lib_name); + kcurrent_lib_name); return false; } if (sample_rate_ != expected_sample_rate) { @@ -169,21 +163,21 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) oss << "WAV sample rate (" << sample_rate_ << ") differs from expected (" << expected_sample_rate << "). Output might be incorrect."; arcforge::embedded::utils::Logger::GetInstance().Warning(oss.str(), - kcurrent_lib_name); + kcurrent_lib_name); } - if (channels_ <= 0) { // 增加对声道数的有效性检查 + if (channels_ <= 0) { std::ostringstream oss; oss << "Invalid number of channels: " << channels_; - arcforge::embedded::utils::Logger::GetInstance().Error(oss.str(), kcurrent_lib_name); + arcforge::embedded::utils::Logger::GetInstance().Error(oss.str(), + kcurrent_lib_name); return false; } - if (channels_ != expected_channels && - expected_channels != 0) { // 允许 expected_channels 为0表示不检查 + if (channels_ != expected_channels && expected_channels != 0) { std::ostringstream oss; oss << "WAV channels (" << channels_ << ") differs from expected (" << expected_channels << "). Will use first channel if multi-channel."; arcforge::embedded::utils::Logger::GetInstance().Warning(oss.str(), - kcurrent_lib_name); + kcurrent_lib_name); } if (bits_per_sample_ != 16) { arcforge::embedded::utils::Logger::GetInstance().Error( @@ -191,7 +185,6 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) return false; } - // uint32_t 通常大于16,这里用 streamoff 做 seek 偏移量 if (sub_chunk_size > 16) { // 16 is sizeof(common PCM fmt sub-chunk data part) std::streamoff offset = static_cast(sub_chunk_size) - 16; wav_file_.seekg(offset, std::ios::cur); @@ -205,8 +198,8 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) } else { wav_file_.seekg(static_cast(sub_chunk_size), std::ios::cur); if (!wav_file_) { - arcforge::embedded::utils::Logger::GetInstance().Error("Seek error past other chunk", - kcurrent_lib_name); + arcforge::embedded::utils::Logger::GetInstance().Error( + "Seek error past other chunk", kcurrent_lib_name); return false; } } @@ -228,15 +221,10 @@ bool WavReader::ParseWavHeader(int expected_sample_rate, int expected_channels) if (std::memcmp(buffer, "data", 4) == 0) { data_found = true; - // data_chunk_pos_ 是 std::streamoff, tellg() 返回 std::streampos (可以隐式转为 streamoff) + data_chunk_pos_ = wav_file_.tellg(); - // 如果 data_chunk_pos_ 声明为 size_t: - // data_chunk_pos_ = static_cast( - // wav_file_.tellg()); // <-- line 132 (假设 data_chunk_pos_ 是 size_t) - // 如果是 std::streamoff 则不需要cast - data_chunk_size_ = - static_cast(sub_chunk_size_data_u32); // uint32_t to size_t (安全) + data_chunk_size_ = static_cast(sub_chunk_size_data_u32); // uint32_t to size_t break; } else { wav_file_.seekg(static_cast(sub_chunk_size_data_u32), std::ios::cur); @@ -260,7 +248,7 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample out_samples.clear(); return 0; } - if (bits_per_sample_ == 0 || channels_ == 0) { // 防御除零 + if (bits_per_sample_ == 0 || channels_ == 0) { //Defensive division by zero arcforge::embedded::utils::Logger::GetInstance().Error( "Error: bits_per_sample or channels is zero.", kcurrent_lib_name); out_samples.clear(); @@ -268,9 +256,8 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample return 0; } - // 所有涉及大小计算的都尽量用 size_t size_t bytes_per_sample_all_channels = static_cast(bits_per_sample_ / 8 * channels_); - if (bytes_per_sample_all_channels == 0) { // 进一步防御 + if (bytes_per_sample_all_channels == 0) { arcforge::embedded::utils::Logger::GetInstance().Error( "Error: bytes_per_sample_all_channels is zero.", kcurrent_lib_name); out_samples.clear(); @@ -279,10 +266,9 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample } size_t max_samples_remaining_in_chunk = 0; - if (data_chunk_size_ >= - bytes_read_from_data_chunk_) { // 确保减法不溢出 (虽然都是size_t理论上ok) - max_samples_remaining_in_chunk = (data_chunk_size_ - bytes_read_from_data_chunk_) / - bytes_per_sample_all_channels; // <-- line 155 + if (data_chunk_size_ >= bytes_read_from_data_chunk_) { + max_samples_remaining_in_chunk = + (data_chunk_size_ - bytes_read_from_data_chunk_) / bytes_per_sample_all_channels; } else { // Should not happen if logic is correct, but defensive. arcforge::embedded::utils::Logger::GetInstance().Warning( @@ -297,30 +283,26 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample return 0; } - out_samples.resize(actual_samples_to_read); // 用 size_t - std::vector temp_s16_buffer(actual_samples_to_read * - static_cast(channels_)); // <-- line 166 + out_samples.resize(actual_samples_to_read); + std::vector temp_s16_buffer(actual_samples_to_read * static_cast(channels_)); - size_t bytes_to_read = actual_samples_to_read * bytes_per_sample_all_channels; // <-- line 169 - // (bits_per_sample_/8) 也用size_t - wav_file_.read( - reinterpret_cast(temp_s16_buffer.data()), - static_cast(bytes_to_read)); // read 的第二个参数是 std::streamsize + size_t bytes_to_read = actual_samples_to_read * bytes_per_sample_all_channels; - if (!wav_file_ && !wav_file_.eof()) { // 检查读取错误(非EOF) + wav_file_.read(reinterpret_cast(temp_s16_buffer.data()), + static_cast(bytes_to_read)); + + if (!wav_file_ && !wav_file_.eof()) { arcforge::embedded::utils::Logger::GetInstance().Error("Error reading WAV data.", - kcurrent_lib_name); + kcurrent_lib_name); out_samples.clear(); eof_ = true; return 0; } - size_t bytes_just_read = - static_cast(wav_file_.gcount()); // <-- line 170, gcount() 返回 streamsize + size_t bytes_just_read = static_cast(wav_file_.gcount()); size_t samples_just_read_per_channel = 0; if (bytes_per_sample_all_channels > 0) { - samples_just_read_per_channel = - bytes_just_read / bytes_per_sample_all_channels; // <-- line 171 + samples_just_read_per_channel = bytes_just_read / bytes_per_sample_all_channels; } bytes_read_from_data_chunk_ += bytes_just_read; @@ -336,16 +318,15 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample } } - if (static_cast(channels_) == - 0) { // 再次检查 channels_,虽然 ParseWavHeader 应该已经保证 + if (static_cast(channels_) == 0) { arcforge::embedded::utils::Logger::GetInstance().Error( "Error: channels_ is zero before processing samples.", kcurrent_lib_name); - out_samples.clear(); // 清空,因为无法处理 + out_samples.clear(); return 0; } for (size_t i = 0; i < samples_just_read_per_channel; ++i) { - // temp_s16_buffer[i * static_cast(channels_)] // <-- line 186 + out_samples[i] = static_cast(temp_s16_buffer[i * static_cast(channels_)]) / 32768.0f; } @@ -353,23 +334,13 @@ size_t WavReader::ReadSamples(std::vector& out_samples, size_t num_sample if (bytes_read_from_data_chunk_ >= data_chunk_size_) { eof_ = true; } - if (wav_file_.eof()) { // 文件流的 EOF 状态也检查 + if (wav_file_.eof()) { eof_ = true; } return samples_just_read_per_channel; } -// 假设 WavReader.h 中有: -// int channels_; -// int sample_rate_; -// int bits_per_sample_; -// std::streamoff data_chunk_pos_; // 或者 size_t data_chunk_pos_; -// size_t data_chunk_size_; -// size_t bytes_read_from_data_chunk_; -// bool is_opened_; -// bool eof_; -// std::ifstream wav_file_; } // namespace ai_asr } // namespace embedded } // namespace arcforge \ No newline at end of file diff --git a/libs/network/include/Network/base/base.h b/libs/network/include/Network/base/base.h index 3b3aafc..4576678 100644 --- a/libs/network/include/Network/base/base.h +++ b/libs/network/include/Network/base/base.h @@ -23,16 +23,14 @@ #pragma once #include "Network/common/common-types.h" -#include "Network/pch.h" // 你的干净PCH (只包含 common-types.h 和标准库) - -// #include "base-config.h" // 你的干净配置 +#include "Network/pch.h" namespace arcforge { namespace embedded { namespace network_socket { -// 向前声明 PIMPL 实现类 -class BaseImpl; // <--- 关键 +// forward declaration of PIMPL implementation class +class BaseImpl; static const std::string k_empty_socket_path_sentinel = ""; @@ -75,9 +73,8 @@ class Base { virtual SocketReturnValue connectToServer(); // server-utilized-only functions - virtual SocketReturnValue startServer( - const size_t& timeout = static_cast(-1)); // 启动Unix域socket服务器 - // std::unique_ptr acceptClient(); // 接受客户端连接 + virtual SocketReturnValue startServer(const size_t& timeout = static_cast(-1)); + virtual SocketAcceptReturn acceptClient(); virtual SocketReturnValue unlinkSocketPath(); diff --git a/libs/network/include/Network/base/impl/base-impl.h b/libs/network/include/Network/base/impl/base-impl.h index abf5b32..19841a7 100644 --- a/libs/network/include/Network/base/impl/base-impl.h +++ b/libs/network/include/Network/base/impl/base-impl.h @@ -20,15 +20,12 @@ * SOFTWARE. */ -// 文件: base/impl/base-impl.h +// libs/network/include/Network/base/impl/base-impl.h #pragma once #include "Network/common/common-types.h" #include "Network/pch.h" -// 向前声明你自己的配置类,因为 Impl 需要它 -// #include "base/base-config.h" // << 注意路径,相对于 impl 目录调整 - namespace arcforge { namespace embedded { namespace network_socket { @@ -49,12 +46,13 @@ struct SocketAcceptImplReturn { class BaseImpl { public: BaseImpl(); - ~BaseImpl(); // 确保在 .cpp 中定义 + ~BaseImpl(); - // 禁止拷贝和赋值 + // forbitd copy and assignment BaseImpl(const BaseImpl&) = delete; BaseImpl& operator=(const BaseImpl&) = delete; - // 允许移动 (如果需要) + + // permit move semantics BaseImpl(BaseImpl&&) noexcept = default; BaseImpl& operator=(BaseImpl&&) noexcept = default; @@ -84,7 +82,7 @@ class BaseImpl { // server-utilized-only functions SocketReturnValue startServer( - const size_t& timeout = static_cast(-1)); // 启动Unix域socket服务器 + const size_t& timeout = static_cast(-1)); SocketAcceptImplReturn acceptClient(); SocketReturnValue unlinkSocketPath(); diff --git a/libs/network/include/Network/client/client.h b/libs/network/include/Network/client/client.h index 756e0c5..caba6cd 100644 --- a/libs/network/include/Network/client/client.h +++ b/libs/network/include/Network/client/client.h @@ -40,8 +40,6 @@ class ClientBase : public Base { ClientBase(ClientBase&&) noexcept = default; ClientBase& operator=(ClientBase&&) noexcept = default; - // // 核心功能 - // SocketReturnValue connectToServer(); // 连接到服务器 }; } // namespace network_socket diff --git a/libs/network/include/Network/common/system-info.h b/libs/network/include/Network/common/system-info.h index 0a55be0..3881b3f 100644 --- a/libs/network/include/Network/common/system-info.h +++ b/libs/network/include/Network/common/system-info.h @@ -28,8 +28,8 @@ namespace embedded { namespace network_socket { /** - * @brief 获取 库的编译时版本字符串。 - * @return 一个格式为 "major.minor.patch" 的字符串。 + * @brief Obtain the library's compile-time version string. + * @return A string in the format "major.minor.patch". */ std::string get_network_socket_library_version(); diff --git a/libs/network/include/Network/pch.h b/libs/network/include/Network/pch.h index 8b9d38a..2da0195 100644 --- a/libs/network/include/Network/pch.h +++ b/libs/network/include/Network/pch.h @@ -29,7 +29,7 @@ #include // For std::unique_ptr (though direct return is fine here) #include //std::ostringstream #include // For std::runtime_error -#include // 确保 string/vector/memory 这些公共接口用到的被包含 +#include #include #include #include //read() close() diff --git a/libs/network/include/Network/server/server.h b/libs/network/include/Network/server/server.h index 80a3af8..05b8bdd 100644 --- a/libs/network/include/Network/server/server.h +++ b/libs/network/include/Network/server/server.h @@ -33,14 +33,6 @@ class ServerBase : public Base { public: ServerBase(); ~ServerBase(); - - // // 核心功能 - // SocketReturnValue startServer( - // const size_t& timeout = static_cast(-1)); // 启动Unix域socket服务器 - // // std::unique_ptr acceptClient(); // 接受客户端连接 - // SocketAcceptReturn acceptClient(); - // SocketReturnValue unlinkSocketPath(); - }; } // namespace network_socket diff --git a/libs/network/src/base/CMakeLists.txt b/libs/network/src/base/CMakeLists.txt index 760457a..554d1c5 100644 --- a/libs/network/src/base/CMakeLists.txt +++ b/libs/network/src/base/CMakeLists.txt @@ -34,19 +34,6 @@ set(BASE_PUBLIC_HEADERS # "${INCLUDE_DIR}/Network/base/base-config.h" "${INCLUDE_DIR}/Network/base/exception.h" ) -#[[ -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${BASE_SOURCES} - PARENT_SCOPE) - -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${BASE_PUBLIC_HEADERS} - PARENT_SCOPE) - -install(FILES ${BASE_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/base) -]] - target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SOURCES} diff --git a/libs/network/src/base/base-config.cpp b/libs/network/src/base/base-config.cpp index f1c4c99..05eec0e 100644 --- a/libs/network/src/base/base-config.cpp +++ b/libs/network/src/base/base-config.cpp @@ -19,7 +19,7 @@ // SOFTWARE. #include "base-config.h" -// #include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API +// #include "sherpa-onnx/c-api/cxx-api.h" namespace arcforge { namespace embedded { diff --git a/libs/network/src/base/base.cpp b/libs/network/src/base/base.cpp index 8dc3c2c..3db14ab 100644 --- a/libs/network/src/base/base.cpp +++ b/libs/network/src/base/base.cpp @@ -18,46 +18,22 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// 文件: base/base.cpp -#include "Network/base/base.h" // 包含你更新后的公共头文件 (base.h) -#include "Network/base/impl/base-impl.h" // 包含PIMPL实现类的头文件 (注意路径) - -// !! 不再需要在这里包含 的头文件 -// !! 也不再需要 using namespace sherpa_onnx::cxx; +// libs/network/src/base/base.cpp +#include "Network/base/base.h" +#include "Network/base/impl/base-impl.h" namespace arcforge { namespace embedded { namespace network_socket { -// 构造函数: 创建 PIMPL 对象 -Base::Base() : impl_(std::make_unique()) { - // 原来的 cout "Base object constructed..." 应该移到 BaseImpl 的构造函数中 - // 或者如果你希望接口层也有日志,可以保留,但通常 Impl 构造时打日志更合适 -} +Base::Base() : impl_(std::make_unique()) {} Base::Base(std::unique_ptr param_impl) : impl_(std::move(param_impl)) {} -// 析构函数: 默认实现即可,std::unique_ptr 会自动处理 impl_ 的销毁 -// 重要的是这个定义要放在 .cpp 文件中,这样编译器在销毁 impl_ 时能看到 BaseImpl 的完整定义 -Base::~Base() { - // 原来的 cout "Base cleaned up..." 应该移到 BaseImpl 的析构函数中 -} +Base::~Base() {} -// 移动构造函数 (通常对于 PIMPL 是需要的) -// Base::Base(Base&& other) noexcept : impl_(std::move(other.impl_)) { -// // 移动构造函数应该保证noexcept,去掉抛出异常的代码 -// // impl_的移动已经在初始化列表中完成 -// } Base::Base(Base&& other) noexcept = default; -// 移动赋值运算符 (通常对于 PIMPL 是需要的) -// Base& Base::operator=(Base&& other) noexcept { -// if (this != &other) { -// impl_ = std::move(other.impl_); -// // std::cout << "Base move assigned." << std::endl; -// } -// return *this; -// } Base& Base::operator=(Base&& other) noexcept = default; SocketStatus Base::isSocketFDValid() const { diff --git a/libs/network/src/base/impl/base-impl.cpp b/libs/network/src/base/impl/base-impl.cpp index 83e72a8..c11f3f0 100644 --- a/libs/network/src/base/impl/base-impl.cpp +++ b/libs/network/src/base/impl/base-impl.cpp @@ -18,16 +18,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// 文件: base/impl/base-impl.cpp +// libs/network/src/base/impl/base-impl.cpp #include "Network/base/impl/base-impl.h" #include "Utils/logger/logger.h" -// 在这里包含所有必需的 sherpa-onnx 头文件 -// #include "sherpa-onnx/c-api/cxx-api.h" // 使用C++ API - -// 如果 base-config.h 不在默认的 include 路径,也需要正确包含 -// #include "base/base-config.h" (如果上一层CMakeLists.txt已添加src为include目录则可能不需要) - namespace arcforge { namespace embedded { namespace network_socket { @@ -41,14 +35,14 @@ BaseImpl::BaseImpl() socket_mutex_(std::make_unique()), log_mutex_(std::make_unique()) { arcforge::embedded::utils::Logger::GetInstance().Info("BaseImpl object constructed.", - kcurrent_lib_name); + kcurrent_lib_name); } -// 析构函数的定义需要在这里,因为 unique_ptr 等需要完整类型 BaseImpl::~BaseImpl() { // socketfd_ = -1; closeSocket_safe(); - arcforge::embedded::utils::Logger::GetInstance().Info("BaseImpl cleaned up.", kcurrent_lib_name); + arcforge::embedded::utils::Logger::GetInstance().Info("BaseImpl cleaned up.", + kcurrent_lib_name); } /*=================================================== @@ -82,7 +76,7 @@ void BaseImpl::closeSocket() { } else { // log_error("socketfd is invalid, alert!!"); arcforge::embedded::utils::Logger::GetInstance().Error("socketfd is invalid, alert!!", - kcurrent_lib_name); + kcurrent_lib_name); } } @@ -106,8 +100,8 @@ void BaseImpl::setFD(int fd) { // socketfd_ = fd; //----------------------------------------------- - // 如果已经持有一个有效的fd,先关闭它 - if (socketfd_ >= 0) { // 或者使用 isSocketFDValid_safe() + // if we have a valid existing fd, close it first + if (socketfd_ >= 0) { arcforge::embedded::utils::Logger::GetInstance().Info( "BaseImpl::setFD - Closing existing socket FD: " + std::to_string(socketfd_), @@ -122,7 +116,6 @@ void BaseImpl::setFD(int fd) { } else { arcforge::embedded::utils::Logger::GetInstance().Info( "BaseImpl::setFD - FD set to invalid value: " + std::to_string(fd), kcurrent_lib_name); - } } @@ -154,37 +147,7 @@ void BaseImpl::setSocketPath(const std::string& path) { socketpath_ = path; } -/*=================================================== - * rx & tx functions - *===================================================*/ -// --- sendFloat_safe (简化版) --- -// SocketReturnValue BaseImpl::sendFloat_safe(const std::vector& data) { -// std::lock_guard lock(*(socket_mutex_.get())); - -// // 1. fd validation verification -// if (socketfd_ < 0) { -// return SocketReturnValue::kfd_illegal; -// } - -// uint32_t count = static_cast(data.size()); - -// if (::send(socketfd_, &count, sizeof(count), 0) != sizeof(count)) { -// arcforge::embedded::utils::Logger::GetInstance().Info("sendFloat_safe: Failed to send count."); -// return SocketReturnValue::ksendcount_failed; -// } - -// if (count > 0) { -// size_t bytes_to_send = count * sizeof(float); -// if (::send(socketfd_, data.data(), bytes_to_send, 0) != -// static_cast(bytes_to_send)) { -// arcforge::embedded::utils::Logger::GetInstance().Info("sendFloat_safe: Failed to send data."); -// return SocketReturnValue::ksenddata_failed; -// } -// } -// arcforge::embedded::utils::Logger::GetInstance().Info("sendFloat_safe: Sent " + std::to_string(count) + " floats."); -// return SocketReturnValue::ksuccess; -// } -// --- sendFloat_safe (修正版) --- +// --- sendFloat_safe --- SocketReturnValue BaseImpl::sendFloat_safe(const std::vector& data) { std::lock_guard lock(*(socket_mutex_.get())); @@ -194,7 +157,7 @@ SocketReturnValue BaseImpl::sendFloat_safe(const std::vector& data) { uint32_t count = static_cast(data.size()); - // 发送长度头 + // transmit the length header if (::send(socketfd_, &count, sizeof(count), 0) != sizeof(count)) { // arcforge::embedded::utils::Logger::GetInstance().Info("sendFloat_safe: Failed to send count. errno: " + std::to_string(errno)); arcforge::embedded::utils::Logger::GetInstance().Error( @@ -203,7 +166,7 @@ SocketReturnValue BaseImpl::sendFloat_safe(const std::vector& data) { return SocketReturnValue::ksendcount_failed; } - // 发送数据体 (使用循环) + // transmit the data body (using a loop) if (count > 0) { size_t bytes_to_send = count * sizeof(float); size_t bytes_has_sent = 0; @@ -230,7 +193,7 @@ SocketReturnValue BaseImpl::sendFloat_safe(const std::vector& data) { return SocketReturnValue::ksuccess; } -// --- receiveFloat_safe (简化版) --- +// --- receiveFloat_safe --- SocketReturnValue BaseImpl::receiveFloat_safe(std::vector& data) { std::lock_guard lock(*(socket_mutex_.get())); @@ -283,8 +246,8 @@ SocketReturnValue BaseImpl::receiveFloat_safe(std::vector& data) { // arcforge::embedded::utils::Logger::GetInstance().Info(temp_str.str()); arcforge::embedded::utils::Logger::GetInstance().Info(temp_str.str(), kcurrent_lib_name); - // 4. 可选:对 count 进行合理性检查 - const uint32_t MAX_ALLOWED_FLOATS = 1024 * 1024; // 示例:最大允许约1M个float (4MB) + // 4. optional: sanity check on count + const uint32_t MAX_ALLOWED_FLOATS = 1024 * 1024; if (count > MAX_ALLOWED_FLOATS) { // arcforge::embedded::utils::Logger::GetInstance().Info("receiveFloat_safe: Received count (" + std::to_string(count) + // ") exceeds MAX_ALLOWED_FLOATS (" + std::to_string(MAX_ALLOWED_FLOATS) + "). Aborting."); @@ -293,17 +256,15 @@ SocketReturnValue BaseImpl::receiveFloat_safe(std::vector& data) { ") exceeds MAX_ALLOWED_FLOATS (" + std::to_string(MAX_ALLOWED_FLOATS) + "). Aborting.", kcurrent_lib_name); - // 客户端可能发送了一个无效的超大count,这可能是协议错误或攻击 - // 服务器可以选择关闭连接或返回特定错误 - // close(socketfd_); // 考虑是否要主动关闭 - return SocketReturnValue::kcount_too_large; // 需要定义这个错误码 + + return SocketReturnValue::kcount_too_large; } if (count == 0) { // end of file, empty block // arcforge::embedded::utils::Logger::GetInstance().Info("receiveFloat_safe: Received EOF marker (empty chunk)"); arcforge::embedded::utils::Logger::GetInstance().Warning( "receiveFloat_safe: Received EOF marker (empty chunk)", kcurrent_lib_name); - return SocketReturnValue::keof; // 添加新的状态码 + return SocketReturnValue::keof; } // 5. receive data @@ -342,7 +303,7 @@ SocketReturnValue BaseImpl::receiveFloat_safe(std::vector& data) { return SocketReturnValue::ksuccess; } -// // --- sendString_safe (简化版) --- +// // --- sendString_safe --- // SocketReturnValue BaseImpl::sendString_safe(const std::string& message) { // std::lock_guard lock(*(socket_mutex_.get())); @@ -369,7 +330,7 @@ SocketReturnValue BaseImpl::receiveFloat_safe(std::vector& data) { // arcforge::embedded::utils::Logger::GetInstance().Info("sendString_safe: Sent string of length " + std::to_string(len) + "."); // return SocketReturnValue::ksuccess; // } -// --- sendString_safe (修正版) --- +// --- sendString_safe --- SocketReturnValue BaseImpl::sendString_safe(const std::string& message) { std::lock_guard lock(*(socket_mutex_.get())); @@ -378,7 +339,7 @@ SocketReturnValue BaseImpl::sendString_safe(const std::string& message) { } uint32_t len = static_cast(message.length()); - // 发送长度头 + if (::send(socketfd_, &len, sizeof(len), 0) != sizeof(len)) { arcforge::embedded::utils::Logger::GetInstance().Info( "sendString_safe: Failed to send length. errno: " + std::to_string(errno), @@ -386,7 +347,6 @@ SocketReturnValue BaseImpl::sendString_safe(const std::string& message) { return SocketReturnValue::ksendlength_failed; } - // 发送数据体 (使用循环) if (len > 0) { size_t bytes_to_send = len; size_t bytes_has_sent = 0; @@ -410,7 +370,7 @@ SocketReturnValue BaseImpl::sendString_safe(const std::string& message) { return SocketReturnValue::ksuccess; } -// --- receiveString_safe (简化版) --- +// --- receiveString_safe --- SocketReturnValue BaseImpl::receiveString_safe(std::string& message) { std::lock_guard lock(*(socket_mutex_.get())); @@ -429,7 +389,7 @@ SocketReturnValue BaseImpl::receiveString_safe(std::string& message) { arcforge::embedded::utils::Logger::GetInstance().Info( "receiveString_safe: Peer closed connection while trying to receive length.", kcurrent_lib_name); - return SocketReturnValue::kpeer_abnormally_closed; // 对端优雅关闭也视为异常 + return SocketReturnValue::kpeer_abnormally_closed; } if (len_recv_bytes < 0) { arcforge::embedded::utils::Logger::GetInstance().Info( @@ -463,8 +423,7 @@ SocketReturnValue BaseImpl::receiveString_safe(std::string& message) { // 5. if has content, receive message body ifself if (len > 0) { - // 合理性检查 - const uint32_t MAX_ALLOWED_CHARS = 1024 * 1024; // 示例: 最大1M字符 + const uint32_t MAX_ALLOWED_CHARS = 1024 * 1024; if (len > MAX_ALLOWED_CHARS) { arcforge::embedded::utils::Logger::GetInstance().Info( "receiveString_safe: Received length (" + std::to_string(len) + @@ -524,7 +483,7 @@ SocketReturnValue BaseImpl::receiveString_safe(std::string& message) { *===================================================*/ SocketReturnValue BaseImpl::connectToServer() { - // 创建Unix域socket + // create Unix domain socket int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { return SocketReturnValue::kfd_illegal; @@ -538,13 +497,13 @@ SocketReturnValue BaseImpl::connectToServer() { return SocketReturnValue::ksocketpath_empty; } - // 设置服务器地址 + // config server address struct sockaddr_un server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sun_family = AF_UNIX; strncpy(server_addr.sun_path, getSocketPath_safe().c_str(), sizeof(server_addr.sun_path) - 1); - // 连接到服务器 + // establish connection to server if (connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { // perror("Client connect failed"); arcforge::embedded::utils::Logger::GetInstance().Error( @@ -553,8 +512,8 @@ SocketReturnValue BaseImpl::connectToServer() { return SocketReturnValue::kconnect_server_failed; } - this->setFD_safe(sock_fd); // <--- 关键: ClientBase (作为Base的子类) 设置其连接FD - // TODO: 需要设置sock_fd到Base类 + this->setFD_safe(sock_fd); + return SocketReturnValue::ksuccess; } /*=================================================== @@ -562,7 +521,6 @@ SocketReturnValue BaseImpl::connectToServer() { *===================================================*/ SocketReturnValue BaseImpl::startServer(const size_t& timeout) { - // 创建Unix域socket int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { return SocketReturnValue::kfd_illegal; @@ -577,16 +535,13 @@ SocketReturnValue BaseImpl::startServer(const size_t& timeout) { return SocketReturnValue::ksocketpath_empty; } - // 设置socket地址 struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, getSocketPath_safe().c_str(), sizeof(addr.sun_path) - 1); - // 如果socket文件已存在,删除它 unlink(getSocketPath_safe().c_str()); - // 绑定socket if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { close(sock_fd); return SocketReturnValue::kbind_error; @@ -622,7 +577,7 @@ SocketReturnValue BaseImpl::startServer(const size_t& timeout) { // i want more standard version that i can get char * string which was edited by posix // perror("setsockopt failed"); arcforge::embedded::utils::Logger::GetInstance().Error("setsockopt failed", - kcurrent_lib_name); + kcurrent_lib_name); close(sock_fd); return SocketReturnValue::ksetsocketopt_error; } @@ -638,19 +593,19 @@ SocketReturnValue BaseImpl::startServer(const size_t& timeout) { } SocketAcceptImplReturn::SocketAcceptImplReturn() - : return_value_impl(SocketReturnValue::kinit_state), client_impl(nullptr){}; + : return_value_impl(SocketReturnValue::kinit_state), client_impl(nullptr) {}; SocketAcceptImplReturn::SocketAcceptImplReturn(SocketReturnValue value, std::unique_ptr client_ptr) - : return_value_impl(value), client_impl(std::move(client_ptr)){}; + : return_value_impl(value), client_impl(std::move(client_ptr)) {}; SocketAcceptImplReturn BaseImpl::acceptClient() { struct sockaddr_un client_addr; socklen_t client_len = sizeof(client_addr); - int listening_fd = this->getFD_safe(); // <--- ServerBase 的监听FD - if (listening_fd < 0) { // 或者 if (this->isSocketFDValid_safe() != SocketStatus::kvalid) + int listening_fd = this->getFD_safe(); + if (listening_fd < 0) { // perror("Server accept: Invalid listening FD for server"); arcforge::embedded::utils::Logger::GetInstance().Info( std::string("Server accept: Invalid listening FD for server") + strerror(errno), @@ -661,7 +616,7 @@ SocketAcceptImplReturn BaseImpl::acceptClient() { return sreturn; } - // 接受客户端连接 + // accept the connection from client int client_fd = ::accept(listening_fd, (struct sockaddr*)&client_addr, &client_len); if (client_fd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -680,12 +635,8 @@ SocketAcceptImplReturn BaseImpl::acceptClient() { // return SocketReturnValue::kfd_illegal; } - // 创建新的Base对象管理客户端连接 - // auto client = std::make_unique(); - auto client_connection = std::make_unique(); // 创建一个新的Base对象代表客户端连接 - client_connection->setFD_safe(client_fd); // <--- 关键: 为这个新连接设置FD - - // TODO: 设置client_fd到Base对象 + auto client_connection = std::make_unique(); + client_connection->setFD_safe(client_fd); return {SocketReturnValue::ksuccess, std::move(client_connection)}; // return SocketReturnValue::ksuccess; @@ -719,51 +670,6 @@ SocketReturnValue BaseImpl::unlinkSocketPath() { return SocketReturnValue::ksuccess; } -// /*=================================================== -// * log utils -// *===================================================*/ -// // using namespace sherpa_onnx::cxx; // 可以方便地使用 OnlineBase 等 -// void BaseImpl::arcforge::embedded::utils::Logger::GetInstance().Info(const std::string& msg) { -// #ifdef DEBUG -// std::cout << "LibArcForge_Network: " << msg << std::endl; -// #endif -// } - -// void BaseImpl::arcforge::embedded::utils::Logger::GetInstance().Warning(const std::string& msg) { -// std::cerr << "LibArcForge_Network Warning: " << msg << std::endl; -// } - -// void BaseImpl::log_error(const std::string& msg) { -// std::cerr << "LibArcForge_Network Error: " << msg << std::endl; -// } - -// void BaseImpl::log_alert(const std::string& msg) { -// std::cerr << "LibArcForge_Network Alert: " << msg << std::endl; -// } - -// // using namespace sherpa_onnx::cxx; // 可以方便地使用 OnlineBase 等 -// void BaseImpl::log_safe(const std::string& msg) { -// #ifdef DEBUG -// std::lock_guard lock(*(log_mutex_.get())); -// arcforge::embedded::utils::Logger::GetInstance().Info(msg); -// #endif -// } - -// void BaseImpl::log_warning_safe(const std::string& msg) { -// std::lock_guard lock(*(log_mutex_.get())); -// arcforge::embedded::utils::Logger::GetInstance().Warning(msg); -// } - -// void BaseImpl::log_error_safe(const std::string& msg) { -// std::lock_guard lock(*(log_mutex_.get())); -// log_error(msg); -// } - -// void BaseImpl::log_alert_safe(const std::string& msg) { -// std::lock_guard lock(*(log_mutex_.get())); -// log_alert(msg); -// } - } // namespace network_socket } // namespace embedded } // namespace arcforge \ No newline at end of file diff --git a/libs/network/src/client/CMakeLists.txt b/libs/network/src/client/CMakeLists.txt index bde689c..0865215 100644 --- a/libs/network/src/client/CMakeLists.txt +++ b/libs/network/src/client/CMakeLists.txt @@ -24,21 +24,6 @@ set(SERVER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/client.cpp") -#[[ -set(PUBLIC_CLIENT_HEADERS "${INCLUDE_DIR}/Network/client/client.h") - -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${SERVER_SOURCES} - PARENT_SCOPE) - -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${PUBLIC_CLIENT_HEADERS} - PARENT_SCOPE) - -install(FILES ${PUBLIC_CLIENT_HEADERS} DESTINATION include/${PROJECT_NAME}/client) -]] - target_sources(${PROJECT_NAME} PRIVATE ${SERVER_SOURCES} diff --git a/libs/network/src/client/client.cpp b/libs/network/src/client/client.cpp index e4bf62f..3d1d1db 100644 --- a/libs/network/src/client/client.cpp +++ b/libs/network/src/client/client.cpp @@ -28,44 +28,9 @@ namespace arcforge { namespace embedded { namespace network_socket { -ClientBase::ClientBase() { - // Base类构造函数已经处理了基础初始化 -} +ClientBase::ClientBase() {} -ClientBase::~ClientBase() { - // Base类析构函数会处理socket关闭 -} - -// SocketReturnValue ClientBase::connectToServer() { -// // 创建Unix域socket -// int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); -// if (sock_fd < 0) { -// return SocketReturnValue::kfd_illegal; -// } - -// // socket path verification -// if (getSocketPath().empty() == true) { -// std::cerr << "Socket path is empty, pls set it before you connect to server." << std::endl; -// return SocketReturnValue::ksocketpath_empty; -// } - -// // 设置服务器地址 -// struct sockaddr_un server_addr; -// memset(&server_addr, 0, sizeof(server_addr)); -// server_addr.sun_family = AF_UNIX; -// strncpy(server_addr.sun_path, getSocketPath().c_str(), sizeof(server_addr.sun_path) - 1); - -// // 连接到服务器 -// if (connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { -// perror("Client connect failed"); -// close(sock_fd); -// return SocketReturnValue::kconnect_server_failed; -// } - -// this->setFD(sock_fd); // <--- 关键: ClientBase (作为Base的子类) 设置其连接FD -// // TODO: 需要设置sock_fd到Base类 -// return SocketReturnValue::ksuccess; -// } +ClientBase::~ClientBase() {} } // namespace network_socket } // namespace embedded diff --git a/libs/network/src/common/CMakeLists.txt b/libs/network/src/common/CMakeLists.txt index ebca814..5f4e1e8 100644 --- a/libs/network/src/common/CMakeLists.txt +++ b/libs/network/src/common/CMakeLists.txt @@ -22,25 +22,11 @@ # sherpa-lib/src/common/CMakeLists.txt # -# 列出这个模块的源文件 (如果有 .cpp 文件) set(COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/common-types.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/system-info.cpp" ) -#[[ -# 列出这个模块提供的头文件 (供父级 CMakeLists.txt 用于安装或接口包含) -set(COMMON_PUBLIC_HEADERS - "${INCLUDE_DIR}/Network/common/common-types.h" -) - -# 将源文件列表设置到父作用域,以便顶层 CMakeLists.txt 可以使用它 -set(LIB_SOURCES ${LIB_SOURCES} ${COMMON_SOURCES} PARENT_SCOPE) -set(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${COMMON_PUBLIC_HEADERS} PARENT_SCOPE) - -install(FILES ${COMMON_PUBLIC_HEADERS} DESTINATION include/${PROJECT_NAME}/common) -]] - target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SOURCES} diff --git a/libs/network/src/common/common-types.cpp b/libs/network/src/common/common-types.cpp index b155d31..3816df7 100644 --- a/libs/network/src/common/common-types.cpp +++ b/libs/network/src/common/common-types.cpp @@ -18,8 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "Network/base/base.h" #include "Network/common/common-types.h" +#include "Network/base/base.h" namespace arcforge { namespace embedded { @@ -27,7 +27,6 @@ namespace network_socket { const std::string_view kcurrent_lib_name = PROJECT_NAME; -// 1. 每一个 member to string 的函数 std::string SocketReturnValueToString(SocketReturnValue value) { switch (value) { case SocketReturnValue::ksuccess: @@ -51,7 +50,7 @@ std::string SocketReturnValueToString(SocketReturnValue value) { return "kcount_too_large (0x70)"; case SocketReturnValue::kempty_string: return "kempty_string (0x71)"; - case SocketReturnValue::kfd_illegal: // 注意: 这个成员的值在新的 enum 中是 0x72 + case SocketReturnValue::kfd_illegal: return "kfd_illegal (0x72)"; case SocketReturnValue::keof: return "keof (0x73)"; @@ -66,9 +65,9 @@ std::string SocketReturnValueToString(SocketReturnValue value) { return "kbind_error (0x82)"; case SocketReturnValue::kpeer_abnormally_closed: return "kpeer_abnormally_closed (0x83)"; - case SocketReturnValue::kaccept_timeout: // 新增成员 + case SocketReturnValue::kaccept_timeout: return "kaccept_timeout (0x84)"; - case SocketReturnValue::ksetsocketopt_error: // 新增成员 + case SocketReturnValue::ksetsocketopt_error: return "ksetsocketopt_error (0x85)"; // --- impl layer errors --- case SocketReturnValue::kimpl_nullptr_error: @@ -78,24 +77,20 @@ std::string SocketReturnValueToString(SocketReturnValue value) { return "kinit_state (0xff)"; case SocketReturnValue::kunknownerror: return "kunknownerror (0x100)"; - // case SocketReturnValue::ksuccess_with_warning: return "ksuccess_with_warning (0xYY)"; // 示例未来扩展 + // case SocketReturnValue::ksuccess_with_warning: return "ksuccess_with_warning (0xYY)"; default: - // 将int值转换为十六进制字符串,以便调试未知值 char hex_string[20]; - // 使用 std::snprintf 需要 + // std::snprintf needs std::snprintf(hex_string, sizeof(hex_string), "Unknown (0x%x)", static_cast(value)); return hex_string; } } -// 2. 判断是否 success 的函数 -// 未来有多个 options 表示 success,可以在这里添加 bool SocketReturnValueIsSuccess(SocketReturnValue value) { switch (value) { case SocketReturnValue::ksuccess: - // 示例:如果未来有其他成功状态 - // case SocketReturnValue::ksuccess_with_warning: + return true; // --- recv opts errors --- case SocketReturnValue::kreceived_null: @@ -123,16 +118,17 @@ bool SocketReturnValueIsSuccess(SocketReturnValue value) { // *************************** case SocketReturnValue::kinit_state: case SocketReturnValue::kunknownerror: - default: // 所有未明确指定为 success 的情况(包括上面列出的错误和任何未定义的值)都返回 false + default: + // all other unspecified values (including those listed above as errors and any undefined values) return false return false; } } SocketAcceptReturn::SocketAcceptReturn() - : return_value(SocketReturnValue::kinit_state), client(nullptr){}; + : return_value(SocketReturnValue::kinit_state), client(nullptr) {}; SocketAcceptReturn::SocketAcceptReturn(SocketReturnValue value, std::unique_ptr client_ptr) - : return_value(value), client(std::move(client_ptr)){}; + : return_value(value), client(std::move(client_ptr)) {}; } // namespace network_socket } // namespace embedded diff --git a/libs/network/src/common/system-info.cpp b/libs/network/src/common/system-info.cpp index e45a8ae..a0e3274 100644 --- a/libs/network/src/common/system-info.cpp +++ b/libs/network/src/common/system-info.cpp @@ -20,35 +20,30 @@ // #include "Network/common/system-info.h" -// 关键:包含由 CMake 在第 3 步生成的头文件 +// IMPORTANT: Import from CMakeLists.txt externally #include "system-info.h" namespace arcforge { namespace embedded { namespace network_socket { -// 定义一个全局常量,以确保版本字符串被编译进二进制文件, -// 这样 'strings' 命令就能找到它。 -// const char* g_internal_version_string_for_binary_scan = VERSION_STRING; - -// 实现公共接口函数 std::string get_network_socket_library_version() { - // 使用 CMake 生成的宏返回版本字符串 + return VERSION_STRING; } std::string get_network_socket_library_author() { - // 使用 CMake 生成的宏返回版本字符串 + return AUTHOR_NAME; } std::string get_network_socket_library_author_email() { - // 使用 CMake 生成的宏返回版本字符串 + return AUTHOR_EMAIL; } std::string get_network_socket_library_build_timestamp() { - // 使用 CMake 生成的宏返回版本字符串 + return BUILD_TIMESTAMP; } } // namespace network_socket diff --git a/libs/network/src/server/CMakeLists.txt b/libs/network/src/server/CMakeLists.txt index 1729d34..4514a75 100644 --- a/libs/network/src/server/CMakeLists.txt +++ b/libs/network/src/server/CMakeLists.txt @@ -24,21 +24,6 @@ set(SERVER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/server.cpp") -#[[ -set(PUBLIC_SERVER_HEADERS "${INCLUDE_DIR}/Network/server/server.h") - -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${SERVER_SOURCES} - PARENT_SCOPE) - -set(LIB_PUBLIC_HEADERS - ${LIB_PUBLIC_HEADERS} ${PUBLIC_SERVER_HEADERS} - PARENT_SCOPE) - -install(FILES ${PUBLIC_SERVER_HEADERS} DESTINATION include/${PROJECT_NAME}/server) -]] - target_sources(${PROJECT_NAME} PRIVATE ${SERVER_SOURCES} diff --git a/libs/network/src/server/server.cpp b/libs/network/src/server/server.cpp index 0738930..f5ed1a2 100644 --- a/libs/network/src/server/server.cpp +++ b/libs/network/src/server/server.cpp @@ -18,7 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. - #include "Network/server/server.h" #include "Utils/logger/logger.h" @@ -26,32 +25,17 @@ namespace arcforge { namespace embedded { namespace network_socket { -ServerBase::ServerBase() { - // 基类Base已经初始化了socket相关资源 -} +ServerBase::ServerBase() {} ServerBase::~ServerBase() { - // 基类Base的析构函数会处理socket关闭 - - // 1. 调用 unlinkSocketPath() 来删除文件系统中的 socket 路径。 - // 这是 ServerBase 特有的职责。 - // 注意:unlinkSocketPath() 内部应该使用 getSocketPath() 来获取路径。 - // 或者,如果 ServerBase 自己也存了一份 path,就用自己的。 - // 从你的 server.cpp 实现来看,unlinkSocketPath 似乎使用了成员变量 path, - // 而 startServer 使用了 getSocketPath()。需要统一。 - // 假设 getSocketPath() 是从 Base 继承的,并且返回正确的路径。 + std::ostringstream ss; ss << "[ServerBase PID:" << getpid() << "] ServerBase destructor called. Attempting to unlink socket path."; arcforge::embedded::utils::Logger::GetInstance().Info(ss.str(), kcurrent_lib_name); - unlinkSocketPath(); // 调用成员函数来执行 unlink + unlinkSocketPath(); - // 2. 不需要显式调用 close(socketfd_) 或 this->closeSocket()。 - // 因为 ServerBase 继承自 Base (而 Base 可能使用 BaseImpl), - // Base 的析构函数 (最终是 BaseImpl 的析构函数) 会被自动调用, - // 并且它会负责关闭 socketfd_。 - // 重复关闭已经关闭的 fd (或者一个无效 fd) 通常是无害的,但没必要。 ss.clear(); ss << "[ServerBase PID:" << getpid() << "] ServerBase destructor finished. Base destructor will handle fd closure."; diff --git a/libs/utils/include/Utils/common/system-info.h b/libs/utils/include/Utils/common/system-info.h index 958c0a2..3d4f729 100644 --- a/libs/utils/include/Utils/common/system-info.h +++ b/libs/utils/include/Utils/common/system-info.h @@ -28,8 +28,8 @@ namespace embedded { namespace utils { /** - * @brief 获取库的编译时版本字符串。 - * @return 一个格式为 "major.minor.patch" 的字符串。 + * @brief Retrieve the library's compile-time version string. + * @return A string in the format "major.minor.patch". */ std::string get_utils_library_version(); diff --git a/libs/utils/include/Utils/logger/logger-old.h b/libs/utils/include/Utils/logger/logger-old.h deleted file mode 100644 index afa78d5..0000000 --- a/libs/utils/include/Utils/logger/logger-old.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2025 PotterWhite - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "Utils/pch.h" - -namespace arcforge { -namespace embedded { -namespace utils { - -enum class LoggerLevel { - kdebug = 0x10, - kinfo = 0x11, - kwarning = 0x12, - kerror = 0x13, - kcritical = 0x14 -}; - -class Logger { - public: - static Logger& GetInstance(); - - ~Logger(); - - // copy - Logger(const Logger&) = delete; - Logger& operator=(const Logger&) = delete; - - // std::move - Logger(Logger&&) = delete; - Logger& operator=(Logger&&) = delete; - - // ---------------------------------------------- - void setLevel(LoggerLevel lv); - - // ---------------------------------------------- - void BatchDebugLog(const std::vector& messages); - void MultiLineDebugLog(const std::string& multiline_message); - void Log(const std::string& message); - void Log(const std::string& message, const std::string& color); - void Log(const std::string& message, const std::string& color, const std::string& background); - void Log(const std::string& message, const std::string& color, const std::string& background, - const std::string& font); - void Log(const std::string& message, const std::string& color, const std::string& background, - const std::string& font, const std::string& style); - - void DebugLog(const std::string& message); - void DebugLog(const std::string& message, const std::string& color); - void DebugLog(const std::string& message, const std::string& color, - const std::string& background); - void DebugLog(const std::string& message, const std::string& color, - const std::string& background, const std::string& font); - void DebugLog(const std::string& message, const std::string& color, - const std::string& background, const std::string& font, const std::string& style); - - void WarningLog(const std::string& message); - - void ErrorLog(const std::string& message); - - void CriticalLog(const std::string& message); - - private: - Logger(); - - private: - // 互斥锁保护日志输出,确保线程安全 - std::mutex log_mutex_; - std::queue log_queue_; - std::condition_variable log_cv_; - LoggerLevel loggerlevel_; -}; - -} // namespace utils -} // namespace embedded -} // namespace arcforge \ No newline at end of file diff --git a/libs/utils/include/Utils/logger/logger.h b/libs/utils/include/Utils/logger/logger.h index 7966acf..1b168e2 100644 --- a/libs/utils/include/Utils/logger/logger.h +++ b/libs/utils/include/Utils/logger/logger.h @@ -29,7 +29,6 @@ namespace arcforge { namespace embedded { namespace utils { -// 日志级别定义 enum class LoggerLevel { kdebug = 0x10, kinfo = 0x11, @@ -44,21 +43,21 @@ class Logger { ~Logger(); - // 删除拷贝和移动语义 + // delete copy and move semantics Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; Logger(Logger&&) = delete; Logger& operator=(Logger&&) = delete; // ---------------------------------------------- - // 配置接口 + // Config Interface // ---------------------------------------------- void setLevel(LoggerLevel lv); void AddSink(std::shared_ptr sink); void ClearSinks(); // ---------------------------------------------- - // 日志记录核心接口 + // Log control interface // ---------------------------------------------- void Log(LoggerLevel level, const std::string& message, std::string_view tag = {}); void BatchLog(LoggerLevel level, const std::vector& messages, @@ -67,10 +66,9 @@ class Logger { std::string_view tag = {}); // ---------------------------------------------- - // 便捷的日志记录方法 + // Convenient logging levels // ---------------------------------------------- - void Info(const std::string& message, - std::string_view tag = {}); // 推荐使用更明确的 Info 而不是 Log + void Info(const std::string& message, std::string_view tag = {}); void Debug(const std::string& message, std::string_view tag = {}); void Warning(const std::string& message, std::string_view tag = {}); void Error(const std::string& message, std::string_view tag = {}); diff --git a/libs/utils/include/Utils/logger/worker/log_entry.h b/libs/utils/include/Utils/logger/worker/log_entry.h index 12f97e2..6480e5b 100644 --- a/libs/utils/include/Utils/logger/worker/log_entry.h +++ b/libs/utils/include/Utils/logger/worker/log_entry.h @@ -28,16 +28,16 @@ namespace arcforge { namespace embedded { namespace utils { -// 前向声明 LoggerLevel,避免与 logger.h 循环引用 +// Forward declaration of LoggerLevel to avoid circular dependency with logger.h enum class LoggerLevel; -// 日志条目结构体,封装一条日志的所有原始信息 +// Log entry structure encapsulating all raw information of a log struct LogEntry { std::chrono::system_clock::time_point timestamp; LoggerLevel level; std::string message; - std::string_view tag; // <--- 2. 添加成员 - // 未来可扩展: + std::string_view tag; // <--- 2. Add tag field + // Expanding future capabilities: // std::thread::id thread_id; // const char* file; // int line; diff --git a/libs/utils/include/Utils/logger/worker/logsink.h b/libs/utils/include/Utils/logger/worker/logsink.h index e58bbc9..80faf5a 100644 --- a/libs/utils/include/Utils/logger/worker/logsink.h +++ b/libs/utils/include/Utils/logger/worker/logsink.h @@ -23,18 +23,18 @@ #pragma once #include "Utils/pch.h" -#include "log_entry.h" // 包含 LogEntry 定义 +#include "log_entry.h" namespace arcforge { namespace embedded { namespace utils { -// LogSink 抽象基类,定义所有 Sink 的统一接口 +// logsink abstract base class defining a common interface for all sinks class LogSink { public: virtual ~LogSink() = default; - // 所有 Sink 必须实现此方法,以处理日志条目 + // all sink must implement this method to handle log entries virtual void log(const LogEntry& entry) = 0; }; diff --git a/libs/utils/src/common/CMakeLists.txt b/libs/utils/src/common/CMakeLists.txt index 8abf83f..8a226e3 100644 --- a/libs/utils/src/common/CMakeLists.txt +++ b/libs/utils/src/common/CMakeLists.txt @@ -22,15 +22,11 @@ # src/common/CMakeLists.txt # -# 列出这个模块的源文件 (如果有 .cpp 文件) set(COMMON_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/common-types.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/system-info.cpp" ) -# 将源文件列表设置到父作用域,以便顶层 CMakeLists.txt 可以使用它 -#set(LIB_SOURCES ${LIB_SOURCES} ${COMMON_SOURCES} PARENT_SCOPE) - target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SOURCES} diff --git a/libs/utils/src/common/system-info.cpp b/libs/utils/src/common/system-info.cpp index cf7d6d3..793da69 100644 --- a/libs/utils/src/common/system-info.cpp +++ b/libs/utils/src/common/system-info.cpp @@ -20,41 +20,34 @@ #include "Utils/common/system-info.h" -// 关键:包含由 CMake 在第 3 步生成的头文件 +// IMPORTANT: Import from CMakeLists.txt externally #include "system-info.h" namespace arcforge { namespace embedded { namespace utils { -// 实现公共接口函数 + std::string get_utils_library_version() { - // 使用 CMake 生成的宏返回版本字符串 + // These macros come from CMakeLists externally return VERSION_STRING; } std::string get_utils_library_author() { - // 使用 CMake 生成的宏返回版本字符串 + // These macros come from CMakeLists externally return AUTHOR_NAME; } std::string get_utils_library_author_email() { - // 使用 CMake 生成的宏返回版本字符串 + // These macros come from CMakeLists externally return AUTHOR_EMAIL; } std::string get_utils_library_build_timestamp() { - // 使用 CMake 生成的宏返回版本字符串 + // These macros come from CMakeLists externally return BUILD_TIMESTAMP; } -// // 定义一个全局常量,以确保版本字符串被编译进二进制文件, -// // 这样 'strings' 命令就能找到它。 -// const char* g_internal_version_string_for_binary_scan = VERSION_STRING; -// const char* g_internal_author_string_for_binary_scan = AUTHOR_NAME; -// const char* g_internal_author_email_string_for_binary_scan = AUTHOR_EMAIL; -// const char* g_internal_build_timestamp_string_for_binary_scan = BUILD_TIMESTAMP; - } // namespace utils } // namespace embedded } // namespace arcforge \ No newline at end of file diff --git a/libs/utils/src/logger/CMakeLists.txt b/libs/utils/src/logger/CMakeLists.txt index 32c475c..d561f21 100644 --- a/libs/utils/src/logger/CMakeLists.txt +++ b/libs/utils/src/logger/CMakeLists.txt @@ -26,13 +26,6 @@ add_subdirectory(worker) set(LOGGER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/logger.cpp") -#[[ -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${LOGGER_SOURCES} - PARENT_SCOPE) -]] - target_sources(${PROJECT_NAME} PRIVATE ${LOGGER_SOURCES} diff --git a/libs/utils/src/logger/logger-old.cpp b/libs/utils/src/logger/logger-old.cpp deleted file mode 100644 index f0dafd4..0000000 --- a/libs/utils/src/logger/logger-old.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2025 PotterWhite -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "Utils/logger/logger.h" - -namespace arcforge { -namespace embedded { -namespace utils { - -// 初始化静态互斥锁 -// std::mutex Logger::log_mutex_; -// std::queue Logger::log_queue_; -// std::condition_variable Logger::log_cv_; - -Logger& Logger::GetInstance() { - static Logger instance; - - return instance; -} - -Logger::Logger() { - std::cout << "Logger initialized in constructor." << std::endl; -} - -Logger::~Logger() { - std::cout << "Logger uninitialized in deconstructor." << std::endl; -} - -void Logger::setLevel(LoggerLevel lv) { - std::lock_guard lock(log_mutex_); - - loggerlevel_ = lv; -} - -/**************************************************************** -* Log -****************************************************************/ -void Logger::Log(const std::string& message) { - if (loggerlevel_ <= LoggerLevel::kinfo) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[0;37m" - << "qtlog: " << message << "\033[0m" << std::endl; // White color - } -} - -void Logger::Log(const std::string& message, const std::string& color) { - if (loggerlevel_ <= LoggerLevel::kinfo) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << "m" - << "qtlog: " << message << "\033[0m" << std::endl; - } -} - -void Logger::Log(const std::string& message, const std::string& color, - const std::string& background) { - if (loggerlevel_ <= LoggerLevel::kinfo) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << "m" - << "qtlog: " << message << "\033[0m" << std::endl; - } -} - -void Logger::Log(const std::string& message, const std::string& color, - const std::string& background, const std::string& font) { - if (loggerlevel_ <= LoggerLevel::kinfo) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << ";" << font << "m" - << "qtlog: " << message << "\033[0m" << std::endl; - } -} - -void Logger::Log(const std::string& message, const std::string& color, - const std::string& background, const std::string& font, const std::string& style) { - if (loggerlevel_ <= LoggerLevel::kinfo) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << ";" << font << ";" << style << "m" - << "qtlog: " << message << "\033[0m" << std::endl; - } -} - -/**************************************************************** -* Debug Log -****************************************************************/ - -void Logger::BatchDebugLog([[maybe_unused]] const std::vector& messages) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - for (const auto& msg : messages) { - std::cout << "\033[0;36m" - << "...qtdebug: " << msg << "\033[0m" << std::endl; - } - } -} - -void Logger::MultiLineDebugLog([[maybe_unused]] const std::string& multiline_message) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - { - std::lock_guard lock(log_mutex_); - - std::istringstream stream(multiline_message); - std::string line; - while (std::getline(stream, line)) { - std::cout << "\033[0;36m" - << "...qtdebug: " << line << "\033[0m" << std::endl; - } - } - // { - // std::lock_guard lock(log_mutex_); - // log_queue_.push(multiline_message); - - // if (!log_queue_.empty()) { - // std::string& msg = log_queue_.front(); - // std::istringstream stream(msg); - // std::string line; - // while (std::getline(stream, line)) { - // std::cout << "\033[0;36m" - // << "...qtdebug: " << line << "\033[0m" << std::endl; - // } - // } - - // log_cv_.notify_one(); - // } - } -} - -void Logger::DebugLog([[maybe_unused]] const std::string& message) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[0;36m" - << "...qtdebug: " << message << "\033[0m" << std::endl; // Cyan color - } -} - -void Logger::DebugLog([[maybe_unused]] const std::string& message, - [[maybe_unused]] const std::string& color) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << "m" - << "...qtdebug: " << message << "\033[0m" << std::endl; - } -} - -void Logger::DebugLog([[maybe_unused]] const std::string& message, - [[maybe_unused]] const std::string& color, - [[maybe_unused]] const std::string& background) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << "m" - << "...qtdebug: " << message << "\033[0m" << std::endl; - } -} - -void Logger::DebugLog([[maybe_unused]] const std::string& message, - [[maybe_unused]] const std::string& color, - [[maybe_unused]] const std::string& background, - [[maybe_unused]] const std::string& font) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << ";" << font << "m" - << "...qtdebug: " << message << "\033[0m" << std::endl; - } -} - -void Logger::DebugLog([[maybe_unused]] const std::string& message, - [[maybe_unused]] const std::string& color, - [[maybe_unused]] const std::string& background, - [[maybe_unused]] const std::string& font, - [[maybe_unused]] const std::string& style) { - if (loggerlevel_ <= LoggerLevel::kdebug) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[" << color << ";" << background << ";" << font << ";" << style << "m" - << "...qtdebug: " << message << "\033[0m" << std::endl; - } -} - -/**************************************************************** -* Warning Log -****************************************************************/ -void Logger::WarningLog(const std::string& message) { - if (loggerlevel_ <= LoggerLevel::kwarning) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[1;33m" - << "...qt warning: " << message << "\033[0m" << std::endl; // Bold yellow color - } -} - -/**************************************************************** -* Error Log -****************************************************************/ -void Logger::ErrorLog(const std::string& message) { - if (loggerlevel_ <= LoggerLevel::kerror) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[1;31m" - << "...qt error: " << message << "\033[0m" << std::endl; // Bold red color - } -} - -/**************************************************************** -* Critical Log -****************************************************************/ -void Logger::CriticalLog(const std::string& message) { - if (loggerlevel_ <= LoggerLevel::kcritical) { - std::lock_guard lock(log_mutex_); - std::cout << "\033[1;37;41m" - << "...qt critical: " << message << "\033[0m" - << std::endl; // Bold white text on red background - } -} - -} // namespace utils -} // namespace embedded -} // namespace arcforge \ No newline at end of file diff --git a/libs/utils/src/logger/logger.cpp b/libs/utils/src/logger/logger.cpp index 023e718..d84f93c 100644 --- a/libs/utils/src/logger/logger.cpp +++ b/libs/utils/src/logger/logger.cpp @@ -21,7 +21,7 @@ #include "Utils/logger/logger.h" #include #include -#include "Utils/logger/worker/consolesink.h" // 默认 Sink +#include "Utils/logger/worker/consolesink.h" #include "Utils/logger/worker/log_entry.h" namespace arcforge { @@ -34,7 +34,6 @@ Logger& Logger::GetInstance() { } Logger::Logger() : loggerlevel_(LoggerLevel::kdebug) { - // 默认添加一个控制台 Sink AddSink(std::make_shared()); } @@ -58,10 +57,10 @@ void Logger::ClearSinks() { } void Logger::dispatch(const LogEntry& entry) { - // 这里故意将锁的范围缩小,只保护 sinks_ 列表的拷贝 - // 这样在执行 I/O 操作 (sink->log) 时不会长时间持有锁,提高性能 std::vector> sinks_copy; { + // shrink the lock scope, only protect sinks_ copying + // this way we don't hold the lock during I/O operations (sink->log), improving performance std::lock_guard lock(log_mutex_); sinks_copy = sinks_; } @@ -74,10 +73,10 @@ void Logger::dispatch(const LogEntry& entry) { } /**************************************************************** -* 核心日志方法 + Key Logging Method ****************************************************************/ void Logger::Log(LoggerLevel level, const std::string& message, std::string_view tag) { - // 级别检查提前,避免不必要的对象创建和函数调用 + // Level check early to avoid unnecessary object creation and function calls if (loggerlevel_ > level) { return; } @@ -92,7 +91,7 @@ void Logger::Log(LoggerLevel level, const std::string& message, std::string_view } /**************************************************************** -* 批量/多行日志方法 + Batch Log / MultiLineLog ****************************************************************/ void Logger::BatchLog(LoggerLevel level, const std::vector& messages, std::string_view tag) { @@ -117,7 +116,7 @@ void Logger::MultiLineLog(LoggerLevel level, const std::string& multiline_messag } /**************************************************************** -* 便捷日志方法 + Convienience Logging Methods ****************************************************************/ void Logger::Info(const std::string& message, std::string_view tag) { Log(LoggerLevel::kinfo, message, tag); diff --git a/libs/utils/src/logger/worker/CMakeLists.txt b/libs/utils/src/logger/worker/CMakeLists.txt index cb37b4c..f4fc845 100644 --- a/libs/utils/src/logger/worker/CMakeLists.txt +++ b/libs/utils/src/logger/worker/CMakeLists.txt @@ -27,14 +27,6 @@ set(WORKER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/filesink.cpp" ) -#[[ -# 上报给父级 -set(LIB_SOURCES - ${LIB_SOURCES} ${WORKER_SOURCES} - PARENT_SCOPE -) -]] - target_sources(${PROJECT_NAME} PRIVATE ${WORKER_SOURCES} diff --git a/libs/utils/src/logger/worker/consolesink.cpp b/libs/utils/src/logger/worker/consolesink.cpp index 516edcd..6e8327d 100644 --- a/libs/utils/src/logger/worker/consolesink.cpp +++ b/libs/utils/src/logger/worker/consolesink.cpp @@ -25,7 +25,6 @@ namespace arcforge { namespace embedded { namespace utils { -// 辅助函数,用于格式化时间戳 static std::string format_timestamp(const std::chrono::system_clock::time_point& tp) { std::time_t time = std::chrono::system_clock::to_time_t(tp); auto ms = std::chrono::duration_cast(tp.time_since_epoch()) % 1000; diff --git a/libs/utils/src/logger/worker/filesink.cpp b/libs/utils/src/logger/worker/filesink.cpp index 0d7bea1..f7ad115 100644 --- a/libs/utils/src/logger/worker/filesink.cpp +++ b/libs/utils/src/logger/worker/filesink.cpp @@ -26,7 +26,6 @@ namespace arcforge { namespace embedded { namespace utils { -// 辅助函数,可以放到公共头文件中 static std::string format_timestamp_for_file(const std::chrono::system_clock::time_point& tp) { std::time_t time = std::chrono::system_clock::to_time_t(tp); auto ms = std::chrono::duration_cast(tp.time_since_epoch()) % 1000; diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 2081d39..83f7d52 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -20,15 +20,12 @@ # third_party/CMakeLists.txt +#Expand in the future: +# we can use the toolchain variables which be imported from CMakePresets.json + # librknnrt should be verified(downloaded) first due to the latter module (sherpa) depend on it add_subdirectory(librknnrt) -# 只有当这是 RV1126BP 平台时,才去处理 sherpa-onnx -# 我们可以利用 Preset 里传进来的 toolchain 变量,或者自定义变量 -# 但目前最简单的是直接加,因为我们在 sherpa 内部有检查 URL 变量的逻辑 - -# 添加 Sherpa-Onnx 子目录 -# 这会触发 FetchContent 下载逻辑 add_subdirectory(sherpa-onnx) # --------------------------------- diff --git a/third_party/librknnrt/CMakeLists.txt b/third_party/librknnrt/CMakeLists.txt index 2f7b0da..b79e4dc 100644 --- a/third_party/librknnrt/CMakeLists.txt +++ b/third_party/librknnrt/CMakeLists.txt @@ -62,8 +62,8 @@ FetchContent_Declare( URL ${CHOSEN_LIBRKNNRT_URL} URL_HASH ${LIBRKNNRT_HASH} # ---------- - # 下载并解压到 build/_deps/librknnrt_pkg-src - # (默认就是自动解压) + # Download and Decompress unto the directory of "build/_deps/librknnrt_pkg-src" + # Default is FALSE # DOWNLOAD_NO_EXTRACT FALSE # ---------- ) diff --git a/third_party/sherpa-onnx/CMakeLists.txt b/third_party/sherpa-onnx/CMakeLists.txt index ae4ccbb..4349003 100644 --- a/third_party/sherpa-onnx/CMakeLists.txt +++ b/third_party/sherpa-onnx/CMakeLists.txt @@ -29,7 +29,7 @@ include(FetchContent) message(STATUS "[Configuration][ThirdParty] Preparing Sherpa-Onnx...") # --------------------------------- -# II. Declare Download Detail声明下载详情 +# II. Declare Download Detail # --------------------------------- # These variables come from CMakePresets.json if(NOT DEFINED SHERPA_ONNX_URL OR NOT DEFINED SHERPA_ONNX_HASH) @@ -61,8 +61,9 @@ FetchContent_Declare( sherpa_onnx_pkg URL ${CHOSEN_SHERPA_URL} URL_HASH ${SHERPA_ONNX_HASH} - # 下载并解压到 build/_deps/sherpa_onnx_pkg-src - # DOWNLOAD_NO_EXTRACT FALSE (默认就是自动解压) + # Download and Decompress unto the directory of "build/_deps/sherpa_onnx_pkg-src" + # Default is FALSE + # DOWNLOAD_NO_EXTRACT FALSE ) # --------------------------------- @@ -70,7 +71,6 @@ FetchContent_Declare( # --------------------------------- FetchContent_MakeAvailable(sherpa_onnx_pkg) -# 获取解压后的根目录路径 set(SHERPA_ROOT "${sherpa_onnx_pkg_SOURCE_DIR}") message(STATUS "[Configuration][ThirdParty] Sherpa-Onnx mounted at: ${SHERPA_ROOT}")