mirror of https://github.com/thesofproject/sof.git
180 lines
4.4 KiB
Matlab
180 lines
4.4 KiB
Matlab
function blob8 = bf_blob_pack(bf, ipc_version)
|
|
|
|
%% Pack TDFB struct to bytes
|
|
%
|
|
% blob8 = bf_blob_pack(bf)
|
|
%
|
|
% bf ..... TDFB design data struct input
|
|
% blob8 .. Packed bytes blob output
|
|
%
|
|
|
|
% SPDX-License-Identifier: BSD-3-Clause
|
|
%
|
|
% Copyright(c) 2020 Intel Corporation. All rights reserved.
|
|
%
|
|
% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
|
|
|
|
%% Check for sane parameters
|
|
if bf.num_filters < 1 || bf.num_filters > 16
|
|
error('Invalid number of filters');
|
|
end
|
|
|
|
if bf.num_output_channels < 1 || bf.num_output_channels > 8
|
|
error('Invalid number of output channels');
|
|
end
|
|
|
|
if bf.num_output_streams < 1 || bf.num_output_streams > 8
|
|
error('Invalid number of output streams');
|
|
end
|
|
|
|
if length(bf.input_channel_select) ~= bf.num_filters
|
|
error('input_channel_select length does not match');
|
|
end
|
|
|
|
if length(bf.output_channel_mix) ~= bf.num_filters
|
|
error('output_channel_mix length does not match');
|
|
end
|
|
|
|
if length(bf.output_stream_mix) ~= bf.num_filters
|
|
error('output_stream_mix length does not match');
|
|
end
|
|
|
|
% Use finer angle enum scale for line array that is limited to -90..+90 deg
|
|
% TODO: This should be done somewhere else
|
|
if strcmp(bf.array, 'line')
|
|
bf.angle_enum_mult = 15;
|
|
bf.angle_enum_offs = -90;
|
|
end
|
|
|
|
%% Endianness of blob
|
|
switch lower(bf.endian)
|
|
case 'little'
|
|
sh16 = [0 -8];
|
|
sh32 = [0 -8 -16 -24];
|
|
case 'big'
|
|
sh16 = [-8 0];
|
|
sh32 = [-24 -16 -8 0];
|
|
otherwise
|
|
error('Unknown endianness');
|
|
end
|
|
|
|
%% Header format is
|
|
% uint32_t size;
|
|
% uint16_t num_filters;
|
|
% uint16_t num_output_channels;
|
|
% uint16_t num_output_streams;
|
|
% uint16_t reserved16;
|
|
% uint32_t reserved32[4];
|
|
% int16_t data[];
|
|
%
|
|
% data[] is
|
|
% int16_t fir_filter1[length_filter1]; Multiple of 4 taps and 32 bit align
|
|
% int16_t fir_filter2[length_filter2]; Multiple of 4 taps and 32 bit align
|
|
% ...
|
|
% int16_t fir_filterN[length_filterN]; Multiple of 4 taps and 32 bit align
|
|
% int16_t input_channel_select[num_filters]; 0 = ch0, 1 = 1ch1, ..
|
|
% int16_t output_channel_mix[num_filters];
|
|
% int16_t output_stream_mix[num_filters];
|
|
|
|
%% Pack as 16 bits
|
|
nh16 = 14;
|
|
h16 = zeros(1, nh16, 'int16');
|
|
nc16 = length(bf.all_filters);
|
|
na16 = 4 * bf.num_angles;
|
|
nl16 = 4 * bf.mic_n;
|
|
if bf.beam_off_defined
|
|
nm16 = 4 * bf.num_filters;
|
|
else
|
|
nm16 = 3 * bf.num_filters;
|
|
end
|
|
|
|
nb16 = ceil((nh16 + nc16 + nm16 + na16 + nl16)/2)*2;
|
|
h16(1) = 2 * nb16;
|
|
h16(2) = 0;
|
|
h16(3) = bf.num_filters;
|
|
h16(4) = bf.num_output_channels;
|
|
h16(5) = bf.num_output_streams;
|
|
h16(6) = bf.mic_n;
|
|
h16(7) = bf.num_angles;
|
|
h16(8) = bf.beam_off_defined;
|
|
h16(9) = bf.track_doa;
|
|
h16(10) = bf.angle_enum_mult;
|
|
h16(11) = bf.angle_enum_offs;
|
|
|
|
%% Merge header and coefficients, make even number of int16 to make it
|
|
% multiple of int32
|
|
blob16 = zeros(1,nb16, 'int16');
|
|
blob16(1:nh16) = h16;
|
|
i1 = nh16 + 1;
|
|
i2 = i1 + nc16 -1;
|
|
blob16(i1:i2) = int16(bf.all_filters);
|
|
i1 = i2 + 1;
|
|
i2 = i1 + bf.num_filters - 1;
|
|
blob16(i1:i2) = int16(bf.input_channel_select);
|
|
i1 = i2 + 1;
|
|
i2 = i1 + bf.num_filters - 1;
|
|
blob16(i1:i2) = int16(bf.output_channel_mix);
|
|
i1 = i2 + 1;
|
|
i2 = i1 + bf.num_filters - 1;
|
|
blob16(i1:i2) = int16(bf.output_stream_mix);
|
|
|
|
if (bf.beam_off_defined)
|
|
i1 = i2 + 1;
|
|
i2 = i1 + bf.num_filters - 1;
|
|
blob16(i1:i2) = int16(bf.output_channel_mix_beam_off);
|
|
end
|
|
|
|
for i = 1:bf.num_angles
|
|
i1 = i2 + 1;
|
|
i2 = i1 + 4 - 1;
|
|
blob16(i1:i2) = int16([ bf.steer_az(i) bf.steer_el(i) (i - 1)*bf.num_filters 0 ]);
|
|
end
|
|
|
|
% Coordinates are Q4.12 m
|
|
scale=2^12;
|
|
for i = 1:bf.mic_n
|
|
i1 = i2 + 1;
|
|
i2 = i1 + 4 - 1;
|
|
loc = [ round(bf.mic_x(i)*scale) round(bf.mic_y(i)*scale) round(bf.mic_z(i)*scale) 0 ];
|
|
blob16(i1:i2) = int16(loc);
|
|
end
|
|
|
|
%% Pack as 8 bits
|
|
nbytes_data = nb16 * 2;
|
|
|
|
%% Get ABI information
|
|
[abi_bytes, nbytes_abi] = get_abi(nbytes_data, ipc_version);
|
|
|
|
%% Initialize uint8 array with correct size
|
|
nbytes = nbytes_abi + nbytes_data;
|
|
blob8 = zeros(1, nbytes, 'uint8');
|
|
|
|
%% Inset ABI header
|
|
blob8(1:nbytes_abi) = abi_bytes;
|
|
j = nbytes_abi + 1;
|
|
|
|
%% Component data
|
|
for i = 1:length(blob16)
|
|
blob8(j:j+1) = w16b(blob16(i), sh16);
|
|
j = j+2;
|
|
end
|
|
|
|
%% Done
|
|
fprintf('Blob size is %d bytes.\n', nbytes);
|
|
|
|
end
|
|
|
|
function bytes = w16b(word, sh)
|
|
bytes = uint8(zeros(1,2));
|
|
bytes(1) = bitand(bitshift(word, sh(1)), 255);
|
|
bytes(2) = bitand(bitshift(word, sh(2)), 255);
|
|
end
|
|
|
|
function bytes = w32b(word, sh)
|
|
bytes = uint8(zeros(1,4));
|
|
bytes(1) = bitand(bitshift(word, sh(1)), 255);
|
|
bytes(2) = bitand(bitshift(word, sh(2)), 255);
|
|
bytes(3) = bitand(bitshift(word, sh(3)), 255);
|
|
bytes(4) = bitand(bitshift(word, sh(4)), 255);
|
|
end
|