Bladeren bron

V1.2
1、修改了底层声卡通道的打开方式,使用声卡的PCM名称打开通道

Apple 3 weken geleden
bovenliggende
commit
9fc0e6d9b7
71 gewijzigde bestanden met toevoegingen van 2093 en 1194 verwijderingen
  1. 60 1
      ACA服务程序设计说明.md
  2. 2 2
      CMakeLists.txt
  3. 13 0
      JSON/声卡信息.json
  4. 18 19
      RTPServer/RtpOneRoadThread.cpp
  5. 2 1
      RTPServer/RtpOneRoadThread.h
  6. 16 21
      RTPServer/RtpServer.cpp
  7. 1 1
      RTPServer/RtpServer.h
  8. 6 7
      RTPServer/Rtpcommon.cpp
  9. 3 4
      RTPServer/Rtpcommon.h
  10. 36 6
      SQL/ACAServer.sql
  11. 37 5
      SQL/ACASetting.sql
  12. 31 26
      SQL/CreateProcedures.sqlbook
  13. 238 0
      SQL/CreateTable-GBase.sqlbook
  14. 43 27
      SQL/CreateTable-达梦.sqlbook
  15. 28 8
      Server/ACAServer.cpp
  16. 2 0
      Server/ACAServer.h
  17. 0 1
      Server/DataManager/DataQueueManager.cpp
  18. 0 37
      Server/DataManager/DataQueueManager.h
  19. 0 101
      Server/DataManager/SoundCardData.cpp
  20. 0 52
      Server/DataManager/SoundCardData.h
  21. 145 0
      Server/DataManager/SoundCards.cpp
  22. 60 0
      Server/DataManager/SoundCards.h
  23. 3 3
      Server/DataStruct/CalculateAudio.cpp
  24. 2 1
      Server/DataStruct/CalculateAudio.h
  25. 2 5
      Server/GlobalInfo/GlobalInfo.h
  26. 2 2
      Server/ThreadCalculate/CalculateDBThread.cpp
  27. 17 20
      Server/ThreadCalculate/CompareItemThread.cpp
  28. 6 6
      Server/ThreadCalculate/ConsistencyCompareThread.cpp
  29. 3 3
      Server/ThreadCalculate/NoiseDetectThread.cpp
  30. 3 2
      Server/ThreadCalculate/NoiseDetectThread.h
  31. 3 3
      Server/ThreadManager/ThreadCompareItemManager.cpp
  32. 3 1
      Server/ThreadManager/ThreadCompareItemManager.h
  33. 171 190
      Server/ThreadManager/ThreadManager.cpp
  34. 15 14
      Server/ThreadManager/ThreadManager.h
  35. 5 5
      Server/ThreadRecord/AssignSrcDataThread.cpp
  36. 13 128
      Server/ThreadRecord/AudioRecord/AudioRecord.cpp
  37. 2 1
      Server/ThreadRecord/AudioRecord/AudioRecord.h
  38. 3 4
      Server/ThreadRecord/BaseRecordThread.cpp
  39. 54 40
      Server/ThreadRecord/CreateDBThread.cpp
  40. 5 0
      Server/ThreadRecord/CreateDBThread.h
  41. 10 12
      Server/ThreadRecord/CreateRecordFileThread.cpp
  42. 3 3
      Server/ThreadRecord/CreateRecordFileThread.h
  43. 6 7
      Server/ThreadRecord/CreateWAVThread.cpp
  44. 5 3
      Server/ThreadRecord/RecordThread.cpp
  45. 5 61
      Server/main.cpp
  46. 3 0
      SettingLibrary/CMakeLists.txt
  47. 28 14
      SettingLibrary/Modules/Basic/basicwidget.cpp
  48. 2 0
      SettingLibrary/Modules/Basic/basicwidget.h
  49. 3 2
      SettingLibrary/Modules/Basic/compareitemdetailwidget.cpp
  50. 2 6
      SettingLibrary/Modules/Basic/compareitemdialog.cpp
  51. 2 2
      SettingLibrary/Modules/Basic/compareitemdialog.h
  52. 24 12
      SettingLibrary/Modules/Basic/singlecompareroadwidget.cpp
  53. 3 3
      SettingLibrary/Modules/Basic/singlecompareroadwidget.h
  54. 36 14
      SettingLibrary/setinfomanager.cpp
  55. 2 0
      SettingLibrary/setinfomanager.h
  56. 6 66
      ThreeLib/signalstats/include/signalstats.h
  57. 12 16
      common/DataManager/SoundCardData.h
  58. 91 47
      common/DataManager/SystemConfig.cpp
  59. 8 2
      common/DataManager/SystemConfig.h
  60. 1 2
      common/DataManager/SystemConfigStruct.cpp
  61. 3 3
      common/DataManager/SystemConfigStruct.h
  62. 34 21
      common/GlobalInfo/GlobalVariable.cpp
  63. 83 29
      common/GlobalInfo/GlobalVariable.h
  64. 166 58
      common/Network/FromWebAPI.cpp
  65. 9 0
      common/Network/FromWebAPI.h
  66. 3 1
      show1/widget.cpp
  67. 344 0
      show3/AudioRecord/AudioRecord.cpp
  68. 125 0
      show3/AudioRecord/AudioRecord.h
  69. 4 0
      show3/CMakeLists.txt
  70. 17 1
      show3/main.cpp
  71. 0 62
      程序设置说明.md

+ 60 - 1
ACA服务程序设计说明.md

@@ -1,3 +1,62 @@
 # ACA服务设计说明
+ ## ACA服务功能
+ - 计算`静音`、`过载`、`反相`、`噪音`、`一致性`状态
+ - 实时发送音量包数据,给客户端绘制波形
+ - 提供RTP监听服务,客户端连接后可以实时听正在录音的内容
+ - 报警功能,报警时录制报警音频,写入报警信息到数据库中
+
+
+## 程序启动
+1. 先启动服务,获取系统声卡信息
+2. 打开设置动态库,设置创建对比项,选择声卡通道
+3. 服务读取到对比项信息,开始创建对比项线程,开始运行
+
+## ACA服务数据流转
+- 服务整体分为两个部分,`数据采集`和`数据计算`部分,数据采集是`录音线程类`,录音并做初步处理,数据计算是`计算线程类`,创建对比项线程后,由对比项线程创建和管理各个计算线程类。
+- 对比项线程汇集所有的计算结果后,取出实时音量,拼接成音量包发送到MQTT中
+- 对比项管理线程发送开启的对比项信息到MQTT中,设置消息保留
+- RTP服务监听客户端消息,发送实时音频数据
+
+
+### 录音线程
+ - 录音线程和声卡录音通道一一对应,一个录音通道会开启6个线程,对原始数据进行处理
+ - 录音间隔33ms是为了对应计算音量值所需的数据大小,1秒大概33个音量值
+
+    |线程类|功能|
+    |---|---|
+    |RecordThread|录制原始音频的线程,33ms获取一次|
+    |AssignSrcDataThread|分派数据线程,这个线程可以合并到录音线程中,分派数据只需要几百us|
+    |CreateWAVThread|创建一致性对比需要的wav文件,分离左右声道数据给噪音检测线程|
+    |CreateRecordFileThread|录制长音频文件,录制报警文件|
+    |CreateDBThread|计算1秒的音量包,给计算静音、过载、反相的线程使用,计算实时音量包给对比项线程使用,发送实时音量包|
+    |RTPOneRoadThread|客户端登陆后,实时发送原始音频数据给客户端|
+
+### 计算线程
+ - 计算线程和对比项相关联,一个对比项会创建若干计算线程,对比项线程销毁时,也会将计算线程销毁
+ - 一个对比项对应的三种计算类并不仅仅是三个线程,这些计算线程和对比项通道相关
+ - 计算线程在计算出报警后,将开启`CreateRecordFileThread`的报警录音,报警结束后通知`CreateRecordFileThread`线程结束录音,报警结束后通过`ThreadWriteDBManager`线程将报警信息写入数据库
+
+    |线程类|功能|
+    |---|---|
+    |CompareItemThread|对比项线程类,从这个类中集合`静音`、`过载`、`反相`、`噪音`、`一致性`检测的结果和音量数据,组合成音量包发送到MQTT|
+    |CalculateDBThread|计算`静音`、`过载`、`反相`的报警|
+    |ConsistencyCompareThread|计算`一致性`数据|
+    |NoiseDetectThread|计算`噪音`报警|
+
+
+### RTP服务
+ - RTP服务提供实时音频数据发送功能,客户端发送登录请求,RTP服务将客户端信息发送给`RTPOneRoadThread`,`RTPOneRoadThread`接收到客户端信息后开始接收分派数据线程发送的数据,然后通过UDP将音频数据发送给客户端
+
+
+ ### 其他线程功能
+ - 
+    |线程功能类|说明|
+    |---|---|
+    |ThreadManager|录音线程管理类|
+    |ThreadCompareItemManager|对比项管理线程类|
+    |ThreadWriteDBManager|写数据库线程类|
+
+ - 录音线程管理线程类`ThreadManager`,录音线程的创建和销毁由这个线程管理,对比项线程通过这个线程开始录音通道
+ - 比项管理线程类`ThreadCompareItemManager`,定时获取数据库中对比项信息,管理对比项的开启和销毁,同时向MQTT中发送对比项信息
+ - 写数据库线程类`ThreadWriteDBManager`,所有的报警信息,录音文件信息都由这个线程写入数据库,单独搞这一个线程为了防止网络状态差,会阻塞计算线程。这个线程还有一个功能是根据设置的时间定时清理数据库中的日志和录音文件,报警文件
 
-## 整体

+ 2 - 2
CMakeLists.txt

@@ -193,12 +193,12 @@ file(GLOB GLOBAL_SRC
 
 if(CMAKE_SYSTEM_NAME MATCHES "Linux")
 add_subdirectory(${CMAKE_SOURCE_DIR}/Server)
-add_subdirectory(${CMAKE_SOURCE_DIR}/show3)
+# add_subdirectory(${CMAKE_SOURCE_DIR}/show3)
 endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
 
 
 add_subdirectory(${CMAKE_SOURCE_DIR}/SettingLibrary)
 add_subdirectory(${CMAKE_SOURCE_DIR}/show1)
-add_subdirectory(${CMAKE_SOURCE_DIR}/show2)
+# add_subdirectory(${CMAKE_SOURCE_DIR}/show2)
 
 

+ 13 - 0
JSON/声卡信息.json

@@ -0,0 +1,13 @@
+{
+    "0": {
+        "Roads": [
+            {
+                "RoadNum": 0
+            }
+        ],
+        "SoundCardDriver": "ENS1371",
+        "SoundCardID": "AudioPCI",
+        "SoundCardName": "Ensoniq AudioPCI",
+        "SoundCardNum": 0
+    }
+}

+ 18 - 19
RTPServer/RtpOneRoadThread.cpp

@@ -15,9 +15,7 @@ RTPOneRoadThread::RTPOneRoadThread(RecordThreadInfo_t& threadInfo)
         fmt::print("RTPServer 日志记录器未初始化,请先初始化日志记录器");
         return;
     }
-    m_logBase = fmt::format("录音通道: {}:{}", m_threadInfo.cardRoadInfo.strSoundCardName.toStdString(), 
-                            m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
-    
+    m_logBase = fmt::format("录音通道: {}:{}", threadInfo.cardRoadInfo.strSoundCardName, threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     
 }
 
@@ -56,16 +54,18 @@ bool RTPOneRoadThread::setData(const AudioSrcData& srcData)
         return true;
     }
 
-    AudioSrcData* data = new AudioSrcData(srcData);
-    if(data == nullptr)
+    AudioSrcData* pData = new AudioSrcData(srcData);
+    if(pData == nullptr)
     {
         return false;
     }
-    if(!m_ringQueue.push_noBlock(data))
+
+    auto oldData = m_ringQueue.push_pop(pData);
+    if(oldData != nullptr)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "{} 环形队列已满,无法添加新的音频数据", m_logBase);
-        delete data; // 删除无用数据
-        return false;
+        delete oldData; // 删除被覆盖的数据
+        oldData = nullptr;
     }
 
     return false;
@@ -156,8 +156,8 @@ void RTPOneRoadThread::task()
     }
 
     m_sendTimer.setTimerType(Qt::PreciseTimer);
-    m_sendTimer.setSingleShot(false); // 设置为循环定时器
-    m_sendTimer.setInterval(10); // 每10毫秒发送一次数据
+    m_sendTimer.setSingleShot(false);
+    m_sendTimer.setInterval(25);
     QEventLoop::connect(&m_sendTimer, &QTimer::timeout, this, &RTPOneRoadThread::do_timerSendData);
     connect(this, &RTPOneRoadThread::signal_timerSendData, this, &RTPOneRoadThread::do_timerSendData);
     m_sendTimer.start();
@@ -254,8 +254,7 @@ bool RTPOneRoadThread::processUdpState()
         m_listClients.clear();
         m_localIP.clear();
         // m_localPort = -1;
-        emit signal_udpClosed(m_threadInfo.cardRoadInfo.nSoundCardNum, 
-                              m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+        emit signal_udpClosed(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
         /* 清空环形队列中的数据 */
         while(m_ringQueue.QueueSize() > 0)
         {
@@ -284,14 +283,14 @@ bool RTPOneRoadThread::sendData()
     while(m_ringQueue.QueueSize() > 0)
     {
         // SPDLOG_LOGGER_TRACE(m_logger, "{} 发送音频数据", m_logBase);
-        auto data = m_ringQueue.front_pop_noBlock();
-        if(data == nullptr)
+        auto pData = m_ringQueue.front_pop_noBlock();
+        if(pData == nullptr)
         {
             continue;
         }
-        if(data->isEmpty())
+        if(pData->isEmpty())
         {
-            delete data;
+            delete pData;
             continue;
         }
         std::lock_guard<std::mutex> lock(m_lockClients);
@@ -301,7 +300,7 @@ bool RTPOneRoadThread::sendData()
 
             // qint64 bytesSent = session.udpSocket->writeDatagram(data->pData, data->dataSize,
                                                                 // QHostAddress(session.clientIP), session.clientPort);
-            qint64 bytesSent = m_udpSocket->writeDatagram(QByteArray(reinterpret_cast<const char*>(data->pData), data->dataSize),
+            qint64 bytesSent = m_udpSocket->writeDatagram(QByteArray(reinterpret_cast<const char*>(pData->pData), pData->dataSize),
                                                                 QHostAddress(session.clientIP), session.clientPort);
             if(bytesSent == -1)
             {
@@ -314,8 +313,8 @@ bool RTPOneRoadThread::sendData()
             }
         }
         /* 发送完数据后,删除这个数据 */
-        delete data;
-        data = nullptr;
+        delete pData;
+        pData = nullptr;
     }
 
     return true;

+ 2 - 1
RTPServer/RtpOneRoadThread.h

@@ -11,6 +11,7 @@
 #include <QTimer>
 #include <QObject>
 #include <mutex>
+#include <string>
 
 
 #include "Rtpcommon.h"
@@ -48,7 +49,7 @@ public:
 
 signals:
     /* 一个UDP关闭了,通知RTP服务,释放掉了一个本地端口 */
-    void signal_udpClosed(int soundCardNum, int roadNum);
+    void signal_udpClosed(std::string pcmName);
     /* 用来触发槽函数 do_timerSendData 用于立刻处理UDP状态  */
     void signal_timerSendData();
 

+ 16 - 21
RTPServer/RtpServer.cpp

@@ -3,6 +3,7 @@
 #include <QTcpSocket>
 #include <QNetworkInterface>
 #include <QHostAddress>
+#include <string>
 
 #include "ThreadManager.h"
 #include "ThreadCompareItemManager.h"
@@ -180,15 +181,14 @@ void RTPServer::do_receiveMessage()
     // sendInfo.compareItemID = recvInfo->compareItemID;
     // sendInfo.compareItemRoadNum = recvInfo->compareItemRoadNum;
     /* 根据对比项ID和通道编号查找到使用到的声卡通道编号 */
-    SoundCardRoadInfo_t roadInfo = CompareItemManager.getSoundCardRoadInfo(recvInfo->compareItemID, recvInfo->compareItemRoadNum);
-    if(roadInfo.nSoundCardNum < 0 || roadInfo.roadInfo.nRoadNum < 0)
+    auto roadInfo = CompareItemManager.getSoundCardRoadInfo(recvInfo->compareItemID, recvInfo->compareItemRoadNum);
+    if(roadInfo.strSoundCardName.empty() || roadInfo.pcmInfo.strPCMName.empty())
     {
         SPDLOG_LOGGER_ERROR(m_logger, "无法获取对比项 {} 通道 {} 的声卡信息", 
                             recvInfo->compareItemID, recvInfo->compareItemRoadNum);
         return;
     }
-    sendInfo.SoundCardNum = roadInfo.nSoundCardNum;
-    sendInfo.SoundCardRoadNum = roadInfo.roadInfo.nRoadNum;
+    sendInfo.cardPCMInfo = roadInfo; // 设置声卡通道信息
 
     switch(recvInfo->type)
     {
@@ -208,10 +208,9 @@ void RTPServer::do_receiveMessage()
 }
 
 /* 一个通道UDP关闭的信号 */
-void RTPServer::do_udpClosed(int soundCardNum, int roadNum)
+void RTPServer::do_udpClosed(std::string pcmName)
 {
-    SPDLOG_LOGGER_DEBUG(m_logger, "接收到释放本地端口的信号: 声卡编号: {}, 通道编号: {}", 
-                        soundCardNum, roadNum);
+    SPDLOG_LOGGER_DEBUG(m_logger, "接收到释放本地端口的信号: 声卡PCM通道信息: {}", pcmName);
     
     // for(auto it = m_mapSoundCardRoadPorts.begin(); it != m_mapSoundCardRoadPorts.end(); ++it)
     // {
@@ -248,8 +247,7 @@ void RTPServer::do_heartbeatTimeout()
         RtpSendClientInfo_t clientInfo;
         clientInfo.clientIP = key.clientIP;
         clientInfo.clientPort = key.clientPort;
-        clientInfo.SoundCardNum = key.SoundCardNum;
-        clientInfo.SoundCardRoadNum = key.SoundCardRoadNum;
+        clientInfo.cardPCMInfo = key.cardPCMInfo;
         handleLogout(clientInfo);
     }
 }
@@ -262,11 +260,11 @@ void RTPServer::handleLogin(RtpSendClientInfo_t& clientInfo)
     // clientInfo.localPort = 10010;
     clientInfo.localIP = m_localIP;
     /* 查找RTP发送线程 */
-    auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
+    auto pThread = ThreadMan.getRtpSendThread(clientInfo.cardPCMInfo.pcmInfo.strPCMName);
     if(pThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}", 
-                            clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡通道名称: {}:{}", 
+                            clientInfo.cardPCMInfo.strSoundCardName, clientInfo.cardPCMInfo.pcmInfo.strPCMName);
         return;
     }
     /* 设置客户端信息 */
@@ -281,8 +279,7 @@ void RTPServer::handleLogin(RtpSendClientInfo_t& clientInfo)
     RtpClientKey_t clientKey;
     clientKey.clientIP = clientInfo.clientIP;
     clientKey.clientPort = clientInfo.clientPort;
-    clientKey.SoundCardNum = clientInfo.SoundCardNum;
-    clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
+    clientKey.cardPCMInfo = clientInfo.cardPCMInfo;
     m_mapClientHeartbeats[clientKey] = QDateTime::currentDateTime();
 }
 
@@ -293,8 +290,7 @@ void RTPServer::handleHeartbeat(RtpSendClientInfo_t& clientInfo)
     RtpClientKey_t clientKey;
     clientKey.clientIP = clientInfo.clientIP;
     clientKey.clientPort = clientInfo.clientPort;
