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

// Audio loopback tests to measure the round trip latency and glitches.

#include <algorithm>
#include <assert.h>
#include <cctype>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>

#include "AAudioSimplePlayer.h"
#include "AAudioSimpleRecorder.h"
#include "AAudioExampleUtils.h"
#include "LoopbackAnalyzer.h"

// Tag for machine readable results as property = value pairs
#define RESULT_TAG              "RESULT: "
#define SAMPLE_RATE             48000
#define NUM_SECONDS             5
#define NUM_INPUT_CHANNELS      1
#define FILENAME                "/data/oboe_input.raw"
#define APP_VERSION             "0.1.22"

struct LoopbackData {
    AAudioStream      *inputStream = nullptr;
    int32_t            inputFramesMaximum = 0;
    int16_t           *inputData = nullptr;
    int16_t            peakShort = 0;
    float             *conversionBuffer = nullptr;
    int32_t            actualInputChannelCount = 0;
    int32_t            actualOutputChannelCount = 0;
    int32_t            inputBuffersToDiscard = 10;
    int32_t            minNumFrames = INT32_MAX;
    int32_t            maxNumFrames = 0;
    bool               isDone = false;

    aaudio_result_t    inputError = AAUDIO_OK;
    aaudio_result_t    outputError = AAUDIO_OK;

    SineAnalyzer       sineAnalyzer;
    EchoAnalyzer       echoAnalyzer;
    AudioRecording     audioRecorder;
    LoopbackProcessor *loopbackProcessor;
};

static void convertPcm16ToFloat(const int16_t *source,
                                float *destination,
                                int32_t numSamples) {
    const float scaler = 1.0f / 32768.0f;
    for (int i = 0; i < numSamples; i++) {
        destination[i] = source[i] * scaler;
    }
}

// ====================================================================================
// ========================= CALLBACK =================================================
// ====================================================================================
// Callback function that fills the audio output buffer.
static aaudio_data_callback_result_t MyDataCallbackProc(
        AAudioStream *outputStream,
        void *userData,
        void *audioData,
        int32_t numFrames
) {
    (void) outputStream;
    aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_CONTINUE;
    LoopbackData *myData = (LoopbackData *) userData;
    float  *outputData = (float  *) audioData;

    // Read audio data from the input stream.
    int32_t framesRead;

    if (numFrames > myData->inputFramesMaximum) {
        myData->inputError = AAUDIO_ERROR_OUT_OF_RANGE;
        return AAUDIO_CALLBACK_RESULT_STOP;
    }

    if (numFrames > myData->maxNumFrames) {
        myData->maxNumFrames = numFrames;
    }
    if (numFrames < myData->minNumFrames) {
        myData->minNumFrames = numFrames;
    }

    if (myData->inputBuffersToDiscard > 0) {
        // Drain the input.
        do {
            framesRead = AAudioStream_read(myData->inputStream, myData->inputData,
                                       numFrames, 0);
            if (framesRead < 0) {
                myData->inputError = framesRead;
                printf("ERROR in read = %d", framesRead);
                result = AAUDIO_CALLBACK_RESULT_STOP;
            } else if (framesRead > 0) {
                myData->inputBuffersToDiscard--;
            }
        } while(framesRead > 0);
    } else {
        framesRead = AAudioStream_read(myData->inputStream, myData->inputData,
                                       numFrames, 0);
        if (framesRead < 0) {
            myData->inputError = framesRead;
            printf("ERROR in read = %d", framesRead);
            result = AAUDIO_CALLBACK_RESULT_STOP;
        } else if (framesRead > 0) {

            myData->audioRecorder.write(myData->inputData,
                                        myData->actualInputChannelCount,
                                        numFrames);

            int32_t numSamples = framesRead * myData->actualInputChannelCount;
            convertPcm16ToFloat(myData->inputData, myData->conversionBuffer, numSamples);

            myData->loopbackProcessor->process(myData->conversionBuffer,
                                              myData->actualInputChannelCount,
                                              outputData,
                                              myData->actualOutputChannelCount,
                                              framesRead);
            myData->isDone = myData->loopbackProcessor->isDone();
            if (myData->isDone) {
                result = AAUDIO_CALLBACK_RESULT_STOP;
            }
        }
    }

    return result;
}

