THE AUDITORY MODELING TOOLBOX

Applies to version: 1.6.0

View the help

Go to function

bramslow2004_equloudn
Correct the power spectrum for equal loudness contours

Program code:

function [PowSpect1]= bramslow2004_equloudn(PowSpect,TransFact,In_FrmSize,In_SampF)
%bramslow2004_equloudn Correct the power spectrum for equal loudness contours
%
%   Usage:  PowSpect = bramslow2004_equloudn(PowSpect, TransFact, In_FrmSize, In_SampF)
%
%   Input parameters:
%     PowSpect      : Row vector with the power spectrum. Size: In_FrmSize/2.
%     TransFact     : Specifies the fixed frequency response equalization applied to the input 
%                     spectrum (after correcting for coupler response) before passing it through
%                     the auditory filterbank. It can be one of the following: 
%
%                     - 'ZWICKA0': a0 transmission factor as described by Zwicker & Fastl (1999).
%
%                     - 'ISO100N': 100-phone equal-loudness contours from ISO 226, see also Glasberg
%                       and Moore (1990).
%
%                     - 'ISO100M': As 'ISO100N' but flat below 1 kHz, see also Glasberg
%                       and Moore (1990).
%
%     In_FrmSize    : Frame size of the original time frame.
%     In_SampF      : Input sampling rate (in Hz).
% 
%   Output parameters:
%     PowSpect      : Row vector with the corrected power spectrum. Size: In_FrmSize/2.
%
%   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.
%     
%     G. Naylor. The AUDMOD auditory model: A critique and revisions.
%     Technical report, Eriksholm Research Centre, Snekkersten, 1994.
%     
%     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.
%     
%     B. R. Glasberg and B. Moore. Derivation of auditory filter shapes from
%     notched-noise data. Hearing Research, 47(1-2):103--138, 1990.
%     
%     E. Zwicker and H. Fastl. Psychoacoustics: Facts and models, volume 254.
%     Springer Berlin, 1999.
%     
%
%   Url: http://amtoolbox.org/amt-1.6.0/doc/modelstages/bramslow2004_equloudn.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.


FirstTime = true;                       % Flag - reset after first call

if (FirstTime)
    Fixed_Eq = zeros(In_FrmSize/2, 1);
    
    switch (TransFact)                % Select transmission factor
        case {'ZWICKA0'}				    % Zwicker's a0 factor
            a0Points = 27;
            a0Gain = [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 2.5 5.0 6.5 6.0 3.5 -1.0 -4.0 -7.5 -20.0];
            a0Freq = [31.5 40 50 63 80 100 125 160 200 250 315 400 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000 12500];
            
            Freq = a0Freq;
            Gain = a0Gain;
            Points = a0Points;
            
        case {'ISO100N'}                  % ELC100 from ISO 226
            ELC100Points = 27;
            ELC100Gain = [-16.6 -12.6 -10.1 -7.9 -5.6 -3.6 -1.8 -0.1 1.3 2.2 2.8 2.7 2.6 1.9 1.0	0.0	0.9	2.3 5.1	8.5 11.2 11.5 7.8 0.1 -6.6 -13.0 -20.0];
            ELC100Freq = [31.5 40 50 63 80 100 125 160 200 250 315 400 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000 12500];
            
            Freq = ELC100Freq;
            Gain = ELC100Gain;
            Points = ELC100Points;
            
        case {'ISO100M'}                  % ELC100, but flat below 1 kHz
            ELC100MPoints = 27;
            ELC100MGain = [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.9 2.3 5.1 8.5 11.2 11.5 7.8 0.1 -6.6 -13.0 -20.0];
            ELC100MFreq = [31.5 40 50 63 80 100 125 160 200 250 315 400 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000 12500];
            
            Freq = ELC100MFreq;
            Gain = ELC100MGain;
            Points = ELC100MPoints;
            
        otherwise                         % Unknown factor - return error code
            error('Unknown Transmission factor %s', TransFact);
    end
    
    
    for Bin = 1:1:In_FrmSize/2
        F_Hz = (Bin * In_SampF)/In_FrmSize;
        Index = bramslow2004_locate (Freq, F_Hz);   % Locate nearest point below F_Hz
        if Index < 0
            Gain_dB = Gain(1);
        elseif Index >= Points - 1
            Gain_dB = Gain(Points - 1);
        else
            Gain_dB = Gain(Index) + (Gain(Index+1) - Gain(Index))* (F_Hz - Freq(Index)) / (Freq(Index+1) - Freq(Index));
        end
        
        % Save the correction in array for future use------------------------------
        Fixed_Eq(Bin) = 10^(Gain_dB/10.0);
    end
    
    
end

% Apply the correction-----------------------------------------------------
% for Bin = 1:1:In_FrmSize/2
%     PowSpect1(Bin) = PowSpect(Bin)*Fixed_Eq(Bin);
% end
[rows, cols] = size(PowSpect);
% Transpose if required
if rows == 1
    Fixed_Eq = Fixed_Eq';
end
PowSpect1(1:In_FrmSize/2) = PowSpect(1:In_FrmSize/2).*Fixed_Eq(1:In_FrmSize/2);

FirstTime = false;