NoiseDetectThread.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "NoiseDetectThread.h"
  2. #include <random>
  3. #include "CreateWAVThread.h"
  4. #include "ThreadManager.h"
  5. #include "commonDefine.h"
  6. #include "GlobalInfo.h"
  7. #include "signalstats.h"
  8. #include "spdlog.h"
  9. NoiseDetectThread::NoiseDetectThread(CalculateThreadInfo_t& threadInfo)
  10. : BaseCalculateThread(threadInfo),
  11. m_leftRightData(0)
  12. {
  13. m_logger = spdlog::get("ACAServer");
  14. if(m_logger == nullptr)
  15. {
  16. fmt::print("NoiseDetectThread: ACAServer Logger not found.\n");
  17. return;
  18. }
  19. }
  20. NoiseDetectThread::~NoiseDetectThread()
  21. {
  22. }
  23. /* 线程功能函数 */
  24. void NoiseDetectThread::task()
  25. {
  26. /* 初始化数据 */
  27. if(!initData())
  28. {
  29. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
  30. return;
  31. }
  32. SPDLOG_LOGGER_INFO(m_logger, " ★ {} 噪音检测线程开始运行 ", m_logBase);
  33. while(m_isRunning)
  34. {
  35. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  36. /*------------------------------------------------------------------------
  37. * 获取最新的左右声道数据
  38. *------------------------------------------------------------------------*/
  39. if(!m_pWAVThread->getLatestLeftRightData(m_leftRightData))
  40. {
  41. continue;
  42. }
  43. // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新的左右声道数据成功,开始调用动态库计算噪音------------------------------------------ ", m_logBase);
  44. /*------------------------------------------------------------------------
  45. * 计算数据
  46. *------------------------------------------------------------------------*/
  47. if(!detectNoise())
  48. {
  49. continue;
  50. }
  51. /*------------------------------------------------------------------------
  52. * 处理结果,写噪音报警信息到数据库(这里不写数据库,只计算结果返回给对比项)
  53. * 上面那个函数已经把结果保存了
  54. *------------------------------------------------------------------------*/
  55. // saveResult();
  56. }
  57. clearData(); // 清理数据
  58. SPDLOG_LOGGER_INFO(m_logger, " ★ {} 噪音检测线程结束 ", m_logBase);
  59. }
  60. /* 初始化数据 */
  61. bool NoiseDetectThread::initData()
  62. {
  63. auto begin = m_threadInfo.compareItemInfo.mapRoad.begin(); // 获取第一个通道的信息
  64. m_roadInfo = begin->scRoadInfo; // 录音通道信息
  65. m_roadName = fmt::format("{}:{}", m_roadInfo.strSoundCardID.toStdString(), m_roadInfo.roadInfo.nRoadNum);
  66. m_logBase = fmt::format("噪音检测通道 {}:", m_roadName);
  67. m_pWAVThread = ThreadMan.getCreateWAVThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum);
  68. if(m_pWAVThread == nullptr)
  69. {
  70. SPDLOG_LOGGER_ERROR(m_logger, "{} 获取数据生成线程失败", m_logBase);
  71. return false;
  72. }
  73. auto sampleRate = GInfo.sampleRate();
  74. m_sample_rate = static_cast<double>(sampleRate);
  75. /* 初始化噪音检测功能 */
  76. // signalstats_wrapper::initialize();
  77. return true;
  78. }
  79. /* 清理数据 */
  80. void NoiseDetectThread::clearData()
  81. {
  82. /* 释放资源 */
  83. // signalstats_wrapper::finalize();
  84. }
  85. /* 调用动态库检测噪音 */
  86. bool NoiseDetectThread::detectNoise()
  87. {
  88. // SPDLOG_LOGGER_TRACE(m_logger, "{} 开始调用动态库计算噪音", m_logBase);
  89. SPDLOG_LOGGER_INFO(m_logger, "{} 左声道数据大小: {}, 右声道数据大小: {}",
  90. m_logBase, m_leftRightData.vecLeftData.size(), m_leftRightData.vecRightData.size());
  91. // std::vector<double> audio_signal(48000);
  92. // std::random_device rd;
  93. // std::mt19937 gen(rd());
  94. // std::normal_distribution<> dist(0.0, 1.0);
  95. // for (auto& sample : audio_signal) {
  96. // sample = dist(gen);
  97. // }
  98. auto startTime = std::chrono::steady_clock::now();
  99. bool isNoiseLeft = false; /* 是否检测到左声道噪音 */
  100. bool isNoiseRight = false; /* 是否检测到右声道噪音 */
  101. try
  102. {
  103. /*-------------------------- 先检测左声道 --------------------------*/
  104. nJson jsonOutput;
  105. auto ret = signalstats::detect_signal(
  106. jsonOutput, /* 返回结果,和jsonResult是一样的 */
  107. m_leftRightData.vecLeftData, /* 左声道数据 */
  108. // audio_signal, /* 测试数据 */
  109. m_sample_rate, /* 采样率(HZ) */
  110. m_silence_threshold, /* 静音阈值 */
  111. m_db_threshold, /* 分贝阈值 */
  112. m_cv_threshold, /* 变异系数阈值 */
  113. m_window_params, /* 窗函数参数 */
  114. m_nperseg, /* 每段样本数 */
  115. m_noverlap, /* 重叠样本数 */
  116. m_nfft, /* FFT点数 */
  117. true /* 是否输出调试信息, true表示输出调试信息, false表示不输出调试信息 */
  118. );
  119. isNoiseLeft = jsonOutput["noise"].is_null() ? false : jsonOutput["noise"].get<bool>();
  120. std::chrono::duration<double> duration = std::chrono::steady_clock::now() - startTime;
  121. std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
  122. SPDLOG_LOGGER_DEBUG(m_logger, "{} 计算左声道噪音耗时: {}ms", m_logBase, ms.count());
  123. startTime = std::chrono::steady_clock::now(); /* 重置开始时间 */
  124. /*-------------------------- 再检测右声道 --------------------------*/
  125. jsonOutput.clear(); /* 清空输出结果 */
  126. signalstats::detect_signal(
  127. jsonOutput, /* 返回结果,和jsonResult是一样的 */
  128. m_leftRightData.vecRightData, /* 右声道数据 */
  129. // audio_signal, /* 测试数据 */
  130. m_sample_rate, /* 采样率(HZ) */
  131. m_silence_threshold, /* 静音阈值 */
  132. m_db_threshold, /* 分贝阈值 */
  133. m_cv_threshold, /* 变异系数阈值 */
  134. m_window_params, /* 窗函数参数 */
  135. m_nperseg, /* 每段样本数 */
  136. m_noverlap, /* 重叠样本数 */
  137. m_nfft, /* FFT点数 */
  138. false /* 是否输出调试信息, true表示输出调试信息, false表示不输出调试信息 */
  139. );
  140. isNoiseRight = jsonOutput["noise"].is_null() ? false : jsonOutput["noise"].get<bool>();
  141. // for(const auto& it : m_leftRightData.vecRightData)
  142. // {
  143. // fmt::print("{:.5f} ", it);
  144. // }
  145. SPDLOG_LOGGER_DEBUG(m_logger, "{} 右声道噪音检测结果: {}", m_logBase, jsonOutput.dump(4));
  146. }
  147. catch (const std::exception& e)
  148. {
  149. SPDLOG_LOGGER_ERROR(m_logger, "{} 调用动态库检测噪音失败: {}", m_logBase, e.what());
  150. return false;
  151. }
  152. std::chrono::duration<double> duration = std::chrono::steady_clock::now() - startTime;
  153. std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
  154. SPDLOG_LOGGER_DEBUG(m_logger, "{} 计算右声道噪音耗时: {}ms", m_logBase, ms.count());
  155. SPDLOG_LOGGER_DEBUG(m_logger, "{} 左声道噪音检测结果: {}, 右声道噪音检测结果: {}", m_logBase, isNoiseLeft, isNoiseRight);
  156. /* -------------------------- 和以往的结果对比 --------------------------*/
  157. m_isNoiseLast = m_isNoise.load(); /* 上一次的噪音检测结果 */
  158. m_isNoise.store(isNoiseLeft || isNoiseRight); /* 是否检测到噪音 */
  159. return true;
  160. }
  161. /* 保存结果 */
  162. void NoiseDetectThread::saveResult()
  163. {
  164. if(m_isNoiseLast)
  165. {
  166. /* 判断这次是否是噪音,没有噪音就报警结束 */
  167. }else
  168. {
  169. /* 上一次没有噪音,这次有噪音,噪音报警开始 */
  170. }
  171. }