⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtmffft.c

📁 VC写的对DTMF信号的识别程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	FFTTerm(&pdfts->fs);
}

static BOOL DFWaveInInit(PDFTHREADSTRUCT pdfts,UINT uDeviceID)
{
	// Open the wave device...
	WAVEFORMATEX wfe=
	{
		WAVE_FORMAT_PCM, // wFormatTag
		DF_NUMCHANNELS, // nChannels
		DF_SAMPLESPERSEC, // nSamplesPerSec
		DF_AVGBYTESPERSEC, // nAvgBytesPerSec=nBlockAlign*nSamplesPerSec
		DF_BLOCKALIGN, //nBlockAlign=(nChannels*wBitsPerSample)/8
		DF_BITSPERSAMPLE, // wBitsPerSample
		0 //cbSize
	};

	pdfts->hwi=NULL;

	if (!FFTInit(&pdfts->fs,DF_FFTLEN))
	{
		return FALSE;
	}

	if (waveInOpen(&pdfts->hwi,uDeviceID,&wfe,(DWORD)DFWaveInCallback,(DWORD)pdfts,CALLBACK_FUNCTION)!=0)
	{
		DFWaveInTerm(pdfts);
		return FALSE;
	}

	if (!DFQueueInit(pdfts->hwi,&pdfts->dfqs))
	{
		DFWaveInTerm(pdfts);
		return FALSE;
	}

	waveInStart(pdfts->hwi);

	return TRUE;
}

static DWORD WINAPI DFThreadProc(PDFTHREADSTRUCT pdfts)
{
	static WORD awBuffer[DF_BUFFERSIZE];
	BOOL bFinish=FALSE;

	DFTSSetStarted(pdfts,TRUE);
	DFTSSetStarting(pdfts,FALSE);

	while (!bFinish)
	{
		DWORD dwTickCount;
		BOOL bRedraw=FALSE; // True if we need to post a message to redraw the spectrum.

		while (DFQueueGet(pdfts->hwi,&pdfts->dfqs,awBuffer,&dwTickCount)) // Should always be true if we're here
		{
			// Search the buffer DF_SAMPLESPERSEC / DF_FFTLEN times per sec for a DTMF tone
			S32 as32Buffer[DF_FFTLEN/2];

			bRedraw=TRUE;

			FFTRun(&pdfts->fs,awBuffer,as32Buffer);
			EnterCriticalSection(&pdfts->cs);
			memcpy(pdfts->as32Buffer,as32Buffer,sizeof(as32Buffer));
			LeaveCriticalSection(&pdfts->cs);

			// Now figure out if we have any DTMF tones worth talking about...
			{
				// Array of DTMF bin indices into the FFT table
				static const int anDTMFBinX[4]=
				{
					DF_DTMFBINX0,
					DF_DTMFBINX1,
					DF_DTMFBINX2,
					DF_DTMFBINX3
				};

				static const int anDTMFBinY[4]=
				{
					DF_DTMFBINY0,
					DF_DTMFBINY1,
					DF_DTMFBINY2,
					DF_DTMFBINY3
				};
				int nToneBitmapX=0;
				int nToneBitmapY=0;
				int nToneX=-1;
				int nToneY=-1;
				int nCountX=0;
				int nCountY=0;
				int nBitMap;
				int n;
				S32 s32AvgX=0;
				S32 s32AvgY=0;
				S32 s32Avg=0;
				S32 s32ThresholdAGC;
				int nThreshold=DFTSGetThreshold(pdfts);
				static char cLast='\0'; // Last decoded
				static char cLastSent='\0'; // Last decoded sent

				// Get the average without the first few bins...
				for (n=DF_DTMFBINMIN-1;n<=DF_DTMFBINMAX+1;n++)
				{
					s32Avg+=as32Buffer[n];
				}

				// Remove the bins for our freqs of interest and for grins
				// get the average of the X and Y bins
				for (n=0;n<4;n++)
				{
					s32Avg-=as32Buffer[anDTMFBinX[n]];
					s32Avg-=as32Buffer[anDTMFBinY[n]];
					s32AvgX+=as32Buffer[anDTMFBinX[n]];
					s32AvgY+=as32Buffer[anDTMFBinY[n]];
				}
				s32Avg=(s32Avg)/(DF_DTMFBINMAX-DF_DTMFBINMIN+3-8);
				s32ThresholdAGC=s32Avg*nThreshold/2;
				DFTSSetThresholdAGC(pdfts,s32ThresholdAGC);
				s32AvgX=s32AvgX*3/4; // We'd like the tones to be significantly over the average
				s32AvgY=s32AvgY*3/4;

				for (n=0,nBitMap=1;n<4;n++,nBitMap<<=1)
				{
					if (as32Buffer[anDTMFBinX[n]]>s32ThresholdAGC)
					{
						nToneBitmapX |= nBitMap;
						nToneX=n;
						nCountX++;
					}
					if (as32Buffer[anDTMFBinY[n]]>s32ThresholdAGC)
					{
						nToneBitmapY |= nBitMap;
						nToneY=n;
						nCountY++;
					}
				}

// Pessimistic algorithm - need two successive correct tone decodes the same
				if (nCountX==1 && nCountY==1) // Only one tone in each group please
				{
					static const char aacToneDecode[4][4]=
					{
						{'1','2','3','A'},
						{'4','5','6','B'},
						{'7','8','9','C'},
						{'*','0','#','D'}
					};
					char c=aacToneDecode[nToneY][nToneX];

					if (pdfts->nLastToneBitmapX==nToneBitmapX && pdfts->nLastToneBitmapY==nToneBitmapY)
					{
						if (c==cLast)
						{
							if (cLastSent!=c)
							{
								PostMessage(pdfts->hdlg,DF_WM_USER_NEWCHAR,(WPARAM)c,(LPARAM)dwTickCount);
								cLastSent=c;
							}
						}
					}
					cLast=c;
				}
				else
				{
					cLast='\0';
					cLastSent='\0';
				}

/* Optimistic algorithm
				if (nCountX==1 && nCountY==1) // Only one tone in each group please
				{
					if (pdfts->nLastToneBitmapX!=nToneBitmapX || pdfts->nLastToneBitmapY!=nToneBitmapY) // If changed from last time
					{
						static const char aacToneDecode[4][4]=
						{
							{'1','2','3','A'},
							{'4','5','6','B'},
							{'7','8','9','C'},
							{'*','0','#','D'}
						};
						char c=aacToneDecode[nToneY][nToneX];

						PostMessage(pdfts->hdlg,DF_WM_USER_NEWCHAR,(WPARAM)c,0);
					}
				}
*/
				pdfts->nLastToneBitmapX=nToneBitmapX;
				pdfts->nLastToneBitmapY=nToneBitmapY;

			}
			DFTSDecWaveBuffers(pdfts);
		}

		if (bRedraw)
		{
			PostMessage(pdfts->hdlg,DF_WM_USER_REDRAW,0,0);
		}

		switch(WaitForSingleObject(pdfts->hevent,100))
		{
			case WAIT_OBJECT_0:
				break;
			case WAIT_TIMEOUT:
				break;
		}

		bFinish=DFTSGetFinish(pdfts);
	}

	DFTSSetStarted(pdfts,FALSE);
	DFTSSetFinished(pdfts,TRUE);
	pdfts->dwThreadID=0;
	pdfts->ht=NULL;
	ExitThread(0);
	return 0;
}

