Skip to content
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
1 change: 1 addition & 0 deletions src/arch/host/configs/library_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CONFIG_COMP_MULTIBAND_DRC=y
CONFIG_COMP_MUX=y
CONFIG_COMP_RTNR=y
CONFIG_COMP_SEL=y
CONFIG_COMP_SOUND_DOSE=y
CONFIG_COMP_SRC=y
CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y
CONFIG_COMP_STUBS=y
Expand Down
3 changes: 3 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_SMART_AMP)
add_subdirectory(smart_amp)
endif()
if(CONFIG_COMP_SOUND_DOSE)
add_subdirectory(sound_dose)
endif()
if(CONFIG_COMP_SRC)
add_subdirectory(src)
endif()
Expand Down
1 change: 1 addition & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ rsource "nxp/Kconfig"
rsource "rtnr/Kconfig"
rsource "selector/Kconfig"
rsource "smart_amp/Kconfig"
rsource "sound_dose/Kconfig"
rsource "src/Kconfig"
rsource "tdfb/Kconfig"
rsource "template/Kconfig"
Expand Down
12 changes: 12 additions & 0 deletions src/audio/eq_iir/tune/sof_eq_plot.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,17 @@ function sof_eq_plot(eq, fn)
eq.f, eq.iir_eq_db + offs_iir, '--',...
eq.f, eq.fir_eq_db + offs_fir, '--');
legend('Target', 'Combined', 'IIR', 'FIR', 'Location', 'NorthWest');
eq.diff_db = eq.tot_eq_db + offs_tot - eq.err_db_s;
end
if eq.enable_fir && eq.enable_iir == 0
semilogx(eq.f, eq.err_db_s, eq.f, eq.fir_eq_db + offs_fir);
legend('Target', 'FIR', 'Location', 'NorthWest');
eq.diff_db = eq.fir_eq_db + offs_fir - eq.err_db_s;
end
if eq.enable_fir == 0 && eq.enable_iir
semilogx(eq.f, eq.err_db_s, eq.f, eq.iir_eq_db + offs_iir);
legend('Target', 'IIR', 'Location', 'NorthWest');
eq.diff_db = eq.iir_eq_db + offs_iir - eq.err_db_s;
end
grid on;
ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 40)]);
Expand All @@ -91,6 +94,15 @@ function sof_eq_plot(eq, fn)
tstr = sprintf('Filter target vs. achieved response: %s', eq.name);
title(tstr);

fh=figure(fn); fn = fn+1;
semilogx(eq.f, eq.diff_db)
grid on;
ax=axis; axis([eq.p_fmin eq.p_fmax -5 5]);
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
tstr = sprintf('Response difference mean abs %.4f dB: %s', mean(abs(eq.diff_db)), eq.name);
title(tstr);

%% FIR filter
if length(eq.b_fir) > 1
% Response
Expand Down
19 changes: 15 additions & 4 deletions src/audio/eq_iir/tune/sof_export_c_eq_uint32t.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function sof_export_c_eq_uint32t(fn, blob8, vn, justeq)
function sof_export_c_eq_uint32t(fn, blob8, vn, justeq, howto)

% sof_export_c_eq_uint32t(fn, blob8, vn)
%
Expand All @@ -8,10 +8,11 @@ function sof_export_c_eq_uint32t(fn, blob8, vn, justeq)
% blob8 - blob data from EQ design
% vn - variable name
% justeq - export just the EQ wihtout ABI headers for direct use in FW
% howto - add a comment how the header file was created

% SPDX-License-Identifier: BSD-3-Clause
%
% Copyright (c) 2021, Intel Corporation. All rights reserved.
% Copyright (c) 2021-2025, Intel Corporation.

% Write blob
fh = fopen(fn, 'w');
Expand All @@ -23,10 +24,20 @@ function sof_export_c_eq_uint32t(fn, blob8, vn, justeq)
year = datestr(now, 'yyyy');
fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n');
fprintf(fh, ' *\n');
fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', year);
fprintf(fh, ' * Copyright(c) %s Intel Corporation.\n', year);
fprintf(fh, ' */\n');
fprintf(fh, '\n');

if nargin == 5
fprintf(fh, '/* Created %s with command:\n', datestr(now, 'yyyy-mm-dd'));
fprintf(fh, ' * %s\n */\n\n', howto);
end

fprintf(fh, '#include <stdint.h>\n\n');

% Drop 8 bytes TLV header
blob8 = blob8(9:end);

% Pad blob length to multiple of four bytes
n_orig = length(blob8);
n_new = ceil(n_orig/4);
Expand All @@ -53,7 +64,7 @@ function sof_export_c_eq_uint32t(fn, blob8, vn, justeq)
numbers_remain = n_new - numbers_in_line * full_lines;

n = 1;
fprintf(fh, 'uint32_t %s[%d] = {\n', vn, n_new);
fprintf(fh, 'static const uint32_t %s[%d] = {\n', vn, n_new);
for i = 1:full_lines
fprintf(fh, '\t');
for j = 1:numbers_in_line
Expand Down
10 changes: 10 additions & 0 deletions src/audio/sound_dose/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause

