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

📄 main.c

📁 FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT FFT
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************
* Fast Fourie Transformation
******************************************************************
  This is only an example how to sample sound with windows
  (should work with windows98/2000/Me) and how to apply 
  a Fouriertransformation.
  To keep this code simple I have done/not done the following
  1) After a Buffer is filled, I take the content of it and 
     give the device another Buffer worthwile.(pBuffer1,pBuffer2)
	 In the time the device fills the buffer, all the transformation
	 has to be done! Usually you should place this in a thread, but
	 this would have made this code not as easy to understand.
	 So keep in mind that you need a faster computer, just try.
  2) The FFT itself is standard and not very fast. I adapted the
     code from a nice book. It is called FFT from
	 the German "Oldenburg Verlag", but it is available
	 in english language as I know. 
  3) Usually the WaveDevice sends its messages to its own 
     MessageProcedure. I have not done this to keep it easier.
	 To understand the wavedevicehandling look up 
	 at msdn.microsoft.com or get 
	 Charles Petzolds Book "Programming Windows". 
  4) In Charles Petzolds Book Chapter 22 WaveFormAudio you find a
     sample code of the SoundRecorder1. Here he explains 
	 how to sample sound and get the Buffer. I startet with this 
	 code and kept most of it for my needs. But it also makes it
	 easies to understand this code, if you have read this chapter 
	 before. 
   5) For the AudioDeviceHandling winmm.lib has to be included
   6) Your AudioDevice must be able to handle 16bit!

******************************************************************/


#include "FFT.h"


#define QUANTIZATION 16
#define WM_FREQ 1234     // user defined Message for Frequ calculation
// the following #defines are needed, because we append the found 
// audiodevices to the menu and assign the following ID's
// with this we can append a maximum of 6 Devices
#define WM_DEV  150
#define WM_DEV1 150
#define WM_DEV2 151
#define WM_DEV3 152
#define WM_DEV4 153
#define WM_DEV5 154
#define WM_DEV6 155



LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL    CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL    CALLBACK SettingsDlgProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName []  = TEXT ("FFT Frequency Analyser") ;
TCHAR szOpenError[] = TEXT ("Error opening Audio Device!");
TCHAR szMemError [] = TEXT ("Cannot allocate memory!") ;
TCHAR szAbout[]     = TEXT ("Code by Tim Buschmann\nContact me:\nt.buschmann@unidui.uni-duisburg.de");

