You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

427 lines
12 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
* Description: mix engine sample
* Author: audio
* Create: 2019-05-19
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "securec.h"
#include "uapi_system.h"
#include "uapi_sound.h"
#include "adp_common_ext.h"
#define RATIO 1000
#define INPUT_CMD_LENGTH 32
typedef struct {
uapi_snd snd;
td_bool peq_enable;
uapi_snd_out_port out_port;
td_u32 select_band;
uapi_snd_peq_attr peq_attr;
td_s32 argc;
td_char *argv[INPUT_CMD_LENGTH];
} sample_peq_ctx;
static const struct {
uapi_snd_out_port out_port;
const td_char *name;
} g_ao_port_name[] = {
{ UAPI_SND_OUT_PORT_DAC0, "DAC0" },
{ UAPI_SND_OUT_PORT_I2S0, "I2S0" },
{ UAPI_SND_OUT_PORT_I2S1, "I2S1" },
{ UAPI_SND_OUT_PORT_I2S2, "I2S2" },
{ UAPI_SND_OUT_PORT_I2S3, "I2S3" },
{ UAPI_SND_OUT_PORT_I2S4, "I2S4" },
{ UAPI_SND_OUT_PORT_HDMITX0, "HDMI0" },
{ UAPI_SND_OUT_PORT_HDMITX1, "HDMI1" },
{ UAPI_SND_OUT_PORT_SPDIF0, "SPDIF0" },
{ UAPI_SND_OUT_PORT_ARC0, "ARC0" },
{ UAPI_SND_OUT_PORT_DAC1, "DAC1" },
{ UAPI_SND_OUT_PORT_DAC2, "DAC2" },
{ UAPI_SND_OUT_PORT_DAC3, "DAC3" },
{ UAPI_SND_OUT_PORT_ALL, "ALLPORT" },
};
static const td_char *autil_port_to_name(uapi_snd_out_port out_port)
{
td_u32 i;
for (i = 0; i < (sizeof((g_ao_port_name)) / sizeof((g_ao_port_name)[0])); i++) {
if (out_port == g_ao_port_name[i].out_port) {
return g_ao_port_name[i].name;
}
}
return "n/a";
}
static uapi_snd_out_port autil_port_name_to_port(td_char *name)
{
td_u32 i;
for (i = 0; i < (sizeof((g_ao_port_name)) / sizeof((g_ao_port_name)[0])); i++) {
if (strncmp(name, g_ao_port_name[i].name, strlen(g_ao_port_name[i].name)) == 0) {
return g_ao_port_name[i].out_port;
}
}
return UAPI_SND_OUT_PORT_MAX;
}
static const struct {
uapi_peq_filter_type filter_type;
const td_char *name;
} g_peq_filter_type_name[] = {
{UAPI_PEQ_FILTER_TYPE_HP, "HP"},
{UAPI_PEQ_FILTER_TYPE_LS, "LS"},
{UAPI_PEQ_FILTER_TYPE_PK, "PK"},
{UAPI_PEQ_FILTER_TYPE_HS, "HS"},
{UAPI_PEQ_FILTER_TYPE_LP, "LP"},
};
static const td_char *autil_peq_type_to_name(uapi_peq_filter_type filter_type)
{
if (filter_type < (sizeof((g_peq_filter_type_name)) / sizeof((g_peq_filter_type_name)[0]))) {
return g_peq_filter_type_name[filter_type].name;
}
return "n/a";
}
static td_void sample_peq_print_attr(sample_peq_ctx *peq_ctx)
{
td_u32 i;
td_s32 ret;
peq_ctx->peq_enable = TD_FALSE;
ret = uapi_snd_get_peq_enable(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_enable);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_enable failed(0x%x)\n", ret);
return;
}
ret = uapi_snd_get_peq_attr(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_attr);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_attr failed(0x%x)\n", ret);
return;
}
printf("==========================================\n");
printf("-out_port: %s\n", autil_port_to_name(peq_ctx->out_port));
printf("-peq_enable: %s\n", (peq_ctx->peq_enable == TD_TRUE) ? "yes" : "no");
printf("-band_num: %d\n", peq_ctx->peq_attr.band_num);
printf("%4s | %-11s | %-6s | %-3s | %-5s |\n",
"band", "filter_type", "freq", "q", "gain");
for (i = 0; i < peq_ctx->peq_attr.band_num; i++) {
printf("%4d | %4d %-6s %-6d %-3d %-5d |\n",
i,
peq_ctx->peq_attr.param[i].filter_type,
autil_peq_type_to_name(peq_ctx->peq_attr.param[i].filter_type),
peq_ctx->peq_attr.param[i].freq,
peq_ctx->peq_attr.param[i].q,
peq_ctx->peq_attr.param[i].gain);
}
printf("-select_band: %d\n", peq_ctx->select_band);
printf("\n==========================================\n");
}
static td_void sample_peq_deinit(sample_peq_ctx *peq_ctx)
{
td_s32 ret;
(td_void)peq_ctx;
ret = uapi_snd_deinit();
if (ret != TD_SUCCESS) {
printf("call uapi_snd_deinit failed(0x%x)\n", ret);
return;
}
}
static td_s32 sample_peq_init(sample_peq_ctx *peq_ctx)
{
td_s32 ret;
ret = memset_s(peq_ctx, sizeof(*peq_ctx), 0, sizeof(sample_peq_ctx));
if (ret != EOK) {
printf("call memset_s failed(0x%x)\n", ret);
return ret;
}
peq_ctx->snd = UAPI_SND_0;
peq_ctx->out_port = UAPI_SND_OUT_PORT_DAC0;
ret = uapi_snd_init();
if (ret != TD_SUCCESS) {
printf("call uapi_snd_init failed(0x%x)\n", ret);
return ret;
}
ret = uapi_snd_get_peq_enable(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_enable);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_enable failed(0x%x)\n", ret);
goto out;
}
ret = uapi_snd_get_peq_attr(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_attr);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_attr failed(0x%x)\n", ret);
goto out;
}
return TD_SUCCESS;
out:
sample_peq_deinit(peq_ctx);
return ret;
}
static td_void sample_peq_set_attr(sample_peq_ctx *peq_ctx)
{
td_s32 ret;
ret = uapi_snd_set_peq_enable(peq_ctx->snd, peq_ctx->out_port, peq_ctx->peq_enable);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_set_peq_enable failed(0x%x)\n", ret);
}
ret = uapi_snd_set_peq_attr(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_attr);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_set_peq_attr failed(0x%x)\n", ret);
}
ret = uapi_snd_get_peq_enable(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_enable);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_enable failed(0x%x)\n", ret);
}
ret = uapi_snd_get_peq_attr(peq_ctx->snd, peq_ctx->out_port, &peq_ctx->peq_attr);
if (ret != TD_SUCCESS) {
printf("call uapi_snd_get_peq_attr failed(0x%x)\n", ret);
}
sample_peq_print_attr(peq_ctx);
}
static td_void sample_peq_print_memu(td_void)
{
printf("==========================================\n");
printf("input q to quit\n");
printf("support option:\n");
printf(
"\t-p: print peq attr\n"
"\t-o: select out port(DAC0/I2S0/HDMI0/SPDIF0)\n"
"\t-e: enable peq\n"
"\t-d: disable peq\n"
"\t-b: set total num of banks [1, 10]\n"
"\t-n: select bank to change attr [0, 9]\n"
"\t-t: filter type(HP:0, LS:1, PK:2, HS:3, LP:4)\n"
"\t-f: freq(HP and LS[20, 4000], PK[20, 22000], HS[4000, 22000], LP[50, 22000])\n"
"\t-q: Q value(HS and LS[7, 10], PK[5, 100], HP and LP is fix to be 7)\n"
"\t-g: gain(-15000, 15000, step by 125)\n"
);
printf("==========================================\n");
}
static td_s32 sample_peq_parse_attr(sample_peq_ctx *peq_ctx, td_char opt, td_char *opt_arg)
{
if (opt_arg == TD_NULL) {
printf("invalid option -- '%c'\n", opt);
sample_peq_print_memu();
return TD_FAILURE;
}
if (peq_ctx->peq_attr.band_num > UAPI_SND_EQ_BAND_MAX) {
printf("invalid band_num -- '%d'\n", peq_ctx->peq_attr.band_num);
sample_peq_print_memu();
return TD_FAILURE;
}
if (peq_ctx->select_band >= UAPI_SND_EQ_BAND_MAX) {
printf("invalid select_band -- '%d'\n", peq_ctx->select_band);
sample_peq_print_memu();
return TD_FAILURE;
}
switch (opt) {
case 'o':
peq_ctx->out_port = autil_port_name_to_port(opt_arg);
break;
case 'b':
peq_ctx->peq_attr.band_num = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
case 'n':
peq_ctx->select_band = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
case 't':
peq_ctx->peq_attr.param[peq_ctx->select_band].filter_type =
(uapi_peq_filter_type)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
case 'f':
peq_ctx->peq_attr.param[peq_ctx->select_band].freq = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
case 'q':
peq_ctx->peq_attr.param[peq_ctx->select_band].q = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
case 'g':
peq_ctx->peq_attr.param[peq_ctx->select_band].gain = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
break;
default:
printf("invalid option -- '%c'\n", opt);
sample_peq_print_memu();
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_u32 sample_peq_parse_opt(sample_peq_ctx *peq_ctx, td_char opt, td_char *opt_arg)
{
td_s32 ret;
switch (opt) {
case 'h' | 'H':
sample_peq_print_memu();
return INPUT_CMD_LENGTH;
case 'p' | 'P':
sample_peq_print_attr(peq_ctx);
return INPUT_CMD_LENGTH;
case 'e':
peq_ctx->peq_enable = TD_TRUE;
return 1;
case 'd':
peq_ctx->peq_enable = TD_FALSE;
return 1;
default:
break;
}
ret = sample_peq_parse_attr(peq_ctx, opt, opt_arg);
if (ret != TD_SUCCESS) {
return INPUT_CMD_LENGTH;
}
return 2; /* consume 2 args */
}
static td_void sample_peq_cmd_line_to_arg(sample_peq_ctx *peq_ctx, td_char *cmd, td_u32 cmd_size)
{
td_u32 j;
peq_ctx->argc = 0;
peq_ctx->argv[0] = TD_NULL;
if ((*cmd == '\0') || (*cmd == '\n')) {
sample_peq_print_memu();
return;
}
for (j = 0; j < cmd_size; j++) {
if ((cmd[j] == ' ') || (cmd[j] == '\n')) {
cmd[j] = '\0';
}
}
for (j = 0; j < cmd_size; j++) {
if ((j == 0) && (cmd[j] != '\0')) {
peq_ctx->argv[peq_ctx->argc] = cmd + j;
peq_ctx->argc++;
}
if ((j > 0) && (cmd[j - 1] == '\0') && (cmd[j] != '\0')) {
peq_ctx->argv[peq_ctx->argc] = cmd + j;
peq_ctx->argc++;
}
}
}
static td_void sample_peq_parse_cmd_line(sample_peq_ctx *peq_ctx, td_char *cmd, td_u32 cmd_size)
{
td_s32 i;
td_s32 j;
sample_peq_cmd_line_to_arg(peq_ctx, cmd, cmd_size);
if (peq_ctx->argc == 0) {
return;
}
i = 0;
while (1) {
if (i >= peq_ctx->argc) {
break;
}
j = sample_peq_parse_opt(peq_ctx, *(peq_ctx->argv[i]), peq_ctx->argv[i + 1]);
if (j == INPUT_CMD_LENGTH) {
return;
}
i += j;
}
sample_peq_set_attr(peq_ctx);
}
td_s32 main(td_s32 argc, td_char *argv[])
{
td_s32 ret;
sample_peq_ctx peq_ctx;
td_char input_cmd[INPUT_CMD_LENGTH];
(td_void)argc;
(td_void)argv;
ret = uapi_sys_init();
if (ret != TD_SUCCESS) {
printf("call uapi_sys_init failed(0x%x)\n", ret);
return ret;
}
ret = sample_peq_init(&peq_ctx);
if (ret != TD_SUCCESS) {
printf("call sample_peq_init failed(0x%x)\n", ret);
goto out;
}
sample_peq_print_attr(&peq_ctx);
sample_peq_print_memu();
while (1) {
if (memset_s(input_cmd, sizeof(input_cmd), 0,
INPUT_CMD_LENGTH) != EOK) {
break;
}
(td_void)fgets((char *)(input_cmd), (sizeof(input_cmd) - 1), stdin);
if (input_cmd[0] == 'q') {
printf("prepare to quit!\n");
break;
}
input_cmd[INPUT_CMD_LENGTH - 1] = '\0';
sample_peq_parse_cmd_line(&peq_ctx, input_cmd, INPUT_CMD_LENGTH);
}
sample_peq_deinit(&peq_ctx);
out:
ret = uapi_sys_deinit();
if (ret != TD_SUCCESS) {
printf("call uapi_sys_deinit failed(0x%x)\n", ret);
return ret;
}
return 0;
}