|
@@ -3,6 +3,8 @@
|
|
|
#include <random>
|
|
|
|
|
|
#include "CreateWAVThread.h"
|
|
|
+#include "CreateLongFileThread.h"
|
|
|
+#include "ThreadAlarmManager.h"
|
|
|
#include "ThreadManager.h"
|
|
|
#include "commonDefine.h"
|
|
|
#include "GlobalInfo.h"
|
|
@@ -27,6 +29,41 @@ NoiseDetectThread::~NoiseDetectThread()
|
|
|
|
|
|
}
|
|
|
|
|
|
+/* 开启对比项通道的噪音报警功能 */
|
|
|
+void NoiseDetectThread::startCompareItemNoiseAlarm(const int itemID, const QString strName, const CompareItemRoadInfo_t& compareItemRoadInfo)
|
|
|
+{
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutexAlarm);
|
|
|
+ /* 如果已经存在这个对比项的报警信息,就不需要重复添加了 */
|
|
|
+ if(m_mapAlarmInfo.find(itemID) != m_mapAlarmInfo.end())
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "{} 对比项 {} 的噪音报警功能已经开启", m_logBase, strName.toStdString());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* 添加对比项的噪音报警信息 */
|
|
|
+ AlarmInfo_t alarmInfo;
|
|
|
+ alarmInfo.CompareItemID = itemID;
|
|
|
+ alarmInfo.strCompareItemName = strName.toStdString();
|
|
|
+ alarmInfo.isAlarm = false; // 初始状态没有报警
|
|
|
+ alarmInfo.RoadInfo = compareItemRoadInfo;
|
|
|
+ alarmInfo.AlarmType = EAlarmType::EAT_Noise;
|
|
|
+
|
|
|
+ m_mapAlarmInfo[itemID] = alarmInfo;
|
|
|
+}
|
|
|
+
|
|
|
+/* 关闭对比项通道的噪音报警功能 */
|
|
|
+void NoiseDetectThread::stopCompareItemNoiseAlarm(const int itemID, const QString strName, const CompareItemRoadInfo_t& compareItemRoadInfo)
|
|
|
+{
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutexAlarm);
|
|
|
+ auto it = m_mapAlarmInfo.find(itemID);
|
|
|
+ if(it != m_mapAlarmInfo.end())
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "{} 对比项 {} 的噪音报警功能已关闭", m_logBase, strName.toStdString());
|
|
|
+ m_mapAlarmInfo.erase(it); // 移除对比项的噪音报警信息
|
|
|
+ }else {
|
|
|
+ SPDLOG_LOGGER_WARN(m_logger, "{} 对比项 {} 的噪音报警功能未开启,无法关闭", m_logBase, strName.toStdString());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
/* 线程功能函数 */
|
|
|
void NoiseDetectThread::task()
|
|
@@ -46,7 +83,7 @@ void NoiseDetectThread::task()
|
|
|
/*------------------------------------------------------------------------
|
|
|
* 获取最新的左右声道数据
|
|
|
*------------------------------------------------------------------------*/
|
|
|
- if(!m_pWAVThread->getLatestLeftRightData(m_leftRightData))
|
|
|
+ if(!m_pThreadWav->getLatestLeftRightData(m_leftRightData))
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
@@ -63,7 +100,7 @@ void NoiseDetectThread::task()
|
|
|
* 处理结果,写噪音报警信息到数据库(这里不写数据库,只计算结果返回给对比项)
|
|
|
* 上面那个函数已经把结果保存了
|
|
|
*------------------------------------------------------------------------*/
|
|
|
- // saveResult();
|
|
|
+ saveResult();
|
|
|
|
|
|
}
|
|
|
clearData(); // 清理数据
|
|
@@ -78,18 +115,37 @@ bool NoiseDetectThread::initData()
|
|
|
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)
|
|
|
+ /* 获取线程 */
|
|
|
+ auto now = std::chrono::steady_clock::now();
|
|
|
+ while(true)
|
|
|
{
|
|
|
- SPDLOG_LOGGER_ERROR(m_logger, "{} 获取数据生成线程失败", m_logBase);
|
|
|
- return false;
|
|
|
+ if(m_pThreadWav == nullptr)
|
|
|
+ {
|
|
|
+ m_pThreadWav = ThreadMan.getCreateWAVThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum);
|
|
|
+ }
|
|
|
+ if(m_pThreadCreateAlarm == nullptr)
|
|
|
+ {
|
|
|
+ m_pThreadCreateAlarm = ThreadMan.getCreateLongFileThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum);
|
|
|
+ }
|
|
|
+ if(m_pThreadWav != nullptr && m_pThreadCreateAlarm != nullptr)
|
|
|
+ {
|
|
|
+ break; // 获取到线程了
|
|
|
+ }
|
|
|
+ if(std::chrono::steady_clock::now() - now > std::chrono::seconds(10))
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "{} 获取数据线程超时", m_logBase);
|
|
|
+ return false; // 超时了,获取线程失败
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
auto sampleRate = GInfo.sampleRate();
|
|
|
m_sample_rate = static_cast<double>(sampleRate);
|
|
|
|
|
|
- /* 初始化噪音检测功能 */
|
|
|
- // signalstats_wrapper::initialize();
|
|
|
+ /* 获取噪音检测参数 */
|
|
|
+ m_noiseDetectParam = SysConfig.getNoiseDetectParam();
|
|
|
+
|
|
|
+ /* 设置噪音检测参数 */
|
|
|
+ m_ringQueueIsNoise.setQueueCapacity(m_noiseDetectParam.nNoiseDetectContinueCount);
|
|
|
|
|
|
return true;
|
|
|
}
|
|
@@ -108,15 +164,6 @@ bool NoiseDetectThread::detectNoise()
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "{} 左声道数据大小: {}, 右声道数据大小: {}",
|
|
|
m_logBase, m_leftRightData.vecLeftData.size(), m_leftRightData.vecRightData.size());
|
|
|
|
|
|
- // std::vector<double> 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; /* 是否检测到右声道噪音 */
|
|
@@ -127,7 +174,6 @@ bool NoiseDetectThread::detectNoise()
|
|
|
auto ret = signalstats::detect_signal(
|
|
|
jsonOutput, /* 返回结果,和jsonResult是一样的 */
|
|
|
m_leftRightData.vecLeftData, /* 左声道数据 */
|
|
|
- // audio_signal, /* 测试数据 */
|
|
|
m_sample_rate, /* 采样率(HZ) */
|
|
|
m_silence_threshold, /* 静音阈值 */
|
|
|
m_db_threshold, /* 分贝阈值 */
|
|
@@ -150,7 +196,6 @@ bool NoiseDetectThread::detectNoise()
|
|
|
signalstats::detect_signal(
|
|
|
jsonOutput, /* 返回结果,和jsonResult是一样的 */
|
|
|
m_leftRightData.vecRightData, /* 右声道数据 */
|
|
|
- // audio_signal, /* 测试数据 */
|
|
|
m_sample_rate, /* 采样率(HZ) */
|
|
|
m_silence_threshold, /* 静音阈值 */
|
|
|
m_db_threshold, /* 分贝阈值 */
|
|
@@ -163,11 +208,7 @@ bool NoiseDetectThread::detectNoise()
|
|
|
);
|
|
|
isNoiseRight = jsonOutput["noise"].is_null() ? false : jsonOutput["noise"].get<bool>();
|
|
|
|
|
|
- // for(const auto& it : m_leftRightData.vecRightData)
|
|
|
- // {
|
|
|
- // fmt::print("{:.5f} ", it);
|
|
|
- // }
|
|
|
- SPDLOG_LOGGER_DEBUG(m_logger, "{} 右声道噪音检测结果: {}", m_logBase, jsonOutput.dump(4));
|
|
|
+ // SPDLOG_LOGGER_DEBUG(m_logger, "{} 右声道噪音检测结果: {}", m_logBase, jsonOutput.dump(4));
|
|
|
|
|
|
}
|
|
|
catch (const std::exception& e)
|
|
@@ -183,8 +224,7 @@ bool NoiseDetectThread::detectNoise()
|
|
|
SPDLOG_LOGGER_DEBUG(m_logger, "{} 左声道噪音检测结果: {}, 右声道噪音检测结果: {}", m_logBase, isNoiseLeft, isNoiseRight);
|
|
|
|
|
|
/* -------------------------- 和以往的结果对比 --------------------------*/
|
|
|
- m_isNoiseLast = m_isNoise.load(); /* 上一次的噪音检测结果 */
|
|
|
- m_isNoise.store(isNoiseLeft || isNoiseRight); /* 是否检测到噪音 */
|
|
|
+ m_currentIsNoise = (isNoiseLeft || isNoiseRight); /* 是否检测到噪音 */
|
|
|
|
|
|
return true;
|
|
|
}
|
|
@@ -193,14 +233,100 @@ bool NoiseDetectThread::detectNoise()
|
|
|
/* 保存结果 */
|
|
|
void NoiseDetectThread::saveResult()
|
|
|
{
|
|
|
- if(m_isNoiseLast)
|
|
|
+ /* 将当前噪音检测结果保存到环形队列中 */
|
|
|
+ m_ringQueueIsNoise.push(m_currentIsNoise);
|
|
|
+ /* 计算出噪音个数和噪音所占百分比 */
|
|
|
+ const int size = m_ringQueueIsNoise.QueueSize();
|
|
|
+ int numNoise = 0; // 噪音的个数
|
|
|
+ int numCountinueNoise = 0; // 连续噪音的个数
|
|
|
+ double percentNoise = 0.0; // 噪音所占百分比
|
|
|
+ for(int i = 0; i < size; ++i)
|
|
|
+ {
|
|
|
+ if(m_ringQueueIsNoise.at(i))
|
|
|
+ {
|
|
|
+ numNoise++;
|
|
|
+ numCountinueNoise++;
|
|
|
+ }else {
|
|
|
+ numCountinueNoise = 0; // 如果不是噪音,连续噪音计数清零
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* 判断是否是噪音预警 */
|
|
|
+ if(numCountinueNoise >= m_noiseDetectParam.nNoiseContinueCountIsWarn)
|
|
|
+ {
|
|
|
+ m_isNoiseWarning.store(true);
|
|
|
+ }
|
|
|
+ percentNoise = numNoise * 100.0 / m_noiseDetectParam.nNoiseContinueCountPercent;
|
|
|
+ /* 根据噪音所占的百分比判断是否是噪音 */
|
|
|
+ if(percentNoise >= m_noiseDetectParam.nNoiseContinueCountPercent)
|
|
|
{
|
|
|
- /* 判断这次是否是噪音,没有噪音就报警结束 */
|
|
|
+ m_isNoise.store(true);
|
|
|
+ }else {
|
|
|
+ m_isNoise.store(false);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
+ if(m_isNoise.load())
|
|
|
+ {
|
|
|
+ /* 判断上次是否是噪音 */
|
|
|
+ if(!m_isNoiseLast)
|
|
|
+ {
|
|
|
+ /* 开始噪音报警 */
|
|
|
+ m_isNoiseWarning = true;
|
|
|
+ /* 通知对比项线程,开始噪音报警 */
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutexAlarm);
|
|
|
+ for(auto& pair : m_mapAlarmInfo)
|
|
|
+ {
|
|
|
+ AlarmInfo_t& alarmInfo = pair.second;
|
|
|
+ if(!alarmInfo.isAlarm) // 如果没有报警
|
|
|
+ {
|
|
|
+ alarmInfo.isAlarm = true; // 设置为报警状态
|
|
|
+ /* 向前推算噪音开始时间,开始时间需要向前推 n次噪音检测的时间 x 单次噪音检测需要的时间,单位秒 */
|
|
|
+ int nNoiseDetectTime = m_noiseDetectParam.nNoiseDetectContinueCount * m_noiseDetectParam.nNoiseDetectDuration;
|
|
|
+ QDateTime startTime = m_leftRightData.startTime;
|
|
|
+ startTime = startTime.addSecs(-nNoiseDetectTime);
|
|
|
+ alarmInfo.StartTime = startTime;
|
|
|
+ SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 开始噪音报警", m_logBase, alarmInfo.strCompareItemName,
|
|
|
+ alarmInfo.RoadInfo.strCompareRoadName.toStdString());
|
|
|
+ /* 这里可以添加通知录制报警文件的线程开始录音 */
|
|
|
+ if(m_pThreadCreateAlarm != nullptr)
|
|
|
+ {
|
|
|
+ m_pThreadCreateAlarm->startRecordAlarmFile(alarmInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}else
|
|
|
{
|
|
|
- /* 上一次没有噪音,这次有噪音,噪音报警开始 */
|
|
|
-
|
|
|
+ /* 没有噪音,判断是否结束报警 */
|
|
|
+ if(m_isNoiseLast)
|
|
|
+ {
|
|
|
+ /* 停止噪音报警 */
|
|
|
+ m_isNoiseWarning = false;
|
|
|
+ /* 通知对比项线程,结束噪音报警 */
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutexAlarm);
|
|
|
+ for(auto& pair : m_mapAlarmInfo)
|
|
|
+ {
|
|
|
+ AlarmInfo_t& alarmInfo = pair.second;
|
|
|
+ if(alarmInfo.isAlarm) // 如果正在报警
|
|
|
+ {
|
|
|
+ // 设置为非报警状态
|
|
|
+ alarmInfo.isAlarm = false;
|
|
|
+ /* 设置结束时间 */
|
|
|
+ alarmInfo.EndTime = m_leftRightData.endTime;
|
|
|
+ SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 结束噪音报警", m_logBase, alarmInfo.strCompareItemName,
|
|
|
+ alarmInfo.RoadInfo.strCompareRoadName.toStdString());
|
|
|
+ /* 这里可以添加通知录制报警文件的线程停止录音 */
|
|
|
+ if(m_pThreadCreateAlarm != nullptr)
|
|
|
+ {
|
|
|
+ m_pThreadCreateAlarm->stopRecordAlarmFile(alarmInfo);
|
|
|
+ }
|
|
|
+ /* 写入数据库,并清空时间 */
|
|
|
+ AlarmManager.addAlarmInfo(alarmInfo);
|
|
|
+ alarmInfo.StartTime = QDateTime();
|
|
|
+ alarmInfo.EndTime = QDateTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
}
|