-    clientKey.SoundCardNum = clientInfo.SoundCardNum;
-    clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
+    clientKey.cardPCMInfo = clientInfo.cardPCMInfo;
     /* 更新心跳时间 */
     if(m_mapClientHeartbeats.contains(clientKey))
     {
@@ -309,11 +305,11 @@ void RTPServer::handleLogout(RtpSendClientInfo_t& clientInfo)
     SPDLOG_LOGGER_TRACE(m_logger, "处理注销请求: {}:{}", clientInfo.clientIP.toStdString(), clientInfo.clientPort);
 
     /* 查找RTP发送线程 */
-    auto pThread = ThreadMan.getRtpSendThread(clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
+    auto pThread = ThreadMan.getRtpSendThread(clientInfo.cardPCMInfo.pcmInfo.strPCMName);
     if(pThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡编号: {}, 通道编号: {}", 
-                            clientInfo.SoundCardNum, clientInfo.SoundCardRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "没有找到对应的RTP发送线程,声卡通道名称: {}:{}", 
+                            clientInfo.cardPCMInfo.strSoundCardName, clientInfo.cardPCMInfo.pcmInfo.strPCMName);
         return;
     }
     /* 删除UDP会话 */
@@ -327,8 +323,7 @@ void RTPServer::handleLogout(RtpSendClientInfo_t& clientInfo)
     RtpClientKey_t clientKey;
     clientKey.clientIP = clientInfo.clientIP;
     clientKey.clientPort = clientInfo.clientPort;
-    clientKey.SoundCardNum = clientInfo.SoundCardNum;
-    clientKey.SoundCardRoadNum = clientInfo.SoundCardRoadNum;
+    clientKey.cardPCMInfo = clientInfo.cardPCMInfo;
     if(m_mapClientHeartbeats.contains(clientKey))
     {
         m_mapClientHeartbeats.remove(clientKey);

+ 1 - 1
RTPServer/RtpServer.h

@@ -54,7 +54,7 @@ private slots:
     void do_receiveMessage();
 
     /* 接收到释放端口的信号 */
-    void do_udpClosed(int soundCardNum, int roadNum);
+    void do_udpClosed(std::string pcmName);
 
     /* 处理心跳超时 */
     void do_heartbeatTimeout();

+ 6 - 7
RTPServer/Rtpcommon.cpp

@@ -54,8 +54,7 @@ RtpSendClientInfo_t& RtpSendClientInfo_t::operator=(const RtpSendClientInfo_t& o
         clientPort = other.clientPort;
         // compareItemID = other.compareItemID;
         // compareItemRoadNum = other.compareItemRoadNum;
-        SoundCardNum = other.SoundCardNum;
-        SoundCardRoadNum = other.SoundCardRoadNum;
+        cardPCMInfo = other.cardPCMInfo;
         // udpSocket = other.udpSocket;     /* 不拷贝udp套接字 */ 
     }
     return *this;
@@ -65,7 +64,7 @@ RtpSendClientInfo_t& RtpSendClientInfo_t::operator=(const RtpSendClientInfo_t& o
 bool RtpClientKey_t::operator==(const RtpClientKey_t& other) const
 {
     return (clientIP == other.clientIP && clientPort == other.clientPort &&
-            SoundCardNum == other.SoundCardNum && SoundCardRoadNum == other.SoundCardRoadNum);
+            cardPCMInfo == other.cardPCMInfo);
 }
 
 
@@ -75,13 +74,13 @@ bool RtpClientKey_t::operator<(const RtpClientKey_t& other) const
         return true;
     if (clientPort > other.clientPort)
         return false;
-    if (SoundCardNum < other.SoundCardNum)
+    if (cardPCMInfo.pcmInfo.strPCMName < other.cardPCMInfo.pcmInfo.strPCMName)
         return true;
-    if (SoundCardNum > other.SoundCardNum)
+    if (cardPCMInfo.pcmInfo.strPCMName > other.cardPCMInfo.pcmInfo.strPCMName)
         return false;
-    if (SoundCardRoadNum < other.SoundCardRoadNum)
+    if (cardPCMInfo.strSoundCardName < other.cardPCMInfo.strSoundCardName)
         return true;
-    if (SoundCardRoadNum > other.SoundCardRoadNum)
+    if (cardPCMInfo.strSoundCardName > other.cardPCMInfo.strSoundCardName)
         return false;
     return clientIP < other.clientIP; // 最后比较IP地址
 }

+ 3 - 4
RTPServer/Rtpcommon.h

@@ -1,6 +1,7 @@
 #ifndef _RTPCOMMON_H_
 #define _RTPCOMMON_H_
 
+#include "GlobalVariable.h"
 #include <QList>
 
 
@@ -52,8 +53,7 @@ struct RtpSendClientInfo_t
     
     // int compareItemID;                  /* 对比项ID */
     // int compareItemRoadNum;             /* 对比项通道号 */
-    int SoundCardNum;                   /* 声卡编号 */
-    int SoundCardRoadNum;               /* 声卡通道编号 */
+    OneSoundCardPCMInfo_t cardPCMInfo;  /* 声卡PCM通道信息 */
 
 
     RtpSendClientInfo_t();
@@ -71,8 +71,7 @@ struct RtpClientKey_t
     QString clientIP;           /* 客户端IP */
     int clientPort;             /* 客户端接收数据的UDP端口 */
 
-    int SoundCardNum = -1;      /* 声卡编号 */
-    int SoundCardRoadNum = -1;  /* 声卡通道编号 */
+    OneSoundCardPCMInfo_t cardPCMInfo;  /* 声卡PCM通道信息 */
 
     RtpClientKey_t() = default;
     

+ 36 - 6
SQL/ACAServer.sql

@@ -16,6 +16,7 @@ SELECT *
 FROM tACASystemConfig;
 
 
+
 #对比项一致性对比时段信息
 SELECT *
 FROM tACADetectPeriod;
@@ -39,6 +40,10 @@ FROM tACARecordFile
 ORDER BY PKID DESC;
 
 
+#获取声卡信息
+SELECT *
+FROM tACASoundCardPCMChannels;
+
 
 
 #清空报警信息内容
@@ -50,10 +55,10 @@ DROP TABLE IF EXISTS tACAAlarmInfo;
 
 #插入报警信息
 INSERT INTO tACAAlarmInfo (
-    ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType, 
+    ItemID, ItemName, AlarmType, SoundCardName, SoundCardPCMName, CompareRoadNum, CompareRoadName, CompareRoadType, 
     AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos, FileState )
 VALUES (
-    @itemID, @itemName, @alarmType, @soundCardNum, @soundCardName, @soundCardRoadNum, @compareRoadNum, @compareRoadName, @compareRoadType, 
+    @itemID, @itemName, @alarmType, @soundCardName, @soundCardPCMName, @compareRoadNum, @compareRoadName, @compareRoadType, 
     @alarmStartTime, @alarmEndTime, @alarmDuration, @alarmFilePath, @fileAlarmStartPos, @fileState );
 
 #删除早于某个时间点的报警信息
@@ -86,10 +91,10 @@ ORDER BY PKID DESC;
 
 #插入录音文件信息
 INSERT INTO tACARecordFile (
-    ItemID, ItemName, ItemRoadNum, ItemRoadName, SoundCardNum, SoundCardRoadNum,
+    ItemID, ItemName, ItemRoadNum, ItemRoadName, SoundCardName, SoundCardPCMName,
     FileStartTime, FileEndTime, FileDuration, FilePath, FileState
 ) VALUES (
-    @itemID, @itemName, @itemRoadNum, @itemRoadName, @soundCardNum, @soundCardRoadNum,
+    @itemID, @itemName, @itemRoadNum, @itemRoadName, @soundCardName, @soundCardPCMName,
     @fileStartTime, @fileEndTime, @fileDuration, @filePath, @fileState
 );
 
@@ -99,7 +104,7 @@ INSERT INTO tACARecordFile (
 UPDATE tACARecordFile
 SET FileEndTime = @fileEndTime, FilePath = @filePath, FileDuration = @fileDuration, FileState = @fileState
 WHERE ItemID = @itemID AND ItemRoadNum = @itemRoadNum 
-    AND SoundCardNum = @soundCardNum AND SoundCardRoadNum = @soundCardRoadNum
+    AND SoundCardName = @soundCardName AND SoundCardPCMName = @soundCardPCMName
     AND FileStartTime = @fileStartTime;
 
 
@@ -119,4 +124,29 @@ WHERE FileStartTime < :timePoint;
 #获取早于某个时间点并且未被删除的的录音文件信息
 SELECT *
 FROM tACARecordFile
-WHERE FileStartTime < @timePoint AND FileState != 3;
+WHERE FileStartTime < @timePoint AND FileState != 3;
+
+#插入声卡通道信息
+INSERT INTO tACASoundCardPCMChannels (
+    SoundCardName, PCMName, PCMDesc, IOID, SoundCardNum, SoundCardRoadNum
+) VALUES (
+    @soundCardName, @pcmName, @pcmDesc, @ioid, @soundCardNum, @soundCardRoadNum
+);
+
+
+#删除PCM通道信息
+DELETE FROM tACASoundCardPCMChannels
+WHERE PKID = @pkid;
+
+#删除所有的PCM通道信息
+DELETE FROM tACASoundCardPCMChannels;
+
+#获取PCM通道信息
+SELECT *
+FROM tACASoundCardPCMChannels;
+
+
+#更新声卡通道信息
+UPDATE tACASoundCardPCMChannels
+SET SoundCardDriver = @soundCardDriver, PCMName = @pcmName, PCMDesc = @pcmDesc, SoundCardNum = @soundCardNum, SoundCardName = @soundCardName, SoundCardRoadNum = @soundCardRoadNum
+WHERE PKID = @pkid;

File diff suppressed because it is too large
+ 37 - 5
SQL/ACASetting.sql


+ 31 - 26
SQL/CreateProcedures.sqlbook

@@ -1,15 +1,16 @@
 -- SQLBook: Code
+-- Active: 1752920752747@@192.1.2.61@5236@EQM_CESHI
 #写入报警数据库的存储过程
 
 -- 达梦数据库
 CREATE OR REPLACE PROCEDURE ACAS_InsertTwoAlarmInfo(
     itemID1 IN INT, itemName1 IN VARCHAR(100), alarmType1 IN INT,
-    soundCardNum1 IN INT, soundCardName1 IN VARCHAR(100), soundCardRoadNum1 IN INT,
+    soundCardName1 IN VARCHAR(100), soundCardPCMName1 IN VARCHAR(100),
     compareRoadNum1 IN INT, compareRoadName1 IN VARCHAR(100), compareRoadType1 IN INT,
     alarmStartTime1 IN DATETIME, alarmEndTime1 IN DATETIME, alarmDuration1 IN INT,
     alarmFilePath1 IN VARCHAR(255), fileAlarmStartPos1 IN INT, fileState1 IN INT,
     itemID2 IN INT, itemName2 IN VARCHAR(100), alarmType2 IN INT,
-    soundCardNum2 IN INT, soundCardName2 IN VARCHAR(100), soundCardRoadNum2 IN INT,
+    soundCardName2 IN VARCHAR(100), soundCardPCMName2 IN VARCHAR(100),
     compareRoadNum2 IN INT, compareRoadName2 IN VARCHAR(100), compareRoadType2 IN INT,
     alarmStartTime2 IN DATETIME, alarmEndTime2 IN DATETIME, alarmDuration2 IN INT,
     alarmFilePath2 IN VARCHAR(255), fileAlarmStartPos2 IN INT, fileState2 IN INT
@@ -18,18 +19,18 @@ AS
     pkid INT;
 BEGIN
     INSERT INTO tACAAlarmInfo (
-        ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType,
+        ItemID, ItemName, AlarmType, SoundCardName, SoundCardPCMName, CompareRoadNum, CompareRoadName, CompareRoadType,
         AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos, FileState
     ) VALUES (
-        itemID1, itemName1, alarmType1, soundCardNum1, soundCardName1, soundCardRoadNum1, compareRoadNum1, compareRoadName1, compareRoadType1,
+        itemID1, itemName1, alarmType1, soundCardName1, soundCardPCMName1, compareRoadNum1, compareRoadName1, compareRoadType1,
         alarmStartTime1, alarmEndTime1, alarmDuration1, alarmFilePath1, fileAlarmStartPos1, fileState1
     );
     SELECT MAX(PKID) INTO pkid FROM tACAAlarmInfo;
     INSERT INTO tACAAlarmInfo (
-        ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType,
+        ItemID, ItemName, AlarmType, SoundCardName, SoundCardPCMName, CompareRoadNum, CompareRoadName, CompareRoadType,
         AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos, MainRoadPKID, FileState
     ) VALUES (
-        itemID2, itemName2, alarmType2, soundCardNum2, soundCardName2, soundCardRoadNum2, compareRoadNum2, compareRoadName2, compareRoadType2,
+        itemID2, itemName2, alarmType2, soundCardName2, soundCardPCMName2, compareRoadNum2, compareRoadName2, compareRoadType2,
         alarmStartTime2, alarmEndTime2, alarmDuration2, alarmFilePath2, fileAlarmStartPos2, pkid, fileState2
     );
 END;
@@ -37,45 +38,49 @@ END;
 # 调用存储过程
 CALL ACAS_InsertTwoAlarmInfo(
     @itemID1, @itemName1, @alarmType1,
-    @soundCardNum1, @soundCardName1, @soundCardRoadNum1,
+    @soundCardName1, @soundCardPCMName1,
     @compareRoadNum1, @compareRoadName1, @compareRoadType1,
     @alarmStartTime1, @alarmEndTime1, @alarmDuration1,
-    @alarmFilePath1, @fileAlarmStartPos1, fileState1,
+    @alarmFilePath1, @fileAlarmStartPos1, @fileState1,
     @itemID2, @itemName2, @alarmType2,
-    @soundCardNum2, @soundCardName2, @soundCardRoadNum2,
+    @soundCardName2, @soundCardPCMName2,
     @compareRoadNum2, @compareRoadName2, @compareRoadType2,
     @alarmStartTime2, @alarmEndTime2, @alarmDuration2,
-    @alarmFilePath2, @fileAlarmStartPos2, fileState2
+    @alarmFilePath2, @fileAlarmStartPos2, @fileState2
 );
 
 #GBase版本的存储过程
 CREATE PROCEDURE ACAS_InsertTwoAlarmInfo(
-    IN itemID1 INT, IN itemName1 VARCHAR(100), IN alarmType1 INT,
-    IN soundCardNum1 INT, IN soundCardName1 VARCHAR(100), IN soundCardRoadNum1 INT,
-    IN compareRoadNum1 INT, IN compareRoadName1 VARCHAR(100), IN compareRoadType1 INT,
-    IN alarmStartTime1 DATETIME, IN alarmEndTime1 DATETIME, IN alarmDuration1 INT,
-    IN alarmFilePath1 VARCHAR(255), IN fileAlarmStartPos1 INT, IN fileState1 INT,
-    IN itemID2 INT, IN itemName2 VARCHAR(100), IN alarmType2 INT,
-    IN soundCardNum2 INT, IN soundCardName2 VARCHAR(100), IN soundCardRoadNum2 INT,
-    IN compareRoadNum2 INT, IN compareRoadName2 VARCHAR(100), IN compareRoadType2 INT,
-    IN alarmStartTime2 DATETIME, IN alarmEndTime2 DATETIME, IN alarmDuration2 INT,
-    IN alarmFilePath2 VARCHAR(255), IN fileAlarmStartPos2 INT, IN fileState2 INT
+    itemID1 INT, itemName1 VARCHAR(100), alarmType1 INT,
+    soundCardName1 VARCHAR(100), soundCardPCMName1 VARCHAR(100),
+    compareRoadNum1 INT, compareRoadName1 VARCHAR(100), compareRoadType1 INT,
+    alarmStartTime1 VARCHAR(32), alarmEndTime1 VARCHAR(32), alarmDuration1 INT,
+    alarmFilePath1 VARCHAR(255), fileAlarmStartPos1 INT, fileState1 INT,
+    itemID2 INT, itemName2 VARCHAR(100), alarmType2 INT,
+    soundCardName2 VARCHAR(100), soundCardPCMName2 VARCHAR(100),
+    compareRoadNum2 INT, compareRoadName2 VARCHAR(100), compareRoadType2 INT,
+    alarmStartTime2 VARCHAR(32), alarmEndTime2 VARCHAR(32), alarmDuration2 INT,
+    alarmFilePath2 VARCHAR(255), fileAlarmStartPos2 INT, fileState2 INT
 )
 DEFINE pkid INT;
 BEGIN
+    
     INSERT INTO tACAAlarmInfo (
-        ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType,
+        ItemID, ItemName, AlarmType, SoundCardName, SoundCardPCMName, CompareRoadNum, CompareRoadName, CompareRoadType,
         AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos, FileState
     ) VALUES (
-        itemID1, itemName1, alarmType1, soundCardNum1, soundCardName1, soundCardRoadNum1, compareRoadNum1, compareRoadName1, compareRoadType1,
+        itemID1, itemName1, alarmType1, soundCardPCMName1, soundCardRoadNum1, compareRoadNum1, compareRoadName1, compareRoadType1,
         alarmStartTime1, alarmEndTime1, alarmDuration1, alarmFilePath1, fileAlarmStartPos1, fileState1
     );
-    LET pkid = dbinfo('sqlca.sqlerrd1');
+    SELECT MAX(PKID) INTO pkid FROM tACAAlarmInfo;
     INSERT INTO tACAAlarmInfo (
-        ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType,
+        ItemID, ItemName, AlarmType, SoundCardName, SoundCardPCMName, CompareRoadNum, CompareRoadName, CompareRoadType,
         AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos, MainRoadPKID, FileState
     ) VALUES (
-        itemID2, itemName2, alarmType2, soundCardNum2, soundCardName2, soundCardRoadNum2, compareRoadNum2, compareRoadName2, compareRoadType2,
+        itemID2, itemName2, alarmType2, soundCardName2, soundCardRoadNum2, soundCardPCMName2, compareRoadName2, compareRoadType2,
         alarmStartTime2, alarmEndTime2, alarmDuration2, alarmFilePath2, fileAlarmStartPos2, pkid, fileState2
     );
-END PROCEDURE;
+END
+END PROCEDURE
+
+

+ 238 - 0
SQL/CreateTable-GBase.sqlbook

@@ -0,0 +1,238 @@
+-- SQLBook: Code
+
+# GBase创建 tACACompareItems
+CREATE TABLE tACACompareItems
+(
+    ItemID SERIAL NOT NULL,
+    ItemName VARCHAR(64) NOT NULL,
+    ItemEnable INTEGER NOT NULL DEFAULT 1,
+    RoadCount INTEGER DEFAULT 0,
+    SilentEnable INTEGER NOT NULL DEFAULT 0,
+    SilentThreshold INTEGER DEFAULT 0,
+    SilentDuration INTEGER DEFAULT 0,
+    SilentSensitivity INTEGER DEFAULT 0,
+    OverloadEnable INTEGER NOT NULL DEFAULT 0,
+    OverloadThreshold INTEGER DEFAULT 0,
+    OverloadDuration INTEGER DEFAULT 0,
+    OverloadSensitivity INTEGER DEFAULT 0,
+    PhaseEnable INTEGER NOT NULL DEFAULT 0,
+    PhaseThreshold FLOAT DEFAULT 0,
+    PhaseDuration INTEGER DEFAULT 0,
+    PhaseSensitivity INTEGER DEFAULT 0,
+    CONSTRAINT tACACompareItems PRIMARY KEY (ItemID)
+);
+
+COMMENT ON TABLE tACACompareItems IS 'ACA对比项表';
+-- 字段注释
+COMMENT ON COLUMN tACACompareItems.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACACompareItems.ItemName IS '对比项名称';
+COMMENT ON COLUMN tACACompareItems.ItemEnable IS '对比项是否启用';
+COMMENT ON COLUMN tACACompareItems.RoadCount IS '对比通道数';
+COMMENT ON COLUMN tACACompareItems.SilentEnable IS '是否启用静音';
+COMMENT ON COLUMN tACACompareItems.SilentThreshold IS '静音阈值';
+COMMENT ON COLUMN tACACompareItems.SilentDuration IS '静音持续时间';
+COMMENT ON COLUMN tACACompareItems.SilentSensitivity IS '静音灵敏度';
+COMMENT ON COLUMN tACACompareItems.OverloadEnable IS '是否启用过载';
+COMMENT ON COLUMN tACACompareItems.OverloadThreshold IS '过载阈值';
+COMMENT ON COLUMN tACACompareItems.OverloadDuration IS '过载持续时间';
+COMMENT ON COLUMN tACACompareItems.OverloadSensitivity IS '过载灵敏度';
+COMMENT ON COLUMN tACACompareItems.PhaseEnable IS '是否启用反相';
+COMMENT ON COLUMN tACACompareItems.PhaseThreshold IS '反相阈值';
+COMMENT ON COLUMN tACACompareItems.PhaseDuration IS '反相持续时间';
+COMMENT ON COLUMN tACACompareItems.PhaseSensitivity IS '反相灵敏度';
+
+
+-- 创建索引(如需要)
+-- CREATE INDEX idx_tACACompareItems_ItemName ON tACACompareItems (ItemName);
+-- SQLBook: Code
+#删除 tACACompareItems
+DROP TABLE IF EXISTS "EQM_CESHI".tACACompareItems;
+-- SQLBook: Code
+
+#创建 tACACompareItemRoad
+#这里设置了级联删除,当 tACACompareItems 表中的某个对比项被删除时,tACACompareItemRoad 中对应的通道也会被删除。
+CREATE TABLE tACACompareItemRoad
+(
+    ItemID SERIAL NOT NULL,
+    RoadNum INTEGER NOT NULL,
+    RoadName VARCHAR(64) NOT NULL,
+    RoadRecordEnable SMALLINT NOT NULL DEFAULT 1,
+    SoundCardNum INTEGER NOT NULL DEFAULT 0,
+    SoundCardID VARCHAR(64),
+    SoundCardName VARCHAR(64),
+    SoundCardRoadNum INTEGER NOT NULL DEFAULT 0,
+    ChannelID INTEGER,
+    ChannelName VARCHAR(64),
+    PRIMARY KEY (ItemID, RoadNum),
+    FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
+        ON DELETE CASCADE
+);
+-- 表注释
+COMMENT ON TABLE tACACompareItemRoad IS '对比项通道表';
+-- 字段注释
+COMMENT ON COLUMN tACACompareItemRoad.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACACompareItemRoad.RoadNum IS '通道编号,1是主通道,其他对比通道依次向后排';
+COMMENT ON COLUMN tACACompareItemRoad.RoadName IS '通道名称';
+COMMENT ON COLUMN tACACompareItemRoad.RoadRecordEnable IS '通道录音是否启用';
+COMMENT ON COLUMN tACACompareItemRoad.SoundCardNum IS '声卡编号,在系统中的编号';
+COMMENT ON COLUMN tACACompareItemRoad.SoundCardID IS '声卡ID,可以使用声卡ID来打开声卡';
+COMMENT ON COLUMN tACACompareItemRoad.SoundCardName IS '声卡名称';
+COMMENT ON COLUMN tACACompareItemRoad.SoundCardRoadNum IS '声卡通道编号,使用声卡编号和声卡通道编号开始录音';
+COMMENT ON COLUMN tACACompareItemRoad.ChannelID IS '频道ID';
+COMMENT ON COLUMN tACACompareItemRoad.ChannelName IS '频道名称';
+-- SQLBook: Code
+#创建ACA的系统配置表,使用Key获取存储的值,值内容是一个JOSN字符串
+CREATE TABLE tACADetectPeriod
+(
+    ItemID INTEGER NOT NULL,
+    IsDetect SMALLINT NOT NULL DEFAULT 1, -- 是否检测
+    WeekType INTEGER NOT NULL,
+    CDate VARCHAR(32),
+    TimeStart VARCHAR(32) NOT NULL,
+    TimeEnd VARCHAR(32) NOT NULL,
+    ApplySlient SMALLINT NOT NULL DEFAULT 0,  -- 是否应用静音
+    ApplyOverload SMALLINT NOT NULL DEFAULT 0, -- 是否应用超载
+    ApplyPhase SMALLINT NOT NULL DEFAULT 0,   -- 是否应用反相
+    ApplyNoise SMALLINT NOT NULL DEFAULT 0,   -- 是否应用噪音
+    FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
+        ON DELETE CASCADE
+);
+
+-- 表注释
+COMMENT ON TABLE tACADetectPeriod IS '检测计划表';
+-- 字段注释
+COMMENT ON COLUMN tACADetectPeriod.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACADetectPeriod.IsDetect IS '是否检测,1表示检测日期,0表示非检测日期';
+COMMENT ON COLUMN tACADetectPeriod.WeekType IS '检测计划的星期,1-7表示周一到周日,8表示特殊日期,也就是非检测日';
+COMMENT ON COLUMN tACADetectPeriod.CDate IS '检测计划的日期';
+COMMENT ON COLUMN tACADetectPeriod.TimeStart IS '检测计划的开始时间';
+COMMENT ON COLUMN tACADetectPeriod.TimeEnd IS '检测计划的结束时间';
+COMMENT ON COLUMN tACADetectPeriod.ApplySlient IS '是否应用静音检测';
+COMMENT ON COLUMN tACADetectPeriod.ApplyOverload IS '是否应用超载检测';
+COMMENT ON COLUMN tACADetectPeriod.ApplyPhase IS '是否应用反相检测';
+COMMENT ON COLUMN tACADetectPeriod.ApplyNoise IS '是否应用噪音检测';
+-- 创建索引
+CREATE INDEX idx_tACADetectPeriod_ItemID ON tACADetectPeriod (ItemID);
+-- SQLBook: Code
+#创建系统配置表格
+
+CREATE TABLE tACASystemConfig (
+	PKID SERIAL NOT NULL,
+	ConfigKey VARCHAR(64) NOT NULL UNIQUE,
+	ConfigValue VARCHAR(4096) NOT NULL,
+    UpdateTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+    ConfigDesc VARCHAR(256)
+);
+
+CREATE OR REPLACE TRIGGER trg_update_time
+BEFORE UPDATE ON tACASystemConfig
+FOR EACH ROW
+BEGIN
+    :NEW.UpdateTime := CURRENT_TIMESTAMP;
+END;
+
+comment on table tACASystemConfig is 'ACA系统配置表' ;
+comment on column tACASystemConfig.PKID is '主键ID' ;
+comment on column tACASystemConfig.ConfigKey is '配置键' ;
+comment on column tACASystemConfig.ConfigValue is '配置值,存储为JSON字符串' ;
+comment on column tACASystemConfig.UpdateTime is '配置更新时间' ;
+comment on column tACASystemConfig.ConfigDesc is '配置描述' ;
+
+
+
+-- SQLBook: Code
+CREATE TABLE tACAAlarmInfo
+(
+    PKID SERIAL NOT NULL,
+    ItemID INTEGER NOT NULL,
+    ItemName VARCHAR(64) NOT NULL,
+    AlarmType INTEGER NOT NULL, -- 报警类型,1-静音,2-过载,3-反相,4-噪音,5-不一致
+    SoundCardNum VARCHAR(64) NOT NULL, -- 声卡编号(在系统中的编号)
+    SoundCardName VARCHAR(64), -- 声卡名称
+    SoundCardRoadNum INTEGER NOT NULL, -- 声卡通道编号
+    CompareRoadNum INTEGER NOT NULL, -- 对比通道编号
+    CompareRoadName VARCHAR(64), -- 对比通道名称
+    CompareRoadType INTEGER, -- 通道类型:1、主输出,2、空收,3、主输出空收
+    AlarmStartTime VARCHAR(32), -- 报警开始时间 (格式:YYYY-MM-DD HH:MM:SS)
+    AlarmEndTime VARCHAR(32), -- 报警结束时间 (格式:YYYY-MM-DD HH:MM:SS)
+    AlarmDuration INTEGER, -- 报警持续时间(秒数)
+    AlarmFilePath VARCHAR(256), -- 报警录音文件路径
+    FileAlarmStartPos INTEGER, -- 在报警录音文件中报警开始的时间
+    MainRoadPKID INTEGER, -- 主通道的PKID
+    FileState INTEGER DEFAULT 0, -- 报警文件状态,1-录音中,2-已录音,3-已删除
+    CONSTRAINT tACAAlarmInfo PRIMARY KEY (PKID),
+    FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
+)
+-- 表注释
+COMMENT ON TABLE tACAAlarmInfo IS 'ACA报警记录表';
+-- 字段注释
+COMMENT ON COLUMN tACAAlarmInfo.PKID IS '主键ID';
+COMMENT ON COLUMN tACAAlarmInfo.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACAAlarmInfo.ItemName IS '对比项名称';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmType IS '报警类型,1-静音,2-过载,3-反相,4-噪音,5-不一致';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardNum IS '声卡编号(在系统中的编号)';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardName IS '声卡名称';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadNum IS '对比通道编号';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadName IS '对比通道名称';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadType IS '通道类型:1、主输出,2、空收,3、主输出空收';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmStartTime IS '报警开始时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmEndTime IS '报警结束时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmDuration IS '报警持续时间(秒数)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmFilePath IS '报警录音文件路径';
+COMMENT ON COLUMN tACAAlarmInfo.FileAlarmStartPos IS '在报警录音文件中报警开始的时间';
+COMMENT ON COLUMN tACAAlarmInfo.MainRoadPKID IS '对比项主通道报警信息的PKID';
+COMMENT ON COLUMN tACAAlarmInfo.FileState IS '报警文件状态,1-录音中,2-已录音,3-已删除';
+
+-- 创建索引
+CREATE INDEX idx_tACAAlarmInfo_ItemID ON tACAAlarmInfo (ItemID);
+CREATE INDEX idx_tACAAlarmInfo_AlarmType ON tACAAlarmInfo (AlarmType);
+CREATE INDEX idx_tACAAlarmInfo_SoundCardNum ON tACAAlarmInfo (SoundCardNum);
+CREATE INDEX idx_tACAAlarmInfo_SoundCardRoadNum ON tACAAlarmInfo (SoundCardRoadNum);
+CREATE INDEX idx_tACAAlarmInfo_CompareRoadNum ON tACAAlarmInfo (CompareRoadNum);
+CREATE INDEX idx_tACAAlarmInfo_AlarmStartTime ON tACAAlarmInfo (AlarmStartTime);
+CREATE INDEX idx_tACAAlarmInfo_AlarmEndTime ON tACAAlarmInfo (AlarmEndTime);
+-- SQLBook: Code
+CREATE TABLE tACARecordFile
+(
+    PKID SERIAL NOT NULL,
+    ItemID INTEGER NOT NULL,                -- 对比项ID
+    ItemName VARCHAR(64) NOT NULL,    -- 对比项名称
+    ItemRoadNum INTEGER NOT NULL,           -- 通道编号
+    ItemRoadName VARCHAR(64) NOT NULL, -- 通道名称
+    SoundCardNum INTEGER NOT NULL,          -- 声卡编号
+    SoundCardRoadNum INTEGER NOT NULL,      -- 声卡通道编号
+    FileStartTime VARCHAR(32) NOT NULL, -- 录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)
+    FileEndTime VARCHAR(32) NOT NULL,   -- 录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)
+    FileDuration INTEGER NOT NULL,          -- 录音文件持续时间(秒数)
+    FilePath VARCHAR(256) NOT NULL,     -- 录音文件路径
+    FileState INTEGER DEFAULT 0,            -- 录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除
+
+    CONSTRAINT tACARecordFile PRIMARY KEY (PKID),
+    FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
+        ON DELETE CASCADE
+);
+
+-- 表注释
+COMMENT ON TABLE tACARecordFile IS 'ACA录音文件记录表';
+-- 字段注释
+COMMENT ON COLUMN tACARecordFile.PKID IS '主键ID';
+COMMENT ON COLUMN tACARecordFile.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACARecordFile.ItemName IS '对比项名称';
+COMMENT ON COLUMN tACARecordFile.ItemRoadNum IS '通道编号';
+COMMENT ON COLUMN tACARecordFile.ItemRoadName IS '通道名称';
+COMMENT ON COLUMN tACARecordFile.SoundCardNum IS '声卡编号';
+COMMENT ON COLUMN tACARecordFile.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACARecordFile.FileStartTime IS '录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACARecordFile.FileEndTime IS '录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACARecordFile.FileDuration IS '录音文件持续时间(秒数)';
+COMMENT ON COLUMN tACARecordFile.FilePath IS '录音文件路径';
+COMMENT ON COLUMN tACARecordFile.FileState IS '录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除';
+-- 创建索引
+CREATE INDEX idx_tACARecordFile_ItemID ON tACARecordFile (ItemID);
+CREATE INDEX idx_tACARecordFile_ItemRoadNum ON tACARecordFile (ItemRoadNum);
+CREATE INDEX idx_tACARecordFile_SoundCardNum ON tACARecordFile (SoundCardNum);
+CREATE INDEX idx_tACARecordFile_SoundCardRoadNum ON tACARecordFile (SoundCardRoadNum);
+CREATE INDEX idx_tACARecordFile_FileStartTime ON tACARecordFile (FileStartTime);
+CREATE INDEX idx_tACARecordFile_FileEndTime ON tACARecordFile (FileEndTime);
+CREATE INDEX idx_tACARecordFile_FileDuration ON tACARecordFile (FileDuration);

+ 43 - 27
SQL/CreateTable.sqlbook → SQL/CreateTable-达梦.sqlbook

@@ -51,6 +51,7 @@ COMMENT ON COLUMN tACACompareItems.PhaseSensitivity IS '反相灵敏度';
 #删除 tACACompareItems
 DROP TABLE IF EXISTS "EQM_CESHI".tACACompareItems;
 -- SQLBook: Code
+-- Active: 1752920752747@@192.1.2.61@5236@EQM_CESHI
 
 #创建 tACACompareItemRoad
 #这里设置了级联删除,当 tACACompareItems 表中的某个对比项被删除时,tACACompareItemRoad 中对应的通道也会被删除。
@@ -60,10 +61,8 @@ CREATE TABLE tACACompareItemRoad
     RoadNum INT NOT NULL,
     RoadName VARCHAR(64) NOT NULL,
     RoadRecordEnable BIT NOT NULL DEFAULT 1,
-    SoundCardNum INT NOT NULL DEFAULT 0,
-    SoundCardID VARCHAR(64),
     SoundCardName VARCHAR(64),
-    SoundCardRoadNum INT NOT NULL DEFAULT 0,
+    SoundCardPCMName VARCHAR(64) NOT NULL DEFAULT 0,
     ChannelID INT,
     ChannelName VARCHAR(64),
     PRIMARY KEY (ItemID, RoadNum),
@@ -78,10 +77,8 @@ COMMENT ON COLUMN tACACompareItemRoad.ItemID IS '对比项ID';
 COMMENT ON COLUMN tACACompareItemRoad.RoadNum IS '通道编号,1是主通道,其他对比通道依次向后排';
 COMMENT ON COLUMN tACACompareItemRoad.RoadName IS '通道名称';
 COMMENT ON COLUMN tACACompareItemRoad.RoadRecordEnable IS '通道录音是否启用';
-COMMENT ON COLUMN tACACompareItemRoad.SoundCardNum IS '声卡编号,在系统中的编号';
-COMMENT ON COLUMN tACACompareItemRoad.SoundCardID IS '声卡ID,可以使用声卡ID来打开声卡';
 COMMENT ON COLUMN tACACompareItemRoad.SoundCardName IS '声卡名称';
-COMMENT ON COLUMN tACACompareItemRoad.SoundCardRoadNum IS '声卡通道编号,使用声卡编号和声卡通道编号开始录音';
+COMMENT ON COLUMN tACACompareItemRoad.SoundCardPCMName IS '声卡PCM通道名称,使用这个名称打开录音';
 COMMENT ON COLUMN tACACompareItemRoad.ChannelID IS '频道ID';
 COMMENT ON COLUMN tACACompareItemRoad.ChannelName IS '频道名称';
 
@@ -150,9 +147,8 @@ CREATE TABLE tACAAlarmInfo
     ItemID INT NOT NULL,
     ItemName VARCHAR(64) NOT NULL,
     AlarmType INT NOT NULL, -- 报警类型,1-静音,2-过载,3-反相,4-噪音,5-不一致
-    SoundCardNum VARCHAR(64) NOT NULL, -- 声卡编号(在系统中的编号)
     SoundCardName VARCHAR(64), -- 声卡名称
-    SoundCardRoadNum INT NOT NULL, -- 声卡通道编号
+    SoundCardPCMName VARCHAR(64) NOT NULL, -- 声卡PCM通道名称
     CompareRoadNum INT NOT NULL, -- 对比通道编号
     CompareRoadName VARCHAR(64), -- 对比通道名称
     CompareRoadType INT, -- 通道类型:1、主输出,2、空收,3、主输出空收
@@ -173,9 +169,8 @@ COMMENT ON COLUMN tACAAlarmInfo.PKID IS '主键ID';
 COMMENT ON COLUMN tACAAlarmInfo.ItemID IS '对比项ID';
 COMMENT ON COLUMN tACAAlarmInfo.ItemName IS '对比项名称';
 COMMENT ON COLUMN tACAAlarmInfo.AlarmType IS '报警类型,1-静音,2-过载,3-反相,4-噪音,5-不一致';
-COMMENT ON COLUMN tACAAlarmInfo.SoundCardNum IS '声卡编号(在系统中的编号)';
 COMMENT ON COLUMN tACAAlarmInfo.SoundCardName IS '声卡名称';
-COMMENT ON COLUMN tACAAlarmInfo.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardPCMName IS '声卡PCM通道名称';
 COMMENT ON COLUMN tACAAlarmInfo.CompareRoadNum IS '对比通道编号';
 COMMENT ON COLUMN tACAAlarmInfo.CompareRoadName IS '对比通道名称';
 COMMENT ON COLUMN tACAAlarmInfo.CompareRoadType IS '通道类型:1、主输出,2、空收,3、主输出空收';
@@ -190,29 +185,28 @@ COMMENT ON COLUMN tACAAlarmInfo.FileState IS '报警文件状态,1-录音中
 -- 创建索引
 CREATE INDEX idx_tACAAlarmInfo_ItemID ON tACAAlarmInfo (ItemID);
 CREATE INDEX idx_tACAAlarmInfo_AlarmType ON tACAAlarmInfo (AlarmType);
-CREATE INDEX idx_tACAAlarmInfo_SoundCardNum ON tACAAlarmInfo (SoundCardNum);
-CREATE INDEX idx_tACAAlarmInfo_SoundCardRoadNum ON tACAAlarmInfo (SoundCardRoadNum);
 CREATE INDEX idx_tACAAlarmInfo_CompareRoadNum ON tACAAlarmInfo (CompareRoadNum);
 CREATE INDEX idx_tACAAlarmInfo_AlarmStartTime ON tACAAlarmInfo (AlarmStartTime);
 CREATE INDEX idx_tACAAlarmInfo_AlarmEndTime ON tACAAlarmInfo (AlarmEndTime);
 
 -- SQLBook: Code
+-- Active: 1752920752747@@192.1.2.61@5236@EQM_CESHI
 -- Active: 1752718919967@@192.1.2.61@5236@EQM_CESHI
 #创建记录录音文件的表格
 CREATE TABLE tACARecordFile
 (
     PKID INT PRIMARY KEY AUTO_INCREMENT,
-    ItemID INT NOT NULL,                -- 对比项ID
-    ItemName VARCHAR(64) NOT NULL,    -- 对比项名称
-    ItemRoadNum INT NOT NULL,           -- 通道编号
-    ItemRoadName VARCHAR(64) NOT NULL, -- 通道名称
-    SoundCardNum INT NOT NULL,          -- 声卡编号
-    SoundCardRoadNum INT NOT NULL,      -- 声卡通道编号
-    FileStartTime VARCHAR(32) NOT NULL, -- 录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)
-    FileEndTime VARCHAR(32) NOT NULL,   -- 录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)
-    FileDuration INT NOT NULL,          -- 录音文件持续时间(秒数)
-    FilePath VARCHAR(256) NOT NULL,     -- 录音文件路径
-    FileState INT DEFAULT 0,            -- 录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除
+    ItemID INT NOT NULL,                    -- 对比项ID
+    ItemName VARCHAR(64) NOT NULL,          -- 对比项名称
+    ItemRoadNum INT NOT NULL,               -- 通道编号
+    ItemRoadName VARCHAR(64) NOT NULL,      -- 通道名称
+    SoundCardName VARCHAR(64) NOT NULL,     -- 声卡名称
+    SoundCardPCMName VARCHAR(64) NOT NULL,  -- 声卡PCM通道编号
+    FileStartTime VARCHAR(32) NOT NULL,     -- 录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)
+    FileEndTime VARCHAR(32) NOT NULL,       -- 录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)
+    FileDuration INT NOT NULL,              -- 录音文件持续时间(秒数)
+    FilePath VARCHAR(256) NOT NULL,         -- 录音文件路径
+    FileState INT DEFAULT 0,                -- 录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除
 
     FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
         ON DELETE CASCADE
@@ -226,8 +220,8 @@ COMMENT ON COLUMN tACARecordFile.ItemID IS '对比项ID';
 COMMENT ON COLUMN tACARecordFile.ItemName IS '对比项名称';
 COMMENT ON COLUMN tACARecordFile.ItemRoadNum IS '通道编号';
 COMMENT ON COLUMN tACARecordFile.ItemRoadName IS '通道名称';
-COMMENT ON COLUMN tACARecordFile.SoundCardNum IS '声卡编号';
-COMMENT ON COLUMN tACARecordFile.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACARecordFile.SoundCardName IS '声卡名称';
+COMMENT ON COLUMN tACARecordFile.SoundCardPCMName IS '声卡PCM通道编号';
 COMMENT ON COLUMN tACARecordFile.FileStartTime IS '录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)';
 COMMENT ON COLUMN tACARecordFile.FileEndTime IS '录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)';
 COMMENT ON COLUMN tACARecordFile.FileDuration IS '录音文件持续时间(秒数)';
@@ -236,10 +230,32 @@ COMMENT ON COLUMN tACARecordFile.FileState IS '录音文件状态,0-未知状
 -- 创建索引
 CREATE INDEX idx_tACARecordFile_ItemID ON tACARecordFile (ItemID);
 CREATE INDEX idx_tACARecordFile_ItemRoadNum ON tACARecordFile (ItemRoadNum);
-CREATE INDEX idx_tACARecordFile_SoundCardNum ON tACARecordFile (SoundCardNum);
-CREATE INDEX idx_tACARecordFile_SoundCardRoadNum ON tACARecordFile (SoundCardRoadNum);
 CREATE INDEX idx_tACARecordFile_FileStartTime ON tACARecordFile (FileStartTime);
 CREATE INDEX idx_tACARecordFile_FileEndTime ON tACARecordFile (FileEndTime);
 CREATE INDEX idx_tACARecordFile_FileDuration ON tACARecordFile (FileDuration);
 
 
