/*
 * 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.
 */

// Play sine waves using AAudio.

#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>
#include <asm/fcntl.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "AAudioExampleUtils.h"
#include "AAudioSimplePlayer.h"
#include "AAudioArgsParser.h"

#define NUM_SECONDS           4

int main(int argc, const char **argv)
{
    AAudioArgsParser   argParser;
    AAudioSimplePlayer player;
    SineThreadedData_t myData;
    aaudio_result_t    result = AAUDIO_OK;

    int32_t         actualChannelCount = 0;
    int32_t         actualSampleRate = 0;
    aaudio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;

    AAudioStream *aaudioStream = nullptr;
    int32_t  framesPerBurst = 0;
    int32_t  framesPerWrite = 0;
    int32_t  framesToPlay = 0;
    int32_t  framesLeft = 0;
    int32_t  xRunCount = 0;
    float   *floatData = nullptr;
    int16_t *shortData = nullptr;

    int      testFd = -1;

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

    printf("%s - Play a sine wave using AAudio V0.1.1\n", argv[0]);

    if (argParser.parseArgs(argc, argv)) {
        return EXIT_FAILURE;
    }

    result = player.open(argParser);
    if (result != AAUDIO_OK) {
        fprintf(stderr, "ERROR -  player.open() returned %d\n", result);
        goto finish;
    }

    aaudioStream = player.getStream();

    argParser.compareWithStream(aaudioStream);

    actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
    actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
    actualDataFormat = AAudioStream_getFormat(aaudioStream);

    myData.sineOsc1.setup(440.0, actualSampleRate);
    myData.sineOsc2.setup(660.0, actualSampleRate);

    // Some DMA might use very short bursts of 16 frames. We don't need to write such small
    // buffers. But it helps to use a multiple of the burst size for predictable scheduling.
    framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
    framesPerWrite = framesPerBurst;
    while (framesPerWrite < 48) {
        framesPerWrite *= 2;
    }
    printf("Buffer: framesPerBurst = %d\n",framesPerBurst);
    printf("Buffer: framesPerWrite = %d\n",framesPerWrite);

    // Allocate a buffer for the audio data.
    if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
        floatData = new float[framesPerWrite * actualChannelCount];
    } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
        shortData = new int16_t[framesPerWrite * actualChannelCount];
    } else {
        printf("ERROR Unsupported data format!\n");
        goto finish;
    }

    testFd = open("/data/aaudio_temp.raw", O_CREAT | O_RDWR, S_IRWXU);
    printf("testFd = %d, pid = %d\n", testFd, getpid());

    // Start the stream.
    printf("call player.start()\n");
    result = player.start();
    if (result != AAUDIO_OK) {
        fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d\n", result);
        goto finish;
    }

    printf("after start, state = %s\n",
            AAudio_convertStreamStateToText(AAudioStream_getState(aaudioStream)));

    // Play for a while.
    framesToPlay = actualSampleRate * argParser.getDurationSeconds();
    framesLeft = framesToPlay;
    while (framesLeft > 0) {

        if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
            // Render sine waves to left and right channels.
            myData.sineOsc1.render(&floatData[0], actualChannelCount, framesPerWrite);
            if (actualChannelCount > 1) {
                myData.sineOsc2.render(&floatData[1], actualChannelCount, framesPerWrite);
            }
        } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
            // Render sine waves to left and right channels.
            myData.sineOsc1.render(&shortData[0], actualChannelCount, framesPerWrite);
            if (actualChannelCount > 1) {
                myData.sineOsc2.render(&shortData[1], actualChannelCount, framesPerWrite);
            }
        }

        // Write audio data to the stream.
        int64_t timeoutNanos = 1000 * NANOS_PER_MILLISECOND;
        int32_t minFrames = (framesToPlay < framesPerWrite) ? framesToPlay : framesPerWrite;
        int32_t actual = 0;
        if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
            actual = AAudioStream_write(aaudioStream, floatData, minFrames, timeoutNanos);
        } else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
            actual = AAudioStream_write(aaudioStream, shortData, minFrames, timeoutNanos);
        }
        if (actual < 0) {
            fprintf(stderr, "ERROR - AAudioStream_write() returned %d\n", actual);
            goto finish;
        } else if (actual == 0) {
            fprintf(stderr, "WARNING - AAudioStream_write() returned %d\n", actual);
            goto finish;
        }
        framesLeft -= actual;

        // Use timestamp to estimate latency.
        /*
        {
            int64_t presentationFrame;
            int64_t presentationTime;
            result = AAudioStream_getTimestamp(aaudioStream,
                                               CLOCK_MONOTONIC,
                                               &presentationFrame,
                                               &presentationTime
                                               );
            if (result == AAUDIO_OK) {
                int64_t elapsedNanos = getNanoseconds() - presentationTime;
                int64_t elapsedFrames = actualSampleRate * elapsedNanos / NANOS_PER_SECOND;
                int64_t currentFrame = presentationFrame + elapsedFrames;
                int64_t framesWritten = AAudioStream_getFramesWritten(aaudioStream);
                int64_t estimatedLatencyFrames = framesWritten - currentFrame;
                int64_t estimatedLatencyMillis = estimatedLatencyFrames * 1000 / actualSampleRate;
                printf("estimatedLatencyMillis %d\n", (int)estimatedLatencyMillis);
            }
        }
         */
    }

    xRunCount = AAudioStream_getXRunCount(aaudioStream);
    printf("AAudioStream_getXRunCount %d\n", xRunCount);

    printf("call stop()\n");
    result = player.stop();
    if (result != AAUDIO_OK) {
        goto finish;
    }

finish:
    printf("testFd = %d, fcntl before aaudio close returns 0x%08X\n",
           testFd, fcntl(testFd, F_GETFD));
    player.close();
    printf("testFd = %d, fcntl after aaudio close returns 0x%08X\n",
           testFd, fcntl(testFd, F_GETFD));
    if (::close(testFd) != 0) {
        printf("ERROR SharedMemoryParcelable::close() of testFd = %d, errno = %s\n",
               testFd, strerror(errno));
    }
    printf("testFd = %d, fcntl after close() returns 0x%08X\n", testFd, fcntl(testFd, F_GETFD));

    delete[] floatData;
    delete[] shortData;
    printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
    return (result != AAUDIO_OK) ? EXIT_FAILURE : EXIT_SUCCESS;
}

