AudioData.cpp 11 KB

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