1.ai界面优化4g调节音量,500ms内调节一次
authorluozheng <1732036298@qq.com>
Sat, 5 Jul 2025 10:00:51 +0000 (18:00 +0800)
committerluozheng <1732036298@qq.com>
Sat, 5 Jul 2025 10:00:51 +0000 (18:00 +0800)
2.解决来电铃声会使4g录音挂掉问题
3.tts播放采用根据符号一句一句播放
4.添加TTS_TEST宏保留测试“回声抑制”环境

code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceView.cpp
code/sdk/application/wearable/fd230app/nativeui/phoneservice/src/PhoneService.cpp
code/sdk/application/wearable/service/msg_center/src/msg_center_customer.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ws.h
code/sdk/middleware/services/media/foundation/sample/wrapper/voice_call_volte_sample_wrapper.cpp
code/sdk/middleware/services/media/foundation/sample/wrapper/voice_call_volte_sample_wrapper.h

index f8b3915..951c09f 100644 (file)
@@ -146,6 +146,10 @@ namespace OHOS
         
         void cancel_tts_play(void);
 
+        void ProcessTextByPunctuation();
+        std::string GetAccumulatedText(void);
+        void sendSegment(const std::string &text, size_t pos);
+
     private:
         AiVoiceModel();
         ~AiVoiceModel();
@@ -162,6 +166,7 @@ namespace OHOS
 #endif
         std::string userQuestionStr;                                         // 用户提出的问题
         std::string aiAnswerStr;                                             // AI回答的问题
+        std::string accumulatedText;                                         // tts播放文本
         uint8_t ChatContentListCount{0};                                     // 列表数量
         static const uint16_t MaxChatContentListCount = 2;                   // 对话列表最大数量
         ChatContentItem chatTtems[MaxChatContentListCount] = {0, "", false}; // 对话项数组
index 200e397..11585bc 100644 (file)
@@ -546,6 +546,319 @@ namespace OHOS
         SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
     }
 
