Skip to content

Commit 2c7b820

Browse files
singalsulgirdwood
authored andcommitted
Audio: STFT Process: Add script to export configuration blob
This patch adds script to create configuration blobs for STFT process module. A few blobs are created to be used with topology to test STFT. This is WIP. The blob format is not yet final. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent abaff48 commit 2c7b820

1 file changed

Lines changed: 185 additions & 0 deletions

File tree

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
% setup_stft_process()
2+
%
3+
% Create binary configuration blob for STFT_PROCESS component. The hex data
4+
% is written to tools/topology/topology1/m4/stft_process/stft_process_config.m4
5+
6+
% SPDX-License-Identifier: BSD-3-Clause
7+
%
8+
% Copyright (c) 2025, Intel Corporation.
9+
10+
function setup_stft_process(cfg)
11+
12+
cfg.tools_path = '../../../../tools/';
13+
cfg.tplg_path = [cfg.tools_path 'topology/topology2/include/components/stft_process/'];
14+
cfg.common_path = [cfg.tools_path 'tune/common'];
15+
cfg.tplg_ver = 2;
16+
cfg.ipc_ver = 4;
17+
cfg.channel = 0;
18+
cfg.sample_frequency = 48000;
19+
20+
cfg.frame_length = 192; % 4 ms
21+
cfg.frame_shift = 48; % 1 ms
22+
cfg.window_type = 'hann';
23+
cfg.tplg_fn = 'hann_192_48.conf';
24+
export_stft_process_setup(cfg);
25+
26+
cfg.frame_length = 512; % 10.7 ms
27+
cfg.frame_shift = 128; % 2.7 ms
28+
cfg.window_type = 'hann';
29+
cfg.tplg_fn = 'hann_512_128.conf';
30+
export_stft_process_setup(cfg);
31+
32+
cfg.frame_length = 768; % 16 ms
33+
cfg.frame_shift = 120; % 2.5 ms
34+
cfg.window_type = 'hann';
35+
cfg.tplg_fn = 'hann_768_120.conf';
36+
export_stft_process_setup(cfg);
37+
38+
cfg.frame_length = 1024; % 21.3 ms
39+
cfg.frame_shift = 256; % 5.3 ms
40+
cfg.window_type = 'hann';
41+
cfg.tplg_fn = 'hann_1024_256.conf';
42+
export_stft_process_setup(cfg);
43+
44+
cfg.frame_length = 1536; % 32 ms
45+
cfg.frame_shift = 240; % 5 ms
46+
cfg.window_type = 'hann';
47+
cfg.tplg_fn = 'hann_1536_240.conf';
48+
export_stft_process_setup(cfg);
49+
50+
end
51+
52+
function export_stft_process_setup(cfg)
53+
54+
% Use blob tool from EQ
55+
addpath(cfg.common_path);
56+
57+
% Blob size, size plus reserved(8) + current parameters
58+
nbytes_data = 64;
59+
60+
% Get ABI information
61+
[abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, cfg.ipc_ver);
62+
63+
% Initialize correct size uint8 array
64+
nbytes = nbytes_abi + nbytes_data;
65+
b8 = uint8(zeros(1,nbytes));
66+
67+
% Insert ABI header
68+
fprintf(1, 'STFT_PROCESS blob size is %d, ABI header is %d, data is %d\n',nbytes, nbytes_abi, nbytes_data);
69+
b8(1:nbytes_abi) = abi_bytes;
70+
j = nbytes_abi + 1;
71+
72+
% Apply default STFT_PROCESS configuration, first struct header and reserved, then data
73+
[b8, j] = add_w32b(nbytes_data, b8, j);
74+
for i = 1:8
75+
[b8, j] = add_w32b(0, b8, j);
76+
end
77+
78+
fft_length = cfg.frame_length;
79+
fft_hop = cfg.frame_shift;
80+
[window_idx, window_gain_comp] = get_window(cfg, fft_length, fft_hop);
81+
82+
v = q_convert(cfg.sample_frequency, 0); [b8, j] = add_w32b(v, b8, j);
83+
v = q_convert(window_gain_comp, 31); [b8, j] = add_w32b(v, b8, j);
84+
v = 0; [b8, j] = add_w32b(v, b8, j); % reserved
85+
v = cfg.channel; [b8, j] = add_w16b(v, b8, j);
86+
v = fft_length; [b8, j] = add_w16b(v, b8, j);
87+
v = fft_hop; [b8, j] = add_w16b(v, b8, j);
88+
v = 0; [b8, j] = add_w16b(v, b8, j); % reserved
89+
v = 0; [b8, j] = add_w32b(v, b8, j); % enum pad
90+
v = window_idx; [b8, j] = add_w32b(v, b8, j); % enum window
91+
92+
% Export
93+
switch cfg.tplg_ver
94+
case 2
95+
sof_tplg2_write([cfg.tplg_path cfg.tplg_fn], b8, "stft_process_config", ...
96+
"Exported STFT_PROCESS configuration", ...
97+
"cd tools/tune/stft_process; octave setup_stft_process.m");
98+
otherwise
99+
error("Illegal cfg.tplg_ver, use 2 topology v2.");
100+
end
101+
102+
rmpath(cfg.common_path);
103+
104+
end
105+
106+
%% Helper functions
107+
108+
function [idx, iwg] = get_window(cfg, len, hop)
109+
switch lower(cfg.window_type)
110+
case 'rectangular'
111+
win = boxcar(len);
112+
idx = 0;
113+
case 'blackman'
114+
win = blackman(len);
115+
idx = 1;
116+
case 'hamming'
117+
win = hamming(len);
118+
idx = 2;
119+
case 'hann'
120+
win = hann(len);
121+
idx = 3;
122+
case 'povey'
123+
idx = 4;
124+
n = 0:(len-1);
125+
win = ((1 - cos(2 * pi * n / len)) / 2).^0.85;
126+
otherwise
127+
error('Unknown window type');
128+
end
129+
iwg = hop / sum(win.^2);
130+
end
131+
132+
function bytes = w8b(word)
133+
bytes = uint8(zeros(1,1));
134+
bytes(1) = bitand(word, 255);
135+
end
136+
137+
function bytes = w16b(word)
138+
sh = [0 -8];
139+
bytes = uint8(zeros(1,2));
140+
bytes(1) = bitand(bitshift(word, sh(1)), 255);
141+
bytes(2) = bitand(bitshift(word, sh(2)), 255);
142+
end
143+
144+
function bytes = w32b(word)
145+
sh = [0 -8 -16 -24];
146+
bytes = uint8(zeros(1,4));
147+
bytes(1) = bitand(bitshift(word, sh(1)), 255);
148+
bytes(2) = bitand(bitshift(word, sh(2)), 255);
149+
bytes(3) = bitand(bitshift(word, sh(3)), 255);
150+
bytes(4) = bitand(bitshift(word, sh(4)), 255);
151+
end
152+
153+
function n = q_convert(val, q)
154+
n = round(val * 2^q);
155+
end
156+
157+
function [blob8, j] = add_w8b(v, blob8, j)
158+
if j > length(blob8)
159+
error('Blob size is not sufficient');
160+
end
161+
blob8(j) = w8b(v);
162+
j = j + 1;
163+
end
164+
165+
function [blob8, j] = add_w16b(v, blob8, j)
166+
if j + 1 > length(blob8)
167+
error('Blob size is not sufficient');
168+
end
169+
if v < 0
170+
v = 2^16 + v;
171+
end
172+
blob8(j : j + 1) = w16b(v);
173+
j = j + 2;
174+
end
175+
176+
function [blob8, j] = add_w32b(v, blob8, j)
177+
if j + 3 > length(blob8)
178+
error('Blob size is not sufficient');
179+
end
180+
if v < 0
181+
v = 2^32 + v;
182+
end
183+
blob8(j : j + 3) = w32b(v);
184+
j = j + 4;
185+
end

0 commit comments

Comments
 (0)