function [MOVI, Fmem] = PQeval (xR, xT, Fmem)
% PEAQ - Process one frame with the FFT model

% P. Kabal $Revision: 1.1 $  $Date: 2003/12/07 13:32:58 $

NF = 2048;
Version = 'Basic';

% Windowed DFT
X2(1,:) = PQDFTFrame (xR);
X2(2,:) = PQDFTFrame (xT);

% Critical band grouping and frequency spreading
[EbN, Es] = PQ_excitCB (X2);

% Time domain smoothing => "Excitation patterns"
[Ehs(1,:), Fmem.TDS.Ef(1,:)] = PQ_timeSpread (Es(1,:), Fmem.TDS.Ef(1,:));
[Ehs(2,:), Fmem.TDS.Ef(2,:)] = PQ_timeSpread (Es(2,:), Fmem.TDS.Ef(2,:));

% Level and pattern adaptation => "Spectrally adapted patterns"
[EP, Fmem.Adap] = PQadapt (Ehs, Fmem.Adap, Version, 'FFT');

% Modulation patterns
[M, ERavg, Fmem.Env] = PQModPatt (Es, Fmem.Env);

% Loudness
MOVI.Loud.NRef  = PQloud (Ehs(1,:), Version, 'FFT');
MOVI.Loud.NTest = PQloud (Ehs(2,:), Version, 'FFT');

% Modulation differences
MOVI.MDiff = PQmovModDiffB (M, ERavg);

% Noise Loudness
MOVI.NLoud.NL = PQmovNLoudB (M, EP);

% Bandwidth
MOVI.BW = PQmovBW (X2);

% Noise-to-mask ratios
MOVI.NMR = PQmovNMRB (EbN, Ehs(1,:));

% Probability of detection
MOVI.PD = PQmovPD (Ehs);

% Error harmonic structure
MOVI.EHS.EHS = PQmovEHS (xR, xT, X2);

%--------------------
function [EbN, Es] = PQ_excitCB (X2)

persistent W2 EIN

NF = 2048;
Version = 'Basic';
if (isempty (W2))
    Fs = 48000;
    f = linspace (0, Fs/2, NF/2+1);
    W2 = PQWOME (f);
    [Nc, fc] = PQCB (Version);
    EIN = PQIntNoise (fc);
end

% Allocate storage
XwN2 = zeros (1, NF/2+1);

% Outer and middle ear filtering
Xw2(1,:) = W2 .* X2(1,1:NF/2+1);
Xw2(2,:) = W2 .* X2(2,1:NF/2+1);

% Form the difference magnitude signal
for (k = 0:NF/2)
    XwN2(k+1) = (Xw2(1,k+1) - 2 * sqrt (Xw2(1,k+1) * Xw2(2,k+1)) ...
               + Xw2(2,k+1));
end

% Group into partial critical bands
Eb(1,:) = PQgroupCB (Xw2(1,:), Version);
Eb(2,:) = PQgroupCB (Xw2(2,:), Version);
EbN     = PQgroupCB (XwN2, Version);

% Add the internal noise term => "Pitch patterns"
E(1,:) = Eb(1,:) + EIN;
E(2,:) = Eb(2,:) + EIN;

% Critical band spreading => "Unsmeared excitation patterns"
Es(1,:) = PQSpreadCB (E(1,:), Version);
Es(2,:) = PQSpreadCB (E(2,:), Version);

%--------------------
function [Ehs, Ef] = PQ_timeSpread (Es, Ef)

persistent Nc a b

if (isempty (Nc))
    [Nc, fc] = PQCB ('Basic');
    Fs = 48000;
    NF = 2048;
    Nadv = NF / 2;
    Fss = Fs / Nadv;
    t100 = 0.030;
    tmin = 0.008;
    [a, b] = PQtConst (t100, tmin, fc, Fss);
end

% Allocate storage
Ehs = zeros (1, Nc);

% Time domain smoothing
for (m = 0:Nc-1)
    Ef(m+1) = a(m+1) * Ef(m+1) + b(m+1) * Es(m+1);
    Ehs(m+1) = max(Ef(m+1), Es(m+1));
end
