#include "AudioData.h" #include "spdlog/spdlog.h" #include "GlobalInfo.h" #include #include /* ========================================================================================= * WAV文件头信息结构体及其功能函数 * =========================================================================================*/ /* 修改wav文件已写入的大小 */ bool modifyWavFileHeader(const QString& fileName, WavHeader& header) { QFile wavFile(fileName); if(!wavFile.open(QIODevice::ReadWrite)) { SPDLOG_WARN("打开WAV文件失败: {}", fileName.toStdString()); return false; } wavFile.seek(0); // 定位到文件开头 wavFile.write(reinterpret_cast(&header), sizeof(WavHeader)); wavFile.close(); return true; } /* 修改录音文件名 */ bool modifyFileName(const QString& fileName, const QString& newFileName) { if(fileName.isEmpty() || newFileName.isEmpty()) { SPDLOG_WARN("文件名或新文件名为空,无法修改"); return false; } if(!QFile::rename(fileName, newFileName)) { SPDLOG_ERROR("修改文件名失败: {} -> {}", fileName.toStdString(), newFileName.toStdString()); return false; } return true; } /* ================================================================= * OneSecondData * ================================================================= */ OneSecondData::OneSecondData() { Init(); } OneSecondData::~OneSecondData() { } OneSecondData::OneSecondData(const OneSecondData& obj) { *this = obj; } OneSecondData& OneSecondData::operator=(const OneSecondData &obj) { nAudioError = obj.nAudioError; for(int i = 0; i < VOLUME_INFO_NUM; ++i) { aryLeftDB[i] = obj.aryLeftDB[i]; aryRightDB[i] = obj.aryRightDB[i]; aryPhase[i] = obj.aryPhase[i]; } startTime = obj.startTime; endTime = obj.endTime; return *this; } void OneSecondData::Init() { nAudioError = 0; for(int i = 0; i < VOLUME_INFO_NUM; ++i) { aryLeftDB[i] = VOLUME_MIN_BD; aryRightDB[i] = VOLUME_MIN_BD; aryPhase[i] = 0.00; } } int OneSecondData::calSilentDB(const StVolumeParam ¶m) { if(!param.GetSilentSwitch()) return 0; int nNum = VOLUME_INFO_NUM; for(int i = 0; i < VOLUME_INFO_NUM; ++i) { if(aryLeftDB[i] > param.GetSilentThreshold() || aryRightDB[i] > param.GetSilentThreshold()) { --nNum; } } return nNum; } bool OneSecondData::CalcDBOneSecond(const StVolumeParam ¶m) { if(!param.GetSilentSwitch()) return false; bool bSilence = false; int nNum = calSilentDB(param); nNum = nNum * 100; if (nNum >= param.GetSilentSensitivity() * VOLUME_INFO_NUM) { bSilence = true; } return bSilence; } // 判定过载 int OneSecondData::CalcOverload(const StVolumeParam ¶m) { if(!param.GetOverloadSwitch()) return 0; int nOverloadNum = 0; for(int i = 0; i < VOLUME_INFO_NUM; ++i) { if(aryLeftDB[i] >= param.GetOverloadThreshold() || aryRightDB[i] >= param.GetOverloadThreshold()) { ++nOverloadNum; } } return nOverloadNum; } /* 判断1s的过载 */ bool OneSecondData::CalcOverloadOneSecond(const StVolumeParam ¶m) { // 25 10 // ---- > ---- // 50 100 bool bOverload = false; int nOverloadNum = CalcOverload(param); nOverloadNum = nOverloadNum * 100; int nNum = param.GetOverloadSensitivity() * VOLUME_INFO_NUM; if (nOverloadNum >= nNum) { bOverload = true; } return bOverload; } // 判定反相: 持续时间内就一个是否反相的值 // bLastReversed:上一次的反相,如果反相不明显时,维持上一次的反相 void OneSecondData::CalcPhase(const StVolumeParam ¶m, StPhase &phase, bool bLastReversed) { if(!param.GetPhaseSwitch()) return; for(int i = 0; i < VOLUME_INFO_NUM; ++i) { if(aryPhase[i] < param.GetPhaseThreshold()) { ++phase.iReversedNum; } else { /************************************************************* * 金海林加入 * 时间: 2017年1月6日 13:42:47 * 描述: bLastReversed:上一次的反相,如果反相不明显时,维持上一次的反相 *************************************************************/ //int nThreshold = 0 - param.GetPhaseThreshold(); float nThreshold = GInfo.ignorePhaseThreshold(); if (param.GetPhaseThreshold() < 0 && nThreshold >= 0) { if (aryPhase[i] < nThreshold && bLastReversed) { ++phase.iReversedNum; } else { ++phase.iUnReversedNum; } } else /**********金海林加入结束*************/ ++phase.iUnReversedNum; } } } // 判定反相: 每秒都有一个是否反相的值,持续时间内每秒都反相,就表示反相 bool OneSecondData::CalcPhaseOneSecond(const StVolumeParam ¶m, bool bLastReversed) { if(!param.GetPhaseSwitch()) return false; StPhase phase; CalcPhase(param, phase, bLastReversed); int iRate = phase.iReversedNum * 100; int nNum = param.GetPhaseSensitivity() * VOLUME_INFO_NUM; // 反相灵敏度 return iRate > nNum; } /* 判断是否是固定的音量 */ bool OneSecondData::isConstDB(int &nLeftDB, int &nRightDB) { nLeftDB = aryLeftDB[0]; nRightDB = aryRightDB[0]; int nLeftNum = 0; int nRightNum = 0; for(int i = 1; i < VOLUME_INFO_NUM; ++i) { if (aryLeftDB[i] == nLeftDB) { ++nLeftNum; } if (aryRightDB[i] == nRightDB) { ++nRightNum; } } // 30个值里面有25个以上是一样的,就表示固定音频 const int nMinNum = GInfo.sinEffectiveNum(); if (nLeftNum >= nMinNum && nRightNum >= nMinNum) { return true; } return false; } /*------------------------------------------------------------------------------- * AudioSrcData *-------------------------------------------------------------------------------*/ AudioSrcData::AudioSrcData(int32_t recordSize) { totalSize = recordSize > 0 ? recordSize : 192000; // 默认大小为192000字节(1秒的48kHz采样率,16位深度,双声道) dataSize = 0; pData = new char[totalSize] {0}; // 初始化为0 } AudioSrcData::AudioSrcData(const AudioSrcData& obj) { *this = obj; // 使用赋值运算符进行深拷贝 } AudioSrcData& AudioSrcData::operator=(const AudioSrcData &obj) { if(this == &obj) { return *this; // 防止自赋值 } if(pData != nullptr) { delete [] pData; pData = nullptr; } dataSize = obj.dataSize; totalSize = obj.totalSize; startTime = obj.startTime; endTime = obj.endTime; pData = new char[totalSize]; if (pData == nullptr) { SPDLOG_ERROR("CRecordData::operator= memory allocation failed, size: {}", totalSize); return *this; // 分配失败,返回当前对象 } memcpy(pData, obj.pData, obj.dataSize); return *this; } // AudioSrcData::AudioSrcData(AudioSrcData&& obj) // { // if(obj.pData == nullptr) // { // return; // } // if(pData != nullptr) // { // delete [] pData; // pData = nullptr; // } // dataSize = obj.dataSize; // totalSize = obj.totalSize; // pData = obj.pData; // dateTime = obj.dateTime; // obj.pData = nullptr; // 避免析构时删除 // obj.dataSize = 0; // 清空数据大小,避免误用 // obj.totalSize = 0; // 清空总大小,避免误用 // obj.dateTime = QDateTime(); // 清空开始时间戳 // return; // } // void AudioSrcData::operator=(AudioSrcData&& obj) // { // if(this == &obj) // { // return; // 防止自赋值 // } // if(obj.pData == nullptr) // { // return; // } // if(pData != nullptr) // { // delete [] pData; // pData = nullptr; // } // dataSize = obj.dataSize; // totalSize = obj.totalSize; // pData = obj.pData; // dateTime = obj.dateTime; // obj.pData = nullptr; // 避免析构时删除 // obj.dataSize = 0; // 清空数据大小,避免误用 // obj.totalSize = 0; // 清空总大小,避免误用 // obj.dateTime = QDateTime(); // 清空开始时间戳 // return; // } AudioSrcData::~AudioSrcData() { if(pData != nullptr) { delete [] pData; } } /* 分配内存空间 */ bool AudioSrcData::allocateMemory(int32_t size) { if(pData != nullptr) { delete [] pData; // 释放之前的内存 pData = nullptr; } if(size == 0) { SPDLOG_ERROR("AudioSrcData::allocateMemory size is 0"); return false; } totalSize = size; dataSize = 0; pData = new char[totalSize] {0}; if(pData == nullptr) { SPDLOG_ERROR("AudioSrcData::allocateMemory memory allocation failed, size: {}", totalSize); return false; } startTime = QDateTime(); endTime = QDateTime(); return true; } /* 置零 */ void AudioSrcData::clear() { if(pData != nullptr) { memset(pData, 0, totalSize); // 清空数据 } dataSize = 0; // 重置数据大小 startTime = QDateTime(); // 重置开始时间戳 endTime = QDateTime(); // 重置结束时间戳 } /* 添加数据,返回添加的数据长度 */ int32_t AudioSrcData::appendData(const char* srcData, int32_t size) { if(srcData == nullptr || size == 0) { SPDLOG_ERROR("AudioSrcData::appendData srcData is null or size is 0"); return 0; // 无效数据 } if(pData == nullptr) { pData = new char[totalSize]; if(pData == nullptr) { SPDLOG_ERROR("AudioSrcData::appendData memory allocation failed, size: {}", totalSize); return 0; // 内存分配失败 } } int32_t copySize = std::min(size, totalSize - dataSize); memcpy(pData + dataSize, srcData, copySize); dataSize += copySize; return copySize; } /*-------------------------------------------------------------- * AudioLeftRightData *--------------------------------------------------------------*/ AudioLeftRightData::AudioLeftRightData(int totalSize) { // if (totalSize == 0) // { // SPDLOG_ERROR("AudioLeftRightData::AudioLeftRightData totalSize is 0"); // return; // } this->totalSize = totalSize; vecLeftData.reserve(totalSize); vecRightData.reserve(totalSize); startTime = QDateTime(); endTime = QDateTime(); numMSecond = 0; } AudioLeftRightData::~AudioLeftRightData() { } AudioLeftRightData::AudioLeftRightData(const AudioLeftRightData& obj) { *this = obj; // 使用赋值运算符进行深拷贝 } AudioLeftRightData& AudioLeftRightData::operator=(const AudioLeftRightData &obj) { if (this == &obj) { return *this; // 防止自赋值 } // 释放原有资源 vecLeftData.clear(); vecRightData.clear(); // 复制数据 totalSize = obj.totalSize; vecLeftData = obj.vecLeftData; vecRightData = obj.vecRightData; // 复制时间戳 startTime = obj.startTime; endTime = obj.endTime; numMSecond = obj.numMSecond; return *this; } /* 判断是否是同一个数据,通过数据大小和时间戳来判断 */ bool AudioLeftRightData::isSameData(const AudioLeftRightData& obj) const { return (totalSize == obj.totalSize && startTime == obj.startTime && endTime == obj.endTime && vecLeftData == obj.vecLeftData && vecRightData == obj.vecRightData); } /*-------------------------------------------------------------- * WavFilePath数据 *--------------------------------------------------------------*/ WavFilePath& WavFilePath::operator=(const WavFilePath& obj) { if (this == &obj) { return *this; // 防止自赋值 } fileName = obj.fileName; startDateTime = obj.startDateTime; endDateTime = obj.endDateTime; return *this; } bool WavFilePath::operator==(const WavFilePath& obj) const { return (fileName == obj.fileName && startDateTime == obj.startDateTime && endDateTime == obj.endDateTime); }