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
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;
|
|
}
|