/*
 * Copyright (C) 2017 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.
 */

#define LOG_TAG "AAudioMixer"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#define ATRACE_TAG ATRACE_TAG_AUDIO

#include <cstring>
#include <utils/Trace.h>

#include "AAudioMixer.h"

#ifndef AAUDIO_MIXER_ATRACE_ENABLED
#define AAUDIO_MIXER_ATRACE_ENABLED    1
#endif

using android::WrappingBuffer;
using android::FifoBuffer;
using android::fifo_frames_t;

void AAudioMixer::allocate(int32_t samplesPerFrame, int32_t framesPerBurst) {
    mSamplesPerFrame = samplesPerFrame;
    mFramesPerBurst = framesPerBurst;
    int32_t samplesPerBuffer = samplesPerFrame * framesPerBurst;
    mOutputBuffer = std::make_unique<float[]>(samplesPerBuffer);
    mBufferSizeInBytes = samplesPerBuffer * sizeof(float);
}

void AAudioMixer::clear() {
    memset(mOutputBuffer.get(), 0, mBufferSizeInBytes);
}

int32_t AAudioMixer::mix(
        int streamIndex, const std::shared_ptr<FifoBuffer>& fifo, bool allowUnderflow) {
    WrappingBuffer wrappingBuffer;
    float *destination = mOutputBuffer.get();

#if AAUDIO_MIXER_ATRACE_ENABLED
    ATRACE_BEGIN("aaMix");
#endif /* AAUDIO_MIXER_ATRACE_ENABLED */

    // Gather the data from the client. May be in two parts.
    fifo_frames_t fullFrames = fifo->getFullDataAvailable(&wrappingBuffer);
#if AAUDIO_MIXER_ATRACE_ENABLED
    if (ATRACE_ENABLED()) {
        char rdyText[] = "aaMixRdy#";
        char letter = 'A' + (streamIndex % 26);
        rdyText[sizeof(rdyText) - 2] = letter;
        ATRACE_INT(rdyText, fullFrames);
    }
#else /* MIXER_ATRACE_ENABLED */
    (void) trackIndex;
#endif /* AAUDIO_MIXER_ATRACE_ENABLED */

    // If allowUnderflow then always advance by one burst even if we do not have the data.
    // Otherwise the stream timing will drift whenever there is an underflow.
    // This actual underflow can then be detected by the client for XRun counting.
    //
    // Generally, allowUnderflow will be false when stopping a stream and we want to
    // use up whatever data is in the queue.
    fifo_frames_t framesDesired = mFramesPerBurst;
    if (!allowUnderflow && fullFrames < framesDesired) {
        framesDesired = fullFrames; // just use what is available then stop
    }

    // Mix data in one or two parts.
    int partIndex = 0;
    int32_t framesLeft = framesDesired;
    while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) {
        fifo_frames_t framesToMixFromPart = framesLeft;
        fifo_frames_t framesAvailableFromPart = wrappingBuffer.numFrames[partIndex];
        if (framesAvailableFromPart > 0) {
            if (framesToMixFromPart > framesAvailableFromPart) {
                framesToMixFromPart = framesAvailableFromPart;
            }
            mixPart(destination, (float *)wrappingBuffer.data[partIndex],
                    framesToMixFromPart);

            destination += framesToMixFromPart * mSamplesPerFrame;
            framesLeft -= framesToMixFromPart;
        }
        partIndex++;
    }
    fifo->advanceReadIndex(framesDesired);

#if AAUDIO_MIXER_ATRACE_ENABLED
    ATRACE_END();
#endif /* AAUDIO_MIXER_ATRACE_ENABLED */

    return (framesDesired - framesLeft); // framesRead
}

void AAudioMixer::mixPart(float *destination, float *source, int32_t numFrames) {
    int32_t numSamples = numFrames * mSamplesPerFrame;
    // TODO maybe optimize using SIMD
    for (int sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
        *destination++ += *source++;
    }
}

float *AAudioMixer::getOutputBuffer() {
    return mOutputBuffer.get();
}
