home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************/
- /* wave.c */
- /* -- Simple tone generation. */
- /* -- To build: "cc -c -d -DSTRICT wave.c" */
- /*****************************************************/
- #include <windows.h>
- #include <windowsx.h>
- #include <mmsystem.h>
- #include <math.h>
- #include <limits.h>
- #include "snd/wave.h"
-
- /* Types. */
- typedef struct
- {
- DWORD lwTag; /* Tag. */
- DWORD lcb; /* Size of data. */
- } CNK; /* ChuNK. */
-
- typedef struct
- {
- CNK cnkRiff; /* 'RIFF' chunk. */
- DWORD lwWaveId; /* Must be 'WAVE'. */
- CNK cnkFormat; /* Wave specific format chunk. */
- PCMWAVEFORMAT wft; /* PCM stuff. */
- CNK cnkData; /* PCM Data chunk. */
- BYTE rgb[1]; /* The sound data. */
- } SND; /* SouND. */
-
- /* Constants. */
- #define rFreqMin 20.f /* Allowable frequency range. */
- #define rFreqMax 20000.f
- #define cbBufMax (0x00010000 - sizeof(SND))
-
- /* Globals. */
- SND far *lpsnd;
- float r2Pi;
-
- BOOL FInitSnd(void)
- /*****************************************************/
- /* -- Initialize this module. */
- /*****************************************************/
- {
- r2Pi = (float)(asin(1) * 4.0);
-
- if (NULL == (lpsnd = (SND far *)GlobalAllocPtr(GMEM_MOVEABLE |
- GMEM_SHARE, 0x00010000)))
- return FALSE;
-
- lpsnd->cnkRiff.lwTag = *(long *)"RIFF";
- lpsnd->cnkRiff.lcb = sizeof(SND) - sizeof(CNK) - sizeof(BYTE);
- lpsnd->lwWaveId = *(long *)"WAVE";
- lpsnd->cnkFormat.lwTag = *(long *)"fmt ";
- lpsnd->cnkFormat.lcb = sizeof(PCMWAVEFORMAT);
- lpsnd->wft.wf.wFormatTag = WAVE_FORMAT_PCM;
- lpsnd->cnkData.lwTag = *(long *)"data";
- lpsnd->cnkData.lcb = 0;
- return TRUE;
- }
-
- void CloseSnd(void)
- /*****************************************************/
- /* -- Close this module. */
- /*****************************************************/
- {
- if (lpsnd != (SND far *)NULL)
- GlobalFreePtr(lpsnd);
- }
-
- void FDelay(long cms)
- {
- DWORD mscStart; /* Tone onset time. */
-
- if( cms > 0 ) {
- mscStart = timeGetTime();
- while (timeGetTime() - mscStart < (DWORD)cms)
- ;
- }
- }
-
-
-
- BOOL FPlaySnd(float rFreq, long cms, UINT csps,
- UINT cbit, UINT cchn)
- /*****************************************************/
- /* -- Play the given sound. */
- /* -- rFreq : Frequency of sound (Hz). */
- /* -- cms : Duration (ms). */
- /* -- csps : Sampling rate (Hz). */
- /* -- cbit : Sample size (bits/sample/channel). */
- /* -- cchn : Number of channels. */
- /*****************************************************/
- {
- float r; /* General purpose. */
- float csmpCycle; /* Samples per tone cycle. */
- UINT cbSample; /* Bytes/sample (per channel). */
- DWORD cbBufReq; /* Required buffer size. */
- UINT csmpBuf; /* Sample count in buffer. */
- UINT ismp, ismpT; /* Sample indices. */
- UINT ichn; /* Channel index. */
- DWORD mscStart; /* Tone onset time. */
-
- if (rFreq < rFreqMin || rFreq > rFreqMax)
- return FALSE; /* Out of range. */
-
- csmpCycle = csps / rFreq;
- csmpBuf = (UINT)(csmpCycle + 0.5);
- cbSample = cbit / 8;
- cbBufReq = csmpBuf * cbSample * cchn;
- if (cbBufMax < cbBufReq)
- return FALSE; /* Too big. */
-
- lpsnd->wft.wf.nChannels = cchn;
- lpsnd->wft.wf.nSamplesPerSec = csps;
- lpsnd->wft.wf.nAvgBytesPerSec =
- csps * cchn * cbSample;
- lpsnd->wft.wf.nBlockAlign = cchn * cbSample;
- lpsnd->wft.wBitsPerSample = cbit;
- lpsnd->cnkData.lcb = cbBufReq;
- lpsnd->cnkRiff.lcb = cbBufReq +
- sizeof(SND) - sizeof(CNK) - sizeof(BYTE);
- for (ismp = 0; ismp < csmpBuf; ismp++)
- {
- r = (float)sin((r2Pi * ismp / csmpCycle) + (r2Pi/16));
- for (ichn = 0; ichn < cchn; ichn++)
- {
- ismpT = ismp * cchn + ichn;
- if (cbSample == 1)
- lpsnd->rgb[ismpT] = 0x80 +
- (int)(128.0 * r);
- else
- ((LPWORD)lpsnd->rgb)[ismpT] =
- (int)(SHRT_MAX * r);
- }
- }
- sndPlaySound((LPCSTR)lpsnd,
- SND_ASYNC | SND_MEMORY | SND_LOOP);
- if( cms > 0 ) {
- mscStart = timeGetTime();
- while (timeGetTime() - mscStart < (DWORD)cms)
- ;
- sndPlaySound(NULL, SND_ASYNC);
- }
-
- return TRUE;
- }
-
- void StopSnd(void)
- /*****************************************************/
- /* -- Stop playing the current sound. */
- /*****************************************************/
- {
- sndPlaySound(NULL, SND_ASYNC);
- }
-
- /* EOF: Wave.c */