static void MyErrorCallbackProc(
        AAudioStream *stream __unused,
        void *userData __unused,
        aaudio_result_t error)
{
    printf("Error Callback, error: %d\n",(int)error);
    LoopbackData *myData = (LoopbackData *) userData;
    myData->outputError = error;
}

static void usage() {
    printf("loopback: -n{numBursts} -p{outPerf} -P{inPerf} -t{test} -g{gain} -f{freq}\n");
    printf("          -c{inputChannels}\n");
    printf("          -f{freq}  sine frequency\n");
    printf("          -g{gain}  recirculating loopback gain\n");
    printf("          -m enable MMAP mode\n");
    printf("          -n{numBursts} buffer size, for example 2 for double buffered\n");
    printf("          -p{outPerf}  set output AAUDIO_PERFORMANCE_MODE*\n");
    printf("          -P{inPerf}   set input AAUDIO_PERFORMANCE_MODE*\n");
    printf("              n for _NONE\n");
    printf("              l for _LATENCY\n");
    printf("              p for _POWER_SAVING;\n");
    printf("          -t{test}   select test mode\n");
    printf("              m for sine magnitude\n");
    printf("              e for echo latency (default)\n");
    printf("For example:  loopback -b2 -pl -Pn\n");
}

static aaudio_performance_mode_t parsePerformanceMode(char c) {
    aaudio_performance_mode_t mode = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    c = tolower(c);
    switch (c) {
        case 'n':
            mode = AAUDIO_PERFORMANCE_MODE_NONE;
            break;
        case 'l':
            mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
            break;
        case 'p':
            mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
            break;
        default:
            printf("ERROR in value performance mode %c\n", c);
            break;
    }
    return mode;
}

enum {
    TEST_SINE_MAGNITUDE = 0,
    TEST_ECHO_LATENCY,
};

static int parseTestMode(char c) {
    int testMode = TEST_ECHO_LATENCY;
    c = tolower(c);
    switch (c) {
        case 'm':
            testMode = TEST_SINE_MAGNITUDE;
            break;
        case 'e':
            testMode = TEST_ECHO_LATENCY;
            break;
        default:
            printf("ERROR in value test mode %c\n", c);
            break;
    }
    return testMode;
}

void printAudioGraph(AudioRecording &recording, int numSamples) {
    int32_t start = recording.size() / 2;
    int32_t end = start + numSamples;
    if (end >= recording.size()) {
        end = recording.size() - 1;
    }
    float *data = recording.getData();
    // Normalize data so we can see it better.
    float maxSample = 0.01;
    for (int32_t i = start; i < end; i++) {
        float samplePos = fabs(data[i]);
        if (samplePos > maxSample) {
            maxSample = samplePos;
        }
    }
    float gain = 0.98f / maxSample;
    for (int32_t i = start; i < end; i++) {
        float sample = data[i];
        printf("%5.3f ", sample); // actual value
        sample *= gain;
        printAudioScope(sample);
    }
}


