123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- #include "ConsistencyCompareThread.h"
- #include "GlobalVariable.h"
- #include "ThreadManager.h"
- #include "CreateRecordFileThread.h"
- #include "ThreadAlarmManager.h"
- #include "CreateWAVThread.h"
- #include "LHCompareAPI.h"
- ConsistencyCompareThread::ConsistencyCompareThread(CalculateThreadInfo_t& threadInfo)
- : BaseCalculateThread(threadInfo)
- {
- }
- ConsistencyCompareThread::~ConsistencyCompareThread()
- {
- }
- /* 判断录音通道是否相等 */
- // bool ConsistencyCompareThread::isRoadEqual(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2)
- // {
- // /* r1对比m_r1,r2对比M_r2 */
- // if( roadInfo1.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum &&
- // roadInfo2.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum )
- // {
- // return true;
- // }
-
- // /* 反过来对比一下 */
- // if( roadInfo1.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum &&
- // roadInfo2.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum )
- // {
- // return true;
- // }
- // return false;
- // }
- /* 初始化 */
- bool ConsistencyCompareThread::initConsistencyCompare()
- {
- /* 初始化数据 */
- if(!initData())
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
- return false;
- }
- SPDLOG_LOGGER_INFO(m_logger, " ★ {} 一致性对比功能(调用动态库)初始化完成 ", m_logBase);
- return true;
- }
- /* 比对函数 */
- bool ConsistencyCompareThread::compareConsistencyData()
- {
- /*--------------------------------------------------------------
- * 更新最新数据
- *--------------------------------------------------------------*/
- m_pCreateWAVThread1->getLatestFileName(m_wavFilePath1);
- m_pCreateWAVThread2->getLatestFileName(m_wavFilePath2);
- /* 检查是否有新的数据 */
- if(m_wavFilePath1 == m_prevWavFilePath1 || m_wavFilePath2 == m_prevWavFilePath2)
- {
- // SPDLOG_LOGGER_INFO(m_logger, "{} 检测到文件路径未变化", m_logBase);
- return true;
- }
- /*--------------------------------------------------------------
- * 开始比对计算,并保存计算结果
- *--------------------------------------------------------------*/
- if(!compareConsistency())
- {
- return false;
- }
- /* 计算一致性结果 */
- computeResult();
- m_prevWavFilePath1 = m_wavFilePath1; // 更新上一个wav文件路径
- m_prevWavFilePath2 = m_wavFilePath2; // 更新上一个wav文件路径
- return true;
- }
- /* 清理数据 */
- void ConsistencyCompareThread::clearConsistencyCompareData()
- {
- clearData();
- SPDLOG_LOGGER_INFO(m_logger, " ★ {} 一致性对比功能(调用动态库)清理完成 ", m_logBase);
- }
- /* 线程功能函数 */
- void ConsistencyCompareThread::task()
- {
- m_isRunning = true;
- /* 初始化 */
- 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(100));
- /* 判断是否开启不一致检测 */
- if(m_isEnableNotConsistencyDetect.load() == false)
- {
- /* 不开启不一致检测,直接返回一致性结果 */
- m_isConsistency = true;
- m_isConsistencyWarning = false;
- continue; // 跳过后续的计算
- }
- /* 判断是否在检测时间段内 */
- if(m_isInDetectPeriod.load() == false)
- {
- /* 不在检测时间段内,不需要比对,结果一直为一致性 */
- m_isConsistency = true;
- m_isConsistencyWarning = false;
- /* 如果此时还在非一致性报警中,结束报警 */
- if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
- {
- saveAlarmInfo();
- }
- continue;
- }
- compareConsistencyData();
- }
- clearData();
- SPDLOG_LOGGER_WARN(m_logger, " ★ {} 一致性对比线程(调用动态库)已结束运行 ", m_logBase);
-
- }
- /* 初始化数据 */
- bool ConsistencyCompareThread::initData()
- {
- if(m_threadInfo.compareItemInfo.mapRoad.size() < 2)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 录音通道信息不足,至少需要两个通道", m_logBase);
- return false;
- }
- /* 获取两个录音通道的信息 */
- auto it = m_threadInfo.compareItemInfo.mapRoad.begin();
- m_itemRoadInfo1 = it.value(); // 第一个通道
- it++;
- m_itemRoadInfo2 = it.value(); // 第二个通道
- m_logBase = fmt::format("对比通道 {}:{} - {}:{}",
- m_itemRoadInfo1.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum,
- m_itemRoadInfo2.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
-
- /* 获取创建wav文件的指针 */
- auto startTime = std::chrono::steady_clock::now(); // 记录开始时间
- while(true)
- {
- if(m_pCreateWAVThread1 == nullptr)
- {
- m_pCreateWAVThread1 = ThreadMan.getCreateWAVThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
- }
- if(m_pCreateWAVThread2 == nullptr)
- {
- m_pCreateWAVThread2 = ThreadMan.getCreateWAVThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
- }
-
- /* 获取生成报警音频文件的线程 */
- if(m_threadCreateAlarmFile1 == nullptr)
- {
- m_threadCreateAlarmFile1 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
- }
- if(m_threadCreateAlarmFile2 == nullptr)
- {
- m_threadCreateAlarmFile2 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
- }
- if( m_pCreateWAVThread1 != nullptr && m_pCreateWAVThread2 != nullptr &&
- m_threadCreateAlarmFile1 != nullptr && m_threadCreateAlarmFile2 != nullptr )
- {
- break; // 获取到两个线程,跳出循环
- }
- /* 超过10秒还没有获取到线程,返回失败 */
- if(std::chrono::steady_clock::now() - startTime > std::chrono::seconds(10))
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 获取生成音量的线程超时", m_logBase);
- return false;
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- if(m_pCreateWAVThread1 == nullptr || m_pCreateWAVThread2 == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 获取录音线程失败", m_logBase);
- return false;
- }
-
- if(m_threadCreateAlarmFile1 == nullptr || m_threadCreateAlarmFile2 == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 获取生成报警音频文件的线程失败", m_logBase);
- return false;
- }
- return true;
- }
- /* 清理数据 */
- void ConsistencyCompareThread::clearData()
- {
- m_isRunning = false;
- m_pCreateWAVThread1 = nullptr;
- m_pCreateWAVThread2 = nullptr;
- /* 设置标志位 */
- m_isRunning = false;
- m_isStop.store(true);
- m_threadInfo.threadState = EThreadState::State_Stopped;
- }
- /* 比对两个wav文件的一致性 */
- bool ConsistencyCompareThread::compareConsistency()
- {
- /* 计算比对需要的时间 */
- std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
- CompareResult* result = LHCompare(m_wavFilePath1.fileName.c_str(), m_wavFilePath2.fileName.c_str(), m_sensitivity);
- if(result == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 一致性比对失败,可能是文件格式不支持或动态库加载失败", m_logBase);
- return false;
- }
- /* 计算比对耗时 */
- std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
- std::chrono::duration<double> duration = endTime - startTime;
- SPDLOG_LOGGER_DEBUG(m_logger, "{} 一致性比对耗时: {}ms", m_logBase,
- std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
- /* 如果高相似度小于1,将两个通道反过来对比一下 */
- if(result->highest_similarity < 1)
- {
- delete result;
- result = nullptr;
- SPDLOG_LOGGER_WARN(m_logger, "{} 高相似度小于1,尝试反向对比", m_logBase);
- result = LHCompare(m_wavFilePath2.fileName.c_str(), m_wavFilePath1.fileName.c_str(), m_sensitivity);
- if(result == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 一致性比对失败,可能是文件格式不支持或动态库加载失败", m_logBase);
- return false;
- }
- }
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 一致性比对结果: 源文件: {}, 目标文件: {}, 最高相似度: {:.3f}, 平均相似度: {:.3f}",
- // m_logBase, m_wavFilePath1.fileName, m_wavFilePath2.fileName, result->highest_similarity, result->average_similarity);
- /* 保存结果 */
- m_consistencyResult.AddResult(result->highest_similarity / 100.0);
- delete result;
- result = nullptr;
- return true;
- }
- /* 根据动态库返回的结果计算一致性 */
- bool ConsistencyCompareThread::computeResult()
- {
- std::string strAIValue, strAIValueNot;
- auto consistencyState = m_consistencyResult.computeConsistency(m_numCompareContinue, m_fConsistencyThreshold, strAIValue);
- auto notConsisencyState = m_consistencyResult.computeNotConsistency(m_numCompareContinue, m_fNotConsistencyThreshold, strAIValueNot);
- if (eConsistencyState::eCS_Consistency == consistencyState)
- {
- /* 计算出的一致性是确定的 */
- m_isConsistency.store(true);
- m_isConsistencyWarning.store(false);
- }
- else if(eConsistencyState::eCS_Consistency == notConsisencyState)
- {
- /* 计算出的不一致性是确定的 */
- m_isConsistency.store(false);
- m_isConsistencyWarning.store(true);
- }else
- {
- /* 都不是确定的一致性和不一致性,使用上次的结果 */
- m_isConsistency.store(m_isConsistencyLatest.load());
- m_isConsistencyWarning.store(true);
- }
- return true;
- }
- /* 保存报警信息 */
- void ConsistencyCompareThread::saveAlarmInfo()
- {
- if(m_isConsistency)
- {
- /* 这次是一致的,判断之前是否在一致性报警中 */
- if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
- {
- /* 之前在一致性报警中,这次一致,结束不一致性报警 */
- m_alarmConsistencyMain.isAlarm = false;
- m_alarmConsistencySub.isAlarm = false;
- /* 结束时间向前推1秒 */
- m_alarmConsistencyMain.EndTime = m_wavFilePath1.endDateTime.addSecs(1);
- m_alarmConsistencySub.EndTime = m_wavFilePath2.endDateTime.addSecs(1);
- /* 结束录制报警音频 */
- m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
- m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
- /* 将报警信息写入数据库 */
- AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
- AlarmManager.addAlarmInfo(m_alarmConsistencySub);
-
- SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
- /* 清除报警信息 */
- m_alarmConsistencyMain = AlarmInfo_t();
- m_alarmConsistencySub = AlarmInfo_t();
- }
- }else
- {
- /* 不一致,判断之前的一致性,判断一个就可以了 */
- if(!m_alarmConsistencySub.isAlarm)
- {
- /* 开是不一致报警 */
- m_alarmConsistencyMain.isAlarm = true;
- m_alarmConsistencySub.isAlarm = true;
- m_alarmConsistencyMain.CompareItemID = m_threadInfo.compareItemInfo.nID;
- m_alarmConsistencySub.CompareItemID = m_threadInfo.compareItemInfo.nID;
- m_alarmConsistencyMain.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
- m_alarmConsistencySub.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
- m_alarmConsistencyMain.RoadInfo = m_itemRoadInfo1;
- m_alarmConsistencySub.RoadInfo = m_itemRoadInfo2;
- m_alarmConsistencyMain.AlarmType = EAlarmType::EAR_Consistency;
- m_alarmConsistencySub.AlarmType = EAlarmType::EAR_Consistency;
-
- /* 计算开始时间,开始时间计算方法:
- 单次计算的时间长度是 numFileDuration, 计算 m_numCompareContinue 次才会不一致性报警,因此向前推
- m_numFileDuration * m_numCompareContinue 秒
- */
- int seconds = m_numFileDuration * m_numCompareContinue;
- /* 因为 m_numCompareContinue 次计算也包括这次的文件,所以从结束时间开始向前推 */
- m_alarmConsistencyMain.StartTime = m_wavFilePath1.endDateTime.addSecs(-seconds);
- m_alarmConsistencySub.StartTime = m_wavFilePath2.endDateTime.addSecs(-seconds);
- SPDLOG_LOGGER_WARN(m_logger, "{}: 不一致报警开始", m_logBase);
- m_threadCreateAlarmFile1->startRecordAlarmFile(m_alarmConsistencyMain);
- m_threadCreateAlarmFile2->startRecordAlarmFile(m_alarmConsistencySub);
- }
- }
- }
- /* 结束报警 */
- void ConsistencyCompareThread::endAlarm()
- {
- m_isConsistency = true;
- /* 这次是一致的,判断之前是否在一致性报警中 */
- if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
- {
- /* 之前在一致性报警中,这次一致,结束不一致性报警 */
- m_alarmConsistencyMain.isAlarm = false;
- m_alarmConsistencySub.isAlarm = false;
- /* 结束时间向前推1秒 */
- m_alarmConsistencyMain.EndTime = m_wavFilePath1.endDateTime.addSecs(1);
- m_alarmConsistencySub.EndTime = m_wavFilePath2.endDateTime.addSecs(1);
- /* 结束录制报警音频 */
- m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
- m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
- /* 将报警信息写入数据库 */
- AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
- AlarmManager.addAlarmInfo(m_alarmConsistencySub);
-
- SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
- /* 清除报警信息 */
- m_alarmConsistencyMain = AlarmInfo_t();
- m_alarmConsistencySub = AlarmInfo_t();
- }
-
- }
|