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

📄 dtmffft.c

📁 VC写的对DTMF信号的识别程序
💻 C
📖 第 1 页 / 共 3 页
字号:
// DTMFFFT.C (c) 2004 Howard Long (G6LVB), Hanlincrest Ltd. All rights reserved.
// 72 Princes Gate
// London SW7 2PA
// United Kingdom
// howard@hanlincrest.com
// Free for educational and non-profit use. For commercial use please contact the author.

#include <windows.h>
#include <string.h>
#include <stdio.h>

#include "resource.h"

#include "fft.h"
#include "about.h"
#include "parameter.h"
#include "registry.h"

#define DF_NUMCHANNELS 1 // Number of audio channels for calc of buffer size - we're mono, so only 1
#define DF_SAMPLESPERSEC 11025
#define DF_BITSPERSAMPLE 16
#define DF_BLOCKALIGN ((DF_NUMCHANNELS * DF_BITSPERSAMPLE)/8)
#define DF_AVGBYTESPERSEC (DF_BLOCKALIGN * DF_SAMPLESPERSEC)

#define DF_FFTLEN 256
#define DF_TIMEBUFFER 1 // Number of seconds to buffer
#define DF_NUMBUFFERS (DF_TIMEBUFFER * DF_SAMPLESPERSEC / DF_FFTLEN) // Choose enough buffers
#define DF_BUFFERSIZE (DF_FFTLEN * DF_BLOCKALIGN)

#define DF_WM_USER_REDRAW (WM_USER)
#define DF_WM_USER_NEWCHAR (WM_USER+1)

// The size of each FFT bin in Hz
#define DF_BINSIZE ((double)DF_SAMPLESPERSEC / DF_FFTLEN)

// DTMF tones in Hz
#define DF_DTMFTONEX0 1209
#define DF_DTMFTONEX1 1336
#define DF_DTMFTONEX2 1477
#define DF_DTMFTONEX3 1633
#define DF_DTMFTONEY0 697
#define DF_DTMFTONEY1 770
#define DF_DTMFTONEY2 852
#define DF_DTMFTONEY3 941

// DTMF FFT Bin indices
#define DF_DTMFBINX0 ((int)((DF_DTMFTONEX0 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINX1 ((int)((DF_DTMFTONEX1 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINX2 ((int)((DF_DTMFTONEX2 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINX3 ((int)((DF_DTMFTONEX3 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINY0 ((int)((DF_DTMFTONEY0 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINY1 ((int)((DF_DTMFTONEY1 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINY2 ((int)((DF_DTMFTONEY2 / DF_BINSIZE) + 0.5))
#define DF_DTMFBINY3 ((int)((DF_DTMFTONEY3 / DF_BINSIZE) + 0.5))

#define DF_DTMFBINMIN DF_DTMFBINY0
#define DF_DTMFBINMAX DF_DTMFBINX3
#define DF_DTMFBINMINX DF_DTMFBINX0
#define DF_DTMFBINMAXX DF_DTMFBINX3
#define DF_DTMFBINMINY DF_DTMFBINY0
#define DF_DTMFBINMAXY DF_DTMFBINY3

#define DF_DLGSTRINGLEN 30
#define DF_DEFAULTNUMDLGPARAMETERS 3 // Default number of dialog box parameters used
#define DF_MAXDLGPARAMETERS 5 // Maximum number of dialog box parameters possible

typedef struct
{
	WAVEHDR wh;
	DWORD dwTickCount; // Tick time that queue item was set up
	BOOL bBufferReady;
	BOOL bWHPrepared;
} DFQUEUEWHSTRUCT, *PDFQUEUEWHSTRUCT;

typedef struct
{
	CRITICAL_SECTION cs;
	DFQUEUEWHSTRUCT adfqwhs[DF_NUMBUFFERS]; // Pool of wave headers
	int anIdx[DF_NUMBUFFERS]; // Queue list of indexes of DFQUEUEWHSTRUCTS
	int nHead;
	int nTail;
} DFQUEUESTRUCT, *PDFQUEUESTRUCT;