// ====================================================================================
// TODO break up this large main() function into smaller functions
int main(int argc, const char **argv)
{

    AAudioArgsParser     argParser;
    AAudioSimplePlayer   player;
    AAudioSimpleRecorder recorder;
    LoopbackData         loopbackData;
    AAudioStream        *outputStream = nullptr;

    aaudio_result_t      result = AAUDIO_OK;
    aaudio_sharing_mode_t requestedInputSharingMode     = AAUDIO_SHARING_MODE_SHARED;
    int                   requestedInputChannelCount = NUM_INPUT_CHANNELS;
    const aaudio_format_t requestedInputFormat = AAUDIO_FORMAT_PCM_I16;
    const aaudio_format_t requestedOutputFormat = AAUDIO_FORMAT_PCM_FLOAT;
    aaudio_format_t       actualInputFormat;
    aaudio_format_t       actualOutputFormat;
    aaudio_performance_mode_t inputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;

    int testMode = TEST_ECHO_LATENCY;
    double gain = 1.0;

    int32_t framesPerBurst = 0;
    float *outputData = NULL;

    // Make printf print immediately so that debug info is not stuck
    // in a buffer if we hang or crash.
    setvbuf(stdout, NULL, _IONBF, (size_t) 0);

    printf("%s - Audio loopback using AAudio V" APP_VERSION "\n", argv[0]);

    for (int i = 1; i < argc; i++) {
        const char *arg = argv[i];
        if (argParser.parseArg(arg)) {
            // Handle options that are not handled by the ArgParser
            if (arg[0] == '-') {
                char option = arg[1];
                switch (option) {
                    case 'C':
                        requestedInputChannelCount = atoi(&arg[2]);
                        break;
                    case 'g':
                        gain = atof(&arg[2]);
                        break;
                    case 'P':
                        inputPerformanceLevel = parsePerformanceMode(arg[2]);
                        break;
                    case 'X':
                        requestedInputSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
                        break;
                    case 't':
                        testMode = parseTestMode(arg[2]);
                        break;
                    default:
                        usage();
                        exit(EXIT_FAILURE);
                        break;
                }
            } else {
                usage();
                exit(EXIT_FAILURE);
                break;
            }
        }

    }

    if (inputPerformanceLevel < 0) {
        printf("illegal inputPerformanceLevel = %d\n", inputPerformanceLevel);
        exit(EXIT_FAILURE);
    }

    int32_t requestedDuration = argParser.getDurationSeconds();
    int32_t recordingDuration = std::min(60, requestedDuration);
    loopbackData.audioRecorder.allocate(recordingDuration * SAMPLE_RATE);

    switch(testMode) {
        case TEST_SINE_MAGNITUDE:
            loopbackData.loopbackProcessor = &loopbackData.sineAnalyzer;
            break;
        case TEST_ECHO_LATENCY:
            loopbackData.echoAnalyzer.setGain(gain);
            loopbackData.loopbackProcessor = &loopbackData.echoAnalyzer;
            break;
        default:
            exit(1);
            break;
    }

    printf("OUTPUT stream ----------------------------------------\n");
    argParser.setFormat(requestedOutputFormat);
    result = player.open(argParser, MyDataCallbackProc, MyErrorCallbackProc, &loopbackData);
    if (result != AAUDIO_OK) {
        fprintf(stderr, "ERROR -  player.open() returned %d\n", result);
        goto finish;
    }
    outputStream = player.getStream();
    argParser.compareWithStream(outputStream);

    actualOutputFormat = AAudioStream_getFormat(outputStream);
    assert(actualOutputFormat == AAUDIO_FORMAT_PCM_FLOAT);

    printf("INPUT stream ----------------------------------------\n");
    // Use different parameters for the input.
    argParser.setNumberOfBursts(AAUDIO_UNSPECIFIED);
    argParser.setFormat(requestedInputFormat);
    argParser.setPerformanceMode(inputPerformanceLevel);
    argParser.setChannelCount(requestedInputChannelCount);
    argParser.setSharingMode(requestedInputSharingMode);
    result = recorder.open(argParser);
    if (result != AAUDIO_OK) {
        fprintf(stderr, "ERROR -  recorder.open() returned %d\n", result);
        goto finish;
    }
    loopbackData.inputStream = recorder.getStream();
    argParser.compareWithStream(loopbackData.inputStream);

    // This is the number of frames that are read in one chunk by a DMA controller
    // or a DSP or a mixer.
    framesPerBurst = AAudioStream_getFramesPerBurst(outputStream);

    actualInputFormat = AAudioStream_getFormat(outputStream);
    assert(actualInputFormat == AAUDIO_FORMAT_PCM_I16);


    loopbackData.actualInputChannelCount = recorder.getChannelCount();
    loopbackData.actualOutputChannelCount = player.getChannelCount();

    // Allocate a buffer for the audio data.
    loopbackData.inputFramesMaximum = 32 * framesPerBurst;
    loopbackData.inputBuffersToDiscard = 100;

    loopbackData.inputData = new int16_t[loopbackData.inputFramesMaximum
                                         * loopbackData.actualInputChannelCount];
    loopbackData.conversionBuffer = new float[loopbackData.inputFramesMaximum *
                                              loopbackData.actualInputChannelCount];

    loopbackData.loopbackProcessor->reset();

    result = recorder.start();
    if (result != AAUDIO_OK) {
        printf("ERROR - AAudioStream_requestStart(input) returned %d = %s\n",
               result, AAudio_convertResultToText(result));
        goto finish;
    }

    result = player.start();
    if (result != AAUDIO_OK) {
        printf("ERROR - AAudioStream_requestStart(output) returned %d = %s\n",
               result, AAudio_convertResultToText(result));
        goto finish;
    }

    printf("------- sleep while the callback runs --------------\n");
    fflush(stdout);
    for (int i = requestedDuration; i > 0 ; i--) {
        if (loopbackData.inputError != AAUDIO_OK) {
            printf("  ERROR on input stream\n");
            break;
        } else if (loopbackData.outputError != AAUDIO_OK) {
                printf("  ERROR on output stream\n");
                break;
        } else if (loopbackData.isDone) {
                printf("  test says it is done!\n");
                break;
        } else {
            sleep(1);
            printf("%4d: ", i);
            loopbackData.loopbackProcessor->printStatus();
            int64_t framesWritten = AAudioStream_getFramesWritten(loopbackData.inputStream);
            int64_t framesRead = AAudioStream_getFramesRead(loopbackData.inputStream);
            printf(" input written = %lld, read %lld, xruns = %d\n",
                   (long long) framesWritten,
                   (long long) framesRead,
                   AAudioStream_getXRunCount(outputStream)
            );
        }
    }

    printf("input error = %d = %s\n",
                loopbackData.inputError, AAudio_convertResultToText(loopbackData.inputError));

    printf("AAudioStream_getXRunCount %d\n", AAudioStream_getXRunCount(outputStream));
    printf("framesRead    = %8d\n", (int) AAudioStream_getFramesRead(outputStream));
    printf("framesWritten = %8d\n", (int) AAudioStream_getFramesWritten(outputStream));
    printf("min numFrames = %8d\n", (int) loopbackData.minNumFrames);
    printf("max numFrames = %8d\n", (int) loopbackData.maxNumFrames);

    if (loopbackData.inputError == AAUDIO_OK) {
        if (testMode == TEST_SINE_MAGNITUDE) {
            printAudioGraph(loopbackData.audioRecorder, 200);
        }
        loopbackData.loopbackProcessor->report();
    }

    {
        int written = loopbackData.audioRecorder.save(FILENAME);
        printf("main() wrote %d mono samples to %s on Android device\n", written, FILENAME);
    }

finish:
    player.close();
    recorder.close();
    delete[] loopbackData.conversionBuffer;
    delete[] loopbackData.inputData;
    delete[] outputData;

    printf(RESULT_TAG "error = %d = %s\n", result, AAudio_convertResultToText(result));
    if ((result != AAUDIO_OK)) {
        printf("error %d = %s\n", result, AAudio_convertResultToText(result));
        return EXIT_FAILURE;
    } else {
        printf("SUCCESS\n");
        return EXIT_SUCCESS;
    }
}

