Skip to content
Open
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/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ static void get_codec_info(struct sof_tlv **tuple)
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_VORBIS, SOF_IPC_STREAM_PLAYBACK);
#endif
#ifdef CONFIG_COMP_MFCC
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_BESPOKE, SOF_IPC_STREAM_CAPTURE);
#endif

if (!codec_info.count)
return;
Expand Down
5 changes: 4 additions & 1 deletion src/audio/mfcc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ if(CONFIG_COMP_MFCC STREQUAL "m" AND DEFINED CONFIG_LLEXT)
add_subdirectory(llext ${PROJECT_BINARY_DIR}/mfcc_llext)
add_dependencies(app mfcc)
else()
add_local_sources(sof mfcc.c mfcc_setup.c mfcc_common.c mfcc_generic.c mfcc_hifi4.c mfcc_hifi3.c)
add_local_sources(sof mfcc.c mfcc_setup.c mfcc_common.c mfcc_generic.c mfcc_hifi4.c mfcc_hifi3.c mfcc_vad.c)
if(CONFIG_IPC_MAJOR_4)
add_local_sources(sof mfcc_ipc4.c)
endif()
endif()
153 changes: 86 additions & 67 deletions src/audio/mfcc/mfcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <sof/audio/format.h>
#include <sof/audio/pipeline.h>
#include <sof/audio/ipc-config.h>
#include <module/audio/source_api.h>
#include <module/audio/sink_api.h>
#include <sof/common.h>
#include <rtos/panic.h>
#include <sof/ipc/msg.h>
Expand All @@ -36,29 +38,31 @@ LOG_MODULE_REGISTER(mfcc, CONFIG_SOF_LOG_LEVEL);

SOF_DEFINE_REG_UUID(mfcc);

__cold_rodata const struct mfcc_func_map mfcc_fm[] = {
/** \brief Source/sink API based source copy function map. */
struct mfcc_source_func_map {
uint8_t source;
mfcc_source_func func;
};

__cold_rodata static const struct mfcc_source_func_map mfcc_sfm[] = {
#if CONFIG_FORMAT_S16LE
{SOF_IPC_FRAME_S16_LE, mfcc_s16_default},
#endif /* CONFIG_FORMAT_S16LE */
{SOF_IPC_FRAME_S16_LE, mfcc_source_copy_s16},
#endif
#if CONFIG_FORMAT_S24LE
{SOF_IPC_FRAME_S24_4LE, mfcc_s24_default},
#endif /* CONFIG_FORMAT_S24LE */
{SOF_IPC_FRAME_S24_4LE, mfcc_source_copy_s24},
#endif
#if CONFIG_FORMAT_S32LE
{SOF_IPC_FRAME_S32_LE, mfcc_s32_default},
#endif /* CONFIG_FORMAT_S32LE */
{SOF_IPC_FRAME_S32_LE, mfcc_source_copy_s32},
#endif
};

static mfcc_func mfcc_find_func(enum sof_ipc_frame source_format,
enum sof_ipc_frame sink_format,
const struct mfcc_func_map *map,
int n)
static mfcc_source_func mfcc_find_source_func(enum sof_ipc_frame source_format)
{
int i;

/* Find suitable processing function from map. */
for (i = 0; i < n; i++) {
if (source_format == map[i].source)
return map[i].func;
for (i = 0; i < ARRAY_SIZE(mfcc_sfm); i++) {
if (source_format == mfcc_sfm[i].source)
return mfcc_sfm[i].func;
}

return NULL;
Expand Down Expand Up @@ -97,56 +101,47 @@ static int mfcc_free(struct processing_module *mod)
struct mfcc_comp_data *cd = module_get_private_data(mod);

comp_info(mod->dev, "entry");
ipc_msg_free(cd->msg);
cd->msg = NULL;
mod_data_blob_handler_free(mod, cd->model_handler);
mfcc_free_buffers(mod);
mod_free(mod, cd);
return 0;
}

static int mfcc_get_config(struct processing_module *mod,
uint32_t config_id, uint32_t *data_offset_size,
uint8_t *fragment, size_t fragment_size)
{
struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment;
struct mfcc_comp_data *cd = module_get_private_data(mod);

comp_info(mod->dev, "entry");

return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size);
}

static int mfcc_set_config(struct processing_module *mod, uint32_t config_id,
enum module_cfg_fragment_position pos, uint32_t data_offset_size,
const uint8_t *fragment, size_t fragment_size, uint8_t *response,
size_t response_size)
{
struct mfcc_comp_data *cd = module_get_private_data(mod);

comp_info(mod->dev, "entry");

return comp_data_blob_set(cd->model_handler, pos, data_offset_size,
fragment, fragment_size);
}

/**
* \brief Source/sink API based process function for MFCC.
*
* Reads input audio from sof_source, runs the STFT/Mel/DCT stage, and
* delegates output formatting and commit handling to mfcc_common.c.
*/
static int mfcc_process(struct processing_module *mod,
struct input_stream_buffer *input_buffers, int num_input_buffers,
struct output_stream_buffer *output_buffers, int num_output_buffers)
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks)
{
struct mfcc_comp_data *cd = module_get_private_data(mod);
struct audio_stream *source = input_buffers->data;
struct audio_stream *sink = output_buffers->data;
int frames = input_buffers->size;

comp_dbg(mod->dev, "start");

frames = MIN(frames, cd->max_frames);
cd->mfcc_func(mod, input_buffers, output_buffers, frames);

/* TODO: use module_update_buffer_position() from #6194 */
input_buffers->consumed += audio_stream_frame_bytes(source) * frames;
output_buffers->size += audio_stream_frame_bytes(sink) * frames;
comp_dbg(mod->dev, "done");
return 0;
struct comp_dev *dev = mod->dev;
struct mfcc_state *state = &cd->state;
size_t source_avail;
int frames;
int num_ceps;

comp_dbg(dev, "start");
source_avail = source_get_data_frames_available(sources[0]);
frames = MIN(source_avail, cd->max_frames);
if (frames == 0)
return -ENODATA;

/* Copy input audio from source to MFCC internal circular buffer */
cd->source_func(sources[0], &state->buf, &state->emph, frames, state->source_channel);
Comment thread
singalsu marked this conversation as resolved.

/* Run STFT and Mel/DCT processing */
num_ceps = mfcc_stft_process(mod, cd);
if (num_ceps < 0)
return num_ceps;

return mfcc_process_output(mod, cd, sources, sinks, num_ceps, frames);
}

