THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

exp_lyon2024
Reproduction of results from Lyon et al. (2024)

Program code:

function exp_lyon2024(varargin)
%exp_lyon2024 Reproduction of results from Lyon et al. (2024)
%
%   EXP_LYON2024(flags) reproduces Figures from Lyon et al. (2024).
%
%   The following flags can be specified:
%
%     'fig1'    Reproduce Fig. 1.
%
%     'fig3'    Reproduce Fig. 3. 
%
%     'fig4'    Reproduce Fig. 4.
%
%   Examples:
%   ---------
%
%   To display Fig. 1 use :
%
%     exp_lyon2024('fig1');
%
%   To display Fig. 3 use :
%
%     exp_lyon2024('fig3');
%
%   To display Fig. 4 use :
%
%     exp_lyon2024('fig4');
%
%   License
%   -------
%
%   This model is licensed under the Apache License Version 2.0. Further usage details 
%   are provided in the in the AMT directory "licences".
%
%   See also: lyon2024
%
%   References:
%     R. F. Lyon, R. Schonberger, M. Slaney, M. Velimirović, and H. Yu. The
%     carfac v2 cochlear model in matlab, numpy, and jax. arXiv preprint
%     arXiv:2404.17490, 2024.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/experiments/exp_lyon2024.php


%   #License: Apache2
%   #Author: Richard F. Lyon (2024): original implementation.
%   #Author: Piotr Majdak (2024): Adaptations for the AMT 1.6.

%   This file is licensed unter the Apache License Version 2.0 which details can 
%   be found in the AMT directory "licences" and at 
%   <http://www.apache.org/licenses/LICENSE-2.0>. 
%   You must not use this file except in compliance with the Apache License 
%   Version 2.0. Unless required by applicable law or agreed to in writing, this 
%   file is distributed on an "as is" basis, without warranties or conditions 
%   of any kind, either express or implied.
  
definput.flags.type={'missingflag', 'fig1', 'fig3', 'fig4'}; 
flags  = 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

