作者 ookk303

讯飞2代库优化

1 -#include <fstream>  
2 -#include <assert.h>  
3 -#include <cstring>  
4 -#include <atomic>  
5 -#include <unistd.h>  
6 -#include <string>  
7 -#include <thread>  
8 -#include <mutex>  
9 -#include <condition_variable>  
10 -  
11 -#include "JZsdkLib.h"  
12 -#include "version_choose.h"  
13 -#include "JZsdk_base/JZring/JZring.h"  
14 -  
15 -#if 1  
16 -  
17 -#include "aikit_biz_api.h"  
18 -#include "aikit_constant.h"  
19 -#include "aikit_biz_config.h"  
20 -#include "iflytek_tts.h"  
21 -#include "AudioDeal/AudioDeal.h"  
22 -#include "../../Megaphone.h"  
23 -#include "iflytek_tts.h"  
24 -  
25 -using namespace std;  
26 -using namespace AIKIT;  
27 -  
28 -static std::atomic_bool ttsFinished(false);  
29 -static std::atomic_bool g_playThreadRunning(false);  
30 -static const char *ABILITY = "e2e44feff";  
31 -static AIKIT_HANDLE *g_AikitHandle = nullptr; // 合成句柄  
32 -  
33 -static int IflytekLib_2_StopTts();  
34 -  
35 -#define IFLYTEK_RING_BUF_SIZE (1024 * 100) // 100KB缓冲区  
36 -static T_JZringHandle g_ringHandle = nullptr;  
37 -static char *g_ringBuf = nullptr;  
38 -  
39 -// 同步机制  
40 -static std::mutex g_mutex;  
41 -static std::condition_variable g_cv;  
42 -  
43 -// 播放线程函数  
44 -void PlaybackThreadFunc()  
45 -{  
46 - U8_t buffer[2048]; // 每次读取2KB  
47 - U32_t readSize = 0;  
48 - T_JZsdkReturnCode ret;  
49 -  
50 - g_playThreadRunning = true;  
51 -  
52 - while (g_playThreadRunning)  
53 - {  
54 - // 等待有数据可读  
55 - {  
56 - std::unique_lock<std::mutex> lock(g_mutex);  
57 - U32_t dataCount = 0;  
58 - JZring_GetDataCount(g_ringHandle, &dataCount);  
59 -  
60 - if (dataCount == 0) {  
61 - // 等待最多100ms或通知  
62 - g_cv.wait_for(lock, std::chrono::milliseconds(100));  
63 - continue;  
64 - }  
65 - }  
66 -  
67 - JZSDK_LOG_DEBUG("有数据可读");  
68 -  
69 - // 从环形缓冲区读取数据  
70 - ret = JZring_Read(g_ringHandle, buffer, sizeof(buffer), &readSize);  
71 - if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS || readSize == 0) {  
72 - usleep(10000); // 10ms  
73 - continue;  
74 - }  
75 -  
76 -  
77 -  
78 - // 发送到音频播放器  
79 - AudioDeal_PcmDataInput_TextSteam(16000, buffer, readSize);  
80 -  
81 - // 检查是否需要停止播放  
82 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
83 - break;  
84 - }  
85 - }  
86 -  
87 - g_playThreadRunning = false;  
88 -}  
89 -  
90 -void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output)  
91 -{  
92 - // 检测数据生成标志位是否有关闭  
93 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
94 - IflytekLib_2_StopTts();  
95 - return;  
96 - }  
97 -  
98 - if (output->node->value) {  
99 - JZSDK_LOG_DEBUG("生产了数据%d", output->node->len);  
100 -  
101 - // 写入环形缓冲区  
102 - T_JZsdkReturnCode ret;  
103 - U32_t written = 0;  
104 -  
105 - while (written < static_cast<U32_t>(output->node->len)) {  
106 - U32_t chunkSize = std::min(static_cast<U32_t>(output->node->len) - written,  
107 - static_cast<U32_t>(4096));  
108 -  
109 - ret = JZring_Write(g_ringHandle,  
110 - reinterpret_cast<U8_t*>(output->node->value) + written,  
111 - chunkSize);  
112 -  
113 - if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
114 - JZSDK_LOG_ERROR("写入环形缓冲区失败: %d", ret);  
115 - break;  
116 - }  
117 -  
118 - written += chunkSize;  
119 - }  
120 -  
121 - // 通知播放线程有新数据  
122 - g_cv.notify_one();  
123 - }  
124 -}  
125 -  
126 -void OnEvent(AIKIT_HANDLE* handle, AIKIT_EVENT eventType, const AIKIT_OutputEvent* eventValue) {  
127 - if (eventType == AIKIT_Event_End) {  
128 - ttsFinished = true;  
129 - JZSDK_LOG_INFO("合成完成");  
130 -  
131 - // 通知播放线程所有数据已生成  
132 - g_cv.notify_one();  
133 - }  
134 -}  
135 -  
136 -void OnError(AIKIT_HANDLE* handle, int32_t err, const char* desc) {  
137 - JZSDK_LOG_ERROR("TTS错误: %d, %s", err, desc);  
138 - IflytekLib_2_StopTts();  
139 -}  
140 -  
141 -int IflytekLib_2_TextToTts(int language,  
142 - const char *TtsRole,  
143 - const char *text, int speed, int volume)  
144 -{  
145 - AIKIT_ParamBuilder* paramBuilder = nullptr;  
146 - AIKIT_DataBuilder* dataBuilder = nullptr;  
147 - AiText* aiText_raw = nullptr;  
148 - int ret = 0;  
149 -  
150 - // 重置完成标志  
151 - ttsFinished = false;  
152 -  
153 - // 重置环形缓冲区  
154 - JZring_Reset(g_ringHandle);  
155 -  
156 - paramBuilder = AIKIT_ParamBuilder::create();  
157 - paramBuilder->clear();  
158 - // 设置发音人  
159 - paramBuilder->param("vcn", TtsRole, strlen(TtsRole));  
160 - paramBuilder->param("vcnModel", TtsRole, strlen(TtsRole));  
161 - // 设置语种  
162 - paramBuilder->param("language", language);  
163 - // 设置文本编码  
164 - paramBuilder->param("textEncoding", "UTF-8", strlen("UTF-8"));  
165 - // 音量  
166 - paramBuilder->param("volume", volume);  
167 - // 语速  
168 - paramBuilder->param("speed", speed);  
169 -  
170 - JZSDK_LOG_DEBUG("TTS Role:%s, Text:%s, language:%d", TtsRole, text, language);  
171 -  
172 - ret = AIKIT_Start(ABILITY, AIKIT_Builder::build(paramBuilder), nullptr, &g_AikitHandle);  
173 - if(ret != 0) {  
174 - JZSDK_LOG_ERROR("AIKIT_Start failed: %d", ret);  
175 - goto exit;  
176 - }  
177 -  
178 - dataBuilder = AIKIT_DataBuilder::create();  
179 - dataBuilder->clear();  
180 - aiText_raw = AiText::get("text")->data(text, strlen(text))->once()->valid();  
181 - dataBuilder->payload(aiText_raw);  
182 -  
183 - ret = AIKIT_Write(g_AikitHandle, AIKIT_Builder::build(dataBuilder));  
184 - if(ret != 0) {  
185 - JZSDK_LOG_ERROR("AIKIT_Write failed: %d", ret);  
186 - goto exit;  
187 - }  
188 -  
189 - // 等待合成完成或停止信号  
190 - while(!ttsFinished) {  
191 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
192 - break;  
193 - }  
194 - usleep(10000); // 10ms  
195 - }  
196 -  
197 - // 结束合成  
198 - ret = AIKIT_End(g_AikitHandle);  
199 - g_AikitHandle = nullptr;  
200 -  
201 -exit:  
202 - if(paramBuilder != nullptr) {  
203 - delete paramBuilder;  
204 - }  
205 - if(dataBuilder != nullptr) {  
206 - delete dataBuilder;  
207 - }  
208 -  
209 - return ret;  
210 -}  
211 -  
212 -int IflytekLib_2_Init()  
213 -{  
214 - // 初始化环形缓冲区  
215 - g_ringBuf = new char[IFLYTEK_RING_BUF_SIZE];  
216 - if (JZring_Init(&g_ringHandle, reinterpret_cast<U8_t*>(g_ringBuf), IFLYTEK_RING_BUF_SIZE)  
217 - != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
218 - JZSDK_LOG_ERROR("环形缓冲区初始化失败");  
219 - return -1;  
220 - }  
221 -  
222 - // 启动播放线程  
223 - std::thread(PlaybackThreadFunc).detach();  
224 -  
225 - // 初始化TTS SDK  
226 - AIKIT_Configurator::builder()  
227 - .app()  
228 - .appID("03857dfd")  
229 - .apiSecret("OTA2OTEzMTVlOGYwMjllMmJkYzEwZGY5")  
230 - .apiKey("2b2c60f8a80b8cdfe45ae1058a25149a")  
231 - .workDir("/root/Iflytek_2")  
232 - .auth()  
233 - .authType(0)  
234 - .log()  
235 - .logLevel(LOG_LVL_OFF) //关闭日志打印  
236 - .logMode(LOG_STDOUT); //日志输出为控制台  
237 -  
238 - int ret = AIKIT_Init();  
239 - if(ret != 0) {  
240 - JZSDK_LOG_ERROR("AIKIT_Init failed: %d", ret);  
241 - return -1;  
242 - }  
243 -  
244 - AIKIT_Callbacks cbs = {OnOutput, OnEvent, OnError};  
245 - AIKIT_RegisterAbilityCallback(ABILITY, cbs);  
246 -  
247 - return 0;  
248 -}  
249 -  
250 -int IflytekLib_2_UnInit()  
251 -{  
252 - // 停止播放线程  
253 - g_playThreadRunning = false;  
254 - g_cv.notify_one();  
255 -  
256 - // 等待播放线程退出  
257 - int waitCount = 0;  
258 - while (g_playThreadRunning && waitCount++ < 50) {  
259 - usleep(100000); // 100ms  
260 - }  
261 -  
262 - // 反初始化TTS SDK  
263 - if (g_AikitHandle) {  
264 - AIKIT_End(g_AikitHandle);  
265 - g_AikitHandle = nullptr;  
266 - }  
267 -  
268 - AIKIT_UnInit();  
269 -  
270 - // 释放环形缓冲区  
271 - if (g_ringHandle) {  
272 - JZring_DeInit(g_ringHandle);  
273 - g_ringHandle = nullptr;  
274 - }  
275 -  
276 - if (g_ringBuf) {  
277 - delete[] g_ringBuf;  
278 - g_ringBuf = nullptr;  
279 - }  
280 -  
281 - return 0;  
282 -}  
283 -  
284 -static int IflytekLib_2_StopTts()  
285 -{  
286 - if (g_AikitHandle) {  
287 - AIKIT_End(g_AikitHandle);  
288 - g_AikitHandle = nullptr;  
289 - ttsFinished = true;  
290 - JZSDK_LOG_INFO("TTS合成已停止");  
291 - }  
292 -  
293 - // 通知播放线程  
294 - g_cv.notify_one();  
295 - return 0;  
296 -}  
297 -  
298 -#endif  
1 -// #include <fstream>  
2 -// #include <assert.h>  
3 -// #include <cstring>  
4 -// #include <atomic>  
5 -// #include <unistd.h>  
6 -// #include <string>  
7 -  
8 -// #include "JZsdkLib.h"  
9 -// #include "version_choose.h"  
10 -// #include "JZsdk_base/JZring/JZring.h"  
11 -  
12 -// #ifdef IFLAY_TTS_2_CONFIG_STATUS_ON  
13 -  
14 -// #include "aikit_biz_api.h"  
15 -// #include "aikit_constant.h"  
16 -// #include "aikit_biz_config.h"  
17 -// #include "iflytek_tts.h"  
18 -// #include "AudioDeal/AudioDeal.h"  
19 -// #include "../../Megaphone.h"  
20 -// #include "iflytek_tts.h"  
21 -  
22 -  
23 -// using namespace std;  
24 -// using namespace AIKIT;  
25 -  
26 -// static std::atomic_bool ttsFinished(false);  
27 -// static const char *ABILITY = "e2e44feff";  
28 -// static AIKIT_HANDLE *g_AikitHandle = nullptr; //合成句柄  
29 -  
30 -// static int IflytekLib_2_StopTts();  
31 -  
32 -// static FILE *iflytts_fp = NULL;  
33 -// #define IFLYTTS_FP_NAME "/root/tmp_tts_file.pcm"  
34 -  
35 -  
36 -// void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output)  
37 -// {  
38 -// //检测数据生成标志位是否有关闭,如果有关闭,则主动关闭合成,并退出该事件  
39 -// if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF)  
40 -// {  
41 -// IflytekLib_2_StopTts();  
42 -// return;  
43 -// }  
44 -  
45 -// //如果存在数据,则播放  
46 -// if (output->node->value)  
47 -// {  
48 -// //生产的文本数据 output->node->value  
49 -// //生产的数据长度 output->node->len  
50 -// //char类型  
51 -  
52 -// //JZSDK_LOG_DEBUG("生产了数据%d", output->node->len);  
53 -// printf("生产了数据%d\n", output->node->len);  
54 -  
55 -// //将该数据发送到alsa播放器  
56 -// //AudioDeal_PcmDataInput_TextSteam(16000, (unsigned char *)output->node->value, output->node->len);  
57 -  
58 -// if (iflytts_fp != NULL)  
59 -// {  
60 -// fwrite(output->node->value, sizeof(char), output->node->len, iflytts_fp);  
61 -// fflush(iflytts_fp);  
62 -// }  
63 -  
64 -// }  
65 -  
66 -  
67 -// }  
68 -  
69 -// void OnEvent(AIKIT_HANDLE* handle, AIKIT_EVENT eventType, const AIKIT_OutputEvent* eventValue) {  
70 -// if (eventType == AIKIT_Event_End) {  
71 -// ttsFinished = true;  
72 -  
73 -// JZSDK_LOG_INFO("合成完成");  
74 -// }  
75 -// }  
76 -  
77 -// void OnError(AIKIT_HANDLE* handle, int32_t err, const char* desc) {  
78 -// printf("OnError:%d\n", err);  
79 -  
80 -// //报错  
81 -// }  
82 -  
83 -// int IflytekLib_2_TextToTts(int language,  
84 -// const char *TtsRole,  
85 -// const char *text, int speed, int volume)  
86 -// {  
87 -  
88 -// if (iflytts_fp != NULL)  
89 -// {  
90 -// JZSDK_LOG_ERROR("file %s is not closed\n", IFLYTTS_FP_NAME);  
91 -// return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;  
92 -// }  
93 -  
94 -  
95 -// AIKIT_ParamBuilder* paramBuilder = nullptr;  
96 -// AIKIT_DataBuilder* dataBuilder = nullptr;  
97 -// AiText* aiText_raw = nullptr;  
98 -  
99 -  
100 -// // 重置完成标志  
101 -// ttsFinished = false;  
102 -  
103 -// paramBuilder = AIKIT_ParamBuilder::create();  
104 -// paramBuilder->clear();  
105 -// // 设置发音人  
106 -// paramBuilder->param("vcn", TtsRole, strlen(TtsRole));  
107 -// paramBuilder->param("vcnModel", TtsRole, strlen(TtsRole));  
108 -// // 设置语种  
109 -// paramBuilder->param("language", language);  
110 -// // 设置文本编码  
111 -// paramBuilder->param("textEncoding", "UTF-8", strlen("UTF-8"));  
112 -  
113 -// //语速  
114 -// paramBuilder->param("speed",speed); //可选参数,默认为0  
115 -  
116 -// //音调  
117 -// //paramBuilder->param("pitch",100); //可选参数,默认为0  
118 -  
119 -// //声音  
120 -// //paramBuilder->param("volume",100);//可选参数,默认为0  
121 -  
122 -// //打开临存文件  
123 -// iflytts_fp = fopen(IFLYTTS_FP_NAME, "w+b");  
124 -// if (iflytts_fp == NULL)  
125 -// {  
126 -// JZSDK_LOG_ERROR("open file %s failed\n", IFLYTTS_FP_NAME);  
127 -// return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;  
128 -// }  
129 -  
130 -// //JZSDK_LOG_DEBUG("TTS Role:%s Len:%d, Text:%s Len:%d, language:%d", TtsRole, strlen(TtsRole), text, strlen(text), language);  
131 -  
132 -// int ret = AIKIT_Start(ABILITY, AIKIT_Builder::build(paramBuilder), nullptr, &g_AikitHandle);  
133 -// if(ret != 0) {  
134 -// printf("AIKIT_Start failed: %d\n", ret);  
135 -// goto exit;  
136 -// }  
137 -  
138 -// dataBuilder = AIKIT_DataBuilder::create();  
139 -// dataBuilder->clear();  
140 -// //aiText_raw = AiText::get("text")->data(text.c_str(), text.length())->once()->valid();  
141 -// aiText_raw = AiText::get("text")->data(text, strlen(text) )->once()->valid();  
142 -// dataBuilder->payload(aiText_raw);  
143 -  
144 -// ret = AIKIT_Write(g_AikitHandle, AIKIT_Builder::build(dataBuilder));  
145 -// if(ret != 0) {  
146 -// printf("AIKIT_Write failed: %d\n", ret);  
147 -// goto exit;  
148 -// }  
149 -  
150 -// // 等待合成完成  
151 -// while(!ttsFinished) {  
152 -// usleep(1000);  
153 -// }  
154 -  
155 -// JZSDK_LOG_DEBUG("合成完成,开始播放");  
156 -  
157 -// //将fp指针移到文件开头  
158 -// fseek(iflytts_fp, 0, SEEK_SET);  
159 -  
160 -// //将数据导入播放器  
161 -// unsigned char buffer[1024];  
162 -// int len;  
163 -// while (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) != JZ_FLAGCODE_OFF)  
164 -// {  
165 -// len = fread(buffer, sizeof(char), 1024, iflytts_fp);  
166 -// if (len <= 0)  
167 -// {  
168 -// JZSDK_LOG_DEBUG("已读取完毕\n");  
169 -// break;  
170 -// }  
171 -  
172 -// AudioDeal_PcmDataInput_TextSteam(16000, buffer, len);  
173 -// }  
174 -  
175 -// JZSDK_LOG_INFO("播放完成");  
176 -  
177 -// ret = AIKIT_End(g_AikitHandle);  
178 -  
179 -// exit:  
180 -// if(paramBuilder != nullptr) {  
181 -// delete paramBuilder;  
182 -// }  
183 -// if(dataBuilder != nullptr) {  
184 -// delete dataBuilder;  
185 -// }  
186 -  
187 -// if (iflytts_fp != NULL)  
188 -// {  
189 -// fclose(iflytts_fp);  
190 -// iflytts_fp = NULL;  
191 -// }  
192 -  
193 -// return 0;  
194 -// }  
195 -  
196 -  
197 -  
198 -  
199 -  
200 -  
201 -  
202 -  
203 -  
204 -  
205 -  
206 -  
207 -// int IflytekLib_2_UnInit()  
208 -// {  
209 -// AIKIT_UnInit();  
210 -// return 0;  
211 -// }  
212 -  
213 -// static int IflytekLib_2_StopTts()  
214 -// {  
215 -// AIKIT_OutputEvent eventData = {};  
216 -// if (g_AikitHandle != nullptr)  
217 -// {  
218 -// OnEvent(g_AikitHandle,AIKIT_Event_End,&eventData);  
219 -// }  
220 -  
221 -// return 0;  
222 -// }  
223 -  
224 -  
225 -  
226 -  
227 -  
228 -  
229 -  
230 -  
231 -  
232 -  
233 -// #define IFLYTEK_RING_BUF_SIZE (1024 * 100) // 100KB缓冲区  
234 -// static T_JZringHandle g_ringHandle = nullptr;  
235 -// static char *g_ringBuf = nullptr;  
236 -// static int g_AudioPlayFinshFlag = JZ_FLAGCODE_OFF;  
237 -// static int g_playThreadRunning = JZ_FLAGCODE_OFF;  
238 -  
239 -// static void PlaybackThreadFunc()  
240 -// {  
241 -// T_JZsdkOsalHandler *osHandler = JZsdk_Platform_GetOsalHandler;  
242 -// U8_t buffer[2048]; // 每次读取2KB  
243 -// U32_t readSize = 0;  
244 -// T_JZsdkReturnCode ret;  
245 -// U32_t dataCount = 0;  
246 -  
247 -// g_playThreadRunning = JZ_FLAGCODE_ON;  
248 -  
249 -// while (g_playThreadRunning == JZ_FLAGCODE_ON)  
250 -// {  
251 -// //监测缓冲区是否有数据  
252 -// dataCount = 0;  
253 -// ret = JZring_GetDataCount(g_ringHandle, &dataCount);  
254 -  
255 -// if (dataCount == 0)  
256 -// {  
257 -// //等候线程唤醒  
258 -  
259 -// continue;  
260 -// }  
261 -  
262 -// //读取数据  
263 -// ret = JZring_Read(g_ringHandle, buffer, sizeof(buffer), &readSize);  
264 -// if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)  
265 -// {  
266 -// JZSDK_LOG_ERROR("读取环形缓冲区失败");  
267 -// break;  
268 -// }  
269 -  
270 -// //写入音频播放器  
271 -// AudioDeal_PcmDataInput_TextSteam(16000, buffer, readSize);  
272 -  
273 -// g_AudioPlayFinshFlag = JZ_FLAGCODE_ON;  
274 -  
275 -// //检查  
276 -// }  
277 -// }  
278 -  
279 -// T_JZsdkReturnCode IflytekLib_2_Init()  
280 -// {  
281 -// //初始化环形缓冲区  
282 -// g_ringBuf = new char[IFLYTEK_RING_BUF_SIZE];  
283 -// if (JZring_Init(&g_ringHandle, reinterpret_cast<U8_t*>(g_ringBuf), IFLYTEK_RING_BUF_SIZE)  
284 -// != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
285 -// JZSDK_LOG_ERROR("环形缓冲区初始化失败");  
286 -// return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;  
287 -// }  
288 -  
289 -// T_JZsdkOsalHandler *osHandler = JZsdk_Platform_GetOsalHandler;  
290 -// T_JZTaskHandle taskhandle;  
291 -// osHandler->TaskCreate("IfytekLibPlay", PlaybackThreadFunc, 1024, NULL, &taskhandle);  
292 -  
293 -// AIKIT_Configurator::builder()  
294 -// .app()  
295 -// .appID("03857dfd")  
296 -// .apiSecret("OTA2OTEzMTVlOGYwMjllMmJkYzEwZGY5")  
297 -// .apiKey("2b2c60f8a80b8cdfe45ae1058a25149a")  
298 -// .workDir("/root/Iflytek_2")  
299 -// .auth()  
300 -// .authType(0)  
301 -// .log()  
302 -// .logLevel(LOG_LVL_OFF) //关闭日志打印  
303 -// .logMode(LOG_STDOUT); //日志输出为控制台  
304 -  
305 -// int ret = AIKIT_Init();  
306 -// if(ret != 0) {  
307 -// printf("AIKIT_Init failed: %d\n", ret);  
308 -// return -1;  
309 -// }  
310 -  
311 -// AIKIT_Callbacks cbs = {OnOutput, OnEvent, OnError};  
312 -// AIKIT_RegisterAbilityCallback(ABILITY, cbs);  
313 -  
314 -// return 0;  
315 -// }  
316 -  
317 -  
318 -  
319 -// #endif  
@@ -107,8 +107,16 @@ void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output) @@ -107,8 +107,16 @@ void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output)
107 ret = JZring_Write(g_ringHandle, 107 ret = JZring_Write(g_ringHandle,
108 reinterpret_cast<U8_t*>(output->node->value) + written, 108 reinterpret_cast<U8_t*>(output->node->value) + written,
109 chunkSize); 109 chunkSize);
  110 + if (ret == JZ_ERROR_SYSTEM_MODULE_CODE_BUFFER_SIZE_NOT_ENOUGH)
  111 + {
  112 + //缓冲区暂无空间,等待一段时间再写入
  113 + usleep(10000); // 10ms
  114 + continue;
  115 + }
  116 +
