home *** CD-ROM | disk | FTP | other *** search
/ Emulator Universe CD / emulatoruniversecd1998.iso / Speccy / Emulators / winemu / SOURCES / SND / WAVE.C next >
Encoding:
C/C++ Source or Header  |  1996-05-12  |  4.5 KB  |  156 lines

  1. /*****************************************************/
  2. /* wave.c                                            */
  3. /* -- Simple tone generation.                        */
  4. /* -- To build: "cc -c -d -DSTRICT wave.c"           */
  5. /*****************************************************/
  6. #include <windows.h>
  7. #include <windowsx.h>
  8. #include <mmsystem.h>
  9. #include <math.h>
  10. #include <limits.h>
  11. #include "snd/wave.h"
  12.  
  13. /* Types. */
  14. typedef struct
  15.     {
  16.     DWORD lwTag; /* Tag. */
  17.     DWORD lcb;   /* Size of data. */
  18.     } CNK;       /* ChuNK. */
  19.  
  20. typedef struct
  21.     {
  22.     CNK   cnkRiff;     /* 'RIFF' chunk. */
  23.     DWORD lwWaveId;    /* Must be 'WAVE'. */
  24.     CNK   cnkFormat;   /* Wave specific format chunk. */
  25.     PCMWAVEFORMAT wft; /* PCM stuff. */
  26.     CNK   cnkData;     /* PCM Data chunk. */
  27.     BYTE  rgb[1];      /* The sound data. */
  28.     } SND;             /* SouND. */
  29.  
  30. /* Constants. */
  31. #define rFreqMin 20.f    /* Allowable frequency range. */
  32. #define rFreqMax 20000.f
  33. #define cbBufMax (0x00010000 - sizeof(SND))
  34.  
  35. /* Globals. */
  36. SND far *lpsnd;
  37. float    r2Pi;
  38.  
  39. BOOL FInitSnd(void)
  40. /*****************************************************/
  41. /* -- Initialize this module.                        */
  42. /*****************************************************/
  43.     {
  44.     r2Pi = (float)(asin(1) * 4.0);
  45.  
  46.     if (NULL == (lpsnd = (SND far *)GlobalAllocPtr(GMEM_MOVEABLE |
  47.       GMEM_SHARE, 0x00010000)))
  48.         return FALSE;
  49.  
  50.     lpsnd->cnkRiff.lwTag = *(long *)"RIFF";
  51.     lpsnd->cnkRiff.lcb = sizeof(SND) - sizeof(CNK) - sizeof(BYTE);
  52.     lpsnd->lwWaveId = *(long *)"WAVE";
  53.     lpsnd->cnkFormat.lwTag = *(long *)"fmt ";
  54.     lpsnd->cnkFormat.lcb = sizeof(PCMWAVEFORMAT);
  55.     lpsnd->wft.wf.wFormatTag = WAVE_FORMAT_PCM;
  56.     lpsnd->cnkData.lwTag = *(long *)"data";
  57.     lpsnd->cnkData.lcb = 0;
  58.     return TRUE;
  59.     }
  60.  
  61. void CloseSnd(void)
  62. /*****************************************************/
  63. /* -- Close this module.                             */
  64. /*****************************************************/
  65.     {
  66.     if (lpsnd != (SND far *)NULL)
  67.         GlobalFreePtr(lpsnd);
  68.     }
  69.  
  70. void FDelay(long cms)
  71. {
  72.    DWORD mscStart;           /* Tone onset time. */
  73.  
  74.    if( cms > 0 ) {
  75.       mscStart = timeGetTime();
  76.       while (timeGetTime() - mscStart < (DWORD)cms)
  77.             ;
  78.    }
  79. }
  80.  
  81.  
  82.  
  83. BOOL FPlaySnd(float rFreq, long cms, UINT csps,
  84.   UINT cbit, UINT cchn)
  85. /*****************************************************/
  86. /* -- Play the given sound.                          */
  87. /* -- rFreq : Frequency of sound (Hz).               */
  88. /* -- cms   : Duration (ms).                         */
  89. /* -- csps  : Sampling rate (Hz).                    */
  90. /* -- cbit  : Sample size (bits/sample/channel).     */
  91. /* -- cchn  : Number of channels.                    */
  92. /*****************************************************/
  93.     {
  94.     float r;         /* General purpose. */
  95.     float csmpCycle; /* Samples per tone cycle. */
  96.     UINT  cbSample;  /* Bytes/sample (per channel). */
  97.     DWORD cbBufReq;  /* Required buffer size. */
  98.     UINT  csmpBuf;   /* Sample count in buffer. */
  99.     UINT  ismp, ismpT; /* Sample indices. */
  100.     UINT  ichn;      /* Channel index. */
  101.     DWORD mscStart;  /* Tone onset time. */
  102.  
  103.     if (rFreq < rFreqMin || rFreq > rFreqMax)
  104.         return FALSE; /* Out of range. */
  105.  
  106.     csmpCycle = csps / rFreq;
  107.     csmpBuf = (UINT)(csmpCycle + 0.5);
  108.     cbSample = cbit / 8;
  109.     cbBufReq = csmpBuf * cbSample * cchn;
  110.     if (cbBufMax < cbBufReq)
  111.         return FALSE; /* Too big. */
  112.  
  113.     lpsnd->wft.wf.nChannels = cchn;
  114.     lpsnd->wft.wf.nSamplesPerSec = csps;
  115.     lpsnd->wft.wf.nAvgBytesPerSec =
  116.       csps * cchn * cbSample;
  117.     lpsnd->wft.wf.nBlockAlign = cchn * cbSample;
  118.     lpsnd->wft.wBitsPerSample = cbit;
  119.     lpsnd->cnkData.lcb = cbBufReq;
  120.     lpsnd->cnkRiff.lcb = cbBufReq +
  121.       sizeof(SND) - sizeof(CNK) - sizeof(BYTE);
  122.     for (ismp = 0; ismp < csmpBuf; ismp++)
  123.         {
  124.         r = (float)sin((r2Pi * ismp / csmpCycle) + (r2Pi/16));
  125.         for (ichn = 0; ichn < cchn; ichn++)
  126.             {
  127.             ismpT = ismp * cchn + ichn;
  128.             if (cbSample == 1)
  129.                 lpsnd->rgb[ismpT] = 0x80 +
  130.                   (int)(128.0 * r);
  131.             else
  132.                 ((LPWORD)lpsnd->rgb)[ismpT] =
  133.                   (int)(SHRT_MAX * r);
  134.             }
  135.         }
  136.     sndPlaySound((LPCSTR)lpsnd,
  137.       SND_ASYNC | SND_MEMORY | SND_LOOP);
  138.     if( cms > 0 ) {
  139.         mscStart = timeGetTime();
  140.         while (timeGetTime() - mscStart < (DWORD)cms)
  141.             ;
  142.         sndPlaySound(NULL, SND_ASYNC);
  143.     }
  144.  
  145.     return TRUE;
  146.     }
  147.  
  148. void StopSnd(void)
  149. /*****************************************************/
  150. /* -- Stop playing the current sound.                */
  151. /*****************************************************/
  152.     {
  153.     sndPlaySound(NULL, SND_ASYNC);
  154.     }
  155.  
  156. /* EOF: Wave.c */