// WaveFFT.cpp: Implementierung der Klasse CWaveFFT.
//
//////////////////////////////////////////////////////////////////////

#include "WaveFFT.h"
#include "Windows.h"
#include "Fourierd.c"

#define SAFE_FREE(p)    { if(p) { free(p);        (p)=NULL; } }
#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

CWaveFFT::CWaveFFT()
{
	m_iSampleFrequency = 0;
	m_piAnalysedData = NULL;
	m_bWindow = false;
	m_iFFTSize = 0;
	m_piStopFreq = NULL;
	m_iNumStopFreq = 0;
	m_iFFTStepWidth = 0;
	m_iNumAnalyzedData = 0;
}

CWaveFFT::~CWaveFFT()
{
	SAFE_FREE(m_piAnalysedData);
	SAFE_FREE(m_piStopFreq);
}

void CWaveFFT::Init(int SampleFrequency, int FFTSize, int FFTStepWidth, bool Window) 
{
	m_iSampleFrequency = SampleFrequency;
	m_iFFTSize = FFTSize;
	m_iFFTStepWidth = FFTStepWidth;
	m_bWindow = Window;
}

void CWaveFFT::AnalyzeData(void* WaveData, int WaveSize)
{
	double* RealIn	= (double*)malloc(sizeof(double) * m_iFFTSize);
	double* ImgIn	= (double*)malloc(sizeof(double) * m_iFFTSize);
	double* RealOut = (double*)malloc(sizeof(double) * m_iFFTSize);
	double* ImgOut	= (double*)malloc(sizeof(double) * m_iFFTSize);


	SAFE_FREE(m_piAnalysedData);
	m_iNumAnalyzedData = WaveSize / 2 / 2 / m_iFFTStepWidth - (m_iFFTSize / m_iFFTStepWidth);
	m_piAnalysedData = (__int16*)malloc(sizeof(__int16) * m_iNumAnalyzedData * m_iNumStopFreq + 100 * 3);
	FillMemory( (__int16*) m_piAnalysedData, sizeof(__int16) * m_iNumAnalyzedData * m_iNumStopFreq + 100 * 3, (__int16) 0);
	m_iAnalysedDataSize = sizeof(__int16) * m_iNumAnalyzedData * m_iNumStopFreq + 100 * 3;

	int i;
	int j;
    for (i = 0; i < m_iFFTSize; i++) ImgIn[i] = 0;
	for (i = 0; i < m_iNumAnalyzedData; i++) {
		for (j = 0; j < m_iFFTSize; j++) {
			RealIn[j] = (((__int16*)WaveData)[j*2 + m_iFFTStepWidth * i * 2] * 0.5 + ((__int16*)WaveData)[j*2 + 1 + m_iFFTStepWidth * i * 2] * 0.5)/32768.0;
		}
		if (m_bWindow) {
			Hanning(m_iFFTSize, RealIn);
		}
		
		fft_double(m_iFFTSize, false, RealIn, ImgIn, RealOut, ImgOut);
		
		// SPECTRUM
		__int16 pdSpectrum[3];
		Spectrum(m_iFFTSize, m_iSampleFrequency, RealOut, ImgOut, m_piStopFreq, pdSpectrum);
		m_piAnalysedData[i*3+0] = pdSpectrum[0];
		m_piAnalysedData[i*3+1] = pdSpectrum[1];
		m_piAnalysedData[i*3+2] = pdSpectrum[2];
	}

	SAFE_FREE(RealIn);
	SAFE_FREE(ImgIn);
	SAFE_FREE(RealOut);
	SAFE_FREE(ImgOut);
}

void CWaveFFT::SetStopFreq(int NumStopFreq, int* StopFreq) {
	SAFE_FREE(m_piStopFreq);
	m_piStopFreq = (int*)malloc(sizeof(int) * NumStopFreq);
	memcpy(m_piStopFreq, StopFreq, sizeof(int) * NumStopFreq);
	m_iNumStopFreq = NumStopFreq;
}

__int16* CWaveFFT::GetAnalysedData() {
	return m_piAnalysedData;
}

bool CWaveFFT::LoadFromFile(char*  strFileName){
    HANDLE		hFile;
	DWORD		dwSizeRead = 0;
	DWORD		fileSize = 0;

	hFile = CreateFile(strFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	
	if(INVALID_HANDLE_VALUE == hFile)
    {
//        CloseFile(hFile);
        return false;
    }

	fileSize = m_iAnalysedDataSize = GetFileSize(hFile, NULL);

	if( fileSize == 0 )
    {
        CloseHandle(hFile);
        return false;
    }

	m_piAnalysedData = (__int16*)malloc(fileSize);
    ZeroMemory(m_piAnalysedData, fileSize);

	ReadFile(hFile, m_piAnalysedData, fileSize, &dwSizeRead, NULL);

	CloseHandle(hFile);
	return true;
}

void CWaveFFT::SaveToFile(char*  strFileName) {
    HANDLE		hFile;
	DWORD		dwSizeWritten = 0;

	hFile = CreateFile(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
	
	if(INVALID_HANDLE_VALUE == hFile)
    {
//        CloseFile(hFile);
        return;
    }
	WriteFile(hFile, m_piAnalysedData, m_iAnalysedDataSize, &dwSizeWritten, NULL);

	CloseHandle(hFile);
	return;
}
