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

📄 main.c

📁 用Windows 下实现快速傅立叶变化
💻 C
📖 第 1 页 / 共 2 页
字号:
               waveform.cbSize          = 0 ; //no exra info needed
               // Open WaveDevice for recording
               if (waveInOpen (&hWaveIn, iDevSel, &waveform, (DWORD) hwnd, 0, CALLBACK_WINDOW))
               {
                    free (pBuffer1) ;
                    free (pBuffer2) ;
                    MessageBeep (MB_ICONEXCLAMATION) ;
                    MessageBox (hwnd, szOpenError, szAppName, MB_ICONEXCLAMATION | MB_OK) ;
               }
               else
			   {
               // init and prepare WaveHeader1;
			   // We need 2 Headers and two Buffers
               pWaveHdr1->lpData          = pBuffer1 ;
               pWaveHdr1->dwBufferLength  = pFFT->iInputBufferSize ;
               pWaveHdr1->dwBytesRecorded = 0 ;
               pWaveHdr1->dwUser          = 0 ;
               pWaveHdr1->dwFlags         = 0 ;
               pWaveHdr1->dwLoops         = 1 ;
               pWaveHdr1->lpNext          = NULL ;
               pWaveHdr1->reserved        = 0 ;
               // The waveInPrepareHeader function 
			   // prepares a buffer for waveform-audio input.
               waveInPrepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
               // init and prepare WaveHeader2;
               pWaveHdr2->lpData          = pBuffer2 ;
               pWaveHdr2->dwBufferLength  = pFFT->iInputBufferSize ;
               pWaveHdr2->dwBytesRecorded = 0 ;
               pWaveHdr2->dwUser          = 0 ;
               pWaveHdr2->dwFlags         = 0 ;
               pWaveHdr2->dwLoops         = 1 ;
               pWaveHdr2->lpNext          = NULL ;
               pWaveHdr2->reserved        = 0 ;
               waveInPrepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
			   SendMessage(hwnd, WM_FREQ,0,0);
			   EnableMenuItem(GetMenu(hwnd),IDM_RSTART,MF_GRAYED); //gray out Start
			   EnableMenuItem(GetMenu(hwnd),IDM_RSTOP,MF_ENABLED); //enable Stop
			   }
			   return 0;
			  case IDM_RSTOP:
			   // Stop recording and reset AudioDevice 
               bEnding = TRUE ;
               waveInReset (hWaveIn) ; 
			   SetWindowText(hwnd, TEXT("FFT Frequency Analyser")); //reload WindowText
			   EnableMenuItem(GetMenu(hwnd),IDM_RSTOP,MF_GRAYED); // grayout stop
			   EnableMenuItem(GetMenu(hwnd),IDM_RSTART,MF_ENABLED); // enable Start
			   EnableMenuItem(GetMenu(hwnd),IDM_SETTINGS,MF_GRAYED);
			   EnableMenuItem(GetMenu(hwnd),IDM_SETTINGS,MF_ENABLED);
			   return 0;
		   } 
		   break;
	 case WM_CREATE:     
           hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
		   pFFT = malloc(sizeof(PFFT_DATA));
		   pFFT->iInputBufferSize   =1024;
		   pFFT->iNumOfSamples      = pFFT->iInputBufferSize/2;
		   pFFT->iSamplesPerSecond  = 8000;
		   //---------------------
           //Device to Menu setup:
		   //----------------------
           // The waveInGetNumDevs function returns the number of 
		   // waveform-audio input devices present 
		   // in the system.
           iNumDev = waveInGetNumDevs();
		   // We append all the devices to our menu. For this
		   // we get our DevCaps Structure filled
		   // by waveInGetDeviceCaps
		   for (i=0;i<iNumDev;i++)
		   {
             waveInGetDevCaps(i, &DevCaps,sizeof(DevCaps));
             AppendMenu(GetSubMenu(GetMenu(hwnd),1), MF_STRING, i+WM_DEV, DevCaps.szPname) ;
		   }
		   // Pre Select Device 0 (Windows WaveMapper);
           iDevSel = 0;
           CheckMenuItem(GetMenu(hwnd),WM_DEV,MF_CHECKED);
		   EnableMenuItem(GetMenu(hwnd),IDM_RSTOP,MF_GRAYED);
		   //-------------------------------------
		   // Now allocate Memory for both headers
           //--------------------------------------
           pWaveHdr1 = malloc (sizeof (WAVEHDR)) ;
           pWaveHdr2 = malloc (sizeof (WAVEHDR)) ;
		  // Here we also need a paint brush and 
		  // a "deleting" brush (Window Color)
		  // don't forget to delete this Resource
          hpen_paint   = CreatePen(PS_SOLID,1,RGB(0,200,240));
          hpen_del     = CreatePen(PS_SOLID,1,RGB(0,0,0));
          //and Setup beginning Scroll Range (view100%)
          SendMessage(hwnd, WM_COMMAND,(WPARAM)IDM100,(LPARAM)NULL);
		  return 0;
     case WM_SIZE:
		  GetClientRect(hwnd, &rect);  // Get Client Area
          return 0 ;
	 // User defined Message to display measured Freuqency 
	 // in the middle of the screen as indicated by the white line
     case WM_FREQ:
		  // Freqenvy = (0,5 * Range + DisplayStartPos)*SamplingFreq/pFFT->iNumOfSamples
		  // Display Frequency in WindowTitle
		  iFreq = (iRange/2 + iStartPos)*pFFT->iSamplesPerSecond/pFFT->iNumOfSamples;
          wsprintf(buffer, TEXT("Frequency: %d Hz"), iFreq);
          SetWindowText(hwnd, buffer);
		  return 0;
     case WM_HSCROLL:
          // Scroll Handling
          switch (LOWORD (wParam))
          {
          case SB_LINEUP:         iStartPos  -= 1 ;  break ;
          case SB_LINEDOWN:       iStartPos  += 1 ;  break ;
          case SB_PAGEUP:         iStartPos  -= 5 ;  break ;
          case SB_PAGEDOWN:       iStartPos  += 5 ;  break ;
		  break;
          case SB_THUMBTRACK:
               iStartPos =  HIWORD (wParam)-iRange/2 ;
              break ;
          default:
               return 0 ;
          }
		  // don't allow to scroll more than half of iRange
		  if (iStartPos <-iRange/2) 
			      iStartPos = -iRange/2;
		  else if (iStartPos > (int)(pFFT->iNumOfSamples-iRange)/2)
			  iStartPos= (int)(pFFT->iNumOfSamples-iRange)/2;
		  // update FrequenyInfo
		  SendMessage(hwnd, WM_FREQ,0,0);
          SetScrollPos (hwnd, SB_HORZ, iRange/2 +iStartPos, TRUE) ;
          return 0 ;

     case MM_WIM_OPEN: // Device is opened  
		  
          // Add Buffer to Device 
          waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
          // Start recording
          bRecording = TRUE ; // device is recording
          bEnding = FALSE ;   // and not shutting down 
          waveInStart (hWaveIn); // Start recording
          return TRUE ;
          
     case MM_WIM_DATA: // waveform-audio data is present
		  
         
          // Copy rec. data to TempBuffer 
          CopyMemory (pTempBuffer, ((PWAVEHDR) lParam)->lpData,
                         ((PWAVEHDR) lParam)->dwBytesRecorded) ;

          if (bEnding)  // if device shutting down
          {
               waveInClose (hWaveIn) ;
               return TRUE ;
          }
          
          // Add new Buffer to device
          waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
		  //--------------------
		  // Now the FFT Part:
		  //--------------------
		  // Copy AudioData into RealBuffer and ImagBuffer
		  // (ImagBuffer is 0) and align data!!!
          CopyAudioData(pTempBuffer, pfRealBuf, pfImagBuf, pFFT->iInputBufferSize); 
          // Do the FFT transformation
          FFT(pfRealBuf, pfImagBuf, pFFT->iNumOfSamples);
          // now Place abslute Value of FFT in ResultBuffer
		  // which is abs(z) = sqrt(re(z)^2+Im(z)^2)
		  GetResult(pfRealBuf, pfImagBuf,pfResBuf,pFFT->iNumOfSamples);
          // Now Paint the window
		  hdc = GetDC(hwnd); // get the device Context
		  SelectObject(hdc,hpen_del); // select deleting Pen
          Polyline (hdc, apt, iTmpRange) ; // delete old line
          SelectObject(hdc,hpen_paint);// select paint color
		  // and Draw ResultBuffer to Window
		  // max Range = NumOfSamples/2 
          DrawFFTBuffer(hdc,rect,apt ,pfResBuf,iStartPos,iRange,pFFT->iNumOfSamples/2);
		  iTmpRange = iRange;  // save Range
		  ReleaseDC(hwnd, hdc); // release DC
          return TRUE ;
          
     case MM_WIM_CLOSE:  // Device shutdown
          // unprepare  and free Waceheader
          waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
          if (pBuffer1) free (pBuffer1) ;
          if (pBuffer2) free (pBuffer2) ;
		  if (apt) free(apt);
		  if (pTempBuffer) free (pTempBuffer) ;
		  if (pfResBuf) free (pfResBuf);
		  if (pfRealBuf) free (pfRealBuf) ;
		  if (pfImagBuf) free (pfImagBuf)  ;
          bRecording = FALSE ; // not recording
		  // if application is waiting to shutdown, do so now
          if (bTerminating) //  
               SendMessage (hwnd, WM_DESTROY, 0, 0) ;
          return TRUE ;
          
          case WM_CLOSE:
			  if (bRecording)  // if still recording
               {
                    bTerminating = TRUE ; // set terminating
                    bEnding = TRUE ;
                    waveInReset (hWaveIn) ; //Reset device
					return 0;  // don't close yet, wait for last WIM_DATA
               }
			   SendMessage (hwnd, WM_DESTROY, 0, 0) ;
          return 0 ;
          case WM_DESTROY:
		       DeleteObject(hpen_paint); // release resource
			   DeleteObject(hpen_del);   // release resource
               if (pWaveHdr1) free (pWaveHdr1) ;
               if (pWaveHdr2) free (pWaveHdr2) ;
               PostQuitMessage (0) ;
		  return 0;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