+    // 安全替换 UTF-8 字符串中的字符
+    static void safe_replace_utf8(std::string &str, const std::string &from_chars, char replacement)
+    {
+        std::string result;
+        result.reserve(str.length()); // 预分配足够空间
+
+        const char *p = str.c_str();
+        const char *end = p + str.length();
+
+        while (p < end)
+        {
+            unsigned char c = *p;
+            size_t char_size = 1;
+
+            // 判断 UTF-8 字符的字节数
+            if ((c & 0x80) == 0)
+            {
+                // 1字节字符 (ASCII)
+                char_size = 1;
+            }
+            else if ((c & 0xE0) == 0xC0)
+            {
+                // 2字节字符
+                char_size = 2;
+            }
+            else if ((c & 0xF0) == 0xE0)
+            {
+                // 3字节字符 (常见中文)
+                char_size = 3;
+            }
+            else if ((c & 0xF8) == 0xF0)
+            {
+                // 4字节字符 (如 Emoji)
+                char_size = 4;
+            }
+            else
+            {
+                // 无效字符,按单字节处理
+                char_size = 1;
+            }
+
+            // 检查字符是否在要替换的集合中
+            bool replace = false;
+            if (char_size == 1)
+            {
+                // 单字节字符直接检查
+                replace = (from_chars.find(c) != std::string::npos);
+            }
+            else
+            {
+                // 多字节字符,提取完整字符并检查
+                std::string utf8_char(p, char_size);
+                for (size_t i = 0; i < from_chars.length();)
+                {
+                    // 提取 from_chars 中的下一个 UTF-8 字符
+                    unsigned char fc = from_chars[i];
+                    size_t fc_size = 1;
+
+                    if ((fc & 0x80) == 0)
+                    {
+                        fc_size = 1;
+                    }
+                    else if ((fc & 0xE0) == 0xC0)
+                    {
+                        fc_size = 2;
+                    }
+                    else if ((fc & 0xF0) == 0xE0)
+                    {
+                        fc_size = 3;
+                    }
+                    else if ((fc & 0xF8) == 0xF0)
+                    {
+                        fc_size = 4;
+                    }
+
+                    if (i + fc_size <= from_chars.length())
+                    {
+                        std::string fc_str = from_chars.substr(i, fc_size);
+                        if (fc_str == utf8_char)
+                        {
+                            replace = true;
+                            break;
+                        }
+                    }
+
+                    i += fc_size;
+                }
+            }
+
+            // 添加到结果字符串
+            if (replace)
+            {
+                result += replacement;
+            }
+            else
+            {
+                result.append(p, char_size);
+            }
+
+            p += char_size;
+        }
+
+        // 替换原字符串
+        str.swap(result);
+    }
+
+#if 0
+    void AiVoiceModel::ProcessTextByPunctuation()
+    {
+        const std::string punctuation = ",。!?;:))”、"; // 要替换的中文标点
+        const char replacement = ',';                         // 替换为英文逗号
+        const size_t MAX_SEGMENT_LENGTH = 120;                // 最大分段长度
+
+        if (accumulatedText.empty())
+            return;
+
+        // 安全替换中文标点为英文逗号
+        std::string processedText = accumulatedText;
+        safe_replace_utf8(processedText, punctuation, replacement);
+
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "processedText:%s", processedText.c_str());
+
+        accumulatedText = processedText;
+        size_t commaPos = accumulatedText.find_last_of(',');
+
+        // 处理长度限制,若超过最大长度则强制分段
+        if (accumulatedText.length() >= MAX_SEGMENT_LENGTH)
+        {
+            commaPos = MAX_SEGMENT_LENGTH - 1;
+            // 查找最大长度内最近的逗号
+            size_t lastCommaInRange = accumulatedText.find_last_of(',', commaPos);
+            if (lastCommaInRange != std::string::npos)
+            {
+                commaPos = lastCommaInRange;
+            }
+        }
+
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "commaPos:%d", commaPos);
+
+        if (commaPos != std::string::npos)
+        {
+            // 提取分段(包含英文逗号)
+            std::string segment = accumulatedText.substr(0, commaPos + 1);
+
+            // 清理文本
+            segment.erase(
+                std::remove(segment.begin(), segment.end(), '\n'),
+                segment.end());
+            segment.erase(
+                std::remove(segment.begin(), segment.end(), '\r'),
+                segment.end());
+
+            // 发送到TTS播放
+            if (!segment.empty())
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "播放分段文本: %s (长度: %zu)",
+                              segment.c_str(), segment.length());
+                uapi_start_tts_single_txt((char *)segment.c_str());
+                LOS_Msleep(50);
+            }
+
+            // 更新累积文本
+            if (commaPos + 1 < accumulatedText.length())
+            {
+                accumulatedText = accumulatedText.substr(commaPos + 1);
+            }
+            else
+            {
+                accumulatedText.clear();
+            }
+        }
+        else
+        {
+            // 无逗号时继续累积或强制分段
+            if (accumulatedText.length() > MAX_SEGMENT_LENGTH)
+            {
+                // 强制截断(确保在字符边界)
+                std::string segment = accumulatedText.substr(0, MAX_SEGMENT_LENGTH);
+                // 清理文本
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\n'),
+                    segment.end());
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\r'),
+                    segment.end());
+                // 发送分段
+                if (!segment.empty())
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "强制分段: %s (长度: %zu)",
+                                  segment.c_str(), segment.length());
+                    uapi_start_tts_single_txt((char *)segment.c_str());
+                    LOS_Msleep(50);
+                }
+                // 更新累积文本
+                accumulatedText = accumulatedText.substr(MAX_SEGMENT_LENGTH);
+            }
+            else
+            {
+                // 无逗号且长度不足时继续累积
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "累积文本(未触发): %s", accumulatedText.c_str());
+            }
+        }
+    }
+#endif
+
+    void AiVoiceModel::ProcessTextByPunctuation()
+    {
+        const std::string punctuation = ",。!?;:))”、"; // 要替换的中文标点
+        const char replacement = ',';                         // 替换为英文逗号
+        const size_t MAX_SEGMENT_LENGTH = 120;                // 最大分段长度
+        const size_t MIN_SEGMENT_LENGTH = 1;                  // 最小发送长度(可调整)
+
+        if (accumulatedText.empty())
+            return;
+
+        // 安全替换中文标点为英文逗号
+        std::string processedText = accumulatedText;
+        safe_replace_utf8(processedText, punctuation, replacement);
+
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "processedText:%s", processedText.c_str());
+
+        accumulatedText = processedText;
+        size_t commaPos = accumulatedText.find_last_of(',');
+
+        // 处理长度限制,若超过最大长度则强制分段
+        if (accumulatedText.length() >= MAX_SEGMENT_LENGTH)
+        {
+            commaPos = MAX_SEGMENT_LENGTH - 1;
+            // 查找最大长度内最近的逗号
+            size_t lastCommaInRange = accumulatedText.find_last_of(',', commaPos);
+            if (lastCommaInRange != std::string::npos)
+            {
+                commaPos = lastCommaInRange;
+            }
+        }
+
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "commaPos:%d", commaPos);
+
+        if (commaPos != std::string::npos)
+        {
+            // 按标点分段发送
+            sendSegment(accumulatedText, commaPos);
+        }
+        else
+        {
+            // 无逗号时的处理逻辑
+            if (accumulatedText.length() >= MIN_SEGMENT_LENGTH)
+            {
+                // 强制发送完整文本(无论是否有标点)
+                std::string segment = accumulatedText;
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\n'),
+                    segment.end());
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\r'),
+                    segment.end());
+
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "强制发送文本: %s (长度: %zu)",
+                              segment.c_str(), segment.length());
+                uapi_start_tts_single_txt((char *)segment.c_str());
+                LOS_Msleep(50);
+
+                // 发送后清空累积文本
+                accumulatedText.clear();
+            }
+            else
+            {
+                // 文本过短,继续累积
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "累积文本过短(长度: %zu), 继续累积",
+                              accumulatedText.length());
+            }
+        }
+    }
+
+    // 辅助函数:按标点分段发送
+    void AiVoiceModel::sendSegment(const std::string &text, size_t pos)
+    {
+        // 提取分段(包含英文逗号)
+        std::string segment = text.substr(0, pos + 1);
+
+        // 清理文本
+        segment.erase(
+            std::remove(segment.begin(), segment.end(), '\n'),
+            segment.end());
+        segment.erase(
+            std::remove(segment.begin(), segment.end(), '\r'),
+            segment.end());
+
+        // 发送到TTS播放
+        if (!segment.empty())
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "按标点发送分段: %s (长度: %zu)",
+                          segment.c_str(), segment.length());
+            uapi_start_tts_single_txt((char *)segment.c_str());
+            LOS_Msleep(50);
+        }
+
+        // 更新累积文本
+        if (pos + 1 < text.length())
+        {
+            accumulatedText = text.substr(pos + 1);
+        }
+        else
+        {
+            accumulatedText.clear();
+        }
+    }
+
+    std::string AiVoiceModel::GetAccumulatedText(void)
+    {
+        return accumulatedText;
+    }
+
     void AiVoiceModel::SetAiAnswerStrStr(std::string str, uint8_t type)
     {
         AIResponseType = type;
@@ -561,6 +874,10 @@ namespace OHOS
                     if (!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) // 如果ai答案没有显示到极限了,就更新ai答案字符串
                     {
                         aiAnswerStr += str;
+                        /* -------------------------------------------------------------------------- */
+                        // 累积接收到的文本
+                        accumulatedText += str;
+                        /* -------------------------------------------------------------------------- */
                         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str());
                         SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
                     }
