THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

barumerli2024_itdlateral
FrAMBI agent performing ITD-based lateralization

Program code:

function [agent, options] = barumerli2024_itdlateral(options)
%barumerli2024_itdlateral FrAMBI agent performing ITD-based lateralization
%
%   Usage: [agent, options] = barumerli2024_itdlateral();
%          [agent, options] = barumerli2024_itdlateral(options);
%
%   Input parameters:
%     options : Optional structure representing the FrAMBI options.
%
%   Output parameters:
%     agent   : Structure representing the FrAMBI agent. See the general description of 
%               FrAMBI for more details. In addition, the following agent-specific
%               fields are created: 
%
%               - name*: String describing the agent. Default: 'ITD-based Lateralization'.
%
%               - model*: Structure defining the functionality of agent by
%                 storing functions handles in fields initialize, observe, 
%                 infer, act, and respond. 
%
%               - state.beliefs*: Prior beliefs on the sound-source lateral 
%                 direction. If set to a number (in degrees), the inference 
%                 will be the average between the belief and the posterior. 
%                 Default: Empty vector, meaning no prior.
%
%               - state.parameters*: Parameter structure as in FRAMBI_PARAMETERS with:
%
%                 - lateral_gain*: The lateral gain (i.e., the slope of the response-target 
%                   function). Default: 1, meaning a perfect lateralization 
%                   without any under- or over shooting.
%
%                 - itd_uncertainty*: The ITD uncertainty (i.e., the ITD standard deviation
%                   in the processing, in s). Default: 20 mu s. 
%
%     options :  Structure representing the FrAMBI options with the following
%                agent-specific fields: 
%
%                - agent.angles*: Sound-source angles (in degrees) used for 
%                  the interpolation to infer the lateralization based on ITDs. 
%                  Set to linearly spaced 15 angles from -90 to +90 degrees. 
%
%                - agent.itds*: ITDs (in s) calculated according to 
%                  Woodworth (1954) based on agent.angles for a head radius
%                  of 7 cm and sound speed of 340 m/s. 
%               
%
%   BARUMERLI2024_ITDLATERAL(..) returns a structure describing an agent 
%   performing ITD-based lateralization. It also creates FrAMBI options 
%   (or updates them, if provided as input). 
%
%   This agent follows the structure required by FRAMBI_SIMULATE.
%   Specifically, BARUMERLI2024_ITDLATERAL(..) defines the following
%   functionality linked with local functions:
%
%   - model.initialize is linked with local_initialize, which sets the 
%     head direction to 0 degrees (i.e., front).
%     The head direction is not considered, but it makes sense to have the head
%     looking to the front when localizing a sound source.
%
%   - model.observe is linked with local_observe, which calculates the 
%     ITD in the observed binaural signal
%     from the environment. The observed ITD is subject to the lateral_gain 
%     and the itd_uncertainty.
%   
%   - model.infer is linked with local_infer, which infers the source 
%     lateral angle based on 
%     the observed ITD. The posterior is based on the precomputed ITD-angle 
%     relation stored in options.agent.angles and options.agent.itd. 
%     If belief is set to an angle, the inference is calculated as the average 
%     between the belief (i.e., the prior) and the posterior. Otherwise
%     the inference is just the posterior. 
%
%   - model.act is linked with local_act, in which it acts by setting: 
%
%     - head to state.head, which, unless modified will be looking at front.
%
%     - hand to state.belief, which is the infered sourceangle.
%
%   - model.respond is linked with local_respond, which responses with 
%     the action of the hand, which is 
%     the infered lateral angle of the sound source (in degrees).
%
%
%   See also: frambi_simulate exp_barumerli2024 frambi_parameters frambi_validate
%
%   References:
%     R. Barumerli and P. Majdak. FrAMBI: A Software Framework for Auditory
%     Modeling Based on Bayesian Inference. under review at Neuroinformatics,
%     2024.
%     
%     R. S. Woodworth and H. Schlosberg. Experimental psychology, Rev. ed.
%     Holt, Oxford, England, 1954.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/models/barumerli2024_itdlateral.php


%   #Author: Roberto Barumerli (2023): Original implementation. 
%   #Author: Roberto Barumerli (2024): Integration in the AMT.
%   #Author: Piotr Majdak (2024): Adaptations for the 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.

%% define the agent
agent.name = 'ITD-based Lateralization';

% add state and parameters
agent.state.beliefs = []; % No prior 
agent.state.parameters = frambi_parameters('set',[], ...
      {'lateral_gain', 'itd_uncertainty'}, ...
       [1.0,            20e-6]); 

  % Link between the ITD and sound-source direction from Woodworth (1954)'s formula
sound_speed = 340; % in m/s
head_radius = 0.07; % in m
angles = linspace(-pi/2, pi/2, 15); % Evaluated on a grid ...
options.agent.itds = head_radius / sound_speed * (angles + sin(angles)); % (in s) ... and stored as constant 
options.agent.angles = rad2deg(angles); % in degrees
  % add functions
agent.model.initialize = @local_initialize;
agent.model.observe = @local_observe;
agent.model.infer = @local_infer;
agent.model.act = @local_act;
agent.model.respond = @local_respond;
  % validate the structures
options=frambi_validate(options);
agent=frambi_validate(agent);

%% initialize: intitalize the trial
function astate = local_initialize(astate, options)
    % trial starts with the head facing the frontal source
    astate.head = 0; 
  
%% observe: calculate features given the binaural input
function observation = local_observe(input, astate, options)
    [~, lag] = max(abs(xcorr(input.signal(:, 1), input.signal(:, 2))));
    itd = (lag - size(input.signal, 1)) / input.fs;

    observation = itd * astate.parameters.lateral_gain.value + randn * astate.parameters.itd_uncertainty.value;

%% infer: infer the environmental states given the observation
function beliefs = local_infer(astate, options)
      % decode the angle from spatial features
    angle = -spline(options.agent.itds, options.agent.angles, astate.observation);
      % this is the heart of bayesian belief update
    if isempty(astate.beliefs)
        % when prior not available, use current observation
        % (i.e. maximum likelihood assuming gaussian distribution)
        beliefs = angle; 
    else
        % when prior available, combine prior with observation
        % (i.e. maximum a posteriori assuming conjugate distribution - 
        % gaussian distributions with equal variance)
        beliefs = 0.5*(astate.beliefs + angle); 
    end

%% act: perform an action according to the beliefs
function action = local_act(astate, options)
    action.head = astate.head; % the head's direction
    action.hand = astate.beliefs; % the hand shows the perceived angle

%% respond: provide a response given the states
function response = local_respond(astate, options)
    response = astate.action.hand;