AudioData.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #include "AudioData.h"
  2. #include "spdlog/spdlog.h"
  3. #include "GlobalInfo.h"
  4. #include <QFile>
  5. #include <cstring>
  6. /* =========================================================================================
  7. * WAV文件头信息结构体及其功能函数
  8. * =========================================================================================*/
  9. /* 修改wav文件已写入的大小 */
  10. bool modifyWavFileHeader(const QString& fileName, WavHeader& header)
  11. {
  12. QFile wavFile(fileName);
  13. if(!wavFile.open(QIODevice::ReadWrite))
  14. {
  15. SPDLOG_WARN("打开WAV文件失败: {}", fileName.toStdString());
  16. return false;
  17. }
  18. wavFile.seek(0); // 定位到文件开头
  19. wavFile.write(reinterpret_cast<const char*>(&header), sizeof(WavHeader));
  20. wavFile.close();
  21. return true;
  22. }
  23. /* 修改录音文件名 */
  24. bool modifyFileName(const QString& fileName, const QString& newFileName)
  25. {
  26. if(fileName.isEmpty() || newFileName.isEmpty())
  27. {
  28. SPDLOG_WARN("文件名或新文件名为空,无法修改");
  29. return false;
  30. }
  31. if(!QFile::rename(fileName, newFileName))
  32. {
  33. SPDLOG_ERROR("修改文件名失败: {} -> {}", fileName.toStdString(), newFileName.toStdString());
  34. return false;
  35. }
  36. return true;
  37. }
  38. /* =================================================================
  39. * OneSecondData
  40. * ================================================================= */
  41. OneSecondData::OneSecondData()
  42. {
  43. Init();
  44. }
  45. OneSecondData::~OneSecondData()
  46. {
  47. }
  48. OneSecondData::OneSecondData(const OneSecondData& obj)
  49. {
  50. *this = obj;
  51. }
  52. OneSecondData& OneSecondData::operator=(const OneSecondData &obj)
  53. {
  54. nAudioError = obj.nAudioError;
  55. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  56. {
  57. aryLeftDB[i] = obj.aryLeftDB[i];
  58. aryRightDB[i] = obj.aryRightDB[i];
  59. aryPhase[i] = obj.aryPhase[i];
  60. }
  61. startTime = obj.startTime;
  62. endTime = obj.endTime;
  63. return *this;
  64. }
  65. void OneSecondData::Init()
  66. {
  67. nAudioError = 0;
  68. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  69. {
  70. aryLeftDB[i] = VOLUME_MIN_BD;
  71. aryRightDB[i] = VOLUME_MIN_BD;
  72. aryPhase[i] = 0.00;
  73. }
  74. }
  75. /* 计算出有多少个静音音量值 */
  76. int OneSecondData::calSilentDB(const StVolumeParam &param)
  77. {
  78. // if(!param.GetSilentSwitch()) return 0;
  79. int nNum = VOLUME_INFO_NUM;
  80. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  81. {
  82. if(aryLeftDB[i] > param.GetSilentThreshold() || aryRightDB[i] > param.GetSilentThreshold())
  83. {
  84. --nNum;
  85. }
  86. // fmt::print("LDB:{}, RDB:{}, threshold:{}\n", aryLeftDB[i], aryRightDB[i], param.GetSilentThreshold());
  87. }
  88. // fmt::print("一秒有 {} 个静音音量值\n", nNum);
  89. return nNum;
  90. }
  91. /* 判断是否是静音 */
  92. bool OneSecondData::CalcDBOneSecond(const StVolumeParam &param)
  93. {
  94. // if(!param.GetSilentSwitch()) return false;
  95. bool bSilence = false;
  96. int nNum = calSilentDB(param);
  97. nNum = nNum * 100;
  98. if (nNum >= param.GetSilentSensitivity() * VOLUME_INFO_NUM)
  99. {
  100. bSilence = true;
  101. }
  102. // SPDLOG_TRACE("静音计算: num: {}, threshold: {}, bSilence: {}", nNum, param.GetSilentSensitivity() * VOLUME_INFO_NUM, bSilence);
  103. return bSilence;
  104. }
  105. // 判定过载
  106. int OneSecondData::CalcOverload(const StVolumeParam &param)
  107. {
  108. if(!param.GetOverloadSwitch()) return 0;
  109. int nOverloadNum = 0;
  110. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  111. {
  112. if(aryLeftDB[i] >= param.GetOverloadThreshold() || aryRightDB[i] >= param.GetOverloadThreshold())
  113. {
  114. ++nOverloadNum;
  115. }
  116. }
  117. return nOverloadNum;
  118. }
  119. /* 判断1s的过载 */
  120. bool OneSecondData::CalcOverloadOneSecond(const StVolumeParam &param)
  121. {
  122. // 25 10
  123. // ---- > ----
  124. // 50 100
  125. bool bOverload = false;
  126. int nOverloadNum = CalcOverload(param);
  127. nOverloadNum = nOverloadNum * 100;
  128. int nNum = param.GetOverloadSensitivity() * VOLUME_INFO_NUM;
  129. if (nOverloadNum >= nNum)
  130. {
  131. bOverload = true;
  132. }
  133. return bOverload;
  134. }
  135. // 判定反相: 持续时间内就一个是否反相的值
  136. // bLastReversed:上一次的反相,如果反相不明显时,维持上一次的反相
  137. void OneSecondData::CalcPhase(const StVolumeParam &param, StPhase &phase, bool bLastReversed)
  138. {
  139. if(!param.GetPhaseSwitch()) return;
  140. for(int i = 0; i < VOLUME_INFO_NUM; ++i)
  141. {
  142. if(aryPhase[i] < param.GetPhaseThreshold())
  143. {
  144. ++phase.iReversedNum;
  145. }
  146. else
  147. {
  148. /*************************************************************
  149. * 金海林加入
  150. * 时间: 2017年1月6日 13:42:47
  151. * 描述: bLastReversed:上一次的反相,如果反相不明显时,维持上一次的反相
  152. *************************************************************/
  153. //int nThreshold = 0 - param.GetPhaseThreshold();
  154. float nThreshold = GInfo.ignorePhaseThreshold();
  155. if (param.GetPhaseThreshold() < 0 && nThreshold >= 0)
  156. {
  157. if (aryPhase[i] < nThreshold && bLastReversed)
  158. {
  159. ++phase.iReversedNum;
  160. }
  161. else
  162. {
  163. ++phase.iUnReversedNum;
  164. }
  165. }
  166. else
  167. /**********金海林加入结束*************/
  168. ++phase.iUnReversedNum;
  169. }
  170. }
  171. }
  172. // 判定反相: 每秒都有一个是否反相的值,持续时间内每秒都反相,就表示反相
  173. bool OneSecondData::CalcPhaseOneSecond(const StVolumeParam &param, bool bLastReversed)
  174. {
  175. // if(!param.GetPhaseSwitch()) return false;
  176. StPhase phase;
  177. CalcPhase(param, phase, bLastReversed);
  178. int iRate = phase.iReversedNum * 100;
  179. int nNum = param.GetPhaseSensitivity() * VOLUME_INFO_NUM;
  180. // 反相灵敏度
  181. return iRate > nNum;
  182. }
  183. /* 判断是否是固定的音量 */
  184. bool OneSecondData::isConstDB(int &nLeftDB, int &nRightDB)
  185. {
  186. nLeftDB = aryLeftDB[0];
  187. nRightDB = aryRightDB[0];
  188. int nLeftNum = 0;
  189. int nRightNum = 0;
  190. for(int i = 1; i < VOLUME_INFO_NUM; ++i)
  191. {
  192. if (aryLeftDB[i] == nLeftDB)
  193. {
  194. ++nLeftNum;
  195. }
  196. if (aryRightDB[i] == nRightDB)
  197. {
  198. ++nRightNum;
  199. }
  200. }
  201. // 30个值里面有25个以上是一样的,就表示固定音频
  202. const int nMinNum = GInfo.sinEffectiveNum();
  203. if (nLeftNum >= nMinNum && nRightNum >= nMinNum)
  204. {
  205. return true;
  206. }
  207. return false;
  208. }
  209. OneDBData& OneDBData::operator=(const OneDBData &obj)
  210. {
  211. if (this == &obj)
  212. {
  213. return *this; // 防止自赋值
  214. }
  215. leftDB = obj.leftDB;
  216. rightDB = obj.rightDB;
  217. phase = obj.phase;
  218. startTime = obj.startTime;
  219. endTime = obj.endTime;
  220. return *this;
  221. }
  222. void OneDBData::clear()
  223. {
  224. leftDB = VOLUME_MIN_BD;
  225. rightDB = VOLUME_MIN_BD;
  226. phase = 0.0f;
  227. startTime = QDateTime();
  228. endTime = QDateTime();
  229. }
  230. /*-------------------------------------------------------------------------------
  231. * AudioSrcData
  232. *-------------------------------------------------------------------------------*/
  233. AudioSrcData::AudioSrcData(int32_t recordSize)
  234. {
  235. totalSize = recordSize > 0 ? recordSize : 192000; // 默认大小为192000字节(1秒的48kHz采样率,16位深度,双声道)
  236. dataSize = 0;
  237. pData = new char[totalSize] {0}; // 初始化为0
  238. }
  239. AudioSrcData::AudioSrcData(const AudioSrcData& obj)
  240. {
  241. *this = obj; // 使用赋值运算符进行深拷贝
  242. }
  243. AudioSrcData& AudioSrcData::operator=(const AudioSrcData &obj)
  244. {
  245. if(this == &obj)
  246. {
  247. return *this; // 防止自赋值
  248. }
  249. if(pData != nullptr)
  250. {
  251. delete [] pData;
  252. pData = nullptr;
  253. }
  254. dataSize = obj.dataSize;
  255. totalSize = obj.totalSize;
  256. startTime = obj.startTime;
  257. endTime = obj.endTime;
  258. pData = new char[totalSize];
  259. if (pData == nullptr)
  260. {
  261. SPDLOG_ERROR("CRecordData::operator= memory allocation failed, size: {}", totalSize);
  262. return *this; // 分配失败,返回当前对象
  263. }
  264. memcpy(pData, obj.pData, obj.dataSize);
  265. return *this;
  266. }
  267. // AudioSrcData::AudioSrcData(AudioSrcData&& obj)
  268. // {
  269. // if(obj.pData == nullptr)
  270. // {
  271. // return;
  272. // }
  273. // if(pData != nullptr)
  274. // {
  275. // delete [] pData;
  276. // pData = nullptr;
  277. // }
  278. // dataSize = obj.dataSize;
  279. // totalSize = obj.totalSize;
  280. // pData = obj.pData;
  281. // dateTime = obj.dateTime;
  282. // obj.pData = nullptr; // 避免析构时删除
  283. // obj.dataSize = 0; // 清空数据大小,避免误用
  284. // obj.totalSize = 0; // 清空总大小,避免误用
  285. // obj.dateTime = QDateTime(); // 清空开始时间戳
  286. // return;
  287. // }
  288. // void AudioSrcData::operator=(AudioSrcData&& obj)
  289. // {
  290. // if(this == &obj)
  291. // {
  292. // return; // 防止自赋值
  293. // }
  294. // if(obj.pData == nullptr)
  295. // {
  296. // return;
  297. // }
  298. // if(pData != nullptr)
  299. // {
  300. // delete [] pData;
  301. // pData = nullptr;
  302. // }
  303. // dataSize = obj.dataSize;
  304. // totalSize = obj.totalSize;
  305. // pData = obj.pData;
  306. // dateTime = obj.dateTime;
  307. // obj.pData = nullptr; // 避免析构时删除
  308. // obj.dataSize = 0; // 清空数据大小,避免误用
  309. // obj.totalSize = 0; // 清空总大小,避免误用
  310. // obj.dateTime = QDateTime(); // 清空开始时间戳
  311. // return;
  312. // }
  313. AudioSrcData::~AudioSrcData()
  314. {
  315. if(pData != nullptr)
  316. {
  317. delete [] pData;
  318. }
  319. }
  320. /* 分配内存空间 */
  321. bool AudioSrcData::allocateMemory(int32_t size)
  322. {
  323. if(pData != nullptr)
  324. {
  325. delete [] pData; // 释放之前的内存
  326. pData = nullptr;
  327. }
  328. if(size == 0)
  329. {
  330. SPDLOG_ERROR("AudioSrcData::allocateMemory size is 0");
  331. return false;
  332. }
  333. totalSize = size;
  334. dataSize = 0;
  335. pData = new char[totalSize] {0};
  336. if(pData == nullptr)
  337. {
  338. SPDLOG_ERROR("AudioSrcData::allocateMemory memory allocation failed, size: {}", totalSize);
  339. return false;
  340. }
  341. startTime = QDateTime();
  342. endTime = QDateTime();
  343. return true;
  344. }
  345. /* 置零 */
  346. void AudioSrcData::clear()
  347. {
  348. if(pData != nullptr)
  349. {
  350. memset(pData, 0, totalSize); // 清空数据
  351. }
  352. dataSize = 0; // 重置数据大小
  353. startTime = QDateTime(); // 重置开始时间戳
  354. endTime = QDateTime(); // 重置结束时间戳
  355. }
  356. /* 添加数据,返回添加的数据长度 */
  357. int32_t AudioSrcData::appendData(const char* srcData, int32_t size)
  358. {
  359. if(srcData == nullptr || size == 0)
  360. {
  361. SPDLOG_ERROR("AudioSrcData::appendData srcData is null or size is 0");
  362. return 0; // 无效数据
  363. }
  364. if(pData == nullptr)
  365. {
  366. pData = new char[totalSize];
  367. if(pData == nullptr)
  368. {
  369. SPDLOG_ERROR("AudioSrcData::appendData memory allocation failed, size: {}", totalSize);
  370. return 0; // 内存分配失败
  371. }
  372. }
  373. int32_t copySize = std::min(size, totalSize - dataSize);
  374. memcpy(pData + dataSize, srcData, copySize);
  375. dataSize += copySize;
  376. return copySize;
  377. }
  378. /*--------------------------------------------------------------
  379. * AudioLeftRightData
  380. *--------------------------------------------------------------*/
  381. AudioLeftRightData::AudioLeftRightData(int totalSize)
  382. {
  383. // if (totalSize == 0)
  384. // {
  385. // SPDLOG_ERROR("AudioLeftRightData::AudioLeftRightData totalSize is 0");
  386. // return;
  387. // }
  388. this->totalSize = totalSize;
  389. vecLeftData.reserve(totalSize);
  390. vecRightData.reserve(totalSize);
  391. startTime = QDateTime();
  392. endTime = QDateTime();
  393. numMSecond = 0;
  394. }
  395. AudioLeftRightData::~AudioLeftRightData()
  396. {
  397. }
  398. AudioLeftRightData::AudioLeftRightData(const AudioLeftRightData& obj)
  399. {
  400. *this = obj; // 使用赋值运算符进行深拷贝
  401. }
  402. AudioLeftRightData& AudioLeftRightData::operator=(const AudioLeftRightData &obj)
  403. {
  404. if (this == &obj)
  405. {
  406. return *this; // 防止自赋值
  407. }
  408. // 释放原有资源
  409. vecLeftData.clear();
  410. vecRightData.clear();
  411. // 复制数据
  412. totalSize = obj.totalSize;
  413. vecLeftData = obj.vecLeftData;
  414. vecRightData = obj.vecRightData;
  415. // 复制时间戳
  416. startTime = obj.startTime;
  417. endTime = obj.endTime;
  418. numMSecond = obj.numMSecond;
  419. return *this;
  420. }
  421. /* 判断是否是同一个数据,通过数据大小和时间戳来判断 */
  422. bool AudioLeftRightData::isSameData(const AudioLeftRightData& obj) const
  423. {
  424. return (totalSize == obj.totalSize && startTime == obj.startTime && endTime == obj.endTime &&
  425. vecLeftData == obj.vecLeftData && vecRightData == obj.vecRightData);
  426. }
  427. /*--------------------------------------------------------------
  428. * WavFilePath数据
  429. *--------------------------------------------------------------*/
  430. WavFilePath& WavFilePath::operator=(const WavFilePath& obj)
  431. {
  432. if (this == &obj)
  433. {
  434. return *this; // 防止自赋值
  435. }
  436. fileName = obj.fileName;
  437. startDateTime = obj.startDateTime;
  438. endDateTime = obj.endDateTime;
  439. return *this;
  440. }
  441. bool WavFilePath::operator==(const WavFilePath& obj) const
  442. {
  443. return (fileName == obj.fileName &&
  444. startDateTime == obj.startDateTime &&
  445. endDateTime == obj.endDateTime);
  446. }