@@ -608,6 +925,7 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "清空上次用户问题和Ai回答字符串");
         userQuestionStr = "";
         aiAnswerStr = "";
+        accumulatedText = "";
     }
 
     /*获取AI音频路径*/
@@ -1237,28 +1555,36 @@ namespace OHOS
 
     /* -------------------------------- tts播放定时器 -------------------------------- */
     static osTimerId_t g_ai4g_is_start_tts_play_Handle = nullptr;
-    static uint8_t AI4G_IS_START_TTS_PLAY_TIME = 1;
-
+    static constexpr const int8_t NUMBER_TEN = 15;
+    static int8_t AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
+    static uint8_t tts_record_flag = 0;
     static void AI4G_IS_START_TTS_CallbackProc(int data)
     {
-        if (AI4G_IS_START_TTS_PLAY_TIME <= 0)
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AI4G_IS_START_TTS_CallbackProc:%s", AiVoiceModel::GetInstance().GetAccumulatedText().c_str());
+        // 用来判断是否需要停止发送文本
+        if (AiVoiceModel::GetInstance().GetAccumulatedText().empty())
         {
             AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
-            std::string str = AiVoiceModel::GetInstance().GetAiAnswerStr();
-            // 移除所有换行符(包括 '\n' 和 '\r')
-            str.erase(
-                std::remove(str.begin(), str.end(), '\n'),
-                str.end());
-            str.erase(
-                std::remove(str.begin(), str.end(), '\r'),
-                str.end());
-            uapi_start_tts_single_txt((char *)str.c_str());
         }
+        if (get_bk_websocket_tts_tick() == 0) // 代表可以发录音文本
+        {
+            AiVoiceModel::GetInstance().ProcessTextByPunctuation();
+        }
+        else
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "get_bk_websocket_tts_tick:%d", get_bk_websocket_tts_tick());
+        }
+#if TTS_TEST
+        if (!tts_record_flag)
+        {
+            tts_record_flag = 1;
+            startAudioCaptureTask(); // 测试汇声抑制的
+        }
+#endif
     }
 
     static void AI4G_IS_START_TTS_Callback(int data)
     {
-        AI4G_IS_START_TTS_PLAY_TIME--;
         AI4G_IS_START_TTS_CallbackProc(data);
         // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_IS_START_TTS_CallbackProc, data));
     }
