<br><br><br><br>#include <windows.h><br>#include <math.h><br>#include "resource.h"<br><br>#define SAMPLE_RATE 11025<br>#define FREQ_MIN 20<br>#define FREQ_MAX 5000<br>#define FREQ_INIT 440<br>#define OUT_BUFFER_SIZE 4096<br>#define PI 3.14159<br><br>BOOL CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;<br><br>TCHAR szAppName [] = TEXT ("SineWave") ;<br><br>int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,<br> PSTR szCmdLine, int iCmdShow)<br>{<br> if (-1 == DialogBox (hInstance, szAppName, NULL, DlgProc))<br> {<br> MessageBox (NULL, TEXT ("This program requires Windows NT!"),<br> szAppName, MB_ICONERROR) ;<br> }<br> return 0 ;<br>}<br><br>VOID FillBuffer (PBYTE pBuffer, int iFreq)<br>{<br> static double fAngle ;<br> int i ;<br><br> for (i = 0 ; i < OUT_BUFFER_SIZE ; i++)<br> {<br> pBuffer = (BYTE) (127 + 127 * sin (fAngle)) ;<br><br> fAngle += 2 * PI * iFreq / SAMPLE_RATE ;<br><br> if (fAngle > 2 * PI)<br> fAngle -= 2 * PI ;<br> }<br>}<br><br>BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br>{<br> static BOOL bShutOff, bClosing ;<br> static HWAVEOUT hWaveOut ;<br> static HWND hwndScroll ;<br> static int iFreq = FREQ_INIT ;<br> static PBYTE pBuffer1, pBuffer2 ;<br> static PWAVEHDR pWaveHdr1, pWaveHdr2 ;<br> static WAVEFORMATEX waveformat ;<br> int iDummy ;<br> <br> switch (message)<br> {<br> case WM_INITDIALOG:<br> hwndScroll = GetDlgItem (hwnd, IDC_SCROLL) ;<br> SetScrollRange (hwndScroll, SB_CTL, FREQ_MIN, FREQ_MAX, FALSE) ;<br> SetScrollPos (hwndScroll, SB_CTL, FREQ_INIT, TRUE) ;<br> SetDlgItemInt (hwnd, IDC_TEXT, FREQ_INIT, FALSE) ;<br> <br> return TRUE ;<br> <br> case WM_HSCROLL:<br> switch (LOWORD (wParam))<br> {<br> case SB_LINELEFT: iFreq -= 1 ; break ;<br> case SB_LINERIGHT: iFreq += 1 ; break ;<br> case SB_PAGELEFT: iFreq /= 2 ; break ;<br> case SB_PAGERIGHT: iFreq *= 2 ; break ;<br> <br> case SB_THUMBTRACK:<br> iFreq = HIWORD (wParam) ;<br> break ;<br> <br> case SB_TOP:<br> GetScrollRange (hwndScroll, SB_CTL, &iFreq, &iDummy) ;<br> break ;<br> <br> case SB_BOTTOM:<br> GetScrollRange (hwndScroll, SB_CTL, &iDummy, &iFreq) ;<br> break ;<br> }<br> <br> iFreq = max (FREQ_MIN, min (FREQ_MAX, iFreq)) ;<br> <br> SetScrollPos (hwndScroll, SB_CTL, iFreq, TRUE) ;<br> SetDlgItemInt (hwnd, IDC_TEXT, iFreq, FALSE) ;<br> return TRUE ;<br> <br> case WM_COMMAND:<br> switch (LOWORD (wParam))<br> {<br> case IDC_ONOFF:<br> // If turning on waveform, hWaveOut is NULL<br> <br> if (hWaveOut == NULL)<br> {<br> // Allocate memory for 2 headers and 2 buffers<br><br> pWaveHdr1 = malloc (sizeof (WAVEHDR)) ;<br> pWaveHdr2 = malloc (sizeof (WAVEHDR)) ;<br> pBuffer1 = malloc (OUT_BUFFER_SIZE) ;<br> pBuffer2 = malloc (OUT_BUFFER_SIZE) ;<br><br> if (!pWaveHdr1 || !pWaveHdr2 || !pBuffer1 || !pBuffer2)<br> {<br> if (!pWaveHdr1) free (pWaveHdr1) ;<br> if (!pWaveHdr2) free (pWaveHdr2) ;<br> if (!pBuffer1) free (pBuffer1) ;<br> if (!pBuffer2) free (pBuffer2) ;<br><br> MessageBeep (MB_ICONEXCLAMATION) ;<br> MessageBox (hwnd, TEXT ("Error allocating memory!"),<br> szAppName, MB_ICONEXCLAMATION | MB_OK) ;<br> return TRUE ;<br> }<br><br> // Variable to indicate Off button pressed<br><br> bShutOff = FALSE ;<br> <br> // Open waveform audio for output<br> <br> waveformat.wFormatTag = WAVE_FORMAT_PCM ;<br> waveformat.nChannels = 1 ;<br> waveformat.nSamplesPerSec = SAMPLE_RATE ;<br> waveformat.nAvgBytesPerSec = SAMPLE_RATE ;<br> waveformat.nBlockAlign = 1 ;<br> waveformat.wBitsPerSample = 8 ;<br> waveformat.cbSize = 0 ;<br> <br> if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveformat,<br> (DWORD) hwnd, 0, CALLBACK_WINDOW)<br> != MMSYSERR_NOERROR)<br> {<br> free (pWaveHdr1) ;<br> free (pWaveHdr2) ;<br> free (pBuffer1) ;<br> free (pBuffer2) ;<br><br> hWaveOut = NULL ;<br> MessageBeep (MB_ICONEXCLAMATION) ;<br> MessageBox (hwnd, <br> TEXT ("Error opening waveform audio device!"),<br> szAppName, MB_ICONEXCLAMATION | MB_OK) ;<br> return TRUE ;<br> }<br><br> // Set up headers and prepare them<br><br> pWaveHdr1->lpData = pBuffer1 ;<br> pWaveHdr1->dwBufferLength = OUT_BUFFER_SIZE ;<br> pWaveHdr1->dwBytesRecorded = 0 ;<br> pWaveHdr1->dwUser = 0 ;<br> pWaveHdr1->dwFlags = 0 ;<br> pWaveHdr1->dwLoops = 1 ;<br> pWaveHdr1->lpNext = NULL ;<br> pWaveHdr1->reserved = 0 ;<br> <br> waveOutPrepareHeader (hWaveOut, pWaveHdr1, <br> sizeof (WAVEHDR)) ;<br><br> pWaveHdr2->lpData = pBuffer2 ;<br> pWaveHdr2->dwBufferLength = OUT_BUFFER_SIZE ;<br> pWaveHdr2->dwBytesRecorded = 0 ;<br> pWaveHdr2->dwUser = 0 ;<br> pWaveHdr2->dwFlags = 0 ;<br> pWaveHdr2->dwLoops = 1 ;<br> pWaveHdr2->lpNext = NULL ;<br> pWaveHdr2->reserved = 0 ;<br> <br> waveOutPrepareHeader (hWaveOut, pWaveHdr2,<br> sizeof (WAVEHDR)) ;<br> }<br> // If turning off waveform, reset waveform audio<br> else<br> {<br> bShutOff = TRUE ;<br> waveOutReset (hWaveOut) ;<br> }<br> return TRUE ;<br> }<br> break ;<br><br> // Message generated from waveOutOpen call<br> <br> case MM_WOM_OPEN:<br> SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn Off")) ;<br><br> // Send two buffers to waveform output device<br> <br> FillBuffer (pBuffer1, iFreq) ;<br> waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;<br> <br> FillBuffer (pBuffer2, iFreq) ;<br> waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;<br> return TRUE ;<br><br> // Message generated when a buffer is finished<br> <br> case MM_WOM_DONE:<br> if (bShutOff)<br> {<br> waveOutClose (hWaveOut) ;<br> return TRUE ;<br> }<br><br> // Fill and send out a new buffer<br><br> FillBuffer (((PWAVEHDR) lParam)->lpData, iFreq) ;<br> waveOutWrite (hWaveOut, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;<br> return TRUE ;<br> <br> case MM_WOM_CLOSE:<br> waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;<br> waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;<br><br> free (pWaveHdr1) ;<br> free (pWaveHdr2) ;<br> free (pBuffer1) ;<br> free (pBuffer2) ;<br><br> hWaveOut = NULL ;<br> SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn On")) ;<br> <br> if (bClosing)<br> EndDialog (hwnd, 0) ;<br> <br> return TRUE ;<br> <br> case WM_SYSCOMMAND:<br> switch (wParam)<br> {<br> case SC_CLOSE:<br> if (hWaveOut != NULL)<br> {<br> bShutOff = TRUE ;<br> bClosing = TRUE ;<br> <br> waveOutReset (hWaveOut) ;<br> }<br> else<br> EndDialog (hwnd, 0) ;<br> <br> return TRUE ;<br> }<br> break ;<br> }<br> return FALSE ;<br>}