classdef AudioLoopTimer < handle
% This class is only in support of the featured example 'Measuring
% Performance of Streaming Real-Time Audio Algorithms'. It may change in a
% future release.

% Copyright 2015 The MathWorks, Inc.

    properties(GetAccess = public, SetAccess = private)
        LoopTimes
        InitTime
    end
    
    properties(Access = private)
        pInitTic
        pLoopTic
        pLoopPtr
        pNumFrames
        pSamplesPerFrame
        pFs
    end
    
    methods
        function obj = AudioLoopTimer(numFrames, samplesPerFrame, fs)
            obj.LoopTimes = nan(numFrames,1);
            obj.InitTime = nan;
            obj.pLoopPtr = 1;
            obj.pNumFrames = numFrames;
            obj.pSamplesPerFrame = samplesPerFrame;
            obj.pFs = fs;
        end
        
        function ticInit(obj)
            obj.pInitTic = tic;
        end
        
        function tocInit(obj)
            obj.InitTime = toc(obj.pInitTic);
        end
        
        function ticLoop(obj)
            obj.pLoopTic = tic;
        end
        
        function tocLoop(obj)
            obj.LoopTimes(obj.pLoopPtr) = toc(obj.pLoopTic);
            obj.pLoopPtr = obj.pLoopPtr + 1;
        end
        
        function [results,figHandle] = generateReport(obj)
            budget =  obj.pSamplesPerFrame/obj.pFs;
            et_loop = obj.LoopTimes;
            et_init = obj.InitTime;
            
            results.InitTime         = et_init;
            results.MedianLoopTime   = median(et_loop,'omitnan');
            results.MaxLoopTime      = max(et_loop);
            results.BudgetPerLoop      = budget;
            
            figHandle  = figure('Name','Loop Execution Timing Report');
            subplot(2,1,1)
            hh = histogram(et_loop,100);
            hold on
            plot(budget * [1 1], hh.Parent.YLim,':r','LineWidth',2)
            title('Loop Execution Time Histogram')
            xlabel('Loop Processing Time (s)')
            ylabel('# of occurrences')
            grid on
            str = sprintf('Init time:         \t\t        %.5f s\n',results.InitTime  );
            str = sprintf('%sMedian loop time: \t\t %.5f s\n',str, results.MedianLoopTime );
            str = sprintf('%sMax loop time:    \t\t   %.5f s\n',str, results.MaxLoopTime );
            str = sprintf('%sBudget per loop:   \t\t %.5f s\n',str, results.BudgetPerLoop );
            text(hh.Parent.XLim(2)/3,(1/2)*hh.Parent.YLim(2),str)

            subplot(2,1,2)
            plot(et_loop,'.-')
            hold on
            plot(budget * ones(size(et_loop)),':r','LineWidth',2)
            xlabel('Loop number')
            ylabel('Loop processing time (s)')
            hold off
            title('Loop Execution Time History')
            grid on
            
        end
    end
    
end