sdk-hwV1.3/external/fast-user-adapter/rt_media/demo/demo_audio_alsa.c

613 lines
15 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <pthread.h>
struct rt_hwparams {
snd_pcm_format_t format;
unsigned int channels;
unsigned int rate;
snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size;
};
pthread_t play_thread;
pthread_t capture_thread;
pthread_attr_t play_thread_attr;
struct sched_param play_schedule_param;
pthread_attr_t capture_thread_attr;
struct sched_param capture_schedule_param;
void *func_play_demo(void *arg);
void *func_play_hub_demo(void *arg);
void *func_capture_demo(void *arg);
void *func_capture_sync_demo(void *arg);
int main(void)
{
pthread_attr_init(&play_thread_attr);
play_schedule_param.sched_priority = 88;
pthread_attr_setinheritsched(&play_thread_attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&play_thread_attr, SCHED_RR);
pthread_attr_setschedparam(&play_thread_attr, &play_schedule_param);
pthread_attr_init(&capture_thread_attr);
capture_schedule_param.sched_priority = 88;
pthread_attr_setinheritsched(&capture_thread_attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&capture_thread_attr, SCHED_RR);
pthread_attr_setschedparam(&capture_thread_attr, &capture_schedule_param);
// pthread_create(&play_thread, &play_thread_attr, func_play_demo, &play_schedule_param);
pthread_create(&play_thread, &play_thread_attr, func_play_hub_demo, &play_schedule_param);
// pthread_create(&capture_thread, &capture_thread_attr, func_capture_demo, &capture_schedule_param);
pthread_create(&capture_thread, &capture_thread_attr, func_capture_sync_demo, &capture_schedule_param);
pthread_join(play_thread, NULL);
pthread_join(capture_thread, NULL);
printf("main exit\n");
return 0;
}
static int rt_snd_pcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode,
snd_pcm_hw_params_t *hw_params, struct rt_hwparams *hwparams)
{
int ret;
ret = snd_pcm_open(pcmp, name, stream, mode);
if (ret < 0) {
printf("snd_pcm_open failed: %d.\n", ret);
goto err_pcm_open;
}
ret = snd_pcm_hw_params_any(*pcmp, hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params_any failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_access(*pcmp, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (ret < 0) {
printf("snd_pcm_hw_params_set_access failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_format(*pcmp, hw_params, hwparams->format);
if (ret < 0) {
printf("snd_pcm_hw_params_set_format failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_channels(*pcmp, hw_params, hwparams->channels);
if (ret < 0) {
printf("snd_pcm_hw_params_set_channels failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_rate(*pcmp, hw_params, hwparams->rate, 0);
if (ret < 0) {
printf("snd_pcm_hw_params_set_rate failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_buffer_size(*pcmp, hw_params, hwparams->buffer_size);
if (ret < 0) {
printf("snd_pcm_hw_params_set_buffer_size failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params_set_period_size(*pcmp, hw_params, hwparams->period_size, 0);
if (ret < 0) {
printf("snd_pcm_hw_params_set_period_size failed: %d.\n", ret);
goto err_pcm_hw_params;
}
ret = snd_pcm_hw_params(*pcmp, hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params failed: %d.\n", ret);
goto err_pcm_hw_params;
}
return 0;
err_pcm_hw_params:
snd_pcm_close(*pcmp);
err_pcm_open:
return -1;
}
static void rt_snd_pcm_close(snd_pcm_t *pcmp)
{
if (pcmp)
snd_pcm_close(pcmp);
}
static int rt_mixer_cset(const char *card_name, const char *str, const char *value)
{
int i, err;
static char card[64] = "default";
static snd_ctl_t *handle = NULL;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *control;
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_value_alloca(&control);
i = snd_card_get_index(card_name);
if (i >= 0 && i < 32)
sprintf(card, "hw:%i", i);
else {
fprintf(stderr, "Invalid card number.\n");
return -EINVAL;
}
if (snd_ctl_ascii_elem_id_parse(id, str)) {
fprintf(stderr, "Wrong control identifier: %s\n", str);
return -EINVAL;
}
if (handle == NULL && (err = snd_ctl_open(&handle, card, 0)) < 0) {
printf("Control %s open error: %s\n", card, snd_strerror(err));
return err;
}
snd_ctl_elem_info_set_id(info, id);
if ((err = snd_ctl_elem_info(handle, info)) < 0) {
printf("Cannot find the given element from control %s\n", card);
snd_ctl_close(handle);
handle = NULL;
return err;
}
snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */
snd_ctl_elem_value_set_id(control, id);
if ((err = snd_ctl_elem_read(handle, control)) < 0) {
snd_ctl_close(handle);
handle = NULL;
return err;
}
err = snd_ctl_ascii_value_parse(handle, control, info, value);
if (err < 0) {
snd_ctl_close(handle);
handle = NULL;
return err;
}
if ((err = snd_ctl_elem_write(handle, control)) < 0) {
snd_ctl_close(handle);
handle = NULL;
return err;
}
snd_ctl_close(handle);
handle = NULL;
return 0;
}
/* base.
* 1. card -> audiocodec
* 2. asound.conf -> default card should be audiocodec, and hooks to open the playback control
*
* process.
* 1. open pcm file
* 2. open and set hw_params audiocodec card
* 3. read pcm file data and write to audiocodec card pcm device
* 4. close audiocodec card
*
* ex.
* channel -> 1
* sample bit -> 16
* sample rate -> 16K
* period size -> 1024
* period count -> 4
*/
void *func_play_demo(void *arg)
{
int ret;
FILE *fp_play = NULL;
size_t fp_read_size;
size_t fp_read_num;
snd_pcm_t *play_handle = NULL;
char *data = NULL;
snd_pcm_sframes_t num_write;
snd_pcm_hw_params_t *hw_params = NULL;
struct rt_hwparams rt_hwparam = {
.channels = 1,
.format = SND_PCM_FORMAT_S16_LE,
.rate = 16000,
.buffer_size = 4096,
.period_size = 1024,
};
fp_play = fopen("play_mono_16k.pcm","rb");
if (!fp_play) {
printf("fopen _failed.\n");
goto err_fopen;
}
printf("play start\n");
ret = snd_pcm_hw_params_malloc(&hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params_malloc failed: %d.\n", ret);
goto err_pcm_hw_params_malloc;
}
ret = rt_snd_pcm_open(&play_handle, "default", SND_PCM_STREAM_PLAYBACK, 0, hw_params, &rt_hwparam);
if (ret < 0) {
printf("rt_snd_pcm_open failed: %d.\n", ret);
goto err_rt_snd_pcm_open;
}
fp_read_size = snd_pcm_frames_to_bytes(play_handle, rt_hwparam.period_size);
data = (char *)malloc(fp_read_size);
if (data == NULL) {
printf("malloc failed\n");
goto err_malloc;
}
do {
fp_read_num = fread(data, 1, fp_read_size, fp_play);
if (fp_read_num < fp_read_size) {
printf("fread failed: %zu\n", fp_read_num);
goto err_pcm_writei;
}
num_write = snd_pcm_writei(play_handle, data, rt_hwparam.period_size);
if (num_write < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(num_write));
goto err_pcm_writei;
}
} while (!feof(fp_play));
snd_pcm_drain(play_handle);
err_pcm_writei:
if (data)
free(data);
err_malloc:
rt_snd_pcm_close(play_handle);
err_rt_snd_pcm_open:
snd_pcm_hw_params_free(hw_params);
err_pcm_hw_params_malloc:
if(fp_play)
fclose(fp_play);
err_fopen:
printf("play exit\n");
pthread_exit(NULL);
}
/* base.
* 1. card -> audiocodec
* 2. asound.conf -> default card should be audiocodec, and hooks to open the capture control
*
* process.
* 1. open new pcm file
* 2. open and set hw_params audiocodec card
* 4. read audiocodec card pcm device data and write to pcm file
* 5. close audiocodec card
*
* ex.
* channel -> 1
* sample bit -> 16
* sample rate -> 16K
* period size -> 1024
* period count -> 4
*/
void *func_capture_demo(void *arg)
{
int i, ret;
FILE *fp_capture = NULL;
size_t fp_write_size;
size_t fp_write_num;
snd_pcm_t *capture_handle = NULL;
char *data = NULL;
snd_pcm_sframes_t num_read;
snd_pcm_hw_params_t *hw_params = NULL;
struct rt_hwparams rt_hwparam = {
.channels = 1,
.format = SND_PCM_FORMAT_S16_LE,
.rate = 16000,
.buffer_size = 4096,
.period_size = 1024,
};
unsigned int capture_time = 500;
fp_capture = fopen("capture_mono_16k.pcm","wb");
if (!fp_capture) {
printf("fopen _failed.\n");
goto err_fopen;
}
printf("capture start\n");
ret = snd_pcm_hw_params_malloc(&hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params_malloc failed: %d.\n", ret);
goto err_pcm_hw_params_malloc;
}
ret = rt_snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0, hw_params, &rt_hwparam);
if (ret < 0) {
printf("rt_snd_pcm_open failed: %d.\n", ret);
goto err_rt_snd_pcm_open;
}
fp_write_size = snd_pcm_frames_to_bytes(capture_handle, rt_hwparam.period_size);
data = (char *)malloc(fp_write_size);
if (data == NULL) {
printf("malloc failed\n");
goto err_malloc;
}
for (i = 0; i < capture_time; i++) {
num_read = snd_pcm_readi(capture_handle, data, rt_hwparam.period_size);
if (num_read < 0) {
printf("snd_pcm_readi failed: %s\n", snd_strerror(num_read));
goto err_pcm_readi;
}
fp_write_num = fwrite(data, 1, fp_write_size, fp_capture);
if (fp_write_num != fp_write_size) {
printf("fwrite failed: %zu\n", fp_write_num);
goto err_pcm_readi;
}
}
snd_pcm_drain(capture_handle);
err_pcm_readi:
if (data)
free(data);
err_malloc:
err_rt_snd_pcm_open:
snd_pcm_hw_params_free(hw_params);
err_pcm_hw_params_malloc:
if(fp_capture)
fclose(fp_capture);
err_fopen:
printf("capture exit\n");
pthread_exit(NULL);
}
/* base.
* 1. card -> audiocodec & snddaudio0
* 2. card func -> audiocodec & snddaudio0 whit "tx hub mode" controls
* 3. asound.conf -> default card should be audiocodec, and hooks to open the playback control
*
* process.
* 1. open pcm file
* 2. set audiocodec & snddaudio0 card "tx hub mode" control to "On"
* 3. open and set hw_params audiocodec & snddaudio0 card
* 4. read pcm file data and write to audiocodec card pcm device
* 5. close audiocodec & snddaudio0 card
*
* ex.
* channel -> 1
* sample bit -> 16
* sample rate -> 16K
* period size -> 1024
* period count -> 4
*/
void *func_play_hub_demo(void *arg)
{
int ret;
FILE *fp_play = NULL;
size_t fp_read_size;
size_t fp_read_num;
snd_pcm_t *play_handle = NULL;
snd_pcm_t *play_hub_handle = NULL;
char *data = NULL;
snd_pcm_sframes_t num_write;
snd_pcm_hw_params_t *hw_params = NULL;
struct rt_hwparams rt_hwparam = {
.channels = 1,
.format = SND_PCM_FORMAT_S16_LE,
.rate = 16000,
.buffer_size = 4096,
.period_size = 1024,
};
fp_play = fopen("play_mono_16k.pcm","rb");
if (!fp_play) {
printf("fopen _failed.\n");
goto err_fopen;
}
printf("capture control set start\n");
ret = rt_mixer_cset("audiocodec", "name='tx hub mode'", "On");
if (ret < 0) {
printf("rt_mixer_cset failed: %d.\n", ret);
goto err_mixer_cset;
}
ret = rt_mixer_cset("snddaudio0", "name='tx hub mode'", "On");
if (ret < 0) {
printf("rt_mixer_cset failed: %d.\n", ret);
goto err_mixer_cset;
}
printf("capture control set exit\n");
printf("play start\n");
ret = snd_pcm_hw_params_malloc(&hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params_malloc failed: %d.\n", ret);
goto err_pcm_hw_params_malloc;
}
ret = rt_snd_pcm_open(&play_handle, "default", SND_PCM_STREAM_PLAYBACK, 0, hw_params, &rt_hwparam);
if (ret < 0) {
printf("rt_snd_pcm_open failed: %d.\n", ret);
goto err_rt_snd_pcm_open;
}
ret = rt_snd_pcm_open(&play_hub_handle, "hw:snddaudio0,0", SND_PCM_STREAM_PLAYBACK, 0, hw_params, &rt_hwparam);
if (ret < 0) {
printf("rt_snd_pcm_open failed: %d.\n", ret);
goto err_rt_snd_pcm_open;
}
fp_read_size = snd_pcm_frames_to_bytes(play_handle, rt_hwparam.period_size);
data = (char *)malloc(fp_read_size);
if (data == NULL) {
printf("malloc failed\n");
goto err_malloc;
}
do {
fp_read_num = fread(data, 1, fp_read_size, fp_play);
if (fp_read_num < fp_read_size) {
printf("fread failed: %zu\n", fp_read_num);
goto err_pcm_writei;
}
num_write = snd_pcm_writei(play_handle, data, rt_hwparam.period_size);
if (num_write < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(num_write));
goto err_pcm_writei;
}
} while (!feof(fp_play));
snd_pcm_drain(play_handle);
err_pcm_writei:
if (data)
free(data);
err_malloc:
rt_snd_pcm_close(play_hub_handle);
rt_snd_pcm_close(play_handle);
err_rt_snd_pcm_open:
snd_pcm_hw_params_free(hw_params);
err_pcm_hw_params_malloc:
err_mixer_cset:
if(fp_play)
fclose(fp_play);
err_fopen:
printf("play exit\n");
pthread_exit(NULL);
}
/* base.
* 1. card -> audiocodec & snddaudio0
* 2. card func -> audiocodec & snddaudio0 whit "rx sync mode" controls
* 3. asound.conf -> default card should be multi audiocodec & snddaudio0, and hooks to open the capture control;
*
* process.
* 1. open pcm file
* 2. set audiocodec & snddaudio0 card "rx sync mode" control to "On"
* 3. open and set hw_params default card
* 4. read default card pcm device data and write to pcm file
* 5. close default card
*
* ex.
* channel -> 2
* sample bit -> 16
* sample rate -> 16K
* period size -> 1024
* period count -> 4
*/
void *func_capture_sync_demo(void *arg)
{
int i, ret;
FILE *fp_capture = NULL;
size_t fp_write_size;
size_t fp_write_num;
snd_pcm_t *capture_handle = NULL;
char *data = NULL;
snd_pcm_sframes_t num_read;
snd_pcm_hw_params_t *hw_params = NULL;
struct rt_hwparams rt_hwparam = {
.channels = 2,
.format = SND_PCM_FORMAT_S16_LE,
.rate = 16000,
.buffer_size = 4096,
.period_size = 1024,
};
unsigned int capture_time = 500;
fp_capture = fopen("capture_stereo_16k.pcm","wb");
if (!fp_capture) {
printf("fopen _failed.\n");
goto err_fopen;
}
printf("capture control set start\n");
ret = rt_mixer_cset("audiocodec", "name='rx sync mode'", "On");
if (ret < 0) {
printf("rt_mixer_cset failed: %d.\n", ret);
goto err_mixer_cset;
}
ret = rt_mixer_cset("snddaudio0", "name='rx sync mode'", "On");
if (ret < 0) {
printf("rt_mixer_cset failed: %d.\n", ret);
goto err_mixer_cset;
}
printf("capture control set exit\n");
printf("capture start\n");
ret = snd_pcm_hw_params_malloc(&hw_params);
if (ret < 0) {
printf("snd_pcm_hw_params_malloc failed: %d.\n", ret);
goto err_pcm_hw_params_malloc;
}
ret = rt_snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0, hw_params, &rt_hwparam);
if (ret < 0) {
printf("rt_snd_pcm_open failed: %d.\n", ret);
goto err_rt_snd_pcm_open;
}
fp_write_size = snd_pcm_frames_to_bytes(capture_handle, rt_hwparam.period_size);
data = (char *)malloc(fp_write_size);
if (data == NULL) {
printf("malloc failed\n");
goto err_malloc;
}
for (i = 0; i < capture_time; i++) {
num_read = snd_pcm_readi(capture_handle, data, rt_hwparam.period_size);
if (num_read < 0) {
printf("snd_pcm_readi failed: %s\n", snd_strerror(num_read));
goto err_pcm_readi;
}
fp_write_num = fwrite(data, 1, fp_write_size, fp_capture);
if (fp_write_num != fp_write_size) {
printf("fwrite failed: %zu\n", fp_write_num);
goto err_pcm_readi;
}
}
snd_pcm_drain(capture_handle);
err_pcm_readi:
if (data)
free(data);
err_malloc:
err_rt_snd_pcm_open:
snd_pcm_hw_params_free(hw_params);
err_pcm_hw_params_malloc:
err_mixer_cset:
if(fp_capture)
fclose(fp_capture);
err_fopen:
printf("capture exit\n");
pthread_exit(NULL);
}