From: luozheng <1732036298@qq.com> Date: Wed, 26 Jun 2024 09:36:48 +0000 (+0800) Subject: Ai语音添加录音功能 X-Git-Tag: release_V1.2.70_20241020_135402~951 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=1ad9aba91a043546ca9fdf3230a933170ba487a1;p=mirrors%2FFD230.git Ai语音添加录音功能 --- diff --git a/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h b/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h index d5c14a6d1..51971c85a 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h +++ b/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h @@ -2,7 +2,7 @@ * @Author: luozheng 1732036298@qq.com * @Date: 2024-06-20 15:14:43 * @LastEditors: luozheng 1732036298@qq.com - * @LastEditTime: 2024-06-25 17:50:45 + * @LastEditTime: 2024-06-26 17:08:39 * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h */ #ifndef AI_VOICE_MODEL_H @@ -17,6 +17,7 @@ namespace OHOS public: static AiVoiceModel &GetInstance(void); bool ChangeToReturnResultTextView(void); + bool CreateIfNotExists(); bool GetBluetoothIsOpen(void); bool GetMobileDataIsOpen(void); @@ -30,6 +31,12 @@ namespace OHOS std::string GetAIAudioPath(void); + void StartListenAndRecordingUserQuestion(void); + void StopListenAndRecordingUserQuestion(void); + + void AIVoice_StartTimer(uint32_t interval = 1000); + void AIVoice_StopTimer(void); + private: AiVoiceModel(); ~AiVoiceModel(); diff --git a/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp index 0a6cb1ff1..4a9accb19 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp @@ -2,13 +2,21 @@ * @Author: luozheng 1732036298@qq.com * @Date: 2024-06-20 15:14:50 * @LastEditors: luozheng 1732036298@qq.com - * @LastEditTime: 2024-06-25 17:50:59 + * @LastEditTime: 2024-06-26 17:35:48 * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp */ #include "aivoice/include/AiVoiceModel.h" #include "aivoice/include/AiVoicePresenter.h" +#include "aivoice/include/AiVoiceView.h" #include "wearable_log.h" - +#include +#include +#include +#include +#include +#include +#include +#include namespace OHOS { AiVoiceModel::AiVoiceModel() {} @@ -34,6 +42,32 @@ namespace OHOS return true; } + bool AiVoiceModel::CreateIfNotExists() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::CreateIfNotExists"); + const std::string filePath = "/user/userdata/AiRecording/AIAudio.pcm"; + // Check if file exists + FILE *file = fopen(filePath.c_str(), "r"); + if (file != NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File already exists: %s", filePath.c_str()); + fclose(file); + return false; + } + + // File does not exist, create it + file = fopen(filePath.c_str(), "w"); + if (file == NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create file: %s", filePath.c_str()); + return false; + } + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File created: %s", filePath.c_str()); + fclose(file); + + return true; + } + // 获取蓝牙是否打开 bool AiVoiceModel::GetBluetoothIsOpen(void) { @@ -54,7 +88,8 @@ namespace OHOS std::string AiVoiceModel::GetUserQuestionStr(void) { - userQuestionStr = "写一篇100字文章"; + // userQuestionStr = "写一篇100字文章"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "userQuestionStr:\n", userQuestionStr.c_str()); return userQuestionStr; } @@ -65,7 +100,8 @@ namespace OHOS std::string AiVoiceModel::GetAiAnswerStrStr(void) { - aiAnswerStr = "春风化雨,时光荏苒。百年之内,生命如白驹过隙,转瞬即逝。唯有心存善念,用爱化解芥蒂,用智慧建构未来,才是人生的真正意义。让我们携手共进,用每一分时光去关爱他人,用每一滴汗水去创造奇迹,用每一个眼神去传递温暖。让这个世界因我们的存在而变得更加美好。生命短暂,但只要我们怀着虔诚的心,坚韧前行,我们就一定能在有限的时光里留下无限的可能。"; + // aiAnswerStr = "春风化雨,时光荏苒。百年之内,生命如白驹过隙,转瞬即逝。唯有心存善念,用爱化解芥蒂,用智慧建构未来,才是人生的真正意义。让我们携手共进,用每一分时光去关爱他人,用每一滴汗水去创造奇迹,用每一个眼神去传递温暖。让这个世界因我们的存在而变得更加美好。生命短暂,但只要我们怀着虔诚的心,坚韧前行,我们就一定能在有限的时光里留下无限的可能。"; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "aiAnswerStr:\n", aiAnswerStr.c_str()); return aiAnswerStr; } @@ -76,6 +112,149 @@ namespace OHOS std::string AiVoiceModel::GetAIAudioPath(void) { + CreateIfNotExists(); return AIAIAudioPath; } + +#ifdef __cplusplus + extern "C" + { +#endif + int32_t AudioCaptureSample(int32_t argc, const char *argv[]); + +#ifdef __cplusplus + }; +#endif + + // 开始聆听并录取用户问题 + void AiVoiceModel::StartListenAndRecordingUserQuestion(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::RecordingUserQuestion"); + AiVoiceView *view_ = AiVoiceView::GetInstance(); + if (view_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::GetInstance fail!!"); + return; + } + if ((view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) != nullptr) && + (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID)->IsVisible())) + { + const char *defaultArgs[6] = {"01", "pcm", "16000", "1", "16", AiVoiceModel::GetInstance().GetAIAudioPath().c_str()}; + AudioCaptureSample(6, (const char **)defaultArgs); + } + // 开启定时器 + AIVoice_StartTimer(); + + return; + } + + // 停止聆听用户问题 + void AiVoiceModel::StopListenAndRecordingUserQuestion(void) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::StopListenAndRecordingUserQuestion"); + int32_t argc = 1; + uint8_t *argv = (uint8_t *)"stop"; + AudioCaptureSample(argc, (const char **)&argv); + } + + /* -------------------------------------------------------------------------- */ + // 声明定时器变量 + static osTimerId_t g_timer = NULL; + static int Time = 15; + static constexpr int ONE_MINUTE = 60; // 一分钟 + static bool START_FLAG = false; + /*定时器到期时的处理*/ + static void AIVoice_TimerCallbackProc(int data) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AIVoice_TimerCallbackProc,Time = %d", Time); + Time--; + AiVoiceView *view_ = AiVoiceView::GetInstance(); + if (view_ == nullptr) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::GetInstance fail!!"); + return; + } + if (Time <= 0) + { + if ((view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) != nullptr) && + (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID)->IsVisible())) + { + if (AiVoiceModel::GetInstance().GetAiVoiceConnectStatus() == true) + view_->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); + else + view_->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_CONNECT_TIMEOUT_VIEWID); + } + AiVoiceModel::GetInstance().AIVoice_StopTimer(); + } + + return; + } + + /* + * @brief 回调函数 + */ + static void AIVoice_TimerCallback(int data) + { + GraphicService::GetInstance()->PostGraphicEvent(std::bind(AIVoice_TimerCallbackProc, data)); + } + + /* + * @brief 开启定时器函数 + * @param interval 时间间隔,单位ms + */ + void AiVoiceModel::AIVoice_StartTimer(uint32_t interval) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::AIVoice_StartTimer"); + /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */ + if (g_timer != NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!"); + return; + } + + /* --------------------------------- 2.创建定时器 -------------------------------- */ + g_timer = osTimerNew((osTimerFunc_t)AIVoice_TimerCallback, osTimerPeriodic, NULL, NULL); + // 检查定时器创建是否成功 + if (g_timer == NULL) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!"); + return; + } + + /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */ + int tick = osMs2Tick(interval); + + /* --------------------------------- 4.启动定时器 -------------------------------- */ + osStatus_t ret = osTimerStart(g_timer, tick); + /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 NULL -------------------- */ + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + if (g_timer != NULL) + { + ret = osTimerDelete(g_timer); + } + g_timer = NULL; + return; + } + } + + /* + * @brief 停止定时器 + */ + void AiVoiceModel::AIVoice_StopTimer(void) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::AIVoice_StopTimer"); + // 检查定时器是否存在 + if (g_timer != NULL) + { + // 删除定时器并置为 NULL + osStatus_t ret = osTimerDelete(g_timer); + if (ret != osOK) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret); + } + g_timer = NULL; + } + } } diff --git a/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp b/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp index be7a87a66..2ceeb6649 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp @@ -2,7 +2,7 @@ * @Author: luozheng 1732036298@qq.com * @Date: 2024-06-20 15:11:17 * @LastEditors: luozheng 1732036298@qq.com - * @LastEditTime: 2024-06-25 17:39:51 + * @LastEditTime: 2024-06-26 17:34:11 * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp */ #include "AppViewIDs.h" @@ -71,6 +71,7 @@ namespace OHOS WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop"); Presenter::OnStop(); ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); + AiVoiceModel::GetInstance().AIVoice_StopTimer(); } bool AiVoicePresenter::JumpToReturnResultTextView(void) @@ -108,6 +109,7 @@ namespace OHOS else { view_->ChangeView(AIVOICE_STARTCHAT_VIEWID, AIVOICE_LISTENING_VIEWID); // 开始对话->聆听中界面 + model->StartListenAndRecordingUserQuestion(); } return true; } @@ -121,6 +123,7 @@ namespace OHOS else { view_->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 聆听中->思考中界面 + model->StopListenAndRecordingUserQuestion(); } return true; } diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/userdata/AiRecording/AIAudio.pcm b/code/sdk/build/config/target_config/brandy/mk_fs_image/fd230/fs/user/userdata/AiRecording/AIAudio.pcm new file mode 100644 index 000000000..e69de29bb