1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <hal_timer.h>
41 #include <aw-alsa-lib/pcm.h>
42 #include <aw-alsa-lib/control.h>
43
44 #include "common.h"
45 #include "wav_parser.h"
46
47 #undef DUPLEX_FS_WAV
48
49 static char *g_pcm_name = "default";
50
51 struct duplex_priv {
52 rt_mutex_t xMutex;
53 audio_mgr_t *playback_mgr;
54 audio_mgr_t *capture_mgr;
55 char *input_name;
56 char *output_name;
57 };
58
pcm_read(snd_pcm_t * handle,char * data,snd_pcm_uframes_t frames_total,unsigned int frame_bytes)59 static int pcm_read(snd_pcm_t *handle, char *data,
60 snd_pcm_uframes_t frames_total, unsigned int frame_bytes)
61 {
62 int ret = 0;
63 snd_pcm_sframes_t size;
64 snd_pcm_uframes_t frames_loop = 400;
65 snd_pcm_uframes_t frames_count = 0;
66 snd_pcm_uframes_t frames = 0;
67 unsigned int offset = 0;
68
69 while (1) {
70 if ((frames_total - frames_count) < frames_loop)
71 frames = frames_total - frames_count;
72 if (frames == 0)
73 frames = frames_loop;
74 /*hal_usleep(500000);*/
75 /*printf("snd_pcm_readi %ld frames\n", frames);*/
76 size = snd_pcm_readi(handle, (void *)(data + offset), frames);
77 if (size < 0)
78 printf("snd_pcm_readi return %ld\n", size);
79 if (size == -EAGAIN) {
80 /* retry */
81 hal_usleep(10000);
82 continue;
83 } else if (size == -EPIPE) {
84 xrun(handle);
85 continue;
86 } else if (size == -ESTRPIPE) {
87
88 continue;
89 } else if (size < 0) {
90 printf("-----snd_pcm_readi failed!!, return %ld\n", size);
91 ret = (int)size;
92 goto err;
93 }
94 offset += (size * frame_bytes);
95 frames_count += size;
96 frames -= size;
97 if (frames_total == frames_count)
98 break;
99 /*printf("frames_count = %ld, frames_total = %ld\n", frames_count, frames_total);*/
100 }
101 err:
102 return frames_count > 0 ? frames_count : ret;
103 }
104
pcm_write(snd_pcm_t * handle,const char * data,snd_pcm_uframes_t frames_total,unsigned int frame_bytes)105 static int pcm_write(snd_pcm_t *handle, const char *data,
106 snd_pcm_uframes_t frames_total, unsigned int frame_bytes)
107 {
108 int ret = 0;
109 snd_pcm_sframes_t size;
110 snd_pcm_uframes_t frames_loop = 400;
111 snd_pcm_uframes_t frames_count = 0;
112 snd_pcm_uframes_t frames = 0;
113
114 while (1) {
115 if ((frames_total - frames_count) < frames_loop)
116 frames = frames_total - frames_count;
117 if (frames == 0)
118 frames = frames_loop;
119 /*hal_usleep(500000);*/
120 size = snd_pcm_writei(handle, data, frames);
121 if (size != frames) {
122 printf("snd_pcm_writei return %ld\n", size);
123 }
124 if (size == -EAGAIN) {
125 hal_usleep(10000);
126 continue;
127 } else if (size == -EPIPE) {
128 xrun(handle);
129 continue;
130 } else if (size == -ESTRPIPE) {
131
132 continue;
133 } else if (size < 0) {
134 printf("-----snd_pcm_writei failed!!, return %ld\n", size);
135 return size;
136 }
137 data += (size * frame_bytes);
138 frames_count += size;
139 frames -= size;
140 if (frames_total == frames_count)
141 break;
142 /*printf("frames_count = %ld, frames_total = %ld\n", frames_count, frames_total);*/
143 }
144
145 return frames_count;
146 }
147
playback_fs_wav(audio_mgr_t * mgr,const char * pcm_name,const char * path)148 static int playback_fs_wav(audio_mgr_t *mgr, const char *pcm_name, const char *path)
149 {
150 int ret = 0;
151 int fd = 0;
152 wav_header_t wav_header;
153 wav_hw_params_t wav_hwparams = {16000, SND_PCM_FORMAT_UNKNOWN, 2};
154 unsigned int c;
155 unsigned int written = 0;
156 unsigned int count;
157 unsigned int chunk_bytes;
158 unsigned int frame_bytes = 0;
159 ssize_t r = 0;
160 char *audiobuf = NULL;
161
162 if (path == NULL) {
163 printf("[%s] path is null.\n", __func__);
164 return -1;
165 }
166
167 fd = open(path, O_RDONLY);
168 if (fd < 0) {
169 printf("no such wav file\n");
170 ret = -1;
171 goto err_fd_open;
172 }
173 r = read(fd, &wav_header, sizeof(wav_header_t));
174 if (r != sizeof(wav_header_t)) {
175 printf("read wav file header failed, return %ld\n", (long int)r);
176 goto err_fread_wav_header;
177 }
178
179 if (check_wav_header(&wav_header, &wav_hwparams) != 0) {
180 printf("check wav header failed\n");
181 goto err_checkout_wav_header;
182 }
183 count = wav_header.dataSize;
184 if (count == 0) {
185 printf("wav data siez is %d.\n", count);
186 goto err_checkout_wav_datasize;
187 }
188
189 /* open card */
190 ret = snd_pcm_open(&mgr->handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
191 if (ret < 0) {
192 printf("audio open error:%d\n", ret);
193 goto err_pcm_open;
194 }
195 mgr->format = wav_hwparams.format;
196 mgr->rate = wav_hwparams.rate;
197 mgr->channels = wav_hwparams.channels;
198
199 ret = set_param(mgr->handle, mgr->format, mgr->rate, mgr->channels,
200 mgr->period_size, mgr->buffer_size);
201 if (ret < 0) {
202 printf("audio set param error:%d\n", ret);
203 goto err_set_param;
204 }
205
206 frame_bytes = snd_pcm_frames_to_bytes(mgr->handle, 1);
207 chunk_bytes = snd_pcm_frames_to_bytes(mgr->handle, mgr->period_size);
208
209 audiobuf = malloc(chunk_bytes);
210 if (!audiobuf) {
211 printf("no memory...\n");
212 goto err_malloc;
213 }
214 while (written < count) {
215 c = count - written;
216 if (c > chunk_bytes)
217 c = chunk_bytes;
218 r = read(fd, audiobuf, c);
219 if (r < 0 || r != c) {
220 printf("read file error, r=%ld,c=%u\n", (long int)r, c);
221 break;
222 }
223 r = pcm_write(mgr->handle, audiobuf, r/frame_bytes, frame_bytes);
224 if (r != c/frame_bytes)
225 break;
226 written += c;
227 }
228 snd_pcm_drain(mgr->handle);
229
230 free(audiobuf);
231
232 err_malloc:
233 err_set_param:
234 /* close card */
235 if (mgr->handle != NULL)
236 snd_pcm_close(mgr->handle);
237 err_pcm_open:
238 err_checkout_wav_datasize:
239 err_checkout_wav_header:
240 err_fread_wav_header:
241 close(fd);
242 err_fd_open:
243 return ret;
244 }
245
capture_fs_wav(audio_mgr_t * mgr,const char * pcm_name,const char * path)246 static int capture_fs_wav(audio_mgr_t *mgr, const char *pcm_name, const char *path)
247 {
248 unsigned int len = 0;
249 int ret = 0;
250 int fd = 0;
251 wav_header_t header;
252 unsigned int written = 0;
253 long rest = -1, c = 0;
254 char *audiobuf = NULL;
255 unsigned int chunk_bytes;
256 unsigned int frame_bytes = 0;
257 struct stat statbuf;
258
259 if (path == NULL)
260 return -1;
261
262 /* open card */
263 ret = snd_pcm_open(&mgr->handle, pcm_name, SND_PCM_STREAM_CAPTURE, 0);
264 if (ret < 0) {
265 printf("audio open error:%d\n", ret);
266 return -1;
267 }
268
269 ret = set_param(mgr->handle, mgr->format, mgr->rate, mgr->channels,
270 mgr->period_size, mgr->buffer_size);
271 if (ret < 0)
272 goto err;
273
274 frame_bytes = snd_pcm_frames_to_bytes(mgr->handle, 1);
275 chunk_bytes = snd_pcm_frames_to_bytes(mgr->handle, mgr->period_size);
276 if (mgr->capture_duration > 0)
277 rest = mgr->capture_duration * snd_pcm_frames_to_bytes(mgr->handle, mgr->rate);
278
279 create_wav(&header, mgr->format, mgr->rate, mgr->channels);
280 if (!stat(path, &statbuf)) {
281 if (S_ISREG(statbuf.st_mode))
282 remove(path);
283 }
284 fd = open(path, O_RDWR | O_CREAT, 0644);
285 if (fd < 0) {
286 printf("create wav file failed\n");
287 goto err;
288 }
289 write(fd, &header, sizeof(header));
290
291 audiobuf = malloc(chunk_bytes);
292 if (!audiobuf) {
293 printf("no memory...\n");
294 goto err;
295 }
296 char *temp_wav_file = NULL;
297 unsigned int temp_wav_file_off = 0;
298 if (rest < 0) {
299 printf("please set capture duration..\n");
300 goto err;
301 }
302 temp_wav_file = malloc(rest);
303 if (!temp_wav_file) {
304 printf("no memory for temp_wav_file\n");
305 goto err;
306 }
307 while (rest > 0 && !mgr->in_aborting) {
308 int f = mgr->period_size;
309 if (rest <= chunk_bytes)
310 c = rest;
311 else
312 c = chunk_bytes;
313 f = pcm_read(mgr->handle, audiobuf, f, frame_bytes);
314 if (f < 0) {
315 printf("pcm read error, return %d\n", f);
316 break;
317 }
318 memcpy(temp_wav_file + temp_wav_file_off, audiobuf, c);
319 temp_wav_file_off += c;
320 if (rest > 0)
321 rest -= c;
322 written += c;
323 }
324
325 ret = snd_pcm_drain(mgr->handle);
326 if (ret < 0)
327 printf("stop failed!, return %d\n", ret);
328
329 err:
330 /* close card */
331 ret = snd_pcm_close(mgr->handle);
332 if (ret < 0) {
333 printf("audio close error:%d\n", ret);
334 return ret;
335 }
336
337 printf("please wait...writing data(%u bytes) into %s\n", temp_wav_file_off, path);
338 ret = write(fd, temp_wav_file, temp_wav_file_off);
339 if (ret != temp_wav_file_off) {
340 printf("write temp_wav_file failed. ret:%d, wav_file_off:%d\n",
341 ret, temp_wav_file_off);
342 goto err1;
343 }
344 printf("write finish...\n");
345 resize_wav(&header, written);
346 lseek(fd, 0, SEEK_SET);
347 write(fd, &header, sizeof(header));
348
349 err1:
350 if (temp_wav_file)
351 free(temp_wav_file);
352
353 if (fd > 0)
354 close(fd);
355 if (audiobuf)
356 free(audiobuf);
357 return ret;
358 }
359
360 /*
361 * arg0: arecord
362 * arg1: card
363 * arg2: format
364 * arg3: rate
365 * arg4: channels
366 * arg5: data
367 * arg6: len
368 */
arecord(const char * card_name,snd_pcm_format_t format,unsigned int rate,unsigned int channels,void * data,unsigned int datalen)369 static int arecord(const char *card_name, snd_pcm_format_t format, unsigned int rate,
370 unsigned int channels, void *data, unsigned int datalen)
371 {
372 int ret = 0;
373 snd_pcm_t *handle;
374 int mode = 0;
375 snd_pcm_hw_params_t *params;
376 snd_pcm_sw_params_t *sw_params;
377 snd_pcm_uframes_t period_frames = 1024, buffer_frames = 4096;
378
379 printf("arecord dump args:\n");
380 printf("card: %s\n", card_name);
381 printf("format: %u\n", format);
382 printf("rate: %u\n", rate);
383 printf("channels: %u\n", channels);
384 printf("data: %p\n", data);
385 printf("datalen: %u\n", datalen);
386
387 /* open card */
388 ret = snd_pcm_open(&handle, card_name, SND_PCM_STREAM_CAPTURE, mode);
389 if (ret < 0) {
390 printf("audio open error:%d\n", ret);
391 return -1;
392 }
393
394 ret = set_param(handle, format, rate, channels, period_frames, buffer_frames);
395 if (ret < 0) {
396 printf("set param failed!, return %d\n", ret);
397 goto err_set_param;
398 }
399 printf("pcm_read start...\n");
400 ret = pcm_read(handle, data, snd_pcm_bytes_to_frames(handle, datalen),
401 snd_pcm_frames_to_bytes(handle, 1));
402 if (ret < 0) {
403 printf("capture error:%d\n", ret);
404 goto err_pcm_read;
405 }
406
407 err_pcm_read:
408 ret = snd_pcm_drain(handle);
409 if (ret < 0)
410 printf("stop failed!, return %d\n", ret);
411
412 err_set_param:
413 /* close card */
414 ret = snd_pcm_close(handle);
415 if (ret < 0)
416 printf("audio close error:%d\n", ret);
417
418 return ret;
419 }
420
421 /*
422 * arg0: aplay
423 * arg1: card
424 * arg2: format
425 * arg3: rate
426 * arg4: channels
427 * arg5: data
428 * arg6: len
429 */
aplay(const char * card_name,snd_pcm_format_t format,unsigned int rate,unsigned int channels,const char * data,unsigned int datalen)430 static int aplay(const char *card_name, snd_pcm_format_t format, unsigned int rate,
431 unsigned int channels, const char *data, unsigned int datalen)
432 {
433 int ret = 0;
434 snd_pcm_t *handle;
435 int mode = 0;
436 snd_pcm_uframes_t period_frames = 1024, buffer_frames = 4096;
437
438 printf("aplay dump args:\n");
439 printf("card: %s\n", card_name);
440 printf("format: %u\n", format);
441 printf("rate: %u\n", rate);
442 printf("channels: %u\n", channels);
443 printf("data: %p\n", data);
444 printf("datalen: %u\n", datalen);
445 printf("period_size: %lu\n", period_frames);
446 printf("buffer_size: %lu\n", buffer_frames);
447
448 /* open card */
449 ret = snd_pcm_open(&handle, card_name, SND_PCM_STREAM_PLAYBACK, mode);
450 if (ret < 0) {
451 printf("audio open error:%d\n", ret);
452 return -1;
453 }
454
455 ret = set_param(handle, format, rate, channels, period_frames, buffer_frames);
456 if (ret < 0) {
457 goto err_set_param;
458 }
459
460 ret = pcm_write(handle, (char *)data,
461 snd_pcm_bytes_to_frames(handle, datalen),
462 snd_pcm_frames_to_bytes(handle, 1));
463 if (ret < 0) {
464 printf("pcm_write error:%d\n", ret);
465 goto err_pcm_write;
466 }
467
468 err_pcm_write:
469 ret = snd_pcm_drain(handle);
470 /*ret = snd_pcm_drop(handle);*/
471 if (ret < 0)
472 printf("stop failed!, return %d\n", ret);
473
474 err_set_param:
475 /* close card */
476 ret = snd_pcm_close(handle);
477 if (ret < 0)
478 printf("audio close error:%d\n", ret);
479
480 return ret;
481 }
482
capture_then_play(audio_mgr_t * audio_mgr)483 static int capture_then_play(audio_mgr_t *audio_mgr)
484 {
485 char *capture_data = NULL;
486 unsigned int len = 0;
487
488 if (audio_mgr->capture_duration == 0)
489 audio_mgr->capture_duration = 3;
490
491 len = snd_pcm_format_size(audio_mgr->format,
492 audio_mgr->capture_duration * audio_mgr->rate *
493 audio_mgr->channels);
494 capture_data = malloc(len);
495 if (!capture_data) {
496 printf("no memory\n");
497 return -1;
498 }
499 memset(capture_data, 0, len);
500
501 printf("arecord start...\n");
502 arecord(g_pcm_name, audio_mgr->format, audio_mgr->rate,
503 audio_mgr->channels, capture_data, len);
504 printf("aplay start...\n");
505 /*snd_ctl_set("audiocodec", "LINEOUT volume", 0x1f);*/
506 aplay("hw:audiocodec", audio_mgr->format, audio_mgr->rate,
507 audio_mgr->channels, capture_data, len);
508
509 free(capture_data);
510 capture_data = NULL;
511 return 0;
512 }
513
arecord_entry(void * arg)514 static void arecord_entry(void * arg)
515 {
516 int ret = 0;
517 struct duplex_priv * duplex_priv = arg;
518 const uint32_t timeout = 1 * 1000;
519
520 ret = rt_mutex_take(duplex_priv->xMutex, timeout);
521 if (!ret) {
522 printf("[%s] semaphore take failed.\n", __func__);
523 // vTaskDelete(NULL);
524 return;
525 }
526 #ifdef DUPLEX_FS_WAV
527 ret = capture_fs_wav(duplex_priv->capture_mgr, g_pcm_name,
528 duplex_priv->input_name);
529 if (ret < 0)
530 printf("capture_fs_wav error:%d\n", ret);
531 #else
532 capture_then_play(duplex_priv->capture_mgr);
533 #endif
534 rt_mutex_release(duplex_priv->xMutex);
535
536 // vTaskDelete(NULL);
537 }
538
usage(void)539 static void usage(void)
540 {
541 printf("Usage: aduplex [option]\n");
542 printf("-D, pcm device name\n");
543 printf("-r, sample rate\n");
544 printf("-f, sample bits\n");
545 printf("-c, channels\n");
546 printf("-p, period size\n");
547 printf("-b, buffer size\n");
548 printf("-i, input file path\n");
549 printf("-o, output file path\n");
550 printf("-d, capture duration(second)\n");
551 printf("-h, for help\n");
552 printf("\n");
553 }
554
cmd_aduplex(int argc,char ** argv)555 int cmd_aduplex(int argc, char ** argv)
556 {
557 int i = 0;
558 int c;
559 int ret = 0;
560 unsigned int bits = 16;
561 const uint32_t timeout = 11 * 1000;
562 // int priority = configAPPLICATION_NORMAL_PRIORITY;
563 uint32_t thread_size = 4 * 1024;
564 struct duplex_priv duplex_priv;
565 // TaskHandle_t pxCreatedTask;
566 unsigned int buf_size;
567
568 g_pcm_name = "hw:snddaudio0";
569
570 duplex_priv.playback_mgr = audio_mgr_create();
571 if (!duplex_priv.playback_mgr) {
572 printf("playback_mgr malloc failed.\n");
573 return -1;
574 }
575
576 duplex_priv.capture_mgr = audio_mgr_create();
577 if (!duplex_priv.capture_mgr) {
578 printf("capture_mgr malloc failed.\n");
579 goto err_malloc_capture_mgr;
580 }
581
582 /* for init */
583 duplex_priv.capture_mgr->capture_duration = 5;
584 #ifdef DUPLEX_FS_WAV
585 duplex_priv.input_name = "/data/connect_success_rec.wav";
586 #endif
587 duplex_priv.output_name = "/data/connect_success.wav";
588
589 optind = 0;
590 while ((c = getopt(argc, argv, "i:o:D:r:f:c:p:b:d:h")) != -1) {
591 switch (c) {
592 case 'i':
593 duplex_priv.input_name = optarg;
594 break;
595 case 'o':
596 duplex_priv.output_name = optarg;
597 break;
598 case 'D':
599 g_pcm_name = optarg;
600 break;
601 case 'r':
602 duplex_priv.playback_mgr->rate = atoi(optarg);
603 duplex_priv.capture_mgr->rate = atoi(optarg);
604 break;
605 case 'f':
606 bits = atoi(optarg);
607 break;
608 case 'c':
609 duplex_priv.playback_mgr->channels = atoi(optarg);
610 duplex_priv.capture_mgr->channels = atoi(optarg);
611 break;
612 case 'p':
613 duplex_priv.playback_mgr->period_size = atoi(optarg);
614 duplex_priv.capture_mgr->period_size = atoi(optarg);
615 break;
616 case 'b':
617 duplex_priv.playback_mgr->buffer_size = atoi(optarg);
618 duplex_priv.capture_mgr->buffer_size = atoi(optarg);
619 break;
620 case 'd':
621 duplex_priv.capture_mgr->capture_duration = atoi(optarg);
622 break;
623 case 'h':
624 default:
625 usage();
626 goto err_cmd;
627 }
628 }
629
630 /* check params */
631 if (duplex_priv.capture_mgr->capture_duration > 10)
632 duplex_priv.capture_mgr->capture_duration = 10;
633 if (duplex_priv.capture_mgr->capture_duration <= 0)
634 duplex_priv.capture_mgr->capture_duration = 5;
635
636 if (duplex_priv.output_name == NULL) {
637 printf("output name is null.\n");
638 goto err_out_filename_null;
639 }
640
641 #ifdef DUPLEX_FS_WAV
642 if (duplex_priv.input_name == NULL) {
643 printf("input file name is null.\n");
644 goto err_in_filename_null;
645 }
646 #endif
647
648 switch (bits) {
649 case 16:
650 duplex_priv.playback_mgr->format = SND_PCM_FORMAT_S16_LE;
651 duplex_priv.capture_mgr->format = SND_PCM_FORMAT_S16_LE;
652 break;
653 case 24:
654 duplex_priv.playback_mgr->format = SND_PCM_FORMAT_S24_LE;
655 duplex_priv.capture_mgr->format = SND_PCM_FORMAT_S24_LE;
656 break;
657 case 32:
658 duplex_priv.playback_mgr->format = SND_PCM_FORMAT_S32_LE;
659 duplex_priv.capture_mgr->format = SND_PCM_FORMAT_S32_LE;
660 break;
661 default:
662 printf("%u bits not supprot\n", bits);
663 goto err_format;
664 }
665
666 duplex_priv.xMutex = rt_mutex_create("sound_mtx", RT_IPC_FLAG_PRIO);
667 if(duplex_priv.xMutex == RT_NULL) {
668 printf("mutex create failed.\n");
669 goto err_create_mutex;
670 }
671
672 // ret = xTaskCreate(arecord_entry, (signed portCHAR *) "arecord-thread",
673 // thread_size, &duplex_priv, priority, &pxCreatedTask);
674 // if (!ret) {
675 // printf("arecord-thread create failed.\n");
676 // goto err_create_arecord;
677 // }
678
679 playback_fs_wav(duplex_priv.playback_mgr, g_pcm_name, duplex_priv.output_name);
680 /* wait for capturing finished */
681 ret = rt_mutex_take(duplex_priv.xMutex, timeout);
682 if (!ret) {
683 printf("[%s] semaphore take failed.\n", __func__);
684 goto err_arecord_timeout;
685 }
686 rt_mutex_release(duplex_priv.xMutex);
687 rt_mutex_delete(duplex_priv.xMutex);
688
689 #ifdef DUPLEX_FS_WAV
690 /* after capture finished */
691 playback_fs_wav(duplex_priv.playback_mgr, "default", duplex_priv.input_name);
692 #endif
693
694 audio_mgr_release(duplex_priv.capture_mgr);
695 audio_mgr_release(duplex_priv.playback_mgr);
696 return 0;
697
698 err_arecord_timeout:
699 // vTaskDelete(pxCreatedTask);
700 err_create_arecord:
701 err_format:
702 err_create_mutex:
703 err_in_filename_null:
704 err_out_filename_null:
705 err_cmd:
706 audio_mgr_release(duplex_priv.capture_mgr);
707 err_malloc_capture_mgr:
708 audio_mgr_release(duplex_priv.playback_mgr);
709 return ret;
710 }
711 FINSH_FUNCTION_EXPORT_CMD(cmd_aduplex, aduplex, Playback and Record);
712