/*===================================================

AudioEventMgr.cpp

A manager for audio events

Written by Alan Wolfe 6/2012

===================================================*/

#include "AudioEventMgr.h"
#include "AudioEvent.h"
#include "wavefile.h"

CAudioEventMgr::CAudioEventMgr(int nSampleRate, int nNumChannels, float fNumSeconds)
:m_nSampleRate(nSampleRate)
,m_nNumChannels(nNumChannels)
,m_fNumSeconds(fNumSeconds)
,m_pRenderedData(NULL)
,m_nNumSamples(0)
,m_nGlobalBlock(0)
,m_fGlobalTime(0.0f)
{
}

CAudioEventMgr::~CAudioEventMgr()
{
	//free the memory for each audio event
	for(AudioEventList::iterator it = m_AudioEvents.begin(); it != m_AudioEvents.end(); ++it)
	{
		delete *it;
	}

	//clear the audio event list
	m_AudioEvents.clear();

	//free the rendered data if we have any
	delete[] m_pRenderedData;
}

void CAudioEventMgr::GetSample(float *pBlock, int nNumBlock, int nNumChannels, int nSampleRate)
{
	//initialize the sample(s) to zero
	pBlock[0] = 0.0f;
	if(nNumChannels == 2)
	{
		pBlock[1] = 0.0f;
	}

	m_nGlobalBlock = nNumBlock;
	m_fGlobalTime = ((float)nNumBlock) / ((float)nSampleRate);

	//let each active audio event contribute to the sample
	for(AudioEventList::iterator it = m_AudioEvents.begin(); it != m_AudioEvents.end(); ++it)
	{
		//if this block is in between the start and end block of this audio event, get the sample
		if((*it)->BlockInRange(nNumBlock))
		{
			(*it)->GetSample(pBlock,nNumBlock - (*it)->GetStartBlock(),nNumChannels,nSampleRate);
		}
	}
}

void CAudioEventMgr::RenderWaveFileUint8(const char *szFileName, bool bNormalizeData /*= true*/)
{
	Render();
	WriteWaveFileUint8(szFileName,m_pRenderedData,m_nNumSamples,m_nNumChannels,m_nSampleRate,bNormalizeData);
}

void CAudioEventMgr::RenderWaveFileInt16(const char *szFileName, bool bNormalizeData /*= true*/)
{
	Render();
	WriteWaveFileInt16(szFileName,m_pRenderedData,m_nNumSamples,m_nNumChannels,m_nSampleRate,bNormalizeData);
}

void CAudioEventMgr::RenderWaveFileInt32(const char *szFileName, bool bNormalizeData /*= true*/)
{
	Render();
	WriteWaveFileInt32(szFileName,m_pRenderedData,m_nNumSamples,m_nNumChannels,m_nSampleRate,bNormalizeData);
}

void CAudioEventMgr::Render(void)
{
	//make sure to free any rendered data if there is any
	delete[] m_pRenderedData;

	//calculate the number of samples and allocate space for the new samples
	m_nNumSamples = (int)((float)m_nSampleRate * m_fNumSeconds * (float)m_nNumChannels);
	m_pRenderedData = new float[m_nNumSamples];

	//render each sample
	for(int nIndex = 0; nIndex < m_nNumSamples; nIndex += m_nNumChannels)
	{
		GetSample(&m_pRenderedData[nIndex], nIndex / m_nNumChannels, m_nNumChannels, m_nSampleRate);
	}
}
