Skip to content
Snippets Groups Projects
Commit 5f36b0ab authored by Achilles Kappis's avatar Achilles Kappis
Browse files

Add function to calculate filter and array output of a first order DMA in the time domain

parent a8f90b96
No related branches found
No related tags found
1 merge request!12Implementation of first order differential arrays in the time domain
%% 1st order Time-Domain Directional Microphone Array
% --------------------------------------------------
% Author: Achilles Kappis
% e-mail: axilleaz@protonmail.com
%
% Date: 04/01/2025 (DD/MM/YYYY)
%
% Copyright: MIT
% --------------------------------------------------
% Functionality: Calculate the filters and output of a first order
% Differential Microphone Array (DMA) in the time-domain.
% --------------------------------------------------
% Input
%
% sMtx [numeric]: The steering matrix of the differential array. This must
% be an NxMx2 array, where N is 2 * L with, L the length of
% the desired FIR beamforming filter. M is the length of
% time-domain the steering vectors (see notes). The third
% dimension corresponds to the number of microphones in the
% array; at the moment only first order arrays with two
% microphones are supported.
%
% del [numeric] (Optional): This is a positive real integer corresponding
% to the delay index at which the right-hand side
% vector will have its non-zero sample. For an
% explanation look at the literature referenced
% in the notes, where ways to calculate the
% optimal value are briefly discussed.
% [Default: 14].
%
% regFac [numeric] (Optional): This is a positive scalar that acts to
% regularise the inversion of the constraints
% matrix. [Default: 0].
%
% sig [numeric] (Optional): This must be an KxPx2 array, corresponding to
% the signals to be filtered by the array, with
% real valued elements. The dimensions are as
% follows: K is the length of the signals in
% samples, P are the number of signals to be
% filtered and the last dimension corresponds to
% the fact that the signals must be given
% separately for each microphone. If no signals
% are given, the output arguments "out" and
% "outSum" will be empty. [Default: []].
%
% --------------------------------------------------
% Output
%
% hMtx [numeric]: The beamforming FIR filter in vector format. This will be
% an Nx1 vector, where N is again 2 * L, with L the length
% of the beamforming FIR filter. The filters corresponding
% to the microphones are stacked and not interleaved.
%
% h [numeric]: The beamforming FIR filters given for each microphone
% separately. This is an Lx2 matrix, with L the length of the
% filters.
%
% out [numeric]: The output of each microphone (after filtering) for each
% signal provided in the input argument "sigs". This is a
% KxPx2 array, with K the length of the signals and P the
% number of signals.
%
% outSum [numeric]: This is the sum of the output signals (after filtering)
% of each microphone. This is a KxP matrix and
% corresponds to "sum(out, 3)".
%
% --------------------------------------------------
% Notes
%
% - The implementation is based on: "On the Design of Time-Domain
% Differential Microphone Arrays" by Buchris, Cohen and Benesty.
%
% --------------------------------------------------
function [hMtx, h, out, outSum] = firstOrderDmaTD(sMtx, del, regFac, sig)
% ====================================================
% Check for number of arguments
% ====================================================
narginchk(1, 4);
nargoutchk(0, 4);
% ====================================================
% Validate input arguments
% ====================================================
validateattributes(sMtx, "numeric", {'3d', 'real', 'nonempty', 'nonnan', 'finite', 'size', [NaN, NaN, 2]}, mfilename, "Angle of null response", 1);
validateattributes(del, "numeric", {'scalar', 'nonempty', 'integer', 'real', 'finite', 'nonnan', 'nonnegative'}, mfilename, "The maximum delay between sensors and reference point of the array", 2);
if nargin > 2 && ~isempty(regFac)
validateattributes(regFac, "numeric", {'scalar', 'nonempty', 'real', 'finite', 'nonnan', 'nonnegative'}, mfilename, "The regularisation factor", 3);
else
regFac = 0;
end
if nargin > 3 && ~isempty(sig)
validateattributes(sig, "numeric", {'3d', 'nonempty', 'real', 'nonnan', 'finite', 'size', [NaN, NaN, 2]}, mfilename, "Signals to be filtered", 4);
else
sig = [];
end
% ====================================================
% Calculate parameters
% ====================================================
% Calculate right hand side vector
rhsVec = zeros(2 * size(sMtx, 2), 1);
rhsVec(del) = 1;
% ====================================================
% Pre-process arguments
% ====================================================
% Stack the array manifolds for the two directions into a single matrix
sMtx = reshape(sMtx, size(sMtx, 1), []).';
% ====================================================
% Calculate filter(s)
% ====================================================
if regFac ~= 0
hMtx = regFac * eye(size(sMtx, 2));
else
hMtx = 0;
end
hMtx = (sMtx.' * sMtx + hMtx)\(sMtx.') * rhsVec;
% ====================================================
% Return additional output arguments
% ====================================================
% Return the individual filters
if nargout > 1
h = reshape(hMtx, [], 2);
end
% Return the filtered signal(s) [output of the DMA]
if nargout > 2 && ~isempty(sig)
for idx = size(h, 2):-1:1
out(:, :, idx) = filter(h(:, idx), 1, sig(:, :, idx));
end
else
out = [];
end
if nargout > 3 && ~isempty(out)
outSum = squeeze(sum(out, 3));
else
outSum = [];
end
end
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment