📄 main.c
字号:
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 + -