CreateDBThread.cpp 9.1 KB

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