Skip to content

Commit 8b278b4

Browse files
committed
Audio: Selector: Add script to create downmix and upmix configurations
This patch adds script Octave tune/sof_selector_blobs.m. The script execute is also added to scripts/sof-rebuild-processing-comp-blobs.sh. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 0a70397 commit 8b278b4

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

scripts/sof-rebuild-processing-comp-blobs.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_iir_bandsplit
3939
cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_spk_eq.m
4040
cd "$SOF_WORKSPACE"/sof/src/audio/multiband_drc/tune; $OCTAVE sof_example_multiband_drc.m
4141
cd "$SOF_WORKSPACE"/sof/src/audio/tdfb/tune; ./sof_example_all.sh
42+
cd "$SOF_WORKSPACE"/sof/src/audio/selector/tune; $OCTAVE ./sof_selector_blobs.m
4243
cd "$SOF_WORKSPACE"/sof/tools/tune/mfcc; $OCTAVE setup_mfcc.m
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
% Export configuration blobs for Selector
2+
3+
% SPDX-License-Identifier: BSD-3-Clause
4+
%
5+
% Copyright (c) 2025, Intel Corporation.
6+
7+
function sof_selector_blobs()
8+
9+
% See ITU-R BS.775-4 for mix coefficient values
10+
sof_selector_paths(true);
11+
12+
% Matrix for 1:1 pass-through
13+
sel.rsvd0 = 0;
14+
sel.rsvd1 = 0;
15+
sel.coeffs = diag(ones(8, 1));
16+
write_blob(sel, "passthrough");
17+
18+
% Stereo to mono downmix
19+
sel.coeffs = zeros(8,8);
20+
sel.coeffs(1, 1) = 0.7071;
21+
sel.coeffs(1, 2) = 0.7071;
22+
write_blob(sel, "downmix_stereo_to_mono");
23+
24+
% 5.1 to stereo downmix
25+
fl = 1; fr = 2; fc = 3; lfe = 4; sl = 5; sr = 6;
26+
m = zeros(8,8);
27+
m(1, fl) = 1.0000; m(1, fr) = 0.0000; m(1, fc) = 0.7071; m(1, sl) = 0.7071; m(1, sr) = 0.0000;
28+
m(2, fl) = 0.0000; m(2, fr) = 1.0000; m(2, fc) = 0.7071; m(2, sl) = 0.0000; m(2, sr) = 0.7071;
29+
sel.coeffs = m;
30+
write_blob(sel, "downmix_51_to_stereo");
31+
sel.coeffs(1, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to left
32+
sel.coeffs(2, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to right
33+
write_blob(sel, "downmix_51_to_stereo_with_lfe");
34+
35+
% 5.1 to mono downmix
36+
fl = 1; fr = 2; fc = 3; lfe = 4; sl = 5; sr = 6;
37+
m = zeros(8,8);
38+
m(1, fl) = 0.7071; m(1, fr) = 0.7071; m(1, fc) = 1.0000; m(1, sl) = 0.5000; m(1, sr) = 0.5000;
39+
sel.coeffs = m;
40+
write_blob(sel, "downmix_51_to_mono");
41+
sel.coeffs(1, lfe) = 10^(+10/20);
42+
write_blob(sel, "downmix_51_to_mono_with_lfe");
43+
44+
% 7.1 to 5.1 downmix
45+
fl8 = 1; fr8 = 2; fc8 = 3; lfe8 = 4; bl8 = 5; br8 = 6; sl8 = 7; sr8 = 8;
46+
fl6 = 1; fr6 = 2; fc6 = 3; lfe6 = 4; sl6 = 5; sr6 = 6;
47+
m = zeros(8,8);
48+
m(fl6, fl8) = 1;
49+
m(fr6, fr8) = 1;
50+
m(fc6, fc8) = 1;
51+
m(sl6, sl8) = 1;
52+
m(sr6, sr8) = 1;
53+
m(sl6, bl8) = 1;
54+
m(sr6, br8) = 1;
55+
m(lfe6, lfe8) = 1;
56+
sel.coeffs = m;
57+
write_blob(sel, "downmix_71_to_51");
58+
59+
% 7.1 to 5.1 downmix
60+
fl = 1; fr = 2; fc = 3; lfe = 4; bl = 5; br = 6; sl = 7; sr = 8;
61+
m = zeros(8,8);
62+
m(1, fl) = 1.0000; m(1, fr) = 0.0000; m(1, fc) = 0.7071; m(1, sl) = 0.7071; m(1, sr) = 0.0000; m(1, bl) = 0.7071; m(1, br) = 0.0000;
63+
m(2, fl) = 0.0000; m(2, fr) = 1.0000; m(2, fc) = 0.7071; m(2, sl) = 0.0000; m(2, sr) = 0.7071; m(2, bl) = 0.0000; m(2, br) = 0.7071;
64+
sel.coeffs = m;
65+
write_blob(sel, "downmix_71_to_stereo");
66+
sel.coeffs(1, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to left
67+
sel.coeffs(2, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to right
68+
write_blob(sel, "downmix_71_to_stereo_with_lfe");
69+
70+
% 7.1 to mono downmix
71+
fl = 1; fc = 3; fr = 2; sr = 8; br = 6; bl = 5; sl = 7; lfe = 4;
72+
m = zeros(8,8);
73+
m(1, fl) = 0.7071; m(1, fr) = 0.7071; m(1, fc) = 1.0000; m(1, sl) = 0.5000; m(1, sr) = 0.5000; m(1, bl) = 0.5000; m(1, br) = 0.5000;
74+
sel.coeffs = m;
75+
write_blob(sel, "downmix_71_to_mono");
76+
m(1, lfe) = 10^(+19/20); % +10 dB
77+
write_blob(sel, "downmix_71_to_mono_with_lfe");
78+
79+
% mono to stereo upmix
80+
sel.coeffs = zeros(8,8);
81+
sel.coeffs(1, 1) = 10^(-3/20);
82+
sel.coeffs(2, 1) = 10^(-3/20);
83+
write_blob(sel, "upmix_mono_to_stereo");
84+
85+
% mono to 5.1 / 7.1 upmix
86+
fc = 3
87+
sel.coeffs = zeros(8,8);
88+
sel.coeffs(fc, 1) = 1;
89+
write_blob(sel, "upmix_mono_to_51");
90+
write_blob(sel, "upmix_mono_to_71");
91+
92+
% stereo to 5.1 / 7.1 upmix
93+
fl = 1; fr = 2;
94+
sel.coeffs = zeros(8,8);
95+
sel.coeffs(fl, 1) = 1;
96+
sel.coeffs(fr, 2) = 1;
97+
write_blob(sel, "upmix_stereo_to_51");
98+
write_blob(sel, "upmix_stereo_to_71");
99+
100+
sof_selector_paths(false);
101+
end
102+
103+
function write_blob(sel, blobname)
104+
str_config = "selector_config";
105+
str_exported = "Exported with script sof_selector_blobs.m";
106+
str_howto = "cd tools/tune/selector; octave sof_selector_blobs.m"
107+
sof_tools = '../../../../tools';
108+
sof_tplg = fullfile(sof_tools, 'topology');
109+
sof_tplg_selector = fullfile(sof_tplg, 'topology2/include/components/micsel');
110+
111+
sel
112+
113+
sum_coefs = sum(sel.coeffs, 2)'
114+
max_sum_coef = max(sum_coefs)
115+
if max_sum_coef > 1
116+
scale = 1 / max_sum_coef;
117+
else
118+
scale = 1;
119+
end
120+
121+
scale
122+
sel.coeffs = scale .* sel.coeffs';
123+
124+
blob8 = sof_selector_build_blob(sel);
125+
tplg2_fn = sprintf("%s/%s.conf", sof_tplg_selector, blobname);
126+
sof_check_create_dir(tplg2_fn);
127+
sof_tplg2_write(tplg2_fn, blob8, str_config, str_exported, str_howto);
128+
end
129+
130+
function sof_selector_paths(enable)
131+
132+
common = '../../../../tools/tune/common';
133+
if enable
134+
addpath(common);
135+
else
136+
rmpath(common);
137+
end
138+
end
139+
140+
function blob8 = sof_selector_build_blob(sel)
141+
142+
s = size(sel.coeffs);
143+
blob_type = 0;
144+
blob_param_id = 0; % IPC4_SELECTOR_COEFFS_CONFIG_ID
145+
data_length = s(1) * s(2) + 2;
146+
data_size = 2 * data_length; % int16_t matrix
147+
coeffs_vec = reshape(sel.coeffs, 1, []); % convert to row vector
148+
coeffs_q10 = int16(round(coeffs_vec .* 1024)); % Q6.10
149+
ipc_ver = 4;
150+
[abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver, blob_type, blob_param_id);
151+
blob_size = data_size + abi_size;
152+
blob8 = uint8(zeros(1, blob_size));
153+
blob8(1:abi_size) = abi_bytes;
154+
j = abi_size + 1;
155+
156+
% header
157+
blob8(j:j+1) = int16_to_byte(int16(sel.rsvd0));
158+
j = j + 2;
159+
blob8(j:j+1) = int16_to_byte(int16(sel.rsvd1));
160+
j = j + 2;
161+
162+
% coeffs matrix
163+
for i = 1:(s(1) * s(2))
164+
blob8(j:j+1) = int16_to_byte(coeffs_q10(i));
165+
j = j + 2;
166+
end
167+
end
168+
169+
function bytes = int16_to_byte(word)
170+
sh = [0 -8];
171+
bytes = uint8(zeros(1,2));
172+
bytes(1) = bitand(bitshift(word, sh(1)), 255);
173+
bytes(2) = bitand(bitshift(word, sh(2)), 255);
174+
end

0 commit comments

Comments
 (0)