blob: a43b1a4f449a44cdee19872f5b77863125d63d76 [file] [log] [blame]
yu.dong8e5f3262023-10-10 03:18:01 -07001#include <stdint.h>
2#include <stdio.h>
3#include <string.h>
4
5#include "liblog/lynq_deflog.h"
6
7#ifdef __cplusplus
8extern "C" {
9#endif
10
11#include "sc_audio.h"
12#include "lynq-qser-audio.h"
13
14#define AUDIO_INIT_MAX_TRY_CNT 100
15
16#define SC_AUDIO_BE_DAI_MIN -1
17#define SC_AUDIO_STREAM_FORMAT_INVALID 0
18
yu.dong72202352023-12-01 00:42:47 -080019sc_audio_handle_t playback_handle = SC_AUDIO_INVALID_HANDLE;
20sc_audio_handle_t capture_handle = SC_AUDIO_INVALID_HANDLE;
21
yu.dong8e5f3262023-10-10 03:18:01 -070022/********************************************************************
23* @brief: _cb_onPlayer, typedef for a callback function that is called
24 when an audio operation is performed
25* @param int [IN]: The result of the audio operation, 0 if successful, non-zero if failed
26* @return : void
27* @todo: NA
28* @see: NA
29* @warning: NA
30*********************************************************************/
31typedef void (*_cb_onPlayer)(int);
32
33/********************************************************************
34* @brief: playback_state_cb, callback function that is called when the audio playback state changes
35* @param handle [IN]: sc_audio_handle_t, the handle of the audio device
36* @param params [IN]: void*, parameters for the callback function
37* @param state [IN]: sc_audio_playback_state_e, the current state of audio playback
38* @return : int, 0 if successful, non-zero if failed
39* @todo: NA
40* @see: NA
41* @warning: NA
42*********************************************************************/
43int playback_state_cb (sc_audio_handle_t handle, void *params, sc_audio_playback_state_e state)
44{
45 LYINFLOG("playback_state_cb handle:0x%lx state:%d\n", handle, state);
46 return 0;
47}
48
49/********************************************************************
50* @brief: capture_state_cb, callback function that is called when the audio capture state changes
51* @param handle [IN]: sc_audio_handle_t, the handle of the audio device
52* @param params [IN]: void*, parameters for the callback function
53* @param state [IN]: sc_audio_capture_state_e, the current state of audio capture
54* @return : int, 0 if successful, non-zero if failed
55* @todo: NA
56* @see: NA
57* @warning: NA
58*********************************************************************/
59int capture_state_cb (sc_audio_handle_t handle, void *params, sc_audio_capture_state_e state)
60{
61 LYINFLOG("capture_state_cb handle:0x%lx state:%d\n", handle, state);
62
63 return 0;
64}
65
66/********************************************************************
67* @brief: get_device_enum, function to convert a device string to its corresponding enum
68* @param device [IN]: const char*, the name of the device
69* @return : sc_audio_fe_pcm_dev_e, the enum corresponding to the device name
70* @todo: NA
71* @see: NA
72* @warning: NA
73*********************************************************************/
74sc_audio_fe_pcm_dev_e get_device_enum(const char* device)
75{
76 if (strcmp(device, "device1") == 0)
77 {
78 return SC_AUDIO_FE_PCM_DEV_MULTIMEDIA1;
79 }
80 else if (strcmp(device, "device2") == 0)
81 {
82 return SC_AUDIO_FE_PCM_DEV_MULTIMEDIA2;
83 }
84 else
85 {
86 return SC_AUDIO_INVALID_HANDLE;
87 }
88}
89
90/********************************************************************
91* @brief: qser_AudPlayer_Open, open the audio device for playback
92* @param device [IN]: char* device, the audio device to be opened for playback
93* @param cb_fun [IN]: _cb_onPlayer, callback function to be called when the audio device is opened
94* @return : int, 0 if successful, non-zero if failed
95* @todo: NA
96* @see: NA
97* @warning: NA
98*********************************************************************/
99int qser_AudPlayer_Open(char* device, _cb_onPlayer cb_fun)
100{
101 int ret = SC_ERR_SUCCESS;
102 int retry_cnt = 0;
103 int audio_is_init = 0;
104
105 sc_audio_fe_pcm_dev_e device_enum = get_device_enum(device); // Convert device string to enum
106
107 while (AUDIO_INIT_MAX_TRY_CNT > retry_cnt)
108 {
109 ret = sc_audio_init();
110 if (SC_ERR_NOT_READY == ret)
111 {
112 LYINFLOG("audio service is not ready, try again, try count = %d\n", (retry_cnt + 1));
113 usleep(200 * 1000);
114 retry_cnt++;
115 }
116 else if (SC_ERR_SUCCESS == ret)
117 {
118 LYINFLOG("Success to initialize audio service\n");
119 audio_is_init = 1;
120 break;
121 }
122 else
123 {
124 LYINFLOG("Failed to initialize audio service, ret = %d\n", ret);
125 break;
126 }
127 }
128 if (1 != audio_is_init)
129 {
130 LYINFLOG("Failed to initialize audio service\n");
131 if (cb_fun != NULL)
132 {
133 cb_fun(-1);
134 }
135 return -1;
136 }
137
138 sc_audio_handle_t device_handle = sc_audio_playback_open(device_enum, SC_AUDIO_FE_PCM_DEV_MIN, SC_AUDIO_OWNER_ID_PLAYER);
139 if (SC_AUDIO_INVALID_HANDLE == device_handle)
140 {
141 LYINFLOG("Failed to open device: %s\n", device);
142 if (cb_fun != NULL)
143 {
144 cb_fun(-1);
145 }
146 return -1;
147 }
148
149 if (cb_fun != NULL)
150 {
151 cb_fun(0);
152 }
153 return 0;
154}
155
156/********************************************************************
157* @brief: qser_AudPlayer_PlayFrmFile, play audio from file
158* @param hdl [IN]: int, handle for the audio device or stream
159* @param fd [IN]: const char*, file descriptor of the audio file
160* @param offset [IN]: int, offset in the audio file
161* @return : success 0, failed -1
162* @todo: NA
163* @see: NA
164* @warning: NA
165*********************************************************************/
166int qser_AudPlayer_PlayFrmFile(int hdl, const char *fd, int offset)
167{
168 int error_line;
169 sc_audio_pcm_config_t pcm_config;
170 int ret = 0;
171 sc_audio_owner_id owner_id = hdl;
172
173 if(NULL== fd || 0 == strlen(fd))
174 {
175 error_line = __LINE__;
176 goto exit;
177 }
178
179 playback_handle = sc_audio_playback_open(SC_AUDIO_FE_PCM_DEV_MULTIMEDIA2,SC_AUDIO_FE_PCM_DEV_MIN,owner_id);
180 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
181 {
182 error_line = __LINE__;
183 goto exit;
184 }
185
186 if(strlen(fd))
187 {
188 ret = sc_audio_playback_file_prepare(playback_handle, fd, NULL, playback_state_cb, NULL);
189 if (SC_ERR_SUCCESS != ret)
190 {
191 error_line = __LINE__;
192 goto exit;
193 }
194 }
195
196 ret = sc_audio_playback_play(playback_handle);
197 if (SC_ERR_SUCCESS != ret)
198 {
199 error_line = __LINE__;
200 goto exit;
201 }
202
203 return 0;
204exit:
205 LYINFLOG("qser_AudPlayer_PlayFrmFile error_line=%d\n",error_line);
206 return -1;
207}
208
209/********************************************************************
yu.dongfd5dc142023-12-21 03:56:19 -0800210* @brief: qser_AudPlayer_Play_Pcmbuf, play audio from PCM buffer
211* @param period_size [IN]: int, size of the period for the PCM buffer, use default value if -1
212* @param period_count [IN]: int, count of the period for the PCM buffer, use default value if -1
213* @param num_channels [IN]: int, number of audio channels, use default value if -1
214* @param sample_rate [IN]: int, sample rate for the audio, use default value if -1
215* @param ownerid [IN]: int, ID of the audio owner, use default value if not in valid range
216* @return : success 0, failed -1
217* @todo: NA
218* @see: NA
219* @warning: NA
220*********************************************************************/
221int qser_AudPlayer_PlayPcmBuf(const unsigned char *pcm_data, int data_size, int period_size, \
222 int period_count, int num_channels, int sample_rate, int ownerid)
223{
224 if (pcm_data == NULL)
225 {
226 LYINFLOG("Error: pcm_data parameter is a null pointer \n");
227 return -1;
228 }
229
230 int error_line;
231 int audio_is_init = 0;
232
233 sc_audio_pcm_config_t pcm_config;
234 int ret = 0;
235 sc_audio_owner_id owner_id;
236
237 if(ownerid <= SC_AUDIO_OWNER_ID_NONE || ownerid >= SC_AUDIO_OWNER_ID_MAX)
238 {
239 owner_id = SC_AUDIO_OWNER_ID_PLAYER;
240 } else
241 {
242 owner_id = ownerid;
243 }
244
245 playback_handle = sc_audio_playback_open(SC_AUDIO_FE_PCM_DEV_MULTIMEDIA2,SC_AUDIO_FE_PCM_DEV_MIN, owner_id);
246 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
247 {
248 error_line = __LINE__;
249 goto exit;
250 }
251
252 if(-1 == period_size || -1 == period_count || -1 == num_channels || -1 == sample_rate)
253 {
254 ret = sc_audio_playback_stream_prepare(playback_handle, NULL, playback_state_cb, NULL);
255 } else
256 {
257 pcm_config.period_size = period_size;
258 pcm_config.period_count = period_count;
259 pcm_config.flags = 0;
260 pcm_config.num_channels = num_channels;
261 pcm_config.sample_rate = sample_rate;
262 pcm_config.pcm_format = 2;
263
264 ret = sc_audio_playback_stream_prepare(playback_handle, &pcm_config, playback_state_cb, NULL);
265 }
266
267 if (SC_ERR_SUCCESS != ret)
268 {
269 error_line = __LINE__;
270 goto exit;
271 }
272
273 ret = sc_audio_playback_push_stream(playback_handle, (void *)pcm_data, data_size);
274 if (SC_ERR_SUCCESS != ret)
275 {
276 error_line = __LINE__;
277 goto exit;
278 }
279
280 ret = sc_audio_playback_play(playback_handle);
281 if (SC_ERR_SUCCESS != ret)
282 {
283 error_line = __LINE__;
284 goto exit;
285 }
286
287 return 0;
288
289exit:
290 if (SC_AUDIO_INVALID_HANDLE != playback_handle)
291 {
292 sc_audio_playback_close(playback_handle);
293 }
294
295 LYINFLOG("player_playback_play_pcmbuf error_line=%d\n",error_line);
296 return -1;
297}
298
299/********************************************************************
yu.dong72202352023-12-01 00:42:47 -0800300* @brief: qser_AudRecorder_StartRecord_Custom, used to capture audio from a file and play it
301* @param file [IN]: char*, the path of the audio file
302* @param period_size [IN]: int, the period size of the PCM buffer
303* @param period_count [IN]: int, the period count of the PCM buffer
304* @param num_channels [IN]: int, the number of channels in the audio
305* @param sample_rate [IN]: int, the sample rate of the audio
306* @return : int, returns 0 if successful, returns -1 if failed
307* @todo: NA
308* @see: NA
309* @warning: NA
310*********************************************************************/
311int qser_AudRecorder_StartRecord_Custom(char *file, int period_size, int period_count, \
312 int num_channels, int sample_rate)
313{
314 int error_line;
315 sc_audio_pcm_config_t pcm_config;
316 int ret = 0;
317
318 if(NULL == file || 0 == strlen(file))
319 {
320 error_line = __LINE__;
321 goto exit;
322 }
323
324 capture_handle = sc_audio_capture_open(SC_AUDIO_FE_PCM_DEV_MULTIMEDIA1, SC_AUDIO_BE_DAI_MIN);
325
326 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
327 {
328 error_line = __LINE__;
329 goto exit;
330 }
331
332 memset(&pcm_config, 0, sizeof(sc_audio_pcm_config_t));
333
334 if(-1 == period_size || -1 == period_count || -1 == num_channels || -1 == sample_rate)
335 {
336 ret = sc_audio_capture_file_prepare(capture_handle, file, SC_AUDIO_STREAM_FORMAT_INVALID, \
337 NULL, capture_state_cb, NULL);
338 }
339 else
340 {
341 pcm_config.period_size = period_size;
342 pcm_config.period_count = period_count;
343 pcm_config.flags = 0;
344 pcm_config.num_channels = num_channels;
345 pcm_config.sample_rate = sample_rate;
346 pcm_config.pcm_format = 2;
347 ret = sc_audio_capture_file_prepare(capture_handle, file, SC_AUDIO_STREAM_FORMAT_INVALID, \
348 &pcm_config, capture_state_cb, NULL);
349 }
350
351 if (SC_ERR_SUCCESS != ret)
352 {
353 error_line = __LINE__;
354 goto exit;
355 }
356
357 ret = sc_audio_capture_record(capture_handle);
358
359 if (SC_ERR_SUCCESS != ret)
360 {
361 error_line = __LINE__;
362 goto exit;
363 }
364
365 return 0;
366
367exit:
368 if (SC_AUDIO_INVALID_HANDLE != capture_handle)
369 {
370 sc_audio_capture_close(capture_handle);
371 }
372 LYINFLOG("player_capture_play_file error_line=%d\n", error_line);
373 return -1;
374}
375
376/********************************************************************
yu.dong8e5f3262023-10-10 03:18:01 -0700377* @brief: qser_AudPlayer_Pause, pause the audio playback
378* @param hdl [IN]: int, handle for the audio device or stream
379* @return : success 0, failed -1
380* @todo: NA
381* @see: NA
382* @warning: NA
383*********************************************************************/
384int qser_AudPlayer_Pause(int hdl)
385{
386 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
387 {
388 LYINFLOG("qser_AudPlayer_Pause handle is invalid.\n");
389 return -1;
390 }
391 if( sc_audio_playback_pause(playback_handle))
392 {
393 LYINFLOG("qser_AudPlayer_Pause sc_audio_playback_pause fail.\n");
394 return -1;
395 }
396 return 0;
397}
398
399/********************************************************************
400* @brief: qser_AudPlayer_Resume, resume the audio playback
401* @param hdl [IN]: int, handle for the audio device or stream
402* @return : success 0, failed -1
403* @todo: NA
404* @see: NA
405* @warning: NA
406*********************************************************************/
407int qser_AudPlayer_Resume(int hdl)
408{
409 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
410 {
411 LYINFLOG("qser_AudPlayer_Resume handle is invalid.\n");
412 return -1;
413 }
414 if( sc_audio_playback_resume(playback_handle))
415 {
416 LYINFLOG("qser_AudPlayer_Resume sc_audio_playback_resume fail.\n");
417 return -1;
418 }
419 return 0;
420}
421
422/********************************************************************
423* @brief: qser_AudPlayer_Stop, stop the audio playback
424* @param hdl [IN]: int, handle for the audio device or stream
425* @return : void
426* @todo: NA
427* @see: NA
428* @warning: NA
429*********************************************************************/
430void qser_AudPlayer_Stop(int hdl)
431{
432 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
433 {
434 LYINFLOG("qser_AudPlayer_Stop handle is invalid.\n");
435 return;
436 }
437
438 if( sc_audio_playback_stop(playback_handle))
439 {
440 LYINFLOG("qser_AudPlayer_Stop sc_audio_playback_stop fail.\n");
441 return;
442 }
443}
444
445/********************************************************************
446* @brief: qser_AudPlayer_Close, close the audio playback
447* @param hdl [IN]: int, handle for the audio device or stream
448* @return : void
449* @todo: NA
450* @see: NA
451* @warning: NA
452*********************************************************************/
453void qser_AudPlayer_Close(int hdl)
454{
455 if (SC_AUDIO_INVALID_HANDLE == playback_handle)
456 {
457 LYINFLOG("qser_AudPlayer_Close handle is invalid.\n");
458 return;
459 }
460 if( sc_audio_playback_stop(playback_handle))
461 {
462 LYINFLOG("qser_AudPlayer_Close sc_audio_playback_stop fail.\n");
463 return;
464 }
465 if( sc_audio_playback_close(playback_handle))
466 {
467 LYINFLOG("qser_AudPlayer_Close sc_audio_playback_close fail.\n");
468 return;
469 }
470
471 playback_handle = SC_AUDIO_INVALID_HANDLE;
472}
473
474/********************************************************************
475* @brief: qser_AudRecorder_Open, open the audio device for recording
476* @param device [IN]: char* device, the audio device to be opened for recording
477* @param cb_fun [IN]: _cb_onPlayer, callback function to be called when the audio device is opened
478* @return : int, 0 if successful, non-zero if failed
479* @todo: NA
480* @see: NA
481* @warning: NA
482*********************************************************************/
483int qser_AudRecorder_Open(char* device, _cb_onPlayer cb_fun)
484{
485 int ret = SC_ERR_SUCCESS;
486 int retry_cnt = 0;
487 int audio_is_init = 0;
488
489 sc_audio_fe_pcm_dev_e device_enum = get_device_enum(device); // Convert device string to enum
490
491 while (AUDIO_INIT_MAX_TRY_CNT > retry_cnt)
492 {
493 ret = sc_audio_init();
494 if (SC_ERR_NOT_READY == ret)
495 {
496 LYINFLOG("audio service is not ready, try again, try count = %d\n", (retry_cnt + 1));
497 usleep(200 * 1000);
498 retry_cnt++;
499 }
500 else if (SC_ERR_SUCCESS == ret)
501 {
502 LYINFLOG("Success to initialize audio service\n");
503 audio_is_init = 1;
504 break;
505 }
506 else
507 {
508 LYINFLOG("Failed to initialize audio service, ret = %d\n", ret);
509 break;
510 }
511 }
512 if (1 != audio_is_init)
513 {
514 LYINFLOG("Failed to initialize audio service\n");
515 if (cb_fun != NULL)
516 {
517 cb_fun(-1);
518 }
519 return -1;
520 }
521
522 sc_audio_handle_t device_handle = sc_audio_playback_open(device_enum, SC_AUDIO_FE_PCM_DEV_MIN, SC_AUDIO_OWNER_ID_PLAYER);
523 if (SC_AUDIO_INVALID_HANDLE == device_handle)
524 {
525 LYINFLOG("Failed to open device: %s\n", device);
526 if (cb_fun != NULL)
527 {
528 cb_fun(-1);
529 }
530 return -1;
531 }
532
533 if (cb_fun != NULL)
534 {
535 cb_fun(0);
536 }
537 return 0;
538}
539
540/********************************************************************
541* @brief: qser_AudRecorder_StartRecord, play a file with capture
542* @param hdl [IN]: int, handle for the audio device or stream
543* @param fd [IN]: const char*, file descriptor of the audio file
544* @param offset [IN]: int, offset in the audio file
545* @return : int, 0 if successful, -1 if failed
546* @todo: NA
547* @see: NA
548* @warning: NA
549*********************************************************************/
550int qser_AudRecorder_StartRecord(int hdl, const char *fd, int offset)
551{
552 int error_line;
553 sc_audio_pcm_config_t pcm_config;
554 int ret = 0;
555 sc_audio_owner_id owner_id = hdl;
556
557 if(NULL== fd || 0 == strlen(fd))
558 {
559 error_line = __LINE__;
560 goto exit;
561 }
562
563 capture_handle = sc_audio_capture_open(SC_AUDIO_FE_PCM_DEV_MULTIMEDIA1,SC_AUDIO_BE_DAI_MIN);
564 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
565 {
566 error_line = __LINE__;
567 goto exit;
568 }
569
570 memset(&pcm_config, 0, sizeof(sc_audio_pcm_config_t));
571
572 ret = sc_audio_capture_file_prepare(capture_handle, fd, SC_AUDIO_STREAM_FORMAT_INVALID, NULL, capture_state_cb, NULL);
573 if (SC_ERR_SUCCESS != ret)
574 {
575 error_line = __LINE__;
576 goto exit;
577 }
578
579 ret = sc_audio_capture_record(capture_handle);
580 if (SC_ERR_SUCCESS != ret)
581 {
582 error_line = __LINE__;
583 goto exit;
584 }
585
586 return 0;
587exit:
588 LYINFLOG("qser_AudRecorder_StartRecord error_line=%d\n",error_line);
589 return -1;
590}
591
592/********************************************************************
593* @brief: qser_AudRecorder_Pause, pause the audio capture
594* @return : int, 0 if successful, -1 if failed
595* @todo: NA
596* @see: NA
597* @warning: NA
598*********************************************************************/
599int qser_AudRecorder_Pause(void)
600{
601 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
602 {
603 LYINFLOG("qser_AudRecorder_Pause capture_handle is invalid.\n");
604 return -1;
605 }
606 if( sc_audio_capture_pause(capture_handle))
607 {
608 LYINFLOG("qser_AudRecorder_Pause sc_audio_capture_pause fail.\n");
609 return -1;
610 }
611 return 0;
612}
613
614/********************************************************************
615* @brief: qser_AudRecorder_Resume, resume the audio capture
616* @return : int, 0 if successful, -1 if failed
617* @todo: NA
618* @see: NA
619* @warning: NA
620*********************************************************************/
621int qser_AudRecorder_Resume(void)
622{
623 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
624 {
625 LYINFLOG("qser_AudRecorder_Resume capture_handle is invalid.\n");
626 return -1;
627 }
628 if( sc_audio_capture_resume(capture_handle))
629 {
630 LYINFLOG("qser_AudRecorder_Resume sc_audio_capture_resume fail.\n");
631 return -1;
632 }
633 return 0;
634}
635
636/********************************************************************
637* @brief: qser_AudRecorder_Stop, stop the audio capture
638* @return : void
639* @todo: NA
640* @see: NA
641* @warning: NA
642*********************************************************************/
643void qser_AudRecorder_Stop(void)
644{
645 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
646 {
647 LYINFLOG("qser_AudRecorder_Stop capture_handle is invalid.\n");
648 return;
649 }
650 if( sc_audio_capture_stop(capture_handle))
651 {
652 LYINFLOG("qser_AudRecorder_Stop sc_audio_capture_stop fail.\n");
653 return;
654 }
655}
656
657/********************************************************************
658* @brief: qser_AudRecorder_Close, close the audio capture
659* @return : void
660* @todo: NA
661* @see: NA
662* @warning: NA
663*********************************************************************/
664void qser_AudRecorder_Close(void)
665{
666 if (SC_AUDIO_INVALID_HANDLE == capture_handle)
667 {
668 LYINFLOG("qser_AudRecorder_Close capture_handle is invalid.\n");
669 return;
670 }
671 if( sc_audio_capture_stop(capture_handle))
672 {
673 LYINFLOG("qser_AudRecorder_Close sc_audio_capture_stop fail.\n");
674 return;
675 }
676 if( sc_audio_capture_close(capture_handle))
677 {
678 LYINFLOG("qser_AudRecorder_Close sc_audio_capture_close fail.\n");
679 return;
680 }
681
682 capture_handle = SC_AUDIO_INVALID_HANDLE;
683}
684
685/********************************************************************
686* @brief: qser_Audio_Deinit, deinitialize the audio system, stop and close any active playback or capture,
687 and uninitialize the audio system
688* @return : void
689* @todo: NA
690* @see: NA
691* @warning: NA
692*********************************************************************/
693void qser_Audio_Deinit(void)
694{
695 if(SC_AUDIO_INVALID_HANDLE != playback_handle)
696 {
697 sc_audio_playback_stop(playback_handle);
698 sc_audio_playback_close(playback_handle);
699 playback_handle = SC_AUDIO_INVALID_HANDLE;
700 }
701
702 if(SC_AUDIO_INVALID_HANDLE != capture_handle)
703 {
704 sc_audio_capture_stop(capture_handle);
705 sc_audio_capture_close(capture_handle);
706 capture_handle = SC_AUDIO_INVALID_HANDLE;
707 }
708
709 sc_audio_uninit();
710}
711
712DEFINE_LYNQ_LIB_LOG(LYNQ_AUDIO)
713
714#ifdef __cplusplus
715}
716#endif