THE AUDITORY MODELING TOOLBOX

Applies to version: 1.1.0

View the help

Go to function

EXP_RELANOIBORRA2019 - experiments from Relano-Iborra et al. 2019

Program code:

function varargout = exp_relanoiborra2019(varargin)
%EXP_RELANOIBORRA2019 experiments from Relano-Iborra et al. 2019
%
%   Usage: relanoiborra2019;
%
%   This script reproduces Figure 3 of Relano-Iborra et al. It finds the free 
%   parameters of the logistic function that relates the output of the sCASP 
%   model (correlation coefficient d) with the percentage of correct answers. 
%   The data used for this fitting is taken from Nielsen and Dau (2009). The 
%   testing conditions are replicated and fed to the sCASP model. Later a least 
%   squares analysis is used to fit the function to the data.
%
%   Examples:
%   ---------
%
%   To display Figure 3 use :
%
%     exp_relanoiborra2019('fig3');
%
%
%   #Author: Helia Relano Iborra (2020): Code provided for the AMT
%   #Author: Piotr Majdak (2021): Various bug fixes for the AMT 1.0
%
%   Url: http://amtoolbox.org/amt-1.1.0/doc/experiments/exp_relanoiborra2019.php

% Copyright (C) 2009-2021 Piotr Majdak, Clara Hollomey, and the AMT team.
% This file is part of Auditory Modeling Toolbox (AMT) version 1.1.0
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

definput.import = {'amt_cache'};

definput.flags.type = {'missingflag', 'fig3'};

[flags,kv]  = ltfatarghelper({},definput,varargin);

if flags.do_missingflag
  flagnames=[sprintf('%s, ',definput.flags.type{2:end-2}),...
             sprintf('%s or %s',definput.flags.type{end-1},...
             definput.flags.type{end})];
  error('%s: You must specify one of the following flags: %s.', ...
      upper(mfilename),flagnames);
end

%% Initialization

Pcorrect_human = [0 8 35 71 90 100 ]; %% Human data
SNRs= -8:2:2;

%load single_150_SentArray22kHz_varLength % CLUE speech
x = amt_load('relanoiborra2019', 'single_150_SentArray22kHz_varLength.mat');
sentenceArray = x.sentenceArray;
fsSent = 22050;

noise_name = 'SSN_CLUE_22kHz.wav'; % SSN Noise
speechSPL = 65;
Nsentences=25;

fsRef = 22050; % sampling freq.

Pref= 20e-6; % Transformation to Pascals

d= zeros(length(SNRs), Nsentences);

%% Run experiment:

for q=1:Nsentences
    
    amt_disp(['Processing sentence: ' num2str(q) ' out of ' num2str(Nsentences)]);
    speech  = sentenceArray{q};
    speech = resample(speech, fsRef, fsSent );
    
    N_org= length(speech);  % Calculate length of original sentence
    speech = [speech; speech]; % Prepane the same sentence
    
    speech = Pref*speech*(1/rms(speech))*10^((speechSPL)/20); % Set speech level
    N = length(speech);  % Overall speech size
    
    
    for n=1:length(SNRs)
        
        %noise = audioread(noise_name);
        noise = amt_load('relanoiborra2019', noise_name);
        Nsegments = floor(length(noise)/N);
        startIdx = randi(Nsegments-2 ,1)*N;
        noise = noise(startIdx:startIdx+N -1)'; % random segment from the noise file
        
        noise = Pref*(noise./rms(noise)*10^((speechSPL-SNRs(n))/20)); % sets the level of the noise signal
        
        if size(noise) ~= size(speech)
            noise = noise'; % Flips noise signal if needed
        end
        
        test = noise + speech; % Gerating the noisy mixture
        
        % DRNL conf:
        flow = 100;
        fhigh = 8e3;
        
        sbj = 'NH';
        
        % Call model:
        tmp = relanoiborra2019(speech, test, fsRef, flow, fhigh, 'N_org',N_org, 'subject',sbj);
        
        d(n, q) = tmp.dfinal;  % correlation value per sentence and SNR
        
    end % End loop over SNRs
end % End loop over sentences

d_mean= mean(d, 2); % Model outputs averaged across sentences

%% Fitting

xdata = d_mean';
ydata = Pcorrect_human;

fun = @(a,xdata) 100./(1 + exp(a(1)*xdata + a(2))); %Logistic function

pguess = [0 0]; %starting guess
[fit_param,R,J,CovB,MSE] = nlinfit(xdata,ydata,fun,pguess); % non-linear least squares optimization

% Goodness of fit
ysim= fun(fit_param, xdata);
rsq2 = 1 - sum(R.^2) / sum((ydata- mean(ydata)).^2);
varagout{1} = 0;
%% Plotting

x = linspace(0, 1, 200);
fit_funct= fun(fit_param, x);

figure
scatter(d_mean, Pcorrect_human, 68, 'filled', 'r')
hold on
plot(x, fit_funct,'k', 'LineWidth', 2)
xlabel('Model output (d)'), ylabel('% correct'), title('sCASP mapping for CLUE material')
le= legend(' Nielsen & Dau (2009) data', 'f_C_L_U_E', 'Location', 'southeast');
set(le, 'box', 'off')
text(3,12,{[' R^2 = ',num2str(rsq2,2)]},'fontsize',12,'FontName', 'cambria');
set(gca, 'fontsize',12)