speaker.cxx
25.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
/******************************************************************
* Author : tyh (tangyinghao@autelrobotics.cn)
* CreateTime : 2024/2/19
* Copyright (c) 2024 Shenzhen Autel Robotics Co., Ltd.
* File Desc :
*******************************************************************/
#include "uav_error.h"
#include "uav_widget.h"
#include "uav_logger.h"
//#include "uav_register.h"
#include <string>
#include <thread>
#include <sys/time.h>
#include "uav_core.h"
#include "uav_platform.h"
#include "uav_sdk_app_info.h"
#include "uav_fc_subscription.h"
#include "uav_low_speed_data_channel.h"
#include "uav_data_type.h"
#include "JZ_lamp.h"
#include "JZ_TempControl.h"
#include "JZ_widget.h"
#include "JZ_uart.h"
#include "ircut.h"
#include "music.h"
#include "util_md5.h"
#include "tts_sample.h"
#include "opus.h"
#include "wiringPi.h"
#include "Interface.h"
/* Exported types ------------------------------------------------------------*/
// typedef enum
// {
// OPUS = 0,
// MP3 = 1,
// }E_AudioType;
/* Private constants ---------------------------------------------------------*/
/* The speaker initialization parameters */
#define WIDGET_SPEAKER_DEFAULT_VOLUME (30)
#define WIDGET_SPEAKER_TASK_STACK_SIZE (10240) //2048
/*! Attention: replace your audio device name here. */
#define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo"
#define WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME "test_audio.opus"
#define WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME "test_audio.pcm"
#define WIDGET_SPEAKER_AUDIO_MP3_FILE_NAME "/root/sdcard/record/record.mp3" //mp3路径
#define WIDGET_SPEAKER_TTS_FILE_NAME "test_tts.txt"
#define WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME "tts_audio.wav"
#define WIDGET_SPEAKER_TTS_FILE_MAX_SIZE (4000)
/* The frame size is hardcoded for this sample code but it doesn't have to be */
#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE (3 * 1276)
#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE (6 * 960)
#define WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE (16000)
#define WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS (1)
#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS (40)
#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS (8000)
#define EKHO_INSTALLED (1)
/* Private values -------------------------------------------------------------*/
static T_UavWidgetSpeakerHandler s_speakerHandler = {0};
static T_UavWidgetSpeakerExHandler s_speakerExHandler = {0};
static T_UavWidgetSpeakerState s_speakerState = {UAV_WIDGET_SPEAKER_STATE_IDEL ,UAV_WIDGET_SPEAKER_WORK_MODE_TTS, UAV_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY, 0};
extern int music_sum;//歌曲总数
extern int music_num;//当前播放的歌曲编号
extern char musiclist[128][128];//最多存取128首歌曲
extern int musicname_len[128];//每首歌曲名字长度
extern int play_mode;//播放模式,play_mode==1单曲循环,play_mode==0单曲播放
extern int now_volume;//默认音量10--》50+10/2==55
extern int now_play_stat;
extern int tts_add;
extern int tts_tone;
extern int tts_volume;
extern int tts_speed;
extern int lock_play;
extern int set_volume_value;//设置音量值
extern int aplay_flag;//默认是0
extern int TTS_flag;//默认是0
extern int WidgetPlayFlag;
extern int TTS_delay;
extern int ReadTimeSpeak_Mode;
uint16_t workMode_flag=UAV_WIDGET_SPEAKER_WORK_MODE_VOICE;
int now_play=0;//当前播放状态 播放为1 停止为0
int reset_play=0;//重置播放标志,用于重头开始播放歌曲,默认使用。
int TTS_switch=1;//默认TTS开关不打开
int jizhi=0;//预留位
int write_EQ_flag=0;
int write_EQ_2K_value=0;
int write_EQ_2_5K_value=0;
int write_EQ_3K_value=0;
int write_EQ_4K_value=0;
int A_write=-1;
static FILE *s_audioFile = NULL;
static FILE *s_ttsFile = NULL;
static bool s_isDecodeFinished = true;
//static E_AudioType s_isAudioType = OPUS;
static uint16_t s_decodeBitrate = 16000;
pthread_mutex_t s_speakerMutex;//扬声器互斥锁
int lampAngle = 0;//无人机云台角度
int gimbalFineTuneAngle = 0; //云台微调角度
int lightMode = 0;//当前探照灯模式
int speakerMode = 0;//喊话模式 0:无播放 1:实时喊话 2:文本喊话 3:录音喊话
char record_file_name[128];//录音文件名
int playback_delay = 2;//循环播放延迟时间
uint16_t text_len;//文本喊话文本长度
uint8_t text_buf[1024];//文本喊话文本
extern int gimbalLinkageState;
extern pthread_mutex_t gimbalMutex;
extern bool thread_created;//判断喊话线程是否已经创建
int playStatusQueryFlag;//播放状态查询标志
/* Private functions declaration ---------------------------------------------*/
static T_UAVReturnCode UAV_WidgetSpeakerInit(void);
static T_UAVReturnCode Test_DecodeAudioData(void);
extern void set_amplifier(int amplifier_mode);
void registThreadFunc(void);
static void myGimbalAngleMsgCB(void *data);
/* Exported functions definition ---------------------------------------------*/
int main(int argc, char *argv[])
{
T_AUserInfo usrInfo;
logger_init(std::string(argv[1]));
if(false == uav_sdk_app_info_init(&usrInfo)) {
LOG_ERROR("uav_sdk_app_info_init failed");
return -1;
}
UAV_Core_Init(&usrInfo);
UAV_Core_SetAlias("speaker");
//设置版本号
T_UAVFirmwareVersion fwVersion;
fwVersion.majorVersion = 1;
fwVersion.minorVersion = 0;
fwVersion.patchVersion = 0;
fwVersion.debugVersion = 0;
UAV_Core_SetFirmwareVersion(fwVersion);
UAV_Uart_Init("/dev/ttyS1",115200);
set_payload_type(6);
UAV_WidgetSpeakerInit();
LOG_INFO(" speaker init ");
std::thread registerThread(registThreadFunc);
registerThread.detach();
return UAV_Core_ApplicationStart();
}
void registThreadFunc(void)
{
int ret = 0;
//wait register success
if(false == wait_register_ready(100)){
LOG_ERROR("waitHandShakeRegister failed");
return;
}
//订阅Speaker消息,进行对应的speaker操作
ret =UAV_LowSpeedDataChannel_Init();
LOG_INFO(" channel init ret :{}", ret);
ret = UAV_Widget_RegSpeakerHandler(&s_speakerHandler);
LOG_INFO(" speaker reg ret :{}", ret);
ret = UAV_Widget_RegSpeakerExHandler(&s_speakerExHandler);
LOG_INFO(" speaker exreg ret :{}", ret);
LOG_INFO("end registThreadFunc");
JzUartInit("/dev/ttyS2",115200);//串口初始化
lamp_init();//初始化探照灯
usleep(500*1000);
init_amplifier();//静音初始化
login_tts();//讯飞初始化
music_init(); //初始化喊话器
TTS_delay = playback_delay + 2; //设置文本喊话播放延迟
usleep(3500*1000);
UAV_SubscribeTopic(UAV_SUBSCRIPTION_TOPIC_GIMBAL_ANGLE, 50, myGimbalAngleMsgCB);
}
static void myGimbalAngleMsgCB(void *data)
{
T_UAVSubscriptionGimbalAngle *gimbalAngle = (T_UAVSubscriptionGimbalAngle *)data;
const float pi = 3.1416f;
float temp = gimbalAngle->x / pi * 180 * 1;
pthread_mutex_lock(&gimbalMutex);
lampAngle = -temp;//获取云台角度
pthread_mutex_unlock(&gimbalMutex);
usleep(20*1000);
}
static void SetSpeakerState(E_UavWidgetSpeakerState speakerState)
{
s_speakerState.state = speakerState;
LOG_INFO("SetSpeakerState:s_speakerState.state={}",s_speakerState.state);
}
static T_UAVReturnCode GetSpeakerState(T_UavWidgetSpeakerState *speakerState)
{
*speakerState = s_speakerState;
LOG_INFO(" speaker State: {} {} {} {}", (int)s_speakerState.state, (int)s_speakerState.workMode,
(int)s_speakerState.playMode, s_speakerState.volume );
if(play_mode == 0)
{
s_speakerState.playMode = UAV_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY;
}
else
{
s_speakerState.playMode = UAV_WIDGET_SPEAKER_PLAY_MODE_LOOP_PLAYBACK;
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode SetWorkMode(E_UavWidgetSpeakerWorkMode workMode)
{
LOG_INFO("Set widget speaker work mode: {}", workMode);
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode SetPlayMode(E_UavWidgetSpeakerPlayMode playMode)
{
LOG_INFO("Set widget speaker play mode: {}", playMode);
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode StartPlay(void)
{
LOG_INFO("StartPlay");
while (1)
{ //等待喊话器无播放
if(aplay_flag == 1 || TTS_flag == 1)
{
usleep(10*1000);
}
else
{
speakerMode = 1;//实时喊话
Init_opus();
SetSpeakerState(UAV_WIDGET_SPEAKER_STATE_PLAYING);
break;
}
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
int stopflag = 0;
static T_UAVReturnCode StopPlay(void)
{
if(stopflag == 1)
{
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
stopflag = 1;
LOG_INFO("StopPlay");
SetSpeakerState(UAV_WIDGET_SPEAKER_STATE_IDEL);
WidgetPlayFlag = 0;//退出录音播放
speakerMode = 0;
Opus_RealTimeSpeak_AbnormalInterrupt();
stopflag = 0;
set_paly_state(0);
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode SetVolume(uint8_t volume)
{
s_speakerState.volume = volume;
set_volume(volume);
LOG_INFO("Set widget speaker volume: {}", volume);
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
//static T_UAVReturnCode GetVolume(uint8_t *volume)
//{
// *volume = s_speakerState.volume;
// LOG_INFO("Get widget speaker volume: %d", *volume);
// return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
//}
static T_UAVReturnCode ReceiveTtsData(E_UavWidgetTransmitDataEvent event,
uint32_t offset, uint8_t *buf, uint16_t size)
{ LOG_INFO("ReceiveTtsData");
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode ReceiveAudioData(E_UavWidgetTransmitDataEvent event,
uint32_t offset, uint8_t *buf, uint16_t size)
{
uint16_t writeLen;
T_UAVReturnCode returnCode;
uint8_t data[256];
LOG_INFO("Transmit voice file, offset: {}, size: {}\n", offset, size);
if(speakerMode == 1)
{//实时喊话
LOG_INFO("实时喊话");
for (int i = 0; i < size; i += 80)
{
// 调用write_loop,传递当前80字节的块和块的大小
if(speakerMode != 1)
{ //如果模式改变,则退出循环
break;
}
memcpy(data, buf + i, 80);
write_loop(data, 80);
}
}
if(speakerMode == 2 && size != 400)//文本喊话
{
LOG_INFO("文本喊话");
text_len = size;
memset(text_buf, 0, sizeof(text_buf));
memcpy(text_buf, buf, size);
}
if(speakerMode == 3 )
{//录音喊话处理
if (s_audioFile != NULL) {
writeLen = fwrite(buf, 1, size, s_audioFile);
if (writeLen != size) {
LOG_ERROR("Write tts file error {}", writeLen);
}
}
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode SpeakerControl(T_UavWidgetSpeakerControl *speakerControl)
{
LOG_INFO("SpeakerControl : moduleID:{} action:{} value:{} strValue:{}" ,speakerControl->moduleID,speakerControl->action,speakerControl->value,speakerControl->strValue);
if(speakerControl->moduleID == 1)//探照灯
{
switch (speakerControl->action) {
case 1://开灯
Jz_Lamp_On();
//play_music(musiclist[music_num],musicname_len[music_num]);
break;
case 2://关灯
Jz_Lamp_Off();
break;
case 3://亮度调节
Jz_LampLumenControl(speakerControl->value,speakerControl->value);
break;
case 4://云台角度控制
if(speakerControl->value < 0)
{
int angle = -speakerControl->value;
Jz_Lamp_Gimbal_Control(angle);
}
break;
case 5://云台联动开启
Jz_GimbalLinkage(1);
break;
case 6://云台联动关闭
Jz_GimbalLinkage(0);
break;
case 8://爆闪模式
if(speakerControl->value == 0)
{
JZ_SelectPoliceLampMode(0,0); //警灯关闭
}
if(speakerControl->value == 1)
{
JZ_SelectPoliceLampMode(0,0);
usleep(50*1000);
JZ_SelectPoliceLampColor(1,1);
usleep(50*1000);
JZ_SelectPoliceLampMode(1,0);//警灯模式 交替快闪
}
if(speakerControl->value == 2)
{
JZ_SelectPoliceLampMode(0,0);
usleep(50*1000);
JZ_SelectPoliceLampColor(1,3);//警灯颜色红 蓝
usleep(50*1000);
JZ_SelectPoliceLampMode(1,0);//警灯模式 交替快闪
}
break;
}
}
if(speakerControl->moduleID == 2)//喊话器
{
switch (speakerControl->action) {
case 4://音频文件上传开启
char opus_file_name[128];
size_t len;
stop_music();
speakerMode = 3;//录音喊话模式
set_paly_state(3);
s_isDecodeFinished = false;//解码标志位
LOG_INFO("Create voice file.");
//将不带格式的名字取出来
len = strrchr(speakerControl->strValue, '.') - speakerControl->strValue;
memcpy(record_file_name, "\0", 128);
strncpy(record_file_name, speakerControl->strValue, len);
record_file_name[len] = '\0';
sprintf(opus_file_name, "record/%s.opus", record_file_name);
s_audioFile = fopen(opus_file_name, "wb");
if (s_audioFile == NULL) {
LOG_ERROR("Create tts file error.");
}
break;
case 5://音频文件上传关闭
if (s_audioFile != NULL) {
LOG_INFO("Close voice file.");
fclose(s_audioFile);
s_audioFile = NULL;
Test_DecodeAudioData();//解码
}
break;
case 8://音频暂停
WidgetPlayFlag = 0;//用于退出录音喊话循环
stop_music();
set_paly_state(0);
if(speakerMode !=1)
{
speakerMode = 0;//用于退出录音喊话循环
}
thread_created = false;//线程是否关闭标志位
break;
case 9://音频停止
WidgetPlayFlag = 0;//用于退出录音喊话
stop_music();
set_paly_state(0);
if(speakerMode !=1)
{
speakerMode = 0;//用于退出录音喊话循环
}
thread_created = false;//线程是否关闭标志位
break;
case 10://上一曲
last_music();
break;
case 11://下一曲
next_music();
break;
case 14:
//播放音频
speakerMode = 3;
JZ_loop_playback_create();//录音喊话线程
break;
case 15:
/*音色选择列表
0---中文女生---1
1---中文男生---2
2---英文女生---11
3---英文男生---12
4---东北话-----31
5---四川话-----32
6---河南话-----33
7---湖南话-----34
8---陕西话-----35
9---广东话-----36 */
switch(speakerControl->value){
case 0:
tts_tone=1;
break;
case 1:
tts_tone=2;
break;
case 2:
tts_tone=11;
break;
case 3:
tts_tone=12;
break;
case 4:
tts_tone=31;
break;
case 5:
tts_tone=32;
break;
case 6:
tts_tone=33;
break;
case 7:
tts_tone=34;
break;
case 8:
tts_tone=35;
break;
case 9:
tts_tone=36;
break;
default:
tts_tone=1;
break;
}
break;
case 16://语速选择
switch(speakerControl->value){
case 0:
tts_speed=25;
break;
case 1:
tts_speed=50;
break;
case 2:
tts_speed=75;
break;
case 3:
tts_speed=100;
break;
default:
tts_speed=50;
break;
}
break;
case 17://文本传输
speakerMode = 2;
break;
case 18://文本传输结束
LOG_INFO("文本传输结束");
if(aplay_flag == 0 && ReadTimeSpeak_Mode == 0)//防止录音喊话或实时喊话未结束就播放TTS
{
TTS(tts_tone,set_volume_value,tts_speed,text_len,(char *)text_buf);
}
else
{
playStatusQueryFlag = 1;//录音喊话或实时喊话未结束,关闭此次喊话
}
break;
case 19://开启循环
set_mode(speakerControl->value);
break;
}
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode SpeakerQuery(T_UavWidgetSpeakerQuery *speakerQuery,T_UavWidgetSpeakerQueryRsp *speakerQueryRsp)
{
LOG_INFO("SpeakerQuery :moduleID:{} action:{} value:{}",speakerQuery->moduleID,speakerQuery->query,speakerQuery->pageIndex);
printf("\tspeakerQueryRsp :value:%d strValue:%s pageContent: %spageIndex:%d pageCnt:%d\n",speakerQueryRsp->value,
speakerQueryRsp->strValue,speakerQueryRsp->pageContent,speakerQueryRsp->pageIndex,speakerQueryRsp->pageCnt);
if(speakerQuery->moduleID ==1)
{
switch(speakerQuery->query)
{
case 4://云台联动状态
speakerQueryRsp->value = gimbalLinkageState;
break;
}
}
if(speakerQuery->moduleID == 2)
{
switch(speakerQuery->query)
{
case 1:
if(play_mode == 1)//开启了循环
{
if(playStatusQueryFlag == 1)//上次播放未完成,关闭播放
{
speakerQueryRsp->value = 0;
playStatusQueryFlag = 0;
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
speakerQueryRsp->value = 1;//一直显示喊话中
}
else
{
if(speakerMode == 2)
{
speakerQueryRsp->value = TTS_flag;
}
if(speakerMode == 3)//录音喊话播放状态
{
speakerQueryRsp->value = aplay_flag;
}
}
break;
case 2://实时喊话音量
speakerQueryRsp->value = set_volume_value;
break;
case 3://查询歌曲列表
if(speakerQuery->pageIndex == 0)
{
}
break;
case 4://opus编码结果
if(s_isDecodeFinished != true)
{
speakerQueryRsp->value = 1;
LOG_ERROR("解码未结束\n");
return -1;
}
speakerQueryRsp->value = 0;
break;
case 5://循环开关查询
speakerQueryRsp->value = play_mode;
break;
}
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode UAV_WidgetSpeakerInit(void)
{
T_UAVReturnCode returnCode;
// s_speakerHandler.SetSpeakerState = SetSpeakerState;
s_speakerHandler.GetSpeakerState = GetSpeakerState;
s_speakerHandler.SetWorkMode = SetWorkMode;
s_speakerHandler.StartPlay = StartPlay;
s_speakerHandler.StopPlay = StopPlay;
s_speakerHandler.SetPlayMode = SetPlayMode;
s_speakerHandler.SetVolume = SetVolume;
// s_speakerHandler.GetVolume = GetVolume;
s_speakerHandler.ReceiveTtsData = ReceiveTtsData;
s_speakerHandler.ReceiveVoiceData = ReceiveAudioData;
s_speakerExHandler.SpeakerControl = SpeakerControl;
s_speakerExHandler.SpeakerQuery = SpeakerQuery;
s_speakerState.state = UAV_WIDGET_SPEAKER_STATE_IDEL;
s_speakerState.workMode = UAV_WIDGET_SPEAKER_WORK_MODE_VOICE;
s_speakerState.playMode = UAV_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY;
returnCode = SetVolume(WIDGET_SPEAKER_DEFAULT_VOLUME);
if (returnCode != UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
LOG_ERROR("Set speaker volume error: 0x%08llX", returnCode);
return returnCode;
}
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
T_UAVReturnCode Test_RunSystemCmd(char *systemCmdStr)
{
int status;
status = system(systemCmdStr);
if (status == -1 || WIFEXITED(status) == false) {
LOG_ERROR("Call %s error, status = %d", systemCmdStr, status);
return UAV_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
}
if (WEXITSTATUS(status) == 0) {
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
} else {
LOG_ERROR("Exit status is = %d", WEXITSTATUS(status));
return UAV_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
}
}
static T_UAVReturnCode ReceiveRealTimeAudioData(E_UavWidgetTransmitDataEvent event,
uint32_t offset, uint8_t *buf, uint16_t size)
{
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
static T_UAVReturnCode Test_DecodeAudioData(void)
{
FILE *fin;
FILE *fout;
OpusDecoder *decoder;
opus_int16 out[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS];
uint8_t cbits[WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE];
int32_t nbBytes;
int32_t err;
char opus_file_name[128]; // Opus文件名
char pcm_file_name[128]; // 解码后的PCM文件名
sprintf(opus_file_name,"record/%s.opus",record_file_name);
fin = fopen(opus_file_name, "rb");
if (fin == NULL) {
LOG_INFO("failed to open input file\n");
return EXIT_FAILURE;
}
sprintf(pcm_file_name,"record/%s.pcm",record_file_name);
fout = fopen(pcm_file_name, "wb");
if (fout == NULL) {
LOG_ERROR("failed to open output file: %s\n", strerror(errno));
goto open_pcm_audio_failed;
}
decoder = opus_decoder_create(WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, &err);
if (err < 0) {
LOG_ERROR("failed to create decoder: %s\n", opus_strerror(err));
goto create_decoder_failed;
}
while (1) {
int i;
unsigned char pcm_bytes[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * 2];
int frame_size;
/* Read a 16 bits/sample audio frame. */
nbBytes = fread(cbits, 1, s_decodeBitrate / WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS *
WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS, fin);
if (feof(fin))
break;
/* Decode the data. In this example, frame_size will be constant because
the encoder is using a constant frame size. However, that may not
be the case for all encoders, so the decoder must always check
the frame size returned. */
frame_size = opus_decode(decoder, cbits, nbBytes, out, WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE, 0);
if (frame_size < 0) {
LOG_ERROR("decoder failed: %s\n", opus_strerror(frame_size));
goto decode_data_failed;
}
LOG_DEBUG("decode data to file: %d\r\n", frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS);
/* Convert to little-endian ordering. */
for (i = 0; i < WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * frame_size; i++) {
pcm_bytes[2 * i] = out[i] & 0xFF;
pcm_bytes[2 * i + 1] = (out[i] >> 8) & 0xFF;
}
/* Write the decoded audio to file. */
fwrite(pcm_bytes, sizeof(short), frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, fout);
}
LOG_INFO("Decode Finished...\n");
s_isDecodeFinished = true;
decode_data_failed:
opus_decoder_destroy(decoder);
create_decoder_failed:
fclose(fout);
open_pcm_audio_failed:
fclose(fin);
return UAV_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}