diff --git a/posix/include/rtos/panic.h b/posix/include/rtos/panic.h index 65b06a1cab43..ca0578c51fa9 100644 --- a/posix/include/rtos/panic.h +++ b/posix/include/rtos/panic.h @@ -33,12 +33,13 @@ void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info); void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, uintptr_t *data) SOF_NORETURN; -void __panic(uint32_t p, char *filename, uint32_t linenum) SOF_NORETURN; +void __panic(uint32_t p, const char *filename, uint32_t linenum) SOF_NORETURN; /** panic dump filename and linenumber of the call * * \param x panic code defined in ipc/trace.h */ + #define sof_panic(x) __panic((x), (RELATIVE_FILE), (__LINE__)) /* runtime assertion */ diff --git a/src/debug/panic.c b/src/debug/panic.c index 8bcb1a2a1176..0c56886e386a 100644 --- a/src/debug/panic.c +++ b/src/debug/panic.c @@ -112,7 +112,7 @@ void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, ; } -void __panic(uint32_t panic_code, char *filename, uint32_t linenum) +void __panic(uint32_t panic_code, const char *filename, uint32_t linenum) { struct sof_ipc_panic_info panicinfo = { .linenum = linenum }; const unsigned int length_max = sizeof(panicinfo.filename); diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index cc143acd6532..650d2caf9854 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -365,7 +365,7 @@ static inline int audio_stream_set_params(struct audio_stream *buffer, if (!params) return -EINVAL; - buffer->runtime_stream_params.frame_fmt = params->frame_fmt; + buffer->runtime_stream_params.frame_fmt = (enum sof_ipc_frame)params->frame_fmt; buffer->runtime_stream_params.rate = params->rate; buffer->runtime_stream_params.channels = params->channels; @@ -990,8 +990,8 @@ static inline void audio_stream_fmt_conversion(enum ipc4_bit_depth depth, * IPC4_DEPTH_24BIT (24) <---> SOF_IPC_FRAME_S24_4LE (1) * IPC4_DEPTH_32BIT (32) <---> SOF_IPC_FRAME_S32_LE (2) */ - *frame_fmt = (depth >> 3) - 2; - *valid_fmt = (valid >> 3) - 2; + *frame_fmt = (enum sof_ipc_frame)((depth >> 3) - 2); + *valid_fmt = (enum sof_ipc_frame)((valid >> 3) - 2); #ifdef CONFIG_FORMAT_U8 if (depth == 8) diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 285a9bee93b4..b4c1deace1ab 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -913,6 +913,8 @@ static const struct ipc4_module_uuid uuid_map[] = { .d = { 0x8d, 0x3f, 0xf9, 0x2c, 0xd5, 0xc4, 0x3c, 0x09 }}}, /* mixin */ {0x3, {.a = 0x3c56505a, .b = 0x24d7, .c = 0x418f, .d = { 0xbd, 0xdc, 0xc1, 0xf5, 0xa3, 0xac, 0x2a, 0xe0 }}}, /* mixout */ + {0x95, {.a = 0x7ae671a7, .b = 0x4617, .c = 0x4a09, + .d = { 0xbf, 0x6d, 0x9d, 0x29, 0xc9, 0x98, 0xdb, 0xc1 }}}, /* noise suppresion */ {0x96, {.a = 0xe2b6031c, .b = 0x47e8, .c = 0x11ed, .d = { 0x07, 0xa9, 0x7f, 0x80, 0x1b, 0x6e, 0xfa, 0x6c }}}, /* host SHM write */ {0x98, {.a = 0xdabe8814, .b = 0x47e8, .c = 0x11ed, diff --git a/src/platform/library/panic.c b/src/platform/library/panic.c index 1276f3cc029e..bb481d69a36a 100644 --- a/src/platform/library/panic.c +++ b/src/platform/library/panic.c @@ -7,7 +7,7 @@ #include #include -void __panic(uint32_t p, char *filename, uint32_t linenum) +void __panic(uint32_t p, const char *filename, uint32_t linenum) { abort(); } diff --git a/test/cmocka/src/common_mocks.c b/test/cmocka/src/common_mocks.c index 93ebe414b92c..92ba58031680 100644 --- a/test/cmocka/src/common_mocks.c +++ b/test/cmocka/src/common_mocks.c @@ -112,7 +112,7 @@ int WEAK rstrlen(const char *s) return strlen(s); } -void WEAK __panic(uint32_t p, char *filename, uint32_t linenum) +void WEAK __panic(uint32_t p, const char *filename, uint32_t linenum) { fail_msg("panic: %s:%d (code 0x%x)\n", filename, linenum, p); exit(EXIT_FAILURE); diff --git a/tools/plugin/CMakeLists.txt b/tools/plugin/CMakeLists.txt index f5a8ade5f8cc..a137a4b7d04c 100644 --- a/tools/plugin/CMakeLists.txt +++ b/tools/plugin/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) -project(SOF_PLUGIN C) +project(SOF_PLUGIN C CXX) include(../../scripts/cmake/misc.cmake) include(CheckCCompilerFlag) diff --git a/tools/plugin/README.md b/tools/plugin/README.md index 518fff713dad..78874d2ba15a 100644 --- a/tools/plugin/README.md +++ b/tools/plugin/README.md @@ -34,7 +34,7 @@ cmake --build build-plugin/ then (use default ALSA prefix atm) ``` -sudo make install +sudo cmake --install build-plugin/ Make sure to set the LD_LIBRARY_PATH to include directory where the SOF modules are installed Ex: "~/work/sof/sof/build_plugin/sof_ep/install/lib:~/work/sof/sof/build_plugin/modules/" @@ -76,6 +76,31 @@ Mixer settings can be adjusted for bdw-nocodec by (Not functional yet) alsamixer -Dsof:tgl-nocodec:1 ``` +# Instructions for testing OpenVino noise suppression model with the SOF plugin: +1. Fetch the model from the Open Model zoo repository ex: noise-suppression-poconetlike-0001.xml + +https://docs.openvino.ai/archive/2023.0/omz_demos.html#build-the-demo-applications-on-linux + +2. Source OpenVino environment and get OpenCV +https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit-download.html + +3. Worth building and running the demo noise suppression application in the open model zoo +repository to make sure OpenVino and OpenCV are configured properly. + +4. Set environment variable NOISE_SUPPRESSION_MODEL_NAME to point to the model file +``` +export NOISE_SUPPRESSION_MODEL_NAME="~/open_model_zoo/demos/noise_suppression_demo/cpp/intel/noise-suppression-poconetlike-0001/FP16/noise-suppression-poconetlike-0001.xml" + +``` +5. Enable noise suppression by setting NOISE_SUPPRESSION=true in the tplg-targets for the sof-plugin topology + +6. Start capture using the following command. This uses the 16K capture from the DMIC from +PCM hw device 0,7. Currently, only 16K capture is supported but in the future this will be expanded +to work with 48K capture. +``` +arecord -Dsof:plugin:1:0:7:16k2c16b -f dat -r 16000 --period-size=2048 file_ns_16k.wa +``` + #TODO Items (and T-shirt size) for single pipeline E2E audio * IPC4 support in tplg parser (M) * IPC4 support in plugin (pipe/ipc4.c) (M) diff --git a/tools/plugin/alsaconf/50-sof.conf b/tools/plugin/alsaconf/50-sof.conf index 4d0232ecc596..91566ec28a55 100644 --- a/tools/plugin/alsaconf/50-sof.conf +++ b/tools/plugin/alsaconf/50-sof.conf @@ -33,6 +33,16 @@ pcm.sof { buffer_frames 192 } + config.16k2c16b { + rate 16000 + channels 2 + format S16_LE + period_time 0 + period_frames 2048 # based on the period size needed for Noise suppression module + buffer_time 0 + buffer_frames 8192 + } + config.48k8c16b { rate 48000 channels 8 diff --git a/tools/plugin/alsaplug/pcm.c b/tools/plugin/alsaplug/pcm.c index f6aef645ce56..f4b3439d865b 100644 --- a/tools/plugin/alsaplug/pcm.c +++ b/tools/plugin/alsaplug/pcm.c @@ -702,6 +702,8 @@ static int plug_pcm_hw_free(snd_pcm_ioplug_t *io) sem_close(pcm->ready[pipe_info->instance_id].sem); sem_close(pcm->done[pipe_info->instance_id].sem); } + + return 0; } static const snd_pcm_ioplug_callback_t sof_playback_callback = { diff --git a/tools/plugin/alsaplug/tplg.c b/tools/plugin/alsaplug/tplg.c index 5b67b47aedfc..ccbef36c6e9e 100644 --- a/tools/plugin/alsaplug/tplg.c +++ b/tools/plugin/alsaplug/tplg.c @@ -292,31 +292,27 @@ static int plug_new_process(snd_sof_plug_t *plug) { struct tplg_context *ctx = &plug->tplg; struct tplg_comp_info *comp_info = ctx->current_comp_info; - struct sof_ipc_comp_process *process; + struct ipc4_base_module_cfg basecfg; struct snd_soc_tplg_ctl_hdr *tplg_ctl; int ret; - process = calloc(MAX_TPLG_OBJECT_SIZE, 1); - if (!process) + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + /* only base config supported for now. extn support will be added later */ + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) return -ENOMEM; - comp_info->ipc_payload = process; + /* FIXME: move this to when the widget is actually set up */ + comp_info->instance_id = plug->instance_ids[SND_SOC_TPLG_DAPM_EFFECT]++; + comp_info->module_id = 0x95; - tplg_ctl = calloc(ctx->hdr->payload_size, 1); - if (!tplg_ctl) { - free(process); - return -ENOMEM; - } + plug_setup_widget_ipc_msg(comp_info); - ret = tplg_new_process(ctx, process, MAX_TPLG_OBJECT_SIZE, - tplg_ctl, ctx->hdr->payload_size); - if (ret < 0) { - SNDERR("error: failed to create PGA\n"); - goto out; - } -out: - free(tplg_ctl); - return ret; + return 0; } static int plug_new_pipeline(snd_sof_plug_t *plug) @@ -699,13 +695,10 @@ static int plug_match_audio_format(snd_sof_plug_t *plug, struct tplg_comp_info * (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; base_cfg->audio_fmt.s_type = (fmt->audio_fmt.fmt_cfg & MASK(23, 16)) >> 16; - base_cfg->ibs = fmt->buffer_size; - /* - * FIXME: is this correct? Choose ALSA period size for obs so that the buffer sizes - * will set accodingly. Need to get channel count and format from output format - */ - base_cfg->obs = plug->period_size * 2 * 2; + /* Choose ALSA period size for ibs/obs so that the buffer sizes will be set accordingly */ + base_cfg->ibs = plug->period_size * 2; + base_cfg->obs = plug->period_size * 2; return 0; } @@ -1022,7 +1015,7 @@ static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_in struct list_item *item; int ret; - /* for playback */ + /* for capture */ list_for_item(item, &plug->route_list) { struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, item); @@ -1045,8 +1038,8 @@ static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_in /* and then continue up the path */ if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_IN && route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { - ret = plug_prepare_widgets(plug, pcm_info, starting_comp_info, - route_info->source); + ret = plug_prepare_widgets_capture(plug, pcm_info, starting_comp_info, + route_info->source); if (ret < 0) return ret; } @@ -1199,7 +1192,8 @@ static int plug_set_up_widgets_capture(snd_sof_plug_t *plug, /* and then continue down the path */ if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_IN && route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { - ret = plug_set_up_widgets(plug, starting_comp_info, route_info->source); + ret = plug_set_up_widgets_capture(plug, starting_comp_info, + route_info->source); if (ret < 0) return ret; } @@ -1389,7 +1383,8 @@ static int plug_free_widgets_capture(snd_sof_plug_t *plug, /* and then continue down the path */ if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN && route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { - ret = plug_free_widgets(plug, starting_comp_info, route_info->source); + ret = plug_free_widgets_capture(plug, starting_comp_info, + route_info->source); if (ret < 0) return ret; } @@ -1409,7 +1404,10 @@ int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipelin pcm_info = container_of(item, struct tplg_pcm_info, item); if (pcm_info->id == plug->pcm_id) { - host = pcm_info->playback_host; /* FIXME */ + if (dir) + host = pcm_info->capture_host; + else + host = pcm_info->playback_host; break; } } @@ -1420,6 +1418,11 @@ int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipelin } if (dir) { + ret = plug_free_widgets_capture(plug, host, host); + if (ret < 0) { + SNDERR("failed to free widgets for capture PCM %d\n", plug->pcm_id); + return ret; + } } else { ret = plug_free_widgets(plug, host, host); if (ret < 0) { diff --git a/tools/plugin/modules/CMakeLists.txt b/tools/plugin/modules/CMakeLists.txt index dfd7105c072e..507f183d97a1 100644 --- a/tools/plugin/modules/CMakeLists.txt +++ b/tools/plugin/modules/CMakeLists.txt @@ -55,3 +55,5 @@ set_target_properties(sof_mod_alsa INSTALL_RPATH "${sof_install_directory}/alsa-lib" INSTALL_RPATH_USE_LINK_PATH TRUE ) + +add_subdirectory(ov_noise_suppression) diff --git a/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt b/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt new file mode 100644 index 000000000000..1e6e0f47aea2 --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Noise suppression module +find_package(OpenVINO COMPONENTS Runtime) + +if(OpenVINO_FOUND) +add_library(sof_ns_interface STATIC noise_suppression_interface.cpp) +target_link_libraries(sof_ns_interface PRIVATE -Wl,--export-dynamic) +target_link_libraries(sof_ns_interface PRIVATE openvino::runtime) +target_compile_options(sof_ns_interface PRIVATE -fPIC) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/posix/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/arch/host/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/platform/posix/include) +set_target_properties(sof_ns_interface PROPERTIES LINKER_LANGUAGE CXX) +sof_append_relative_path_definitions(sof_ns_interface) +install(TARGETS sof_ns_interface DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +add_library(sof_ns MODULE noise_suppression.c) +target_link_libraries(sof_ns PRIVATE sof_ns_interface) +target_link_libraries(sof_ns PRIVATE -Wl,--export-dynamic) +sof_append_relative_path_definitions(sof_ns) +target_compile_options(sof_ns PRIVATE -DPIC -g -O3 -Wl,-EL -Wall -Werror -DCONFIG_LIBRARY -imacros${config_h}) +install(TARGETS sof_ns DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_include_directories(sof_ns PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../pipe + ${sof_source_directory}/src/audio) + + +target_link_options(sof_ns PRIVATE -Wl,--export-dynamic) +target_include_directories(sof_ns PRIVATE ${sof_install_directory}/include) +target_include_directories(sof_ns PRIVATE ${parser_install_dir}/include) + +set_target_properties(sof_ns + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) +endif() diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression.c b/tools/plugin/modules/ov_noise_suppression/noise_suppression.c new file mode 100644 index 000000000000..1dd6b26ddea2 --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "noise_suppression_interface.h" + +LOG_MODULE_REGISTER(ns, CONFIG_SOF_LOG_LEVEL); + +/* 7ae671a7-4617-4a09-bf6d-9d29c998dbc1 */ +DECLARE_SOF_RT_UUID("ns", ns_comp_uuid, 0x7ae671a7, 0x4617, + 0x4a09, 0xbf, 0x6d, 0x9d, 0x29, 0xc9, 0x98, 0xdb, 0xc1); + +DECLARE_TR_CTX(ns_comp_tr, SOF_UUID(ns_comp_uuid), LOG_LEVEL_INFO); + +static int ns_free(struct processing_module *mod) +{ + ns_handle handle = module_get_private_data(mod); + + ov_ns_free(handle); + return 0; +} + +static int ns_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + + return ov_ns_init(&mod_data->private); +} + +static int +ns_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) +{ + ns_handle handle = module_get_private_data(mod); + int ret; + + ret = ov_ns_process(handle, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); + if (ret < 0) + return ret; + + module_update_buffer_position(&input_buffers[0], &output_buffers[0], ret); + + return 0; +} + +static const struct module_interface ns_interface = { + .init = ns_init, + .process_audio_stream = ns_process, + .free = ns_free +}; + +DECLARE_MODULE_ADAPTER(ns_interface, ns_comp_uuid, ns_comp_tr); +SOF_MODULE_INIT(ns, sys_comp_module_ns_interface_init); diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp new file mode 100644 index 000000000000..0c401c94b10e --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan + + +#include +#include +#include +#include + +#include "noise_suppression_interface.h" +#define NS_MAX_SOURCE_CHANNELS 2 + +extern "C" { + struct ns_data { + std::shared_ptr model; + std::vector> state_names; + ov::InferRequest infer_request[NS_MAX_SOURCE_CHANNELS]; + ov::Shape inp_shape; + int iter; + }; + + int ov_ns_init(ns_handle *handle) { + struct ns_data *nd; + ov::OutputVector inputs, outputs; + ov::Core core; + size_t state_size = 0; + const char* model_name = std::getenv("NOISE_SUPPRESSION_MODEL_NAME"); + int i; + + nd = new ns_data(); + if(!nd) + return -ENOMEM; + + *handle = nd; + nd->model = core.read_model(model_name); + inputs = nd->model->inputs(); + outputs = nd->model->outputs(); + + /* get state name pairs */ + for (size_t i = 0; i < inputs.size(); i++) { + std::string inp_state_name = inputs[i].get_any_name(); + if (inp_state_name.find("inp_state_") == std::string::npos) + continue; + + std::string out_state_name(inp_state_name); + out_state_name.replace(0, 3, "out"); + + /* find corresponding output state */ + if (outputs.end() == std::find_if(outputs.begin(), outputs.end(), [&out_state_name](const ov::Output& output) { + return output.get_any_name() == out_state_name; + })) + return -EINVAL; + + nd->state_names.emplace_back(inp_state_name, out_state_name); + + ov::Shape shape = inputs[i].get_shape(); + size_t tensor_size = std::accumulate(shape.begin(), shape.end(), 1, + std::multiplies()); + + state_size += tensor_size; + } + + if (!state_size) + return -EINVAL; + + /* + * compile the model for the CPU and save the infer_request objects for each + * channel separately + */ + ov::CompiledModel compiled_model = core.compile_model(nd->model, "CPU", {}); + for (i = 0; i < NS_MAX_SOURCE_CHANNELS; i++) + nd->infer_request[i] = compiled_model.create_infer_request(); + + nd->inp_shape = nd->model->input("input").get_shape(); + + return 0; + } + + void ov_ns_free(ns_handle handle) { + struct ns_data *nd = (struct ns_data *)handle; + + delete nd; + } + + int ov_ns_process(ns_handle handle, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers) + { + struct audio_stream *source = (struct audio_stream *)input_buffers[0].data; + struct audio_stream *sink = (struct audio_stream *)output_buffers[0].data; + struct ns_data *nd = (struct ns_data *)handle; + std::vector inp_wave_fp32, out_wave_fp32; + /* only 16-bit supported for now */ + int16_t *input_data = (int16_t *)audio_stream_get_rptr(source); + int16_t *output_data = (int16_t *)audio_stream_get_wptr(sink); + uint32_t frame_count = input_buffers[0].size; + float scale = 1.0f / std::numeric_limits::max(); + int i, j, ch; + + /* + * The noise suppression model only supports mono, so process each channel + * separately + */ + inp_wave_fp32.resize(frame_count, 0); + out_wave_fp32.resize(frame_count, 0); + + for (ch = 0; ch < NS_MAX_SOURCE_CHANNELS; ch++) { + /* split each channel samples and convert to floating point */ + for (i = ch, j = 0; j < frame_count; i+=2,j++) { + void *inp = &input_data[i]; + + /* wrap if needed */ + if (inp >= source->end_addr) + inp = (char *)source->addr + + ((char *)inp - (char *)source->end_addr); + + inp_wave_fp32[j] = (float)(*(int16_t *)inp) * scale; + } + + ov::Tensor input_tensor(ov::element::f32, nd->inp_shape, + &inp_wave_fp32[0]); + nd->infer_request[ch].set_tensor("input", input_tensor); + + for (auto& state_name: nd->state_names) { + const std::string& inp_state_name = state_name.first; + const std::string& out_state_name = state_name.second; + ov::Tensor state_tensor; + ov::Shape state_shape; + + state_shape = nd->model->input(inp_state_name).get_shape(); + if (nd->iter > 0) { + /* + * set input state by corresponding output state from prev + * infer + */ + state_tensor = + nd->infer_request[ch].get_tensor(out_state_name); + } else { + state_tensor = ov::Tensor(ov::element::f32, state_shape); + std::memset(state_tensor.data(), 0, + state_tensor.get_byte_size()); + } + nd->infer_request[ch].set_tensor(inp_state_name, state_tensor); + } + nd->infer_request[ch].infer(); + + /* process output */ + float* src = nd->infer_request[ch].get_tensor("output").data(); + float* dst = &out_wave_fp32[0]; + std::memcpy(dst, src, frame_count * sizeof(float)); + + /* convert back to int and write back to output buffer */ + for (i = 0, j = ch; i < frame_count; i++,j+=2) { + float v = out_wave_fp32[i]; + void *out = &output_data[j]; + + /* wrap if needed */ + if (out >= sink->end_addr) + out = (char *)sink->addr + + ((char *)out - (char *)sink->end_addr); + + v = std::clamp(v, -1.0f, +1.0f); + *(int16_t *)out = (int16_t)(v * std::numeric_limits::max()); + } + } + + nd->iter++; + + /* return frame_count so the input and output buffers can be updated accordingly */ + return frame_count; + } +} /* extern "C" */ + diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h new file mode 100644 index 000000000000..5005e1f58161 --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan + * + */ + +#ifndef _NOISE_SUPPRESSION_INTERFACE_H +#define _NOISE_SUPPRESSION_INTERFACE_H + +#ifdef __cplusplus +extern "C" { +#endif + typedef void *ns_handle; + int ov_ns_init(ns_handle *handle); + void ov_ns_free(ns_handle handle); + int ov_ns_process(ns_handle handle, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers); + +#ifdef __cplusplus +} +#endif + +#endif /*_NOISE_SUPPRESSION_INTERFACE_H */ diff --git a/tools/plugin/pipe/ipc4.c b/tools/plugin/pipe/ipc4.c index 9320eeef1999..2766d0c1dbbd 100644 --- a/tools/plugin/pipe/ipc4.c +++ b/tools/plugin/pipe/ipc4.c @@ -63,6 +63,7 @@ static const struct sof_pipe_module_library_map library_map[] = { {0x6, "libsof_volume.so"}, {0x2, "libsof_mixer.so"}, {0x3, "libsof_mixer.so"}, + {0x95, "libsof_ns.so"}, /*FIXME: hack for now to set up ALSA and SHM components */ {0x96, "libsof_mod_shm.so"}, /* host playback */ {0x97, "libsof_mod_alsa.so"}, /* dai playback */ diff --git a/tools/topology/topology2/development/sof-plugin.conf b/tools/topology/topology2/development/sof-plugin.conf index 23d52056fd45..ffa20de74ac8 100644 --- a/tools/topology/topology2/development/sof-plugin.conf +++ b/tools/topology/topology2/development/sof-plugin.conf @@ -25,6 +25,7 @@ + Object.Pipeline.io-gateway-capture [ { @@ -42,6 +43,7 @@ Object.Pipeline.io-gateway-capture [ num_input_audio_formats 1 Object.Base.input_audio_format [ { + in_rate 16000 in_bit_depth 16 in_valid_bit_depth 16 } @@ -49,6 +51,7 @@ Object.Pipeline.io-gateway-capture [ num_output_audio_formats 1 Object.Base.output_audio_format [ { + out_rate 16000 out_bit_depth 16 out_valid_bit_depth 16 } @@ -67,6 +70,7 @@ Object.Pipeline.host-gateway-capture [ num_input_audio_formats 1 Object.Base.input_audio_format [ { + in_rate 16000 in_bit_depth 16 in_valid_bit_depth 16 } @@ -74,6 +78,7 @@ Object.Pipeline.host-gateway-capture [ num_output_audio_formats 1 Object.Base.output_audio_format [ { + out_rate 16000 out_bit_depth 16 out_valid_bit_depth 16 } @@ -157,14 +162,35 @@ Object.PCM.pcm [ } ] +IncludeByKey.NOISE_SUPPRESSION { +"true" { + Object.Widget.ov_ns.1 { + index 9 + } + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "ov_ns.9.1" + } + { + source "ov_ns.9.1" + sink "host-copier.1.capture" + } + ] + } +"false" { + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "host-copier.1.capture" + } + ] + } +} Object.Base.route [ { source "host-copier.1.playback" sink "dai-copier.SSP.NoCodec-1.playback" } - { - source "dai-copier.SSP.NoCodec-1.capture" - sink "host-copier.1.capture" - } ] diff --git a/tools/topology/topology2/development/tplg-targets.cmake b/tools/topology/topology2/development/tplg-targets.cmake index e8a05ac2fa55..80b54d30f6c4 100644 --- a/tools/topology/topology2/development/tplg-targets.cmake +++ b/tools/topology/topology2/development/tplg-targets.cmake @@ -116,5 +116,5 @@ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-nocodec-crossover.bin,EFX_CROSSOVE PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-nocodec-rtcaec.bin" # Topology for SOF plugin -"development/sof-plugin\;sof-plugin" +"development/sof-plugin\;sof-plugin\;NOISE_SUPPRESSION=false" ) diff --git a/tools/topology/topology2/include/components/ov_noise_suppression.conf b/tools/topology/topology2/include/components/ov_noise_suppression.conf new file mode 100644 index 000000000000..ff06f1fedf6a --- /dev/null +++ b/tools/topology/topology2/include/components/ov_noise_suppression.conf @@ -0,0 +1,81 @@ +# +# OpenVino noise suppression module +# +# A noise suppression widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.ov_ns.N.attribute_name" +# +# Usage: this component can be used by declaring int a parent object. i.e. +# +# Object.Widget.ov_ns."N" { +# index 1 +# no_pm "true" +# } +# +# Where N is the unique instance number for ov_ns widget in the same alsaconf node. + +Class.Widget."ov_ns" { + # + # Pipeline ID for the ov_ns widget object + # + DefineAttribute."index" {} + + # + # ov_ns object instance + # + DefineAttribute."instance" {} + + #include common component definition + + + # Only 16-bit depth format is supported by ov_ns + num_input_audio_formats 1 + num_output_audio_formats 1 + # 16-bit 16KHz 2ch + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + Object.Base.output_audio_format [ + { + out_rate 16000 + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + + # Attribute categories + attributes { + # + # The ov_ns widget name would be constructed using the index and instance attributes. + # For ex: "ov_ns.1.1" or "ov_ns.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + "type" + ] + + # + # ov_ns widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for ov_ns widget + type "effect" + uuid "a7:71:e6:7a:17:46:09:4a:bf:6d:9d:29:c9:98:db:c1" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/xtos/include/rtos/panic.h b/xtos/include/rtos/panic.h index 90f19ad9326c..921ea710d88f 100644 --- a/xtos/include/rtos/panic.h +++ b/xtos/include/rtos/panic.h @@ -33,7 +33,7 @@ void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info); void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, uintptr_t *data) SOF_NORETURN; -void __panic(uint32_t p, char *filename, uint32_t linenum) SOF_NORETURN; +void __panic(uint32_t p, const char *filename, uint32_t linenum) SOF_NORETURN; /** panic dump filename and linenumber of the call *