123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- #include "CreateDBThread.h"
- #include "GlobalVariable.h"
- #include "AudioData.h"
- #include "GlobalInfo.h"
- #include "CalculateAudio.h"
- CreateDBThread::CreateDBThread(RecordThreadInfo_t& threadInfo)
- : BaseRecordThread(threadInfo)
- {
- }
- CreateDBThread::~CreateDBThread()
- {
- }
- /* 设置数据 */
- bool CreateDBThread::setData(const AudioSrcData& srcData)
- {
- if(srcData.pData == nullptr || srcData.dataSize == 0)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 设置数据失败,srcData为空或dataSize为0", m_logBase);
- return false;
- }
- /* 创建一个新的AudioSrcData对象 */
- AudioSrcData* audioData = new AudioSrcData(srcData);
- if(audioData == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 创建AudioSrcData对象失败", m_logBase);
- return false;
- }
- /* 判断环形队列是否满 */
- if(m_queueAudioData.isFull())
- {
- /* 出队一个最早的元素 */
- AudioSrcData* oldData = m_queueAudioData.front_pop();
- SPDLOG_LOGGER_WARN(m_logger, "{} 环形队列已满,出队一个元素,时间: {}, 大小: {}",
- m_logBase, oldData->startTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), oldData->dataSize);
- if(oldData != nullptr){
- delete oldData;
- oldData = nullptr;
- }
- }
- /* 入队新的数据 */
- if(!m_queueAudioData.push_noBlock(audioData))
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 数据加入环形队列失败", m_logBase);
- delete audioData; // 入队失败,释放内存
- audioData = nullptr;
- return false;
- }
- return true;
- }
- /* 获取最新的结果,根据时间进行对比,最新的时间比传入的晚,就是有新的数据了 */
- bool CreateDBThread::getLatestResult(OneSecondData& resultData)
- {
- if(resultData.startTime.isNull())
- {
- // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新结果失败,传入的时间戳为空", m_logBase);
- return false;
- }
- std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
- auto lastSecondData = m_queueResultData->back();
- if(lastSecondData == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 获取最新结果失败,结果队列为空", m_logBase);
- return false;
- }
- /* 比较时间戳 */
- if(lastSecondData->startTime <= resultData.startTime)
- {
- return false;
- }
- resultData = *lastSecondData;
- return true;
- }
- /* 获取最新的结果,让整个环形队列相等 */
- bool CreateDBThread::getLatestResult(RingQueueManualMutex<OneSecondData*>& resultQueue)
- {
- std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
- if(m_queueResultData->isEmpty())
- {
- // SPDLOG_LOGGER_TRACE(m_logger, "{} 获取最新数据,数据队列为空", m_logBase);
- return false;
- }
- /* 目标队列为空,全部拷贝 */
- if(resultQueue.isEmpty())
- {
- SPDLOG_LOGGER_DEBUG(m_logger, "{} 获取最新数据,目标队列为空,拷贝整个结果队列", m_logBase);
- for(int i = 0; i < m_queueResultData->QueueSize(); ++i)
- {
- OneSecondData* data = m_queueResultData->at(i);
- if(data != nullptr)
- {
- OneSecondData* newData = new OneSecondData(*data); // 深拷贝
- resultQueue.push(newData);
- }
- }
- return true;
- }
- /* 队列不为空,查找队列中相等的位置,拷贝后面的数据,不拷贝整个队列,减少开销
- * 这里直接从最新的数据往前找 */
- auto itBack = resultQueue.back();
- int index = m_queueResultData->QueueSize() - 1;
- while(index >= 0)
- {
- OneSecondData* data = m_queueResultData->at(index);
- if(data == nullptr)
- {
- --index;
- continue;
- }
- /* 找到相等的位置 */
- if(data->startTime == itBack->startTime)
- {
- break;
- }
- --index;
- }
- if(index < 0)
- {
- SPDLOG_LOGGER_WARN(m_logger, "{} 获取最新数据失败,未找到相等的时间戳,将清空队列,拷贝全部数据", m_logBase);
- SPDLOG_LOGGER_WARN(m_logger, "队列大小: {}, 目标队列大小: {}", m_queueResultData->QueueSize(), resultQueue.QueueSize());
- /* 清空目标队列,将所有的数据全部拷贝 */
- while(!resultQueue.isEmpty())
- {
- OneSecondData* data = resultQueue.front_pop();
- if(data != nullptr)
- {
- delete data;
- data = nullptr;
- }
- }
- /* 拷贝全部数据 */
- for(int i = 0; i < m_queueResultData->QueueSize(); ++i)
- {
- OneSecondData* data = m_queueResultData->at(i);
- if(data != nullptr)
- {
- OneSecondData* newData = new OneSecondData(*data); // 深拷贝
- resultQueue.push(newData);
- }
- }
- return true;
- }
- else if(index == m_queueResultData->QueueSize() - 1)
- {
- // 已经是最新的数据了,不需要拷贝
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 获取最新数据,已经是最新的数据了", m_logBase);
- return false;
- }
- /* 拷贝数据 */
- for(; index < m_queueResultData->QueueSize(); ++index)
- {
- OneSecondData* data = m_queueResultData->at(index);
- if(data == nullptr)
- {
- continue;
- }
- OneSecondData* newData = new OneSecondData(*data); // 深拷贝
- auto fornt = resultQueue.push(newData);
- if(fornt != nullptr)
- {
- delete fornt; // 出队的元素是之前的结果,释放内存
- fornt = nullptr;
- }
- }
- return true;
- }
- /* 计算音量和反相的线程函数 */
- void CreateDBThread::task()
- {
- SPDLOG_LOGGER_INFO(m_logger, "➢ {} 开始计算音量线程", m_logBase);
- /* 初始化一些数据 */
- if(!initData())
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
- return;
- }
- while(m_isRunning)
- {
- /* 取出一个数据,没有数据则阻塞住 */
- AudioSrcData* audioData = m_queueAudioData.front_pop();
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 从环形队列中取出数据,队列大小: {}", m_logBase, m_queueAudioData.QueueSize());
- if(audioData == nullptr)
- {
- SPDLOG_LOGGER_WARN(m_logger, "{} 从环形队列中取出数据失败,可能是队列为空", m_logBase);
- std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待一段时间再尝试
- continue;
- }
- /* 计算音量和反相,结果存储在m_result */
- if(!CreateDBPhase(audioData))
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 计算音量和反相失败", m_logBase);
- }
- /* 将结果放入结果队列 */
- if(m_result != nullptr)
- {
- std::lock_guard<std::mutex> lock(m_queueResultData->mutex);
- auto result = m_queueResultData->push(m_result);
- if(result != nullptr)
- {
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 队列已满,出队一个元素", m_logBase);
- delete result; // 出队的元素是之前的结果,释放内存
- result = nullptr;
- }
- m_result = nullptr; // 清空结果指针,等待下一次使用
- }
- delete audioData; // 释放内存
- audioData = nullptr;
-
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 创建音量的线程处理数据完成,队列大小: {}",
- // m_logBase, m_queueResultData->QueueSize());
- }
- /* 清理数据 */
- clearData();
- SPDLOG_LOGGER_WARN(m_logger, "➢ {} 计算音量线程结束 ", m_logBase);
-
- }
- /* 初始化一些数据 */
- bool CreateDBThread::initData()
- {
- int queueSize = GInfo.queueElementCount();
- /* 初始化一些数据 */
- m_queueAudioData.clearQueue();
- m_queueAudioData.setQueueCapacity(queueSize);
- m_sampleRate = GInfo.sampleRate(); /* 采样率 */
- m_numChannels = GInfo.numChannels(); /* 声道数 */
- m_bitsPerSample = GInfo.bitsPerSample(); /* 每个采样点的位数 */
- /* 一秒钟数据大小,单位:字节 */
- m_oneSecondSize = m_sampleRate * m_numChannels * (m_bitsPerSample / 8);
- /* 计算每个音量值需要的数据大小,单位数据单位: short,一个通道的大小 */
- m_oneDBLengthOfSrcData = m_sampleRate / VOLUME_INFO_NUM;
- m_singleDataLength = m_oneSecondSize / m_numChannels;
- /* 计算音量和反相的环形队列元素数目,默认是180个,即180秒 */
- // m_queueAudioDataCapacity = queueSize;
- m_queueResultData = new RingQueueManualMutex<OneSecondData*>(queueSize);
- m_queueResultData->mutex.lock();
- m_queueResultData->setDefaultValue(nullptr);
- m_queueResultData->mutex.unlock();
- return true;
- }
- /* 清理数据 */
- void CreateDBThread::clearData()
- {
- /* 清理环形队列 */
- while(!m_queueAudioData.isEmpty())
- {
- AudioSrcData* data = m_queueAudioData.front_pop();
- if(data != nullptr)
- {
- delete data;
- data = nullptr;
- }
- }
- // if(m_remainData != nullptr)
- // {
- // delete m_remainData;
- // m_remainData = nullptr;
- // }
- }
- /* 计算音量和反相 */
- bool CreateDBThread::CreateDBPhase(AudioSrcData* audioData)
- {
- short* pWaveVu = reinterpret_cast<short*>(audioData->pData);
- /* 一秒钟平分30个音量值,每个音量值占有的长度 */
- const int oneDBSize = m_oneDBLengthOfSrcData;
- StAudioNum audioInfo;
- audioInfo.roadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
- audioInfo.nTotal = m_singleDataLength;
- int iCurPos = 0;
- /* 存储结果 */
- m_result = new OneSecondData();
- /* 计算音量和反相的计算类 */
- CAudio2ChanCorrelator audioCor;
- /* 音量值计算,好多个字节计算出一个最大音量值 */
- for(int i = 0; i < VOLUME_INFO_NUM; ++i)
- {
- // 采样点最大值
- short sMaxA, sMaxB, sRMSA, sRMSB;
- audioCor.CorrelateChunks(pWaveVu + iCurPos, (pWaveVu + iCurPos + 1), oneDBSize, &sMaxA, &sMaxB, &sRMSA, &sRMSB, audioInfo);
- /* 这里乘2是要增加两个通道的数据大小 */
- iCurPos += (oneDBSize * 2);
- m_result->aryLeftDB[i] = calculateDB(sMaxA);
- m_result->aryRightDB[i] = calculateDB(sMaxB);
- // 获取反相值,-100 到 100;反相是左右声道比对得到的值,所以只有一个
- int iReversed = audioCor.GetCorrelationLevel();
- if(iReversed > REVERSED_MAX_VALUE || iReversed < REVERSED_MIN_VALUE)
- {
- iReversed = 0;
- }
- // 和反相阈值比较,来判定是否为反相
- float dReversed = iReversed / 100.00;
- m_result->aryPhase[i] = dReversed;
- }
- /* 设置时间戳 */
- m_result->startTime = audioData->startTime;
- m_result->endTime = audioData->endTime;
- return true;
- }
|