Skip to content

File CpuLoadMeter.h

File List > external-docs > libDaisy > src > util > CpuLoadMeter.h

Go to the documentation of this file

Source Code

#pragma once

#include "sys/system.h"
#include <cmath>

namespace daisy
{
class CpuLoadMeter
{
  public:
    CpuLoadMeter(){};

    void Init(float sampleRateInHz,
              int   blockSizeInSamples,
              float smoothingFilterCutoffHz = 1.0f)
    {
        const auto secPerBlock = float(blockSizeInSamples) / sampleRateInHz;
        const auto ticksPerS   = float(System::GetTickFreq());
        ticksPerBlockInv_      = 1.0f / (ticksPerS * secPerBlock);

        // update filter coefficient for smoothing filter (1pole lowpass)
        const auto blockRateInHz = sampleRateInHz / float(blockSizeInSamples);
        const auto cutoffNormalized
            = smoothingFilterCutoffHz * 2.0f * 3.141592653f / blockRateInHz;
        // according to
        // https://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter
        smoothingConstant_ = cutoffNormalized / (cutoffNormalized + 1.0f);

        Reset();
    }

    void OnBlockStart() { currentBlockStartTicks_ = System::GetTick(); }

    void OnBlockEnd()
    {
        const auto end         = System::GetTick();
        const auto ticksPassed = end - currentBlockStartTicks_;
        const auto currentBlockLoad
            = float(ticksPassed) * ticksPerBlockInv_; // usPassed / usPerBlock

        if(firstCycle_)
        {
            max_ = min_ = avg_ = currentBlockLoad;
            firstCycle_        = false;
        }
        else
        {
            if(currentBlockLoad > max_)
                max_ = currentBlockLoad;
            if(currentBlockLoad < min_)
                min_ = currentBlockLoad;

            avg_ = smoothingConstant_ * currentBlockLoad
                   + (1.0f - smoothingConstant_) * avg_;
        }
    }

    float GetAvgCpuLoad() const { return avg_; }
    float GetMinCpuLoad() const { return min_; }
    float GetMaxCpuLoad() const { return max_; }

    void Reset()
    {
        firstCycle_ = true;
        avg_ = max_ = min_ = NAN;
    }

  private:
    bool     firstCycle_;
    float    ticksPerBlockInv_;
    uint32_t currentBlockStartTicks_;
    float    min_;
    float    max_;
    float    avg_;
    float    smoothingConstant_;

    CpuLoadMeter(const CpuLoadMeter&) = delete;
    CpuLoadMeter& operator=(const CpuLoadMeter&) = delete;
};
} // namespace daisy