static void DFThreadTerm(PDFTHREADSTRUCT pdfts)
{
	if (DFTSGetStarting(pdfts) || DFTSGetStarted(pdfts))
	{
		DFTSSetFinished(pdfts,FALSE);
		DFTSSetFinish(pdfts,TRUE);
		SetEvent(pdfts->hevent);
		while (!DFTSGetFinished(pdfts))
		{
			Sleep(100);
		}
	}
}

static BOOL DFThreadInit(PDFTHREADSTRUCT pdfts,LONG lDeviceID)
{
	BOOL brc=FALSE; // pessimistic return code

	if (!DFTSGetStarting(pdfts) && !DFTSGetStarted(pdfts))
	{
		pdfts->ht=NULL;
		pdfts->dwThreadID=0;
		pdfts->nLastToneBitmapX=0;
		pdfts->nLastToneBitmapY=0;

		// Open the wave device...
		DFTSSetWaveBuffers(pdfts,0);
		if (!DFWaveInInit(pdfts,(UINT)lDeviceID))
		{
			DFThreadTerm(pdfts);
			MessageBox(pdfts->hdlg,"Could not open wave device","DTMF FFT",MB_OK | MB_ICONEXCLAMATION);
			return FALSE;
		}

		// Start the thread...
		DFTSSetStarting(pdfts,TRUE);
		DFTSSetStarted(pdfts,FALSE);
		DFTSSetFinish(pdfts,FALSE);
		DFTSSetFinished(pdfts,TRUE);

		if ((pdfts->ht=CreateThread(NULL,0,DFThreadProc,(LPVOID)pdfts,0,&pdfts->dwThreadID))==NULL)
		{
			DFThreadTerm(pdfts);
			MessageBox(pdfts->hdlg,"Could not start thread","DTMF FFT",MB_OK | MB_ICONEXCLAMATION);
			return FALSE;
		}
		brc=TRUE;
	}
	return brc;
}

