classdef (StrictDefaults)FullWaveIntegrator < matlab.System
    % FullWaveIntegrator
    % Integrates the absolute value of the input. The output is reset to
    % zero when the input has a zero crossing with a positive slope.
    %
    % This object is used in the "Psychoacoustic Bass enhancement for
    % Band-Limited Signals" featured example
    
    % Copyright 2015-2022 The MathWorks, Inc.
    
    %#codegen
    properties (DiscreteState)
        yMinus1;
        uMinus1;
    end
    
    properties (Access = private)
        K = 1; % input gain
    end
    
    methods (Access = protected)
        function setupImpl(obj,~)
            obj.yMinus1 = 0;
            obj.uMinus1 = 0;
        end
        
        function y = stepImpl(obj,u)
            
            % Operates on mono signal only
            y = zeros(length(u),1);
            
            % Take absolute value of input
            uAbs = abs(u);
            
            % First iteration
            y(1) = obj.yMinus1 + obj.K * obj.uMinus1;
            
            L = length(u);
            for i=2:L
                % Forward euler method
                % y(n) = y(n-1) + K*u(n-1);
                y(i) = y(i-1) + obj.K * uAbs(i-1);
                
                % Reset to zero when the input has a zero crossing with a
                % positive slope
                if((u(i) > 0) && (u(i-1) <= 0))
                    y(i) = 0;
                end
                
            end
            
            % Save state
            obj.yMinus1 = y(L);
            obj.uMinus1 = uAbs(L);
        end
        
        function resetImpl(obj)
            obj.yMinus1 = 0;
            obj.uMinus1 = 0;
        end
        
        function flag = isInputSizeMutableImpl(~,~)
            flag = true;
        end

        function s = saveObjectImpl(obj)
            s = saveObjectImpl@matlab.System(obj);
            if isLocked(obj)
                s.K = obj.K;
            end
        end

        function loadObjectImpl(obj, s, wasLocked)
            if wasLocked
                obj.K = s.K;
            end
            loadObjectImpl@matlab.System(obj,s,wasLocked);
        end
    end
end