RecordThread.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "RecordThread.h"
  2. #include "GlobalInfo.h"
  3. #include "ThreadManager.h"
  4. #include "AssignSrcDataThread.h"
  5. #include "spdlog.h"
  6. #include <cstring>
  7. RecordThread::RecordThread(RecordThreadInfo_t& threadInfo) : BaseRecordThread(threadInfo)
  8. {
  9. m_logger = spdlog::get("RecordAudio");
  10. if(m_logger == nullptr)
  11. {
  12. fmt::print("RecordThread: RecordAudio Logger not found.\n");
  13. return;
  14. }
  15. }
  16. RecordThread::~RecordThread()
  17. {
  18. }
  19. /* 设置声卡描述符 */
  20. void RecordThread::setAudioRecordDesc(const std::string& desc)
  21. {
  22. m_audioRecordDesc = desc;
  23. }
  24. /* 设置分派线程的指针 */
  25. void RecordThread::setAssignSrcDataThread(AssignSrcDataThread* pThread)
  26. {
  27. if(pThread == nullptr)
  28. {
  29. SPDLOG_LOGGER_ERROR(m_logger, "{} 分派数据线程指针为空", m_logBase);
  30. return;
  31. }
  32. m_assignThread = pThread;
  33. // SPDLOG_LOGGER_INFO(m_logger, "{} 设置分派数据线程成功", m_logBase);
  34. }
  35. /* 录制功能线程函数 */
  36. void RecordThread::task()
  37. {
  38. SPDLOG_LOGGER_INFO(m_logger, "➢ {} 开始录音线程 ", m_logBase);
  39. /* 先初始化数据 */
  40. if(!initData())
  41. {
  42. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
  43. return;
  44. }
  45. /* 打开录音通道 */
  46. if(m_audioRecordDesc.empty())
  47. {
  48. SPDLOG_LOGGER_ERROR(m_logger, "{} 声卡描述符为空,无法打开录音通道", m_logBase);
  49. return;
  50. }
  51. if(!m_audioRecord.openRecordChannel(m_audioRecordDesc))
  52. {
  53. SPDLOG_LOGGER_ERROR(m_logger, "{} 打开声卡通道失败: {}", m_logBase, m_audioRecordDesc);
  54. return;
  55. }
  56. while(m_assignThread == nullptr)
  57. {
  58. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  59. m_assignThread = getAssignSrcDataThread();
  60. }
  61. SPDLOG_LOGGER_INFO(m_logger, "{} 获取AssignSrcDataThread线程成功", m_logBase);
  62. m_isRunning = true;
  63. while(m_isRunning)
  64. {
  65. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 开始录音", m_logBase);
  66. /* 获取音频数据,读取的帧数就是采样率,也就是一秒钟数据 */
  67. if(!m_audioRecord.recordAudio(m_pRecordBuffer, m_recordBufferSize, m_oneRecordSize))
  68. {
  69. SPDLOG_LOGGER_ERROR(m_logger, "{} 录音失败,可能是声卡被占用或其他错误", m_logBase);
  70. break; /* 录音失败,退出循环 */
  71. }
  72. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 录音完成,数据大小: {}", m_logBase, m_recordBufferSize);
  73. QDateTime currentTime = QDateTime::currentDateTime();
  74. /* 将音频数据拷贝给分派数据的线程 */
  75. if(m_assignThread != nullptr)
  76. {
  77. m_assignThread->setSrcData(m_pRecordBuffer, m_recordBufferSize, currentTime);
  78. }
  79. // for(int i = 0; i < 30; ++i)
  80. // {
  81. // /* 这里可以添加对音频数据的处理,比如噪音检测等 */
  82. // fmt::print(" |{} {}, short: {}\n", static_cast<uint8_t>(*(m_pRecordBuffer + i*2)), static_cast<uint8_t>(*(m_pRecordBuffer + i*2+1)),
  83. // static_cast<int16_t>(*(m_pRecordBuffer + i * 2)));
  84. // }
  85. memset(m_pRecordBuffer, 0, m_recordBufferSize); /* 清空缓存,准备下一次录音 */
  86. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 录音数据已分派给AssignSrcDataThread线程", m_logBase);
  87. }
  88. SPDLOG_LOGGER_WARN(m_logger, "➢ {} 结束录音", m_logBase);
  89. m_isRunning = false;
  90. }
  91. /* 设置数据 */
  92. bool RecordThread::setData(const AudioSrcData& srcData)
  93. {
  94. return true;
  95. }
  96. /* 初始化数据 */
  97. bool RecordThread::initData()
  98. {
  99. /* 获取全局数据 */
  100. m_sampleRate = GInfo.sampleRate(); /* 采样率 */
  101. m_numChannels = GInfo.numChannels(); /* 声道数 */
  102. m_bitsPerSample = GInfo.bitsPerSample(); /* 每个采样点的位数 */
  103. m_oneSecondSize = m_sampleRate * m_numChannels * (m_bitsPerSample / 8); /* 每秒钟的音频数据大小 */
  104. /* 每次录音的音频数据大小,这里是100ms去一次数据,监听的时候延迟会小一些 */
  105. m_recordBufferSize = m_oneSecondSize / 10;
  106. m_oneRecordSize = m_sampleRate / 10;
  107. m_pRecordBuffer = new char[m_recordBufferSize] {0}; /* 录音数据缓存 */
  108. /* 初始化录制类的参数 */
  109. m_audioRecord.setRecordParams(m_sampleRate, m_bitsPerSample, m_numChannels);
  110. /* 设置声卡描述符 */
  111. m_audioRecordDesc = fmt::format("hw:{},{}", m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
  112. return true;
  113. }
  114. /* 清除数据 */
  115. void RecordThread::clearData()
  116. {
  117. if(m_pRecordBuffer != nullptr)
  118. {
  119. delete[] m_pRecordBuffer;
  120. m_pRecordBuffer = nullptr;
  121. }
  122. m_recordBufferSize = 0;
  123. }
  124. /* 获取AssignSrcDataThread线程 */
  125. AssignSrcDataThread* RecordThread::getAssignSrcDataThread()
  126. {
  127. auto pThread = ThreadMan.findRecordThread(EThreadType::Type_AssignSrcData, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
  128. if(pThread != nullptr)
  129. {
  130. return dynamic_cast<AssignSrcDataThread*>(pThread);
  131. }
  132. return nullptr;
  133. }