#ifndef _AUDIODATA_H_ #define _AUDIODATA_H_ #include #include #include #include #include "GlobalVariable.h" #include "ChannelParam.h" /* ========================================================================================= * WAV文件头信息结构体及其功能函数 * =========================================================================================*/ #pragma pack(1) /** * @brief Wav头信息 * */ struct WavHeader { char RIFF[4] = {'R', 'I', 'F', 'F'}; /* RIFF标识符 */ int32_t fileSize = 0; // 文件大小 char WAVE[4] = {'W', 'A', 'V', 'E'}; // WAVE标识符 char fmt[4] = {'f', 'm', 't', ' '}; // fmt子块标识符 int32_t fmtChunkSize = 16; // fmt子块大小 int16_t audioFormat = 1; // 音频格式,1表示PCM int16_t numChannels = 2; // 声道数,1表示单声道,2表示立体声 int32_t sampleRate = 48000; // 采样率 int32_t byteRate = 0; // 字节率,等于采样率 * 声道数 * 每个采样点的字节数 int16_t blockAlign = 4; // 块对齐,等于声道数 * 每个采样点的字节数 int16_t bitsPerSample = 16; // 每个采样点的位数,16位深度 char data[4] = {'d', 'a', 't', 'a'}; // data子块标识符 int32_t dataChunkSize = 0; // 数据块大小,等于音频数据的字节数 /* 一些需要手动设置的参数 */ void setSampleRate(int32_t rate) { sampleRate = rate; } void setNumChannels(uint16_t channels) { numChannels = channels; } void setBitsPerSample(uint16_t bits) { bitsPerSample = bits; } void setDataSize(int32_t size) { dataChunkSize = size; } /* 计算一些其他需要计算的数据 */ void calculateDerivedFields() { byteRate = sampleRate * numChannels * (bitsPerSample / 8); blockAlign = numChannels * (bitsPerSample / 8); fileSize = sizeof(WavHeader) - 8 + dataChunkSize; // 文件大小 = 头部大小 - 8 + 数据块大小 } }; #pragma pack() /* 修改wav文件已写入的大小 */ bool modifyWavFileHeader(const QString& fileName, WavHeader& header); /* 修改录音文件名 */ bool modifyFileName(const QString& fileName, const QString& newFileName); /* ========================================================================================= * 其他数据结构 * =========================================================================================*/ // 反相数结构 struct StPhase { StPhase() : iReversedNum(0), iUnReversedNum(0) {} StPhase(const StPhase& obj) { *this = obj; } // 1秒钟内的反相数 int iReversedNum; // 1秒钟内的非反相数 int iUnReversedNum; int GetPhaseNum() { return iReversedNum + iUnReversedNum; } StPhase& operator=(const StPhase& obj) { iReversedNum = obj.iReversedNum; iUnReversedNum = obj.iUnReversedNum; return *this; } }; // 一秒钟的数据 struct OneSecondData { OneSecondData(); ~OneSecondData(); OneSecondData(const OneSecondData& obj); OneSecondData& operator=(const OneSecondData &obj); void Init(); // 音频是否有错误 // bool AudioLeftRightDiff(); // 判定静音 int calSilentDB(const StVolumeParam ¶m); bool CalcDBOneSecond(const StVolumeParam ¶m); // 判定过载 int CalcOverload(const StVolumeParam ¶m); bool CalcOverloadOneSecond(const StVolumeParam ¶m); // 判定反相: 持续时间内就一个是否反相的值 // bLastReversed:上一次的反相,如果反相不明显时,维持上一次的反相 void CalcPhase(const StVolumeParam ¶m, StPhase &phase, bool bLastReversed); // 判定反相: 每秒都有一个是否反相的值,持续时间内每秒都反相,就表示反相 bool CalcPhaseOneSecond(const StVolumeParam ¶m, bool bLastReversed); /* 判断是否是固定的音量 */ bool isConstDB(int &nLeftDB, int &nRightDB); // // 打印输出 // void OutPutVolumeInfo(QString strHeader); // void OutPutVolumeInfoEx(QString strHeader, CShowCmdLog &logFile); public: int nAudioError; // 一个音量包有30个DB int aryLeftDB[VOLUME_INFO_NUM]; int aryRightDB[VOLUME_INFO_NUM]; // 相位值列表 float aryPhase[VOLUME_INFO_NUM]; QDateTime startTime; /* 开始时间戳 */ QDateTime endTime; /* 结束时间戳 */ }; /** * @brief 音频原始数据 * */ struct AudioSrcData { public: AudioSrcData(int32_t recordSize = 0); AudioSrcData(const AudioSrcData& obj); AudioSrcData& operator=(const AudioSrcData &obj); AudioSrcData(AudioSrcData&& obj) = delete; void operator=(AudioSrcData&& obj) = delete; ~AudioSrcData(); /* 分配内存空间 */ bool allocateMemory(int32_t size); /* 置零 */ void clear(); /* 添加数据,返回添加的数据长度 */ int32_t appendData(const char* srcData, int32_t size); /* 返回是数据否满了 */ bool isFull() const { return (dataSize >= totalSize); } /* 判断是否为空 */ bool isEmpty() const { return (dataSize == 0); } char *pData = nullptr; /* 数据缓存 */ int32_t totalSize = 0; /* 总长度 */ int32_t dataSize = 0; /* 有效数据长度 */ QDateTime startTime; /* 数据时间戳,开始时间 */ QDateTime endTime; /* 数据时间戳,结束时间 */ private: }; /** * @brief 存储左右声道的数据 * */ struct AudioLeftRightData { AudioLeftRightData(int totalSize); ~AudioLeftRightData(); AudioLeftRightData(const AudioLeftRightData& obj); AudioLeftRightData& operator=(const AudioLeftRightData &obj); /* 判断是否是同一个数据,通过数据大小和时间戳来判断 */ bool isSameData(const AudioLeftRightData& obj) const; /* 音频数据 */ std::vector vecLeftData; /* 左声道数据 */ std::vector vecRightData; /* 右声道数据 */ int totalSize = 0; /* 总长度,两个声道的总长度是一样的 */ int numMSecond = 0; /* 数据对应的毫秒数 */ QDateTime startTime; /* 开始时间戳 */ QDateTime endTime; /* 结束时间戳 */ }; /** * @brief 存储wav小文件路径的结构体 * */ struct WavFilePath { std::string fileName; /* 文件路径 */ QDateTime startDateTime; /* 开始时间戳 */ QDateTime endDateTime; /* 结束时间戳 */ WavFilePath() = default; WavFilePath& operator=(const WavFilePath& obj); bool operator==(const WavFilePath& obj) const; }; #endif // _AUDIODATA_H_