CalculateAudio.cpp 23 KB

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