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.
373 lines
9.7 KiB
373 lines
9.7 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_sound.h"
|
|
#include "uapi_system.h"
|
|
#include "adp_common_ext.h"
|
|
|
|
#define RATIO 1000
|
|
#define INPUT_CMD_LENGTH 32
|
|
|
|
typedef struct {
|
|
uapi_snd snd;
|
|
td_bool drc_enable;
|
|
uapi_snd_out_port out_port;
|
|
uapi_snd_drc_attr drc_attr;
|
|
|
|
td_s32 argc;
|
|
td_char *argv[INPUT_CMD_LENGTH];
|
|
} sample_drc_ctx;
|
|
|
|
static const struct {
|
|
uapi_snd_out_port 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_SPDIF0, "SPDIF0" },
|
|
{ UAPI_SND_OUT_PORT_HDMITX0, "HDMI0" },
|
|
{ UAPI_SND_OUT_PORT_HDMITX1, "HDMI1" },
|
|
{ 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 port)
|
|
{
|
|
td_u32 i;
|
|
|
|
for (i = 0; i < (sizeof(g_ao_port_name) / sizeof(g_ao_port_name[0])); i++) {
|
|
if (port == g_ao_port_name[i].port) {
|
|
return g_ao_port_name[i].name;
|
|
}
|
|
}
|
|
|
|
return "unknown_port";
|
|
}
|
|
|
|
static uapi_snd_out_port autil_port_name_to_port(const 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].port;
|
|
}
|
|
}
|
|
|
|
return UAPI_SND_OUT_PORT_MAX;
|
|
}
|
|
|
|
static td_void sample_drc_print_attr(sample_drc_ctx *drc_ctx)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = uapi_snd_get_drc_enable(drc_ctx->snd, drc_ctx->out_port, &drc_ctx->drc_enable);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_get_drc_enable failed(0x%x)\n", ret);
|
|
}
|
|
|
|
ret = uapi_snd_get_drc_attr(drc_ctx->snd, drc_ctx->out_port, &drc_ctx->drc_attr);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_get_drc_attr failed(0x%x)\n", ret);
|
|
}
|
|
|
|
printf("==========================================\n");
|
|
printf("-out_port: %s\n", autil_port_to_name(drc_ctx->out_port));
|
|
printf("-drc_enable: %s\n", (drc_ctx->drc_enable == TD_TRUE) ? "yes" : "no");
|
|
|
|
printf("-attack_time: %d\n", drc_ctx->drc_attr.attack_time);
|
|
printf("-release_time: %d\n", drc_ctx->drc_attr.release_time);
|
|
|
|
printf("-threshold:%d.%ddB\n",
|
|
drc_ctx->drc_attr.thrhd / RATIO,
|
|
-drc_ctx->drc_attr.thrhd % RATIO);
|
|
|
|
printf("-limit:%d.%ddB\n",
|
|
drc_ctx->drc_attr.limit / RATIO,
|
|
drc_ctx->drc_attr.limit % RATIO);
|
|
|
|
printf("-ref_mode: %d\n", drc_ctx->drc_attr.ref_mode);
|
|
printf("-speed_ctrl_mode: %d\n", drc_ctx->drc_attr.speed_ctrl_mode);
|
|
|
|
printf("==========================================\n");
|
|
}
|
|
|
|
static td_void sample_drc_deinit(const sample_drc_ctx *drc_ctx)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = uapi_snd_deinit();
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_deinit failed(0x%x)\n", ret);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static td_s32 sample_drc_init(sample_drc_ctx *drc_ctx)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = memset_s(drc_ctx, sizeof(*drc_ctx), 0, sizeof(sample_drc_ctx));
|
|
if (ret != EOK) {
|
|
printf("call memset_s failed(0x%x)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
drc_ctx->snd = UAPI_SND_0;
|
|
drc_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_drc_enable(drc_ctx->snd, drc_ctx->out_port, &drc_ctx->drc_enable);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_get_drc_enable failed(0x%x)\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
ret = uapi_snd_get_drc_attr(drc_ctx->snd, drc_ctx->out_port, &drc_ctx->drc_attr);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_get_drc_attr failed(0x%x)\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
out:
|
|
sample_drc_deinit(drc_ctx);
|
|
return ret;
|
|
}
|
|
|
|
static td_void sample_drc_set_attr(sample_drc_ctx *drc_ctx)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = uapi_snd_set_drc_enable(drc_ctx->snd, drc_ctx->out_port, drc_ctx->drc_enable);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_set_drc_enable failed(0x%x)\n", ret);
|
|
}
|
|
|
|
ret = uapi_snd_set_drc_attr(drc_ctx->snd, drc_ctx->out_port, &drc_ctx->drc_attr);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_snd_set_drc_attr failed(0x%x)\n", ret);
|
|
}
|
|
|
|
sample_drc_print_attr(drc_ctx);
|
|
}
|
|
|
|
static td_void sample_drc_print_memu(td_void)
|
|
{
|
|
printf("==========================================\n");
|
|
printf("input q to quit\n");
|
|
printf("support option:\n");
|
|
printf(
|
|
"\t-p: print drc attr\n"
|
|
"\t-o: select out port(DAC0/I2S0/HDMI0/SPDIF0)\n"
|
|
"\t-e: enable drc\n"
|
|
"\t-d: disable drc\n"
|
|
"\t-a: attack_time [20, 2000]\n"
|
|
"\t-r: release_time [20, 2000]\n"
|
|
"\t-t: threshold [-80.000, -1.000] dB\n"
|
|
"\t-l: limit [-80.000, -1.000] dB\n"
|
|
"\t-f: ref_mode [0 or 1]\n"
|
|
"\t-s: speed_ctrl_mode [0 or 1]\n");
|
|
printf("==========================================\n");
|
|
}
|
|
|
|
static td_s32 sample_drc_parse_attr(sample_drc_ctx *drc_ctx, td_char opt, const td_char *opt_arg)
|
|
{
|
|
if (opt_arg == TD_NULL) {
|
|
printf("invalid option -- '%c'\n", opt);
|
|
sample_drc_print_memu();
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
switch (opt) {
|
|
case 'o':
|
|
drc_ctx->out_port = autil_port_name_to_port(opt_arg);
|
|
break;
|
|
case 'a':
|
|
drc_ctx->drc_attr.attack_time = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
|
|
break;
|
|
case 'r':
|
|
drc_ctx->drc_attr.release_time = (td_u32)strtol(opt_arg, NULL, 10); /* 10 is Dec */
|
|
break;
|
|
case 't':
|
|
drc_ctx->drc_attr.thrhd = (td_s32)(strtod(opt_arg, NULL) * RATIO);
|
|
break;
|
|
case 'l':
|
|
drc_ctx->drc_attr.limit = (td_s32)(strtod(opt_arg, NULL) * RATIO);
|
|
break;
|
|
case 'f':
|
|
drc_ctx->drc_attr.ref_mode = !!strtol(opt_arg, NULL, 10); /* 10 is Dec */
|
|
break;
|
|
case 's':
|
|
drc_ctx->drc_attr.speed_ctrl_mode = !!strtol(opt_arg, NULL, 10); /* 10 is Dec */
|
|
break;
|
|
default:
|
|
printf("invalid option -- '%c'\n", opt);
|
|
sample_drc_print_memu();
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_u32 sample_drc_parse_opt(sample_drc_ctx *drc_ctx, td_char opt, const td_char *opt_arg)
|
|
{
|
|
td_s32 ret;
|
|
|
|
switch (opt) {
|
|
case 'h' | 'H':
|
|
sample_drc_print_memu();
|
|
return INPUT_CMD_LENGTH;
|
|
case 'p' | 'P':
|
|
sample_drc_print_attr(drc_ctx);
|
|
return INPUT_CMD_LENGTH;
|
|
case 'e':
|
|
drc_ctx->drc_enable = TD_TRUE;
|
|
return 1;
|
|
case 'd':
|
|
drc_ctx->drc_enable = TD_FALSE;
|
|
return 1;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ret = sample_drc_parse_attr(drc_ctx, opt, opt_arg);
|
|
if (ret != TD_SUCCESS) {
|
|
return INPUT_CMD_LENGTH;
|
|
}
|
|
|
|
return 2; /* consume 2 args */
|
|
}
|
|
|
|
static td_void sample_drc_cmd_line_to_arg(sample_drc_ctx *drc_ctx, td_char *cmd, td_u32 cmd_size)
|
|
{
|
|
td_u32 i;
|
|
|
|
drc_ctx->argc = 0;
|
|
drc_ctx->argv[0] = TD_NULL;
|
|
|
|
if ((*cmd == '\0') || (*cmd == '\n')) {
|
|
sample_drc_print_memu();
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < cmd_size; i++) {
|
|
if ((cmd[i] == ' ') || (cmd[i] == '\n')) {
|
|
cmd[i] = '\0';
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < cmd_size; i++) {
|
|
if ((i == 0) && (cmd[i] != '\0')) {
|
|
drc_ctx->argv[drc_ctx->argc] = cmd + i;
|
|
drc_ctx->argc++;
|
|
}
|
|
|
|
if ((i > 0) && (cmd[i - 1] == '\0') && (cmd[i] != '\0')) {
|
|
drc_ctx->argv[drc_ctx->argc] = cmd + i;
|
|
drc_ctx->argc++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static td_void sample_drc_parse_cmd_line(sample_drc_ctx *drc_ctx, td_char *cmd, td_u32 cmd_size)
|
|
{
|
|
td_u32 i;
|
|
td_u32 j;
|
|
|
|
drc_ctx->argc = 0;
|
|
sample_drc_cmd_line_to_arg(drc_ctx, cmd, cmd_size);
|
|
|
|
if (drc_ctx->argc == 0) {
|
|
return;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
while (1) {
|
|
if (i >= drc_ctx->argc) {
|
|
break;
|
|
}
|
|
|
|
j = sample_drc_parse_opt(drc_ctx, *(drc_ctx->argv[i]), drc_ctx->argv[i + 1]);
|
|
if (j == INPUT_CMD_LENGTH) {
|
|
return;
|
|
}
|
|
|
|
i += j;
|
|
}
|
|
|
|
sample_drc_set_attr(drc_ctx);
|
|
}
|
|
|
|
td_s32 main(td_s32 argc, td_char *argv[])
|
|
{
|
|
td_s32 ret;
|
|
sample_drc_ctx drc_ctx;
|
|
td_char input_cmd[INPUT_CMD_LENGTH];
|
|
|
|
ret = uapi_sys_init();
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_sys_init failed(0x%x)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = sample_drc_init(&drc_ctx);
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call sample_drc_init failed(0x%x)\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
sample_drc_print_attr(&drc_ctx);
|
|
sample_drc_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_drc_parse_cmd_line(&drc_ctx, input_cmd, INPUT_CMD_LENGTH);
|
|
}
|
|
|
|
sample_drc_deinit(&drc_ctx);
|
|
|
|
out:
|
|
ret = uapi_sys_deinit();
|
|
if (ret != TD_SUCCESS) {
|
|
printf("call uapi_sys_deinit failed(0x%x)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|