#include "RecordThread.h" #include "GlobalInfo.h" #include "ThreadManager.h" #include "AssignSrcDataThread.h" #include "spdlog.h" #include RecordThread::RecordThread(RecordThreadInfo_t& threadInfo) : BaseRecordThread(threadInfo) { m_logger = spdlog::get("RecordAudio"); if(m_logger == nullptr) { fmt::print("RecordThread: RecordAudio Logger not found.\n"); return; } } RecordThread::~RecordThread() { } /* 设置声卡描述符 */ void RecordThread::setAudioRecordDesc(const std::string& desc) { m_audioRecordDesc = desc; } /* 设置分派线程的指针 */ void RecordThread::setAssignSrcDataThread(AssignSrcDataThread* pThread) { if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 分派数据线程指针为空", m_logBase); return; } m_assignThread = pThread; // SPDLOG_LOGGER_INFO(m_logger, "{} 设置分派数据线程成功", m_logBase); } /* 录制功能线程函数 */ void RecordThread::task() { SPDLOG_LOGGER_INFO(m_logger, "➢ {} 开始录音线程 ", m_logBase); /* 先初始化数据 */ if(!initData()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase); return; } /* 打开录音通道 */ if(m_audioRecordDesc.empty()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 声卡描述符为空,无法打开录音通道", m_logBase); return; } if(!m_audioRecord.openRecordChannel(m_audioRecordDesc)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 打开声卡通道失败: {}", m_logBase, m_audioRecordDesc); return; } while(m_assignThread == nullptr) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); m_assignThread = getAssignSrcDataThread(); } SPDLOG_LOGGER_INFO(m_logger, "{} 获取AssignSrcDataThread线程成功", m_logBase); m_isRunning = true; while(m_isRunning) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 开始录音", m_logBase); /* 获取音频数据,读取的帧数就是采样率,也就是一秒钟数据 */ if(!m_audioRecord.recordAudio(m_pRecordBuffer, m_recordBufferSize, m_oneRecordSize)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 录音失败,可能是声卡被占用或其他错误", m_logBase); break; /* 录音失败,退出循环 */ } // SPDLOG_LOGGER_DEBUG(m_logger, "{} 录音完成,数据大小: {}", m_logBase, m_recordBufferSize); QDateTime currentTime = QDateTime::currentDateTime(); /* 将音频数据拷贝给分派数据的线程 */ if(m_assignThread != nullptr) { m_assignThread->setSrcData(m_pRecordBuffer, m_recordBufferSize, currentTime); } // for(int i = 0; i < 30; ++i) // { // /* 这里可以添加对音频数据的处理,比如噪音检测等 */ // fmt::print(" |{} {}, short: {}\n", static_cast(*(m_pRecordBuffer + i*2)), static_cast(*(m_pRecordBuffer + i*2+1)), // static_cast(*(m_pRecordBuffer + i * 2))); // } memset(m_pRecordBuffer, 0, m_recordBufferSize); /* 清空缓存,准备下一次录音 */ // SPDLOG_LOGGER_DEBUG(m_logger, "{} 录音数据已分派给AssignSrcDataThread线程", m_logBase); } SPDLOG_LOGGER_WARN(m_logger, "➢ {} 结束录音", m_logBase); m_isRunning = false; } /* 设置数据 */ bool RecordThread::setData(const AudioSrcData& srcData) { return true; } /* 初始化数据 */ bool RecordThread::initData() { /* 获取全局数据 */ m_sampleRate = GInfo.sampleRate(); /* 采样率 */ m_numChannels = GInfo.numChannels(); /* 声道数 */ m_bitsPerSample = GInfo.bitsPerSample(); /* 每个采样点的位数 */ m_oneSecondSize = m_sampleRate * m_numChannels * (m_bitsPerSample / 8); /* 每秒钟的音频数据大小 */ /* 每次录音的音频数据大小,这里是100ms去一次数据,监听的时候延迟会小一些 */ m_recordBufferSize = m_oneSecondSize / 10; m_oneRecordSize = m_sampleRate / 10; m_pRecordBuffer = new char[m_recordBufferSize] {0}; /* 录音数据缓存 */ /* 初始化录制类的参数 */ m_audioRecord.setRecordParams(m_sampleRate, m_bitsPerSample, m_numChannels); /* 设置声卡描述符 */ m_audioRecordDesc = fmt::format("hw:{},{}", m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum); return true; } /* 清除数据 */ void RecordThread::clearData() { if(m_pRecordBuffer != nullptr) { delete[] m_pRecordBuffer; m_pRecordBuffer = nullptr; } m_recordBufferSize = 0; } /* 获取AssignSrcDataThread线程 */ AssignSrcDataThread* RecordThread::getAssignSrcDataThread() { auto pThread = ThreadMan.findRecordThread(EThreadType::Type_AssignSrcData, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum); if(pThread != nullptr) { return dynamic_cast(pThread); } return nullptr; }