Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add copier gain feature #9323

Merged
merged 4 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/audio/copier/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ if(CONFIG_IPC4_GATEWAY)
copier_ipcgtw.c
)
endif()

if(CONFIG_COPIER_GAIN)
add_local_sources(sof copier_gain.c)
endif()
13 changes: 13 additions & 0 deletions src/audio/copier/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,16 @@ config COMP_DAI_GROUP
help
Select for grouping physical DAIs into a logical DAI that can be
triggered atomically to synchronise stream start and stop operations.

if COMP_COPIER

config COPIER_GAIN
bool "COPIER gain feature"
default y
help
Select for using copier gain feature. There are three modes available:
- Static gain: gain is set at initialization and remains constant.
- Mute: gain is set to 0, signal is muted.
- Transition gain: gain is set to a target value over a specified time.
Common use cases are fade-in and fade-out effects.
endif
22 changes: 22 additions & 0 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <sof/audio/module_adapter/module/generic.h>
#include "copier.h"
#include "dai_copier.h"
#include "copier_gain.h"

LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);

Expand Down Expand Up @@ -217,9 +218,29 @@ static int copier_dai_init(struct comp_dev *dev,
if (ret < 0)
goto e_zephyr_free;

/* Allocate gain data if selected for this dai type and set basic params */
if (dai->apply_gain) {
struct copier_gain_params *gain_data = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED,
0, SOF_MEM_CAPS_RAM,
sizeof(*gain_data));
if (!gain_data) {
ret = -ENOMEM;
goto e_zephyr_free;
}
cd->dd[index]->gain_data = gain_data;

ret = copier_gain_set_params(dev, cd->dd[index]);
if (ret < 0) {
comp_err(dev, "Failed to set gain params!");
goto gain_free;
}
}

cd->endpoint_num++;

return 0;
gain_free:
rfree(dd->gain_data);
e_zephyr_free:
dai_common_free(dd);
free_dd:
Expand Down Expand Up @@ -348,6 +369,7 @@ void copier_dai_free(struct copier_data *cd)
{
for (int i = 0; i < cd->endpoint_num; i++) {
dai_common_free(cd->dd[i]);
rfree(cd->dd[i]->gain_data);
rfree(cd->dd[i]);
}
/* only dai have multi endpoint case */
Expand Down
150 changes: 150 additions & 0 deletions src/audio/copier/copier_gain.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation.
//
// Author: Ievgen Ganakov <ievgen.ganakov@intel.com>

#include <sof/trace/trace.h>
#include <ipc4/base-config.h>
#include <sof/audio/component_ext.h>
#include <module/module/base.h>
#include "copier.h"
#include "copier_gain.h"

LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);

int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd)
{
struct processing_module *mod = comp_mod(dev);
struct copier_data *cd = module_get_private_data(mod);
struct ipc4_base_module_cfg *ipc4_cfg = &cd->config.base;
uint32_t sampling_freq = ipc4_cfg->audio_fmt.sampling_frequency;
uint32_t frames = sampling_freq / dev->pipeline->period;
uint32_t fade_period = GAIN_DEFAULT_FADE_PERIOD;
int ret;

/* Set basic gain parameters */
copier_gain_set_basic_params(dev, dd, ipc4_cfg);

/* Set fade parameters */
ret = copier_gain_set_fade_params(dev, dd, ipc4_cfg, fade_period, frames);
if (ret)
comp_err(dev, "Failed to set fade params");

return ret;
}

int copier_gain_input(struct comp_dev *dev, struct comp_buffer *buff,
struct copier_gain_params *gain_params,
enum copier_gain_envelope_dir dir, uint32_t stream_bytes)
{
enum sof_ipc_frame frame_fmt = audio_stream_get_frm_fmt(&buff->stream);
uint32_t frames = stream_bytes / audio_stream_frame_bytes(&buff->stream);
enum copier_gain_state state;

if (!gain_params)
return -EINVAL;

state = copier_gain_eval_state(gain_params);

comp_dbg(dev, "copier selected gain state %d", state);

switch (frame_fmt) {
case SOF_IPC_FRAME_S16_LE:
return copier_gain_input16(buff, state, dir, gain_params, frames);
case SOF_IPC_FRAME_S32_LE:
return copier_gain_input32(buff, state, dir, gain_params, frames);
default:
comp_err(dev, "unsupported frame format %d for copier gain", frame_fmt);
return -EINVAL;
}
}

enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_params)
{
enum copier_gain_state state = STATIC_GAIN;

if (gain_params->silence_sg_count < gain_params->silence_sg_length)
state = MUTE;
else if ((gain_params->fade_in_sg_count < gain_params->fade_sg_length) &&
(gain_params->fade_sg_length != 0))
state = TRANS_GAIN;

return state;
}

int copier_gain_dma_control(uint32_t node_id, const uint32_t *config_data,
size_t config_size, enum sof_ipc_dai_type dai_type)
{
struct ipc *ipc = ipc_get();
struct ipc_comp_dev *icd;
struct comp_dev *dev;
struct list_item *clist;

int ret;

list_for_item(clist, &ipc->comp_list) {
struct gain_dma_control_data *gain_data = NULL;

icd = container_of(clist, struct ipc_comp_dev, list);

if (!icd || icd->type != COMP_TYPE_COMPONENT)
continue;

dev = icd->cd;

if (!dev || dev->ipc_config.type != SOF_COMP_DAI)
continue;

struct processing_module *mod = comp_mod(dev);
struct copier_data *cd = module_get_private_data(mod);

ret = copier_set_gain(dev, cd->dd[0], gain_data);
if (ret)
comp_err(dev, "Gain DMA control: failed to set gain");
return ret;
}

return -ENODEV;
}

int copier_set_gain(struct comp_dev *dev, struct dai_data *dd,
struct gain_dma_control_data *gain_data)
{
struct copier_gain_params *gain_params = dd->gain_data;
struct ipc4_copier_module_cfg *copier_cfg = dd->dai_spec_config;
const int channels = copier_cfg->base.audio_fmt.channels_count;
uint16_t static_gain[MAX_GAIN_COEFFS_CNT];
int ret;

if (!gain_data) {
comp_err(dev, "Gain data is NULL");
return -EINVAL;
}

/* Set gain coefficients */
comp_info(dev, "Update gain coefficients from DMA_CONTROL ipc");

size_t gain_coef_size = channels * sizeof(uint16_t);

ret = memcpy_s(static_gain, gain_coef_size, gain_data->gain_coeffs,
gain_coef_size);
if (ret) {
comp_err(dev, "memcpy_s failed with error %d", ret);
return ret;
}

for (int i = channels; i < MAX_GAIN_COEFFS_CNT; i++)
static_gain[i] = static_gain[i % channels];

ret = memcpy_s(gain_params->gain_coeffs, sizeof(static_gain),
static_gain, sizeof(static_gain));
if (ret) {
comp_err(dev, "memcpy_s failed with error %d", ret);
return ret;
}

gain_params->unity_gain = copier_is_unity_gain(gain_params);

return 0;
}
Loading
Loading