THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

demo_mckenzie2022
Demo for the model of colouration between binaural signals

Program code:

% demo_mckenzie2022 Demo for the model of colouration between binaural signals
%
%   This is a demonstration of MCKENZIE2022, a model predicting the 
%   coloration between two binaural signals in terms of the perceptual 
%   binaural coloration (PBC) scores. The demonstration compares various 
%   binaural Ambisonic renderers with and without diffuse-field equalisation
%   of the HRTFs as used in McKenzie et al. (2018). It also shows how to 
%   plot the PBC scores using PLOT_MCKENZIE2022. 
%
%   Figure 1: PBC scores calculated based on signals from McKenzie et al. (2018) for various Ambisonic orders (OAs) and with and without diffuse-field equalization (DFE).
%
%   Figure 2: PBC dataset normalisation; marker colours get lighter with iterations (see Fig. 2 of McKenzie et al., 2022)
%
%   Figure 3: PBC scores calculated calculated from frequency-domain data
%
%
%
%   References:
%     T. McKenzie, D. T. Murphy, and G. Kearney. Diffuse-field equalisation
%     of binaural ambisonic rendering. Applied Sciences, 8(10), 2018.
%     [1]http ]
%     
%     T. McKenzie, C. Armstrong, L. Ward, D. Murphy, and G. Kearney.
%     Predicting the colouration between binaural signals. Appl. Sci.,
%     12(2441), 2022.
%     
%     References
%     
%     1. https://www.mdpi.com/2076-3417/8/10/1956
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/demos/demo_mckenzie2022.php


%   #Requirements: MATLAB M-Stats M-Curvefit
%   #Author: Thomas McKenzie (2022): initial implementation
%   #Author: Cal Armstrong (2022): initial implementation
%   #Author: Lauren Ward (2022): initial implementation
%   #Author: Damian Murphy (2022): initial implementation
%   #Author: Gavin Kearney (2022): initial implementation
%   #Author: Piotr Majdak (2023): documentation and structure adaptations
%   #Author: Michael Mihocic (2024): catching if Octave is used, and if curve fitting toolbox is not available -> otherwise returning warning

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

if isoctave
    warning([mfilename ' is not supported in Octave.']);
    return;
end

if exist('fit','file') == 0
    warning([mfilename ' requires Matlab Curve-Fitting Toolbox.']);
    return;
end

%% Read in listening test stimuli from McKenzie 2018 paper.
data = amt_load('mckenzie2022', 'sig_mckenzie2018.mat');
% data = load('sig_mckenzie2022.mat');

fs = data.fs;
rsH = data.rsH;
testDirections = data.testDirections;
tsA1 = data.tsA1;
tsA3 = data.tsA3;
tsA5 = data.tsA5;
tsD1 = data.tsD1;
tsD3 = data.tsD3;
tsD5 = data.tsD5;
% combine stimuli into one matrix
ts = cat(3,tsA1,tsA3,tsA5,tsD1,tsD3,tsD5);
rs = cat(3,rsH,rsH,rsH,rsH,rsH,rsH);
tsP = permute(ts,[1 3 2]);
rsP = permute(rs,[1 3 2]);

%% Run spectral difference calculation
%- simple example

% Parameters
domFlag = 0; % specify that inputs are time-domain signals
freqRange = [20 20000]; % calculate spectral difference between 20Hz and 20kHz
nfft = length(rs(:,1,1)); % fft window size same as signal length
f = struct; 
f.fs = fs;f.nfft = nfft;f.minFreq = freqRange(1); f.maxFreq = freqRange(2);
datasetNormalisation = 0; % blank vector for using iterative dataset normalisation. if an int, then that fixes the dataset normalisation in dB. Thus for no normalisation, set to 0.

% Calculate perceptual spectral difference
[~,PSpecDiff] = mckenzie2022(tsP,rsP,domFlag,f,datasetNormalisation);
PSpecDiff = squeeze(PSpecDiff);

% get single values of spectral difference for all stimuli
PavgSpecDiffS = mean(PSpecDiff,2);

