CreateDBThread.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "CreateDBThread.h"
  2. #include "GlobalVariable.h"
  3. #include "AudioData.h"
  4. #include "GlobalInfo.h"
  5. #include "CalculateAudio.h"
  6. CreateDBThread::CreateDBThread(RecordThreadInfo_t& threadInfo)
  7. : BaseRecordThread(threadInfo)
  8. {
  9. }
  10. CreateDBThread::~CreateDBThread()
  11. {
  12. }
  13. /* 设置数据 */
  14. bool CreateDBThread::setData(const AudioSrcData& srcData)
  15. {
  16. if(srcData.pData == nullptr || srcData.dataSize == 0)
  17. {
  18. SPDLOG_LOGGER_ERROR(m_logger, "{} 设置数据失败,srcData为空或dataSize为0", m_logBase);
  19. return false;
  20. }
  21. /* 创建一个新的AudioSrcData对象 */
  22. AudioSrcData* audioData = new AudioSrcData(srcData);
  23. if(audioData == nullptr)
  24. {
  25. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建AudioSrcData对象失败", m_logBase);
  26. return false;
  27. }
  28. /* 判断环形队列是否满 */
  29. if(m_queueAudioData.isFull())
  30. {
  31. /* 出队一个最早的元素 */
  32. AudioSrcData* oldData = m_queueAudioData.front_pop();
  33. SPDLOG_LOGGER_WARN(m_logger, "{} 环形队列已满,出队一个元素,时间: {}, 大小: {}",
  34. m_logBase, oldData->startTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), oldData->dataSize);
  35. if(oldData != nullptr){
  36. delete oldData;
  37. oldData = nullptr;
  38. }
  39. }
  40. /* 入队新的数据 */
  41. if(!m_queueAudioData.push_noBlock(audioData))
  42. {
  43. SPDLOG_LOGGER_ERROR(m_logger, "{} 数据加入环形队列失败", m_logBase);
  44. delete audioData; // 入队失败,释放内存
  45. audioData = nullptr;
  46. return false;
  47. }
  48. return true;
  49. }
  50. /* 获取最新的结果,根据时间进行对比,最新的时间比传入的晚,就是有新的数据了 */
  51. bool CreateDBThread::getLatestResult(OneSecondData& resultData)
  52. {
  53. if(resultData.startTime.isNull())
  54. {
  55. // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新结果失败,传入的时间戳为空", m_logBase);
  56. return false;
  57. }
  58. std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
  59. auto lastSecondData = m_queueResultData->back();
  60. if(lastSecondData == nullptr)
  61. {
  62. SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新结果失败,结果队列为空", m_logBase);
  63. return false;
  64. }
  65. /* 比较时间戳 */
  66. if(lastSecondData->startTime <= resultData.startTime)
  67. {
  68. return false;
  69. }
  70. resultData = *lastSecondData;
  71. return true;
  72. }
  73. /* 获取最新的结果,让整个环形队列相等 */
  74. bool CreateDBThread::getLatestResult(RingQueueManualMutex<OneSecondData*>& resultQueue)
  75. {
  76. std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
  77. if(m_queueResultData->isEmpty())
  78. {
  79. // SPDLOG_LOGGER_TRACE(m_logger, "{} 获取最新数据,数据队列为空", m_logBase);
  80. return false;
  81. }
  82. /* 目标队列为空,全部拷贝 */
  83. if(resultQueue.isEmpty())
  84. {
  85. SPDLOG_LOGGER_DEBUG(m_logger, "{} 获取最新数据,目标队列为空,拷贝整个结果队列", m_logBase);
  86. for(int i = 0; i < m_queueResultData->QueueSize(); ++i)
  87. {
  88. OneSecondData* data = m_queueResultData->at(i);
  89. if(data != nullptr)
  90. {
  91. OneSecondData* newData = new OneSecondData(*data); // 深拷贝
  92. resultQueue.push(newData);
  93. }
  94. }
  95. return true;
  96. }
  97. /* 队列不为空,查找队列中相等的位置,拷贝后面的数据,不拷贝整个队列,减少开销
  98. * 这里直接从最新的数据往前找 */
  99. auto itBack = resultQueue.back();
  100. int index = m_queueResultData->QueueSize() - 1;
  101. while(index >= 0)
  102. {
  103. OneSecondData* data = m_queueResultData->at(index);
  104. if(data == nullptr)
  105. {
  106. --index;
  107. continue;
  108. }
  109. /* 找到相等的位置 */
  110. if(data->startTime == itBack->startTime)
  111. {
  112. break;
  113. }
  114. --index;
  115. }
  116. if(index < 0)
  117. {
  118. SPDLOG_LOGGER_WARN(m_logger, "{} 获取最新数据失败,未找到相等的时间戳,将清空队列,拷贝全部数据", m_logBase);
  119. SPDLOG_LOGGER_WARN(m_logger, "队列大小: {}, 目标队列大小: {}", m_queueResultData->QueueSize(), resultQueue.QueueSize());
  120. /* 清空目标队列,将所有的数据全部拷贝 */
  121. while(!resultQueue.isEmpty())
  122. {
  123. OneSecondData* data = resultQueue.front_pop();
  124. if(data != nullptr)
  125. {
  126. delete data;
  127. data = nullptr;
  128. }
  129. }
  130. /* 拷贝全部数据 */
  131. for(int i = 0; i < m_queueResultData->QueueSize(); ++i)
  132. {
  133. OneSecondData* data = m_queueResultData->at(i);
  134. if(data != nullptr)
  135. {
  136. OneSecondData* newData = new OneSecondData(*data); // 深拷贝
  137. resultQueue.push(newData);
  138. }
  139. }
  140. return true;
  141. }
  142. else if(index == m_queueResultData->QueueSize() - 1)
  143. {
  144. // 已经是最新的数据了,不需要拷贝
  145. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 获取最新数据,已经是最新的数据了", m_logBase);
  146. return false;
  147. }
  148. /* 拷贝数据 */
  149. for(; index < m_queueResultData->QueueSize(); ++index)
  150. {
  151. OneSecondData* data = m_queueResultData->at(index);
  152. if(data == nullptr)
  153. {
  154. continue;
  155. }
  156. OneSecondData* newData = new OneSecondData(*data); // 深拷贝
  157. auto fornt = resultQueue.push(newData);
  158. if(fornt != nullptr)
  159. {
  160. delete fornt; // 出队的元素是之前的结果,释放内存
  161. fornt = nullptr;
  162. }
  163. }
  164. return true;
  165. }
  166. /* 计算音量和反相的线程函数 */
  167. void CreateDBThread::task()
  168. {
  169. SPDLOG_LOGGER_INFO(m_logger, "➢ {} 开始计算音量线程", m_logBase);
  170. /* 初始化一些数据 */
  171. if(!initData())
  172. {
  173. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
  174. return;
  175. }
  176. while(m_isRunning)
  177. {
  178. /* 取出一个数据,没有数据则阻塞住 */
  179. AudioSrcData* audioData = m_queueAudioData.front_pop();
  180. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 从环形队列中取出数据,队列大小: {}", m_logBase, m_queueAudioData.QueueSize());
  181. if(audioData == nullptr)
  182. {
  183. SPDLOG_LOGGER_WARN(m_logger, "{} 从环形队列中取出数据失败,可能是队列为空", m_logBase);
  184. std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待一段时间再尝试
  185. continue;
  186. }
  187. /* 计算音量和反相,结果存储在m_result */
  188. if(!CreateDBPhase(audioData))
  189. {
  190. SPDLOG_LOGGER_ERROR(m_logger, "{} 计算音量和反相失败", m_logBase);
  191. }
  192. /* 将结果放入结果队列 */
  193. if(m_result != nullptr)
  194. {
  195. std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
  196. auto result = m_queueResultData->push(m_result);
  197. if(result != nullptr)
  198. {
  199. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 队列已满,出队一个元素", m_logBase);
  200. delete result; // 出队的元素是之前的结果,释放内存
  201. result = nullptr;
  202. }
  203. m_result = nullptr; // 清空结果指针,等待下一次使用
  204. }
  205. delete audioData; // 释放内存
  206. audioData = nullptr;
  207. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 创建音量的线程处理数据完成,队列大小: {}",
  208. // m_logBase, m_queueResultData->QueueSize());
  209. }
  210. /* 清理数据 */
  211. clearData();
  212. SPDLOG_LOGGER_WARN(m_logger, "➢ {} 计算音量线程结束 ", m_logBase);
  213. }
  214. /* 初始化一些数据 */
  215. bool CreateDBThread::initData()
  216. {
  217. int queueSize = GInfo.queueElementCount();
  218. /* 初始化一些数据 */
  219. m_queueAudioData.clearQueue();
  220. m_queueAudioData.setQueueCapacity(queueSize);
  221. m_sampleRate = GInfo.sampleRate(); /* 采样率 */
  222. m_numChannels = GInfo.numChannels(); /* 声道数 */
  223. m_bitsPerSample = GInfo.bitsPerSample(); /* 每个采样点的位数 */
  224. /* 一秒钟数据大小,单位:字节 */
  225. m_oneSecondSize = m_sampleRate * m_numChannels * (m_bitsPerSample / 8);
  226. /* 计算音量和反相的环形队列元素数目,默认是180个,即180秒 */
  227. m_queueAudioDataCapacity = queueSize;
  228. m_queueResultData = new RingQueueManualMutex<OneSecondData*>(m_queueAudioDataCapacity);
  229. m_queueResultData->mutex.lock();
  230. m_queueResultData->setDefaultValue(nullptr);
  231. m_queueResultData->mutex.unlock();
  232. return true;
  233. }
  234. /* 清理数据 */
  235. void CreateDBThread::clearData()
  236. {
  237. /* 清理环形队列 */
  238. while(!m_queueAudioData.isEmpty())
  239. {
  240. AudioSrcData* data = m_queueAudioData.front_pop();
  241. if(data != nullptr)
  242. {
  243. delete data;
  244. data = nullptr;
  245. }
  246. }
  247. // if(m_remainData != nullptr)
  248. // {
  249. // delete m_remainData;
  250. // m_remainData = nullptr;
  251. // }
  252. }
  253. /* 计算音量和反相 */
  254. bool CreateDBThread::CreateDBPhase(AudioSrcData* audioData)
  255. {
  256. short* pWaveVu = (short*)(audioData->pData);
  257. /* 一秒钟平分30个音量值,每个音量值占有的长度 */
  258. const int oneDBSize = m_oneDBLengthOfSrcData;;
  259. StAudioNum audioInfo;
  260. audioInfo.roadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
  261. audioInfo.nTotal = m_singleDataLength;
  262. int iCurPos = 0;
  263. /* 存储结果 */
  264. m_result = new OneSecondData();
  265. /* 计算音量和反相的计算类 */
  266. CAudio2ChanCorrelator audioCor;
  267. /* 音量值计算,好多个字节计算出一个最大音量值 */
  268. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  269. {
  270. // oneDBSize / 2 除以2是因为左右声道同时计算
  271. // 采样点最大值
  272. short sMaxA, sMaxB, sRMSA, sRMSB;
  273. audioCor.CorrelateChunks(pWaveVu + iCurPos, (pWaveVu + iCurPos + 1), oneDBSize / 2, &sMaxA, &sMaxB, &sRMSA, &sRMSB, audioInfo);
  274. iCurPos += oneDBSize;
  275. m_result->aryLeftDB[i] = calculateDB(sMaxA);
  276. m_result->aryRightDB[i] = calculateDB(sMaxB);
  277. // 获取反相值,-100 到 100;反相是左右声道比对得到的值,所以只有一个
  278. int iReversed = audioCor.GetCorrelationLevel();
  279. if(iReversed > REVERSED_MAX_VALUE || iReversed < REVERSED_MIN_VALUE)
  280. {
  281. iReversed = 0;
  282. }
  283. // 和反相阀值比较,来判定是否为反相
  284. float dReversed = iReversed / 100.00;
  285. m_result->aryPhase[i] = dReversed;
  286. }
  287. /* 设置时间戳 */
  288. m_result->startTime = audioData->startTime;
  289. m_result->endTime = audioData->endTime;
  290. return true;
  291. }