THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

bramslow2004_roexfilt
Correct the power spectrum by the roex-filter shape considering signal level and hearing loss

Program code:

function [Roex_SPL, E_Vector, HTLL]=bramslow2004_roexfilt(PowSpect, E_SPL, In_FrmSize, In_SampF, NoChan, Widen, AGFs_E, AGLoss, RET4153, E_Beg, E_End, E_Bin)
%bramslow2004_roexfilt Correct the power spectrum by the roex-filter shape considering signal level and hearing loss
%
%   Usage: [Roex_SPL, E_Vector, HTLL]=bramslow2004_roexfilt(PowSpect, E_SPL, In_FrmSize, In_SampF, NoChan, Widen, AGFs_E, AGLoss, RET4153, E_Beg, E_End, E_Bin)
%
%   Input parameters:
%     PowSpect      : Row vector with the power spectrum. Size: In_FrmSize/2.
%     E_SPL         : SPL (in dB) in each ERB, used to adjust the roex filter slopes.
%     In_FrmSize    : Input framesize (in samples).
%     In_SampF      : Input sampling rate (in Hz).
%     NoChan        : Number of output channels (equally distributed on the ERB scale).
%     Widen         : Flag for filter widening dependent on level. If true, the filter will be widened. 
%     AGFs_E        : Audiogram frequencies on ERB scale (in Cams).
%     AGLoss        : Audiogram (in dB HL) specified at frequencies [125 250 500 750 1000 1500 2000 3000 4000 6000 8000 10000 12500] Hz.
%     RET4153       : ISO 389 thresholds (in dB SPL) as measured on the ear-simulator (4153) coupler. 
%                     Specified at the same frequencies as for AGLoss.
%     E_Beg         : Lowest ERB rate considered (in Cams, typically 3 Cams).
%     E_End         : Highest ERB rate considered (in Cams, typically 32 Cams).
%     E_Bin         : ERB rates (in Cams) of the individual bins in the frame.
% 
%   Output parameters:
%     Roex_SPL      : SPL (in dB) corrected by the roex-filterbank output.
%     E_Vector      : Power spectrum (in dB) corrected by the roex-filterbank output.
%     HTLL          : Hearing threshold levels (in dB) interpolated along the ERB scale to obtain SPL of the 4152 coupler.
%
%   See also other parameters as in arg_bramslow2004.
%
%   See also: demo_bramslow2004 exp_bramslow2004 bramslow2004
%
%   References:
%     L. Bramsløw Nielsen. An Auditory Model with Hearing Loss. Technical
%     report, Eriksholm Research Centre, Snekkersten, 1993.
%     
%     L. Bramsløw. An objective estimate of the perceived quality of
%     reproduced sound in normal and impaired hearing. Acta Acustica united
%     with Acustica, 90(6):1007--1018, 2004.
%     
%     L. Bramsløw. An auditory loudness model with hearing loss. In
%     Baltic-Nordic Acoustics Meeting, pages 318--323, 2024.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/modelstages/bramslow2004_roexfilt.php


%   #StatusDoc: 
%   #StatusCode: 
%   #Verification: Unknown
%   #Requirements: M-Signal
%   #Author: Lars Bramslow (1993): Original C code
%   #Author: Graham Naylor (1994): Updates to model
%   #Author: Tayyib Arshad (2007): Ported to Matlab
%   #Author: Lars Bramslow (2024): Integration into AMT
%   #Author: Piotr Majdak (2024): Integration for AMT 1.6.0

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


% Flag for first pass 
FirstTime = true;
PrevWiden = 'WIDEN';
C1=     24.673;
C2=     4.368;

PU_DEP_HL = true;
PL_DEP_HL = true;
PL_MOD2 = true;
MAX_THR = 100;
PU_THR = 36.8;
GMAX = 10;
PMIN = 3;
PL_INT2 = 30.16;
PL_SLO2 = -0.38;
PL_THR2 = 20;

f0_kHz = [30,1];
f0_Hz = [30,1];
pl_51 = [30,1];
pu_51 = [30,1];
HTLL = [30,1];
HTLU = [30,1];
BinL = [30,1];
BinU = [30,1];


% Initialize each E-band to some energy, -100 dB = 1e-10-------------------

E_Vector(1:NoChan) = 1e-10;

% Calculate constants right away-------------------------------------------
% If PL_DEP_HL is defined
%--------------------------------------------------------------------------
if (PL_DEP_HL~=true)
    if (FirstTime)
        p51_1k = 4.0 * 1000.0 / (C1 * (C2 + 1.0));
    end
end

% Now, calculate the energy for each band----------------------------------
E = E_Beg;
E_Step = 0;