% plot values
spectralDifference=PavgSpecDiffS;

maxValue = max(spectralDifference);
minValue = min(spectralDifference);
figure('position',[100,100,1200 400]);
titles={'1OA no DFE','3OA no DFE','5OA no DFE','1OA with DFE','3OA no DFE','5OA no DFE'};
for i = 1:length(spectralDifference)/length(testDirections)
    subplot(2,3,i)
    plot_mckenzie2022(spectralDifference((i-1)*length(testDirections)+1:i*(length(testDirections))),testDirections);
    averagePBCvalue = mean(spectralDifference((i-1)*length(testDirections)+1:i*(length(testDirections))));
    title(strcat([titles{i} '. Mean PBC=',num2str(averagePBCvalue),' sones']));    
    caxis([minValue,maxValue]);
    xlim([0 180]); % as this data is only in a hemisphere, constrain axis limits
end


%% Run spectral difference calculation
%- with normalisation, alternative frequency range, pre-model FFT calculation

% Parameters
domFlag = 2; % specify that inputs are frequency-domain signals in dB
freqRange = [1000 10000]; % this time for a 1kHz - 10kHz frequency range
nfft = length(rs(:,1,1));

% Take FFT of matrices
fft_matrix_input = fft(tsP, nfft); % Get Fast Fourier transform

% Compute freq bins for x-axis limits
fr_low = round(freqRange(1)*nfft/fs);
fr_high = round(freqRange(2)*nfft/fs);

% Get absolute values for frequency bins
fft_abs_matrix_input = abs(fft_matrix_input(fr_low:fr_high,:,:));

% Get values in dB
tsF = 20*log10(fft_abs_matrix_input);

% Take FFT of matrices
fft_matrix_input = fft(rsP, nfft); % Get Fast Fourier transform

% Compute freq bins for x-axis limits
fr_low = round(freqRange(1)*nfft/fs);
fr_high = round(freqRange(2)*nfft/fs);

% Get absolute values for frequency bins
fft_abs_matrix_input = abs(fft_matrix_input(fr_low:fr_high,:,:));

% Get values in dB
rsF = 20*log10(fft_abs_matrix_input);

% Frequency vector for plotting
f = 0:fs/nfft:fs-(fs/nfft);
f = f(fr_low:fr_high);


%--------------------------------------------------------------------------


datasetNormalisation = []; % blank vector for using iterative dataset normalisation. if an int, then that fixes the dataset normalisation in dB. Thus for no normalisation, set to 0.
w = 1; % for sample weighting. If input signals correspond to irregularly spaced points on a sphere, such as a gaussian quadrature, w could be a vector of solid angle weights, which is then used in the spectral difference calculation.
normalisationPlotFlag = 1; % show dataset normalisation curve
normalisationResolution = 0.001; % choose resolution of dataset normalisation - smaller number for finer resolution.

% Calculate perceptual spectral difference
[~,PSpecDiff] = mckenzie2022(tsF,rsF,domFlag,f,datasetNormalisation,w,normalisationPlotFlag,normalisationResolution);
PSpecDiff = squeeze(PSpecDiff);

% get single values of spectral difference for all stimuli
PavgSpecDiffS = mean(PSpecDiff,2);

% plot values
spectralDifference=PavgSpecDiffS;

maxValue = max(spectralDifference);
minValue = min(spectralDifference);
figure('position',[100,100,1200 400]);
titles={'1OA no DFE','3OA no DFE','5OA no DFE','1OA with DFE','3OA no DFE','5OA no DFE'};
for i = 1:length(spectralDifference)/length(testDirections)
    subplot(2,3,i)
    plot_mckenzie2022(spectralDifference((i-1)*length(testDirections)+1:i*(length(testDirections))),testDirections);
    averagePBCvalue = mean(spectralDifference((i-1)*length(testDirections)+1:i*(length(testDirections))));
    title(strcat([titles{i} '. Mean PBC=',num2str(averagePBCvalue),' sones']));    
    caxis([minValue,maxValue]);
    xlim([0 180]); % as this data is only in a hemisphere, constrain axis limits
end