/*
 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * 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 HOLDER 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.
 *
 */

#ifndef __MODULATOR_H__
#define __MODULATOR_H__
/*******************************************************************************
 * Standard C Included Files
 ******************************************************************************/
#include <stdint.h>
/*******************************************************************************
 * SDK Included Files
 ******************************************************************************/
#include "fsl_soundcard.h"
#include "fsl_sai_driver.h"
#include "fsl_sai_features.h"
/*******************************************************************************
 * Include CMSIS-DSP library
 ******************************************************************************/
#include "arm_math.h" 
/*******************************************************************************
 * Definitions
 ******************************************************************************/   
/* @brief Standard Winodws PCM wave file header length */
#define WAVE_FILE_HEADER_SIZE   0x2CU
#define WAV_PARTIAL_BUFFER_SIZE 512
#define WAV_PI 3.14159265
/*******************************************************************************
 * Constants
 ******************************************************************************/
/* Modulations available */
enum wav_mods
{
    kNoModulation,
    kSquareWave,
    kSawWave,
    kTriangleWave
};
/*******************************************************************************
 * Data Structures
 ******************************************************************************/
/* @brief Standard Windows PCM wave file header struct. */
typedef struct wave_header  
{  
    uint8_t  riff[4];
    uint32_t size;
    uint8_t  waveFlag[4];
    uint8_t  fmt[4];
    uint32_t fmtLen;
    uint16_t tag;
    uint16_t channels;
    uint32_t sampFreq;
    uint32_t byteRate;
    uint16_t blockAlign;
    uint16_t bitSamp;
    uint8_t  dataFlag[4];
    uint32_t length;
} wave_header_t;  
  
/* @brief Wave file struct */
typedef struct wave_file  
{  
    wave_header_t header;
    uint32_t *data;
} wave_file_t;

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/* 
 * @brief Initialize I2S, I2C, & TWR-AUDIO-SGTL board.
 *
 */
void modulator_init(void);

/*
 * @brief Collects data from wav file header.
 * 
 * @param waveFile Data structure of pcm data array.
 *
 * @return status_t Return kStatus_Success if function completed successfully, return kStatusFail if function failed.
 *
 */
snd_status_t get_wav_data(wave_file_t *waveFile);

/* 
 * @brief Play PCM audio data from wav format array.
 *
 * @param pcmBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param divider Integer to divide PCM data length to adjust audio sample duration.
 * 
 * @return status_t Return kStatus_Success if function completed successfully, return kStatusFail if function failed. 
 *
 */
snd_status_t play_wav(uint32_t *pcmBuffer, uint8_t divider);

/* 
 * @brief Send audio data to sound card.
 *
 * @param dataBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param length Length of data to send to sound card.
 * 
 * @param dataFormat Point to audio_data_format_t for sound card.
 *
 */
static void send_wav(uint8_t *dataBuffer, uint32_t length, sai_data_format_t *dataFormat);

/* 
 * @brief Play modulated PCM audio data from wav format array.
 *
 * @param pcmBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param modBuffer Pointer to data array to store modulated PCM data.
 * 
 * @param fftData Pointer to data array for storing Fast Fourier Transform data.
 * 
 * @param fftResult Point to data array for storing real frequency bins from FFT.
 * 
 * @param divider Integer to divide PCM data length to adjust audio sample duration.
 * 
 * @param modulation Constant representing type of waveform acheive from modulation.
 * 
 * @param srcSizeBytes Size of wav format array being processed.
 * 
 * @param sampleSize Size of sample for FFT (each sample is 16-bit integer from PCM data).
 * 
 * @return status_t Return kStatus_Success if function completed successfully, return kStatusFail if function failed. 
 *
 */
snd_status_t play_mod_wav(uint16_t *pcmBuffer, uint16_t *modPointer, float32_t *fftData, float32_t *fftResult, uint8_t divider, uint8_t modulation, uint32_t srcSizeBytes, uint32_t sampleSize);

/* 
 * @brief Find fundamental frequency of PCM data in wav format array.
 *
 * @param pcmBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param fftData Pointer to data array for storing Fast Fourier Transform data.
 * 
 * @param fftResult Point to data array for storing real frequency bins from FFT.
 * 
 * @param sampleSize Size of sample for FFT (each sample is 16-bit integer from PCM data).
 * 
 * @return float32_t Returns fundamental frequency in Hz. 
 *
 */
float32_t get_wav_Hz(uint16_t *pcmBuffer, float32_t *fftData, float32_t *fftResult, uint32_t sampleSize);

/* 
 * @brief Find fundamental frequency of PCM data in wav format array.
 *
 * @param pcmBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param modBuffer Pointer to data array to store modulated PCM data.
 * 
 * @param fftData Pointer to data array for storing Fast Fourier Transform data.
 * 
 * @param fftResult Point to data array for storing real frequency bins from FFT.
 *
 * @param startIndex Starting index of array to get PCM data from.
 *
 * @param sampleSize Size of sample for FFT (each sample is 16-bit integer from PCM data).
 *
 * @param modType Constant representing type of waveform acheive from modulation.
 *
 * @return float32_t Returns fundamental frequency in Hz. 
 *
 */
uint32_t mod_wav_data(uint16_t *pcmBuffer, uint16_t *modBuffer, float32_t *fftData, float32_t *fftResult, uint16_t startIndex, uint32_t sampleSize, uint8_t modType);

/* 
 * @brief Play modulated PCM audio data from array of wav format data arrays.
 *
 * @param arpeggioBuffer Pointer to data array containing wav formatted audio data.
 * 
 * @param introLength The number of notes in the arpeggio. 
 * 
 * @param divider Integer to divide PCM data length to adjust audio sample duration.
 * 
 */
void play_wav_arpeggio(uint32_t *arpeggioBuffer, uint32_t introLength, uint8_t divider);

#endif /* __MODULATOR_H__ */

/*******************************************************************************
 * EOF                                           
 *******************************************************************************/