THE AUDITORY MODELING TOOLBOX

Applies to version: 0.9.2

View the help

Go to function

DIETZ2011INTERAURALFUNCTIONS - Interaural stages of Dietz 2011

Program code:

function [outp] = dietz2011interauralfunctions(s1, s2, tau, fc, signal_level_dB_SPL, compr, coh_cycles, fs)
%DIETZ2011INTERAURALFUNCTIONS  Interaural stages of Dietz 2011
%
%   Input parameters
%     s1, s2 : input signals
%     tau    : lowpass filter parameter, such that a = exp(-1./(fs*tau)), 
%              lowpass = filter([1-a], [1, -a], x)  
%     fc     : center frequencies
%     fs     : sampling frequencies
%
%   Output parameters:
%     outp   : Structure containing the output. See the description
%              below.
%
%   XXX Description is missing. What does this function actually do?
%
%   **Note**: If *tau* is a scalar, lowpass is done on every channel
%   with the value of *tau*. If the filter parameter *tau* is a vector, it has
%   to have as many elements as the number of channels of *s1* and *s2*; each
%   value *tau(i)* is applied to the signals in `s1(i,:)` and `s2(i,:)`.
%
%   The output structure *outp* contains the following fields:
%     itf       : transfer function
%     itf_equal : transfer function without amplitude
%     ipd : phase difference in rad
%     ipd_lp    : based on lowpass-filtered itf, phase difference in rad
%     ild : level difference in dB
%     itd, itd_C, itd_lp, itd_C_lp - time difference based on instantaneous
%                  and central frequencies, with and without low-passed itf
%     f_inst_1 : instantaneous frequencies in the channels of the filtered s1
%     f_inst_2 : instantaneous frequencies in the channels of the filtered s2
%     f_inst   : instantaneous frequencies (average of f_inst1 and 2)
%
%   See also: dietz2011
%
%   References: dietz2011auditory

  a = exp( -1./(fs*tau) );

  outp.itf = s2 .* conj(s1);
  
  outp.ipd_lp = zeros(size(s1));
  
  % interaural phase difference
  outp.ipd = angle(outp.itf);
  
  % interaural coherence
  outp.ic = new_ic(outp.itf, coh_cycles./fc, fs);
  
  % interaural level difference for the case of tau - scalar
  
  s1_low = lowpass(abs(s1),a);
  s2_low = lowpass(abs(s2),a);    % take envelope at higher frequencies
  
  s1_low( abs(s1_low) < eps ) = eps;    % avoid log(0)
  s2_low( abs(s2_low) < eps ) = eps;    % avoid division by zero
  
  outp.ild = 20*log10(s1_low./s2_low)./compr;
  if length(a) == 1
    a(1:length(fc)) = a;
    tau(1:length(fc)) = tau;
  end
  
  for k = 1:length(fc);
    outp.ipd_lp(:,k) = angle(lowpass(outp.itf(:,k),a(k)))';
  end
  
  % interaural time difference, based on central and instantaneous frequencies
  for k = 1:length(fc)
    outp.f_inst_1(:,k) = calc_f_inst(s1(:,k),fs,tau(k),0);
    outp.f_inst_2(:,k) = calc_f_inst(s2(:,k),fs,tau(k),0);
    outp.itd_C(:,k) = 1/(2*pi)*outp.ipd(:,k)/fc(k);
    outp.itd_C_lp(:,k) = 1/(2*pi)*outp.ipd_lp(:,k)/fc(k);
  end
  outp.f_inst = max(eps,0.5*(outp.f_inst_1 + outp.f_inst_2)); % to avoid division by zero
  
  % based on instantaneous frequencies
  outp.itd = 1/(2*pi)*outp.ipd./outp.f_inst;    
  outp.itd_lp = 1/(2*pi)*outp.ipd_lp./outp.f_inst;
  
  % weighting of channels for cumulative ixd determination
  % sqrt(2) is due to half-wave rectification (included 28th Sep 07)
  outp.rms = signal_level_dB_SPL*compr + 20*log10(sqrt(2)*min(rms(abs(s1)),rms(abs(s2))));
  outp.rms = max(outp.rms,0); % avoid negative weights
  
  outp.s1 = s1; % put input in output structure
  outp.s2 = s2;
  outp.fc = fc;
end

%% lowpass
function y = lowpass(x, a)
% y = lowpass(x, a)
% This is a simple low-pass filter y(n) = (1-a)*x(n) - a*y(n-1)
% Meaning of parameter a:
%   a - damping coefficient (0 - no filtering, 1 - flat output)
%   tau = 1/(2*pi*f_c)      where f_c is the cutoff frequency of the filter
%   a = exp(-1/(f_s*tau))   where fs - sampling frequency
%
% Input
%   x - input signal
%   1] The signal x may be either row or column vector, the output y is ALWAYS a column vector
%   2] If x is a matrix, time is considered along the LONGER dimension of x
%      Then, the output y is always a column vector or a matrix with time
%      along the rows
%
% Output
%  y - filtered signal
%
% Example see ...\examples\example_lowpass_tester.m
  
  [rows, columns] = size(x);
  if rows < columns
    x = x.';
    y = zeros(columns,rows);
  else
    y = zeros(rows, columns);
  end
  [rows, columns] = size(y);
  
  y = filter([1-a], [1, -a], x);
end



%% f_inst - instantaneous frequency
function f_inst = calc_f_inst(sig,fs,tau,norm)
%
% function f_inst = calc_f_inst(sig,fs,tau,norm);
%
% Calculates instantaneous frequency from a complex (analytical) signal
% using first order differences
%
% input parameters:
%   sig  : complex (analytical) input signal
%   fs   : sampling frequency of sig
%   tau  : exponential decay time of temporal averaging filter
%   norm : exponent for amplitude weighting for temporal averaging filter
%          process(0: no level weigthing)
%
% output values:
%   f_inst:   vector of estimated inst. frequency values (with temporl averaging)
%
% copyright: Universitaet Oldenburg
% author   : volker hohmann
% date     : 12/2004
%

sig = sig';

alpha = exp(-1/tau/fs);
b = [1-alpha];
a = [1 -alpha];

f_inst = sig./(abs(sig)+eps);
f_inst = abs(sig).^norm.*[0 f_inst(2:end).*conj(f_inst(1:end-1))];
f_inst = filter(b,a,f_inst);
f_inst = angle(f_inst')/2/pi*fs;

end



function ic = new_ic(itf,tau_coherence,fs)

%tau_coherence = 15e-3; % good value for ipd_fine

c_coh = exp(-1./(fs.*tau_coherence));
if length(tau_coherence)==1
    ic = abs(filter(1-c_coh,[1 -c_coh],itf))./abs(filter(1-c_coh,[1 -c_coh],abs(itf)));
elseif length(tau_coherence)==size(itf,2)
    ic = zeros(size(itf));
    for n = 1:length(tau_coherence)
        ic(:,n) = abs(filter(1-c_coh(n),[1 -c_coh(n)],itf(:,n)))./ ...
            abs(filter(1-c_coh(n),[1 -c_coh(n)],abs(itf(:,n))));
    end
else
    error('wrong number of tau_coherence values')
end
end