|
| 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