AudioData.cpp 12 KB

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