static int mfcc_prepare(struct processing_module *mod,
Expand Down Expand Up @@ -187,22 +182,41 @@ static int mfcc_prepare(struct processing_module *mod,
audio_stream_get_channels(&sourceb->stream));
if (ret < 0) {
comp_err(dev, "setup failed.");
goto err;
return ret;
}
} else {
comp_err(dev, "configuration is missing.");
return -EINVAL;
}

cd->mfcc_func = mfcc_find_func(source_format, sink_format, mfcc_fm, ARRAY_SIZE(mfcc_fm));
if (!cd->mfcc_func) {
comp_err(dev, "No proc func");
ret = -EINVAL;
goto err;
cd->source_func = mfcc_find_source_func(source_format);
if (!cd->source_func) {
comp_err(dev, "No source func");
mfcc_free_buffers(mod);
return -EINVAL;
}

return 0;
cd->source_format = source_format;

err:
comp_set_state(dev, COMP_TRIGGER_RESET);
return ret;
if (cd->config->compress_output)
comp_info(dev, "compress PCM output mode enabled");

if (cd->config->enable_dtx && !cd->config->compress_output)
comp_warn(dev, "enable_dtx ignored in normal PCM mode, only applies to compress");

/* Initialize VAD switch control notification if enabled */
if (cd->config->enable_vad && cd->config->update_controls) {
if (!cd->msg) {
ret = mfcc_ipc_notification_init(mod);
if (ret < 0) {
mfcc_free_buffers(mod);
return ret;
}
}
}

cd->vad_prev = false;
return 0;
}

static int mfcc_reset(struct processing_module *mod)
Expand All @@ -211,8 +225,13 @@ static int mfcc_reset(struct processing_module *mod)

comp_info(mod->dev, "entry");

/* Free MFCC buffers to prevent leaks on reset->prepare cycles.
* mfcc_free_buffers() NULLs the pointers after free.
*/
mfcc_free_buffers(mod);

/* Reset to similar state as init() */
cd->mfcc_func = NULL;
cd->source_func = NULL;
return 0;
}

Expand All @@ -221,7 +240,7 @@ static const struct module_interface mfcc_interface = {
.free = mfcc_free,
.set_configuration = mfcc_set_config,
.get_configuration = mfcc_get_config,
.process_audio_stream = mfcc_process,
.process = mfcc_process,
.prepare = mfcc_prepare,
.reset = mfcc_reset,
};
Expand Down
Loading
Loading