110 117
111 - if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 118 + if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS && ret != JZ_ERROR_SYSTEM_MODULE_CODE_BUFFER_SIZE_NOT_ENOUGH)
  119 + {
112 JZSDK_LOG_ERROR("写入环形缓冲区失败: %d", ret); 120 JZSDK_LOG_ERROR("写入环形缓冲区失败: %d", ret);
113 break; 121 break;
114 } 122 }
1 -#include <fstream>  
2 -#include <assert.h>  
3 -#include <cstring>  
4 -#include <atomic>  
5 -#include <unistd.h>  
6 -#include <string>  
7 -#include <thread>  
8 -#include <mutex>  
9 -#include <condition_variable>  
10 -  
11 -#include "JZsdkLib.h"  
12 -#include "version_choose.h"  
13 -#include "JZsdk_base/JZring/JZring.h"  
14 -  
15 -#if 0  
16 -  
17 -#include "aikit_biz_api.h"  
18 -#include "aikit_constant.h"  
19 -#include "aikit_biz_config.h"  
20 -#include "iflytek_tts.h"  
21 -#include "AudioDeal/AudioDeal.h"  
22 -#include "../../Megaphone.h"  
23 -#include "iflytek_tts.h"  
24 -  
25 -using namespace std;  
26 -using namespace AIKIT;  
27 -  
28 -static std::atomic_bool ttsFinished(false);  
29 -static std::atomic_bool g_playThreadRunning(false);  
30 -static const char *ABILITY = "e2e44feff";  
31 -static AIKIT_HANDLE *g_AikitHandle = nullptr; // 合成句柄  
32 -  
33 -static int IflytekLib_2_StopTts();  
34 -  
35 -#define IFLYTEK_RING_BUF_SIZE (1024 * 100) // 100KB缓冲区  
36 -static T_JZringHandle g_ringHandle = nullptr;  
37 -static char *g_ringBuf = nullptr;  
38 -static int g_AudioPlayFinshFlag = JZ_FLAGCODE_OFF;  
39 -  
40 -// 同步机制  
41 -static std::mutex g_mutex;  
42 -static std::condition_variable g_cv;  
43 -  
44 -// 播放线程函数  
45 -void PlaybackThreadFunc()  
46 -{  
47 - U8_t buffer[2048]; // 每次读取2KB  
48 - U32_t readSize = 0;  
49 - T_JZsdkReturnCode ret;  
50 -  
51 - g_playThreadRunning = true;  
52 -  
53 - std::unique_lock<std::mutex> lock(g_mutex);  
54 -  
55 - while (g_playThreadRunning)  
56 - {  
57 - // 等待有数据可读  
58 - {  
59 - U32_t dataCount = 0;  
60 - JZring_GetDataCount(g_ringHandle, &dataCount);  
61 -  
62 - JZSDK_LOG_DEBUG("缓冲区数据量: %d", dataCount);  
63 -  
64 - if (dataCount == 0) {  
65 - // 等待最多100ms或通知  
66 - g_cv.wait_for(lock, std::chrono::milliseconds(100));  
67 - continue;  
68 - }  
69 - }  
70 -  
71 - g_AudioPlayFinshFlag = JZ_FLAGCODE_ON;  
72 -  
73 - JZSDK_LOG_DEBUG("有数据可读");  
74 -  
75 - // 从环形缓冲区读取数据  
76 - ret = JZring_Read(g_ringHandle, buffer, sizeof(buffer), &readSize);  
77 - if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS || readSize == 0) {  
78 - usleep(10000); // 10ms  
79 - continue;  
80 - }  
81 -  
82 - JZSDK_LOG_DEBUG("输入数据进音频库");  
83 -  
84 - // 发送到音频播放器  
85 - AudioDeal_PcmDataInput_TextSteam(16000, buffer, readSize);  
86 -  
87 - g_AudioPlayFinshFlag = JZ_FLAGCODE_OFF;  
88 -  
89 - JZSDK_LOG_DEBUG("音频库播放完毕");  
90 -  
91 - // 检查是否需要停止播放  
92 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
93 - break;  
94 - }  
95 - }  
96 -  
97 - g_playThreadRunning = false;  
98 -}  
99 -  
100 -void OnOutput(AIKIT_HANDLE* handle, const AIKIT_OutputData* output)  
101 -{  
102 - // 检测数据生成标志位是否有关闭  
103 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
104 - IflytekLib_2_StopTts();  
105 - return;  
106 - }  
107 -  
108 - if (output->node->value) {  
109 - JZSDK_LOG_DEBUG("生产了数据%d", output->node->len);  
110 -  
111 - // 写入环形缓冲区  
112 - T_JZsdkReturnCode ret;  
113 - U32_t written = 0;  
114 -  
115 - while (written < static_cast<U32_t>(output->node->len)) {  
116 - U32_t chunkSize = std::min(static_cast<U32_t>(output->node->len) - written,  
117 - static_cast<U32_t>(4096));  
118 -  
119 - ret = JZring_Write(g_ringHandle,  
120 - reinterpret_cast<U8_t*>(output->node->value) + written,  
121 - chunkSize);  
122 -  
123 - if (ret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
124 - JZSDK_LOG_ERROR("写入环形缓冲区失败: %d", ret);  
125 - break;  
126 - }  
127 -  
128 - written += chunkSize;  
129 - }  
130 -  
131 - // 通知播放线程有新数据  
132 - g_cv.notify_one();  
133 - }  
134 -}  
135 -  
136 -void OnEvent(AIKIT_HANDLE* handle, AIKIT_EVENT eventType, const AIKIT_OutputEvent* eventValue) {  
137 - if (eventType == AIKIT_Event_End) {  
138 - ttsFinished = true;  
139 - JZSDK_LOG_INFO("合成完成");  
140 -  
141 - // 通知播放线程所有数据已生成  
142 - g_cv.notify_one();  
143 - }  
144 -}  
145 -  
146 -void OnError(AIKIT_HANDLE* handle, int32_t err, const char* desc) {  
147 - JZSDK_LOG_ERROR("TTS错误: %d, %s", err, desc);  
148 - IflytekLib_2_StopTts();  
149 -}  
150 -  
151 -int IflytekLib_2_TextToTts(int language,  
152 - const char *TtsRole,  
153 - const char *text, int speed, int volume)  
154 -{  
155 - AIKIT_ParamBuilder* paramBuilder = nullptr;  
156 - AIKIT_DataBuilder* dataBuilder = nullptr;  
157 - AiText* aiText_raw = nullptr;  
158 - int ret = 0;  
159 -  
160 - // 重置完成标志  
161 - ttsFinished = false;  
162 -  
163 - // 重置环形缓冲区  
164 - JZring_Reset(g_ringHandle);  
165 -  
166 - paramBuilder = AIKIT_ParamBuilder::create();  
167 - paramBuilder->clear();  
168 - // 设置发音人  
169 - paramBuilder->param("vcn", TtsRole, strlen(TtsRole));  
170 - paramBuilder->param("vcnModel", TtsRole, strlen(TtsRole));  
171 - // 设置语种  
172 - paramBuilder->param("language", language);  
173 - // 设置文本编码  
174 - paramBuilder->param("textEncoding", "UTF-8", strlen("UTF-8"));  
175 - // 音量  
176 - paramBuilder->param("volume", volume);  
177 - // 语速  
178 - paramBuilder->param("speed", speed);  
179 -  
180 - JZSDK_LOG_DEBUG("TTS Role:%s, Text:%s, language:%d", TtsRole, text, language);  
181 -  
182 - ret = AIKIT_Start(ABILITY, AIKIT_Builder::build(paramBuilder), nullptr, &g_AikitHandle);  
183 - if(ret != 0) {  
184 - JZSDK_LOG_ERROR("AIKIT_Start failed: %d", ret);  
185 - goto exit;  
186 - }  
187 -  
188 - dataBuilder = AIKIT_DataBuilder::create();  
189 - dataBuilder->clear();  
190 - aiText_raw = AiText::get("text")->data(text, strlen(text))->once()->valid();  
191 - dataBuilder->payload(aiText_raw);  
192 -  
193 - ret = AIKIT_Write(g_AikitHandle, AIKIT_Builder::build(dataBuilder));  
194 - if(ret != 0) {  
195 - JZSDK_LOG_ERROR("AIKIT_Write failed: %d", ret);  
196 - goto exit;  
197 - }  
198 -  
199 - // 等待合成完成或停止信号  
200 - while(!ttsFinished || g_AudioPlayFinshFlag == JZ_FLAGCODE_ON) {  
201 - if (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_OFF) {  
202 - break;  
203 - }  
204 - usleep(10000); // 10ms  
205 - }  
206 -  
207 - JZSDK_LOG_INFO("合成结束");  
208 -  
209 - // 结束合成  
210 - ret = AIKIT_End(g_AikitHandle);  
211 - g_AikitHandle = nullptr;  
212 -  
213 -exit:  
214 - if(paramBuilder != nullptr) {  
215 - delete paramBuilder;  
216 - }  
217 - if(dataBuilder != nullptr) {  
218 - delete dataBuilder;  
219 - }  
220 -  
221 - return ret;  
222 -}  
223 -  
224 -int IflytekLib_2_Init()  
225 -{  
226 - // 初始化环形缓冲区  
227 - g_ringBuf = new char[IFLYTEK_RING_BUF_SIZE];  
228 - if (JZring_Init(&g_ringHandle, reinterpret_cast<U8_t*>(g_ringBuf), IFLYTEK_RING_BUF_SIZE)  
229 - != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
230 - JZSDK_LOG_ERROR("环形缓冲区初始化失败");  
231 - return -1;  
232 - }  
233 -  
234 - // 启动播放线程  
235 - std::thread(PlaybackThreadFunc).detach();  
236 -  
237 - // 初始化TTS SDK  
238 - AIKIT_Configurator::builder()  
239 - .app()  
240 - .appID("03857dfd")  
241 - .apiSecret("OTA2OTEzMTVlOGYwMjllMmJkYzEwZGY5")  
242 - .apiKey("2b2c60f8a80b8cdfe45ae1058a25149a")  
243 - .workDir("/root/Iflytek_2")  
244 - .auth()  
245 - .authType(0)  
246 - .log()  
247 - .logLevel(LOG_LVL_OFF) //关闭日志打印  
248 - .logMode(LOG_STDOUT); //日志输出为控制台  
249 -  
250 - int ret = AIKIT_Init();  
251 - if(ret != 0) {  
252 - JZSDK_LOG_ERROR("AIKIT_Init failed: %d", ret);  
253 - return -1;  
254 - }  
255 -  
256 - AIKIT_Callbacks cbs = {OnOutput, OnEvent, OnError};  
257 - AIKIT_RegisterAbilityCallback(ABILITY, cbs);  
258 -  
259 - return 0;  
260 -}  
261 -  
262 -int IflytekLib_2_UnInit()  
263 -{  
264 - // 停止播放线程  
265 - g_playThreadRunning = false;  
266 - g_cv.notify_one();  
267 -  
268 - // 等待播放线程退出  
269 - int waitCount = 0;  
270 - while (g_playThreadRunning && waitCount++ < 50) {  
271 - usleep(100000); // 100ms  
272 - }  
273 -  
274 - // 反初始化TTS SDK  
275 - if (g_AikitHandle) {  
276 - AIKIT_End(g_AikitHandle);  
277 - g_AikitHandle = nullptr;  
278 - }  
279 -  
280 - AIKIT_UnInit();  
281 -  
282 - // 释放环形缓冲区  
283 - if (g_ringHandle) {  
284 - JZring_DeInit(g_ringHandle);  
285 - g_ringHandle = nullptr;  
286 - }  
287 -  
288 - if (g_ringBuf) {  
289 - delete[] g_ringBuf;  
290 - g_ringBuf = nullptr;  
291 - }  
292 -  
293 - return 0;  
294 -}  
295 -  
296 -static int IflytekLib_2_StopTts()  
297 -{  
298 - if (g_AikitHandle) {  
299 - AIKIT_End(g_AikitHandle);  
300 - g_AikitHandle = nullptr;  
301 - ttsFinished = true;  
302 - JZSDK_LOG_INFO("TTS合成已停止");  
303 - }  
304 -  
305 - // 通知播放线程  
306 - g_cv.notify_one();  
307 - return 0;  
308 -}  
309 -  
310 -#endif