@@ -1266,7 +1592,7 @@ namespace OHOS
     void AiVoiceModel::start_ai4g_tts_play_timer(uint32_t interval)
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai_isready_timer");
-        AI4G_IS_START_TTS_PLAY_TIME = 3;
+        // AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
         /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
         if (g_ai4g_is_start_tts_play_Handle != nullptr)
         {
@@ -1304,7 +1630,7 @@ namespace OHOS
         // 检查定时器是否存在
         if (g_ai4g_is_start_tts_play_Handle != nullptr)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::stop_ai_isready_timer");
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "stop_ai4g_tts_play_timer");
             osTimerStop(g_ai4g_is_start_tts_play_Handle);
             // 删除定时器并置为 nullptr
             osStatus_t ret = osTimerDelete(g_ai4g_is_start_tts_play_Handle);
@@ -1313,7 +1639,17 @@ namespace OHOS
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
             }
             g_ai4g_is_start_tts_play_Handle = nullptr;
-            AI4G_IS_START_TTS_PLAY_TIME = 1;
+            AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
+#if TTS_TEST
+            tts_record_flag = 0;
+            std::string filePath = "/user/aiRecord456.mp3";
+            // 删除filePath文件
+            if (remove(filePath.c_str()) != 0)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "remove failed, path: %s", filePath.c_str());
+            }
+            StopListenAndRecordingUserQuestion();
+#endif
         }
     }
 
index a164a4b..27c3b0c 100644 (file)
@@ -97,6 +97,7 @@ namespace OHOS
         add_4GAI_vote(); // 4g投票
 
         uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH_AI);
+        Audio::AudioManager::GetInstance().SetVolume(AUDIO_STREAM_VOICE_ASSISTANT, 100); 
     }
 
     // 页面已经展示后的调用逻辑
@@ -321,6 +322,7 @@ namespace OHOS
             AiVoiceModel::GetInstance().ClearQuestionAndAiAnswerStr(); // 清空上次用户问题和Ai回答字符串
             AiVoiceModel::GetInstance().SetIsClickable(false);
             AiVoiceModel::GetInstance().SetIsLimitDisplayed(false);
+            AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
             break;
         default:
             // Handle other cases if needed