typedef struct
{
	int nDlgIDName;
	int nDlgIDUnits;
	int nDlgIDValue;
	char szName[DF_DLGSTRINGLEN];
	char szUnits[DF_DLGSTRINGLEN];
	double dOffset;
	double dMultiplier;
} DFDLGPARAMETERSTRUCT;

typedef struct
{
	HWAVEIN hwi;
	HWND hdlg;
	HFONT hf; // Monospaced font
	HANDLE ht; // Thread handle
	DWORD dwThreadID; // Thread ID
	DFQUEUESTRUCT dfqs; // Queue of wave headers
	FILE *pf; // File holding output data
	FFTSTRUCT fs; // FFT structure
	CRITICAL_SECTION cs;
	HANDLE hevent; // Used by application thread to signal FFT thread
	BOOL bStarting; // Is thread in the process of starting up?
	BOOL bStarted; // Has thread started?
	BOOL bFinish; // Used to notify thread to end
	BOOL bFinished; // Has thread ended?
	S32 as32Buffer[DF_FFTLEN/2];
	int nThreshold; // Threshold set by user
	S32 s32ThresholdAGC; // Threshold ajusted by AGC and user's threshold setting
	int nWaveBuffers; // Number of WAV buffers queued up
	int nLastToneBitmapX; // Bitmap of last tone X group
	int nLastToneBitmapY; // Bitmap of last tone Y group
	int nNumDlgParms; // Number of telemtry parameters (up to DF_MAXDLGPARAMETERS)
	DFDLGPARAMETERSTRUCT ddps[DF_MAXDLGPARAMETERS];
} DFTHREADSTRUCT, *PDFTHREADSTRUCT;

static HINSTANCE _hinst=NULL;

static void DFQueueTerm(HWAVEIN hwi,PDFQUEUESTRUCT pdfqs)
{
	int n;

	for (n=0;n<DF_NUMBUFFERS;n++)
	{
		if (pdfqs->adfqwhs[n].bWHPrepared)
		{
			waveInUnprepareHeader(hwi,&pdfqs->adfqwhs[n].wh,sizeof(pdfqs->adfqwhs[n].wh));
			pdfqs->adfqwhs[n].bWHPrepared=FALSE;
		}

		if (pdfqs->adfqwhs[n].wh.lpData!=NULL)
		{
			free(pdfqs->adfqwhs[n].wh.lpData);
			pdfqs->adfqwhs[n].wh.lpData=NULL;
		}
	}
	DeleteCriticalSection(&pdfqs->cs);
}

static BOOL DFQueueInit(HWAVEIN hwi,PDFQUEUESTRUCT pdfqs)
{
	int n;

	InitializeCriticalSection(&pdfqs->cs);
	pdfqs->nHead=0;
	pdfqs->nTail=0;
	for (n=0;n<DF_NUMBUFFERS;n++) // Initialise NULL pointers first in case
	{
		pdfqs->adfqwhs[n].wh.lpData=NULL;
		pdfqs->adfqwhs[n].bWHPrepared=FALSE;
		pdfqs->adfqwhs[n].bBufferReady=FALSE;
		pdfqs->anIdx[n]=-1;
	}
	for (n=0;n<DF_NUMBUFFERS;n++)
	{
		if ((pdfqs->adfqwhs[n].wh.lpData=malloc(DF_BUFFERSIZE))==NULL)
		{
			DFQueueTerm(hwi,pdfqs);
			return FALSE;
		}
		pdfqs->adfqwhs[n].wh.dwBufferLength=DF_BUFFERSIZE;
		pdfqs->adfqwhs[n].wh.dwFlags=0;
		pdfqs->adfqwhs[n].wh.dwUser=(DWORD)n; // So that when given a WAVEHDR, the callback can figure out which one it is.

		if (waveInPrepareHeader(hwi,&pdfqs->adfqwhs[n].wh,sizeof(pdfqs->adfqwhs[n].wh))!=0)
		{
			DFQueueTerm(hwi,pdfqs);
			return FALSE;
		}
		pdfqs->adfqwhs[n].bWHPrepared=TRUE;
		waveInAddBuffer(hwi,&pdfqs->adfqwhs[n].wh,sizeof(pdfqs->adfqwhs[n].wh));
	}
	return TRUE;
}