for Filt_Index = 1:1:NoChan, E = E + E_Step;
    E_Step = (E_End - E_Beg)/(NoChan - 1.0);

    if FirstTime || strcmp(PrevWiden, Widen) == 0

        f0_kHz(Filt_Index) = erbrate2f(E)/1000;		
        f0_Hz(Filt_Index) = f0_kHz(Filt_Index) * 1000.0;

        if PU_DEP_HL ~= false
            Erb_Hz = f2erb(f0_Hz(Filt_Index));			
            pl_51(Filt_Index) = 4.0*f0_Hz(Filt_Index)/Erb_Hz;
            pu_51(Filt_Index) = pl_51(Filt_Index);
        end

        % Find hearing loss and force to range-------------------------------------
        if (Widen == true)
            HTLL(Filt_Index) = bramslow2004_erbrateinterp(E, AGLoss, AGFs_E, E_Beg, E_End);
        else
            HTLL(Filt_Index) = bramslow2004_erbrateinterp(E, RET4153, AGFs_E, E_Beg, E_End);
        end

        HTLL(Filt_Index) = min(HTLL(Filt_Index), MAX_THR);

        HTLU(Filt_Index) = HTLL(Filt_Index);

        HTLU(Filt_Index) = max(HTLU(Filt_Index), PU_THR);

        % Find bin above GMAX------------------------------------------------------
        f_Hz = (1 - GMAX)*f0_Hz(Filt_Index);
        BinL(Filt_Index) = ceil(f_Hz/(In_SampF/In_FrmSize));

        if BinL(Filt_Index) < 1
            BinL(Filt_Index) = 1;       % Don't allow bin-numbers under 1
        end

        % Find bin below GMAX -----------------------------------------------------
        f_Hz = (1 + GMAX)*f0_Hz(Filt_Index);
        BinU(Filt_Index) = floor(f_Hz/(In_SampF/In_FrmSize));  % compensation for bin starts at 1 not 0!


        BinU(Filt_Index) = min(BinU(Filt_Index), (In_FrmSize/2));   % Don't go beyond fs/2
    end
    % if FirstTime etc.

    Prev_ESPL_Index = 10000;   % Make sure this is out of range before loop

    % Sum up the bins----------------------------------------------------------

    for Bin = BinL(Filt_Index):1:BinU(Filt_Index)

        f_Hz = Bin*In_SampF/In_FrmSize;

        % Index is 0 for bins below E_Beg------------------------------------------
        ESPL_Index = (max(1, (E_Bin(Bin) - E_Beg)/E_Step ));
        % Don't go above NoChan either---------------------------------------------
        ESPL_Index = min(ESPL_Index, NoChan);
        if ESPL_Index == 0
            ESPL_Index = 1;
        end
        ESPL_Index= round(ESPL_Index);
        if ESPL_Index ~= Prev_ESPL_Index

            if 1
                if PL_DEP_HL
                    if (PL_MOD2~=true)
                        pl = (((C2 + 1)*f0_kHz(Filt_Index))/(C2*f0_kHz(Filt_Index) + 1))*((PL_INT1 + PL_SLO1*max(HTLL(Filt_Index),PL_THR1))- 0.380*(E_SPL(ESPL_Index) - 71.0));

                    else

                        pl = (((C2 + 1)*f0_kHz(Filt_Index))/(C2*f0_kHz(Filt_Index) + 1))*(PL_INT2 + PL_SLO2*(max(min(0,E_SPL(ESPL_Index) - 71.0),HTLL(Filt_Index)-PL_THR2)+PL_THR2));
                    end


                else


                    pl = pl_51(Filt_Index) - 0.380*(pl_51(Filt_Index)/p51_1k)*(E_SPL(ESPL_Index) - 51.0);
                end

                % Upper skirt doesn't change with level------------------------------------
                if PU_DEP_HL == false
                    pu = (((C2 + 1)*f0_kHz(Filt_Index))/(C2*f0_kHz(Filt_Index) + 1))*(PU_INT + PU_SLOPE*HTLU(Filt_Index));
                else
                    pu = pu_51(Filt_Index);
                end

            else
                pl = pl_51(Filt_Index) - 0.380*(E_SPL(ESPL_Index) - 51.0);
                pu = pu_51(Filt_Index) + 0.118*(E_SPL(ESPL_Index) - 51.0);
            end

            % Make sure pl and pu are valid--------------------------------------------
            pl = max(pl, PMIN);
            pu = max(pu, PMIN);
        end

        % if ESPL_Index ...--------------------------------------------------------
        % Remember index-----------------------------------------------------------

        Prev_ESPL_Index = ESPL_Index;

        g = (f_Hz - f0_Hz(Filt_Index))/f0_Hz(Filt_Index);

        if g < 0
            E_Vector(Filt_Index) = E_Vector(Filt_Index) + PowSpect(Bin) * (1-pl*g)*exp(pl*g);
        else
            E_Vector(Filt_Index) = E_Vector(Filt_Index) + PowSpect(Bin) * (1+pu*g)*exp(-pu*g);
        end
    end

end


Roex_SPL(NoChan) = 0.0;
for Filt_Index = 1:1:NoChan
    Roex_SPL(Filt_Index) = 10 * log10(E_Vector(Filt_Index));

end

% Don't initialize next time-----------------------------------------------
FirstTime = false;
PrevWiden = Widen;