static void DFTerm(PDFTHREADSTRUCT pdfts)
{
	// Close thread down...
	DFThreadTerm(pdfts);

	// Close down WAV handle...
	DFWaveInTerm(pdfts);

	// Close down event...
	CloseHandle(pdfts->hevent);
	pdfts->hevent=NULL;

	// Close down critical section...
	DeleteCriticalSection(&pdfts->cs);

	// Delete any font I've created
	if (pdfts->hf!=NULL)
	{
		DeleteObject(pdfts->hf);
		pdfts->hf=NULL;
	}

	// Close the log file
	if (pdfts->pf!=NULL)
	{
		SYSTEMTIME st;

		GetSystemTime(&st);
		fprintf(pdfts->pf,"DTMFFFT,%04d%02d%02d %02d:%02d:%02d.%03d,UTC,Close  \n",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
		fclose(pdfts->pf);
		pdfts->pf=NULL;
	}
}

static void DFInitSetParameterFields(PDFTHREADSTRUCT pdfts)

{ // Try to get the registry values and fudge factors, and set dialog field texts
	int n;
	char szKey[30]="NumParameters";
	char szVal[30];

	// First try to get the number of parameters...
	if (!RegGetString(szKey,szVal,sizeof(szVal)))
	{
		sprintf(szVal,"%d",DF_DEFAULTNUMDLGPARAMETERS);
		RegSetString(szKey,szVal);
	}
	pdfts->nNumDlgParms=atoi(szVal);

	for (n=0;n<DF_MAXDLGPARAMETERS;n++)
	{
		static const int anDlgIDName[DF_MAXDLGPARAMETERS]=
		{
			IDC_DF_PARAMETER_NAME1,
			IDC_DF_PARAMETER_NAME2,
			IDC_DF_PARAMETER_NAME3,
			IDC_DF_PARAMETER_NAME4,
			IDC_DF_PARAMETER_NAME5
		};
		static const int anDlgIDValue[DF_MAXDLGPARAMETERS]=
		{
			IDC_DF_PARAMETER_VALUE1,
			IDC_DF_PARAMETER_VALUE2,
			IDC_DF_PARAMETER_VALUE3,
			IDC_DF_PARAMETER_VALUE4,
			IDC_DF_PARAMETER_VALUE5
		};
		static const int anDlgIDUnits[DF_MAXDLGPARAMETERS]=
		{
			IDC_DF_PARAMETER_UNITS1,
			IDC_DF_PARAMETER_UNITS2,
			IDC_DF_PARAMETER_UNITS3,
			IDC_DF_PARAMETER_UNITS4,
			IDC_DF_PARAMETER_UNITS5
		};
		static const char *aszNameDefault[DF_MAXDLGPARAMETERS]=
		{
			"Parameter 1",
			"Parameter 2",
			"Parameter 3",
			"Parameter 4",
			"Parameter 5"
		};
		static const char *aszUnitsDefault[DF_MAXDLGPARAMETERS]=
		{
			"Units 1",
			"Units 2",
			"Units 3",
			"Units 4",
			"Units 5"
		};
		static const double adOffsetDefault[DF_MAXDLGPARAMETERS]=
		{
			0.0,
			0.0,
			0.0,
			0.0,
			0.0
		};
		static const double adMultiplierDefault[DF_MAXDLGPARAMETERS]=
		{
			1.0,
			1.0,
			1.0,
			1.0,
			1.0
		};
		pdfts->ddps[n].nDlgIDName=anDlgIDName[n];
		pdfts->ddps[n].nDlgIDValue=anDlgIDValue[n];
		pdfts->ddps[n].nDlgIDUnits=anDlgIDUnits[n];

		strcpy(pdfts->ddps[n].szName,aszNameDefault[n]);
		sprintf(szKey,"ParameterName%d",n+1);
		if (!RegGetString(szKey,pdfts->ddps[n].szName,DF_DLGSTRINGLEN))
		{
			RegSetString(szKey,pdfts->ddps[n].szName);
		}
		SetDlgItemText(pdfts->hdlg,pdfts->ddps[n].nDlgIDName,pdfts->ddps[n].szName);

		sprintf(szKey,"ParameterOffset%d",n+1);
		if (RegGetString(szKey,szVal,sizeof(szVal)))
		{
			pdfts->ddps[n].dOffset=atof(szVal);
		}
		else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -