1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 #ifdef HAAS_AUDIO_DEMO
5 #include <posix/pthread.h>
6 #else
7 #include <pthread.h>
8 #endif
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include "sound_pcm.h"
14 #include "audio_drv.h"
15 #include "ulog/ulog.h"
16 
17 #define LOG_TAG  "[sound_example_lb]"
18 #define AUDIO_PLAYER_HIGH_STACKSIZE        8192
19 #define AUDIO_PLAYER_DEFAULT_PRIORITY      33
20 
21 static char *param = NULL;
22 static pthread_cond_t  g_play_cond;
23 static pthread_mutex_t  g_play_mutex;
24 static pthread_t g_play_thread;
25 static bool bCreateAudioThreadFlag = false;
26 
sound_loopback_thread(void * arg)27 static void sound_loopback_thread(void *arg)
28 {
29     aos_pcm_t *pb_pcm = NULL, *cap_pcm = NULL;
30     unsigned char * dataBuf = NULL;
31     unsigned int buf_size = 0;
32     //int freq = 22050, channels = 1;
33     int freq = 16000, channels = 1;
34     int ret = -1;
35 
36     LOGD(LOG_TAG, "%s:%d: sound_loopback_thread entry!!", __func__, __LINE__);
37     buf_size = freq * channels * 2 / 5;
38     dataBuf = (unsigned char *)malloc(buf_size);
39     if(!dataBuf) {
40         LOGE(LOG_TAG, "%s:%d: malloc %d failed. ", __func__, __LINE__, buf_size);
41         return 0;
42     }
43     while(1) {
44         if(!strcmp(param, "start")) {
45             if(!pb_pcm) {
46                 LOGD(LOG_TAG, "%s:%d: open capture & playback stream!!", __func__, __LINE__);
47                 /* open playback stream */
48                 ret = aos_pcm_open(&pb_pcm, "default", AOS_PCM_STREAM_PLAYBACK, 0);
49                 if(!ret) {
50                     aos_pcm_hw_params_alloca(&pb_pcm->hw_params);
51                     aos_pcm_sw_params_alloca(&pb_pcm->sw_params);
52                     aos_pcm_sw_params_any(pb_pcm->sw_params);
53                     aos_pcm_set_params(pb_pcm, AOSRV_PCM_FORMAT_S16_LE, AOS_PCM_ACCESS_RW_INTERLEAVED, channels, freq, 0, 0);
54                     aos_pcm_prepare(pb_pcm);
55                     aos_pcm_start(pb_pcm);
56                 } else {
57                     LOGE(LOG_TAG, "%s:%d: open playback stream failed. ", __func__, __LINE__);
58                 }
59             }
60             if(!cap_pcm) {
61                 /* open capture stream */
62                 ret = aos_pcm_open(&cap_pcm, "default", AOS_PCM_STREAM_CAPTURE, 0);
63                 if(!ret) {
64                     aos_pcm_hw_params_alloca(&cap_pcm->hw_params);
65                     aos_pcm_sw_params_alloca(&cap_pcm->sw_params);
66                     aos_pcm_sw_params_any(cap_pcm->sw_params);
67                     aos_pcm_set_params(cap_pcm, AOSRV_PCM_FORMAT_S16_LE, AOS_PCM_ACCESS_RW_INTERLEAVED, channels, freq, 0, 0);
68                     aos_pcm_prepare(cap_pcm);
69                     aos_pcm_start(cap_pcm);
70                 } else {
71                     LOGE(LOG_TAG, "%s:%d: open capture stream failed. ", __func__, __LINE__);
72                 }
73             }
74             ret = aos_pcm_readi(cap_pcm, dataBuf, aos_pcm_bytes_to_frames(cap_pcm, buf_size));
75             if(ret > 0) {
76                 //LOGD(LOG_TAG, "%s:%d: readi frames(%d) bytes(%d) successfully. ", __func__, __LINE__, ret, aos_pcm_frames_to_bytes(cap_pcm, ret));
77                 ret = aos_pcm_writei(pb_pcm, dataBuf, aos_pcm_bytes_to_frames(pb_pcm, aos_pcm_frames_to_bytes(cap_pcm, ret)));
78             }
79         } else {
80             if(pb_pcm) {
81                 LOGD(LOG_TAG, "%s:%d: close capture & playback stream!!", __func__, __LINE__);
82                 //aos_pcm_drain(pb_pcm);
83                 aos_pcm_stop(pb_pcm);
84                 aos_pcm_close(pb_pcm);
85                 pb_pcm = NULL;
86             }
87             if(cap_pcm) {
88                 aos_pcm_stop(cap_pcm);
89                 aos_pcm_close(cap_pcm);
90                 cap_pcm = NULL;
91             }
92             usleep(200*1000);
93         }
94     }
95 
96     return 0;
97 }
98 
sound_example_loopback_init(void)99 static void sound_example_loopback_init(void)
100 {
101     if(bCreateAudioThreadFlag) {
102         return;
103     }
104     LOGD(LOG_TAG, "%s:%d, -->>", __func__, __LINE__);
105 
106     pthread_attr_t attr;
107     struct sched_param sched;
108 
109     pthread_cond_init(&g_play_cond, NULL);
110     pthread_mutex_init(&g_play_mutex, NULL);
111 
112     pthread_attr_init(&attr);
113     pthread_attr_setstacksize(&attr, AUDIO_PLAYER_HIGH_STACKSIZE);
114     sched.sched_priority = AUDIO_PLAYER_DEFAULT_PRIORITY;
115     pthread_attr_setschedparam(&attr, &sched);
116 
117     pthread_create(&g_play_thread, &attr, sound_loopback_thread, NULL);
118     pthread_setname_np(g_play_thread, "soundplaythread");
119 
120     pthread_attr_destroy(&attr);
121     bCreateAudioThreadFlag = true;
122 }
123 
sound_example_loopback_entry(int argc,char ** argv)124 void sound_example_loopback_entry(int argc, char **argv)
125 {
126     if (argc < 2) {
127         LOGD(LOG_TAG, "%s:%d: Usage: %s start/stop ", __func__, __LINE__, argv[0]);
128         return;
129     }
130     param = strdup(argv[1]);
131     if(param && !strcmp(param, "start"))
132     {
133         printf("sound loopback test begin ...\r\n");
134     } else {
135         printf("sound loopback test end !!!\r\n");
136     }
137     sound_example_loopback_init();
138 }