@@ -402,6 +404,7 @@ namespace OHOS
                 PlayersModel::GetInstance()->PlayerPause();         // 暂停手机音乐
                 if (model->GetSelect4gorbt() == AI_SELECT_4G)
                 {
+                    AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
                     uapi_UI_start_asr();
                     usleep(50000);
                     ChangeViewAndLogicOperator(AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_AIMODE_CONNECTING);
@@ -417,6 +420,7 @@ namespace OHOS
             {
                 if (model->GetSelect4gorbt() == AI_SELECT_4G)
                 {
+                    AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
                     // model->cancel_tts_play();
                     dinit_ai_task();
                     usleep(50000);
@@ -749,8 +753,8 @@ namespace OHOS
             if (slider)
             {
                 int value = slider->GetValue();
-                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "volume:%d front", value);
-                if (event.GetRotate() > 0)
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d front", value);
+                if (event.GetRotate() <= 0)
                 {
                     WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "222");
                     value += 20;
@@ -768,7 +772,7 @@ namespace OHOS
                         value = 0;
                     }
                 }
-                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "volume:%d end", value);
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d end", value);
                 do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_CHANGE_SYSTEM_VOLUME, (void *)(&value), sizeof(value));
             }
         }
@@ -776,7 +780,27 @@ namespace OHOS
 
     bool AiVoicePresenter::OnRotate(UIView &view, const RotateEvent &event)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotateEnd");
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate");
+        static uint32_t lastCallTime = 0;
+        const uint32_t MIN_INTERVAL = 500; // 最小间隔500ms
+
+        uint32_t currentTime = event.GetTimeStamp();
+
+        // 计算时间间隔
+        uint32_t interval = currentTime - lastCallTime;
+
+        // 仅当间隔大于500ms时才调用ChangeVolume
+        if (interval >= MIN_INTERVAL)
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 允许调用ChangeVolume, 间隔: %ums", interval);
+            ChangeVolume(view, event);
+            lastCallTime = currentTime;
+        }
+        else
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 忽略调用ChangeVolume, 间隔: %ums (需要>500ms)", interval);
+        }
+
         return true;
     }
 
index 2013239..37fcc1e 100644 (file)
@@ -497,7 +497,7 @@ namespace OHOS
             VolumeProcess->SetForegroundStyle(STYLE_BACKGROUND_OPA, 0xff);
             VolumeProcess->SetKnobStyle(StyleDefault::GetSliderKnobStyle());
             VolumeProcess->RequestFocus();
-            VolumeProcess->SetRotateFactor(1.0);
+            VolumeProcess->SetRotateFactor(5.0);
             // VolumeProcess->SetVisible(false);
             VolumeProcess->SetOnRotateListener(presenter_);
             container_->Add(VolumeProcess);
