///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 Intel Corporation 
// 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. 
// * Neither name of Intel Corporation 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 INTEL 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 "stdafx.h"
#include "ipp.h"
#include "tools.h"
#include "wave.h"

// header row and column of touch-tone frequencies in cycles/second
int pFreqs1[] = { 697, 770, 852, 941 };
int pFreqs2[] = { 1209, 1336, 1477, 1633 };

// 4x4 table of touch-tone frequencies in cycles/second
const int mapSize = 16;
struct CodeMap { char code;int freq1; int freq2; }
	codeList[mapSize] = {
	'1',  697, 1209, '2', 697, 1336, '3', 697, 1477, 'A', 697, 1633,
	'4',  770, 1209, '5', 770, 1336, '6', 770, 1477, 'B', 770, 1633,
	'7',  852, 1209, '8', 852, 1336, '9', 852, 1477, 'C', 852, 1633,
	'*',  941, 1209, '0', 941, 1336, '#', 941, 1477, 'D', 941, 1633
};

int myMakeTone_16s(Ipp16s* pDst, int len, char code, int mag, int samplesPerSec)
{
	// Sampling rate must be at least twice the highest frequency
	if (samplesPerSec < (1633*2)) return -1;

	int index = -1, i;
	for (i=0; i<mapSize; i++)
		if (code == codeList[i].code) { index = i; break; }
	if (index == -1) return -1;

	// Generate tones
	// Frequency in cycles/sample is (freq in cycles/sec)/(samples/sec)
	Ipp16s* pTmp = ippsMalloc_16s(len);
	float phase = 0;
	ippsTone_Direct_16s(pDst, len, mag/2, (float)codeList[index].freq1 /
		(float)samplesPerSec, &phase, ippAlgHintNone);
	phase = 0;
	ippsTone_Direct_16s(pTmp, len, mag/2, (float)codeList[index].freq2 /
		(float)samplesPerSec, &phase, ippAlgHintNone);
	ippsAdd_16s_I(pTmp, pDst, len);
	ippsFree(pTmp);

	return 0;
}

int main(int argc, char* argv[])
{
	const int numSize = 7;
	int i;
	char pNumber[numSize+1] = "2345678";
//	char pNumber[numSize+1] = "5551212";
	float toneLen, toneLenMax = .2;
	int sampleRate, sampleRateMax = 44100;

	int toneSamps = toneLenMax * sampleRateMax;
	int gapSamps = toneSamps / 2;
	int totSamps = toneSamps * numSize + gapSamps * (numSize-1);

	Ipp16s *pDial = ippsMalloc_16s(totSamps);

	sampleRate = 22000;
	toneLen = 0.1;
	Ipp16s* pTmp = pDial;

	toneSamps = toneLen * sampleRate;
	gapSamps = toneSamps / 2;
	totSamps = toneSamps * numSize + gapSamps * (numSize-1);
			
	ippsZero_16s(pDial, totSamps);
	for (i=0; i<numSize; i++)
	{
		myMakeTone_16s(pTmp, toneSamps, pNumber[i], 16384, sampleRate);
		pTmp += toneSamps + gapSamps;
	}

	DrawingSettings settings = 
	{
		1,1,
		PS_SOLID, PS_DASH,
		0x00606060, 0x00000000,
		1,1,
		0x00cfcfcf, 0x007f7f7f
	};

	spView_16s(pDial, totSamps, "Tones", 0, settings);
	spView_16s(pDial, toneSamps, "First Tone", 1, settings);

	// Optional code to play the signal:
	//	WaveMem wm;
	//	wm.InitAlloc(totSamps, 16, sampleRate/1.2, 1);
	//	wm.Set(pDial);
	//	wm.Play(0);

	ippsFree(pDial);

	return 0;
}