+
+-- SQLBook: Code
+#创建存储声卡PCM通道的表格
+CREATE TABLE tACASoundCardPCMChannels
+(
+    -- PKID INT PRIMARY KEY AUTO_INCREMENT,
+    SoundCardName VARCHAR(64) NOT NULL,   -- 声卡驱动名称,自定义的,用来表示PCM通道的
+    PCMName VARCHAR(64) NOT NULL,           -- PCM通道名称
+    PCMDesc VARCHAR(256) NOT NULL,          -- PCM通道描述
+    IOID VARCHAR(32),                       -- 输入输出
+    SoundCardNum INT,                       -- 声卡编号,在系统中的编号,这个不是必须的,有些PCM通道是虚拟的,获取不到属于哪个声卡
+    SoundCardRoadNum INT                    -- 声卡通道编号,同上
+);
+
+-- 表注释
+COMMENT ON TABLE tACASoundCardPCMChannels IS '存储声卡PCM通道信息的表格';
+-- 字段注释
+-- COMMENT ON COLUMN tACASoundCardPCMChannels.PKID IS '主键ID';
+COMMENT ON COLUMN tACASoundCardPCMChannels.SoundCardName IS '声卡名称';
+COMMENT ON COLUMN tACASoundCardPCMChannels.PCMName IS 'PCM通道名称';
+COMMENT ON COLUMN tACASoundCardPCMChannels.PCMDesc IS 'PCM通道描述';
+COMMENT ON COLUMN tACASoundCardPCMChannels.IOID IS '输入输出标识,表示这个PCM通道是输入还是输出';
+COMMENT ON COLUMN tACASoundCardPCMChannels.SoundCardNum IS '声卡编号';
+COMMENT ON COLUMN tACASoundCardPCMChannels.SoundCardRoadNum IS '声卡通道编号';

+ 28 - 8
Server/ACAServer.cpp

@@ -3,7 +3,7 @@
 
 #include "GlobalInfo/GlobalInfo.h"
 #include "commonDefine.h"
-#include "SoundCardData.h"
+#include "SoundCards.h"
 #include "SystemConfig.h"
 #include "ThreadPool.h"
 #include "ThreadManager.h"
@@ -45,13 +45,20 @@ ACAServer::~ACAServer()
 
 
 
-/* 初始化基础信息 */
+/**
+ * @brief 初始化基础信息
+ *        返回值说明:
+ *              这里返回false会直接退出服务,因此不是必须项即使失败也不返回false
+ *
+ * @return true 
+ * @return false 
+ */
 bool ACAServer::initGlobalInfo()
 {
     /*------------------------------------------------------------------------------------*/
     /* 读取配置文件 */
     if(!readConfigFile()) {
-        spdlog::error("读取配置文件失败");
+        SPDLOG_ERROR("读取配置文件失败");
         return false;
     }
 
@@ -71,7 +78,7 @@ bool ACAServer::initGlobalInfo()
     }
 
     /* 设置WebAPI信息 */
-    m_webAPIID = "cf6b57fa3d9841e22c3c897e6b8e66b8";
+    // m_webAPIID = "cf6b57fa3d9841e22c3c897e6b8e66b8";
     GInfo.setWebAPIInfo(m_webAPIUrl, m_webAPIID);
 
     /* 登录webapi */
@@ -86,12 +93,16 @@ bool ACAServer::initGlobalInfo()
     {
         return false;
     }
+    /* 清空数据库声卡PCM数据 */
+    if(!m_fromWebAPI.clearSoundCardInfo())
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "清空声卡信息失败");
+        return false;
+    }
+
     auto soundCardsInfo = SoundCards.getSoundCardInfo();
-    std::string jsonSoundCards;
-    SysConfig.setSoundCardInfoToJson(soundCardsInfo, jsonSoundCards);
-    // SPDLOG_DEBUG("声卡信息: {}", jsonSoundCards);
     /* 将声卡信息写入数据库 */
-    if(!m_fromWebAPI.updateSystemConfig(Config_SoundCardInfo, jsonSoundCards, SysConfig.mapSysConfigDesc[eSystemConfigType::eSCT_SoundCardInfo]))
+    if(!m_fromWebAPI.insertPCMChannelInfo(soundCardsInfo))
     {
         SPDLOG_LOGGER_WARN(m_logger, "更新声卡信息到WebAPI失败");
     }
@@ -253,6 +264,15 @@ bool ACAServer::waitForWebAPIReply()
     return true;
 }
 
