tts_demo.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =================================================================*/
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "tts_demo.h"
  9. #include "ql_api_osi.h"
  10. #include "ql_api_tts.h"
  11. #include "ql_log.h"
  12. #include "ql_osi_def.h"
  13. #include "ql_audio.h"
  14. #include "ql_fs.h"
  15. /*
  16. 1. 不同的TTS资源文件,对应的播放效果不同。其中中文资源不能用来播英文单词,单词会以字母的方式播出; 英文资源也不能用来播中文。默认使用
  17. 中文16k TTS资源
  18. 2. 若使用16k中文TTS资源,且TTS资源文件预置到内置flash中,则不需要修改json脚本(脚本默认已选择预置16k中文资源,且预置到内置flash),只需要调用
  19. ql_tts_engine_init函数即可完成初始化,不需要关注以下描述
  20. 3. 所有的资源文件均在components\ql-config\download\prepack下,其中:
  21. 英文16k资源文件名为: "quectel_tts_resource_english_16k.bin"
  22. 中文8k资源文件为:"quectel_tts_resource_chinese_8k.bin"
  23. 中文16k资源文件为:"quectel_pcm_resource.bin"
  24. 4. 预置文件时,请将json脚本中的"file"固定为"/qsfs/quectel_pcm_resource.bin"(预置资源文件到内置flash), 或
  25. "/ext/qsfs/quectel_pcm_resource.bin"(预置到外置6线spi flash中), 并修改"local_file"来选择上传哪个资源文件,如下述示例.
  26. 若不使用中文16k资源,则需要使用"ql_tts_engine_init_ex"函数,将配置结构体中的"resource"变量设置为需要使用的资源;
  27. 若将资源文件预置到外置6线spi flash,需要将"position"变量设置为 POSIT_EFS
  28. 当TTS资源文件预置在内置Flash时,针对需要FOTA升级的情况,新版本SDK中默认将该文件进行拆分为多个子文件进行预置!
  29. 外置存储时可以不用拆分。
  30. 5. 使用英文16k TTS资源播放时,需要1.45M的RAM空间,因此要注意RAM空间是否充足; 选择中文16k TTS资源文件时,需要620k的RAM空间; 选择中文
  31. 8k资源时,需要570kRAM空间
  32. 预置文件示例:
  33. 1. 预置16k中文TTS资源文件到内部flash(默认):
  34. "files": [
  35. {
  36. "file": "/qsfs/quectel_pcm_resource.bin",
  37. "local_file": "quectel_pcm_resource.bin"
  38. }
  39. ]
  40. 2. 预置16k英文TTS资源文件到内部flash(以"/qsfs/quectel_pcm_resource.bin"为文件系统路径)
  41. "files": [
  42. {
  43. "file": "/qsfs/quectel_pcm_resource.bin",
  44. "local_file": "quectel_tts_resource_english_16k.bin"
  45. }
  46. ]
  47. 3. 预置8K中文TTS资源文件到内部flash(以"/qsfs/quectel_pcm_resource.bin"为文件系统路径)
  48. "files": [
  49. {
  50. "file": "/qsfs/quectel_pcm_resource.bin",
  51. "local_file": "quectel_tts_resource_chinese_8k.bin"
  52. }
  53. ]
  54. 4. (1)预置16k英文TTS资源到外置6线spi flash(以/ext/qsfs/quectel_pcm_resource.bin"为文件系统路径)
  55. "files": [
  56. {
  57. "file": "/ext/qsfs/quectel_pcm_resource.bin",
  58. "local_file": "quectel_tts_resource_english_16k.bin"
  59. }
  60. ]
  61. (2)需要把boot_fdl_dnld.c文件的bool fdlDnldStart(fdlEngine_t *fdl, unsigned devtype),
  62. 6线flash部分的#if 0打开为1(CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR_SFFS部分);
  63. (3)在target.config中,CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR_SFFS打开,CONFIG_QUEC_PROJECT_FEATURE_SPI4_EXT_NOR关闭
  64. 5. (1)预置16k中文TTS资源文件到外部4线flash
  65. "files": [
  66. {
  67. "file": "/ext4n/qsfs/quectel_pcm_resource.bin",
  68. "local_file": "quectel_pcm_resource.bin"
  69. }
  70. ]
  71. (2)需要把boot_fdl_dnld.c文件的bool fdlDnldStart(fdlEngine_t *fdl, unsigned devtype),
  72. 4线flash部分的#if 0打开为1(CONFIG_QUEC_PROJECT_FEATURE_SPI4_EXT_NOR_SFFS部分);
  73. (3)在target.config中,CONFIG_QUEC_PROJECT_FEATURE_SPI4_EXT_NOR_SFFS打开,CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR关闭
  74. */
  75. #define QL_TTS_LANGUAGE_ENGLISH 0
  76. /*0:tts库在内置flash,1:tts库在六线flash,2:tts库在四线flash*/
  77. #define QL_TTS_LOCATION 0
  78. #define QL_TTS_LOG_LEVEL QL_LOG_LEVEL_INFO
  79. #define QL_TTS_LOG(msg, ...) QL_LOG(QL_TTS_LOG_LEVEL, "ql_app_tts", msg, ##__VA_ARGS__)
  80. #define QL_TTS_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_app_tts", msg, ##__VA_ARGS__)
  81. #if !defined(tts_demo_no_err)
  82. #define tts_demo_no_err(x, action, str) \
  83. do \
  84. { \
  85. if(x != 0) \
  86. { \
  87. QL_TTS_LOG(str); \
  88. {action;} \
  89. } \
  90. } while( 1==0 )
  91. #endif
  92. /*===========================================================================
  93. * Variate
  94. ===========================================================================*/
  95. PCM_HANDLE_T tts_player = NULL;
  96. ql_task_t ql_tts_demo_task = NULL;
  97. /*===========================================================================
  98. * Functions
  99. ===========================================================================*/
  100. int userCallback(void *param, int param1, int param2, int param3, int data_len, const void *pcm_data)
  101. {
  102. int err;
  103. err = ql_pcm_write(tts_player, (void *)pcm_data, data_len);
  104. if(err <= 0)
  105. {
  106. QL_TTS_LOG("write data to PCM player failed");
  107. return -1;
  108. }
  109. return 0;
  110. }
  111. void ql_tts_thread(void *param)
  112. {
  113. int err = 0, cnt = 0, len=0;
  114. QL_PCM_CONFIG_T config = {1, 16000, 0};
  115. tts_param_t tts_param = {0};
  116. ql_set_audio_path_earphone();
  117. ql_aud_set_volume(QL_AUDIO_PLAY_TYPE_LOCAL, AUDIOHAL_SPK_VOL_11);
  118. tts_player = ql_pcm_open(&config, QL_PCM_BLOCK_FLAG|QL_PCM_WRITE_FLAG);
  119. tts_demo_no_err(!tts_player, goto exit, "create pcm_player failed");
  120. #if !QL_TTS_LANGUAGE_ENGLISH
  121. tts_param.resource = TTS_RESOURCE_16K_CN;
  122. #else
  123. tts_param.resource = TTS_RESOURCE_16K_EN;
  124. #endif
  125. #if QL_TTS_LOCATION==1 //使用的tts库在外部6线flash
  126. tts_param.position = POSIT_EFS;
  127. #elif QL_TTS_LOCATION==2 //使用的tts库在外部4线flash
  128. tts_param.position = POSIT_EXNSFFS;
  129. #else //默认使用的tts库在内置flash
  130. tts_param.position = POSIT_INTERNAL_FS;
  131. #endif
  132. //err = ql_tts_engine_init(userCallback); //若使用默认的中文16k资源,且资源文件预置到内置flash, 则直接调用ql_tts_engine_init即可
  133. err = ql_tts_engine_init_ex(userCallback, &tts_param);
  134. tts_demo_no_err(err, goto exit, "tts session begain failed");
  135. while(1)
  136. {
  137. #if !QL_TTS_LANGUAGE_ENGLISH //英文资源文件无法播中文TTS
  138. if(cnt == 0) //play utf8 encoding
  139. {
  140. char *tts_str = "֧支付宝收款123456789.000元"; //utf-8 encoding
  141. len = strlen(tts_str);
  142. ql_tts_set_config_param(QL_TTS_CONFIG_ENCODING,QL_TTS_UTF8);
  143. ql_tts_set_config_param(QL_TTS_CONFIG_DGAIN, 0);////set tts digtal gain
  144. err = ql_tts_start((const char *)tts_str, len);
  145. tts_demo_no_err(err, goto exit, "tts start failed");
  146. }
  147. else if(cnt == 1) //play ucs2 encoding
  148. {
  149. uint16 tts_str[8] = {0x6B22, 0x8FCE, 0x4F7F, 0x7528, 0x79FB, 0x8FDC, 0x6A21, 0x5757}; //欢迎使用移远模块
  150. len = sizeof(tts_str);
  151. ql_tts_set_config_param(QL_TTS_CONFIG_ENCODING,QL_TTS_UCS2);
  152. ql_tts_set_config_param(QL_TTS_CONFIG_DGAIN, 0);//set tts digtal gain
  153. err = ql_tts_start((const char *)tts_str, len);
  154. tts_demo_no_err(err, goto exit, "tts start failed");
  155. }
  156. #else
  157. if(cnt == 2)
  158. {
  159. char *str_eng = "The price of the shirt is $50, and the price of the computer is $1200";
  160. len = strlen(str_eng);
  161. err = ql_tts_start((const char *)str_eng, len);
  162. tts_demo_no_err(err, goto exit, "tts start failed");
  163. }
  164. #endif
  165. ql_rtos_task_sleep_ms(1000);
  166. if(cnt == 2){
  167. goto exit;
  168. }
  169. else{
  170. cnt++;
  171. continue;
  172. }
  173. }
  174. exit:
  175. ql_aud_data_done();
  176. ql_aud_wait_play_finish(QL_WAIT_FOREVER);
  177. ql_tts_end();
  178. if(tts_player){
  179. ql_pcm_close(tts_player);
  180. tts_player = NULL;
  181. }
  182. QL_TTS_LOG("tts done");
  183. ql_rtos_task_delete(NULL);
  184. }
  185. void ql_tts_demo1_init(void)
  186. {
  187. uint8_t err = QL_OSI_SUCCESS;
  188. err = ql_rtos_task_create(&ql_tts_demo_task, QL_TTS_TASK_STACK, QL_TTS_TASK_PRIO, "ql_tts_task", ql_tts_thread, NULL, 1);
  189. if (err != QL_OSI_SUCCESS)
  190. {
  191. QL_TTS_LOG("TTS demo task created failed");
  192. }
  193. }