static BOOL DFQueuePut(PDFQUEUESTRUCT pdfqs,LPWAVEHDR lpwh)
{
	// Insert a filled buffer into the queue.
	EnterCriticalSection(&pdfqs->cs);
	{
		int nNext=((pdfqs->nHead)+1) % DF_NUMBUFFERS;
		int nIdx=(int)lpwh->dwUser; // User data is index of WAVEHDR item

		if (nNext==pdfqs->nTail)
		{
			LeaveCriticalSection(&pdfqs->cs);
			return FALSE; // Overrun!
		}
		pdfqs->anIdx[pdfqs->nHead]=nIdx;
		pdfqs->adfqwhs[nIdx].bBufferReady=TRUE; // Flag as data ready - may be used in future, handy for debugging
		pdfqs->adfqwhs[nIdx].dwTickCount=GetTickCount(); // Set a timestamp of when this happened
		pdfqs->nHead=nNext;
	}
	LeaveCriticalSection(&pdfqs->cs);
	return TRUE;
}

static BOOL DFQueueGet(HWAVEIN hwi,PDFQUEUESTRUCT pdfqs,PWORD pwData,PDWORD pdwTickCount)
{
	int nIdx;

	// Pull a buffer from the queue
	EnterCriticalSection(&pdfqs->cs);

	if (pdfqs->nHead==pdfqs->nTail)
	{
		LeaveCriticalSection(&pdfqs->cs);
		return FALSE; // Nothing in queue to get
	}
	LeaveCriticalSection(&pdfqs->cs);
	
	memcpy(pwData,pdfqs->adfqwhs[pdfqs->nTail].wh.lpData,DF_BUFFERSIZE);
	if (pdwTickCount!=NULL)
	{
		*pdwTickCount=pdfqs->adfqwhs[pdfqs->nTail].dwTickCount;
	}

	EnterCriticalSection(&pdfqs->cs);

	nIdx=pdfqs->nTail;
	pdfqs->adfqwhs[nIdx].bBufferReady=FALSE;
	pdfqs->nTail=((pdfqs->nTail)+1) % DF_NUMBUFFERS;

	LeaveCriticalSection(&pdfqs->cs);

	waveInAddBuffer(hwi,&pdfqs->adfqwhs[nIdx].wh,sizeof(pdfqs->adfqwhs[nIdx].wh));
	return TRUE;
}

static void DFTSSetThreshold(PDFTHREADSTRUCT pdfts,int n)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->nThreshold=n;
	LeaveCriticalSection(&pdfts->cs);
}

static int DFTSGetThreshold(PDFTHREADSTRUCT pdfts)
{
	int n;

	EnterCriticalSection(&pdfts->cs);
	n=pdfts->nThreshold;
	LeaveCriticalSection(&pdfts->cs);
	return n;
}

static void DFTSSetThresholdAGC(PDFTHREADSTRUCT pdfts,S32 s32)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->s32ThresholdAGC=s32;
	LeaveCriticalSection(&pdfts->cs);
}

static S32 DFTSGetThresholdAGC(PDFTHREADSTRUCT pdfts)
{
	S32 s32;

	EnterCriticalSection(&pdfts->cs);
	s32=pdfts->s32ThresholdAGC;
	LeaveCriticalSection(&pdfts->cs);
	return s32;
}

