THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

eurich2024_backend
Backend stage of the eMoBi-Q model eurich2024

Program code:

function [obj_mon_norm, obj_bin_norm] = eurich2024_backend(features,nfilt)
%eurich2024_backend Backend stage of the eMoBi-Q model eurich2024
%   Usage: [d_mon, d_bin] = eurich2024_backend(features, nfilt)
%
%   Input parameters:
%     features:        A structure describing the model's features obtained
%                      from eurich2024:
% 
%                      - d_gamma: [m x n] matrix with gamma feature for m time frames and n frequency bands
%
%                      - d_ild: [m x n] matrix with ild feature for m time frames and n frequency bands
%
%                      - d_snr: [m x n] matrix with snr feature for m time frames and n frequency bands
%
%     nfilt:           Desired number of filters per ERB
%
%   
%   Output parameters:
%     d_mon:   vector containing dprime of monaural pathway, see Eq. 10 in Eurich et al. (2024)
%     d_bin:   vector containing dprime of binaural pathway, see Eq. 9 in Eurich et al. (2024)
%
%
%   See also: eurich2024 exp_eurich2024
%
%   References:
%     B. Eurich, S. D. Ewert, M. Dietz, and T. Biberger. A computationally
%     efficient model for combined assessment of monaural and binaural audio
%     quality. Journal of the Audio Engineering Society, 100(4):2381--2396,
%     June 2024.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/modelstages/eurich2024_backend.php


%   #Author: Bernhard Eurich (2024): original implementation
%   #Author: Piotr Majdak (2024): adaptation to AMT 1.6

% This file is licensed unter the GNU General Public License (GPL) either 
% version 3 of the license, or any later version as published by the Free Software 
% Foundation. Details of the GPLv3 can be found in the AMT directory "licences" and 
% at <https://www.gnu.org/licenses/gpl-3.0.html>. 
% You can redistribute this file and/or modify it under the terms of the GPLv3. 
% This file is distributed without any warranty; without even the implied warranty 
% of merchantability or fitness for a particular purpose. 


  % load model parameters
mpar = arg_eurich2024;
mpar.desired_filters_per_ERB = nfilt;

  % preallocate
obj_gamma_mult = zeros(size(features,1),size(features,2),16,size(features(1,1).data_gamma,2));
obj_ild_mult = obj_gamma_mult;

  % read the features 
for aa = 1:size(features,1)
    for bb = 1:size(features,2)       
        obj_gamma_mult(aa,bb,1:size(features(aa,bb).data_gamma,1),1:size(features(aa,bb).data_gamma,2)) = features(aa,bb).data_gamma;
        obj_ild_mult(aa,bb,1:size(features(aa,bb).data_ild,1),1:size(features(aa,bb).data_ild,2))       = features(aa,bb).data_ild;
        if size(features(aa,bb).data_mon,3) == 2
            obj_mon_mult(aa,bb,1:size(features(aa,bb).data_mon,1),1:size(features(aa,bb).data_mon,2))       = mean(features(aa,bb).data_mon,3);
        else
            obj_mon_mult(aa,bb,1:size(features(aa,bb).data_mon,1),1:size(features(aa,bb).data_mon,2))       = features(aa,bb).data_mon;
        end
    end
end


  % limiting ILDs to 10 dB (d')
if any(obj_ild_mult(:))
    obj_ild_mult = min(obj_ild_mult,2*mpar.ild_lim);
end

  % sparsing filter bands if requested
old_fc = features(1,1).mpar.center_frequencies_hz;

if mpar.desired_filters_per_ERB < features(1,1).mpar.GT_filters_per_ERBaud
    sFB_sparse = hohmann2002(features(1,1).mpar.fs,features(1,1).mpar.GT_lowest_center_frequency,...
        features(1,1).mpar.GT_fix_center_frequency,features(1,1).mpar.GT_highest_center_frequency, mpar.desired_filters_per_ERB,'bandwidth_factor',features(1,1).mpar.GT_bwfactor);
    new_fc = sFB_sparse.center_frequencies_hz;

    for aa = 1:length(new_fc)
        n=33;
        [val,idx(aa)]=min(abs(old_fc-new_fc(aa)));
        minVal(aa)=old_fc(idx(aa));
    end

elseif mpar.desired_filters_per_ERB == features(1,1).mpar.GT_filters_per_ERBaud
    new_fc = old_fc;
    idx = 1:size(obj_gamma_mult,4);
else
    error('You requested more filters than available!')
end

  % preallocate with NaN so that dimensions are preserved
obj_gamma_mult_sparse = NaN(size(obj_gamma_mult(:,:,:,idx)));
obj_ild_mult_sparse = NaN(size(obj_ild_mult(:,:,:,idx)));
obj_mon_mult_sparse = NaN(size(obj_mon_mult(:,:,:,idx)));


obj_gamma_mult_sparse(:,:,:,idx) = obj_gamma_mult(:,:,:,idx);
obj_ild_mult_sparse(:,:,:,idx) = obj_ild_mult(:,:,:,idx);
obj_mon_mult_sparse(:,:,:,idx) = obj_mon_mult(:,:,:,idx);


%% Evaluation

  % combination across frames and channels (Eq. 8)
for aa = 1:size(features,1)
    for bb = 1:size(features,2)       
        obj_gamma_temp = squeeze(obj_gamma_mult(aa,bb,:,idx));
        obj_gamma_temp = sqrt(sum(obj_gamma_temp.^2,2,'omitnan'));
        obj_gamma(aa,bb) = sqrt(sum(obj_gamma_temp.^2,'omitnan'));
        
        obj_ild_temp = squeeze(obj_ild_mult(aa,bb,:,idx));

        % if desired, only use ILDs for, e.g., frequency bands beyond the rolloff
        features(1).mpar.mso_rolloff = 1300; % delete after next model run
        [~,filters_below_rolloff] = find(features(1).mpar.center_frequencies_hz < features(1).mpar.mso_rolloff);
        obj_ild_temp(:,filters_below_rolloff) = 0;

        obj_ild_temp = sqrt(sum(obj_ild_temp.^2,2));
        obj_ild(aa,bb) = sqrt(sum(obj_ild_temp.^2,'omitnan'));
        obj_mon_temp = squeeze(mean(obj_mon_mult(aa,bb,:,idx),3,'omitnan'));
        obj_mon(aa,bb) = sqrt(sum(obj_mon_temp .^2));
    end
end
  % combine binaural features (Eq. 9)
weighted_ild = mpar.ild_weight.*obj_ild;
obj_bin = sqrt(obj_gamma.^2 + weighted_ild.^2);

%% Normalization

mon_min = mpar.mon_min;
mon_max = mpar.mon_max;
bin_min = mpar.bin_min;
bin_max = mpar.bin_max;

  % limit to pre-defined range, normalize to [1 0] (Eq. 10)
obj_mon_lim=min(max(10*log10(obj_mon)+10,mon_min),mon_max); 
obj_mon_norm = 1-((obj_mon_lim-mon_min)./(mon_max-mon_min));

obj_bin_lim = min(max(obj_bin,bin_min),bin_max); 
obj_bin_norm = 1-((obj_bin_lim-bin_min)./(bin_max-bin_min));