CalculateAudio.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. #include "CalculateAudio.h"
  2. #include "spdlog/spdlog.h"
  3. #include "AudioData.h"
  4. #include <string>
  5. StAudioNum::StAudioNum()
  6. {
  7. nTotal = 0;
  8. nLDataNum = 0;
  9. nLUnDataNum = 0;
  10. nRDataNum = 0;
  11. nRUnDataNum = 0;
  12. }
  13. StAudioNum& StAudioNum::operator=(const StAudioNum& obj)
  14. {
  15. roadInfo = obj.roadInfo;
  16. nTotal = obj.nTotal;
  17. nLDataNum = obj.nLDataNum;
  18. nLUnDataNum = obj.nLUnDataNum;
  19. nRDataNum = obj.nRDataNum;
  20. nRUnDataNum = obj.nRUnDataNum;
  21. return *this;
  22. }
  23. bool StAudioNum::AudioIsError(int nDataNum, int nUnDataNum, bool bLeft)
  24. {
  25. std::string strRoadName = roadInfo.strSoundCardName.toStdString() + ":" + std::to_string(roadInfo.roadInfo.nRoadNum);
  26. if (nDataNum > 0 && nUnDataNum > 0 && pcmErrorPercent > 0)
  27. {
  28. int nMax = nDataNum > nUnDataNum ? nDataNum : nUnDataNum;
  29. int nMin = nDataNum < nUnDataNum ? nDataNum : nUnDataNum;
  30. nMin *= 100;
  31. int nPer = nMin / nMax;
  32. if (nPer < pcmErrorPercent )
  33. {
  34. if (bLeft)
  35. {
  36. SPDLOG_INFO("通道{}: 左声道数据不对称,判断为噪音, Left: {}, {}", strRoadName, nLDataNum, nLUnDataNum);
  37. } else
  38. {
  39. SPDLOG_INFO("通道{}: 右声道数据不对称,判断为噪音, Right: {}, {}", strRoadName, nRDataNum, nRUnDataNum);
  40. }
  41. return true;
  42. }
  43. }
  44. return false;
  45. }
  46. // 有问题的音频
  47. bool StAudioNum::IsErrorAudio()
  48. {
  49. std::string strRoadName = roadInfo.strSoundCardName.toStdString() + ":" + std::to_string(roadInfo.roadInfo.nRoadNum);
  50. const int nMute = 200;
  51. if (nLDataNum > nMute || nLUnDataNum > nMute || nRDataNum > nMute || nRUnDataNum > nMute)
  52. {
  53. if (pcmLessPercent > 0)
  54. {
  55. const int nMinTotal = nTotal / pcmLessPercent;
  56. if ((nLDataNum > 0 || nLUnDataNum > 0) && (nLDataNum < nMinTotal || nLUnDataNum < nMinTotal) )
  57. {
  58. SPDLOG_INFO("通道{} : 左声道数据很少, Left: {}, {}, Right: {}, {}", strRoadName, nLDataNum, nLUnDataNum, nRDataNum, nRUnDataNum);
  59. // 不是静音,但数据很少,直接判断为有误
  60. return true;
  61. }
  62. if ((nRDataNum > 0 || nRUnDataNum > 0) && (nRDataNum < nMinTotal || nRUnDataNum < nMinTotal))
  63. {
  64. SPDLOG_INFO("通道{} : 右声道数据很少, Left: {}, {}, Right: {}, {}", strRoadName, nLDataNum, nLUnDataNum, nRDataNum, nRUnDataNum);
  65. // 不是静音,但数据很少,直接判断为有误
  66. return true;
  67. }
  68. }
  69. } else
  70. {
  71. SPDLOG_INFO("通道 {} : 静音了, Left: {}, {}, Right: {}, {}", strRoadName, nLDataNum, nLUnDataNum, nRDataNum, nRUnDataNum);
  72. return false; // 静音了
  73. }
  74. if (AudioIsError(nLDataNum, nLUnDataNum, true))
  75. {
  76. return true;
  77. }
  78. if (AudioIsError(nRDataNum, nRUnDataNum, false))
  79. {
  80. return true;
  81. }
  82. return false;
  83. }
  84. /*--------------------------------------------------------------------------
  85. * CAudio2ChanCorrelator 成员函数
  86. *--------------------------------------------------------------------------*/
  87. CAudio2ChanCorrelator::CAudio2ChanCorrelator()
  88. : m_nDisplayCutOffLevel(128) // 以前是64,音量为-50时反相不准确,所以修改为128 20150508 jinhl
  89. , m_bSignA(false)
  90. , m_fCorrelationSum(0.0f)
  91. , m_nCorrelationValue(0)
  92. , m_fDampingFactor(0.3f)
  93. {
  94. }
  95. CAudio2ChanCorrelator::~CAudio2ChanCorrelator()
  96. {
  97. }
  98. /**
  99. * @brief correlate data contained in A & B buffers ( range -100 to 100 )
  100. *
  101. * @param ptrBufferA
  102. * @param ptrBufferB
  103. * @param nBufferLength
  104. * @param pMaxA
  105. * @param pMaxB
  106. * @param pRMSA
  107. * @param pRMSB
  108. * @param audioInfo
  109. * @return int
  110. */
  111. int CAudio2ChanCorrelator::CorrelateChunks(const short * ptrBufferA,
  112. const short * ptrBufferB,
  113. int nBufferLength,
  114. short* pMaxA, short* pMaxB,
  115. short* pRMSA, short* pRMSB,
  116. StAudioNum &audioInfo)
  117. {
  118. int64_t nTotalA = 0, nTotlB = 0;
  119. *pMaxA = *pMaxB = *pRMSA = *pRMSB = 0;
  120. m_fCorrelationSum = 0; // reset correlation sum
  121. int nSamplesProcessedCount = 0;
  122. if( ptrBufferB )
  123. {
  124. for ( int i = 0; i < nBufferLength; i+=2)// run through the buffer
  125. {
  126. if( abs((int)*ptrBufferA) > *pMaxA )
  127. {
  128. *pMaxA = abs((int)*ptrBufferA);
  129. }
  130. nTotalA += (*ptrBufferA)*(*ptrBufferA);
  131. if( abs((int)*ptrBufferB) > *pMaxB )
  132. {
  133. *pMaxB = abs((int)*ptrBufferB);
  134. }
  135. nTotlB += (*ptrBufferB)*(*ptrBufferB);
  136. //test sample A against threshold and if above record it's sign
  137. if (*ptrBufferA < m_nDisplayCutOffLevel && *ptrBufferA > -m_nDisplayCutOffLevel)
  138. {
  139. ptrBufferA += 2;// increment buffer pointers for next sample in the loop
  140. ptrBufferB += 2;
  141. continue; //level A below display threshold, hence no more processing required
  142. }
  143. if (*ptrBufferA > m_nDisplayCutOffLevel )
  144. {
  145. // 金海林添加 2022-11-17 统计音频数据正负数
  146. ++audioInfo.nLDataNum;
  147. m_bSignA = true; // A sample is positive
  148. }
  149. else
  150. {
  151. // 金海林添加 2022-11-17 统计音频数据正负数
  152. ++audioInfo.nLUnDataNum;
  153. m_bSignA =false; // A sample is negative
  154. }
  155. //test sample B against threshold
  156. if (*ptrBufferB < m_nDisplayCutOffLevel && *ptrBufferB > -m_nDisplayCutOffLevel)
  157. {
  158. ptrBufferA += 2;// increment buffer pointers for next sample in the loop
  159. ptrBufferB += 2;
  160. continue; //level B below display threshold, hence no more processing required
  161. }
  162. if (*ptrBufferB > m_nDisplayCutOffLevel ) //B sample is positive
  163. {
  164. // 金海林添加 2022-11-17 统计音频数据正负数
  165. ++audioInfo.nRDataNum;
  166. if(m_bSignA == true) // A & B samples are positive
  167. m_fCorrelationSum++;
  168. else
  169. m_fCorrelationSum--; // A negative & B positive
  170. }
  171. else //B sample is negative
  172. {
  173. // 金海林添加 2022-11-17 统计音频数据正负数
  174. ++audioInfo.nRUnDataNum;
  175. if(m_bSignA == false) // A & B samples are negative
  176. m_fCorrelationSum++;
  177. else
  178. m_fCorrelationSum--; // A positive & B negative
  179. }
  180. // increment the buffers for next sample in the for loop
  181. ptrBufferA += 2;
  182. ptrBufferB += 2;
  183. nSamplesProcessedCount++;
  184. }//end of for loop
  185. m_nCorrelationValue = (int)(100 * (1- m_fDampingFactor) *m_fCorrelationSum/nSamplesProcessedCount + 1)
  186. + (int)(m_nCorrelationValue * m_fDampingFactor);
  187. *pRMSA = sqrt((long double)nTotalA/nBufferLength);
  188. *pRMSB = sqrt((long double)nTotlB/nBufferLength);
  189. }
  190. else
  191. {
  192. for ( int i = 0; i < nBufferLength; i++)// run through the buffer
  193. {
  194. if( abs((int)*ptrBufferA) > *pMaxA )
  195. {
  196. *pMaxA = abs((int)*ptrBufferA);
  197. }
  198. nTotalA += (*ptrBufferA)*(*ptrBufferA);
  199. // increment the buffers for next sample in the for loop
  200. ptrBufferA += 1;
  201. }//end of for loop
  202. m_nCorrelationValue = 100;
  203. *pRMSA = sqrt((long double)nTotalA/nBufferLength);
  204. }
  205. return m_nCorrelationValue;
  206. }
  207. int CAudio2ChanCorrelator::CorrelateChunks(const short * ptrBufferA,
  208. const short * ptrBufferB,
  209. int nBufferLength,
  210. short* pMaxA, short* pMaxB,
  211. short* pRMSA, short* pRMSB,
  212. short* pLRAvg) //L+R的平均值
  213. {
  214. int64_t nTotalA = 0, nTotlB = 0;
  215. *pMaxA = *pMaxB = *pRMSA = *pRMSB = *pLRAvg = 0;
  216. m_fCorrelationSum = 0; // reset correlation sum
  217. int nSamplesProcessedCount = 0;
  218. if( ptrBufferB )
  219. {
  220. for ( int i = 0; i < nBufferLength; i+=2)// run through the buffer
  221. {
  222. if( abs((int)*ptrBufferA) > *pMaxA )
  223. {
  224. *pMaxA = abs((int)*ptrBufferA);
  225. }
  226. nTotalA += (*ptrBufferA)*(*ptrBufferA);
  227. if( abs((int)*ptrBufferB) > *pMaxB )
  228. {
  229. *pMaxB = abs((int)*ptrBufferB);
  230. }
  231. nTotlB += (*ptrBufferB)*(*ptrBufferB);
  232. if( abs((int)*ptrBufferA+(int)*ptrBufferB)/2 > *pLRAvg )
  233. {
  234. *pLRAvg = abs((int)*ptrBufferA+(int)*ptrBufferB)/2;
  235. }
  236. //test sample A against threshold and if above record it's sign
  237. if (*ptrBufferA < m_nDisplayCutOffLevel && *ptrBufferA > -m_nDisplayCutOffLevel)
  238. {
  239. ptrBufferA += 2;// increment buffer pointers for next sample in the loop
  240. ptrBufferB += 2;
  241. continue; //level A below display threshold, hence no more processing required
  242. }
  243. if (*ptrBufferA > m_nDisplayCutOffLevel )
  244. m_bSignA = true; // A sample is positive
  245. else
  246. m_bSignA =false; // A sample is negative
  247. //test sample B against threshold
  248. if (*ptrBufferB < m_nDisplayCutOffLevel && *ptrBufferB > -m_nDisplayCutOffLevel)
  249. {
  250. ptrBufferA += 2;// increment buffer pointers for next sample in the loop
  251. ptrBufferB += 2;
  252. continue; //level B below display threshold, hence no more processing required
  253. }
  254. if (*ptrBufferB > m_nDisplayCutOffLevel ) //B sample is positive
  255. {
  256. if(m_bSignA == true) // A & B samples are positive
  257. m_fCorrelationSum++;
  258. else
  259. m_fCorrelationSum--; // A negative & B positive
  260. }
  261. else //B sample is negative
  262. {
  263. if(m_bSignA == false) // A & B samples are negative
  264. m_fCorrelationSum++;
  265. else
  266. m_fCorrelationSum--; // A positive & B negative
  267. }
  268. // increment the buffers for next sample in the for loop
  269. ptrBufferA += 2;
  270. ptrBufferB += 2;
  271. nSamplesProcessedCount++;
  272. }//end of for loop
  273. m_nCorrelationValue = (int)(100 * (1- m_fDampingFactor) *m_fCorrelationSum/nSamplesProcessedCount + 1)
  274. + (int)(m_nCorrelationValue * m_fDampingFactor);
  275. *pRMSA = sqrt((long double)nTotalA/nBufferLength);
  276. *pRMSB = sqrt((long double)nTotlB/nBufferLength);
  277. }
  278. else
  279. {
  280. for ( int i = 0; i < nBufferLength; i++)// run through the buffer
  281. {
  282. if( abs((int)*ptrBufferA) > *pMaxA )
  283. {
  284. *pMaxA = abs((int)*ptrBufferA);
  285. }
  286. nTotalA += (*ptrBufferA)*(*ptrBufferA);
  287. // increment the buffers for next sample in the for loop
  288. ptrBufferA += 1;
  289. }//end of for loop
  290. m_nCorrelationValue = 100;
  291. *pRMSA = sqrt((long double)nTotalA/nBufferLength);
  292. }
  293. return m_nCorrelationValue;
  294. }
  295. /**
  296. * @brief returns current correlation value (between -100 to 100)
  297. *
  298. * @return int
  299. */
  300. int CAudio2ChanCorrelator::GetCorrelationLevel(void)
  301. {
  302. return m_nCorrelationValue;
  303. }
  304. /*--------------------------------------------------------------------------
  305. * 全局函数
  306. *--------------------------------------------------------------------------*/
  307. int calculateDB(short val)
  308. {
  309. if( val == 0 )
  310. {
  311. return -90;
  312. }
  313. if( val < 0 )
  314. {
  315. val = -val;
  316. }
  317. int iDB = ( 20*log10((long double)val) - 90.3 );
  318. if(iDB > VOLUME_MAX_BD || iDB < VOLUME_MIN_BD)
  319. {
  320. iDB = VOLUME_MIN_BD;
  321. }
  322. return iDB;
  323. }
  324. /*--------------------------------------------------------------------------
  325. * 计算音量的静音、过载、反相等功能的类
  326. *--------------------------------------------------------------------------*/
  327. CaculateDBData::CaculateDBData()
  328. {
  329. /* 初始化环形队列 */
  330. ringQueue.setQueueCapacity(CACHE_DATA_SECOND_MAX);
  331. ringQueue.setDefaultValue(nullptr);
  332. }
  333. CaculateDBData::~CaculateDBData()
  334. {
  335. if(!ringQueue.isEmpty())
  336. {
  337. OneSecondData* data = nullptr;
  338. while(!ringQueue.isEmpty())
  339. {
  340. data = ringQueue.front_pop();
  341. if(data)
  342. {
  343. delete data; // 释放内存
  344. data = nullptr;
  345. }
  346. }
  347. ringQueue.clearQueue(); // 清空队列
  348. }
  349. }
  350. /* 设置偏移值 */
  351. void CaculateDBData::setOffset(long offset)
  352. {
  353. /* 将ms转换成秒 */
  354. int offsetSeconds = offset / 1000;
  355. if(offsetSeconds < ringQueue.QueueSize())
  356. {
  357. m_offset = offsetSeconds;
  358. }
  359. }
  360. /**
  361. * @brief 根据参数计算静音的起始和结束位置
  362. *
  363. * @param param 这个频道的音量参数
  364. * @param avgDBSeconds 计算静音的平均音量秒数
  365. * @param startPos 开始位置
  366. * @param endPos 结束位置
  367. * @return true
  368. * @return false
  369. */
  370. bool CaculateDBData::calculateSilent(const StVolumeParam& param, const int avgDBSeconds, int& startPos, int& endPos)
  371. {
  372. startPos = -1;
  373. endPos = -1;
  374. if(param.GetSilentSwitch())
  375. {
  376. const int silentDuration = param.GetSilentDuration();
  377. if (silentDuration >= CACHE_DATA_SECOND_MAX)
  378. {
  379. SPDLOG_WARN("静音持续时间({})不能大于等于最大缓存{}秒", silentDuration, CACHE_DATA_SECOND_MAX);
  380. return false;
  381. }
  382. if (ringQueue.QueueSize() < (silentDuration + m_offset) || silentDuration <= 0)
  383. {
  384. SPDLOG_INFO("队列中数据暂不满足静音持续时间检测({})的要求,当前队列大小为{}", silentDuration + m_offset, ringQueue.QueueSize());
  385. return false;
  386. }
  387. if (silentDuration >= avgDBSeconds)
  388. {
  389. SPDLOG_WARN("静音持续时间({})不能大于等于{}秒", silentDuration, avgDBSeconds);
  390. return false;
  391. }
  392. int nNum = 0;
  393. /* 计算起始位置,获取最新的需要用到的silentDuration个数据,环形队列数据永远从0开始获取,
  394. * 如果需要获取最新的数据,那么需要从队列的尾部开始获取
  395. * 如果有偏移,那么起始点就是如下计算方式 */
  396. int queueSize = ringQueue.QueueSize();
  397. int startIndex = queueSize - silentDuration - m_offset;
  398. for(int j = startIndex; j < queueSize; ++j)
  399. {
  400. OneSecondData *data = ringQueue[j];
  401. if(data == nullptr)
  402. {
  403. continue;
  404. }
  405. if (data->CalcDBOneSecond(param))
  406. {
  407. endPos = j;
  408. if (startPos < 0)
  409. {
  410. startPos = j;
  411. }
  412. ++nNum;
  413. }
  414. }
  415. nNum = nNum * 100;
  416. if (nNum >= param.GetSilentNum())
  417. {
  418. return true;
  419. }
  420. }
  421. return false;
  422. }
  423. /**
  424. * @brief 计算过载
  425. *
  426. * @param param 计算参数
  427. * @param avgDBSeconds 计算音量值需要的秒数
  428. * @param startPos 过载开始位置
  429. * @param endPos 过载结束位置
  430. * @param lastReversed 上次是否是过载
  431. * @return true
  432. * @return false
  433. */
  434. bool CaculateDBData::calculateOverload(const StVolumeParam& param, const int avgDBSeconds, int& startPos, int& endPos, bool bLastOverload)
  435. {
  436. startPos = -1;
  437. endPos = -1;
  438. if(!param.GetOverloadSwitch())
  439. {
  440. return false; // 没有开启过载检测
  441. }
  442. /* 获取需要计算的音量秒数 */
  443. const int calculateDuration = param.GetOverloadDuration();
  444. if (calculateDuration >= CACHE_DATA_SECOND_MAX)
  445. {
  446. SPDLOG_WARN("过载持续时间({})不能大于等于最大缓存{}秒", calculateDuration, CACHE_DATA_SECOND_MAX);
  447. return false;
  448. }
  449. /* 判断队列中数据数量是否满足计算需要的数目 */
  450. if(ringQueue.QueueSize() < calculateDuration || calculateDuration <= 0)
  451. {
  452. SPDLOG_INFO("队列中数据暂不满足过载持续时间检测({})的要求,当前队列大小为{}", calculateDuration, ringQueue.QueueSize());
  453. return false;
  454. }
  455. if (calculateDuration >= avgDBSeconds)
  456. {
  457. SPDLOG_WARN("过载持续时间({})不能大于等于{}秒", calculateDuration, avgDBSeconds);
  458. return false;
  459. }
  460. /* 计算起始位置,获取最新的需要用到的 overloadDuration 个数据,环形队列数据永远从0开始获取,
  461. * 如果需要获取最新的数据,那么需要从队列的尾部开始获取 */
  462. int queueSize = ringQueue.QueueSize();
  463. int startIndex = queueSize - calculateDuration;
  464. // 第一秒和最后1秒都是过载的,如果中间有一秒不是过载的,那么中间这秒也仍然认为是过载的
  465. int nMidOverload = 0;
  466. int nOverloadNum = 0;
  467. for(int j = startIndex; j < queueSize; ++j)
  468. {
  469. OneSecondData *data = ringQueue[j];
  470. if(data == nullptr)
  471. {
  472. continue; // 没有获取到最新数据,继续等待
  473. }
  474. if (data->CalcOverloadOneSecond(param))
  475. {
  476. // 记录过载的起始位置
  477. if (startPos < 0)
  478. {
  479. startPos = j;
  480. }
  481. endPos = j;
  482. ++nOverloadNum;
  483. }
  484. else
  485. {
  486. if (j > 0 && j < calculateDuration - 1)
  487. {
  488. ++nMidOverload;
  489. }
  490. }
  491. //nOverloadNum += data->CalcOverload(param);
  492. }
  493. // 第一秒和最后1秒都是过载的,如果中间有一秒不是过载的,那么中间这秒也仍然认为是过载的
  494. if (1 == nMidOverload && calculateDuration == nOverloadNum + 1)
  495. {
  496. nOverloadNum = calculateDuration;
  497. }
  498. // 如果上一次是过载,那么允许后面的过载少一个
  499. if (bLastOverload && calculateDuration == nOverloadNum + 1)
  500. {
  501. nOverloadNum = calculateDuration;
  502. }
  503. nOverloadNum = nOverloadNum * 100;
  504. if (nOverloadNum >= param.GetOverloadNum())
  505. {
  506. return true;
  507. }
  508. return false;
  509. }
  510. /* 计算反相 */
  511. bool CaculateDBData::calculatePhase(const StVolumeParam& param, const int avgDBSeconds, int& startPos, int& endPos, bool isLastReversed)
  512. {
  513. startPos = -1;
  514. endPos = -1;
  515. if(!param.GetPhaseSwitch())
  516. {
  517. return false; // 没有开启反相检测
  518. }
  519. /* 获取需要计算的音量秒数 */
  520. const int calculateDuration = param.GetPhaseDuration();
  521. if (calculateDuration >= CACHE_DATA_SECOND_MAX)
  522. {
  523. SPDLOG_WARN("反相持续时间({})不能大于等于最大缓存{}秒", calculateDuration, CACHE_DATA_SECOND_MAX);
  524. return false;
  525. }
  526. /* 判断队列中数据数量是否满足计算需要的数目 */
  527. if(ringQueue.QueueSize() < calculateDuration || calculateDuration <= 0)
  528. {
  529. SPDLOG_INFO("队列中数据暂不满足反相持续时间检测({})的要求,当前队列大小为{}", calculateDuration, ringQueue.QueueSize());
  530. return false;
  531. }
  532. if (calculateDuration >= avgDBSeconds)
  533. {
  534. SPDLOG_WARN("反相持续时间({})不能大于等于{}秒", calculateDuration, avgDBSeconds);
  535. return false;
  536. }
  537. StPhase phaseData;
  538. //1、上一秒是否反相,如果是,当反相值比较小时也表示反相
  539. bool bLastTest = isLastReversed;
  540. /* 计算起始位置,获取最新的需要用到的 overloadDuration 个数据,环形队列数据永远从0开始获取,
  541. * 如果需要获取最新的数据,那么需要从队列的尾部开始获取 */
  542. int queueSize = ringQueue.QueueSize();
  543. int startIndex = queueSize - calculateDuration;
  544. for(int j = startIndex; j < queueSize; ++j)
  545. {
  546. OneSecondData *data = ringQueue[j];
  547. if(data == nullptr)
  548. {
  549. continue; // 没有获取到最新数据,继续等待
  550. }
  551. if (data->CalcPhaseOneSecond(param, bLastTest))
  552. {
  553. // 记录反相的起始位置
  554. if (startPos < 0)
  555. {
  556. startPos = j;
  557. }
  558. endPos = j;
  559. ++phaseData.iReversedNum;
  560. bLastTest = true;
  561. }
  562. else
  563. {
  564. bLastTest = false;
  565. ++phaseData.iUnReversedNum;
  566. }
  567. //stPhase phase;
  568. //data->CalcPhase(param, phase, bLastReversed);
  569. //stTotal.iReversedNum += phase.iReversedNum;
  570. //stTotal.iUnReversedNum += phase.iUnReversedNum;
  571. }
  572. // 反相百分比
  573. int iRate = phaseData.iReversedNum * 100;
  574. return iRate >= param.GetPhaseNum();
  575. }
  576. /**
  577. * @brief 判断平均音量是否低于设置的值
  578. *
  579. * @param minDBLongTime 最小声音时长
  580. * @param minDB 最小声音
  581. * @return true
  582. * @return false
  583. */
  584. bool CaculateDBData::isAvgDBLessThan(const long minDBLongTime, const long minDB)
  585. {
  586. if (ringQueue.QueueSize() < minDBLongTime || minDBLongTime <= 0)
  587. {
  588. return false;
  589. }
  590. int nNum = 0;
  591. double dTotalLeftDB = 0;
  592. double dTotalRightDB = 0;
  593. /* 计算起始位置,获取最新的minDBLongTime个数据,这里不需要管偏移值 */
  594. int startIndex = ringQueue.QueueSize() - minDBLongTime;
  595. for(int j = startIndex; j < minDBLongTime; ++j)
  596. {
  597. OneSecondData *data = ringQueue[j];
  598. if(data == nullptr)
  599. {
  600. continue;
  601. }
  602. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  603. {
  604. dTotalLeftDB += data->aryLeftDB[i];
  605. dTotalRightDB += data->aryRightDB[i];
  606. ++nNum;
  607. }
  608. }
  609. if (nNum > 0)
  610. {
  611. // 求平均值
  612. int leftDB = dTotalLeftDB / nNum;
  613. int rightDB = dTotalRightDB / nNum;
  614. if (leftDB <= minDB && rightDB <= minDB)
  615. {
  616. return true;
  617. }
  618. }
  619. return false;
  620. }
  621. /**
  622. * @brief 计算正弦波是否是噪音,正弦波几秒直接判断为噪音
  623. *
  624. * @param sinSeconds 判断是否是正弦波的条件秒数
  625. * @param calSeconds 自定义的计算描述
  626. * @param leftDB
  627. * @param rightDB
  628. * @return true
  629. * @return false
  630. */
  631. bool CaculateDBData::isSinDB(const int sinSeconds, const int calSeconds, int& leftDB, int& rightDB)
  632. {
  633. int overloadDuration = sinSeconds;
  634. if (ringQueue.QueueSize() < overloadDuration || overloadDuration <= 0)
  635. {
  636. return false;
  637. }
  638. if (overloadDuration >= calSeconds)
  639. {
  640. overloadDuration = calSeconds - 5;
  641. }
  642. /* 计算起始位置,获取最新的minDBLongTime个数据,这里不需要管偏移值 */
  643. int startIndex = ringQueue.QueueSize() - overloadDuration;
  644. for(int j = startIndex; j < overloadDuration; ++j)
  645. {
  646. OneSecondData *data = ringQueue[j];
  647. if(data == nullptr)
  648. {
  649. continue;
  650. }
  651. int nLeftDBTemp, nRightDBTmp;
  652. if (!data->isConstDB(nLeftDBTemp, nRightDBTmp))
  653. {
  654. // 不是正弦波,固定音量值
  655. return false;
  656. }
  657. if (0 == j)
  658. {
  659. leftDB = nLeftDBTemp;
  660. rightDB = nRightDBTmp;
  661. }
  662. // 虽然是固定音量值,但是音量值不相等
  663. else if (leftDB != nLeftDBTemp || rightDB != nRightDBTmp)
  664. {
  665. return false;
  666. }
  667. }
  668. return true;
  669. }