static void DFTSSetStarting(PDFTHREADSTRUCT pdfts,BOOL bStarting)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->bStarting=bStarting;
	LeaveCriticalSection(&pdfts->cs);
}

static BOOL DFTSGetStarting(PDFTHREADSTRUCT pdfts)
{
	BOOL b;

	EnterCriticalSection(&pdfts->cs);
	b=pdfts->bStarting;
	LeaveCriticalSection(&pdfts->cs);
	return b;
}

static void DFTSSetStarted(PDFTHREADSTRUCT pdfts,BOOL bStarted)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->bStarted=bStarted;
	LeaveCriticalSection(&pdfts->cs);
}

static BOOL DFTSGetStarted(PDFTHREADSTRUCT pdfts)
{
	BOOL b;

	EnterCriticalSection(&pdfts->cs);
	b=pdfts->bStarted;
	LeaveCriticalSection(&pdfts->cs);
	return b;
}

static void DFTSSetFinish(PDFTHREADSTRUCT pdfts,BOOL bFinish)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->bFinish=bFinish;
	LeaveCriticalSection(&pdfts->cs);
}

static BOOL DFTSGetFinish(PDFTHREADSTRUCT pdfts)
{
	BOOL b;

	EnterCriticalSection(&pdfts->cs);
	b=pdfts->bFinish;
	LeaveCriticalSection(&pdfts->cs);
	return b;
}

static void DFTSSetFinished(PDFTHREADSTRUCT pdfts,BOOL bFinished)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->bFinished=bFinished;
	LeaveCriticalSection(&pdfts->cs);
}

static BOOL DFTSGetFinished(PDFTHREADSTRUCT pdfts)
{
	BOOL b;

	EnterCriticalSection(&pdfts->cs);
	b=pdfts->bFinished;
	LeaveCriticalSection(&pdfts->cs);
	return b;
}

static int DFTSIncWaveBuffers(PDFTHREADSTRUCT pdfts)
{
	int n;

	EnterCriticalSection(&pdfts->cs);
	pdfts->nWaveBuffers++;
	n=pdfts->nWaveBuffers;
	LeaveCriticalSection(&pdfts->cs);
	return n;
}

static int DFTSDecWaveBuffers(PDFTHREADSTRUCT pdfts)
{
	int n;

	EnterCriticalSection(&pdfts->cs);
	pdfts->nWaveBuffers--;
	n=pdfts->nWaveBuffers;
	LeaveCriticalSection(&pdfts->cs);
	return n;
}

static int DFTSGetWaveBuffers(PDFTHREADSTRUCT pdfts)
{
	int n;

	EnterCriticalSection(&pdfts->cs);
	n=pdfts->nWaveBuffers;
	LeaveCriticalSection(&pdfts->cs);
	return n;
}

static void DFTSSetWaveBuffers(PDFTHREADSTRUCT pdfts,int n)
{
	EnterCriticalSection(&pdfts->cs);
	pdfts->nWaveBuffers=n;
	LeaveCriticalSection(&pdfts->cs);
}

void CALLBACK DFWaveInCallback(HWAVEIN hwi,UINT uMsg,PDFTHREADSTRUCT pdfts,DWORD dwParam1,DWORD dwParam2)
{
	if(uMsg==MM_WIM_DATA)
	{
		DFQueuePut(&pdfts->dfqs,(LPWAVEHDR)dwParam1);
		DFTSIncWaveBuffers(pdfts); // Tell thread we have more data

		SetEvent(pdfts->hevent);
	}
}

static void DFWaveInTerm(PDFTHREADSTRUCT pdfts)
{
	DFQueueTerm(pdfts->hwi,&pdfts->dfqs);
	if (pdfts->hwi!=NULL)
	{
		waveInClose(pdfts->hwi);
		pdfts->hwi=NULL;
	}

⌨️ 快捷键说明

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