+
+/* 等待一些必选项设置成功,不成功会一直等待 */
+bool ACAServer::waitForRequiredOptions()
+{
+
+    return true;
+}
+
+
 /* 发送服务信息到MQTT中 */
 bool ACAServer::sendServerInfoToMQTT()
 {

+ 2 - 0
Server/ACAServer.h

@@ -57,6 +57,8 @@ private:
     bool readConfigFile();
     /* 等待webapi回复信息 */
     bool waitForWebAPIReply();
+    /* 等待一些必选项设置成功,不成功会一直等待 */
+    bool waitForRequiredOptions();
     /* 发送服务信息到MQTT中 */
     bool sendServerInfoToMQTT();
 

+ 0 - 1
Server/DataManager/DataQueueManager.cpp

@@ -1 +0,0 @@
-#include "DataQueueManager.h"

+ 0 - 37
Server/DataManager/DataQueueManager.h

@@ -1,37 +0,0 @@
-#ifndef _DATAQUEUEMANAGER_H_
-#define _DATAQUEUEMANAGER_H_
-
-
-#include "RingQueue.hpp"
-#include "RingQueueManualMutex.hpp"
-
-#include "AudioData.h"
-
-#define DataQueueMgr DataQueueManager::getInstance()
-
-class DataQueueManager
-{
-
-    // 禁止拷贝和赋值
-    DataQueueManager(const DataQueueManager&) = delete;
-    DataQueueManager& operator=(const DataQueueManager&) = delete;
-public:
-    DataQueueManager() = default;
-    ~DataQueueManager() = default;
-
-    // 获取单例实例
-    static DataQueueManager& getInstance()
-    {
-        static DataQueueManager instance;
-        return instance;
-    }
-
-
-private:
-    /* WAV小文件名路径 */
-    // RingQueue<WavFilePath> m_wavFilePathQueue;
-    /* 音量值数据队列 */
-};
-
-
-#endif // _DATAQUEUEMANAGER_H_

+ 0 - 101
Server/DataManager/SoundCardData.cpp

@@ -1,101 +0,0 @@
-#include "SoundCardData.h"
-
-
-/* 初始化数据,获取声卡信息 */
-bool SoundCardManager::InitData()
-{
-    /* 获取可用的声卡列表 */
-    if(AudioDevice::getAudioDevices(m_listAudioDevice))
-    {
-        SPDLOG_INFO("成功获取到声卡设备信息");
-    } else
-    {
-        SPDLOG_ERROR("获取声卡设备信息失败");
-    }
-
-    SPDLOG_INFO("----------------------------------------------------------------------------");
-    /* 打印声卡列表 */
-    printAudioDevices();
-
-    SPDLOG_INFO("----------------------------------------------------------------------------");
-    // /* 获取并打印另一种声卡信息 */
-    // std::list<AudioDeviceDesc_t> pcmDevices;
-    // if(getPCMAudioDevice(pcmDevices))
-    // {
-    //     SPDLOG_INFO("成功获取到PCM设备信息");
-    //     printAudioDeviceDesc(pcmDevices);
-    // } else
-    // {
-    //     SPDLOG_ERROR("获取PCM设备信息失败");
-    // }    
-
-
-    return true;
-}
-
-/* 获取声卡信息,转换成系统使用的数据类型 */
-QMap<int, SoundCardInfo_t> SoundCardManager::getSoundCardInfo() const
-{
-    QMap<int, SoundCardInfo_t> soundCardInfoMap;
-
-    for(const auto& device : m_listAudioDevice)
-    {
-        SoundCardInfo_t soundCardInfo;
-        soundCardInfo.nSoundCardNum = device.CardNumber;
-        soundCardInfo.strSoundCardID = QString::fromStdString(device.CardID);
-        soundCardInfo.strSoundCardName = QString::fromStdString(device.CardName);
-        soundCardInfo.strSoundCardDriver = QString::fromStdString(device.CardDriver);
-
-        for(const auto& pcmDevice : device.PCMDevices)
-        {
-            OneRoadInfo_t roadInfo;
-            roadInfo.nRoadNum = pcmDevice.PCMDevice;
-
-            soundCardInfo.listRoad.append(roadInfo);
-        }
-
-        soundCardInfoMap.insert(soundCardInfo.nSoundCardNum, soundCardInfo);
-    }
-
-    return soundCardInfoMap;
-}
-
-
-/* 打印声卡列表 */
-void SoundCardManager::printAudioDevices()
-{
-    SPDLOG_INFO("声卡列表: ");
-    for(const auto& device : m_listAudioDevice)
-    {
-        SPDLOG_INFO("   声卡编号: {}, ID: {}, 名称: {}, 驱动: {}",
-                     device.CardNumber, device.CardID, device.CardName, device.CardDriver);
-        SPDLOG_INFO("   长名称: {}, 混音器名称: {}, 组件信息: {}", 
-                    device.CardLongName, device.CardMixername, device.CardComponents);
-        for(const auto& pcmDevice : device.PCMDevices)
-        {
-            SPDLOG_INFO("       PCM设备编号: {}, 子设备编号: {}, PCM ID: {}, 名称: {}, 子设备名称: {}",
-                         pcmDevice.PCMDevice, pcmDevice.SubDevice, pcmDevice.CardNumber,
-                         pcmDevice.PCMID, pcmDevice.PCMName, pcmDevice.PCMSubName);
-        }
-    }
-}
-
-/* 打印声卡描述列表 */
-void SoundCardManager::printAudioDeviceDesc(std::list<AudioDeviceDesc_t>& pcmDevices)
-{
-    for(const auto& device : pcmDevices)
-    {
-        SPDLOG_INFO("设备名称: {}, 描述: {}, IOID: {}, 声卡: {}, 设备编号: {}",
-                     device.DeviceName, device.DeviceDesc, device.IOID,
-                     device.Card, device.DevNum);
-    }
-}
-
-/* 声卡信息写入数据库 */
-void SoundCardManager::writeAudioDeviceToDB()
-{
-
-}
-
-
-

+ 0 - 52
Server/DataManager/SoundCardData.h

@@ -1,52 +0,0 @@
-#ifndef __SOUNDCARDDATA_H__
-#define __SOUNDCARDDATA_H__
-
-#include "GlobalVariable.h"
-#include "AudioRecord.h"
-#include "spdlog/spdlog.h"
-
-/**
- * @brief 全局的声卡信息
- * 
- */
-
-#define SoundCards SoundCardManager::Instance()
-
-class SoundCardManager
-{
-
-    SoundCardManager() = default;
-    SoundCardManager(const SoundCardManager&) = delete;
-    SoundCardManager& operator=(const SoundCardManager&) = delete;
-public:
-    ~SoundCardManager() = default;
-    static SoundCardManager& Instance()
-    {
-        static SoundCardManager instance;
-        return instance;
-    }
-
-    /* 初始化数据,获取声卡信息 */
-    bool InitData();
-    /* 获取声卡信息 */
-    const std::list<AudioDevice_t>& getListAudioDevice() const { return m_listAudioDevice; }
-    /* 获取声卡信息,转换成系统使用的数据类型 */
-    QMap<int, SoundCardInfo_t> getSoundCardInfo() const;
-
-private:
-    /* 打印声卡列表 */
-    void printAudioDevices();
-    /* 打印声卡描述列表 */
-    void printAudioDeviceDesc(std::list<AudioDeviceDesc_t>& pcmDevices);
-    /* 声卡信息写入数据库 */
-    void writeAudioDeviceToDB();
-
-private:
-    /* 声卡设备列表 */
-    std::list<AudioDevice_t> m_listAudioDevice;
-
-};
-
-
-
-#endif // __SOUNDCARDDATA_H__

+ 145 - 0
Server/DataManager/SoundCards.cpp

@@ -0,0 +1,145 @@
+#include "SoundCards.h"
+
+
+/* 初始化数据,获取声卡信息 */
+bool SoundCardManager::InitData()
+{
+    /* 获取可用的声卡列表 */
+    // if(AudioDevice::getAudioDevices(m_listAudioDevice))
+    if(AudioDevice::getPCMAudioDevice(m_listAudioDeviceDesc))
+    {
+        SPDLOG_INFO("成功获取到声卡设备信息");
+    } else
+    {
+        SPDLOG_ERROR("获取声卡设备信息失败");
+    }
+
+    /* 将PCM通道根据已知的规则分类 */
+    classifyPCMChannels();
+
+    /* 打印声卡列表 */
+    // printAudioDevices();
+    printAudioDeviceDesc(m_mapSoundCardInfo);
+
+    // /* 获取并打印另一种声卡信息 */
+    // std::list<AudioDeviceDesc_t> pcmDevices;
+    // if(getPCMAudioDevice(pcmDevices))
+    // {
+    //     SPDLOG_INFO("成功获取到PCM设备信息");
+    //     printAudioDeviceDesc(pcmDevices);
+    // } else
+    // {
+    //     SPDLOG_ERROR("获取PCM设备信息失败");
+    // }    
+
+
+    return true;
+}
+
+
+
+/* 打印声卡列表 */
+// void SoundCardManager::printAudioDevices()
+// {
+//     SPDLOG_INFO("声卡列表: ");
+//     for(const auto& device : m_listAudioDevice)
+//     {
+//         SPDLOG_INFO("   声卡编号: {}, ID: {}, 名称: {}, 驱动: {}",
+//                      device.CardNumber, device.CardID, device.CardName, device.CardDriver);
+//         SPDLOG_INFO("   长名称: {}, 混音器名称: {}, 组件信息: {}", 
+//                     device.CardLongName, device.CardMixername, device.CardComponents);
+//         for(const auto& pcmDevice : device.PCMDevices)
+//         {
+//             SPDLOG_INFO("       PCM设备编号: {}, 子设备编号: {}, PCM ID: {}, 名称: {}, 子设备名称: {}",
+//                          pcmDevice.PCMDevice, pcmDevice.SubDevice, pcmDevice.CardNumber,
+//                          pcmDevice.PCMID, pcmDevice.PCMName, pcmDevice.PCMSubName);
+//         }
+//     }
+// }
+
+/* 打印声卡描述列表 */
+void SoundCardManager::printAudioDeviceDesc(const std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard)
+{
+    SPDLOG_INFO("----------------------------------------------------------------------------");
+    for(const auto& device : mapSoundCard)
+    {
+        SPDLOG_INFO("声卡名称: {}", device.first);
+        for(const auto& pcm : device.second.listPCM)
+        {
+            SPDLOG_INFO("   PCM设备名称: {}, 设备描述: {}", pcm.strPCMName, pcm.strPCMDesc);
+        }
+        SPDLOG_INFO("----------------------------------------------------------------------------");
+    }
+}
+
+
+/* 将PCM通道分类 */
+void SoundCardManager::classifyPCMChannels()
+{
+    std::list<AudioDeviceDesc_t> listPCM = m_listAudioDeviceDesc;
+    /* 获取Dante声卡的PCM通道信息 */
+    getDanteSoundCardInfo(listPCM);
+    /* 分类其他pcm通道 */
+    classifyRemainingPCMChannels(listPCM);
+}
+
+
+/* 取出dante声卡的PCM通道信息
+   dante声卡通过设备描述信息识别区分录音通道 */
+void SoundCardManager::getDanteSoundCardInfo(std::list<AudioDeviceDesc_t>& listPCM)
+{
+    SoundCardPCMInfo_t scPCMInfo;
+    scPCMInfo.strSoundCardName = SC_AlpDANTE;
+    for(auto it = listPCM.begin(); it != listPCM.end(); )
+    {
+        const auto& device = *it;
+        if(device.DeviceDesc.find(SC_AlpDANTE) != std::string::npos)
+        {
+            /* 通过描述信息中的“ in” 区分是输入还是输出通道 */
+            if(device.DeviceDesc.find(" in") != std::string::npos)
+            {
+                SPDLOG_DEBUG("Dante声卡输入通道: {}, IOID: {}, 描述: {}",
+                            device.DeviceName, device.IOID, device.DeviceDesc);
+                OnePCMChannelInfo_t pcm;
+                pcm.strPCMName = device.DeviceName;
+                pcm.strPCMDesc = device.DeviceDesc;
+                pcm.strIO = device.IOID;
+                scPCMInfo.listPCM.push_back(pcm);
+            } 
+            else if(device.DeviceDesc.find(" out") != std::string::npos)
+            {
+                SPDLOG_DEBUG("Dante声卡输出通道: {}, IOID: {}, 描述: {}",
+                            device.DeviceName, device.IOID, device.DeviceDesc);
+            } else
+            {
+                SPDLOG_DEBUG("Dante声卡未知通道类型: {}, IOID: {}, 描述: {}",
+                            device.DeviceName, device.IOID, device.DeviceDesc);
+            }
+
+            /* 去掉这个pcm信息 */
+            it = listPCM.erase(it);
+        } else
+        {
+            ++it;
+        }
+    }
+    m_mapSoundCardInfo[scPCMInfo.strSoundCardName] = scPCMInfo;
+}
+
+/* 将剩余的PCM通道信息分类
+    剩余的通道都放入到systemOther中 */
+void SoundCardManager::classifyRemainingPCMChannels(std::list<AudioDeviceDesc_t>& listPCM)
+{
+    SoundCardPCMInfo_t scPCMInfo;
+    scPCMInfo.strSoundCardName = SC_System;
+    for(const auto& device : listPCM)
+    {
+        OnePCMChannelInfo_t pcm;
+        pcm.strPCMName = device.DeviceName;
+        pcm.strPCMDesc = device.DeviceDesc;
+        pcm.strIO = device.IOID;
+        scPCMInfo.listPCM.push_back(pcm);
+    }
+    m_mapSoundCardInfo[scPCMInfo.strSoundCardName] = scPCMInfo;
+}
+

+ 60 - 0
Server/DataManager/SoundCards.h

@@ -0,0 +1,60 @@
+#ifndef __SOUNDCARDS_H__
+#define __SOUNDCARDS_H__
+
+#include "GlobalVariable.h"
+#include "AudioRecord.h"
+#include "spdlog/spdlog.h"
+#include <string>
+
+/**
+ * @brief 全局的声卡信息
+ * 
+ */
+
+#define SoundCards SoundCardManager::Instance()
+
+class SoundCardManager
+{
+
+    SoundCardManager() = default;
+    SoundCardManager(const SoundCardManager&) = delete;
+    SoundCardManager& operator=(const SoundCardManager&) = delete;
+public:
+    ~SoundCardManager() = default;
+    static SoundCardManager& Instance()
+    {
+        static SoundCardManager instance;
+        return instance;
+    }
+
+    /* 初始化数据,获取声卡信息 */
+    bool InitData();
+    /* 获取声卡信息 */
+    // const std::list<AudioDevice_t>& getListAudioDevice() const { return m_listAudioDevice; }
+    const std::list<AudioDeviceDesc_t>& getListAudioDeviceDesc() const { return m_listAudioDeviceDesc; }
+    /* 获取声卡信息,将PCM通道根据规则分类 */
+    const std::map<std::string, SoundCardPCMInfo_t>& getSoundCardInfo() { return m_mapSoundCardInfo; }
+
+private:
+    /* 打印声卡列表 */
+    // void printAudioDevices();
+    /* 打印声卡描述列表 */
+    void printAudioDeviceDesc(const std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard);
+    /* 将PCM通道分类 */
+    void classifyPCMChannels();
+    /* 取出dante声卡的PCM通道信息 */
+    void getDanteSoundCardInfo(std::list<AudioDeviceDesc_t>& listPCM);
+    /* 将剩余的PCM通道信息分类 */
+    void classifyRemainingPCMChannels(std::list<AudioDeviceDesc_t>& listPCM);
+
+private:
+    /* 声卡设备列表 */
+    // std::list<AudioDevice_t> m_listAudioDevice;
+    std::list<AudioDeviceDesc_t> m_listAudioDeviceDesc;         /* 声卡字符设备列表 */
+
+    std::map<std::string, SoundCardPCMInfo_t> m_mapSoundCardInfo;   /* 声卡信息,key是声卡标识符 */
+};
+
+
+
+#endif // __SOUNDCARDS_H__

+ 3 - 3
Server/DataStruct/CalculateAudio.cpp

@@ -98,7 +98,7 @@ StAudioNum::StAudioNum()
 
 StAudioNum& StAudioNum::operator=(const StAudioNum& obj)
 {
-	roadInfo = obj.roadInfo;
+	cardRoadInfo = obj.cardRoadInfo;
 	nTotal = obj.nTotal;
 	nLDataNum = obj.nLDataNum;
 	nLUnDataNum = obj.nLUnDataNum;
@@ -109,7 +109,7 @@ StAudioNum& StAudioNum::operator=(const StAudioNum& obj)
 
 bool StAudioNum::AudioIsError(int nDataNum, int nUnDataNum, bool bLeft)
 {
-	std::string strRoadName = roadInfo.strSoundCardName.toStdString() + ":" + std::to_string(roadInfo.roadInfo.nRoadNum);
+	std::string strRoadName = cardRoadInfo.strSoundCardName + ":" + cardRoadInfo.pcmInfo.strPCMName;
 	if (nDataNum > 0 && nUnDataNum > 0 && pcmErrorPercent > 0)
 	{
 		int nMax = nDataNum > nUnDataNum ? nDataNum : nUnDataNum;
@@ -134,7 +134,7 @@ bool StAudioNum::AudioIsError(int nDataNum, int nUnDataNum, bool bLeft)
 // 有问题的音频
 bool StAudioNum::IsErrorAudio()
 {
-	std::string strRoadName = roadInfo.strSoundCardName.toStdString() + ":" + std::to_string(roadInfo.roadInfo.nRoadNum);
+	std::string strRoadName = cardRoadInfo.strSoundCardName + ":" + cardRoadInfo.pcmInfo.strPCMName;
 	const int nMute = 200;
 	if (nLDataNum > nMute || nLUnDataNum > nMute || nRDataNum > nMute || nRUnDataNum > nMute)
 	{

+ 2 - 1
Server/DataStruct/CalculateAudio.h

@@ -146,7 +146,8 @@ struct StAudioNum
 	StAudioNum();
 	StAudioNum(const StAudioNum& obj) { *this = obj; }
 
-	SoundCardRoadInfo_t roadInfo; 	/* 通道ID */
+	// SoundCardRoadInfo_t roadInfo; 	/* 通道ID */
+	OneSoundCardPCMInfo_t cardRoadInfo; /* 声卡通道信息 */
 	int nTotal;             /* 总数据包数 */
 	int nLDataNum;          // 音频数据正数个数
 	int nLUnDataNum;        // 音频数据负数个数

+ 2 - 5
Server/GlobalInfo/GlobalInfo.h

@@ -72,9 +72,6 @@ public:
 
     /* 获取环形队列元素数目 */
     int32_t queueElementCount() const {return m_queueElementCount;}
-    /* 获取wav文件时长 */
-    int32_t wavFileDuration() const {return m_wavFileDuration;}
-
 
     /* 设置根目录 */
     void setRootPath(const QString& path) { m_rootPath = path; }
@@ -141,8 +138,8 @@ private:
     uint16_t m_bitsPerSample = 16;              /* 每个采样点的位数 */
 
     /******************** 一些默认的设置 *********************/
-    int32_t m_queueElementCount = 180;          /* 默认缓冲区的大小,也就是音频处理线程的环形队列的大小,单位是秒 */
-    int32_t m_wavFileDuration = 60;             /* 一个wav小文件有多少秒的数据 */
+    int32_t m_queueElementCount = 120;          /* 默认缓冲区的大小,也就是音频处理线程的环形队列的大小,单位是秒 */
+
 
     /* 音频错误计算的百分比,目前没用到 */
     // int m_pcmErrorPercent = 10;                 /* PCM数据不对称少于多少百分比,就判断为噪音,0表示不判断 */

+ 2 - 2
Server/ThreadCalculate/CalculateDBThread.cpp

@@ -149,11 +149,11 @@ bool CalculateDBThread::initData()
         /* 获取计算音量的线程 */
         if(m_threadCreateDB == nullptr)
         {
-            m_threadCreateDB = ThreadMan.getCreateDBThread(m_roadInfo.scRoadInfo.nSoundCardNum, m_roadInfo.scRoadInfo.roadInfo.nRoadNum);
+            m_threadCreateDB = ThreadMan.getCreateDBThread(m_roadInfo.scRoadInfo.pcmInfo.strPCMName);
         }
         if(m_threadCreateAlarmFile == nullptr)
         {
-            m_threadCreateAlarmFile = ThreadMan.getCreateRecordFileThread(m_roadInfo.scRoadInfo.nSoundCardNum, m_roadInfo.scRoadInfo.roadInfo.nRoadNum);
+            m_threadCreateAlarmFile = ThreadMan.getCreateRecordFileThread(m_roadInfo.scRoadInfo.pcmInfo.strPCMName);
         }
         
         if(m_threadCreateDB != nullptr && m_threadCreateAlarmFile != nullptr)

+ 17 - 20
Server/ThreadCalculate/CompareItemThread.cpp

@@ -37,7 +37,7 @@ void CompareItemThread::threadTask()
     for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
     {
         SPDLOG_LOGGER_INFO(m_logger, "      通道名称: {}, 通道编号: {}, 声卡通道: {}:{}",
-                           road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
+                           road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName, road.scRoadInfo.pcmInfo.strPCMName);
     }
     SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
 
@@ -135,7 +135,7 @@ void CompareItemThread::task()
     for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
     {
         SPDLOG_LOGGER_INFO(m_logger, "      通道名称: {}, 通道编号: {}, 声卡通道: {}:{}",
-                           road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
+                           road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.nCompareRoadNum, road.scRoadInfo.strSoundCardName, road.scRoadInfo.pcmInfo.strPCMName);
     }
     SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
 
@@ -168,7 +168,8 @@ void CompareItemThread::timerTask()
      * ------------------------------------------------------------------------------------- */
     if(updateThreadInfoInternal())
     {
-        SPDLOG_LOGGER_INFO(m_logger, "{} 暂停对比检测,更新对比项信息");
+        SPDLOG_LOGGER_INFO(m_logger, "{} 暂停对比检测,开始更新对比项信息...");
+        clearData();
         m_threadInfo.compareItemInfo = m_threadInfoNew.compareItemInfo;
         initData();
         SPDLOG_LOGGER_INFO(m_logger, "{} 更新对比项信息完成,继续检测对比");
@@ -215,17 +216,17 @@ bool CompareItemThread::initData()
     }
 
     /* 创建计算音量报警信息的线程指针 */
-    destroyCalculateDBThreads(); // 清理之前的线程
+    // destroyCalculateDBThreads(); // 清理之前的线程
     createCalculateDBThreads();
 
     /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
-    destroyCompareThreads();
+    // destroyCompareThreads();
     createCompareThreads();
 
     /* 创建计算噪音的线程 */
     if(m_noiseDetectConfig.isEnableNoiseDetect)
     {
-        destroyNoiseDetectThreads();
+        // destroyNoiseDetectThreads();
         createNoiseDetectThreads();
     }
     
@@ -289,10 +290,10 @@ void CompareItemThread::clearData()
     /* 移除使用到的录音通道 */
     for(auto& it : m_threadInfo.compareItemInfo.mapRoad)
     {
-        SoundCardRoadInfo_t roadInfo = it.scRoadInfo;
+        OneSoundCardPCMInfo_t roadInfo = it.scRoadInfo;
         if(!ThreadMan.removeRecordThread(roadInfo, m_threadInfo.compareItemInfo.nID))
         {
-            SPDLOG_LOGGER_ERROR(m_logger, "{} 移除录音通道 {}:{} 失败", m_logBase, roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+            SPDLOG_LOGGER_ERROR(m_logger, "{} 移除录音通道 {}:{} 失败", m_logBase, roadInfo.strSoundCardName, roadInfo.pcmInfo.strPCMName);
         }
     }
 
@@ -358,7 +359,7 @@ bool CompareItemThread::getCreateDBThread()
         bool isAllThreadsReady = true;
         for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
         {
-            CreateDBThread* pThread = ThreadMan.getCreateDBThread(road.scRoadInfo.nSoundCardNum, road.scRoadInfo.roadInfo.nRoadNum);
+            CreateDBThread* pThread = ThreadMan.getCreateDBThread(road.scRoadInfo.pcmInfo.strPCMName);
             if(pThread != nullptr)
             {
                 m_mapCreateDBThreads[road.nCompareRoadNum] = pThread;
@@ -366,7 +367,7 @@ bool CompareItemThread::getCreateDBThread()
             } else
             {
                 isAllThreadsReady = false;
-                SPDLOG_LOGGER_WARN(m_logger, "{} 获取创建实时音量线程失败,通道: {}:{}", m_logBase, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_WARN(m_logger, "{} 获取创建实时音量线程失败,通道: {}:{}", m_logBase, road.scRoadInfo.strSoundCardName, road.scRoadInfo.pcmInfo.strPCMName);
             }
         }
         if(isAllThreadsReady)
@@ -393,14 +394,14 @@ void CompareItemThread::getRecordThread()
         {
             continue; // 不需要录音的通道,不获取录音线程
         }
-        CreateRecordFileThread* pThread = ThreadMan.getCreateRecordFileThread(road.scRoadInfo.nSoundCardNum, road.scRoadInfo.roadInfo.nRoadNum);
+        CreateRecordFileThread* pThread = ThreadMan.getCreateRecordFileThread(road.scRoadInfo.pcmInfo.strPCMName);
         if(pThread != nullptr)
         {
             m_mapRecordThreads.insert({road.nCompareRoadNum, pThread});
             // SPDLOG_LOGGER_INFO(m_logger, "{} 获取录音线程成功,通道: {}:{}", m_logBase, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
         } else
         {
-            SPDLOG_LOGGER_WARN(m_logger, "{} 获取录音线程失败,通道: {}:{}", m_logBase, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
+            SPDLOG_LOGGER_WARN(m_logger, "{} 获取录音线程失败,通道: {}:{}", m_logBase, road.scRoadInfo.strSoundCardName, road.scRoadInfo.pcmInfo.strPCMName);
         }
     }
 }
@@ -705,16 +706,13 @@ bool CompareItemThread::updateResultData()
         m_compareResult.mapRoadVolumes[pair.first].isConsistency = pThread->isConsistency();
         m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = pThread->isNotConsistencyWarning();
         
-
-        /* 下面这两个条件不会同时设置为true,只会二选一 */
-
         /* 判断是否开启了不一致报警条件: 在其他报警时,不一致不报警且后台不进行不一致对比 */
         if(m_isConsistencyNoWarnWhenOtherAlarm == true)
         {
             /* 有其他报警,不一致不报警,并且暂停计算,直到其他报警结束后再继续计算 */
             if(mapAlarmFlags[pair.first] == true)
             {
-                m_compareResult.mapRoadVolumes[pair.first].isConsistency = false;
+                m_compareResult.mapRoadVolumes[pair.first].isConsistency = true;
                 m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = false;
                 pThread->enableNotConsistencyDetect(false);
                 continue;
@@ -798,8 +796,8 @@ bool CompareItemThread::generateMQTTJsonData(const CompareResult_t& compareResul
         {
             const int roadNum = roadVolume.first;
             nJson json1;
-            json1["soundCard_id"] = roadVolume.second.roadInfo.scRoadInfo.strSoundCardID.toStdString(); /* 声卡id和声卡通道id */
-            json1["soundCard_road_id"] = roadVolume.second.roadInfo.scRoadInfo.roadInfo.nRoadNum;
+            json1["soundCard_name"] = roadVolume.second.roadInfo.scRoadInfo.strSoundCardName;
+            json1["soundCard_road_name"] = roadVolume.second.roadInfo.scRoadInfo.pcmInfo.strPCMName;
             /* 对比项通道编号和名称 */
             json1["item_road_num"] = roadNum;
             json1["item_road_name"] = roadVolume.second.roadInfo.strCompareRoadName.toStdString();
@@ -956,8 +954,7 @@ void CompareItemThread::startOrStopRecord(bool isStart)
         itemRoadInfo.strCompareItemName = m_threadInfo.compareItemInfo.strName;
         itemRoadInfo.nCompareRoadNum = pair.first;
         itemRoadInfo.strCompareRoadName = m_threadInfo.compareItemInfo.mapRoad[pair.first].strCompareRoadName;
-        itemRoadInfo.nSoundCardNum = m_threadInfo.compareItemInfo.mapRoad[pair.first].scRoadInfo.nSoundCardNum;
-        itemRoadInfo.nSoundCardRoadNum = m_threadInfo.compareItemInfo.mapRoad[pair.first].scRoadInfo.roadInfo.nRoadNum;
+        itemRoadInfo.scRoadInfo = m_threadInfo.compareItemInfo.mapRoad[pair.first].scRoadInfo;
         if(isStart)
         {
             pThread->startRecordLongFile(itemRoadInfo);

+ 6 - 6
Server/ThreadCalculate/ConsistencyCompareThread.cpp

@@ -201,8 +201,8 @@ bool ConsistencyCompareThread::initData()
     m_itemRoadInfo2 = it.value(); // 第二个通道
 
     m_logBase = fmt::format("对比通道 {}:{} - {}:{}", 
-                    m_itemRoadInfo1.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum, 
-                    m_itemRoadInfo2.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
+                    m_itemRoadInfo1.scRoadInfo.strSoundCardName, m_itemRoadInfo1.scRoadInfo.pcmInfo.strPCMName, 
+                    m_itemRoadInfo2.scRoadInfo.strSoundCardName, m_itemRoadInfo2.scRoadInfo.pcmInfo.strPCMName);
     
     /* 获取创建wav文件的指针 */
     auto startTime = std::chrono::steady_clock::now(); // 记录开始时间
@@ -210,21 +210,21 @@ bool ConsistencyCompareThread::initData()
     {
         if(m_pCreateWAVThread1 == nullptr)
         {
-            m_pCreateWAVThread1 = ThreadMan.getCreateWAVThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
+            m_pCreateWAVThread1 = ThreadMan.getCreateWAVThread(m_itemRoadInfo1.scRoadInfo.pcmInfo.strPCMName);
         }
         if(m_pCreateWAVThread2 == nullptr)
         {
-            m_pCreateWAVThread2 = ThreadMan.getCreateWAVThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
+            m_pCreateWAVThread2 = ThreadMan.getCreateWAVThread(m_itemRoadInfo2.scRoadInfo.pcmInfo.strPCMName);
         }
         
         /* 获取生成报警音频文件的线程 */
         if(m_threadCreateAlarmFile1 == nullptr)
         {
-            m_threadCreateAlarmFile1 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
+            m_threadCreateAlarmFile1 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo1.scRoadInfo.pcmInfo.strPCMName);
         }
         if(m_threadCreateAlarmFile2 == nullptr)
         {
-            m_threadCreateAlarmFile2 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
+            m_threadCreateAlarmFile2 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo2.scRoadInfo.pcmInfo.strPCMName);
         }
 
         if( m_pCreateWAVThread1 != nullptr && m_pCreateWAVThread2 != nullptr && 

+ 3 - 3
Server/ThreadCalculate/NoiseDetectThread.cpp

@@ -155,7 +155,7 @@ bool NoiseDetectThread::initData()
 {
     auto begin =  m_threadInfo.compareItemInfo.mapRoad.begin(); // 获取第一个通道的信息
     m_roadInfo = begin->scRoadInfo; // 录音通道信息
-    m_roadName = fmt::format("{}:{}", m_roadInfo.strSoundCardID.toStdString(), m_roadInfo.roadInfo.nRoadNum);
+    m_roadName = fmt::format("{}:{}", m_roadInfo.strSoundCardName, m_roadInfo.pcmInfo.strPCMName);
     m_logBase = fmt::format("噪音检测通道 {}:", m_roadName);
 
     /* 获取线程 */
@@ -164,11 +164,11 @@ bool NoiseDetectThread::initData()
     {
         if(m_pThreadWav == nullptr)
         {
-            m_pThreadWav = ThreadMan.getCreateWAVThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum);
+            m_pThreadWav = ThreadMan.getCreateWAVThread(m_roadInfo.pcmInfo.strPCMName);
         }
         if(m_pThreadCreateAlarm == nullptr)
         {
-            m_pThreadCreateAlarm = ThreadMan.getCreateRecordFileThread(m_roadInfo.nSoundCardNum, m_roadInfo.roadInfo.nRoadNum);
+            m_pThreadCreateAlarm = ThreadMan.getCreateRecordFileThread(m_roadInfo.pcmInfo.strPCMName);
         }
         if(m_pThreadWav != nullptr && m_pThreadCreateAlarm != nullptr)
         {

+ 3 - 2
Server/ThreadCalculate/NoiseDetectThread.h

@@ -4,6 +4,7 @@
 
 #include "BaseCalculateThread.h"
 #include "AudioData.h"
+#include "GlobalVariable.h"
 #include "SystemConfig.h"
 #include "RingQueueManualMutex.hpp"
 
@@ -41,7 +42,7 @@ public:
     ~NoiseDetectThread() override;
 
     /* 获取通道信息 */
-    const SoundCardRoadInfo_t& getRoadInfo() const { return m_roadInfo; }
+    const OneSoundCardPCMInfo_t& getRoadInfo() const { return m_roadInfo; }
     /* 获取当前噪音结果 */
     bool isNoise() const { return m_isNoise.load(); }
     /* 获取是否噪音预警 */
@@ -76,7 +77,7 @@ private:
     void endAlarm();
 
 private:
-    SoundCardRoadInfo_t m_roadInfo;                 /* 录音通道编号 */
+    OneSoundCardPCMInfo_t m_roadInfo;               /* 录音通道编号 */
     std::string m_roadName;                         /* 录音通道名称 */
     CreateWAVThread* m_pThreadWav = nullptr;        /* WAV小文件生成线程指针 */
     CreateRecordFileThread * m_pThreadCreateAlarm = nullptr; /* 生成报警文件的线程 */

+ 3 - 3
Server/ThreadManager/ThreadCompareItemManager.cpp

@@ -107,17 +107,17 @@ void ThreadCompareItemManager::addCompareItemThread(CompareItemThread* pThread)
 }
 
 /* 通过对比项ID和通道ID获取声卡通道信息 */
-SoundCardRoadInfo_t ThreadCompareItemManager::getSoundCardRoadInfo(int compareItemID, int roadNum)
+OneSoundCardPCMInfo_t ThreadCompareItemManager::getSoundCardRoadInfo(int compareItemID, int roadNum)
 {
     std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
     auto it  = m_mapThreads.find(compareItemID);
     if(it == m_mapThreads.end())
     {
         SPDLOG_LOGGER_WARN(m_logger, "对比项线程不存在,ID: {}", compareItemID);
-        return SoundCardRoadInfo_t();
+        return OneSoundCardPCMInfo_t();
     }
     auto compareInfo = it.value()->getThreadInfo().compareItemInfo;
-    SoundCardRoadInfo_t roadInfo;
+    OneSoundCardPCMInfo_t roadInfo;
     for(const auto& road : compareInfo.mapRoad)
     {
         if(road.nCompareRoadNum == roadNum)

+ 3 - 1
Server/ThreadManager/ThreadCompareItemManager.h

@@ -2,6 +2,7 @@
 #define __THREADCOMPAREITEMMANAGER_H__
 
 
+#include "GlobalVariable.h"
 #include "spdlog/spdlog.h"
 #include "FromWebAPI.h"
 #include "CompareItemThread.h"
@@ -9,6 +10,7 @@
 #include <QObject>
 #include <QEventLoop>
 #include <QTimer>
+#include <string>
 
 class FromMQTT;
 
@@ -43,7 +45,7 @@ public:
     /* 添加对比项实例 */
     void addCompareItemThread(CompareItemThread* pThread);
     /* 通过对比项ID和通道ID获取声卡通道信息 */
-    SoundCardRoadInfo_t getSoundCardRoadInfo(int compareItemID, int roadNum);
+    OneSoundCardPCMInfo_t getSoundCardRoadInfo(int compareItemID, int roadNum);
     
 
     /*  给对比项套一层壳,这个函数就是新的线程,在里面new出新的对比项实例,防止Qt报线程归属权错误,

+ 171 - 190
Server/ThreadManager/ThreadManager.cpp

@@ -13,6 +13,7 @@
 
 #include "ThreadPool.h"
 #include <mutex>
+#include <string>
 
 ThreadManager::ThreadManager()
 {
@@ -38,16 +39,15 @@ void ThreadManager::stopAllThreads()
 }
 
 /* 创建一个录音通道及其附属的线程 */
-bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID)
+bool ThreadManager::createRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID)
 {
     /* 先查找队列中有没有该录音通道 */
     std::lock_guard<std::mutex> lock(m_mutexRecordThreadRefCount);
     for(const auto& pair : m_mapRecordThreadRefCount)
     {
-        if( pair.first.nSoundCardNum == roadInfo.nSoundCardNum &&
-            pair.first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+        if( pair.first == pcmInfo.pcmInfo.strPCMName)
         {
-            SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 录音线程已存在", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+            SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 录音线程已存在", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
             /*  录音线程已存在,增加引用计数
                 先判断对比项ID是否已经在列表中了 */
             bool idFound = false;
@@ -65,7 +65,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
                 m_mapRecordThreadRefCount[pair.first].push_back(compareItemID);
             }
             SPDLOG_LOGGER_INFO(m_logger, "{}:{} 录音线程引用计数增加,当前计数: {}",
-                roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, m_mapRecordThreadRefCount[pair.first].size());
+                pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName, m_mapRecordThreadRefCount[pair.first].size());
             /* 返回成功 */
             return true;
         }
@@ -75,13 +75,13 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
 
     /* 先创建生成wav小文件数据的线程 */
     RecordThreadInfo_t threadInfo;
-    threadInfo.cardRoadInfo = roadInfo;
+    threadInfo.cardRoadInfo = pcmInfo;
     threadInfo.threadState = EThreadState::State_Inited;
     threadInfo.threadType = EThreadType::Type_CreateWAV;
     CreateWAVThread* pCreateWAVThread = new CreateWAVThread(threadInfo);
     if(pCreateWAVThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成wav小文件线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成wav小文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
         // return false; // 创建失败
     }else 
     {
@@ -96,7 +96,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     CreateDBThread* pCreateDBThread = new CreateDBThread(threadInfo);
     if(pCreateDBThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建计算音量线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建计算音量线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
         // return false; // 创建失败
     }else 
     {
@@ -110,7 +110,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     CreateRecordFileThread* pCreateLongWAVThread = new CreateRecordFileThread(threadInfo);
     if(pCreateLongWAVThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成长文件线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建生成长文件线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
         // return false; // 创建失败
     }else 
     {
@@ -126,7 +126,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     // RTPOneRoadThread* pRtpSendThread = new RTPOneRoadThread(threadInfo);
     // if(pRtpSendThread == nullptr) 
     // {
-    //     SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建发送RTP数据线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+    //     SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建发送RTP数据线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
     // }else 
     // {
     //     CPPTP.add_task(&RTPOneRoadThread::threadTask, pRtpSendThread);
@@ -139,7 +139,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     RecordThread* pRecordThread = new RecordThread(threadInfo);
     if(pRecordThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建录音线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建录音线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
         // return false; // 创建失败
     }else
     {
@@ -153,7 +153,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     AssignSrcDataThread* pAssignSrcDataThread = new AssignSrcDataThread(threadInfo);
     if(pAssignSrcDataThread == nullptr)
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建分派数据线程失败", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "{}:{} 创建分派数据线程失败", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
         // return false; // 创建失败
     }else
     {
@@ -163,7 +163,7 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     }
 
     /* 录音线程创建成功,增加引用计数 */
-    m_mapRecordThreadRefCount[roadInfo].push_back(compareItemID);
+    m_mapRecordThreadRefCount[pcmInfo.pcmInfo.strPCMName].push_back(compareItemID);
 
     return true;
 }
@@ -172,15 +172,14 @@ bool ThreadManager::createRecordThread(const SoundCardRoadInfo_t& roadInfo, int
     销毁一个录音通道及其附属的线程,如果引用计数为0, 这里只停止该录音通道的所有线程,不会删除实例
     线程实例会由其他管理线程定期去删除
  */
-bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID)
+bool ThreadManager::removeRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID)
 {
     std::lock_guard<std::mutex> lock(m_mutexRecordThreadRefCount);
     /* 先查找这个引用计数是否存在 */
     int refCount = 0;
     for(auto& pair : m_mapRecordThreadRefCount)
     {
-        if(pair.first.nSoundCardNum == roadInfo.nSoundCardNum &&
-           pair.first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+        if(pair.first == pcmInfo.pcmInfo.strPCMName)
         {
             /* 找到该引用计数,减少引用计数 */
             for(auto& it : pair.second)
@@ -195,14 +194,13 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
             break;
         }
     }
+    std::string logBase = fmt::format("{}:{}", pcmInfo.strSoundCardName, pcmInfo.pcmInfo.strPCMName);
     if(refCount > 0)
     {
-        SPDLOG_LOGGER_INFO(m_logger, "{}:{} 录音线程引用计数减少,当前计数: {}",
-                roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, refCount);
+        SPDLOG_LOGGER_INFO(m_logger, "{} 录音线程引用计数减少,当前计数: {}", logBase, refCount);
         return true;
     }
-    SPDLOG_LOGGER_INFO(m_logger, "{}:{} 录音线程引用计数为0,即将停止该录音通道的所有线程",
-                roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+    SPDLOG_LOGGER_INFO(m_logger, "{} 录音线程引用计数为0,即将停止该录音通道的所有线程", logBase);
     
     /* 引用计数为0,停止该录音通道的所有线程 */
     /* 停止录音线程 */
@@ -211,11 +209,10 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_recordThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 录音线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 录音线程已停止", logBase);
                 break;
             }
         }
@@ -226,11 +223,10 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_assignSrcDataThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 分派数据线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 分派数据线程已停止", logBase);
                 break;
             }
         }
@@ -241,11 +237,10 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_createWAVThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 生成wav小文件线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 生成wav小文件线程已停止", logBase);
                 break;
             }
         }
@@ -257,11 +252,10 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_createDBThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 计算音量线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 计算音量线程已停止", logBase);
                 break;
             }
         }
@@ -273,11 +267,10 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_createLongWAVThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 生成长文件线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 生成长文件线程已停止", logBase);
                 break;
             }
         }
@@ -289,25 +282,24 @@ bool ThreadManager::removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int
         for(auto it : m_rtpSendThreads)
         {
             const auto& threadInfo = it->getThreadInfo();
-            if(threadInfo.cardRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-               threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+            if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmInfo.pcmInfo.strPCMName)
             {
                 it->stopThread();
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 发送RTP数据线程已停止", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+                SPDLOG_LOGGER_TRACE(m_logger, "{} 发送RTP数据线程已停止", logBase);
                 break;
             }
         }
     }
 
     /* 从引用计数中移除该录音通道 */
-    auto it = m_mapRecordThreadRefCount.find(roadInfo);
+    auto it = m_mapRecordThreadRefCount.find(pcmInfo.pcmInfo.strPCMName);
     if(it != m_mapRecordThreadRefCount.end())
     {
         m_mapRecordThreadRefCount.erase(it);
-        SPDLOG_LOGGER_INFO(m_logger, "{}:{} 录音线程已停止运行", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_INFO(m_logger, "{} 录音线程已停止运行", logBase);
     } else
     {
-        SPDLOG_LOGGER_WARN(m_logger, "{}:{} 录音线程引用计数未找到", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+        SPDLOG_LOGGER_WARN(m_logger, "{} 录音线程引用计数未找到", logBase);
     }
 
     // 设置销毁录音线程标志
@@ -463,7 +455,7 @@ void ThreadManager::destroyeRecordThread()
 
 
 /* 查找录音线程 */
-BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID, int roadID)
+BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, std::string pcmName)
 {
     switch(type)
     {
@@ -472,8 +464,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexRecordThreads);
                 for (auto& pThread : m_recordThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID &&
-                        pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -485,8 +476,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexCreateWAVThreads);
                 for (auto& pThread : m_createWAVThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-                        pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -498,8 +488,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexCreateDBThreads);
                 for (auto& pThread : m_createDBThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-                        pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -511,8 +500,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexCreateLongWAVThreads);
                 for (auto& pThread : m_createLongWAVThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-                        pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -524,8 +512,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexAssignSrcDataThreads);
                 for (auto& pThread : m_assignSrcDataThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-                        pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -537,8 +524,7 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
                 std::lock_guard<std::mutex> lock(m_mutexRtpSendThreads);
                 for (auto& pThread : m_rtpSendThreads)
                 {
-                    if (pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-                        pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+                    if (pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName )
                     {
                         return pThread;
                     }
@@ -556,13 +542,12 @@ BaseRecordThread* ThreadManager::findRecordThread(EThreadType type, int cardID,
 
 
 /* 获取创建WAV线程指针 */
-CreateWAVThread* ThreadManager::getCreateWAVThread(int cardID, int roadID)
+CreateWAVThread* ThreadManager::getCreateWAVThread(std::string pcmName)
 {
     std::lock_guard<std::mutex> lock(m_mutexCreateWAVThreads);
     for(auto& pThread : m_createWAVThreads)
     {
-        if(pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-           pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+        if(pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName)
         {
             return dynamic_cast<CreateWAVThread*>(pThread);
         }
@@ -571,13 +556,12 @@ CreateWAVThread* ThreadManager::getCreateWAVThread(int cardID, int roadID)
 }
 
 /* 获取创建音量值的线程 */
-CreateDBThread* ThreadManager::getCreateDBThread(int cardID, int roadID)
+CreateDBThread* ThreadManager::getCreateDBThread(std::string pcmName)
 {
     std::lock_guard<std::mutex> lock(m_mutexCreateDBThreads);
     for(auto& pThread : m_createDBThreads)
     {
-        if(pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-           pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+        if(pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName)
         {
             return dynamic_cast<CreateDBThread*>(pThread);
         }
@@ -586,14 +570,13 @@ CreateDBThread* ThreadManager::getCreateDBThread(int cardID, int roadID)
 }
 
 /* 获取发送Rtp数据的线程 */
-RTPOneRoadThread* ThreadManager::getRtpSendThread(int cardID, int roadID)
+RTPOneRoadThread* ThreadManager::getRtpSendThread(std::string pcmName)
 {
     std::lock_guard<std::mutex> lock(m_mutexRtpSendThreads);
     for(auto& pThread : m_rtpSendThreads)
     {
         const auto& threadInfo = pThread->getThreadInfo();
-        if(threadInfo.cardRoadInfo.nSoundCardNum == cardID &&
-           threadInfo.cardRoadInfo.roadInfo.nRoadNum == roadID)
+        if(threadInfo.cardRoadInfo.pcmInfo.strPCMName == pcmName)
         {
             return dynamic_cast<RTPOneRoadThread*>(pThread);
         }
@@ -602,13 +585,12 @@ RTPOneRoadThread* ThreadManager::getRtpSendThread(int cardID, int roadID)
 }
 
 /* 获取录制报警文件的线程 */
-CreateRecordFileThread* ThreadManager::getCreateRecordFileThread(int cardID, int roadID)
+CreateRecordFileThread* ThreadManager::getCreateRecordFileThread(std::string pcmName)
 {
     std::lock_guard<std::mutex> lock(m_mutexCreateLongWAVThreads);
     for(auto& pThread : m_createLongWAVThreads)
     {
-        if(pThread->getThreadInfo().cardRoadInfo.nSoundCardNum == cardID &&
-           pThread->getThreadInfo().cardRoadInfo.roadInfo.nRoadNum == roadID)
+        if(pThread->getThreadInfo().cardRoadInfo.pcmInfo.strPCMName == pcmName)
         {
             return dynamic_cast<CreateRecordFileThread*>(pThread);
         }
@@ -695,138 +677,137 @@ CreateRecordFileThread* ThreadManager::getCreateRecordFileThread(int cardID, int
 // }
 
 /* 获取噪音检测线程 */
-NoiseDetectThread* ThreadManager::getNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID)
-{
-    std::lock_guard<std::mutex> lock(m_mutexNoiseDetectThreads);
-    NoiseDetectThread* pNoiseDetectThread = nullptr;
-    for(const auto pThread : m_listNoiseDetectThreads)
-    {
-        const SoundCardRoadInfo_t& threadRoadInfo = pThread->getRoadInfo();
-        if(threadRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-           threadRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
-        {
-            pNoiseDetectThread = pThread;
-            break;
-        }
-    }
-    /* 判断引用计数是否需要增加 */
-    if(pNoiseDetectThread != nullptr)
-    {
-        /* 查找这个通道是否在列表中(实际上肯定在列表中) */
-        bool isExist = false;
-        for(auto it  = m_mapNoiseDetectThreadRefCount.begin(); it != m_mapNoiseDetectThreadRefCount.end(); ++it)
-        {
-            if(it->first.nSoundCardNum == roadInfo.nSoundCardNum &&
-               it->first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
-            {
-                bool isFound = false;
-                for(auto& id : it->second)
-                {
-                    if(id == compareItemID)
-                    {
-                        isFound = true;
-                        break; // 找到相同的对比项ID,直接返回
-                    }
-                }
-                if(!isFound)
-                {
-                    it->second.push_back(compareItemID); // 添加新的对比项ID
-                    SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 噪音检测线程引用计数增加,当前计数: {}",
-                    roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, it->second.size());
-                }
-                isExist = true;
-                break;
-            }
-        }
-        if(!isExist)
-        {
-            /* 不在引用计数的列表中,添加进入 */
-            m_mapNoiseDetectThreadRefCount[roadInfo].push_back(compareItemID);
-        }
-        return pNoiseDetectThread;
-    }
+// NoiseDetectThread* ThreadManager::getNoiseDetectThread(const OneSoundCardPCMInfo_t& roadInfo, int compareItemID)
+// {
+//     std::lock_guard<std::mutex> lock(m_mutexNoiseDetectThreads);
+//     NoiseDetectThread* pNoiseDetectThread = nullptr;
+//     for(const auto pThread : m_listNoiseDetectThreads)
+//     {
+//         const OneSoundCardPCMInfo_t & threadRoadInfo = pThread->getRoadInfo();
+//         if(threadRoadInfo.pcmInfo.strPCMName == roadInfo.pcmInfo.strPCMName)
+//         {
+//             pNoiseDetectThread = pThread;
+//             break;
+//         }
+//     }
+//     /* 判断引用计数是否需要增加 */
+//     if(pNoiseDetectThread != nullptr)
+//     {
+//         /* 查找这个通道是否在列表中(实际上肯定在列表中) */
+//         bool isExist = false;
+//         for(auto it  = m_mapNoiseDetectThreadRefCount.begin(); it != m_mapNoiseDetectThreadRefCount.end(); ++it)
+//         {
+//             if(it->first.roadInfo. == roadInfo.pcmInfo.strPCMName &&
+//                it->first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+//             {
+//                 bool isFound = false;
+//                 for(auto& id : it->second)
+//                 {
+//                     if(id == compareItemID)
+//                     {
+//                         isFound = true;
+//                         break; // 找到相同的对比项ID,直接返回
+//                     }
+//                 }
+//                 if(!isFound)
+//                 {
+//                     it->second.push_back(compareItemID); // 添加新的对比项ID
+//                     SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 噪音检测线程引用计数增加,当前计数: {}",
+//                     roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, it->second.size());
+//                 }
+//                 isExist = true;
+//                 break;
+//             }
+//         }
+//         if(!isExist)
+//         {
+//             /* 不在引用计数的列表中,添加进入 */
+//             m_mapNoiseDetectThreadRefCount[roadInfo].push_back(compareItemID);
+//         }
+//         return pNoiseDetectThread;
+//     }
 
-    /* 没找到该线程,创建新的线程 */
-    CalculateThreadInfo_t threadInfo;
-    CompareItemRoadInfo_t item;
-    item.nCompareRoadNum = 1; // 假设噪音检测线程
-    item.scRoadInfo = roadInfo;
-    threadInfo.compareItemInfo.mapRoad.insert(item.nCompareRoadNum, item);
-    NoiseDetectThread* newThread = new NoiseDetectThread(threadInfo);
-    if(newThread == nullptr)
-    {
-        SPDLOG_LOGGER_ERROR(m_logger, "创建噪音检测线程失败");
-        return nullptr; // 创建失败
-    }
-    CPPTP.add_task(&NoiseDetectThread::threadTask, newThread);
-    m_listNoiseDetectThreads.push_back(newThread);
+//     /* 没找到该线程,创建新的线程 */
+//     CalculateThreadInfo_t threadInfo;
+//     CompareItemRoadInfo_t item;
+//     item.nCompareRoadNum = 1; // 假设噪音检测线程
+//     item.scRoadInfo = roadInfo;
+//     threadInfo.compareItemInfo.mapRoad.insert(item.nCompareRoadNum, item);
+//     NoiseDetectThread* newThread = new NoiseDetectThread(threadInfo);
+//     if(newThread == nullptr)
+//     {
+//         SPDLOG_LOGGER_ERROR(m_logger, "创建噪音检测线程失败");
+//         return nullptr; // 创建失败
+//     }
+//     CPPTP.add_task(&NoiseDetectThread::threadTask, newThread);
+//     m_listNoiseDetectThreads.push_back(newThread);
     
-    /* 不在引用计数的列表中,添加进入 */
-    m_mapNoiseDetectThreadRefCount[roadInfo].push_back(compareItemID);
+//     /* 不在引用计数的列表中,添加进入 */
+//     m_mapNoiseDetectThreadRefCount[roadInfo].push_back(compareItemID);
 
-    return newThread;
-}
+//     return newThread;
+// }
 
 /* 去掉噪音检测线程,线程使用的计数减一,计数为0则销毁该线程 */
-bool ThreadManager::removeNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID)
-{
-    std::lock_guard<std::mutex> lock(m_mutexNoiseDetectThreads);
-    NoiseDetectThread* pThreadToRemove = nullptr;
-    for(const auto pThread : m_listNoiseDetectThreads)
-    {
-        const SoundCardRoadInfo_t& threadRoadInfo = pThread->getRoadInfo();
-        if(threadRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
-           threadRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
-        {
-            pThreadToRemove = pThread; // 找到相同的线程,直接返回
-            break;
-        }
-    }
-    if(pThreadToRemove == nullptr)
-    {
-        SPDLOG_LOGGER_WARN(m_logger, "{}:{} 噪音检测线程未找到", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
-        return false; // 没找到该线程
-    }
+// bool ThreadManager::removeNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID)
+// {
+//     std::lock_guard<std::mutex> lock(m_mutexNoiseDetectThreads);
+//     NoiseDetectThread* pThreadToRemove = nullptr;
+//     for(const auto pThread : m_listNoiseDetectThreads)
+//     {
+//         const SoundCardRoadInfo_t& threadRoadInfo = pThread->getRoadInfo();
+//         if(threadRoadInfo.nSoundCardNum == roadInfo.nSoundCardNum &&
+//            threadRoadInfo.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+//         {
+//             pThreadToRemove = pThread; // 找到相同的线程,直接返回
+//             break;
+//         }
+//     }
+//     if(pThreadToRemove == nullptr)
+//     {
+//         SPDLOG_LOGGER_WARN(m_logger, "{}:{} 噪音检测线程未找到", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+//         return false; // 没找到该线程
+//     }
 
-    /* 引用计数减一 */
-    int useCount = 0;
-    for(auto it = m_mapNoiseDetectThreadRefCount.begin(); it != m_mapNoiseDetectThreadRefCount.end(); ++it)
-    {
-        if(it->first.nSoundCardNum == roadInfo.nSoundCardNum &&
-           it->first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
-        {
-            /* 将对比项ID从列表中删除 */
-            auto& compareItemList = it->second;
-            auto itemIt = std::find(compareItemList.begin(), compareItemList.end(), compareItemID);
-            if(itemIt != compareItemList.end())
-            {
-                compareItemList.erase(itemIt); // 移除该对比项ID
-                SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 噪音检测线程引用计数减少,当前计数: {}",
-                    roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, compareItemList.size());
-            }
-            useCount = compareItemList.size(); // 获取当前引用计数
-            if(useCount <= 0)
-            {
-                m_mapNoiseDetectThreadRefCount.erase(it); // 如果引用计数为0,则从列表中移除
-            }
-            break; // 找到后退出循环
-        }
-    }
+//     /* 引用计数减一 */
+//     int useCount = 0;
+//     for(auto it = m_mapNoiseDetectThreadRefCount.begin(); it != m_mapNoiseDetectThreadRefCount.end(); ++it)
+//     {
+//         if(it->first.nSoundCardNum == roadInfo.nSoundCardNum &&
+//            it->first.roadInfo.nRoadNum == roadInfo.roadInfo.nRoadNum)
+//         {
+//             /* 将对比项ID从列表中删除 */
+//             auto& compareItemList = it->second;
+//             auto itemIt = std::find(compareItemList.begin(), compareItemList.end(), compareItemID);
+//             if(itemIt != compareItemList.end())
+//             {
+//                 compareItemList.erase(itemIt); // 移除该对比项ID
+//                 SPDLOG_LOGGER_TRACE(m_logger, "{}:{} 噪音检测线程引用计数减少,当前计数: {}",
+//                     roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum, compareItemList.size());
+//             }
+//             useCount = compareItemList.size(); // 获取当前引用计数
+//             if(useCount <= 0)
+//             {
+//                 m_mapNoiseDetectThreadRefCount.erase(it); // 如果引用计数为0,则从列表中移除
+//             }
+//             break; // 找到后退出循环
+//         }
+//     }
 
 
-    if(useCount <= 0)
-    {
-        SPDLOG_LOGGER_INFO(m_logger, "{}:{} 噪音检测线程引用计数为0,准备销毁该线程",
-                    roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
-        pThreadToRemove->stopThreadBlock(); // 停止线程
-        m_listNoiseDetectThreads.remove(pThreadToRemove); // 从列表中移除
-        delete pThreadToRemove; // 删除线程
-        pThreadToRemove = nullptr;
-        SPDLOG_LOGGER_INFO(m_logger, "{}:{} 噪音检测线程已销毁", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
-    }
+//     if(useCount <= 0)
+//     {
+//         SPDLOG_LOGGER_INFO(m_logger, "{}:{} 噪音检测线程引用计数为0,准备销毁该线程",
+//                     roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+//         pThreadToRemove->stopThreadBlock(); // 停止线程
+//         m_listNoiseDetectThreads.remove(pThreadToRemove); // 从列表中移除
+//         delete pThreadToRemove; // 删除线程
+//         pThreadToRemove = nullptr;
+//         SPDLOG_LOGGER_INFO(m_logger, "{}:{} 噪音检测线程已销毁", roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
+//     }
 
-    return true;
-}
+//     return true;
+// }
 
 
 
@@ -903,7 +884,7 @@ void ThreadManager::thread_RTPSend(RecordThreadInfo_t& threadInfo)
     RTPOneRoadThread* pRtpSendThread = new RTPOneRoadThread(threadInfo);
     if(pRtpSendThread == nullptr)
     {
-        SPDLOG_ERROR("{}:{} 创建RTP发送线程失败", threadInfo.cardRoadInfo.strSoundCardName.toStdString(), threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+        SPDLOG_ERROR("{}:{} 创建RTP发送线程失败", threadInfo.cardRoadInfo.strSoundCardName, threadInfo.cardRoadInfo.pcmInfo.strPCMName);
         return;
     }
     /* 先加入队列,再开启线程 */

+ 15 - 14
Server/ThreadManager/ThreadManager.h

@@ -11,6 +11,7 @@
 
 #include <list>
 #include <mutex>
+#include <string>
 
 class CreateWAVThread;
 class ConsistencyCompareThread;
@@ -53,9 +54,9 @@ public:
         注意,这里只会停止线程运行,删除线程实例由其他管理线程来完成
      * -------------------------------------------------------------------------------------------- */
     /* 创建一个录音通道及其附属的线程 */
-    bool createRecordThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID);
+    bool createRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID);
     /* 移除一个录音通道一个录音通道及其附属的线程 */
-    bool removeRecordThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID);
+    bool removeRecordThread(const OneSoundCardPCMInfo_t& pcmInfo, int compareItemID);
     /* 获取是否需要销毁录音线程实例 */
     bool isDestroyeRecordThread() const { return m_isDestroyeRecordThread.load(); }
     /* 销毁录音线程,由外部的管理线程调用 */
@@ -67,17 +68,17 @@ public:
      * 获取录音线程,录音线程是统一创建的,有一路录音通道,就会有所有的对应的录音处理线程
      * -------------------------------------------------------------------------------------------- */
     /* 查找录音线程,给原始音频分派数据的线程使用的 */
-    BaseRecordThread* findRecordThread(EThreadType type, int cardID, int roadID);
+    BaseRecordThread* findRecordThread(EThreadType type, std::string pcmName);
     
     /* 这三个线程给对比项以及其附属的计算线程使用的 */
     /* 获取创建WAV线程指针 */
-    CreateWAVThread* getCreateWAVThread(int cardID, int roadID);
+    CreateWAVThread* getCreateWAVThread(std::string pcmName);
     /* 获取创建音量值的线程 */
-    CreateDBThread* getCreateDBThread(int cardID, int roadID);
+    CreateDBThread* getCreateDBThread(std::string pcmName);
     /* 获取发送Rtp数据的线程 */
-    RTPOneRoadThread* getRtpSendThread(int cardID, int roadID);
+    RTPOneRoadThread* getRtpSendThread(std::string pcmName);
     /* 获取录制报警文件的线程 */
-    CreateRecordFileThread* getCreateRecordFileThread(int cardID, int roadID);
+    CreateRecordFileThread* getCreateRecordFileThread(std::string pcmName);
 
     /* -------------------------------------------------------------------------------------------
      * 获取计算线程,如果该线程不存在则创建该线程
@@ -92,9 +93,9 @@ public:
     // bool removeConsistencyCompareThread(SoundCardRoadInfo_t& roadInfo1, SoundCardRoadInfo_t& roadInfo2);
 
     /* 获取噪音检测线程,如果不存在,则创建线程 */
-    NoiseDetectThread* getNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID);
+    // NoiseDetectThread* getNoiseDetectThread(const OneSoundCardPCMInfo_t & roadInfo, int compareItemID);
     /* 去掉噪音检测线程,线程使用的计数减一,计数为0则销毁该线程 */
-    bool removeNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID);
+    // bool removeNoiseDetectThread(const SoundCardRoadInfo_t& roadInfo, int compareItemID);
 
     // /* 获取音量报警线程,如果不存在,则创建线程 */
     // CalculateDBPhaseThread* getCalculateDBPhaseThread(const SoundCardRoadInfo_t& roadInfo);
@@ -108,9 +109,9 @@ private:
     
 
 private:
-    /* 记录每个录音通道的引用计数 */
+    /* 记录每个录音通道的引用计数,key是PCM通道名,在系统中是唯一的 */
     std::mutex m_mutexRecordThreadRefCount;
-    std::map<SoundCardRoadInfo_t, std::list<int>> m_mapRecordThreadRefCount;
+    std::map<std::string, std::list<int>> m_mapRecordThreadRefCount;
 
     /* 录音线程队列 */
     std::mutex m_mutexRecordThreads;
@@ -137,10 +138,10 @@ private:
     // std::list<ConsistencyCompareThread*> m_listConsistencyCompareThreads;
 
     /* 噪音检测线程 */
-    std::mutex m_mutexNoiseDetectThreads;           /* 互斥锁,保护噪音检测线程列表 */
+    // std::mutex m_mutexNoiseDetectThreads;           /* 互斥锁,保护噪音检测线程列表 */
     /* 噪音检测线程的引用计数,键是录音通道,值是对比项ID集合 */
-    std::map<SoundCardRoadInfo_t, std::list<int>> m_mapNoiseDetectThreadRefCount; 
-    std::list<NoiseDetectThread*> m_listNoiseDetectThreads;
+    // std::map<SoundCardRoadInfo_t, std::list<int>> m_mapNoiseDetectThreadRefCount; 
+    // std::list<NoiseDetectThread*> m_listNoiseDetectThreads;
 
     /* 音量计算线程 */
     // std::mutex m_mutexCalculateDBPhaseThreads;   /* 互斥锁,保护音量计算线程列表 */

+ 5 - 5
Server/ThreadRecord/AssignSrcDataThread.cpp

@@ -227,28 +227,28 @@ bool AssignSrcDataThread::getDispatchThread()
     /* 根据生成数据文件的类型顺序获取,循环获取,直到所有的线程都获取到 */
 
     /* 先获取生成wav小文件的线程 */
-    auto pWavThread = ThreadMan.findRecordThread(EThreadType::Type_CreateWAV, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    auto pWavThread = ThreadMan.findRecordThread(EThreadType::Type_CreateWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     if(pWavThread != nullptr)
     {
         // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pWavThread));
         m_pThreadCreateWAV = dynamic_cast<CreateWAVThread*>(pWavThread);
     }
     /* 获取生成音量和反相数据的线程 */
-    auto pDBAndPhaseThread = ThreadMan.findRecordThread(EThreadType::Type_CreateDB, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    auto pDBAndPhaseThread = ThreadMan.findRecordThread(EThreadType::Type_CreateDB, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     if(pDBAndPhaseThread != nullptr)
     {
         // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pDBAndPhaseThread));
         m_pThreadCreateDB = dynamic_cast<CreateDBThread*>(pDBAndPhaseThread);
     }
     /* 获取生成长文件的线程 */
-    auto pLongFileThread = ThreadMan.findRecordThread(EThreadType::Type_CreateLongWAV, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    auto pLongFileThread = ThreadMan.findRecordThread(EThreadType::Type_CreateLongWAV, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     if(pLongFileThread != nullptr )
     {
         // m_listDispatchThreads.push_back(dynamic_cast<BaseRecordThread*>(pLongFileThread));
         m_pThreadCreateLongFile = dynamic_cast<CreateRecordFileThread*>(pLongFileThread);
     }
     /* 获取发送RTP数据的线程 */
-    m_rtpSenderThread = ThreadMan.findRecordThread(EThreadType::Type_RtpSend, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    m_rtpSenderThread = ThreadMan.findRecordThread(EThreadType::Type_RtpSend, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     if(m_rtpSenderThread == nullptr)
     {
         // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取RTP发送线程失败", m_logBase);
@@ -258,7 +258,7 @@ bool AssignSrcDataThread::getDispatchThread()
     /* 最后获取录音线程信息,如果获取不到则一直获取 */
     while(true)
     {
-        auto pThreadBase = ThreadMan.findRecordThread(EThreadType::Type_RecordSrc, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+        auto pThreadBase = ThreadMan.findRecordThread(EThreadType::Type_RecordSrc, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
         if(pThreadBase != nullptr)
         {
             m_pThreadRecord = dynamic_cast<RecordThread*>(pThreadBase);

+ 13 - 128
Server/ThreadRecord/AudioRecord/AudioRecord.cpp

@@ -80,6 +80,9 @@ bool AudioDevice::getAudioDevices(std::list<AudioDevice_t> &devices)
 	return true;
 }
 
+
+
+
 bool AudioDevice::getPCMAudioDevice(std::list<AudioDeviceDesc_t> &devices)
 {
 	void **hints;
@@ -125,134 +128,16 @@ bool AudioDevice::getPCMAudioDevice(std::list<AudioDeviceDesc_t> &devices)
 	return true;
 }
 
-// void record(std::string deviceName)
-// {
-// 	int32_t sample_rate = 44100;
-// 	int32_t channels = 2;
-// 	int i;
-// 	int err;
-
-// 	long unsigned int rframes = 44100; // 每次读取的帧数
-// 	short* buf = (short*)malloc(rframes * sizeof(short) * channels);
-// 	if (!buf) {
-// 		fprintf(stderr, "Failed to allocate buffer memory\n");
-// 		exit(1);
-// 	}
-// 	snd_pcm_t *capture_handle;
-// 	snd_pcm_hw_params_t *hw_params;
-
-// 	if ((err = snd_pcm_open (&capture_handle, deviceName.c_str(), SND_PCM_STREAM_CAPTURE, 0)) < 0) {
-// 		fprintf (stderr, "cannot open audio device %s (%s)\n", 
-// 			 deviceName.c_str(),
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 给参数分配内存 */
-// 	if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
-// 		fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 初始化硬件参数结构 */
-// 	if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) {
-// 		fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 设置硬件参数 */
-// 	if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
-// 		fprintf (stderr, "cannot set access type (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 设置采样格式 */
-// 	// SND_PCM_FORMAT_S16_LE: 16位小端格式
-// 	// SND_PCM_FORMAT_FLOAT_LE: 32位小端浮点格式
-// 	// SND_PCM_FORMAT_U8: 8位无符号格式
-// 	// SND_PCM_FORMAT_S32_LE: 32位小端整数格式
-// 	// SND_PCM_FORMAT_S24_LE: 24位小端整数格式
-// 	if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
-// 		fprintf (stderr, "cannot set sample format (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 设置采样率 */
-// 	if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, &sample_rate, 0)) < 0) {
-// 		fprintf (stderr, "cannot set sample rate (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 设置通道数 */
-// 	if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, channels)) < 0) {
-// 		fprintf (stderr, "cannot set channel count (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 设置交错模式 */
-// 	err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
-// 	if (err < 0) {
-// 		fprintf(stderr, "cannot set interleaved mode (%s)\n", snd_strerror(err));
-// 		exit(1);
-// 	}
-// 	/* 设置周期大小 */
-// 	err = snd_pcm_hw_params_set_period_size(capture_handle, hw_params, 882, 0);
-// 	if (err < 0) {
-// 		fprintf(stderr, "cannot set period size (%s)\n", snd_strerror(err));
-// 		exit(1);
-// 	}
-// 	/* 设置缓冲区大小 */
-// 	err = snd_pcm_hw_params_set_buffer_size(capture_handle, hw_params, 8820);
-// 	if (err < 0) {
-// 		fprintf(stderr, "cannot set buffer size (%s)\n", snd_strerror(err));
-// 		exit(1);
-// 	}
-// 	/* 设置参数给声卡 */
-// 	if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) {
-// 		fprintf (stderr, "cannot set parameters (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	/* 释放参数内存 */
-// 	snd_pcm_hw_params_free (hw_params);
-
-// 	if ((err = snd_pcm_prepare (capture_handle)) < 0) {
-// 		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
-// 			 snd_strerror (err));
-// 		exit (1);
-// 	}
-// 	auto f1 = fopen("r1.wav", "wb");
-// 	if(!f1) {
-// 		fprintf(stderr, "Failed to open file for writing\n");
-// 		exit(1);
-// 	}
-// 	std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
-// 	for (i = 0; i < 10; ++i) 
-// 	{
-// 		long unsigned int readNum;
-// 		start_time = std::chrono::steady_clock::now();
-// 		if ((readNum = snd_pcm_readi (capture_handle, buf, rframes)) != rframes) {
-// 			fprintf (stderr, "read from audio interface failed (%s)\n",
-// 				 snd_strerror (readNum));
-// 			exit (1);
-// 		}
-// 		auto end_time = std::chrono::steady_clock::now();
-// 		auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
-// 		SPDLOG_DEBUG("第 {} 次录音,读取数据量: {} 帧,{} 字节,耗时: {} 毫秒", i + 1, readNum, readNum, duration.count());
-
-// 		if (fwrite(buf, sizeof(short), readNum * 2, f1) != readNum * 2) {
-// 			fprintf(stderr, "Failed to write data to file\n");
-// 			fclose(f1);
-// 			exit(1);
-// 		}
-// 	}
-// 	fclose(f1);
-
-// 	snd_pcm_close (capture_handle);
-// 	free(buf);
-// 	printf("录音完成,数据已保存到 r1.wav\n");
-
-// 	exit (0);
-// }
+
+/* 打印声卡字符设备,设置对齐 */
+void AudioDevice::printPCMAudioDevice(const std::list<AudioDeviceDesc_t> &devices)
+{
+	for (const auto &device : devices)
+	{
+		SPDLOG_INFO("设备名称: {}, IOID: {}, 声卡: {}, 通道编号: {}, 设备描述: {}",
+			device.DeviceName, device.IOID, device.Card, device.DevNum, device.DeviceDesc);
+	}
+}
 
 
 

+ 2 - 1
Server/ThreadRecord/AudioRecord/AudioRecord.h

@@ -69,7 +69,8 @@ namespace AudioDevice
     bool getAudioDevices(std::list<AudioDevice_t> &devices);
     /* 获取声卡字符设备名称,可以直接被打开 */
     bool getPCMAudioDevice(std::list<AudioDeviceDesc_t> &devices);
-
+    /* 打印声卡字符设备 */
+    void printPCMAudioDevice(const std::list<AudioDeviceDesc_t> &devices);
 }
 
 /**

+ 3 - 4
Server/ThreadRecord/BaseRecordThread.cpp

@@ -13,8 +13,7 @@ BaseRecordThread::BaseRecordThread(RecordThreadInfo_t& threadInfo)
         return;
     }
 
-    m_logBase = fmt::format("录音通道: {}:{}", m_threadInfo.cardRoadInfo.strSoundCardName.toStdString(), 
-                            m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+   
 }
 
 BaseRecordThread::~BaseRecordThread()
@@ -27,8 +26,8 @@ BaseRecordThread::~BaseRecordThread()
 void BaseRecordThread::threadTask()
 {
     m_isRunning.store(true);
-    m_logBase = fmt::format("录音通道: {}:{}", m_threadInfo.cardRoadInfo.strSoundCardName.toStdString(), 
-                            m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    m_logBase = fmt::format("录音通道: {}:{}", m_threadInfo.cardRoadInfo.strSoundCardName, 
+                            m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
 
     m_threadInfo.threadState = EThreadState::State_Running;
 

+ 54 - 40
Server/ThreadRecord/CreateDBThread.cpp

@@ -39,9 +39,10 @@ bool CreateDBThread::setData(const AudioSrcData& srcData)
     {
         /* 出队一个最早的元素 */
         AudioSrcData* oldData = m_queueAudioData.front_pop();
-        SPDLOG_LOGGER_WARN(m_logger, "{} 环形队列已满,出队一个元素,时间: {}, 大小: {}", 
+        SPDLOG_LOGGER_TRACE(m_logger, "{} 环形队列已满,出队一个元素,时间: {}, 大小: {}", 
             m_logBase, oldData->startTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), oldData->dataSize);
-        if(oldData != nullptr){
+        if(oldData != nullptr)
+        {
             delete oldData;
             oldData = nullptr;
         }
@@ -335,41 +336,7 @@ void CreateDBThread::task()
         /*--------------------------------------------------------------
         * 计算常规音量值,1秒计算一次
         *--------------------------------------------------------------*/
-        /* 判断是否够一秒的数据 */
-        if(m_queueAudioData.isEmpty())
-        {
-            continue;
-        }
-
-        auto audioData = m_queueAudioData.front_pop();
-
-        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;
+        calculateVolumeData();
         
         // std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
         // std::chrono::microseconds duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - rtEndTime);
@@ -444,7 +411,7 @@ bool CreateDBThread::CreateDBPhase(AudioSrcData* audioData)
     const int oneDBSize = m_oneDBLengthOfSrcData;
 
     StAudioNum audioInfo;
-    audioInfo.roadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
+    audioInfo.cardRoadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
     audioInfo.nTotal = m_singleDataLength;
     int iCurPos = 0;
     /* 存储结果 */
@@ -484,6 +451,50 @@ bool CreateDBThread::CreateDBPhase(AudioSrcData* audioData)
 }
 
 
+/* 计算音量数据 */
+bool CreateDBThread::calculateVolumeData()
+{
+    /* 判断是否够一秒的数据 */
+    if(m_queueAudioData.isEmpty())
+    {
+        return false;;
+    }
+
+    auto audioData = m_queueAudioData.front_pop();
+
+    if(audioData == nullptr)
+    {
+        SPDLOG_LOGGER_WARN(m_logger, "{} 从环形队列中取出数据失败,可能是队列为空", m_logBase);
+        // std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待一段时间再尝试
+        return false;;
+    }
+    /* 计算音量和反相,结果存储在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;
+
+    return true;
+}
+
+
+
 /* 计算实时音量值 */
 bool CreateDBThread::calculateRealTimeVolume()
 {
@@ -502,7 +513,7 @@ bool CreateDBThread::calculateRealTimeVolume()
         /* 计算音量和反相的计算类 */
         CAudio2ChanCorrelator audioCor;
         StAudioNum audioInfo;
-        audioInfo.roadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
+        audioInfo.cardRoadInfo = m_threadInfo.cardRoadInfo; // 设置通道信息
         audioInfo.nTotal = m_singleDataLength;
 
         short* pData = reinterpret_cast<short*>(audioData->pData);
@@ -541,7 +552,10 @@ bool CreateDBThread::calculateRealTimeVolume()
             /* 超过最大数量,删除最早的一个 */
             m_listRealTimeResult.pop_front();
         }
-        
+
+        /* 删除元素内存 */
+        delete audioData;
+        audioData = nullptr;
     }
 
     return true;

+ 5 - 0
Server/ThreadRecord/CreateDBThread.h

@@ -50,9 +50,14 @@ private:
     /* 计算音量和反相 */
     bool CreateDBPhase(AudioSrcData* audioData);
 
+    /* 计算音量数据 */
+    bool calculateVolumeData();
+
+
     /* 计算实时音量值 */
     bool calculateRealTimeVolume();
 
+    
 private:
 
     /* --------------------------- 正常音量值的数据 --------------------------- */

+ 10 - 12
Server/ThreadRecord/CreateRecordFileThread.cpp

@@ -97,8 +97,8 @@ bool CreateRecordFileThread::setData(const AudioSrcData& srcData)
 /* 开始录制长文件 */
 bool CreateRecordFileThread::startRecordLongFile(const OneCompareItemRoadInfo_t& compareItemRoadInfo)
 {
-    if(compareItemRoadInfo.nSoundCardNum != m_threadInfo.cardRoadInfo.nSoundCardNum ||
-       compareItemRoadInfo.nSoundCardRoadNum != m_threadInfo.cardRoadInfo.roadInfo.nRoadNum)
+    if(compareItemRoadInfo.scRoadInfo.strSoundCardName != m_threadInfo.cardRoadInfo.strSoundCardName ||
+       compareItemRoadInfo.scRoadInfo.pcmInfo.strPCMName != m_threadInfo.cardRoadInfo.pcmInfo.strPCMName)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "{} 开始录制音频文件失败,通道信息不匹配", m_logBase);
         return false;
@@ -117,8 +117,8 @@ bool CreateRecordFileThread::startRecordLongFile(const OneCompareItemRoadInfo_t&
 /* 停止录制长文件 */
 bool CreateRecordFileThread::stopRecordLongFile(const OneCompareItemRoadInfo_t& compareItemRoadInfo)
 {
-    if(compareItemRoadInfo.nSoundCardNum != m_threadInfo.cardRoadInfo.nSoundCardNum ||
-       compareItemRoadInfo.nSoundCardRoadNum != m_threadInfo.cardRoadInfo.roadInfo.nRoadNum)
+    if(compareItemRoadInfo.scRoadInfo.strSoundCardName != m_threadInfo.cardRoadInfo.strSoundCardName ||
+       compareItemRoadInfo.scRoadInfo.pcmInfo.strPCMName != m_threadInfo.cardRoadInfo.pcmInfo.strPCMName)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "{} 结束录制音频文件失败,通道信息不匹配", m_logBase);
         return false;
@@ -242,8 +242,7 @@ void CreateRecordFileThread::task()
 bool CreateRecordFileThread::initData()
 {
     m_logBase = fmt::format("录音通道 {}:{} - 记录长文件线程", 
-        m_threadInfo.cardRoadInfo.strSoundCardName.toStdString(),
-        m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+        m_threadInfo.cardRoadInfo.strSoundCardName, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     /* 获取全局数据 */
     m_sampleRate = GInfo.sampleRate();          /* 采样率 */
     m_numChannels = GInfo.numChannels();        /* 声道数 */
@@ -435,8 +434,8 @@ bool CreateRecordFileThread::setTodayPath(bool isNewFile)
     /* 创建这个通道的文件夹,文件夹格式: AudioPCI-0 */
     QString roadDirName = QString("%1/%2-%3")
         .arg(todayDirName)
-        .arg(m_threadInfo.cardRoadInfo.strSoundCardID)
-        .arg(QString::number(m_threadInfo.cardRoadInfo.roadInfo.nRoadNum));
+        .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.strSoundCardName))
+        .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName));
     m_todayDir.setPath(roadDirName);
     if(!m_todayDir.exists())
     {
@@ -505,8 +504,8 @@ QString CreateRecordFileThread::generateFileName(const QDateTime& startTime, con
     // SPDLOG_LOGGER_DEBUG(m_logger, "{} 生成文件名: 开始时间: {}, 结束时间: {}", 
     //     m_logBase, startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
     //     endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-    QString chnannelStr = QString("%1-%2").arg(m_threadInfo.cardRoadInfo.strSoundCardID)
-                                            .arg(QString::number(m_threadInfo.cardRoadInfo.roadInfo.nRoadNum));
+    QString chnannelStr = QString("%1-%2").arg(QString::fromStdString(m_threadInfo.cardRoadInfo.strSoundCardName))
+                                            .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName));
     QString fileName = QString("%1_%2-%3.wav")
         .arg(chnannelStr)
         .arg(startTime.toString("yyyyMMdd_hhmmss"))
@@ -551,8 +550,7 @@ void CreateRecordFileThread::updateRecordFileInfoToDB(bool isNewFile, bool isRec
         recordFileInfo.ItemName = it.strCompareItemName;
         recordFileInfo.ItemRoadNum = it.nCompareRoadNum;
         recordFileInfo.ItemRoadName = it.strCompareRoadName;
-        recordFileInfo.SoundCardNum = it.nSoundCardNum;
-        recordFileInfo.SoundCardRoadNum = it.nSoundCardRoadNum;
+        recordFileInfo.scRoadInfo = it.scRoadInfo;
 
         recordFileInfo.FileStartTime = m_writtenStartTime;
         recordFileInfo.FileEndTime = m_writtenNowTime;

+ 3 - 3
Server/ThreadRecord/CreateRecordFileThread.h

@@ -164,10 +164,10 @@ private:
     QList<OneCompareItemRoadInfo_t> m_listCompareItemRoadInfo;
     std::atomic_bool m_isRequireRecord = false;    /* 是否需要录音 */
 
-    /* 临时缓存数据, 一分钟写入一次,给这个分配2分钟的数据大小 */
+    /* 临时缓存数据, 一定时间写一次,分配两倍的大小 */
     std::mutex m_mutexBuffer;
-    AudioSrcData m_bufferData;              /* 音频数据缓冲区,存储写入的1分钟数据 */
-    AudioSrcData m_srcData;                 /* 当前的音频数据,满一分钟后会拷贝到这里,然后写入数据,防止写入的时候阻塞缓冲区 */
+    AudioSrcData m_bufferData;              /* 音频数据缓冲区 */
+    AudioSrcData m_srcData;                 /* 当前的音频数据,满一定时间后会拷贝到这里,然后写入数据,防止写入的时候阻塞缓冲区 */
 
     int32_t m_writeCriticalSize = 0;        /* 写入文件的临界大小,单位:字节,缓存超过这个大小就写入文件 */
     int32_t m_oneHourSize = 0;              /* 一小时的音频数据大小 */

+ 6 - 7
Server/ThreadRecord/CreateWAVThread.cpp

@@ -6,6 +6,7 @@
 
 #include <QFile>
 #include <QDir>
+#include <qchar.h>
 #include <random>
 
 
@@ -60,18 +61,15 @@ bool CreateWAVThread::setData(const AudioSrcData& srcData)
 
     /* -------------------------- 入队LeftRight环形队列 ---------------------------- */
     AudioSrcData* newData2 = new AudioSrcData(srcData);
-    if(!m_queueLeftRightSrcData.isFull())
-    {
-        m_queueLeftRightSrcData.push(newData2);
-    } else
+    if(m_queueLeftRightSrcData.isFull())
     {
         AudioSrcData* oldData = m_queueLeftRightSrcData.front_pop();
         SPDLOG_LOGGER_TRACE(m_logger, "{} 左右声道环形队列已满,出队一个元素,时间: {}, 大小: {}", 
             m_logBase, oldData->startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), oldData->dataSize);
         delete oldData;
         oldData = nullptr;
-        m_queueLeftRightSrcData.push(newData2);
     }
+    m_queueLeftRightSrcData.push(newData2);
 
     return true;
 }
@@ -201,7 +199,8 @@ bool CreateWAVThread::initData()
 
     
     QString wavPath = GInfo.wavPath();
-    wavPath = wavPath + QString("/Record%1-%2").arg(m_threadInfo.cardRoadInfo.nSoundCardNum).arg(m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    wavPath = wavPath + QString("/Record_%1-%2").arg(QString::fromStdString(m_threadInfo.cardRoadInfo.strSoundCardName))
+                                                .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName));
     m_wavDir.setPath(wavPath);
     if(!m_wavDir.exists())
     {
@@ -268,7 +267,7 @@ bool CreateWAVThread::createWAVFile(int secondCount)
     }
     newFileStartTime = audioData->startTime; // 获取开始时间
     QString strFileName = QString("WAV_%1-%2_%3.wav")
-        .arg(m_threadInfo.cardRoadInfo.nSoundCardNum).arg(m_threadInfo.cardRoadInfo.roadInfo.nRoadNum)
+        .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.strSoundCardName)).arg(QString::fromStdString(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName))
         .arg(newFileStartTime.toString("yyyyMMdd_hhmmss"));
     QString fileName = m_wavDir.filePath(strFileName);
 

+ 5 - 3
Server/ThreadRecord/RecordThread.cpp

@@ -152,7 +152,7 @@ bool RecordThread::initData()
 
     /* 设置声卡描述符 */
     // m_audioRecordDesc = fmt::format("hw:{},{}", m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
-    m_audioRecordDesc = fmt::format("plughw:{},{}", m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    m_audioRecordDesc = m_threadInfo.cardRoadInfo.pcmInfo.strPCMName;
 
 
     return true;
@@ -173,7 +173,7 @@ void RecordThread::clearData()
 /* 获取AssignSrcDataThread线程 */
 AssignSrcDataThread* RecordThread::getAssignSrcDataThread()
 {
-    auto pThread = ThreadMan.findRecordThread(EThreadType::Type_AssignSrcData, m_threadInfo.cardRoadInfo.nSoundCardNum, m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+    auto pThread = ThreadMan.findRecordThread(EThreadType::Type_AssignSrcData, m_threadInfo.cardRoadInfo.pcmInfo.strPCMName);
     if(pThread != nullptr)
     {
         return dynamic_cast<AssignSrcDataThread*>(pThread);
@@ -185,7 +185,9 @@ AssignSrcDataThread* RecordThread::getAssignSrcDataThread()
 void RecordThread::testOpenData()
 {
     QString strFileName = QString("%1-%2.wav")
-        .arg(m_threadInfo.cardRoadInfo.nSoundCardNum).arg(m_threadInfo.cardRoadInfo.roadInfo.nRoadNum);
+        .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.strSoundCardName))
+        .arg(QString::fromStdString(m_threadInfo.cardRoadInfo.pcmInfo.strPCMName));
+    strFileName = GInfo.wavPath() + "/" + strFileName;
     QFile wavFile;
     wavFile.setFileName(strFileName);
     if(!wavFile.open(QIODevice::ReadOnly))

+ 5 - 61
Server/main.cpp

@@ -13,10 +13,10 @@
 #include <QDir>
 #include <QFile>
 
-void test();
-void test1();
 
-void LoadLibrary();
+
+
+
 
 int main(int argc, char* argv[])
 {
@@ -52,7 +52,8 @@ int main(int argc, char* argv[])
     /* 初始化一些系统信息 */
     if(!acas.initGlobalInfo())
     {
-        SPDLOG_LOGGER_ERROR(logger, "ACAServer 初始化失败!");
+        SPDLOG_LOGGER_ERROR(logger, "ACAServer 初始化失败! 即将退出程序");
+        return -1;
     }
 
     /* 启动服务 */
@@ -75,60 +76,3 @@ int main(int argc, char* argv[])
 }
 
 
-void test()
-{
-    QString appDataPath = QCoreApplication::applicationDirPath() + "/testDir";
-    QDir dir;
-    dir.setPath(appDataPath);
-    if (!dir.exists()) {
-        if(dir.mkpath(appDataPath))
-        {
-            SPDLOG_INFO("Directory created: {}", dir.absolutePath().toStdString());
-        }
-        else
-        {
-            SPDLOG_ERROR("Failed to create directory: {}", dir.absolutePath().toStdString());
-            return;
-        }
-    }
-    SPDLOG_INFO("当前文件夹: {}", dir.absolutePath().toStdString());
-    // dir.setCurrent(appDataPath);
-    QFile file(dir.filePath("test.txt"));
-    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-        file.write("Hello, World!");
-        file.close();
-    } else {
-        SPDLOG_INFO("Failed to create file: {}", file.errorString().toStdString());
-    }
-    SPDLOG_INFO("Current directory: {}", dir.absolutePath().toStdString());
-    SPDLOG_INFO("File created at: {}", file.fileName().toStdString());
-    if(QFile::rename(file.fileName(), dir.filePath("test3.txt")))
-    {
-        SPDLOG_INFO("File renamed successfully to: {}", dir.filePath("test3.txt").toStdString());
-    }
-    else
-    {
-        SPDLOG_ERROR("Failed to rename file: {}", file.errorString().toStdString());
-    }
-}
-
-void test1()
-{
-    
-    QFile file("test1.txt");
-    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-        file.write("Hello, World!");
-        file.close();
-        SPDLOG_INFO("File created successfully: {}", file.fileName().toStdString());
-    } else {
-        SPDLOG_ERROR("Failed to create file: {}", file.errorString().toStdString());
-    }
-    
-    SPDLOG_INFO("File path: {}", file.fileName().toStdString());
-    SPDLOG_INFO("Current working directory: {}", QDir::currentPath().toStdString());
-
-    QFile::rename("test1.txt", "test2.txt");
-
-}
-
-

+ 3 - 0
SettingLibrary/CMakeLists.txt

@@ -20,6 +20,8 @@ file(GLOB LOCAL_SRC
     ${CMAKE_SOURCE_DIR}/common/Network/*.cpp
     ${CMAKE_SOURCE_DIR}/common/GlobalInfo/*.cpp
 
+    ${CMAKE_SOURCE_DIR}/Server/ThreadRecord/AudioRecord/*.cpp
+
     ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc
     ${CMAKE_CURRENT_SOURCE_DIR}/*.rc
     ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
@@ -87,6 +89,7 @@ target_include_directories(${libName} PRIVATE
     ${CMAKE_SOURCE_DIR}/common/DataManager
     ${CMAKE_SOURCE_DIR}/common/Network
     ${CMAKE_SOURCE_DIR}/common/GlobalInfo
+    ${CMAKE_SOURCE_DIR}/Server/ThreadRecord/AudioRecord
 
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_SOURCE_DIR}/common

+ 28 - 14
SettingLibrary/Modules/Basic/basicwidget.cpp

@@ -11,6 +11,7 @@
 #include "GlobalInfo.h"
 #include "SoundCardData.h"
 
+#include <qchar.h>
 #include <string>
 
 
@@ -59,15 +60,17 @@ BasicWidget::BasicWidget(QWidget *parent) :
     ui->label_5->hide();
     ui->comBox_notConsistency->hide();
 
-    /* 设置从数据库读取到的选项 */
-    restoreBasicSettingInfo();
-
+    
     /* 连接信号和槽 */
     connect(ui->comBox_driverName, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &BasicWidget::do_soundCardChanged);
     connect(ui->pBtn_restore, &QPushButton::clicked, this, &BasicWidget::do_pBtn_restore_clicked);
+    connect(ui->checkBox_enableSoundCardName, &QCheckBox::clicked, this, &BasicWidget::do_checkBox_showSoundCardDesc_clicked);
+    
     /* 设置声卡信息 */
     setSoundCardInfo();
-    
+
+    /* 设置从数据库读取到的选项 */
+    restoreBasicSettingInfo();
 }
 
 BasicWidget::~BasicWidget()
@@ -122,16 +125,21 @@ void BasicWidget::do_pBtn_CompareItemClicked()
 /* 修改了选择了声卡 */
 void BasicWidget::do_soundCardChanged(int nIndex)
 {
-    int nSoundCardNum = ui->comBox_driverName->currentData().toInt();
-    if(nSoundCardNum < 0)
+    if(nIndex < 0 || nIndex >= ui->comBox_driverName->count())
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "选择的声卡索引无效: {}", nIndex);
+        return;
+    }
+    std::string strSoundCardName = ui->comBox_driverName->currentData().toString().toStdString();
+    if(strSoundCardName.empty())
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "选择的声卡无效,无法设置通道信息");
+        SPDLOG_LOGGER_ERROR(m_logger, "选择的声卡无效,无法设置通道信息: {}", strSoundCardName);
         return;
     }
     /* 设置当前声卡信息 */
-    if(!SoundCards.setCurrentSoundCard(nSoundCardNum))
+    if(!SoundCards.setCurrentSoundCard(strSoundCardName))
     {
-        SPDLOG_LOGGER_ERROR(m_logger, "设置当前声卡失败,声卡编号: {}", nSoundCardNum);
+        SPDLOG_LOGGER_ERROR(m_logger, "设置当前声卡失败,声卡名称: {}", strSoundCardName);
         return;
     }
 }
@@ -147,6 +155,13 @@ void BasicWidget::do_pBtn_restore_clicked()
 }
 
 
+/* 点击了显示声卡通道名的checkBox */
+void BasicWidget::do_checkBox_showSoundCardDesc_clicked(bool checked)
+{
+    SoundCards.setShowSoundCardDesc(checked);
+}
+
+
 /* 判断基础信息有没有修改 */
 bool BasicWidget::isDataChangedBasicInfo()
 {
@@ -154,8 +169,7 @@ bool BasicWidget::isDataChangedBasicInfo()
     /* 获取基础配置信息 */
     m_baseConfig.strServerIP = ui->lineEdit_serverIP->text();
     m_baseConfig.nRecordMode = ui->comBox_recordMode->currentData().toInt();
-    m_baseConfig.strDriverName = ui->comBox_driverName->currentData().toString();
-    m_baseConfig.nNotConsistency = ui->comBox_notConsistency->currentData().toInt();
+    m_baseConfig.strSoundCardName = ui->comBox_driverName->currentData().toString();
 
     m_baseConfig.isEnableMultiCore = ui->checkBox_enableMultiCPU->isChecked();
     m_baseConfig.isEnableDebugLog = ui->checkBox_enableDebug->isChecked();
@@ -222,7 +236,8 @@ void BasicWidget::setSoundCardInfo()
     /* 添加声卡信息到下拉框 */
     for(const auto& it : soundCardInfo)
     {
-        ui->comBox_driverName->addItem(it.strSoundCardName, it.nSoundCardNum);
+        QString strDriverName = QString::fromStdString(it.first);
+        ui->comBox_driverName->addItem(strDriverName, strDriverName);
     }
     /* 设置当前信息 */
     ui->comBox_driverName->setCurrentIndex(0);
@@ -412,8 +427,7 @@ void BasicWidget::restoreBasicSettingInfo()
     const BaseConfig_t& baseConfig = SysConfig.getBaseConfigSrc();
     ui->lineEdit_serverIP->setText(baseConfig.strServerIP);
     ui->comBox_recordMode->setCurrentIndex(ui->comBox_recordMode->findData(baseConfig.nRecordMode));
-    ui->comBox_driverName->setCurrentText(baseConfig.strDriverName);
-    ui->comBox_notConsistency->setCurrentIndex(ui->comBox_notConsistency->findData(baseConfig.nNotConsistency));
+    ui->comBox_driverName->setCurrentIndex(ui->comBox_driverName->findData(baseConfig.strSoundCardName));
     ui->checkBox_enableMultiCPU->setChecked(baseConfig.isEnableMultiCore);
     ui->checkBox_enableDebug->setChecked(baseConfig.isEnableDebugLog);
     ui->checkBox_clearHistoryDir->setChecked(baseConfig.isClearDirSystemOn);

+ 2 - 0
SettingLibrary/Modules/Basic/basicwidget.h

@@ -37,6 +37,8 @@ private slots:
     void do_soundCardChanged(int nIndex);
     /* 恢复配置项 */
     void do_pBtn_restore_clicked();
+    /* 点击了显示声卡通道名的checkBox */
+    void do_checkBox_showSoundCardDesc_clicked(bool checked);
 
 private:
     /* 判断基础信息有没有修改 */

+ 3 - 2
SettingLibrary/Modules/Basic/compareitemdetailwidget.cpp

@@ -1,7 +1,7 @@
 #include "compareitemdetailwidget.h"
 #include "ui_compareitemdetailwidget.h"
 
-
+#include "SoundCardData.h"
 #include "UIStyleManager.h"
 
 
@@ -43,6 +43,7 @@ void CompareItemDetailWidget::setCompareItemInfo(const CompareItemInfo_t& info)
     /* 设置是否启用对比项 */
     ui->label_compareItemEnable->setText(info.isEnable ? "启用" : "未启用");
 
+    bool isShowPCMDesc = SoundCards.isShowSoundCardDesc();
     for(const auto& it : info.mapRoad)
     {
         /* 添加一行 */
@@ -55,7 +56,7 @@ void CompareItemDetailWidget::setCompareItemInfo(const CompareItemInfo_t& info)
         /* 通道名称 */
         items.append(new QTableWidgetItem(it.strCompareRoadName));
         /* 通道声卡设备编号 */
-        QString soundCardRoad = QString("%1:%2").arg(it.scRoadInfo.strSoundCardName, QString::number(it.scRoadInfo.roadInfo.nRoadNum));
+        QString soundCardRoad = isShowPCMDesc ? QString::fromStdString(it.scRoadInfo.pcmInfo.strPCMDesc) : QString::fromStdString(it.scRoadInfo.pcmInfo.strPCMName);
         items.append(new QTableWidgetItem(soundCardRoad));
 
         int row = ui->tableWidget->rowCount();

+ 2 - 6
SettingLibrary/Modules/Basic/compareitemdialog.cpp

@@ -51,14 +51,10 @@ CompareItemDialog::~CompareItemDialog()
 }
 
 /* 设置可选的声卡通道信息 */
-void CompareItemDialog::setSoundCardRoadList(const SoundCardInfo_t& soundCardInfo)
+void CompareItemDialog::setSoundCardRoadList(const SoundCardPCMInfo_t& soundCardInfo)
 {
     m_soundCardInfo = soundCardInfo;
-    // OneRoadInfo_t defaultRoad;
-    // defaultRoad.nRoadNum = 1;
-    // m_soundCardInfo.listRoad.push_back(defaultRoad);
-    // defaultRoad.nRoadNum = 2;
-    // m_soundCardInfo.listRoad.push_back(defaultRoad);
+
     /* 设置已有两个通道的可选录音通道 */
     ui->widget_mainRoad->setSoundCardRoadList(m_soundCardInfo);
     ui->widget_secondRoad->setSoundCardRoadList(m_soundCardInfo);

+ 2 - 2
SettingLibrary/Modules/Basic/compareitemdialog.h

@@ -34,7 +34,7 @@ public:
     ~CompareItemDialog();
 
     /* 设置可选的声卡通道信息 */
-    void setSoundCardRoadList(const SoundCardInfo_t& soundCardInfo);
+    void setSoundCardRoadList(const SoundCardPCMInfo_t& soundCardInfo);
     
 
     /* 设置默认的参数 */
@@ -81,7 +81,7 @@ private:
 private:
     Ui::CompareItemWidget *ui;
 
-    SoundCardInfo_t m_soundCardInfo;        /* 声卡信息 */
+    SoundCardPCMInfo_t m_soundCardInfo;        /* 声卡信息 */
 
     QList<SingleCompareRoadWidget*> m_listOtherRoadWgt;
     CompareItemInfo_t m_compareItemInfo;    /* 对比项信息 */

+ 24 - 12
SettingLibrary/Modules/Basic/singlecompareroadwidget.cpp

@@ -1,8 +1,11 @@
 #include "singlecompareroadwidget.h"
+#include "GlobalVariable.h"
 #include "ui_singlecompareroadwidget.h"
 #include "customcombobox.h"
 
 #include "spdlog/spdlog.h"
+#include <qchar.h>
+#include <string>
 
 SingleCompareRoadWidget::SingleCompareRoadWidget(QWidget *parent)
     : QWidget(parent)
@@ -34,15 +37,17 @@ void SingleCompareRoadWidget::setDelBtnVisible(bool bVisible)
 
 
 /* 设置声卡通道列表 */
-void SingleCompareRoadWidget::setSoundCardRoadList(const SoundCardInfo_t& soundCard)
+void SingleCompareRoadWidget::setSoundCardRoadList(const SoundCardPCMInfo_t& soundCard)
 {
     m_soundCardInfo = soundCard;
 
+    bool bShowDesc = SoundCards.isShowSoundCardDesc();
     ui->comboBox_soundCardNum->clear();
-    for(const auto& it : m_soundCardInfo.listRoad)
+    for(const auto& it : m_soundCardInfo.listPCM)
     {
-        QString strRoadName = QString("%1:%2").arg(m_soundCardInfo.strSoundCardName).arg(it.nRoadNum);
-        ui->comboBox_soundCardNum->addItem(strRoadName, QVariant::fromValue(it.nRoadNum));
+        QString strItem = bShowDesc ? QString::fromStdString(it.strPCMDesc) : QString::fromStdString(it.strPCMName);
+        QString strData = QString::fromStdString(it.strPCMName);
+        ui->comboBox_soundCardNum->addItem(strItem, strData);
     }
     /* 默认选择第一个 */
     ui->comboBox_soundCardNum->setCurrentIndex(0);
@@ -56,7 +61,7 @@ void SingleCompareRoadWidget::setDefaultParams(const CompareItemRoadInfo_t& road
     // setIndex(roadInfo.nCompareRoadNum);  /* 通道编号不需要设置 */
     /* 先清空选择,再设置当前选项 */
     // ui->comboBox_soundCardNum->setCurrentIndex(-1);
-    int numIndex = ui->comboBox_soundCardNum->findData(roadInfo.scRoadInfo.roadInfo.nRoadNum);
+    int numIndex = ui->comboBox_soundCardNum->findData(QString::fromStdString(roadInfo.scRoadInfo.pcmInfo.strPCMName));
     if(numIndex != -1)
     {
         ui->comboBox_soundCardNum->setCurrentIndex(numIndex);
@@ -99,14 +104,21 @@ QString SingleCompareRoadWidget::getRoadName() const
 }
 
 /* 获取声卡录音通道编号 */
-SoundCardRoadInfo_t SingleCompareRoadWidget::getSoundCardRoadInfo()
+OneSoundCardPCMInfo_t SingleCompareRoadWidget::getSoundCardRoadInfo()
 {
-    SoundCardRoadInfo_t roadInfo;
-    roadInfo.nSoundCardNum = m_soundCardInfo.nSoundCardNum;
-    roadInfo.strSoundCardID = m_soundCardInfo.strSoundCardID;
-    roadInfo.strSoundCardName = m_soundCardInfo.strSoundCardName;
-    roadInfo.roadInfo.nRoadNum = ui->comboBox_soundCardNum->currentData().value<int>();
-    return roadInfo;
+    std::string strPCMName = ui->comboBox_soundCardNum->currentData().toString().toStdString();
+    OneSoundCardPCMInfo_t pcmInfo;
+    pcmInfo.strSoundCardName = m_soundCardInfo.strSoundCardName;
+    for(const auto& it : m_soundCardInfo.listPCM)
+    {
+        if(it.strPCMName == strPCMName)
+        {
+            pcmInfo.pcmInfo = it;
+            break;
+        }
+    }
+    
+    return pcmInfo;
 }
 
 /* 是否开启录音 */

+ 3 - 3
SettingLibrary/Modules/Basic/singlecompareroadwidget.h

@@ -26,7 +26,7 @@ public:
     void setDelBtnVisible(bool bVisible);
 
     /* 设置声卡通道列表 */
-    void setSoundCardRoadList(const SoundCardInfo_t& sounCard);
+    void setSoundCardRoadList(const SoundCardPCMInfo_t& sounCard);
     /* 设置默认参数,设置之前需要先设置完成声卡可选通道列表 */
     void setDefaultParams(const CompareItemRoadInfo_t& roadInfo);
 
@@ -36,7 +36,7 @@ public:
     /* 获取通道名称 */
     QString getRoadName() const;
     /* 获取声卡录音通道编号 */
-    SoundCardRoadInfo_t getSoundCardRoadInfo();
+    OneSoundCardPCMInfo_t getSoundCardRoadInfo();
     /* 是否开启录音 */
     bool isRecordEnabled() const;
 
@@ -52,7 +52,7 @@ signals:
 private:
     Ui::SingleCompareRoadWidget *ui;
 
-    SoundCardInfo_t m_soundCardInfo;  /* 声卡信息 */
+    SoundCardPCMInfo_t m_soundCardInfo;  /* 声卡信息 */
 
     int m_nIndex;
 };

+ 36 - 14
SettingLibrary/setinfomanager.cpp

@@ -43,7 +43,6 @@ int SetInfoManager::Init(const stInitData* pData)
         return -1;
     }
 
-    /* 初始化mqtt,获取声卡等信息 */
 
     /* 初始化webAPI */
     if(!initWebAPI())
@@ -58,6 +57,14 @@ int SetInfoManager::Init(const stInitData* pData)
         return -1;
     }
 
+    /* 从数据库中获取声卡信息 */
+    if(!getSoundCardInfo())
+    {
+        SPDLOG_ERROR("获取声卡信息失败");
+        return -1;
+    }
+    
+
     /* 从数据库获取对比项信息 */
     QList<CompareItemInfo_t> listItems;
     if(!m_fromWebAPI->getCompareItemInfo(listItems))
@@ -166,16 +173,16 @@ void SetInfoManager::setDefaultCompareItem()
     mainRoad.isEnableRecord = true; // 主通道默认开启录音
     mainRoad.nCompareRoadNum = 1; // 主通道编号为1
     mainRoad.strCompareRoadName = "主通道"; // 主通道名称
-    mainRoad.scRoadInfo.nSoundCardNum = 0; // 默认声卡编号为0
-    mainRoad.scRoadInfo.roadInfo.nRoadNum = 0; // 默认通道编号为0
+    // mainRoad.scRoadInfo.strSoundCardName = SC_System;
+    // mainRoad.scRoadInfo.roadInfo.nRoadNum = 0; // 默认通道编号为0
     defaultItem.mapRoad.insert(mainRoad.nCompareRoadNum, mainRoad);
 
     CompareItemRoadInfo_t secondRoad;
     secondRoad.isEnableRecord = true; // 第二通道默认开启录音
     secondRoad.nCompareRoadNum = 2; // 第二通道编号为2
     secondRoad.strCompareRoadName = "第2通道"; // 第二通道名称
-    secondRoad.scRoadInfo.nSoundCardNum = 0; // 默认声卡编号为0
-    secondRoad.scRoadInfo.roadInfo.nRoadNum = 1; // 默认通道编号为1
+    // secondRoad.scRoadInfo.nSoundCardNum = 0; // 默认声卡编号为0
+    // secondRoad.scRoadInfo.roadInfo.nRoadNum = 1; // 默认通道编号为1
     
     defaultItem.mapRoad.insert(secondRoad.nCompareRoadNum, secondRoad);
 
@@ -269,15 +276,15 @@ bool SetInfoManager::getSystemConfig()
                 SPDLOG_ERROR("获取数据库设置失败");
             }
         }
-        else if(Config_SoundCardInfo == it.key())
-        {
-            QMap<int, SoundCardInfo_t> soundCardInfo;
-            if(!SysConfig.getSoundCardInfoFromJson(it.value(), soundCardInfo))
-            {
-                SPDLOG_ERROR("获取声卡信息失败");
-            }
-            SoundCards.setSoundCardInfo(soundCardInfo); // 设置声卡信息到全局管理器
-        } 
+        // else if(Config_SoundCardInfo == it.key())
+        // {
+        //     QMap<int, SoundCardInfo_t> soundCardInfo;
+        //     if(!SysConfig.getSoundCardInfoFromJson(it.value(), soundCardInfo))
+        //     {
+        //         SPDLOG_ERROR("获取声卡信息失败");
+        //     }
+        //     SoundCards.setSoundCardInfo(soundCardInfo); // 设置声卡信息到全局管理器
+        // } 
         else
         {
             SPDLOG_DEBUG("未知的系统配置项: {}", it.key());
@@ -297,3 +304,18 @@ bool SetInfoManager::getSystemConfig()
 }
 
 
+/* 获取声卡信息 */
+bool SetInfoManager::getSoundCardInfo()
+{
+    std::map<std::string, SoundCardPCMInfo_t> mapSoundCard;
+    if(!m_fromWebAPI->getSoundCardInfo(mapSoundCard))
+    {
+        return false;
+    }
+
+    SoundCards.setSoundCardInfo(mapSoundCard); // 设置声卡信息到全局管理器
+    
+    return true;
+}
+
+

+ 2 - 0
SettingLibrary/setinfomanager.h

@@ -46,6 +46,8 @@ private:
     bool initWebAPI();
     /* 获取数据库中系统设置参数 */
     bool getSystemConfig();
+    /* 获取声卡信息 */
+    bool getSoundCardInfo();
 
 private:
     stInitData m_initData;      // 初始化数据

+ 6 - 66
ThreeLib/signalstats/include/signalstats.h

@@ -6,85 +6,25 @@ SoundCardDataManager::~SoundCardDataManager()
 }
 
 /* 设置声卡列表 */
-void SoundCardDataManager::setSoundCardInfo(QMap<int, SoundCardInfo_t>& soundInfo)
+void SoundCardDataManager::setSoundCardInfo(std::map<std::string, SoundCardPCMInfo_t>& mapSoundInfo)
 {
     m_mapSoundCardInfo.clear();
-    m_mapSoundCardInfo = soundInfo;
+    m_mapSoundCardInfo = mapSoundInfo;
 }
 
-/* 获取单个声卡信息 */
-SoundCardInfo_t SoundCardDataManager::getOneSoundCardInfo(int nSoundCardNum) const
-{
-    auto it = m_mapSoundCardInfo.find(nSoundCardNum);
-    if(it != m_mapSoundCardInfo.end())
-    {
-        return it.value(); // 返回找到的声卡信息
-    }
-    SoundCardInfo_t emptyInfo;
-    emptyInfo.nSoundCardNum = -1; // 未找到时返回无效信息
-    emptyInfo.strSoundCardID = "";
-    emptyInfo.strSoundCardName = "";
-    return emptyInfo;
-}
 
 /* 设置当前声卡 */
-bool SoundCardDataManager::setCurrentSoundCard(int nSoundCardNum)
+bool SoundCardDataManager::setCurrentSoundCard(std::string strSoundCardName)
 {
-    auto it = m_mapSoundCardInfo.find(nSoundCardNum);
+    auto it = m_mapSoundCardInfo.find(strSoundCardName);
     if(it == m_mapSoundCardInfo.end())
     {
         return false;
     }
-    m_currentSoundCardInfo = it.value(); // 设置当前声卡信息
-    m_listSoundCardRoad.clear(); // 清空现有的通道列表
-    const SoundCardInfo_t& soundCardInfo = it.value();
-    for(const auto& road : soundCardInfo.listRoad)
-    {
-        SoundCardRoadInfo_t roadInfo;
-        roadInfo.nSoundCardNum = soundCardInfo.nSoundCardNum;
-        roadInfo.strSoundCardID = soundCardInfo.strSoundCardID;
-        roadInfo.strSoundCardName = soundCardInfo.strSoundCardName;
-        roadInfo.roadInfo = road; // 设置通道信息
-        m_listSoundCardRoad.append(roadInfo); // 添加到列表中
-    }
-
+    m_currentSoundCardInfo = it->second;
+    
     return true;
 }
 
 
-/* 根据声卡编号和录音通道编号获取声卡信息 */
-SoundCardRoadInfo_t SoundCardDataManager::getSoundCardRoadInfo(int nSoundCardNum, int nChannelID)
-{
-    for(const auto& soundCard : m_mapSoundCardInfo)
-    {
-        if(nSoundCardNum == soundCard.nSoundCardNum)
-        {
-            for(const auto& road : soundCard.listRoad)
-            {
-                if(road.nRoadNum == nChannelID)
-                {
-                    SoundCardRoadInfo_t roadInfo;
-                    roadInfo.nSoundCardNum = soundCard.nSoundCardNum;
-                    roadInfo.strSoundCardID = soundCard.strSoundCardID;
-                    roadInfo.strSoundCardName = soundCard.strSoundCardName;
-                    roadInfo.roadInfo = road; // 设置通道信息
-                    return roadInfo; // 返回找到的声卡通道信息
-                }
-            }
-        }
-    }
-    SoundCardRoadInfo_t emptyInfo;
-    emptyInfo.nSoundCardNum = -1; // 未找到时返回无效信息
-    emptyInfo.strSoundCardID = "";
-    emptyInfo.strSoundCardName = "";
-    emptyInfo.roadInfo.nRoadNum = -1;
-    return emptyInfo;
-}
-
-/* 获取带有声卡信息的通道列表 */
-const QList<SoundCardRoadInfo_t>& SoundCardDataManager::getCurrSoundCardRoadList() const
-{
-    return m_listSoundCardRoad;
-}
-
 

+ 12 - 16
common/DataManager/SoundCardData.h

@@ -28,31 +28,27 @@ public:
         return instance;
     }
     /* 设置声卡列表 */
-    void setSoundCardInfo(QMap<int, SoundCardInfo_t>& soundInfo);
+    void setSoundCardInfo(std::map<std::string, SoundCardPCMInfo_t>& mapSoundInfo);
     /* 获取声卡列表 */
-    const QMap<int, SoundCardInfo_t>& getSoundCardInfo() const { return m_mapSoundCardInfo; }
+    const std::map<std::string, SoundCardPCMInfo_t>& getSoundCardInfo() const { return m_mapSoundCardInfo; }
 
-    /* 获取单个声卡信息 */
-    SoundCardInfo_t getOneSoundCardInfo(int nSoundCardNum) const;
     /* 设置当前声卡 */
-    bool setCurrentSoundCard(int nSoundCardNum);
+    bool setCurrentSoundCard(std::string strSoundCardName);
     /* 获取当前声卡信息 */
-    const SoundCardInfo_t& getCurrentSoundCardInfo() const { return m_currentSoundCardInfo; }
-
-    /* 根据声卡编号和录音通道编号获取声卡信息 */
-    SoundCardRoadInfo_t getSoundCardRoadInfo(int nSoundCardNum, int nChannelID);
-    /* 获取当前带有声卡信息的通道列表 */
-    const QList<SoundCardRoadInfo_t>& getCurrSoundCardRoadList() const;
+    const SoundCardPCMInfo_t& getCurrentSoundCardInfo() const { return m_currentSoundCardInfo; }
     
+    void setShowSoundCardDesc(bool bShow) { m_isShowSoundCardDesc = bShow; }
+    bool isShowSoundCardDesc() const { return m_isShowSoundCardDesc; }
 
 private:
-    
+    bool m_isShowSoundCardDesc = false;         /* 是否显示PCM通道的描述信息,为false,则显示PCM名 */
     /* 声卡信息,key为声卡编号 */
-    QMap<int, SoundCardInfo_t> m_mapSoundCardInfo;
-    /* 当前选择的声卡编号 */
-    SoundCardInfo_t m_currentSoundCardInfo;
+    // QMap<int, SoundCardInfo_t> m_mapSoundCardInfo;
+    std::map<std::string, SoundCardPCMInfo_t> m_mapSoundCardInfo;
+    /* 当前选择的声卡 */
+    SoundCardPCMInfo_t m_currentSoundCardInfo;
     /* 带有声卡信息的通道列表,设置当前声卡信息的时候会更新 */
-    QList<SoundCardRoadInfo_t> m_listSoundCardRoad;
+    // QList<SoundCardRoadInfo_t> m_listSoundCardRoad;
 };
 
 

+ 91 - 47
common/DataManager/SystemConfig.cpp

@@ -2,6 +2,7 @@
 
 #include "spdlog/spdlog.h"
 #include "commonDefine.h"
+#include <qchar.h>
 #include <string>
 
 
@@ -76,8 +77,7 @@ bool SystemConfigInfo::getBaseConfigFromJson(const std::string& jsonStr)
         nJson jsonConfig = nJson::parse(jsonStr);
         m_baseConfigSrc.strServerIP = QString::fromStdString(jsonConfig["ServerIP"].get<std::string>());
         m_baseConfigSrc.nRecordMode = jsonConfig["RecordMode"].get<int>();
-        m_baseConfigSrc.strDriverName = QString::fromStdString(jsonConfig["DriverName"].get<std::string>());
-        m_baseConfigSrc.nNotConsistency = jsonConfig["NotConsistency"].get<int>();
+        m_baseConfigSrc.strSoundCardName = QString::fromStdString(jsonConfig["SoundCardName"].get<std::string>());
         m_baseConfigSrc.isEnableMultiCore = jsonConfig["EnableMultiCore"].get<bool>();
         m_baseConfigSrc.isEnableDebugLog = jsonConfig["EnableDebugLog"].get<bool>();
         m_baseConfigSrc.isClearDirSystemOn = jsonConfig["ClearHistryDirOnStart"].get<bool>();
@@ -94,8 +94,7 @@ bool SystemConfigInfo::setBaseConfigToJson(const BaseConfig_t& baseConfig, std::
         nJson jsonConfig;
         jsonConfig["ServerIP"] = baseConfig.strServerIP.toStdString();
         jsonConfig["RecordMode"] = baseConfig.nRecordMode;
-        jsonConfig["DriverName"] = baseConfig.strDriverName.toStdString();
-        jsonConfig["NotConsistency"] = baseConfig.nNotConsistency;
+        jsonConfig["SoundCardName"] = baseConfig.strSoundCardName.toStdString();
         jsonConfig["EnableMultiCore"] = baseConfig.isEnableMultiCore;
         jsonConfig["EnableDebugLog"] = baseConfig.isEnableDebugLog;
         jsonConfig["ClearHistryDirOnStart"] = baseConfig.isClearDirSystemOn;
@@ -295,32 +294,87 @@ void SystemConfigInfo::setDetectPeriodConfig(const QMap<int, DetectPeriodConfig_
 }
 
 
-/* 将声卡信息转换成json */
-bool SystemConfigInfo::setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const
+// /* 将声卡信息转换成json */
+// bool SystemConfigInfo::setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const
+// {
+//     try {
+//         nJson jsonConfig;
+//         for (const auto& soundCard : soundCardInfo) 
+//         {
+//             nJson soundCardJson;
+//             soundCardJson["SoundCardNum"] = soundCard.nSoundCardNum;
+//             soundCardJson["SoundCardID"] = soundCard.strSoundCardID.toStdString();
+//             soundCardJson["SoundCardName"] = soundCard.strSoundCardName.toStdString();
+//             soundCardJson["SoundCardDriver"] = soundCard.strSoundCardDriver.toStdString();
+
+//             nJson roadArray = nJson::array();
+//             for (const auto& road : soundCard.listRoad) {
+//                 nJson roadJson;
+//                 roadJson["RoadNum"] = road.nRoadNum;
+//                 // roadJson["ChannelID"] = road.nChannelID;
+//                 // roadJson["ChannelName"] = road.strChannelName.toStdString();
+//                 roadArray.push_back(roadJson);
+//             }
+//             soundCardJson["Roads"] = roadArray;
+
+//             jsonConfig[std::to_string(soundCard.nSoundCardNum)] = soundCardJson;
+//         }
+
+//         strJson = jsonConfig.dump();
+//     }nJsonCatch
+
+//     return true;
+// }
+
+// /* 将json转换成声卡信息 */
+// bool SystemConfigInfo::getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo)
+// {
+//     try {
+//         nJson jsonConfig = nJson::parse(jsonStr);
+//         soundCardInfo.clear();
+
+//         for (auto& item : jsonConfig) 
+//         {
+//             SoundCardInfo_t soundCard;
+//             soundCard.nSoundCardNum = item["SoundCardNum"].get<int>();
+//             soundCard.strSoundCardID = QString::fromStdString(item["SoundCardID"].get<std::string>());
+//             soundCard.strSoundCardName = QString::fromStdString(item["SoundCardName"].get<std::string>());
+//             soundCard.strSoundCardDriver = QString::fromStdString(item["SoundCardDriver"].get<std::string>());
+            
+//             soundCard.listRoad.clear();
+//             auto roadsArray = item["Roads"];
+//             for (const auto& roadItem : roadsArray) 
+//             {
+//                 OneRoadInfo_t road;
+//                 road.nRoadNum = roadItem["RoadNum"].get<int>();
+//                 // road.nChannelID = roadItem["ChannelID"].get<int>();
+//                 // road.strChannelName = QString::fromStdString(roadItem["ChannelName"].get<std::string>());
+//                 soundCard.listRoad.append(road);
+//             }
+
+//             soundCardInfo[soundCard.nSoundCardNum] = soundCard;
+//         }
+//     }nJsonCatch
+
+//     return true;
+// }
+
+/* 将PCM信息转换成json */
+bool SystemConfigInfo::setSoundCardPCMInfoToJson(const std::list<AudioDeviceDesc_t>& soundCardPCMInfo, std::string& strJson) const
 {
     try {
-        nJson jsonConfig;
-        for (const auto& soundCard : soundCardInfo) 
+        nJson jsonConfig = nJson::array();
+        for (const auto& device : soundCardPCMInfo) 
         {
-            nJson soundCardJson;
-            soundCardJson["SoundCardNum"] = soundCard.nSoundCardNum;
-            soundCardJson["SoundCardID"] = soundCard.strSoundCardID.toStdString();
-            soundCardJson["SoundCardName"] = soundCard.strSoundCardName.toStdString();
-            soundCardJson["SoundCardDriver"] = soundCard.strSoundCardDriver.toStdString();
-
-            nJson roadArray = nJson::array();
-            for (const auto& road : soundCard.listRoad) {
-                nJson roadJson;
-                roadJson["RoadNum"] = road.nRoadNum;
-                // roadJson["ChannelID"] = road.nChannelID;
-                // roadJson["ChannelName"] = road.strChannelName.toStdString();
-                roadArray.push_back(roadJson);
-            }
-            soundCardJson["Roads"] = roadArray;
-
-            jsonConfig[std::to_string(soundCard.nSoundCardNum)] = soundCardJson;
+            nJson deviceJson;
+            deviceJson["PCMName"] = device.DeviceName;
+            deviceJson["PCMDesc"] = device.DeviceDesc;
+            deviceJson["IOID"] = device.IOID;
+            deviceJson["CardNum"] = device.Card;
+            deviceJson["SubDevNum"] = device.DevNum;
+
+            jsonConfig.push_back(deviceJson);
         }
-
         strJson = jsonConfig.dump();
     }nJsonCatch
 
@@ -328,32 +382,22 @@ bool SystemConfigInfo::setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>&
 }
 
 /* 将json转换成声卡信息 */
-bool SystemConfigInfo::getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo)
+bool SystemConfigInfo::getSoundCardPCMInfoFromJson(const std::string& jsonStr, std::list<AudioDeviceDesc_t>& soundCardPCMInfo)
 {
     try {
         nJson jsonConfig = nJson::parse(jsonStr);
-        soundCardInfo.clear();
+        soundCardPCMInfo.clear();
 
-        for (auto& item : jsonConfig) 
+        for (const auto& item : jsonConfig) 
         {
-            SoundCardInfo_t soundCard;
-            soundCard.nSoundCardNum = item["SoundCardNum"].get<int>();
-            soundCard.strSoundCardID = QString::fromStdString(item["SoundCardID"].get<std::string>());
-            soundCard.strSoundCardName = QString::fromStdString(item["SoundCardName"].get<std::string>());
-            soundCard.strSoundCardDriver = QString::fromStdString(item["SoundCardDriver"].get<std::string>());
-            
-            soundCard.listRoad.clear();
-            auto roadsArray = item["Roads"];
-            for (const auto& roadItem : roadsArray) 
-            {
-                OneRoadInfo_t road;
-                road.nRoadNum = roadItem["RoadNum"].get<int>();
-                // road.nChannelID = roadItem["ChannelID"].get<int>();
-                // road.strChannelName = QString::fromStdString(roadItem["ChannelName"].get<std::string>());
-                soundCard.listRoad.append(road);
-            }
-
-            soundCardInfo[soundCard.nSoundCardNum] = soundCard;
+            AudioDeviceDesc_t device;
+            device.DeviceName = item["PCMName"].get<std::string>();
+            device.DeviceDesc = item["PCMDesc"].get<std::string>();
+            device.IOID = item["IOID"].get<std::string>();
+            device.Card = item["CardNum"].get<int>();
+            device.DevNum = item["SubDevNum"].get<int>();
+
+            soundCardPCMInfo.push_back(device);
         }
     }nJsonCatch
 

+ 8 - 2
common/DataManager/SystemConfig.h

@@ -15,6 +15,7 @@
  */
 
 
+#include "AudioRecord.h"
 #include "GlobalVariable.h"
 #include "SystemConfigStruct.h"
 #include <string>
@@ -145,9 +146,14 @@ public:
     /*-------------------------------------------------------------------------------------*/
     /* 声卡信息有单独的声卡信息类,不在这里存储 */
     /* 将声卡信息转换成json */
-    bool setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const;
+    // bool setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const;
     /* 将json转换成声卡信息 */
-    bool getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo);
+    // bool getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo);
+
+    /* 将PCM信息转换成json */
+    bool setSoundCardPCMInfoToJson(const std::list<AudioDeviceDesc_t>& soundCardPCMInfo, std::string& strJson) const;
+    /* 将json转换成声卡信息 */
+    bool getSoundCardPCMInfoFromJson(const std::string& jsonStr, std::list<AudioDeviceDesc_t>& soundCardPCMInfo);
 
 public:
     

+ 1 - 2
common/DataManager/SystemConfigStruct.cpp

@@ -16,8 +16,7 @@ bool BaseConfig_t::operator==(const BaseConfig_t &other) const
 
     if(strServerIP == other.strServerIP &&
        nRecordMode == other.nRecordMode &&
-       strDriverName == other.strDriverName &&
-       nNotConsistency == other.nNotConsistency &&
+       strSoundCardName == other.strSoundCardName &&
        isEnableMultiCore == other.isEnableMultiCore &&
        isEnableDebugLog == other.isEnableDebugLog &&
        isClearDirSystemOn == other.isClearDirSystemOn &&

+ 3 - 3
common/DataManager/SystemConfigStruct.h

@@ -5,6 +5,7 @@
 #include <QString>
 #include <QMap>
 #include <cerrno>
+#include <qchar.h>
 
 #include "GlobalVariable.h"
 
@@ -24,7 +25,7 @@ const QMap<int, QString> g_mapNotConsistency =
 /* 录音模式 */
 const QMap<int, QString> g_mapRecordModes = 
 {
-    {1, "ASIO"}
+    {1, "ALSA"}
 };
 
 const float fespipe = 1e-6f;    /* 单精度浮点数比较时的误差 */
@@ -39,8 +40,7 @@ struct BaseConfig_t
 {
     QString strServerIP;        /* 服务器IP地址 */
     int nRecordMode;            /* 录音模式, ASIO等 */
-    QString strDriverName;      /* 驱动名称 */
-    int nNotConsistency = 1;    /* 不一致判断选项,默认是1 */
+    QString strSoundCardName;   /* 声卡名称 */
 
     bool isEnableMultiCore = false;     /* 是否启用多核处理 */
     bool isEnableDebugLog = false;      /* 是否启用调试日志 */

+ 34 - 21
common/GlobalInfo/GlobalVariable.cpp

@@ -16,25 +16,40 @@ const QMap<eWeekType, QString> MapWeekTypeToString = {
 };
 
 
+
+
 /* ====================================================================
  * 声卡相关信息结构体
  * ==================================================================== */
 
 
-bool SoundCardRoadInfo_t::operator<(const SoundCardRoadInfo_t &other) const
+// bool SoundCardRoadInfo_t::operator<(const SoundCardRoadInfo_t &other) const
+// {
+//     if(nSoundCardNum < other.nSoundCardNum)
+//     {
+//         return true; // 声卡编号小的排在前面
+//     }
+//     if(nSoundCardNum > other.nSoundCardNum)
+//     {
+//         return false; // 声卡编号大的排在后面
+//     }
+//     // 声卡编号相同,比较通道编号
+//     return roadInfo.nRoadNum < other.roadInfo.nRoadNum;
+// }
+
+bool OneSoundCardPCMInfo_t::operator==(const OneSoundCardPCMInfo_t& obj) const
 {
-    if(nSoundCardNum < other.nSoundCardNum)
-    {
-        return true; // 声卡编号小的排在前面
-    }
-    if(nSoundCardNum > other.nSoundCardNum)
+    if( strSoundCardName == obj.strSoundCardName && 
+    pcmInfo.strPCMName == obj.pcmInfo.strPCMName &&
+    pcmInfo.strPCMDesc == obj.pcmInfo.strPCMDesc &&
+    pcmInfo.strIO == obj.pcmInfo.strIO)
     {
-        return false; // 声卡编号大的排在后面
+        return true;
     }
-    // 声卡编号相同,比较通道编号
-    return roadInfo.nRoadNum < other.roadInfo.nRoadNum;
+    return false;
 }
 
+
 /* ====================================================================
  * CompareItemInfo_t对比项结构体
  * ==================================================================== */
@@ -44,12 +59,10 @@ bool CompareItemRoadInfo_t::operator==(const CompareItemRoadInfo_t &other) const
     return (isEnableRecord == other.isEnableRecord &&
             nCompareRoadNum == other.nCompareRoadNum &&
             strCompareRoadName == other.strCompareRoadName &&
-            scRoadInfo.nSoundCardNum == other.scRoadInfo.nSoundCardNum &&
-            scRoadInfo.strSoundCardID == other.scRoadInfo.strSoundCardID &&
             scRoadInfo.strSoundCardName == other.scRoadInfo.strSoundCardName &&
-            scRoadInfo.roadInfo.nRoadNum == other.scRoadInfo.roadInfo.nRoadNum &&
-            scRoadInfo.roadInfo.nChannelID == other.scRoadInfo.roadInfo.nChannelID &&
-            scRoadInfo.roadInfo.strChannelName == other.scRoadInfo.roadInfo.strChannelName
+            scRoadInfo.pcmInfo.strPCMName == other.scRoadInfo.pcmInfo.strPCMName &&
+            scRoadInfo.pcmInfo.strPCMDesc == other.scRoadInfo.pcmInfo.strPCMDesc &&
+            scRoadInfo.pcmInfo.strIO == other.scRoadInfo.pcmInfo.strIO
             );
 }
 
@@ -69,10 +82,9 @@ OneCompareItemRoadInfo_t& OneCompareItemRoadInfo_t::operator=(const OneCompareIt
     }
     nCompareItemID = other.nCompareItemID;
     nCompareRoadNum = other.nCompareRoadNum;
-    nSoundCardNum = other.nSoundCardNum;
-    nSoundCardRoadNum = other.nSoundCardRoadNum;
     strCompareItemName = other.strCompareItemName;
     strCompareRoadName = other.strCompareRoadName;
+    scRoadInfo = other.scRoadInfo;
     return *this;
 }
 
@@ -80,10 +92,12 @@ bool OneCompareItemRoadInfo_t::operator==(const OneCompareItemRoadInfo_t &other)
 {
     return (nCompareItemID == other.nCompareItemID &&
             nCompareRoadNum == other.nCompareRoadNum &&
-            nSoundCardNum == other.nSoundCardNum &&
-            nSoundCardRoadNum == other.nSoundCardRoadNum &&
             strCompareItemName == other.strCompareItemName &&
-            strCompareRoadName == other.strCompareRoadName
+            strCompareRoadName == other.strCompareRoadName &&
+            scRoadInfo.strSoundCardName == other.scRoadInfo.strSoundCardName &&
+            scRoadInfo.pcmInfo.strPCMName == other.scRoadInfo.pcmInfo.strPCMName &&
+            scRoadInfo.pcmInfo.strPCMDesc == other.scRoadInfo.pcmInfo.strPCMDesc &&
+            scRoadInfo.pcmInfo.strIO == other.scRoadInfo.pcmInfo.strIO
             );
 }
 
@@ -347,8 +361,7 @@ RecordFileInfo_t& RecordFileInfo_t::operator=(const RecordFileInfo_t& obj)
     ItemName = obj.ItemName;
     ItemRoadNum = obj.ItemRoadNum;
     ItemRoadName = obj.ItemRoadName;
-    SoundCardNum = obj.SoundCardNum;
-    SoundCardRoadNum = obj.SoundCardRoadNum;
+    scRoadInfo = obj.scRoadInfo;
     FileStartTime = obj.FileStartTime;
     FileEndTime = obj.FileEndTime;
     FileDuration = obj.FileDuration;

+ 83 - 29
common/GlobalInfo/GlobalVariable.h

@@ -9,6 +9,26 @@
 #include <QMetaType>
 
 #include <QDateTime>
+#include <string>
+
+
+
+
+
+
+/* 声卡识别符号,在PCM通道中通过这个字符识别是属于哪些声卡的 */
+
+#define SC_System   "SystemOther"       /* 不需要识别的声卡 */
+#define SC_AlpDANTE "AlpDANTE"          /* dante声卡 */
+
+
+
+
+
+
+
+
+
 
 /**
  * @brief 星期枚举定义,星期八是带有日期的特殊日
@@ -106,42 +126,42 @@ struct OnePlan_t
  * ==================================================================== */
 
 /* 单个录音通道信息,带有频道信息 */
-struct OneRoadInfo_t
-{
-    int nRoadNum = -1;              /* 录音通道编号,是声卡在系统中的物理编号 */
-    int nChannelID = -1;            /* 频道ID */
-    QString strChannelName;         /* 频道名称 */
-};
+// struct OneRoadInfo_t
+// {
+//     int nRoadNum = -1;              /* 录音通道编号,是声卡在系统中的物理编号 */
+//     int nChannelID = -1;            /* 频道ID */
+//     QString strChannelName;         /* 频道名称 */
+// };
 
 
 /**
  * @brief 声卡信息,这里的信息都是设备上和物理声卡相关的
  * 
  */
-struct SoundCardInfo_t
-{
-    int nSoundCardNum = -1;             /* 声卡编号,系统上的物理编号 */
-    QString strSoundCardID;             /* 声卡ID,这个是声卡名称,可以用来打开 */
-    QString strSoundCardName;           /* 声卡名称 */
-    QString strSoundCardDriver;         /* 声卡驱动名称 */
+// struct SoundCardInfo_t
+// {
+//     int nSoundCardNum = -1;             /* 声卡编号,系统上的物理编号 */
+//     QString strSoundCardID;             /* 声卡ID,这个是声卡名称,可以用来打开 */
+//     QString strSoundCardName;           /* 声卡名称 */
+//     QString strSoundCardDriver;         /* 声卡驱动名称 */
     
-    QList<OneRoadInfo_t> listRoad;      /* 录音通道列表,存储通道编号 */
-};
+//     QList<OneRoadInfo_t> listRoad;      /* 录音通道列表,存储通道编号 */
+// };
 
 
 /**
  * @brief 单个声卡通道信息,带有声卡自身的信息
  * 
  */
-struct SoundCardRoadInfo_t
-{
-    int nSoundCardNum = -1;             /* 声卡编号 */
-    QString strSoundCardID;             /* 声卡ID,这个是声卡名称,可以用来打开 */
-    QString strSoundCardName;           /* 声卡名称 */
-    OneRoadInfo_t roadInfo;             /* 单个通道信息 */
+// struct SoundCardRoadInfo_t
+// {
+//     int nSoundCardNum = -1;             /* 声卡编号 */
+//     QString strSoundCardID;             /* 声卡ID,这个是声卡名称,可以用来打开 */
+//     QString strSoundCardName;           /* 声卡名称 */
+//     OneRoadInfo_t roadInfo;             /* 单个通道信息 */
 
-    bool operator<(const SoundCardRoadInfo_t &other) const;
-};
+//     bool operator<(const SoundCardRoadInfo_t &other) const;
+// };
 
 /* 使用声卡通道最为Key的结构体 */
 struct SoundCardRoadKey_t
@@ -164,7 +184,41 @@ struct SoundCardRoadKey_t
 };
 
 /* 注册数据类型到系统 */
-Q_DECLARE_METATYPE(SoundCardRoadInfo_t)
+// Q_DECLARE_METATYPE(SoundCardRoadInfo_t)
+
+
+
+/**
+ * @brief 声卡PCM通道信息
+ * 
+ */
+struct OnePCMChannelInfo_t
+{
+    std::string strPCMName;         /* PCM名称,可以使用这个直接打开录音通道,这个在系统中是唯一的 */
+    std::string strPCMDesc;         /* PCM描述 */
+    std::string strIO;              /* 输入输出 */
+};
+
+
+/**
+ * @brief 声卡描述符信息,声卡名称这里不定义,从设置动态库中定义
+ * 
+ */
+struct SoundCardPCMInfo_t
+{
+    std::string strSoundCardName;       /* 声卡名称,这个是自定义的,用来识别系统中的PCM通道 */
+    std::list<OnePCMChannelInfo_t> listPCM;  /* PCM信息列表 */
+};
+
+
+/* 带有声卡名称信息的PCM通道 */
+struct OneSoundCardPCMInfo_t
+{
+    std::string strSoundCardName;       /* 声卡名称,这个是自定义的,用来识别系统中的PCM通道 */
+    OnePCMChannelInfo_t pcmInfo;        /* PCM信息 */
+
+    bool operator==(const OneSoundCardPCMInfo_t& obj) const;
+};
 
 
 /* ====================================================================
@@ -192,7 +246,8 @@ struct CompareItemRoadInfo_t
     bool isEnableRecord;        /* 是否开启录音 */
     int nCompareRoadNum;        /* 对比通道编号,1是主通道,其余往后排 */
     QString strCompareRoadName; /* 对比项通道名称,不是声卡的通道名 */
-    SoundCardRoadInfo_t scRoadInfo; /* 声卡通道信息,包含声卡编号和通道编号 */
+    // SoundCardRoadInfo_t scRoadInfo; /* 声卡通道信息,包含声卡编号和通道编号 */
+    OneSoundCardPCMInfo_t scRoadInfo; /* 声卡通道信息,包含声卡名称和PCM名称 */
 
     bool operator==(const CompareItemRoadInfo_t &other) const;
 };
@@ -203,10 +258,9 @@ struct OneCompareItemRoadInfo_t
 {
     int nCompareItemID = -1;                /* 对比项ID */
     int nCompareRoadNum = -1;               /* 对比项通道编号 */
-    int nSoundCardNum = -1;                 /* 声卡编号 */
-    int nSoundCardRoadNum = -1;             /* 声卡通道编号 */
     QString strCompareItemName;             /* 对比项名称 */
     QString strCompareRoadName;             /* 对比项通道名称 */
+    OneSoundCardPCMInfo_t scRoadInfo;       /* 声卡通道信息,包含声卡名称和PCM名称 */
 
     OneCompareItemRoadInfo_t() = default;
     OneCompareItemRoadInfo_t(const OneCompareItemRoadInfo_t &other);
@@ -345,7 +399,8 @@ enum class EThreadType
  */
 struct RecordThreadInfo_t
 {
-    SoundCardRoadInfo_t cardRoadInfo;           /* 录音通道信息 */
+    // SoundCardRoadInfo_t cardRoadInfo;           /* 录音通道信息 */
+    OneSoundCardPCMInfo_t cardRoadInfo;         /* 录音通道信息,包含声卡名称和PCM名称 */
     EThreadType threadType;                     /* 线程类型 */
     EThreadState threadState;                   /* 线程状态 */
     // BaseRecordThread* pThread = nullptr;        /* 线程对象 */
@@ -422,8 +477,7 @@ struct RecordFileInfo_t
     QString ItemName;               /* 对比项名称 */
     int ItemRoadNum = -1;           /* 对比项通道编号 */
     QString ItemRoadName;           /* 对比项通道名称 */
-    int SoundCardNum = -1;          /* 声卡编号 */
-    int SoundCardRoadNum = -1;      /* 声卡通道编号 */
+    OneSoundCardPCMInfo_t scRoadInfo;/* 声卡PCM通道信息,包含声卡名称和PCM名称 */
 
     QDateTime FileStartTime;        /* 文件开始时间 */
     QDateTime FileEndTime;          /* 文件结束时间 */

+ 166 - 58
common/Network/FromWebAPI.cpp

@@ -5,7 +5,7 @@
 #include "spdlog.h"
 
 #include <QString>
-#include <qchar.h>
+
 
 
 FromWebAPI::FromWebAPI()
@@ -31,7 +31,7 @@ bool FromWebAPI::getCompareItemInfo(QList<CompareItemInfo_t>& listItems)
     json0["opName"] = "ACAS_GetCompareItem";
     QString strCmd1 = QString::fromStdString(json0.dump());
     QString strRet1;
-    int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strCmd1, strRet1);
+    int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strCmd1, strRet1, true);
     if(ret != 0)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "获取对比项信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -45,7 +45,7 @@ bool FromWebAPI::getCompareItemInfo(QList<CompareItemInfo_t>& listItems)
     json1["opName"] = "ACAS_GetCompareItemRoad";
     QString strCmd2 = QString::fromStdString(json1.dump());
     QString strRet2;
-    ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strCmd2, strRet2);
+    ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strCmd2, strRet2, true);
     if(ret != 0)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "获取对比项通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -125,12 +125,8 @@ bool FromWebAPI::getCompareItemInfo(QList<CompareItemInfo_t>& listItems)
             roadInfo.nCompareRoadNum = item["roadnum"].get<int>();
             roadInfo.strCompareRoadName = QString::fromStdString(item["roadname"].get<std::string>());
             roadInfo.isEnableRecord = item["roadrecordenable"].get<bool>();
-            roadInfo.scRoadInfo.nSoundCardNum = item["soundcardnum"].is_null() ? -1 : item["soundcardnum"].get<int>();
-            roadInfo.scRoadInfo.strSoundCardID = item["soundcardid"].is_null() ? "" : QString::fromStdString(item["soundcardid"].get<std::string>());
-            roadInfo.scRoadInfo.strSoundCardName = item["soundcardname"].is_null() ? "" : QString::fromStdString(item["soundcardname"].get<std::string>());
-            roadInfo.scRoadInfo.roadInfo.nRoadNum = item["soundcardroadnum"].is_null() ? -1 : item["soundcardroadnum"].get<int>();
-            roadInfo.scRoadInfo.roadInfo.nChannelID = item["channelid"].is_null() ? -1 : item["channelid"].get<int>();
-            roadInfo.scRoadInfo.roadInfo.strChannelName = item["channelname"].is_null() ? "" : QString::fromStdString(item["channelname"].get<std::string>());
+            roadInfo.scRoadInfo.strSoundCardName = item["soundcardname"].get<std::string>();
+            roadInfo.scRoadInfo.pcmInfo.strPCMName = item["soundcardpcmname"].get<std::string>();
 
             /* 如果这个通道是当前迭代器的,就直接插入,如果不是则重新寻找 */
             if(it->nID == itemID)
@@ -194,7 +190,7 @@ bool FromWebAPI::insertCompareItem(const QList<CompareItemInfo_t>& listItems)
 
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "添加对比项信息失败: {}, {}", ret, strRet.toStdString());
@@ -232,20 +228,17 @@ bool FromWebAPI::insertCompareItemRoad(const QList<CompareItemInfo_t>& listItems
                 jsonRoad["roadName"] = road.strCompareRoadName.toStdString();
                 jsonRoad["roadRecordEnable"] = road.isEnableRecord;
 
-                jsonRoad["soundCardNum"] = road.scRoadInfo.nSoundCardNum;
-                jsonRoad["soundCardID"] = road.scRoadInfo.strSoundCardID.toStdString();
-                jsonRoad["soundCardName"] = road.scRoadInfo.strSoundCardName.toStdString();
-                jsonRoad["soundCardRoadNum"] = road.scRoadInfo.roadInfo.nRoadNum;
-                jsonRoad["channelID"] = road.scRoadInfo.roadInfo.nChannelID;
-                jsonRoad["channelName"] = road.scRoadInfo.roadInfo.strChannelName.toStdString();
+                jsonRoad["soundCardName"] = road.scRoadInfo.strSoundCardName;
+                jsonRoad["soundCardPCMName"] = road.scRoadInfo.pcmInfo.strPCMName;
 
                 json1["paramList"] = jsonRoad;
                 jsonArray.push_back(json1);
             }
         }
+        // SPDLOG_LOGGER_DEBUG(m_logger, "插入对比项通道信息: {}", jsonArray.dump(4));
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "添加对比项通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -298,7 +291,7 @@ bool FromWebAPI::updateCompareItemOnly(const QList<CompareItemInfo_t>& listItems
 
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "更新对比项信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -358,12 +351,8 @@ bool FromWebAPI::updateCompareItemOneRoadOnly(const QList<CompareItemInfo_t>& li
                 jsonRoad["roadName"] = road.strCompareRoadName.toStdString();
                 jsonRoad["roadRecordEnable"] = road.isEnableRecord;
 
-                jsonRoad["soundCardNum"] = road.scRoadInfo.nSoundCardNum;
-                jsonRoad["soundCardID"] = road.scRoadInfo.strSoundCardID.toStdString();
-                jsonRoad["soundCardName"] = road.scRoadInfo.strSoundCardName.toStdString();
-                jsonRoad["soundCardRoadNum"] = road.scRoadInfo.roadInfo.nRoadNum;
-                jsonRoad["channelID"] = road.scRoadInfo.roadInfo.nChannelID;
-                jsonRoad["channelName"] = road.scRoadInfo.roadInfo.strChannelName.toStdString();
+                jsonRoad["soundCardName"] = road.scRoadInfo.strSoundCardName;
+                jsonRoad["soundCardPCMName"] = road.scRoadInfo.pcmInfo.strPCMName;
 
                 json1["paramList"] = jsonRoad;
                 jsonArray.push_back(json1);
@@ -371,7 +360,7 @@ bool FromWebAPI::updateCompareItemOneRoadOnly(const QList<CompareItemInfo_t>& li
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "更新对比项通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -404,7 +393,7 @@ bool FromWebAPI::deleteCompareItem(const QList<int> listIDs)
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除对比项信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -438,7 +427,7 @@ bool FromWebAPI::deleteCompareItemRoad(const QList<int>& listIDs)
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除对比项通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -474,7 +463,7 @@ bool FromWebAPI::deleteCompareItemRoad(QMap<int, QList<int>>& mapItemRoads)
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除对比项通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -494,7 +483,7 @@ bool FromWebAPI::getSystemConfig(QMap<std::string, std::string>& mapConfig)
         json0["opName"] = "ACAS_GetSystemConfigInfo";
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置信息失败, 错误码: {}, {}", ret, strRet.toStdString());
@@ -539,7 +528,7 @@ bool FromWebAPI::updateSystemConfig(const std::string& key, const std::string& v
     
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "更新系统设置失败, 错误码:{}, {}", ret, strRet.toStdString());
@@ -559,7 +548,7 @@ bool FromWebAPI::getDetectPeriodConfig(QMap<int, DetectPeriodConfig_t>& mapDetec
         json0["opName"] = "ACAS_GetDetectPeriod";
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "获取对比项检测时段信息失败, 错误码: {}, {}", ret, strRet.toStdString());
@@ -683,7 +672,7 @@ bool FromWebAPI::insertDetectPeriodConfig(const QMap<int, DetectPeriodConfig_t>&
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "写入 对比项检测计划 信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -715,7 +704,7 @@ bool FromWebAPI::deleteDetectPeriodConfig(const QList<int>& listIDs)
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除对比项检测时段信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -743,9 +732,8 @@ bool FromWebAPI::insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
             jsonAlarm["itemID"] = it.CompareItemID;
             jsonAlarm["itemName"] = it.strCompareItemName.toStdString();
             jsonAlarm["alarmType"] = static_cast<int>(it.AlarmType);
-            jsonAlarm["soundCardNum"] = it.RoadInfo.nCompareRoadNum;
-            jsonAlarm["soundCardName"] = it.RoadInfo.strCompareRoadName.toStdString();
-            jsonAlarm["soundCardRoadNum"] = it.RoadInfo.scRoadInfo.roadInfo.nRoadNum;
+            jsonAlarm["soundCardName"] = it.RoadInfo.scRoadInfo.strSoundCardName;
+            jsonAlarm["soundCardPCMName"] = it.RoadInfo.scRoadInfo.pcmInfo.strPCMName;
             jsonAlarm["compareRoadNum"] = it.RoadInfo.nCompareRoadNum;
             jsonAlarm["compareRoadName"] = it.RoadInfo.strCompareRoadName.toStdString();
             jsonAlarm["compareRoadType"] = static_cast<int>(it.RoadType);
@@ -762,7 +750,7 @@ bool FromWebAPI::insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
         }
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "写入报警数据失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -786,9 +774,8 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         json1["itemID1"] = mainAlarm.CompareItemID;
         json1["itemName1"] = mainAlarm.strCompareItemName.toStdString();
         json1["alarmType1"] = static_cast<int>(mainAlarm.AlarmType);
-        json1["soundCardNum1"] = mainAlarm.RoadInfo.nCompareRoadNum;
-        json1["soundCardName1"] = mainAlarm.RoadInfo.strCompareRoadName.toStdString();
-        json1["soundCardRoadNum1"] = mainAlarm.RoadInfo.scRoadInfo.roadInfo.nRoadNum;
+        json1["soundCardName1"] = mainAlarm.RoadInfo.scRoadInfo.strSoundCardName;
+        json1["soundCardPCMName1"] = mainAlarm.RoadInfo.scRoadInfo.pcmInfo.strPCMName;
         json1["compareRoadNum1"] = mainAlarm.RoadInfo.nCompareRoadNum;
         json1["compareRoadName1"] = mainAlarm.RoadInfo.strCompareRoadName.toStdString();
         json1["compareRoadType1"] = static_cast<int>(mainAlarm.RoadType);
@@ -802,9 +789,8 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         json1["itemID2"] = subAlarm.CompareItemID;
         json1["itemName2"] = subAlarm.strCompareItemName.toStdString();
         json1["alarmType2"] = static_cast<int>(subAlarm.AlarmType);
-        json1["soundCardNum2"] = subAlarm.RoadInfo.nCompareRoadNum;
-        json1["soundCardName2"] = subAlarm.RoadInfo.strCompareRoadName.toStdString();
-        json1["soundCardRoadNum2"] = subAlarm.RoadInfo.scRoadInfo.roadInfo.nRoadNum;
+        json1["soundCardName2"] = subAlarm.RoadInfo.scRoadInfo.strSoundCardName;
+        json1["soundCardPCMName2"] = subAlarm.RoadInfo.scRoadInfo.pcmInfo.strPCMName;
         json1["compareRoadNum2"] = subAlarm.RoadInfo.nCompareRoadNum;
         json1["compareRoadName2"] = subAlarm.RoadInfo.strCompareRoadName.toStdString();
         json1["compareRoadType2"] = static_cast<int>(subAlarm.RoadType);
@@ -819,7 +805,7 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         // SPDLOG_LOGGER_DEBUG(m_logger, "写入一致性报警信息: {}", json0.dump(4));
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "写入一致性报警信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -843,7 +829,7 @@ bool FromWebAPI::deleteAlarmInfoBeforeTime(const QDateTime& timePoint)
         json0["paramList"] = jsonParam;
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除早于一定时间的报警信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -866,7 +852,7 @@ bool FromWebAPI::getAlarmInfoBeforeTime(const QDateTime& timePoint, std::list<Al
         json0["paramList"] = jsonParam;
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "获取早于某个时间点的报警信息失败: {}, {}", ret, strRet.toStdString());
@@ -926,7 +912,7 @@ bool FromWebAPI::updateAlarmFileState(const std::list<AlarmInfo_t>& listAlarm)
 
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "更新报警文件状态失败失败: {}, {}", ret, strRet.toStdString());
@@ -959,8 +945,8 @@ bool FromWebAPI::insertRecordFileInfo(const std::list<RecordFileInfo_t>& listRec
             jsonRecord["itemName"] = it.ItemName.toStdString();
             jsonRecord["itemRoadNum"] = it.ItemRoadNum;
             jsonRecord["itemRoadName"] = it.ItemRoadName.toStdString();
-            jsonRecord["soundCardNum"] = it.SoundCardNum;
-            jsonRecord["soundCardRoadNum"] = it.SoundCardRoadNum;
+            jsonRecord["soundCardName"] = it.scRoadInfo.strSoundCardName;
+            jsonRecord["soundCardPCMName"] = it.scRoadInfo.pcmInfo.strPCMName;
 
             jsonRecord["fileStartTime"] = it.FileStartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
             jsonRecord["fileEndTime"] = it.FileEndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
@@ -976,7 +962,7 @@ bool FromWebAPI::insertRecordFileInfo(const std::list<RecordFileInfo_t>& listRec
         // SPDLOG_LOGGER_DEBUG(m_logger, "写入录音文件信息: {}", jsonArray.dump(4));
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "写入录音文件数据失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -1003,8 +989,9 @@ bool FromWebAPI::updateRecordFileInfo(const std::list<RecordFileInfo_t>& listRec
             nJson jsonRecord;
             jsonRecord["itemID"] = it.ItemID;
             jsonRecord["itemRoadNum"] = it.ItemRoadNum;
-            jsonRecord["soundCardNum"] = it.SoundCardNum;
-            jsonRecord["soundCardRoadNum"] = it.SoundCardRoadNum;
+            jsonRecord["itemRoadName"] = it.ItemRoadName.toStdString();
+            jsonRecord["soundCardName"] = it.scRoadInfo.strSoundCardName;
+            jsonRecord["soundCardPCMName"] = it.scRoadInfo.pcmInfo.strPCMName;
 
             jsonRecord["fileStartTime"] = it.FileStartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
             jsonRecord["fileEndTime"] = it.FileEndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
@@ -1016,9 +1003,10 @@ bool FromWebAPI::updateRecordFileInfo(const std::list<RecordFileInfo_t>& listRec
             
             jsonArray.push_back(json1);
         }
+        
         QString strSend = QString::fromStdString(jsonArray.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "更新录音文件数据失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -1038,7 +1026,7 @@ bool FromWebAPI::deleteAllRecordFileInfo()
         json0["opName"] = "ACAS_DeleteAllRecordFileInfo";
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "设置所有录音文件状态失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -1061,7 +1049,7 @@ bool FromWebAPI::deleteRecordFileInfoBeforeTime(const QDateTime& timePoint)
         json0["paramList"] = jsonParam;
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "删除早于一定时间的录音文件信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
@@ -1084,7 +1072,7 @@ bool FromWebAPI::getRecordFileInfoBeforeTime(const QDateTime& timePoint, std::li
         json0["paramList"] = jsonParam;
         QString strSend = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet, true);
         if(ret != 0)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "获取 录音文件信息 失败, 错误码: {}, {}", ret, strRet.toStdString());
@@ -1110,8 +1098,8 @@ bool FromWebAPI::getRecordFileInfoBeforeTime(const QDateTime& timePoint, std::li
             recordFile.ItemName = QString::fromStdString(item["itemname"].get<std::string>());
             recordFile.ItemRoadNum = item["itemroadnum"].get<int>();
             recordFile.ItemRoadName = QString::fromStdString(item["itemroadname"].get<std::string>());
-            recordFile.SoundCardNum = item["soundcardnum"].get<int>();
-            recordFile.SoundCardRoadNum = item["soundcardroadnum"].get<int>();
+            recordFile.scRoadInfo.strSoundCardName = item["soundcardname"].get<std::string>();
+            recordFile.scRoadInfo.pcmInfo.strPCMName = item["soundcardpcmname"].get<std::string>();
             recordFile.FileStartTime = QDateTime::fromString(QString::fromStdString(item["filestarttime"].get<std::string>()), "yyyy-MM-dd HH:mm:ss");
             recordFile.FileEndTime = QDateTime::fromString(QString::fromStdString(item["fileendtime"].get<std::string>()), "yyyy-MM-dd HH:mm:ss");
             recordFile.FilePath = QString::fromStdString(item["filepath"].get<std::string>());
@@ -1127,5 +1115,125 @@ bool FromWebAPI::getRecordFileInfoBeforeTime(const QDateTime& timePoint, std::li
 }
 
 
+/* 获取声卡信息 */
+bool FromWebAPI::getSoundCardInfo(std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard)
+{
+    try
+    {
+        nJson json0;
+        json0["opName"] = "ACAS_GetSoundCardPCMChannels";
+        QString strSend = QString::fromStdString(json0.dump());
+        QString strRet;
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Select, strSend, strRet, true);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "获取声卡信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+
+        /* 解析并转换成小写key */
+        nJson jsonRet;
+        convertJsonKeyToLower(nJson::parse(strRet.toStdString()), jsonRet);
+        int code = jsonRet["code"].get<int>();
+        if(code != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "获取声卡信息失败,错误码: {}, 错误信息: {}", code, jsonRet["message"].get<std::string>());
+            return false;
+        }
+
+        nJson jsonResult = jsonRet["result"];
+        mapSoundCard.clear();
+
+        for(const auto& item : jsonResult)
+        {
+            std::string soundCardName = item["soundcardname"].get<std::string>();
+            auto it = mapSoundCard.find(soundCardName);
+            if(it == mapSoundCard.end())
+            {
+                mapSoundCard[soundCardName] = SoundCardPCMInfo_t();
+                it = mapSoundCard.find(soundCardName);
+            }
+
+            // 找到对应的声卡信息
+            SoundCardPCMInfo_t& soundCardInfo = it->second;
+            soundCardInfo.strSoundCardName = soundCardName;
+
+            OnePCMChannelInfo_t pcmChannelInfo;
+            pcmChannelInfo.strPCMName = item["pcmname"].get<std::string>();
+            pcmChannelInfo.strPCMDesc = item["pcmdesc"].get<std::string>();
+            pcmChannelInfo.strIO = item["ioid"].get<std::string>();
+            soundCardInfo.listPCM.push_back(pcmChannelInfo);
+            
+        }
+
+    } nJsonCatch
+
+    return true;
+}
+
+/* 清空表格 */
+bool FromWebAPI::clearSoundCardInfo()
+{
+    try
+    {
+        nJson json0;
+        json0["opName"] = "ACAS_ClearSoundCardPCMInfo";
+        QString strSend = QString::fromStdString(json0.dump());
+        QString strRet;
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strSend, strRet, true);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "清空声卡信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+    }nJsonCatch
+
+    return true;
+}
+
+/* 插入PCM通道信息 */
+bool FromWebAPI::insertPCMChannelInfo(const std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard)
+{
+    try 
+    {
+        nJson jsonArray = nJson::array();
+        int Key = 1;
+
+        for(const auto& soundCard : mapSoundCard)
+        {
+
+            for(const auto& pcmChannel : soundCard.second.listPCM)
+            {
+                nJson jsonItem;
+                jsonItem["Key"] = Key++;
+                jsonItem["opName"] = "ACAS_InsertSoundCardPCMChannels";
+                nJson jsonParam;
+                jsonParam["soundCardName"] = soundCard.first;
+                jsonParam["pcmName"] = pcmChannel.strPCMName;
+                jsonParam["pcmDesc"] = pcmChannel.strPCMDesc;
+                jsonParam["ioid"] = pcmChannel.strIO;
+                jsonParam["soundCardNum"] = 0;
+                jsonParam["soundCardRoadNum"] = 0;
+
+                jsonItem["paramList"] = jsonParam;
+
+                jsonArray.push_back(jsonItem);
+            }
+        }
+
+        QString strSend = QString::fromStdString(jsonArray.dump());
+        QString strRet;
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet, true);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "插入PCM通道信息失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+
+    }nJsonCatch
+
+    return true;
+}
+
 
 

+ 9 - 0
common/Network/FromWebAPI.h

@@ -74,6 +74,15 @@ public:
     /* 获取早于某个时间点的录音文件信息 */
     bool getRecordFileInfoBeforeTime(const QDateTime& timePoint, std::list<RecordFileInfo_t>& listRecordFile);
 
+    /* ================================================================================== */
+    /* 获取声卡信息 */
+    bool getSoundCardInfo(std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard);
+    /* 清空表格 */
+    bool clearSoundCardInfo();
+    /* 插入PCM通道信息 */
+    bool insertPCMChannelInfo(const std::map<std::string, SoundCardPCMInfo_t>& mapSoundCard);
+
+
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
 

+ 3 - 1
show1/widget.cpp

@@ -28,7 +28,9 @@ Widget::Widget(QWidget *parent) :
     // 初始化数据
     stInitData initData;
     initData.strWebAddr = "http://192.1.3.133:31000/v6/";
-    initData.strDBID = "cf6b57fa3d9841e22c3c897e6b8e66b8";
+    
+    initData.strDBID = "cf6b57fa3d9841e22c3c897e6b8e66b8";       /* 达梦数据库 */
+    // initData.strDBID = "3b8889a0d58b8d71affc04bc27d14e42";          /* GBase */
     DoInit(&initData);
     // 创建窗口
     int skinType = 0; // 0: 白色风格, 1: 黑色风格

+ 344 - 0
show3/AudioRecord/AudioRecord.cpp

@@ -0,0 +1,344 @@
+#include "AudioRecord.h"
+#include "spdlog.h"
+
+
+#include <alsa/pcm.h>
+#include <chrono>
+#include <cstdint>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "spdlog/spdlog.h"
+
+
+/* 获取声卡名称列表 */
+bool AudioDevice::getAudioDevices(std::list<AudioDevice_t> &devices)
+{
+	snd_ctl_t *card_handle;
+	snd_ctl_card_info_t *info;
+	int card = -1;
+	while (snd_card_next(&card) >= 0 && card >= 0) 
+	{
+		char name[32];
+		snprintf(name, sizeof(name), "hw:%d", card);
+		
+		if (snd_ctl_open(&card_handle, name, 0) < 0) {
+			continue; // 无法打开声卡
+		}
+
+		snd_ctl_card_info_alloca(&info);
+		if (snd_ctl_card_info(card_handle, info) < 0) {
+			snd_ctl_close(card_handle);
+			continue; // 获取声卡信息失败
+		}
+		AudioDevice_t device;
+		/* 获取声卡信息 */
+		device.CardNumber = card;
+		device.CardID = snd_ctl_card_info_get_id(info);
+		device.CardName = snd_ctl_card_info_get_name(info);
+		device.CardDriver = snd_ctl_card_info_get_driver(info);
+		device.CardLongName = snd_ctl_card_info_get_longname(info);
+		device.CardMixername = snd_ctl_card_info_get_mixername(info);
+		device.CardComponents = snd_ctl_card_info_get_components(info);
+
+		/* 获取声卡中的所有pcm设备 */
+		snd_pcm_info_t *pcm_info;
+		snd_pcm_info_alloca(&pcm_info);
+		int pcmDevice = -1;
+		while(true)
+		{
+			if(snd_ctl_pcm_next_device(card_handle, &pcmDevice) < 0 || pcmDevice < 0) 
+			{
+				break; // 没有更多的PCM设备
+			}
+			snd_pcm_info_set_device(pcm_info, pcmDevice);
+			snd_pcm_info_set_subdevice(pcm_info, 0); // 获取主设备
+			snd_pcm_info_set_stream(pcm_info, SND_PCM_STREAM_CAPTURE); // 获取捕获设备信息
+
+			if(snd_ctl_pcm_info(card_handle, pcm_info) < 0) 
+			{
+				continue; // 获取PCM设备信息失败
+			}
+			PCMDevice_t pcmDeviceInfo;
+			pcmDeviceInfo.PCMDevice = snd_pcm_info_get_device(pcm_info);
+			pcmDeviceInfo.SubDevice = snd_pcm_info_get_subdevice(pcm_info);
+			pcmDeviceInfo.CardNumber = card;
+			pcmDeviceInfo.PCMID = snd_pcm_info_get_id(pcm_info);
+			pcmDeviceInfo.PCMName = snd_pcm_info_get_name(pcm_info);
+			pcmDeviceInfo.PCMSubName = snd_pcm_info_get_subdevice_name(pcm_info);
+
+			// 将PCM设备信息添加到声卡设备列表中
+			device.PCMDevices.push_back(pcmDeviceInfo);
+		}
+		
+		devices.push_back(device);
+
+		snd_ctl_close(card_handle);
+	}
+
+	return true;
+}
+
+
+/* 获取声卡所有的录音列表 */
+// bool AudioDevice::getAllSoundCard()
+// {
+// 	    int err = 0;
+//         void** hints;
+//         err = snd_device_name_hint(-1, "pcm", &hints);
+//         if(err != 0)
+//         {
+//             LH_WRITE_ERROR(QString("Get audio device count error %1").arg(snd_strerror(err)));
+//             return;
+//         }
+
+//         QStringList audioDevList;
+//         void** n = hints;
+//         while(*n != NULL)
+//         {
+//             char* chname = snd_device_name_get_hint(*n, "NAME");
+//             if(chname != NULL && 0 != strcmp("null", chname))
+//             {
+//                 QByteArray devName(chname);
+//                 if(devName.contains("mic"))
+//                 {
+//                     audioDevList.append(QByteArray(chname));
+//                 }
+//                 //audioDevList.append(QByteArray(chname));
+//             }
+//             n++;
+//         }
+
+//         snd_device_name_free_hint((void**)hints);
+// }
+
+
+bool AudioDevice::getPCMAudioDevice(int cardID, std::list<AudioDeviceDesc_t> &devices)
+{
+	void **hints;
+    int err = snd_device_name_hint(cardID, "pcm", &hints);
+    if (err < 0) {
+        SPDLOG_ERROR("无法获取声卡设备信息: {}", snd_strerror(err));
+        return false;
+    }
+	if (hints == NULL) {
+		SPDLOG_ERROR("没有找到任何声卡设备");
+		return false;
+	}
+    void **n = hints;
+    while (*n != NULL) {
+        char *name = snd_device_name_get_hint(*n, "NAME"); // 设备字符
+        char *desc = snd_device_name_get_hint(*n, "DESC"); // 设备描述
+        char *ioid = snd_device_name_get_hint(*n, "IOID"); // 输入/输出类型
+		char *card = snd_device_name_get_hint(*n, "CARD"); // 声卡名称
+		char* devName = snd_device_name_get_hint(*n, "DEV"); /* 设备编号 */
+
+        if (name == nullptr)
+		{
+            continue; // 跳过没有名称的设备
+        }
+		AudioDeviceDesc_t deviceDesc;
+        deviceDesc.DeviceName = name;
+		deviceDesc.DeviceDesc = desc ? desc : "无描述";
+		deviceDesc.IOID = ioid ? ioid : "未知类型";
+		deviceDesc.Card = card ? card : "未知声卡";
+		deviceDesc.DevNum = devName ? devName : "未知设备编号";
+
+		devices.push_back(deviceDesc);
+
+        if (name) free(name);
+        if (desc) free(desc);
+        if (ioid) free(ioid);
+		if (card) free(card);
+		if (devName) free(devName);
+        n++;
+    }
+    snd_device_name_free_hint(hints);
+
+	return true;
+}
+
+
+
+
+
+
+/* 打印声卡字符设备,设置对齐 */
+void AudioDevice::printPCMAudioDevice(const std::list<AudioDeviceDesc_t> &devices)
+{
+	for (const auto &device : devices)
+	{
+		SPDLOG_INFO("设备名称: {}, IOID: {}, 声卡: {}, 通道编号: {}, 设备描述: {}",
+			device.DeviceName, device.IOID, device.Card, device.DevNum, device.DeviceDesc);
+	}
+}
+
+
+
+/**
+ * @brief Set the Record Params object
+ * 
+ * @param sampleRate 采样率
+ * @param bits 位深度,支持8位,16位,24位,32位
+ * @param channels 通道数
+ */
+void AudioRecord::setRecordParams(int sampleRate, int bits, int channels)
+{
+	m_sampleRate = sampleRate;
+	m_bitDepth = bits;
+	m_channels = channels;
+	m_oneSampleSize = (m_bitDepth / 8) * m_channels; // 单个采样点的大小,单位字节
+}
+
+
+/* 打开录音通道 */
+bool AudioRecord::openRecordChannel(const std::string &deviceName)
+{
+	m_deviceName = deviceName;
+	/* 计算缓冲区大小和周期大小
+	 * 周期大小是指一个周期有多少个采样点,缓冲区大小是周期大小 * 周期个数,这里不需要设置周期个数
+	 * 直接设置缓冲区大小,系统会自动计算周期个数,缓冲区是个环形队列
+	 * 周期大小最好设置成可以被采样率的整数除尽,每次取出1秒数据的时候,间隔相差时间最短 */
+	snd_pcm_uframes_t buffer_size = m_sampleRate / 5; 		// 设置缓冲区大小为采样率的1/5秒
+	snd_pcm_uframes_t period_size = buffer_size / 10;	 	// 设置周期大小为缓冲区大小的1/10秒
+
+	_snd_pcm_format bit_frame = _snd_pcm_format::SND_PCM_FORMAT_UNKNOWN;
+	if(m_bitDepth == 8)
+	{
+		bit_frame = SND_PCM_FORMAT_S8; // 8位采样格式
+	}
+	else if (m_bitDepth == 16)
+	{
+		bit_frame = SND_PCM_FORMAT_S16_LE; // 16位小端格式
+	}
+	else if (m_bitDepth == 24)
+	{
+		bit_frame = SND_PCM_FORMAT_S24_LE; // 24位小端格式
+	}
+	else if (m_bitDepth == 32)
+	{
+		bit_frame = SND_PCM_FORMAT_S32_LE; // 32位小端格式
+	}
+	else
+	{
+		SPDLOG_ERROR("不支持的采样位深度: {}", m_bitDepth);
+		return false;
+	}
+
+	snd_pcm_hw_params_t *hw_params;
+	int err;
+	/* 打开声卡设备 */
+	if ((err = snd_pcm_open(&m_captureHandle, deviceName.c_str(), SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+		SPDLOG_ERROR("无法打开音频设备 {}: {}", deviceName, snd_strerror(err));
+		return false;
+	}
+	/* 分配硬件参数结构 */
+	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+		SPDLOG_ERROR("无法分配硬件参数结构: {}", snd_strerror(err));
+		snd_pcm_close(m_captureHandle);
+		return false;
+	}
+	/* 初始化硬件参数结构 */
+	if ((err = snd_pcm_hw_params_any(m_captureHandle, hw_params)) < 0) {
+		SPDLOG_ERROR("无法初始化硬件参数结构: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置访问类型 */
+	if ((err = snd_pcm_hw_params_set_access(m_captureHandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+		SPDLOG_ERROR("无法设置访问类型: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置采样格式 */
+	if ((err = snd_pcm_hw_params_set_format(m_captureHandle, hw_params, bit_frame)) < 0) {
+		SPDLOG_ERROR("无法设置采样格式: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置采样率 */
+	if ((err = snd_pcm_hw_params_set_rate(m_captureHandle, hw_params, m_sampleRate, 0)) < 0) {
+		SPDLOG_ERROR("无法设置采样率: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置通道数 */
+	if ((err = snd_pcm_hw_params_set_channels(m_captureHandle, hw_params, m_channels)) < 0) {
+		SPDLOG_ERROR("无法设置通道数: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置缓冲区大小 */
+	if ((err = snd_pcm_hw_params_set_buffer_size(m_captureHandle, hw_params, buffer_size)) < 0) {
+		SPDLOG_ERROR("无法设置缓冲区大小: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 设置周期大小 */
+	if ((err = snd_pcm_hw_params_set_period_size(m_captureHandle, hw_params, period_size, 0)) < 0) {
+		SPDLOG_ERROR("无法设置周期大小: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 应用硬件参数 */
+	if ((err = snd_pcm_hw_params(m_captureHandle, hw_params)) < 0) {
+		SPDLOG_ERROR("无法应用硬件参数: {}", snd_strerror(err));
+		goto snd_free;
+		return false;
+	}
+	/* 释放硬件参数结构 */
+	snd_pcm_hw_params_free(hw_params);
+	/* 准备PCM设备 */
+	if ((err = snd_pcm_prepare(m_captureHandle)) < 0) {
+		SPDLOG_ERROR("无法准备PCM设备: {}", snd_strerror(err));	
+		snd_pcm_close(m_captureHandle);
+		return false;
+	}
+
+	return true;
+
+snd_free:
+	snd_pcm_hw_params_free(hw_params);
+	snd_pcm_close(m_captureHandle);
+	return false;
+}
+
+/**
+ * @brief 读取录音大小
+ * 
+ * @param buffer 数据缓冲区指针
+ * @param bufferSize 缓冲区大小,缓冲区大小需要大于等于 recordFrames * 单个采样点的大小
+ *                   例如:44100帧 * 2通道 * 2字节
+ * @param recordFrames 需要读取的帧数,一帧就是一个采样点,16bit / 2 * 2 通道 = 4字节
+ *                     44100帧就是1秒
+ * @return int32_t 读取到的字节数
+ */
+int AudioRecord::recordAudio(char* buffer, int32_t bufferSize, int32_t recordFrames)
+{
+	if(m_captureHandle == nullptr) 
+	{
+		SPDLOG_WARN("PCM设备未打开,请先调用 openAudioChannel 打开设备");
+		return -1;
+	}
+	if (buffer == nullptr || bufferSize == 0) 
+	{
+		SPDLOG_WARN("缓冲区指针为空或缓冲区大小为0");
+		return -1;
+	}
+	if(recordFrames * m_oneSampleSize > bufferSize) 
+	{
+		SPDLOG_ERROR("缓冲区大小不足,无法存储 {} 帧数据", recordFrames);
+		return -1;
+	}
+	auto readFrames = snd_pcm_readi(m_captureHandle, buffer, recordFrames);
+	if (readFrames < 0)
+	{
+		SPDLOG_ERROR("获取录音数据失败: {}", snd_strerror(readFrames));
+		return -1;
+	}
+	
+	return readFrames * m_oneSampleSize; // 返回读取到的字节数
+}
+
+

+ 125 - 0
show3/AudioRecord/AudioRecord.h

@@ -0,0 +1,125 @@
+#ifndef AUDIORECORD_H
+#define AUDIORECORD_H
+
+
+#include <cstdint>
+#include <list>
+#include <string>
+
+#include <alsa/asoundlib.h>
+#include <alsa/pcm.h>
+
+/**
+ * @file AudioRecord.h
+ * @brief 声卡录音类,使用ALSA库进行录音
+ * 
+ * 该文件定义了声卡设备信息结构体和录音类,提供获取声卡信息和录音功能。
+ * 依赖库:libasound2-dev
+ * 
+ * @author Your Name
+ * @date 2025-06-29
+ */
+
+
+/* 声卡的PCM信息结构体 */
+struct PCMDevice_t
+{
+    unsigned int PCMDevice;         /* PCM设备编号,打开的设备编号就是这个 */
+    unsigned int SubDevice;         /* 子设备编号 */
+    int CardNumber;                 /* 声卡编号 */
+    std::string PCMID;              /* 声卡ID */
+    std::string PCMName;            /* 声卡名称 */
+    std::string PCMSubName;         /* 子设备名称 */
+};
+
+/**
+ * @brief 声卡设备信息结构体
+ * 
+ */
+struct AudioDevice_t
+{
+    int CardNumber;                 /* 声卡编号,打开录音的设备编号是这个 */
+    std::string CardID;             /* 声卡ID */
+    std::string CardName;           /* 声卡名称 */
+    std::string CardDriver;         /* 驱动名称 */
+    std::string CardLongName;       /* 声卡长名称 */
+    std::string CardMixername;      /* 混音器名称 */
+    std::string CardComponents;     /* 组件信息 */
+    std::list<PCMDevice_t> PCMDevices; /* PCM设备列表 */
+};
+
+
+/**
+ * @brief 直接获取到的声卡通道描述符信息,可以直接用来打开
+ * 
+ */
+struct AudioDeviceDesc_t
+{
+    std::string DeviceName;         /* 设备字符名称,可以直接打开 */
+    std::string DeviceDesc;         /* 设备描述 */
+    std::string IOID;               /* 输入/输出类型 */
+    std::string Card;               /* 声卡编号或标识,可能会没有 */
+    std::string DevNum;             /* 设备编号,可能会没有 */
+};
+
+/* 使用命名空间包装一下 */
+namespace AudioDevice 
+{
+    /* 获取声卡信息列表,包括可以用来录音的PCM列表 */
+    bool getAudioDevices(std::list<AudioDevice_t> &devices);
+    /* 获取声卡所有的录音列表 */
+    // bool getAllSoundCard();
+    /* 获取声卡字符设备名称,可以直接被打开 */
+    bool getPCMAudioDevice(int cardID, std::list<AudioDeviceDesc_t> &devices);
+    /* 打印声卡字符设备 */
+    void printPCMAudioDevice(const std::list<AudioDeviceDesc_t> &devices);
+    
+}
+
+/**
+ * @brief 录音类
+ * 
+ */
+class AudioRecord
+{
+
+public:
+    AudioRecord() = default;
+    ~AudioRecord() = default;
+
+    /**
+     * @brief Set the Record Params object
+     * 
+     * @param sampleRate 采样率
+     * @param bits 位深度
+     * @param channels 通道数
+     */
+    void setRecordParams(int sampleRate = 44100, int bits = 16, int channels = 2);
+    /* 打开录音通道,通常的格式: "hw:0:0" */
+    bool openRecordChannel(const std::string &deviceName);
+
+    /**
+     * @brief 读取录音大小
+     * 
+     * @param buffer 数据缓冲区
+     * @param bufferSize 缓冲区大小
+     * @param recordFrames 需要读取的帧数,一帧就是一个采样点,16bit / 2 * 2 通道 = 4字节
+     *                     44100帧就是1秒
+     * @return int 读取到的字节数
+     */
+    int recordAudio(char* buffer, int32_t bufferSize, int32_t recordFrames);
+
+private:
+    int32_t m_sampleRate = 44100;      /* 默认采样率 */
+    int m_bitDepth = 16;                /* 默认位深度 */
+    int m_channels = 2;                 /* 默认通道数 */
+    int m_oneSampleSize = 2;            /* 单个采样点的大小,默认16位小端格式,2字节 */
+    std::string m_deviceName;           /* 设备名称,打开的设备名称 */
+
+    snd_pcm_t* m_captureHandle = nullptr; /* PCM设备句柄 */
+    
+};
+
+
+
+#endif // AUDIORECORD_H

+ 4 - 0
show3/CMakeLists.txt

@@ -15,6 +15,8 @@ file(GLOB LOCAL_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/*.ui
 
+    ${CMAKE_CURRENT_SOURCE_DIR}/AudioRecord/*.cpp
+
     ${CMAKE_SOURCE_DIR}/External/module/ThreadPool/*.cpp
 )
 
@@ -38,6 +40,7 @@ add_executable(${this_exe}
 target_include_directories(${this_exe} PRIVATE
 
     ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/AudioRecord
 
     ${CMAKE_SOURCE_DIR}
     ${CMAKE_SOURCE_DIR}/External/common
@@ -60,6 +63,7 @@ target_link_libraries(${this_exe} PRIVATE
 target_link_libraries(${this_exe} PRIVATE
     ${spdlog_LIBRARY}
     libsignalstats.so
+    asound
 )
 
 

+ 17 - 1
show3/main.cpp

@@ -12,6 +12,7 @@
 #include <QAudioOutput>
 #include <QTimer>
 #include <QFile>
+#include "AudioRecord.h"
 
 
 void test1();
@@ -19,6 +20,7 @@ void test2();
 void test3();
 void test4(int argc, char** argv);
 void test5();
+void test6(int argc, char** argv);
 
 int main(int argc, char* argv[]) 
 {
@@ -37,7 +39,8 @@ int main(int argc, char* argv[])
 
     // signalstats_wrapper::finalize();
     // test4(argc, argv);
-    test5();
+    // test5();
+    test6(argc, argv);
 
     std::this_thread::sleep_for(std::chrono::seconds(2));
 
@@ -224,3 +227,16 @@ void test5()
     SPDLOG_INFO("Old: {}, New: {}", str1.toStdString(), str2.toStdString());
 }
 
+
+void test6(int argc, char** argv)
+{
+    if(argc < 2)
+    {
+        SPDLOG_ERROR("Please provide a sound card ID as an argument.");
+        return;
+    }
+    std::list<AudioDeviceDesc_t> devices;
+    AudioDevice::getPCMAudioDevice(atoi(argv[1]), devices);
+    AudioDevice::printPCMAudioDevice(devices);
+}
+

+ 0 - 62
程序设置说明.md

@@ -1,62 +0,0 @@
-# ACA服务设计说明
-
-## 程序架构说明
-### 整体流程
-    读取数据(录音)-> 调用动态库分析数据-> 将结果通过TCP或者MQTT发送出去
-1. 原始采集数据存放在采集类中,由采集类管理
-2. 可以再创建一个生成wav文件的类,用于生成wav文件,管理wav文件
-3. 比对类获取wav文件数据,调用比对动态库进行比对
-4. 
-
-### 数据形式
-1. 从声卡读取出的原始数据是char[]数组,存储在一个环形队列中
-2. 对比时要从环形队列中取出,转换成wav文件,传入动态库API中进行比对
-
-
-### 其他功能
-    噪音对比功能
-
-## 老代码中的东西
-### 使用到的文件和类
-1. Old代码中使用到的文件和类说明
-    |文件|类、结构体|说明|
-    |---|---|---|
-    |Road.h|CRoad类|录音功能|
-    |||生成wav小文件功能|
-    ||DBCalcThread|计算出音量和反相,存储在缓存中,给外部线程使用|
-    |||调用动态库计算噪音功能,计算噪音使用的是原始文件|
-    ||DBCalcRealTimeThread|计算实时音量,貌似只是为了写日志,不向外发送|
-    ||SendForListenThread|发送原始数据|
-    |Channel.h|CompareNewThread()|对比线程|
-    ||CChannel类|对比类,在里面实现对比的相关操作|
-    |SecondData.h|CCacheDataListOfSecond类|维护一个环形队列,存储180秒的音频缓存|
-    ||OneSecondData结构体|环形队列的元素,一秒的录音数据|
-    |ChannelList.h|CChannelList类|开启录制进程,开启对比进程|
-    |TCPServer.h|SendInfo()函数|发送客户端请求的信息|
-    
-## 功能流程
-
-### 初始化一些数据
-
-### 录音功能
-1. 录音到原始文件
-2. 原始文件拷贝一份到计算比对线程,存储到一个环形队列中,队列中的每个单元包含一秒或者几秒的音频数据,计算时取出一定的时间长度,计算出音量,生成wav小文件,进行比对
-3. 原始文件拷贝一份到记录线程,记录到录音文件,1小时一个文件,可以用于发送给客户端
-4. 比对报警时记录报警的时间长度,单独生成一个小的音频文件,单独存放到一个文件夹中。
-
-#### 录音功能处理流程(线程设计)
-1. 获取原始音频的线程,在这里进行数据分发
-2. 一个缓存到环形队列中,生成wav小文件
-3. 一个记录原始音频到文件的线程,每1小时一个wav文件
-4. 一个线程,计算出音量和反相,保存到缓存中
-5. 一个线程,实时向外发送原始音频数据
-6. 一个线程,计算实时音量,写日志,这个貌似不重要,可以合并到其他线程中
-
-### 对比功能
-1. 取出相同时间的两个wav小文件,传入动态库进行比对,获取结果,进行其他操作
-
-### 其他功能(TCP监听服务,UDP发送服务)
-
-
-
-

Some files were not shown because too many files changed in this diff