tts.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include "tts.h"
  2. #include "app.h"
  3. #include "lsapi_tts.h"
  4. #include "lsapi_audio.h"
  5. #include "mallocSw.h"
  6. #define TTS_MAX_LEN (20+4*200) //max 200 chinese
  7. typedef struct{
  8. T_UINT8 plyNow:1;
  9. T_UINT8 ttsType;
  10. T_UINT16 ttsLen;
  11. T_UINT8 ttsData[TTS_MAX_LEN+2];//should have 2 '"'
  12. }TTS_DEF;
  13. TTS_DEF tts={
  14. .plyNow=0,
  15. };
  16. T_BOOL preTTSHandler(unsigned char *data, T_UINT16 *len,int data_size,unsigned char type){
  17. int i,j;
  18. T_BOOL ret=FALSE;
  19. unsigned char ch,lachIsZimu=0;
  20. if(type!=LSAPI_TTS_GBK) return TRUE;
  21. unsigned char *tbuf=(unsigned char *)wmalloc(data_size);
  22. if(tbuf==NULL) return FALSE;
  23. j=0;
  24. for(i=0;i<*len;i++){
  25. ch=data[i];
  26. if(ch >0x9f){
  27. if(lachIsZimu!=0){//要插入一个逗号
  28. if(j<data_size) tbuf[j++]=',';
  29. else goto ERR_END;
  30. }
  31. if(j<data_size) tbuf[j++]=data[i];
  32. else goto ERR_END;
  33. if(j<data_size) tbuf[j++]=data[i+1];
  34. else goto ERR_END;
  35. i++;
  36. lachIsZimu=0;
  37. }else if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')){
  38. if(j<data_size) tbuf[j++]=ch;
  39. else goto ERR_END;
  40. lachIsZimu=1;
  41. }else{
  42. if(j<data_size) tbuf[j++]=ch;
  43. else goto ERR_END;
  44. lachIsZimu=0;
  45. }
  46. }
  47. *len=j;
  48. memcpy(data,tbuf,j);
  49. ret=TRUE;
  50. ERR_END:
  51. wfree(tbuf);
  52. return ret;
  53. }
  54. static void prvLsTtsPlayerEvCb(LSAPI_AUD_PlayerEvent_t event){
  55. wlog_info("tts event:%d",event);
  56. if(LSAPI_AUD_EVENT_FINISHED==event){//播放完毕
  57. msgToOutter("+LSHTTS: END\r\n");
  58. wlog_warn("tts end");
  59. app.media=MEDIA_IDLE;
  60. }
  61. }
  62. static int tts_speak(void){
  63. int result=-1;
  64. LSAPI_AUD_SetPlayerEvCb(prvLsTtsPlayerEvCb);
  65. result=LSAPI_TTS_Play(tts.ttsData, tts.ttsLen, tts.ttsType);
  66. wlog_info("TTS:%d,%d", tts.ttsType,tts.ttsLen);
  67. return result;
  68. }
  69. void tts_stop(void){
  70. LSAPI_TTS_Stop();
  71. }
  72. PT_THREAD (ptTTSTask(pt_timer_t *ptPool, struct pt *pt)){
  73. static pt_timer_t ptTimer;
  74. bool status;
  75. PT_BEGIN(pt);
  76. while(1){
  77. if(tts.plyNow==1){
  78. if(MEDIA_PCM==app.media){
  79. //media is taken by poc, need to wait it stop
  80. app.media=MEDIA_SHUT_PCM;
  81. PTTimerStart(ptPool, &ptTimer,1000);//wait 200ms to shut poc
  82. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer)||MEDIA_PCM_PENDING==app.media);
  83. app.media=MEDIA_PCM_PENDING;
  84. }
  85. status=LSAPI_TTS_IsPlaying();
  86. if(MEDIA_TTS==app.media || true==status){
  87. //media is taken by tts, need to shut the current pro if it is on
  88. wlog_info("call tts stop");
  89. tts_stop();
  90. PTTimerStart(ptPool, &ptTimer,1000);//wait 1000ms to stop
  91. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer)|| false==(status=LSAPI_TTS_IsPlaying()));
  92. }
  93. if(false==status) wlog_info("tts stop ok");
  94. else{
  95. wlog_info("tts stop failed, continue");
  96. continue;
  97. }
  98. //start new tts
  99. if(0==tts_speak()){
  100. wlog_info("tts play ok");
  101. app.media=MEDIA_TTS;
  102. }else{
  103. msgToOutter("+LSHTTS: END\r\n");
  104. wlog_info("tts play failed");
  105. }
  106. tts.plyNow=0;
  107. }
  108. PTTimerStart(ptPool, &ptTimer,1);//can be fast
  109. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  110. }
  111. PT_END(pt);
  112. }
  113. char checkTtsData(unsigned char *data, int len){
  114. int i;
  115. unsigned char ch;
  116. for(i=0;i<len;i++){
  117. ch=data[i];
  118. if((ch>='0' && ch <= '9') ||
  119. (ch>='a' && ch <= 'f') ||
  120. (ch>='A' && ch <= 'F')) {}else return 1;
  121. }
  122. return 0;
  123. }
  124. void cmdTTSHandler(T_UINT8 *data, T_UINT16 len){
  125. //AT+LSHTTS=x,"vvvvvv"//没有回车换行了
  126. //x,"vvvvvv"
  127. T_UINT32 thisTime,i,j,k;
  128. T_UINT8 *ptr=data+10,type,tmp;
  129. T_BOOL ttsErr=FALSE;
  130. //wlog_warn("*****%d,%s",len,data);
  131. //如果是停止指令
  132. if(len==11 && ptr[0]=='0'){
  133. tts_stop();
  134. return;
  135. }
  136. //如果是播放指令
  137. if(len<15 || ptr[1] != ',' || (ptr[0] != '1' && ptr[0] != '2' && ptr[0] != '3') || ptr[2]!='"' || data[len-1] != '"'){
  138. wlog_warn("tts invalid1");
  139. goto TTS_ERROR;
  140. }
  141. type=ptr[0]-0x30;
  142. ptr += 3;//VVVVVVV"
  143. k=len-10-3-1;
  144. //检测数据合法性
  145. if(type==1 || type==2){//GBK/UNICODE的十六进制字符串
  146. if(type==1) tmp=k%2;
  147. else tmp=k%4;
  148. if(0!=checkTtsData(ptr,k) || tmp){
  149. wlog_warn("tts invalid2");
  150. goto TTS_ERROR;
  151. }
  152. if(0!=restoreDataFormatByHex(ptr,k)){
  153. wlog_warn("tts invalid3");
  154. goto TTS_ERROR;
  155. }
  156. k /= 2;
  157. type --;
  158. }else type=0;
  159. if(k>TTS_MAX_LEN){
  160. wlog_warn("tts len over");
  161. goto TTS_LENOV;
  162. }
  163. tts.ttsLen=k;
  164. tts.ttsType=type;
  165. memcpy(tts.ttsData,ptr,tts.ttsLen);
  166. if(FALSE==preTTSHandler(tts.ttsData,&tts.ttsLen,sizeof(tts.ttsData),tts.ttsType)) goto TTS_ERROR;
  167. tts.plyNow=1;
  168. return;
  169. TTS_ERROR:
  170. msgToOutter("+LSHTTS: ERROR\r\n");
  171. return;
  172. TTS_LENOV:
  173. msgToOutter("+LSHTTS: LENOV\r\n");
  174. }