if(CONFIG_COMP_SOUND_DOSE STREQUAL "m")
add_subdirectory(llext ${PROJECT_BINARY_DIR}/sound_dose_llext)
add_dependencies(app sound_dose)
else()
add_local_sources(sof sound_dose.c)
add_local_sources(sof sound_dose-generic.c)
add_local_sources(sof sound_dose-ipc4.c)
endif()
15 changes: 15 additions & 0 deletions src/audio/sound_dose/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: BSD-3-Clause

config COMP_SOUND_DOSE
tristate "Sound Dose module"
default m if LIBRARY_DEFAULT_MODULAR
depends on COMP_MODULE_ADAPTER
depends on IPC_MAJOR_4
select MATH_IIR
select MATH_IIR_DF1
select MATH_EXP
help
Select this for Sound Dose SOF module. The purpose is
to calculate for audio playback MEL values (momentary
sound exposure level) to provide to user space the data
to compute the sound dose CSD as defined in EN 50332-3.
75 changes: 75 additions & 0 deletions src/audio/sound_dose/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
Sound Dose

The purpose of this component is to calculate with DSP offload the
headphone audio playback MEL values (momentary sound exposure level).
The calculated MEL values are notified to user space to be available
every one second. The user space should respond to notification with
bytes control get to get the data. The MEL values are used to
calculate the CSD value (cumulative sound dose). Low enough CSD value
ensures the music listening is safe the user's hearing.

The calculation of MEL values and CSD values is defined in EN 50332-3
stadard. The implementation in the Android OS is described in
https://source.android.com/docs/core/audio/sound-dose .

The SOF Sound Dose component should be placed in topology as last
component before playback dai-copier.

Currently it can be tested with next test topologies:
- sof-hda-benchmark-sound_dose32.tplg
- sof-mtl-sdw-benchmark-sound_dose32-sdw0.tplg
- sof-mtl-sdw-benchmark-sound_dose32-simplejack.tplg

E.g. in the sdw topologies the controls for setting it up can be
seen with command:

$ amixer -c0 controls | grep "Jack Out Sound Dose"
numid=33,iface=MIXER,name='Jack Out Sound Dose data bytes'
numid=32,iface=MIXER,name='Jack Out Sound Dose gain bytes'
numid=30,iface=MIXER,name='Jack Out Sound Dose setup bytes'
numid=31,iface=MIXER,name='Jack Out Sound Dose volume bytes'

The above topologies program the setup bytes for acoustical
sensitivity of acoustical 100 dBSPL for 0 dBFS digital level.
The gain is set to 0 dB and volume to 0 dB.

To test the basics copy a compatible test topology over the
normal topology file. Or alternative use module options
tplg_filename and tplg_path for module snd_sof.

Get kcontrol_events from https://github.com/ujfalusi/kcontrol_events
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ujfalusi please upstream this test too in here in a follow up PR. Thanks !

and build and install it.

Start playback of some music or test signal. Note that there is no SOF
volume control component in the test topology, so it plays out at max
volume.

Start in other console kcontrol_events. The control 'Jack Out Sound
Dose data bytes' should get updates every one second. The structures
are defined in src/include/user/audio_feature.h and
src/include/user/sound_dose.h.

The next steps require build of blobs for sof-ctl. The blobs can be
rebuilt with command

cd src/audio/sound_dose/tune; octave --quiet --no-window-system sof_sound_dose_blobs.m

To simulate effect of initial sensitivity setup, try command

sof-ctl -c name='Jack Out Sound Dose setup bytes' -s <path>/sound_dose/setup_sens_0db.txt
sof-ctl -c name='Jack Out Sound Dose setup bytes' -s <path>/sound_dose/setup_sens_100db.txt

To simulate adjusting codec volume control down 10 dB and up again 10 dB

sof-ctl -c name='Jack Out Sound Dose volume bytes' -s ctl4/sound_dose/setup_vol_-10db.txt
sof-ctl -c name='Jack Out Sound Dose volume bytes' -s ctl4/sound_dose/setup_vol_0db.txt

To force user's listening level 10 dB down after observing too large dose per the MSD value

sof-ctl -c name='Jack Out Sound Dose gain bytes' -s ctl4/sound_dose/setup_gain_-10db.txt

To restore user's listening level to non-attenuated

sof-ctl -c name='Jack Out Sound Dose gain bytes' -s ctl4/sound_dose/setup_gain_0db.txt

The above commands have impact to data shown by kcontrol_events.
9 changes: 9 additions & 0 deletions src/audio/sound_dose/llext/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025 Intel Corporation.
# SPDX-License-Identifier: Apache-2.0

sof_llext_build("sound_dose"
SOURCES ../sound_dose.c
../sound_dose-generic.c
../sound_dose-ipc4.c
LIB openmodules
)
6 changes: 6 additions & 0 deletions src/audio/sound_dose/llext/llext.toml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <tools/rimage/config/platform.toml>
#define LOAD_TYPE "2"
#include "../sound_dose.toml"

[module]
count = __COUNTER__
Loading
Loading