#include "NoiseDetectThread.h" #include #include "CreateWAVThread.h" #include "ThreadManager.h" #include "commonDefine.h" #include "GlobalInfo.h" #include "signalstats.h" #include "spdlog.h" NoiseDetectThread::NoiseDetectThread(CalculateThreadInfo_t& threadInfo) : BaseCalculateThread(threadInfo), m_leftRightData(0) { m_logger = spdlog::get("ACAServer"); if(m_logger == nullptr) { fmt::print("NoiseDetectThread: ACAServer Logger not found.\n"); return; } } NoiseDetectThread::~NoiseDetectThread() { } /* 线程功能函数 */ void NoiseDetectThread::task() { /* 初始化数据 */ if(!initData()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase); return; } SPDLOG_LOGGER_INFO(m_logger, " ★ {} 噪音检测线程开始运行 ", m_logBase); while(m_isRunning) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); /*------------------------------------------------------------------------ * 获取最新的左右声道数据 *------------------------------------------------------------------------*/ if(!m_pWAVThread->getLatestLeftRightData(m_leftRightData)) { continue; } // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新的左右声道数据成功,开始调用动态库计算噪音------------------------------------------ ", m_logBase); /*------------------------------------------------------------------------ * 计算数据 *------------------------------------------------------------------------*/ if(!detectNoise()) { continue; } /*------------------------------------------------------------------------ * 处理结果,写噪音报警信息到数据库(这里不写数据库,只计算结果返回给对比项) * 上面那个函数已经把结果保存了 *------------------------------------------------------------------------*/ // saveResult(); } clearData(); // 清理数据 SPDLOG_LOGGER_INFO(m_logger, " ★ {} 噪音检测线程结束 ", m_logBase); } /* 初始化数据 */ bool NoiseDetectThread::initData() { auto begin = m_threadInfo.compareItemInfo.mapRoad.begin(); // 获取第一个通道的信息 m_roadInfo = begin->scRoadInfo; // 录音通道信息 m_roadName = fmt::format("{}:{}", m_roadInfo.strSoundCardID.toStdString(), m_roadInfo.roadInfo.nRoadNum); m_logBase = fmt::format("噪音检测通道 {}:", m_roadName); m_pWAVThread = ThreadMan.getCreateWAVThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum); if(m_pWAVThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取数据生成线程失败", m_logBase); return false; } auto sampleRate = GInfo.sampleRate(); m_sample_rate = static_cast(sampleRate); /* 初始化噪音检测功能 */ // signalstats_wrapper::initialize(); return true; } /* 清理数据 */ void NoiseDetectThread::clearData() { /* 释放资源 */ // signalstats_wrapper::finalize(); } /* 调用动态库检测噪音 */ bool NoiseDetectThread::detectNoise() { // SPDLOG_LOGGER_TRACE(m_logger, "{} 开始调用动态库计算噪音", m_logBase); SPDLOG_LOGGER_INFO(m_logger, "{} 左声道数据大小: {}, 右声道数据大小: {}", m_logBase, m_leftRightData.vecLeftData.size(), m_leftRightData.vecRightData.size()); // std::vector audio_signal(48000); // std::random_device rd; // std::mt19937 gen(rd()); // std::normal_distribution<> dist(0.0, 1.0); // for (auto& sample : audio_signal) { // sample = dist(gen); // } auto startTime = std::chrono::steady_clock::now(); bool isNoiseLeft = false; /* 是否检测到左声道噪音 */ bool isNoiseRight = false; /* 是否检测到右声道噪音 */ try { /*-------------------------- 先检测左声道 --------------------------*/ nJson jsonOutput; auto ret = signalstats::detect_signal( jsonOutput, /* 返回结果,和jsonResult是一样的 */ m_leftRightData.vecLeftData, /* 左声道数据 */ // audio_signal, /* 测试数据 */ m_sample_rate, /* 采样率(HZ) */ m_silence_threshold, /* 静音阈值 */ m_db_threshold, /* 分贝阈值 */ m_cv_threshold, /* 变异系数阈值 */ m_window_params, /* 窗函数参数 */ m_nperseg, /* 每段样本数 */ m_noverlap, /* 重叠样本数 */ m_nfft, /* FFT点数 */ true /* 是否输出调试信息, true表示输出调试信息, false表示不输出调试信息 */ ); isNoiseLeft = jsonOutput["noise"].is_null() ? false : jsonOutput["noise"].get(); std::chrono::duration duration = std::chrono::steady_clock::now() - startTime; std::chrono::milliseconds ms = std::chrono::duration_cast(duration); SPDLOG_LOGGER_DEBUG(m_logger, "{} 计算左声道噪音耗时: {}ms", m_logBase, ms.count()); startTime = std::chrono::steady_clock::now(); /* 重置开始时间 */ /*-------------------------- 再检测右声道 --------------------------*/ jsonOutput.clear(); /* 清空输出结果 */ signalstats::detect_signal( jsonOutput, /* 返回结果,和jsonResult是一样的 */ m_leftRightData.vecRightData, /* 右声道数据 */ // audio_signal, /* 测试数据 */ m_sample_rate, /* 采样率(HZ) */ m_silence_threshold, /* 静音阈值 */ m_db_threshold, /* 分贝阈值 */ m_cv_threshold, /* 变异系数阈值 */ m_window_params, /* 窗函数参数 */ m_nperseg, /* 每段样本数 */ m_noverlap, /* 重叠样本数 */ m_nfft, /* FFT点数 */ false /* 是否输出调试信息, true表示输出调试信息, false表示不输出调试信息 */ ); isNoiseRight = jsonOutput["noise"].is_null() ? false : jsonOutput["noise"].get(); // for(const auto& it : m_leftRightData.vecRightData) // { // fmt::print("{:.5f} ", it); // } SPDLOG_LOGGER_DEBUG(m_logger, "{} 右声道噪音检测结果: {}", m_logBase, jsonOutput.dump(4)); } catch (const std::exception& e) { SPDLOG_LOGGER_ERROR(m_logger, "{} 调用动态库检测噪音失败: {}", m_logBase, e.what()); return false; } std::chrono::duration duration = std::chrono::steady_clock::now() - startTime; std::chrono::milliseconds ms = std::chrono::duration_cast(duration); SPDLOG_LOGGER_DEBUG(m_logger, "{} 计算右声道噪音耗时: {}ms", m_logBase, ms.count()); SPDLOG_LOGGER_DEBUG(m_logger, "{} 左声道噪音检测结果: {}, 右声道噪音检测结果: {}", m_logBase, isNoiseLeft, isNoiseRight); /* -------------------------- 和以往的结果对比 --------------------------*/ m_isNoiseLast = m_isNoise.load(); /* 上一次的噪音检测结果 */ m_isNoise.store(isNoiseLeft || isNoiseRight); /* 是否检测到噪音 */ return true; } /* 保存结果 */ void NoiseDetectThread::saveResult() { if(m_isNoiseLast) { /* 判断这次是否是噪音,没有噪音就报警结束 */ }else { /* 上一次没有噪音,这次有噪音,噪音报警开始 */ } }