index 0c90da9..f82c016 100644 (file)
@@ -51,6 +51,8 @@ extern "C" {
 #define CALL_TMP_LOG_PATH "/user/userdata/calltmplog.bin"
 #define CALL_LOG_DIR "/user/userdata"
 
+#include  "cat1_ws.h"
+
 #ifndef UNUSED
 #define UNUSED(x) ((void)(x))
 #endif
@@ -1510,6 +1512,8 @@ static void PlayWatchRing(void)
     if(true != OHOS::ConfigModel::GetInstance()->GetDnotdisturb() && (!uapi_sleep_mode_flag_get()) && true != OHOS::ConfigModel::GetInstance()->GetSilentMode())
     {
 
+        dinit_ai_task();
+        LOS_Msleep(50);
         OHOS::AlarmClockModel::GetInstance()->testPlayerStart(RING_MUSIC);
         //g_audioState = AUDIO_ACT_INTERRUPT_WATCH_RING; 
 
index 7921b8b..2896f26 100644 (file)
@@ -94,6 +94,7 @@
 #include "PhoneAGService.h"
 #include <custom_save_runtime.h>
 #include "PhoneServiceC.h"
+#include  "cat1_ws.h"
 
 #define DIALDATASET 1
 //#include "Systemupgrade.h"
@@ -1091,6 +1092,8 @@ void MsgCenterNotifyCatIncomingCallProc(const Topic topic, Request* req)
 
         if(true != ConfigModel::GetInstance()->GetDnotdisturb() && (!uapi_sleep_mode_flag_get()) && true != ConfigModel::GetInstance()->GetSilentMode())
         {
+            dinit_ai_task();
+            LOS_Msleep(50);
             AlarmClockModel::GetInstance()->testPlayerStart(RING_MUSIC);
         }
 
index 5a48951..869db83 100644 (file)
@@ -1126,6 +1126,11 @@ void set_ai_tts_server_init_flag(uint8_t flag)
     ai_tts_server_init_flag = flag;
 }
 
+uint8_t get_bk_websocket_tts_tick(void)
+{
+    return bk_websocket_tts_tick;
+}
+
 void bk_websocket_demo(void *data) {
   
     // while (1)
index a6f7717..0039031 100644 (file)
@@ -34,6 +34,7 @@ uint8_t get_ai_chat_service_init_flag(void);
 void set_ai_chat_service_init_flag(uint8_t flag);
 uint8_t get_ai_tts_server_init_flag(void);
 void set_ai_tts_server_init_flag(uint8_t flag);
+uint8_t get_bk_websocket_tts_tick(void);
 
 void uapi_start_asr_task(void);
 
index 98211d2..a87b229 100755 (executable)
@@ -1285,7 +1285,12 @@ static void AudioCaptureProcess_AI(void* arg)
     }
     MEDIA_ERR_LOG("g_stream_in_uplink->Start");
 
-    uint8_t* data_buf=(uint8_t *)malloc(1024);
+    #if TTS_TEST
+    int ai_size = 2048;
+    #else
+    int ai_size = 1024;
+    #endif
+    uint8_t* data_buf=(uint8_t *)malloc(ai_size);
     if(data_buf == NULL)
     {
         MEDIA_ERR_LOG("malloc");
@@ -1294,7 +1299,7 @@ static void AudioCaptureProcess_AI(void* arg)
 
     AudioCaptureTask_is_run=1;
 
-    FILE *fp= fopen("/user/aiRecord.bin","wb+");
+    FILE *fp= fopen("/user/aiRecord123.mp3","wb+");
 
     uint32_t record_size=0;
 
@@ -1303,7 +1308,7 @@ static void AudioCaptureProcess_AI(void* arg)
         LOS_Msleep(10);
         CapturerBuffer capBuf = {};
         capBuf.data = data_buf;
-        capBuf.size = 1024;
+        capBuf.size = ai_size;
         capBuf.frameCount = 1;
         int32_t readlen = g_stream_in_uplink->ObtainBuffer(capBuf, true);
         if(readlen>0)
@@ -1314,11 +1319,18 @@ static void AudioCaptureProcess_AI(void* arg)
             record_size+=readlen;
 
             fwrite(data_buf,1,readlen,fp);
+            #if TTS_TEST
+            if(record_size>=1024*80)
+            {
+                g_sample_needStop=1;
+            }
+            #else
             if(record_size>=1024*40)
             {
                 g_sample_needStop=1;
             }
-            memset_s(data_buf,1024,0,1024);
+            #endif
+            memset_s(data_buf,ai_size,0,ai_size);
         }
         
         // 蓝牙接口发送实时录音数据
@@ -1402,6 +1414,32 @@ void set_AIStreamend(uint8_t data)
 
 int32_t AIStreamWrite(uint8_t *buf, uint32_t size)
 {
+
+    //保存音频流数据
+    #if TTS_TEST
+    int32_t r = 0;
+    // 文件保存逻辑
+    std::string filePath = "/user/aiRecord456.mp3";
+    FILE *pfd = fopen(filePath.c_str(), "ab+");  // 以追加模式打开文件
+    if (pfd == NULL) {
+        MEDIA_ERR_LOG("fopen failed, path: %s", filePath.c_str());
+        return r;  // 保留原有流写入的返回值
+    }
+    
+    // 写入音频数据到文件
+    size_t written = fwrite(buf, 1, size, pfd);
+    if (written != size) {
+        MEDIA_ERR_LOG("fwrite failed, expected: %u, actual: %zu", size, written);
+    } else {
+        MEDIA_INFO_LOG("Successfully saved %u bytes to file", size);
+    }
+    
+    // 关闭文件
+    if (fclose(pfd) != 0) {
+        MEDIA_ERR_LOG("fclose failed");
+    }
+    #endif
+
     int32_t ret = 0;
     if(buf==NULL && size==1)
     {