/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "common/Trace.h"
#include "oboe/AudioClock.h"
#include "oboe/StabilizedCallback.h"

constexpr int32_t kLoadGenerationStepSizeNanos = 20000;
constexpr float kPercentageOfCallbackToUse = 0.8;

using namespace oboe;

StabilizedCallback::StabilizedCallback(AudioStreamCallback *callback) : mCallback(callback) {
}

/**
 * An audio callback which attempts to do work for a fixed amount of time.
 *
 * @param oboeStream
 * @param audioData
 * @param numFrames
 * @return
 */
DataCallbackResult
StabilizedCallback::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) {

    int64_t startTimeNanos = AudioClock::getNanoseconds();

    if (mFrameCount == 0){
        mEpochTimeNanos = startTimeNanos;
    }

    int64_t durationSinceEpochNanos = startTimeNanos - mEpochTimeNanos;

    // In an ideal world the callback start time will be exactly the same as the duration of the
    // frames already read/written into the stream. In reality the callback can start early
    // or late. By finding the delta we can calculate the target duration for our stabilized
    // callback.
    int64_t idealStartTimeNanos = (mFrameCount * kNanosPerSecond) / oboeStream->getSampleRate();
    int64_t lateStartNanos = durationSinceEpochNanos - idealStartTimeNanos;

    if (lateStartNanos < 0){
        // This was an early start which indicates that our previous epoch was a late callback.
        // Update our epoch to this more accurate time.
        mEpochTimeNanos = startTimeNanos;
        mFrameCount = 0;
    }

    int64_t numFramesAsNanos = (numFrames * kNanosPerSecond) / oboeStream->getSampleRate();
    int64_t targetDurationNanos = static_cast<int64_t>(
            (numFramesAsNanos * kPercentageOfCallbackToUse) - lateStartNanos);

    bool traceEnabled = Trace::getInstance().isEnabled();
    if (traceEnabled) Trace::getInstance().beginSection("Actual load");
    DataCallbackResult result = mCallback->onAudioReady(oboeStream, audioData, numFrames);
    if (traceEnabled) Trace::getInstance().endSection();

    int64_t executionDurationNanos = AudioClock::getNanoseconds() - startTimeNanos;
    int64_t stabilizingLoadDurationNanos = targetDurationNanos - executionDurationNanos;

    if (traceEnabled) Trace::getInstance().beginSection("Stabilized load for %lldns", stabilizingLoadDurationNanos);
    generateLoad(stabilizingLoadDurationNanos);
    if (traceEnabled) Trace::getInstance().endSection();

    // Wraparound: At 48000 frames per second mFrameCount wraparound will occur after 6m years,
    // significantly longer than the average lifetime of an Android phone.
    mFrameCount += numFrames;
    return result;
}

void StabilizedCallback::generateLoad(int64_t durationNanos) {

    int64_t currentTimeNanos = AudioClock::getNanoseconds();
    int64_t deadlineTimeNanos = currentTimeNanos + durationNanos;

    // opsPerStep gives us an estimated number of operations which need to be run to fully utilize
    // the CPU for a fixed amount of time (specified by kLoadGenerationStepSizeNanos).
    // After each step the opsPerStep value is re-calculated based on the actual time taken to
    // execute those operations.
    auto opsPerStep = (int)(mOpsPerNano * kLoadGenerationStepSizeNanos);
    int64_t stepDurationNanos = 0;
    int64_t previousTimeNanos = 0;

    while (currentTimeNanos <= deadlineTimeNanos){

        for (int i = 0; i < opsPerStep; i++) cpu_relax();

        previousTimeNanos = currentTimeNanos;
        currentTimeNanos = AudioClock::getNanoseconds();
        stepDurationNanos = currentTimeNanos - previousTimeNanos;

        // Calculate exponential moving average to smooth out values, this acts as a low pass filter.
        // @see https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
        static const float kFilterCoefficient = 0.1;
        auto measuredOpsPerNano = (double) opsPerStep / stepDurationNanos;
        mOpsPerNano = kFilterCoefficient * measuredOpsPerNano + (1.0 - kFilterCoefficient) * mOpsPerNano;
        opsPerStep = (int) (mOpsPerNano * kLoadGenerationStepSizeNanos);
    }
}