typedef struct 
{
	int iSamplesPerSecond,
	    iNumOfSamples,
		iInputBufferSize;
} *PFFT_DATA;


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;  // we need Scrollbars
     wndclass.lpfnWndProc   = MainWndProc ;              // Window Procedure
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_FFT)) ;  //Load FFT Icon
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ; // Get Cursor
     wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ; // Load black brush from stock
     wndclass.lpszMenuName  = MAKEINTRESOURCE(IDM_FFT) ;  // Menu
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {    
          MessageBox (NULL, TEXT ("Could not init Programm"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }

      hwnd = CreateWindow (szAppName,                 // Windows Class Name
                  szAppName,                          // Window Name
                  WS_OVERLAPPEDWINDOW |
				  WS_MINIMIZEBOX      |
				  WS_HSCROLL          |
				  WS_MAXIMIZEBOX      |
				  WS_BORDER,
				  CW_USEDEFAULT,                      // X-Position of Window
                  0,                                  // Y-Position of Window
                  320,                                // Window width
                  240,                                // Window height
                  NULL,                               
                  NULL,                               // Menu
                  hInstance,                          // 
                  NULL) ;                             // 

     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}


LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static BOOL         bRecording,    // Device is recording
                         bEnding,       // Ending to record
						 bTerminating ; // application shutting down	                 
     static HWAVEIN      hWaveIn  ;     // WaveIn DeviceHandle
	 static PWORD        pwTemp; 
	 static PBYTE        pBuffer1,    // Device Buffer 1
		                 pBuffer2,    // Device Buffer 2
						 pTempBuffer; // Recording Buffer
     static PWAVEHDR     pWaveHdr1, pWaveHdr2 ; // WaveheadrStructure
     static WAVEFORMATEX waveform ;             //
     static int   iDevSel,      // Menu Device Selection
		          iViewSel=0,     // Menu View Selection
		          iTmpRange=0,  // Last painted Window Range
				  iStartPos,    // Array Pos to Display in Window left side
				  iRange = 256; // Array range displayed in Window
	 static PFFT_DATA pFFT; 
     HDC         hdc ;          // Device Context
	 static HINSTANCE hInstance;       // HandleInstance
     int         i,             //
		         iFreq,         // Frequency to display 
				 iNumDev;       // Number of Devices
     static POINT       *apt;     //FFT Points to paint
     static PFLOAT      pfRealBuf,  // RealBuffer
	                    pfImagBuf,  // ImaginaryBuffer
	                    pfResBuf;   // ResultBuffer
     static RECT rect;              // client rect
	 WAVEINCAPS DevCaps;            // DriverCaps
     TCHAR buffer[30];              // WindowTextBuffer

     switch (message)
     {
	 
	 case WM_COMMAND:
		   switch (LOWORD (wParam))
           {
              
		      case IDM_HELP:
                 DialogBox (hInstance, 
					        MAKEINTRESOURCE(IDD_HELP),
							hwnd, 
							AboutDlgProc) ;
		      return 0;
			  case IDM_ABOUT:
				  MessageBox(hwnd,
					         szAbout,
							 TEXT("About"),
							 MB_OK);
					         
			  return 0;
		      case IDM_SETTINGS:
                 DialogBoxParam (hInstance, 
					             MAKEINTRESOURCE(IDD_SETTINGS),
							     hwnd, 
							     SettingsDlgProc,
								 (long)pFFT) ;
				 //after Settings reset to view 100%
                SendMessage(hwnd, WM_COMMAND,(WPARAM)IDM100,(LPARAM)NULL);
				// and clear old canvas
				InvalidateRect(hwnd,&rect,TRUE);
		      return 0;
              case IDM_EXIT:
               SendMessage (hwnd, WM_CLOSE, 0, 0) ;
              return 0 ;
			  // The following Command Zoom in a Section of
			  // the window. For that we need to update the
			  // Scrollbar Range.
			  case IDM100:   // 100% View
                CheckMenuItem(GetMenu(hwnd),iViewSel,MF_UNCHECKED);
				CheckMenuItem(GetMenu(hwnd),IDM100,MF_CHECKED);
				iViewSel = IDM100;
                iRange = pFFT->iNumOfSamples/2; 
				iStartPos =  0;
			    SetScrollRange (hwnd, SB_HORZ, 0,iRange, FALSE) ; // SetNewRange, don't update Bar
                SetScrollPos   (hwnd, SB_HORZ, iRange/2, TRUE) ;      // SetNewPos and update Bar
                SendMessage(hwnd, WM_FREQ,0,0);
              return 0 ;
			  case IDM200:  // 200% View
				CheckMenuItem(GetMenu(hwnd),iViewSel,MF_UNCHECKED);
				CheckMenuItem(GetMenu(hwnd),IDM200,MF_CHECKED);
				iViewSel = IDM200;
                iRange = pFFT->iNumOfSamples/8; 
				iStartPos =  pFFT->iNumOfSamples/4-iRange/2;
			    SetScrollRange (hwnd, SB_HORZ, 0,pFFT->iNumOfSamples/2, FALSE) ;
                SetScrollPos   (hwnd, SB_HORZ, pFFT->iNumOfSamples/4, TRUE) ;
				SendMessage(hwnd, WM_FREQ,0,0);
			  return 0 ;
			  case IDM300:
				CheckMenuItem(GetMenu(hwnd),iViewSel,MF_UNCHECKED);
				CheckMenuItem(GetMenu(hwnd),IDM300,MF_CHECKED);
				iViewSel = IDM300;
               iRange = pFFT->iNumOfSamples/16; 
			    iStartPos =  pFFT->iNumOfSamples/4-iRange/2;
			    SetScrollRange (hwnd, SB_HORZ, 0,pFFT->iNumOfSamples/2, FALSE) ;
                SetScrollPos   (hwnd, SB_HORZ, pFFT->iNumOfSamples/4, TRUE) ;
				SendMessage(hwnd, WM_FREQ,0,0);
              return 0 ;
			  case IDM400:
				CheckMenuItem(GetMenu(hwnd),iViewSel,MF_UNCHECKED);
				CheckMenuItem(GetMenu(hwnd),IDM400,MF_CHECKED);
				iViewSel = IDM400;
                iRange = pFFT->iNumOfSamples/32;
			 	iStartPos =  pFFT->iNumOfSamples/4-iRange/2;
			    SetScrollRange (hwnd, SB_HORZ, 0,pFFT->iNumOfSamples/2, FALSE) ;
                SetScrollPos   (hwnd, SB_HORZ, pFFT->iNumOfSamples/4, TRUE) ;
				SendMessage(hwnd, WM_FREQ,0,0);
              return 0 ;
			  // The following Commands select the appropiate 
			  // audiodevice:
			  case WM_DEV1:
              case WM_DEV2:
			  case WM_DEV3:
			  case WM_DEV4:
			  case WM_DEV5:
			  case WM_DEV6:
				 bEnding = TRUE ;
                 waveInReset (hWaveIn) ; // reset Wave Device
				 EnableMenuItem(GetMenu(hwnd),IDM_RSTOP,MF_GRAYED); //Gray out Stop button
			     EnableMenuItem(GetMenu(hwnd),IDM_RSTART,MF_ENABLED); //enable Start button
			     SetWindowText(hwnd, TEXT("FFT Frequency Analyser")); // Set WindowName to title again
				 CheckMenuItem(GetMenu(hwnd),iDevSel+WM_DEV,MF_UNCHECKED); // uncheck old device
			     iDevSel = LOWORD(wParam)-WM_DEV;  // get new DeviceID
				 CheckMenuItem(GetMenu(hwnd),LOWORD(wParam),MF_CHECKED); // and check it
			  return 0;
              // Recording Start
			  case IDM_RSTART:
			   // Now do not allow the settings dialog anymore
			   // that would be fatal
			   EnableMenuItem(GetMenu(hwnd),IDM_SETTINGS,MF_GRAYED);
			   
			   //-------------------------------------
		       // Now allocate Memory for Buffers
               //--------------------------------------
			   //Buffer for FFT Points to Paint
		       apt = malloc(pFFT->iInputBufferSize*sizeof(POINT));
		       // Recording Buffer:
		       pTempBuffer = malloc(pFFT->iInputBufferSize);
		      // the FFT creates Values in the pos and neg range
		      // which are symmetrical to the 
		      // horiziontal Y axis
		      // we actually only paint the left side
		      // but we need the full buffer for the fft
		      // Buffer for RealValues of FFT
              pfRealBuf= malloc(pFFT->iInputBufferSize*sizeof(float));
		      // Buffer for Imaginary Values of FFT
		      pfImagBuf= malloc(pFFT->iInputBufferSize*sizeof(float));
		      // Absolute Value result Buffer
		      pfResBuf = malloc(pFFT->iInputBufferSize*sizeof(float));
			  // allocate 2 Buffers for AudioDevice
               pBuffer1 = malloc (pFFT->iInputBufferSize) ; 
               pBuffer2 = malloc (pFFT->iInputBufferSize) ;
               
		       if(!pfRealBuf || 
			      !pfImagBuf || 
			      !pfResBuf  ||
			      !apt       ||
			      !pBuffer1  || 
			      !pBuffer2 )
			   {   MessageBeep (MB_ICONEXCLAMATION) ;
                   MessageBox (hwnd, szMemError, szAppName, MB_ICONEXCLAMATION | MB_OK) ;
			       return 0;
			   }     
               // Else: open AudioDevice for the rocording 
               waveform.wFormatTag      = WAVE_FORMAT_PCM ;
               waveform.nChannels       = 1 ;
               waveform.nSamplesPerSec  = pFFT->iSamplesPerSecond ;
               waveform.nAvgBytesPerSec = pFFT->iSamplesPerSecond*2;//16bit=2Byte*8kHz
               waveform.nBlockAlign     = QUANTIZATION/8 ; //16bit/8=2Byte
               waveform.wBitsPerSample  = QUANTIZATION ;   //16 bit per Sample

⌨️ 快捷键说明

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