/*
 * Copyright (C) 2014 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#include "pvamrwbdecoder.h"
#include <audio_utils/sndfile.h>

// Constants for AMR-WB.
enum {
    kInputBufferSize = 64,
    kSamplesPerFrame = 320,
    kBitsPerSample = 16,
    kOutputBufferSize = kSamplesPerFrame * kBitsPerSample/8,
    kSampleRate = 16000,
    kChannels = 1,
    kFileHeaderSize = 9,
    kMaxSourceDataUnitSize = 477 * sizeof(int16_t)
};

const uint32_t kFrameSizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60 };

int main(int argc, char *argv[]) {

    if (argc != 3) {
        fprintf(stderr, "Usage %s <input file> <output file>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // Open the input file.
    FILE* fpInput = fopen(argv[1], "rb");
    if (fpInput == NULL) {
        fprintf(stderr, "Could not open %s\n", argv[1]);
        return EXIT_FAILURE;
    }

    // Validate the input AMR file.
    char header[kFileHeaderSize];
    int bytesRead = fread(header, 1, kFileHeaderSize, fpInput);
    if ((bytesRead != kFileHeaderSize) ||
        (memcmp(header, "#!AMR-WB\n", kFileHeaderSize) != 0)) {
        fprintf(stderr, "Invalid AMR-WB file\n");
        fclose(fpInput);
        return EXIT_FAILURE;
    }

    // Open the output file.
    SF_INFO sfInfo;
    memset(&sfInfo, 0, sizeof(SF_INFO));
    sfInfo.channels = kChannels;
    sfInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    sfInfo.samplerate = kSampleRate;
    SNDFILE *handle = sf_open(argv[2], SFM_WRITE, &sfInfo);
    if (handle == NULL) {
        fprintf(stderr, "Could not create %s\n", argv[2]);
        fclose(fpInput);
        return EXIT_FAILURE;
    }

    // Allocate the decoder memory.
    uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
    void *decoderBuf = malloc(memRequirements);
    assert(decoderBuf != NULL);

    // Create AMR-WB decoder instance.
    void *amrHandle;
    int16_t *decoderCookie;
    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);

    // Allocate input buffer.
    uint8_t *inputBuf = (uint8_t*) malloc(kInputBufferSize);
    assert(inputBuf != NULL);

    // Allocate input sample buffer.
    int16_t *inputSampleBuf = (int16_t*) malloc(kMaxSourceDataUnitSize);
    assert(inputSampleBuf != NULL);

    // Allocate output buffer.
    int16_t *outputBuf = (int16_t*) malloc(kOutputBufferSize);
    assert(outputBuf != NULL);

    // Decode loop.
    int retVal = EXIT_SUCCESS;
    RX_State_wb rx_state{};
    while (1) {
        // Read mode.
        uint8_t modeByte;
        bytesRead = fread(&modeByte, 1, 1, fpInput);
        if (bytesRead != 1) break;
        int16 mode = ((modeByte >> 3) & 0x0f);

        // AMR-WB file format cannot have mode 10, 11, 12 and 13.
        if (mode >= 10 && mode <= 13) {
            fprintf(stderr, "Encountered illegal frame type %d\n", mode);
            retVal = EXIT_FAILURE;
            break;
        }

        if (mode >= 9) {
            // Produce silence for comfort noise, speech lost and no data.
            memset(outputBuf, 0, kOutputBufferSize);
        } else /* if (mode < 9) */ {
            // Read rest of the frame.
            int32_t frameSize = kFrameSizes[mode];
            bytesRead = fread(inputBuf, 1, frameSize, fpInput);
            if (bytesRead != frameSize) break;

            int16 frameType, frameMode;
            frameMode = mode;
            mime_unsorting(
                    (uint8_t *)inputBuf,
                    inputSampleBuf,
                    &frameType, &frameMode, 1, &rx_state);

            int16_t numSamplesOutput;
            pvDecoder_AmrWb(
                    frameMode, inputSampleBuf,
                    outputBuf,
                    &numSamplesOutput,
                    decoderBuf, frameType, decoderCookie);

            if (numSamplesOutput != kSamplesPerFrame) {
                fprintf(stderr, "Decoder encountered error\n");
                retVal = EXIT_FAILURE;
                break;
            }

            for (int i = 0; i < kSamplesPerFrame; ++i) {
                outputBuf[i] &= 0xfffC;
            }
        }

        // Write output to wav.
        sf_writef_short(handle, outputBuf, kSamplesPerFrame / kChannels);
    }

    // Close input and output file.
    fclose(fpInput);
    sf_close(handle);

    // Free allocated memory.
    free(inputBuf);
    free(inputSampleBuf);
    free(outputBuf);

    return retVal;
}