// The AboutBox Sialog Procedure
BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
     switch (message)
     {
     case WM_INITDIALOG :
     return TRUE ;
          
     case WM_COMMAND :
          switch (LOWORD (wParam))
          {
          case IDOK :
               EndDialog (hDlg, 0) ;
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}

// The Settings DialogProcedure
BOOL CALLBACK SettingsDlgProc (HWND hDlg, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
	static PFFT_DATA pFFTData ; 
	static int iValueSampleRate[] = {8000,11025,22050,44100},
		       iValueBufferSize[] = {1024,2048,4096,8192};
	static unsigned char cSampleRateNr=0,  // which of the cekcbox is checked
		                 cBufferSizeNr=0,
						 n;                

     switch (message)
     {
     case WM_INITDIALOG :
          pFFTData = (PFFT_DATA) lParam;   // get the FFT Struct from lparam
		  CheckRadioButton (hDlg, IDC_RADIO1, IDC_RADIO4, IDC_RADIO1+cBufferSizeNr);
          CheckRadioButton (hDlg, IDC_RADIO5, IDC_RADIO8, IDC_RADIO5+cSampleRateNr);
          return TRUE ;
          
     case WM_COMMAND :
          switch (LOWORD (wParam))
          {
          case IDOK :
		   // now check the appropiate checkboxes
		   // for this loop it is important to 
		   // have the checkBox Symbols in the right order
		   // IDC_RADIO1=1000 ..... IDC_RADIO4 = 1004
		   // IDC_RADIO5=1005.......IDC_RADIO8 = 1008
           for (n=0;n<4;n++)
		   {
		     if (IsDlgButtonChecked (hDlg, IDC_RADIO1+n))
			 {
				 pFFTData->iInputBufferSize  = iValueBufferSize[n];
				 pFFTData->iNumOfSamples     = iValueBufferSize[n]/2;
				 cBufferSizeNr=n;
				 break;
			 }
		   }
		   for (n=0;n<4;n++)
		   {
		     if (IsDlgButtonChecked (hDlg, IDC_RADIO5+n))
			 {
		        pFFTData->iSamplesPerSecond = iValueSampleRate[n];
				cSampleRateNr=n;
				break;
			 }
		   }
          case IDCANCEL :
               EndDialog (hDlg, 0) ;
               return TRUE ;
          } // end switch
          break ;
     }
     return FALSE ;
}

⌨️ 快捷键说明

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