%% Figure 1: (from CARFAC_two_cap_IHC_compression_fig.m ???)
if flags.do_fig1
    
    fs = 22050; 
    dB_SPL_list = 20:20:80;
      % create a harmonic complexs
    flist = 1400 + (1:4)*200;  % for QDT
    sine_signal = sig_tone(flist(1),0.5,fs);
    for fno = 2:length(flist)
        sine_signal = sine_signal + sig_tone(flist(fno),0.5,fs);
    end
      % create an SPL scaled repetition of the harmonic complex
    test_signal = [];
    for dB =  dB_SPL_list
        test_signal = [test_signal; scaletodbspl(sine_signal,dB)];
    end
      % call the model
    CF_struct = lyon2024_design(1, fs);  % mostly-default design, 1 ear
    CF_struct = lyon2024_init(CF_struct); 
    [~, ~, nap, BM] = lyon2024(test_signal, CF_struct);
      % define analysis ranges
    snip_dB = 60;
    snip_end = length(sine_signal) * find(snip_dB == dB_SPL_list);
    if isempty(snip_end), snip_end = size(nap, 1); end
    BM_snippet = BM(snip_end+(-440:0), :);
    fft_snippet = abs(fft(BM_snippet));  % look at fft of some channels only
      % plot
    figure;
    set(gca, 'Position', [.25, .25, .5, .5]);
    imagesc((fft_snippet(1:220, :)' + 0.002).^ 0.333); 
    colormap(1 - gray);
    axis([0, 89, 0, 71]);
    colormap(1-gray);
    set(gca, 'XTick', 1:20:81, 'XTickLabel',0:1:4);
    xlabel('Frequency (in kHz)');
    ylabel('Channel Number');
    title('Basilar membrane outputs for 4-tone harmonic complex');

end

%% Figure 3
if flags.do_fig3
  
    fs = 22050;
    dB_SPL = 60;
    f = 3000;
    ch = 23;  % Roughly 3 kHz place.
      % create the test signal and time vectors
    test_signal = scaletodbspl(sig_tone(f, 0.01, fs),dB_SPL);
    test_signal(end+1:end+round(0.005*fs)) = 0;  % add a 5-ms silence
    samps = 1:length(test_signal);
    times_ms = (0:(length(test_signal)-1))/fs*1000;

    figure;
      % one-cap model (for reference)
    CF_struct = lyon2011_design(1, fs);  % mostly-default design, 1 ear
    CF_struct = lyon2011_init(CF_struct);
    [~, ~, nap] = lyon2011(test_signal, CF_struct);  
    plot(times_ms, nap(:,ch), 'k:', 'linewidth', 1);
    hold on
      % two-cap model    
    CF_struct = lyon2024_design(1, fs);  % mostly-default design, 1 ear
    CF_struct = lyon2024_init(CF_struct);
    [CF_struct, ~, nap, BM] = lyon2024(test_signal, CF_struct); 
    plot(times_ms, nap(:,ch), 'k-', 'linewidth', 0.6);
        
      % two-cap model: plot more stuff
    bm_row = BM(:, ch);
      % Run an IHC open-loop on the BM response for the frequency channel
    coeffs = CF_struct.ears(1).IHC_coeffs;
    n_ch = coeffs.n_ch;
    state.ihc_accum = zeros(n_ch, 1); 
    state.cap1_voltage = coeffs.rest_cap1 * ones(n_ch, 1); 
    state.cap2_voltage = coeffs.rest_cap2 * ones(n_ch, 1);
    state.lpf1_state = coeffs.rest_output * ones(n_ch, 1);       
    receptor_potential_row = zeros(length(samps),1);
    for s = samps
      [~, state] = lyon2024_ihcstep(bm_row(s), coeffs, state);
      receptor_potential_row(s) = 1 - state.cap1_voltage(ch);
    end
      % plot
    plot(times_ms, 6 + 20*receptor_potential_row, 'k-');
    plot(times_ms, 12 + bm_row, 'k-');
    title('BM (top), receptor potential (middle), and NAP (bottom)');
    xlabel('Time (in ms)');
    ylabel('Amplitudes (arbitrary units, shifted by 6)');
    set(gca, 'Position', [.25, .25, .55, .55]);
    ylim([-2 16]);
    yticks(-2:2:16);
    text(12, 13, '12+BM');
    text(12, 8, '6+20 V_{recep}');
    text(12, 1, 'NAP');

end

if flags.do_fig4

    tau1 = 200e-6;
    tau2 = 80e-6;

    f = 30 * 10.^(0.25:(1/32):2.8)';
    s = 2*1i*pi*f;
    h1 = abs(1./(tau1*s + 1));
    h2 = abs(1./(tau2*s + 1));
    h_one_cap = h2.*h2;
    h_two_cap = h1.*h2;

    lw = 0.6;  % linewidth
    figure;
    semilogx(f, [h_one_cap, h_two_cap], 'k-', 'linewidth', lw);
    hold on
    semilogx(f, h_two_cap ./ h_one_cap, 'k--', 'linewidth', lw);

    i300 = find(f == 300);
    i3k = find(f == 3000);

    plot(f(i300)*[1;1], [h_one_cap(i300); h_two_cap(i300)], 'k-', 'linewidth', lw);
    plot(f(i3k)*[1;1], [h_one_cap(i3k); h_two_cap(i3k)], 'k-', 'linewidth', lw);
    set(gca, 'Position', [.25, .25, .5, .5]);
    xlabel('Frequency (in Hz)');
    ylabel('Smoothing filters gain = synchrony reduction');

    text(4000, 0.47, 'v2/v1 ratio');
    text(1500, 0.7, 'v1, one\_cap');
    text(210, 0.7, 'v2, two\_cap');
    text(2000, 0.1, '3 kHz');
    text(200, 0.86, '300 Hz');

end