function [ A ] = NEMA( A, lambda )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Name: NEMA
% Date: April 2018
% Programmer: Christian Dittmar
%
% This function takes a matrix of row-wise time series and applies a
% non-linear exponential moving average (NEMA) to each row. This filter
% introduces exponentially decaying slopes and is defined in eq. (3) from [1].
%
% The difference equation of that filter would be:
% y(n) = max( x(n), y(n-1)*(decay) + x(n)*(1-decay) )
%
% References:
% [1] Christian Dittmar, Patricio López-Serrano, Meinard Müller: "Unifying
% Local and Global Methods for Harmonic-Percussive Source Separation"
% In Proceedings of the IEEE International Conference on Acoustics,
% Speech, and Signal Processing (ICASSP), 2018.
%
% Input: A the matrix with time series in its rows
% lambda the decay parameter in the range [0 ... 1], this can be
% given as a column-vector with individual decays per row
% or as a scalar
%
% Output: A the result after application of the NEMA filter
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% If you use the 'NMF toolbox' please refer to:
% [2] Patricio López-Serrano, Christian Dittmar, Yiğitcan Özer, and Meinard
% Müller
% NMF Toolbox: Music Processing Applications of Nonnegative Matrix
% Factorization
% In Proceedings of the International Conference on Digital Audio Effects
% (DAFx), 2019.
%
% License:
% This file is part of 'NMF toolbox'.
% https://www.audiolabs-erlangen.de/resources/MIR/NMFtoolbox/
% 'NMF toolbox' is free software: you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% the Free Software Foundation, either version 3 of the License, or (at
% your option) any later version.
%
% 'NMF toolbox' is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.
%
% You should have received a copy of the GNU General Public License along
% with 'NMF toolbox'. If not, see http://www.gnu.org/licenses/.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Check parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ~exist('lambda') | isempty(lambda)
lambda = 0.9;
end
% prevent instable filter
lambda = max(0,min(0.9999999,lambda));
% get input dimensions
[numRows, numCols] = size(A);
% start recursive processing at second time frame
for k = 2:numCols
storeRow = A(:,k);
A(:,k) = lambda.*A(:,k-1) + A(:,k).*(1-lambda);
A(:,k) = max(A(:,k),storeRow);
end