plyRec.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. #include "includes.h"
  2. typedef enum{
  3. PLY_IDLE,
  4. PLY_ON_START,
  5. PLY_ON_SWITCH,
  6. PLY_ON_WAIT,
  7. PLY_ON_BUSY,
  8. PLY_ON_PENDING
  9. }PLY_ENUM;
  10. T_BOOL plyShutNow=FALSE;
  11. PLY_ENUM playStatus=PLY_IDLE;
  12. typedef enum{
  13. REC_IDLE,
  14. REC_ON_START,
  15. REC_ON_SWITCH,
  16. PREC_ON_WAIT,
  17. REC_ON_BUSY,
  18. REC_ON_PENDING
  19. }REC_ENUM;
  20. volatile T_BOOL g_player_status=FALSE;
  21. volatile T_BOOL g_recorder_status=FALSE;
  22. T_BOOL recShutNow=FALSE;
  23. REC_ENUM recordStatus=REC_IDLE;
  24. static void playClose(void);
  25. static void recordClose(void);
  26. static int prvRecordPcmDataCb(uint8_t *buf, uint32_t len){
  27. if(0!=msgToRecord(buf, len))
  28. wlog_error("msgToRecord failed");
  29. return 0;
  30. }
  31. static void lsapiWriteFrame(unsigned char *pcm, unsigned int len){
  32. if(NWY_SUCESS!=nwy_audio_player_play(pcm,len)){
  33. wlog_error("pcm_write error");
  34. playClose();
  35. playStatus=PLY_IDLE;
  36. }else{
  37. talking.voiceLengthTimeMs += 20;
  38. talking.playVoiceDone=TRUE;
  39. }
  40. }
  41. bool isPcmPlayerOn(void){
  42. if(TRUE==g_player_status) return true;
  43. else return false;
  44. }
  45. static int player_cb(nwy_player_status state){
  46. wlog_info("player_cb state=%d", state);
  47. if(0==state){//播放完毕了
  48. wlog_info("pcm play finished");
  49. }
  50. }
  51. static T_BOOL playOpen(void){
  52. T_BOOL status;
  53. wlog_warn("playOpen call");
  54. if(NWY_SUCESS==nwy_audio_player_open(player_cb)) status=TRUE;
  55. else status=FALSE;
  56. g_player_status=status;
  57. return status;
  58. }
  59. static void playClose(void){
  60. if(TRUE==g_player_status){
  61. nwy_audio_player_stop();
  62. nwy_audio_player_close();
  63. g_player_status=FALSE;
  64. wlog_info("try play close done");
  65. }else wlog_info("no need to close opt");
  66. }
  67. static T_BOOL recordOpen(void){
  68. wlog_warn("recordOpen call");
  69. if(NWY_SUCESS!=nwy_audio_recorder_open(prvRecordPcmDataCb)){
  70. g_recorder_status=FALSE;
  71. return FALSE;
  72. }
  73. if(NWY_SUCESS!=nwy_audio_recorder_start()){
  74. g_recorder_status=FALSE;
  75. nwy_audio_recorder_close();
  76. return FALSE;
  77. }
  78. g_recorder_status=TRUE;
  79. return g_recorder_status;
  80. }
  81. static void recordClose(void){
  82. if(TRUE==g_recorder_status){
  83. nwy_audio_recorder_stop();
  84. nwy_audio_recorder_close();
  85. wlog_info("record close ok");
  86. g_recorder_status=FALSE;
  87. }else wlog_info("record close skip");
  88. }
  89. void isPocPlyIdle(void){
  90. if(PLY_IDLE==playStatus) ticketVote(TICKET_PT_POCPLY);
  91. else ticketDeVote(TICKET_PT_POCPLY);
  92. }
  93. void isPocRecIdle(void){
  94. if(REC_IDLE==recordStatus) ticketVote(TICKET_PT_POCREC);
  95. else ticketDeVote(TICKET_PT_POCREC);
  96. }
  97. T_BOOL isTTSBusy(void){
  98. if(MEDIA_TTS==talking.media || MEDIA_SHUT_POC==talking.media) return TRUE;
  99. else return FALSE;
  100. }
  101. bool isToneReady(void);
  102. T_BOOL playStartTone(void){
  103. if(talking.toneStatus==0) return FALSE;
  104. tryToneNow();
  105. if(true==isToneReady()) return TRUE;
  106. else return FALSE;
  107. }
  108. //poc play handler start...////////////////////////////////
  109. PT_THREAD (ptPocPlayTask(pt_timer_t *ptPool, struct pt *pt)){
  110. static pt_timer_t ptTimer;
  111. static T_UINT32 lastUpdCnt=0;
  112. static T_UINT32 noVoiceTimeout=0,restoreTimeOut=0;
  113. T_UINT8 buffer[PCM_FRAME_BYTE_SIZE];
  114. T_UINT8 tbuf[PCM_FRAME_BYTE_SIZE],temp[32];
  115. T_UINT8 type;
  116. T_INT16 len,framesize;
  117. T_UINT8 voiceType,ft,f_len;
  118. T_INT32 i,ret;
  119. static void *ct_decoder;
  120. static T_BOOL evrc_decode_init_flag=FALSE;
  121. if(FALSE==evrc_decode_init_flag){
  122. evrc_decode_init_flag=TRUE;
  123. #if defined ENABLE_EVRC
  124. ct_decoder=evrc_decoder_init();
  125. #endif
  126. #if defined ENABLE_AMRNB
  127. #ifdef ENABLE_USE_AMRNB
  128. wamr_decoder_init();
  129. wlog_info("amrnb decoder init...");
  130. #endif
  131. #endif
  132. }
  133. if(getSysTick()>talking.voiceLengthTimeMs) talking.playVoiceDone=TRUE;
  134. PT_BEGIN(pt);
  135. while(1){
  136. if(plyShutNow==TRUE || MEDIA_SHUT_POC==talking.media){
  137. playClose();
  138. if(MEDIA_SHUT_POC==talking.media && PLY_IDLE != playStatus){
  139. playStatus=PLY_ON_PENDING;
  140. talking.media=MEDIA_POC_PENDING;
  141. }
  142. if(TRUE==plyShutNow){
  143. if(MEDIA_TTS != talking.media) talking.media=MEDIA_IDLE;
  144. if(PLY_IDLE != playStatus) tryToneNow();//有UDB放卖指令的POC播放结束输出TONE音
  145. playStatus=PLY_IDLE;
  146. plyShutNow=FALSE;
  147. }
  148. }
  149. if(PLY_IDLE==playStatus){
  150. if(lastUpdCnt != talking.udpVoiceCnt && FALSE==talking.hasVoicePri){
  151. recordClose();
  152. recordStatus=REC_IDLE;
  153. playStatus=PLY_ON_START;
  154. }
  155. }else if(PLY_ON_START==playStatus){
  156. /*
  157. if(talking.toneStatus=='1'){
  158. tryToneNow();
  159. PTTimerStart(ptPool, &ptTimer,11);
  160. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  161. }
  162. */
  163. wlog_info("PLY_ON_START");
  164. if(TRUE==playStartTone()){
  165. //使用pt等待100ms
  166. wlog_info("pt wait");
  167. #ifdef SKIP_PA_BY_CB
  168. for(;;){
  169. PTTimerStart(ptPool, &ptTimer,50);//should be fast
  170. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer) || talking.toneBusy==FALSE);
  171. break;
  172. }
  173. #else
  174. PTTimerStart(ptPool, &ptTimer,25);//should be fast
  175. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer)||talking.toneBusy==FALSE);
  176. #endif
  177. }
  178. if(TRUE==isTTSBusy()){
  179. wlog_info("PLY_ON_PENDING");
  180. playStatus=PLY_ON_PENDING;
  181. }else playStatus=PLY_ON_SWITCH;
  182. }else if(PLY_ON_SWITCH==playStatus){
  183. wlog_info("PLY_ON_SWITCH");
  184. if(TRUE==isTTSBusy()){
  185. playStatus=PLY_ON_PENDING;
  186. wlog_info("PLY_ON_PENDING");
  187. break;
  188. }else{
  189. recordClose();recordStatus=REC_IDLE;
  190. if(FALSE==playOpen()){
  191. wlog_error("play open err");
  192. PTTimerStart(ptPool, &ptTimer,100);//wait 1s and then retry
  193. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  194. playStatus=PLY_ON_START;
  195. }else{
  196. if(TRUE==isTTSBusy()){
  197. playClose();
  198. playStatus=PLY_ON_PENDING;
  199. wlog_info("PLY_ON_PENDING");
  200. }else{
  201. talking.media=MEDIA_POC;
  202. noVoiceTimeout=getSysTick();
  203. playStatus=PLY_ON_WAIT;
  204. wlog_info("PLY_ON_WAIT");
  205. }
  206. }
  207. }
  208. }else if(PLY_ON_WAIT==playStatus){
  209. //if(msgQueueNum(Q_VOICEP)>=2){
  210. if(TRUE){
  211. restoreTimeOut=getSysTick();
  212. playStatus=PLY_ON_BUSY;
  213. talking.voiceLengthTimeMs=getSysTick();//need to add 20ms when play one frame
  214. wlog_info("PLY_ON_BUSY");
  215. }else{
  216. if(TRUE==isTTSBusy()){
  217. playClose();
  218. playStatus=PLY_ON_PENDING;
  219. wlog_info("PLY_ON_PENDING");
  220. }else{
  221. if(getSysTick()-restoreTimeOut >= 100){
  222. restoreTimeOut=getSysTick();
  223. msgQueueClear(Q_VOICEP);
  224. playClose();
  225. playStatus=PLY_IDLE;
  226. lastUpdCnt=talking.udpVoiceCnt;
  227. }
  228. }
  229. }
  230. }else if(PLY_ON_BUSY==playStatus){
  231. if(TRUE==isTTSBusy()){
  232. playClose();
  233. playStatus=PLY_ON_PENDING;
  234. wlog_info("PLY_ON_PENDING");
  235. }else{
  236. if(talking.hasVoicePri==TRUE){
  237. wlog_info("has pri,close ply,start rec");
  238. playClose();
  239. playStatus=PLY_IDLE;
  240. pocStartRecord();
  241. goto PLY_TAIL;
  242. }
  243. len=msgQueueAccept(buffer,sizeof(buffer), Q_VOICEP, (T_UINT8 *)&type);
  244. if(len<=0 || QSUB_VOICE_PLAY != type){
  245. restoreTimeOut=getSysTick();
  246. if(TRUE==talking.playVoiceDone){
  247. if(getSysTick()-noVoiceTimeout >= 100){// || LSAPI_AUD_GetPlayerState()!=LSAPI_PLAYER_PLAYING){
  248. wlog_warn("No voice data");
  249. noVoiceTimeout=getSysTick();
  250. playClose();
  251. playStatus=PLY_IDLE;
  252. if(talking.media!= MEDIA_TTS) talking.media=MEDIA_IDLE;
  253. lastUpdCnt=talking.udpVoiceCnt;
  254. tryToneNow();//没有UDP放麦指令的POC从这里发播放结束TONE音
  255. }
  256. }else{
  257. PTTimerStart(ptPool, &ptTimer,5);//wait 5ms
  258. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  259. }
  260. }else{
  261. noVoiceTimeout=getSysTick();
  262. voiceType=buffer[12];
  263. len=evrcPacketDecode(tbuf, buffer,len);
  264. i=0;
  265. while(i<len){
  266. if(HAS_AMRNB_RATE==voiceType){
  267. #if defined ENABLE_AMRNB
  268. #ifdef ENABLE_USE_AMRNB
  269. ft=(*(tbuf+i)>>3) & 0x0f;
  270. framesize=packed_size[ft]+1;
  271. if(TRUE==talking.hasVoicePri){
  272. i += framesize;
  273. continue;
  274. }
  275. memset(temp,0,sizeof(temp));
  276. memcpy(temp,tbuf+i,framesize);
  277. ret=wamr_decoder_decode_frame(temp, framesize,(short *)buffer,PCM_FRAME_BYTE_SIZE/2);
  278. i += framesize;
  279. if(AMRC_CODEC_SUCC != ret){
  280. wlog_error("amrnb decode frame failed");
  281. continue;
  282. }
  283. #endif
  284. #else
  285. wlog_warn("amrnb is disable!!!");
  286. continue;
  287. #endif
  288. }else{
  289. #if defined ENABLE_EVRC
  290. f_len=tbuf[i+1]+2;
  291. if(TRUE==talking.hasVoicePri){
  292. i += f_len;
  293. continue;
  294. }
  295. ret=evrc_decoder_decode_from_stream(ct_decoder, tbuf+i,f_len, (short *)buffer, PCM_FRAME_BYTE_SIZE/2);
  296. i += f_len;
  297. if(ret<=0){
  298. wlog_error("evrc decode frame failed");
  299. continue;
  300. }
  301. #else
  302. wlog_warn("evrc is disable!!!");
  303. continue;
  304. #endif
  305. }
  306. lsapiWriteFrame(buffer,PCM_FRAME_BYTE_SIZE);
  307. if(TRUE==isTTSBusy()){
  308. playClose();
  309. playStatus=PLY_ON_PENDING;
  310. break;
  311. }
  312. if(plyShutNow==TRUE) break;
  313. }
  314. }
  315. }
  316. }else if(PLY_ON_PENDING==playStatus){
  317. msgQueueClear(Q_VOICEP);
  318. if(MEDIA_IDLE==talking.media){
  319. PTTimerStart(ptPool, &ptTimer,5);//wait 5ms
  320. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  321. playStatus=PLY_ON_START;
  322. wlog_info("PLY_ON_PENDING recover");
  323. }
  324. }
  325. PLY_TAIL:
  326. lastUpdCnt=talking.udpVoiceCnt;
  327. isPocPlyIdle();
  328. PTTimerStart(ptPool, &ptTimer,1);//should be fast
  329. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  330. }
  331. PT_END(pt);
  332. }
  333. void pocSpkMicNotify(SPK_MIC_ENUM mic, SPK_MIC_ENUM spk){
  334. #ifndef SKIP_PA_BY_CB
  335. T_INT8 info[15];
  336. static SPK_MIC_ENUM lmic=C_OFF;
  337. static SPK_MIC_ENUM lspk=C_OFF;
  338. if(C_NO_PRI != spk){
  339. if(lmic == mic && lspk == spk) return;
  340. }
  341. snprintf(info, sizeof(info), "+POC:8B");
  342. if(C_OFF == mic) strcat(info, "00");
  343. else strcat(info , "01");
  344. if(C_OFF == spk) strcat(info , "00");
  345. else if(C_ON == spk) strcat(info, "01");
  346. else if(C_ON_TTS== spk) strcat(info, "02");
  347. else strcat(info, "13");
  348. strcat(info, "\r\n");
  349. lmic=mic;lspk=spk;
  350. //msgToOutter(info);
  351. outterInfo(info,strlen(info));
  352. #endif
  353. }
  354. void NotifyHandle(void){
  355. if(talking.media==MEDIA_TTS) pocSpkMicNotify(C_OFF,C_ON_TTS);
  356. else{
  357. if(talking.hasVoicePri==TRUE){
  358. if(recordStatus<=REC_ON_BUSY && recordStatus>=REC_ON_START) pocSpkMicNotify(C_ON,C_OFF);
  359. else pocSpkMicNotify(C_OFF,C_OFF);
  360. }else{
  361. if(playStatus<=PLY_ON_BUSY && playStatus>=PLY_ON_START) pocSpkMicNotify(C_OFF,C_ON);
  362. else pocSpkMicNotify(C_OFF,C_OFF);;
  363. }
  364. }
  365. }
  366. //poc record handler start...////////////////////////////////
  367. PT_THREAD (ptPocRecordTask(pt_timer_t *ptPool, struct pt *pt)){
  368. static pt_timer_t ptTimer;
  369. static T_BOOL lastPttStatus=FALSE;
  370. static T_UINT32 pendTime=0;
  371. T_UINT8 buffer[PCM_FRAME_BYTE_SIZE];
  372. PT_BEGIN(pt);
  373. while(1){
  374. if(recShutNow==TRUE || MEDIA_SHUT_POC==talking.media){
  375. recordClose();
  376. if(MEDIA_SHUT_POC==talking.media && REC_IDLE != recordStatus){
  377. recordStatus=REC_ON_PENDING;
  378. talking.media=MEDIA_POC_PENDING;
  379. }
  380. if(TRUE==recShutNow){
  381. if(MEDIA_TTS != talking.media) talking.media=MEDIA_IDLE;
  382. if(REC_IDLE != recordStatus){
  383. tryToneNow();
  384. #ifdef SKIP_PA_BY_CB
  385. poc_8b(C_OFF,C_OFF);//当不开TONE音时,录音结束需要发结束指令
  386. #endif
  387. }
  388. recordStatus=REC_IDLE;
  389. recShutNow=FALSE;
  390. }
  391. }
  392. if(REC_IDLE==recordStatus){
  393. if(TRUE==talking.pttReqStatus){
  394. playClose();
  395. playStatus=PLY_IDLE;
  396. recordStatus=REC_ON_START;
  397. }
  398. }else if(REC_ON_START==recordStatus){
  399. wlog_info("REC_ON_START");
  400. if(talking.tcpLoginStatus!=TCP_ONLINE_IDLE){
  401. //处理以下情况:
  402. //本机A比另一台B优先级高,同时在线时,B呼A
  403. //平台修改A,目的让A掉线,同时保持A还是高优
  404. //10秒左右后A请麦再放开,此时A会掉线同时,对讲状态异常
  405. //原因是先掉线,请麦结果后面收到,启动了播放流程
  406. wlog_info("LINE OFF, QUIT REC");
  407. talking.pttReqStatus=FALSE;
  408. talking.pttReleasedAlready=TRUE;
  409. talking.hasVoicePri=FALSE;
  410. recordStatus=REC_IDLE;
  411. }else{
  412. if(TRUE==isTTSBusy()){
  413. recordStatus=REC_ON_PENDING;
  414. wlog_info("REC_ON_PENDING");
  415. }else recordStatus=REC_ON_SWITCH;
  416. }
  417. }else if(REC_ON_SWITCH==recordStatus){
  418. wlog_info("REC_ON_SWITCH");
  419. if(TRUE==isTTSBusy()){
  420. recordStatus=REC_ON_PENDING;
  421. wlog_info("REC_ON_PENDING");
  422. }else{
  423. playClose();
  424. if(PLY_IDLE != playStatus) playStatus=PLY_IDLE;
  425. #ifdef SKIP_PA_BY_CB
  426. wlog_info("pt wait");
  427. for(;;){
  428. PTTimerStart(ptPool, &ptTimer,50);//should be fast
  429. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer) || talking.toneBusy==FALSE);
  430. break;
  431. }
  432. #endif
  433. if(FALSE==recordOpen()){
  434. wlog_error("record open err");
  435. PTTimerStart(ptPool, &ptTimer,50);//wait 0.5s and then retry
  436. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  437. recordStatus=REC_ON_START;
  438. }else{
  439. if(TRUE==isTTSBusy()){
  440. recordClose();
  441. recordStatus=REC_ON_PENDING;
  442. wlog_info("REC_ON_PENDING");
  443. }else{
  444. talking.media=MEDIA_POC;
  445. recordStatus=REC_ON_BUSY;
  446. wlog_info("REC_ON_BUSY");
  447. #ifdef SKIP_PA_BY_CB
  448. poc_8b(C_ON,C_OFF);
  449. #endif
  450. }
  451. }
  452. }
  453. }else if(REC_ON_BUSY==recordStatus){
  454. if(TRUE==isTTSBusy()){
  455. recordClose();
  456. recordStatus=REC_ON_PENDING;
  457. wlog_info("REC_ON_PENDING");
  458. }else{
  459. //add record process
  460. //done in callback
  461. }
  462. }else if(REC_ON_PENDING==recordStatus){
  463. if(MEDIA_IDLE==talking.media){
  464. pendTime=0;
  465. PTTimerStart(ptPool, &ptTimer,50);//wait 0.5s
  466. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  467. if(TRUE==talking.pttReqStatus){
  468. recordStatus=REC_ON_START;
  469. wlog_info("REC_ON_PENDING recover");
  470. }else{
  471. recordStatus=REC_IDLE;
  472. wlog_info("REC_ON_PENDING quit");
  473. }
  474. }else{
  475. //if(getSysTick()>pendTime){
  476. //pendTime += 2;
  477. if(++pendTime>=2){
  478. pendTime = 0;
  479. memset(buffer, 0xff, sizeof(buffer));
  480. if(0!=msgToRecord(buffer, sizeof(buffer))) wlog_error("REC QUE POST FAIL");
  481. }
  482. //PTTimerStart(ptPool, &ptTimer,2);
  483. //PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  484. }
  485. }
  486. #ifndef SKIP_PA_BY_CB
  487. NotifyHandle();
  488. #endif
  489. lastPttStatus=talking.pttReqStatus;
  490. isPocRecIdle();
  491. PTTimerStart(ptPool, &ptTimer,1);//should be fast
  492. PT_WAIT_UNTIL(pt, PTTimerIsExpired(&ptTimer));
  493. }
  494. PT_END(pt);
  495. }
  496. void RecCloseNowApi(void){recShutNow=TRUE;}
  497. void PlyCloseNowApi(void){plyShutNow=TRUE;}
  498. void RecOpenNowApi(void){
  499. if(REC_IDLE==recordStatus)
  500. recordStatus=REC_ON_START;
  501. }
  502. void PlyOpenNowApi(void){
  503. if(PLY_IDLE==playStatus)
  504. playStatus=PLY_ON_START;
  505. }
  506. T_BOOL isPlayerIsOff(void){
  507. if(PLY_IDLE == playStatus) return TRUE;
  508. else return FALSE;
  509. }
  510. T_BOOL isRecordIsOff(void){
  511. if(REC_IDLE == recordStatus) return TRUE;
  512. else return FALSE;
  513. }
  514. ////////////////////////////////以下为tone音操作///////////////////////////////////
  515. static int tunNum=0;
  516. #define TONE_FREQUENCY 880
  517. static nwy_osiThread_t *gToneTd = NULL;
  518. bool isToneReady(void){
  519. if(talking.media==MEDIA_TTS){
  520. wlog_info("try tone but tts is busy");
  521. return false;
  522. }
  523. if(true==isPcmPlayerOn()){
  524. wlog_info("try tone but player is busy");
  525. return false;//播放过程中不输出TONE音
  526. }
  527. if(TRUE==g_recorder_status){
  528. wlog_info("try tone but rec is busy");
  529. return false;
  530. }
  531. return true;
  532. }
  533. void toneThread(void *param){
  534. nwy_osiEvent_t waitevent;
  535. wlog_info("toneThread start");
  536. for(;;){
  537. nwy_wait_thead_event(nwy_get_current_thread(), &waitevent,0);
  538. if(waitevent.id==USER_EVENT_EXIT) break;
  539. else if(waitevent.id==USER_EVENT_TONE){
  540. if(true==isToneReady() && tunNum!=0){
  541. talking.toneBusy=TRUE;
  542. msgToOutter("+TONE:1\r\n");
  543. wlog_info("tone now");
  544. nwy_audio_tone_play("DTMF", 100, 15);
  545. wlog_info("tone end");
  546. tunNum=0;
  547. talking.toneBusy=FALSE;
  548. }
  549. }
  550. }
  551. gToneTd=NULL;
  552. nwy_exit_thread();
  553. }
  554. void toneThreadOn(void){
  555. if(NULL != gToneTd) return;
  556. gToneTd=nwy_create_thread("tone", toneThread, NULL, NWY_OSI_PRIORITY_NORMAL, TONE_THREAD_STACK, 10);
  557. if(NULL==gToneTd) wlog_info("Tone thread failed");
  558. }
  559. void toneExit(void){
  560. if(NULL==gToneTd) return;
  561. threadPostEvent(gToneTd,USER_EVENT_EXIT);
  562. }
  563. void tryToneNow(void){
  564. if(NULL==gToneTd) return;
  565. tunNum++;
  566. threadPostEvent(gToneTd,USER_EVENT_TONE);
  567. }
  568. #ifdef SKIP_PA_BY_CB
  569. void poc_8b(SPK_MIC_ENUM mic, SPK_MIC_ENUM spk){
  570. T_INT8 info[15];
  571. static SPK_MIC_ENUM lmic=C_OFF;
  572. static SPK_MIC_ENUM lspk=C_OFF;
  573. if(C_NO_PRI != spk){
  574. if(lmic == mic && lspk == spk) return;
  575. }
  576. snprintf(info, sizeof(info), "+POC:8B");
  577. if(C_OFF == mic) strcat(info, "00");
  578. else strcat(info , "01");
  579. if(C_OFF == spk) strcat(info , "00");
  580. else if(C_ON == spk) strcat(info, "01");
  581. else if(C_ON_TTS== spk) strcat(info, "02");
  582. else strcat(info, "13");
  583. strcat(info, "\r\n");
  584. lmic=mic;lspk=spk;
  585. //msgToOutter(info);
  586. outterInfo(info,strlen(info));
  587. }
  588. nwy_osiThread_t *threadIdPa=NULL;
  589. typedef enum{
  590. PA_TTS=1,
  591. PA_TONE=2,
  592. PA_PCM=16
  593. }PA_ENUM;
  594. static void prvExterPACallBack(uint8_t pa_switch_on, uint32_t clk_user, uint8_t outdev){
  595. nwy_osiEvent_t event = {};
  596. event.id=USER_EVENT_PA;
  597. event.param2=clk_user;
  598. if(pa_switch_on) event.param1=0;
  599. else event.param1=1;
  600. if(clk_user ==PA_TTS || clk_user == PA_TONE || clk_user == PA_PCM) osiEventTrySend(threadIdPa,&event,0);
  601. }
  602. static void paProcess(void *param){
  603. nwy_osiEvent_t event = {};
  604. wlog_info("paProcess task start");
  605. #if 0
  606. for(;;){
  607. nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
  608. if(event.id==USER_EVENT_PA){
  609. if(event.param1==1){//关闭PA操作
  610. if(event.param2==PA_PCM) poc_8b(C_OFF,C_OFF);
  611. else if(event.param2==PA_TTS) poc_8b(C_OFF,C_OFF);
  612. else if(event.param2==PA_TONE) poc_8b(C_OFF,C_OFF);
  613. LSAPI_AUD_SetExterPAStatus(LSAPI_EXTERN_PA_STOP_BEGIN);
  614. nwy_sleep(40);
  615. LSAPI_AUD_SetExterPAStatus(LSAPI_EXTERN_PA_STOP_DONE);
  616. }else if(event.param1==0){//打开PA操作
  617. LSAPI_AUD_SetExterPAStatus(LSAPI_EXTERN_PA_START_BEGIN);
  618. nwy_sleep(250);
  619. if(event.param2==PA_PCM) poc_8b(C_OFF,C_ON);
  620. else if(event.param2==PA_TTS) poc_8b(C_OFF,C_ON_TTS);
  621. else if(event.param2==PA_TONE) poc_8b(C_OFF,C_ON_TTS);
  622. LSAPI_AUD_SetExterPAStatus(LSAPI_EXTERN_PA_START_DONE);
  623. }
  624. }
  625. }
  626. #endif
  627. }
  628. void audioPAInit(void){
  629. bool ret = true;
  630. threadIdPa=nwy_create_thread("paProcess", paProcess, NULL, NWY_OSI_PRIORITY_NORMAL, 1024.4, 6);
  631. if(NULL==threadIdPa){
  632. wlog_error("paProcess create failed");
  633. return;
  634. }
  635. // if(false == LSAPI_AUD_SetExterPACallback(prvExterPACallBack)) wlog_error("Audio PA Init failed");
  636. // else wlog_info("Audio PA Init ok");
  637. }
  638. #endif