home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Issue 2 / Freelog_HS_3_Setp_Oct_Nov_2000_CD2.mdx / Arcade / Orbit / src / sound.c < prev    next >
C/C++ Source or Header  |  1999-09-27  |  12KB  |  480 lines

  1. /*
  2.  
  3. ORBIT, a freeware space combat simulator
  4. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. */
  21.  
  22. #include "orbit.h"
  23.  
  24. /* Sound file names */
  25. char *sample_names[NSOUNDS] = {
  26.     "sounds/phaser.wav",      /* SOUND_FIRE */
  27.     "sounds/explosion1.wav",  /* SOUND_BOOM */
  28.     "sounds/communicator.wav" /* SOUND_COMM */
  29. };
  30.  
  31. /*
  32.  *  Lots of stuff for sound
  33.  *
  34.  *  Much of this is based on code from StackUp by Tool@theWaterCooler.com
  35.  */
  36.  
  37. #ifdef WIN32
  38.  
  39. #include <dsound.h>
  40.  
  41. #define USE_DSOUND
  42.  
  43. /* Windows stuff I don't understand */
  44. HRESULT        g_DX_Result;
  45. HWND    hwnd;
  46. LPDIRECTSOUND    g_lpDS;
  47. int        g_bSoundPresent;
  48. int        m_bSoundPresent;
  49. LPDIRECTSOUNDBUFFER   m_lpDS_Sounds[NSOUNDS];
  50.  
  51. #define DS_CHECK_ERROR(ErrorMessage) \
  52.     {if(g_DX_Result != DS_OK) {Log (ErrorMessage); return 0;}}
  53. #define DS_CB_ERROR(ErrorMessage) {Log (ErrorMessage); return 0;}
  54.  
  55. int InitSound (void);
  56. void FinishSound (void);
  57. int g_DS_Init (void);
  58. void g_DS_Finish (void);
  59. int InitSound2 (void);
  60. int FinishSound2 (void);
  61. int DS_Init (void);
  62. int DS_CreateBufferFromWaveFile(char* FileName, DWORD dwBuf);
  63. int DS_CreateSoundBuffer(DWORD dwBuf, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo);
  64. int DS_ReadData(LPDIRECTSOUNDBUFFER lpDSB, FILE* pFile, DWORD dwSize, DWORD dwPos);
  65. int StopAllSounds (void);
  66. int DS_PlaySound(enum sounds nSound, DWORD dwFlags);
  67. void DS_Finish (void);
  68.  
  69. int InitSound()
  70. {
  71. //  m_pThisApp = AfxGetApp();
  72.     hwnd = GetDesktopWindow();
  73.  
  74.     g_bSoundPresent = g_DS_Init();
  75.     if(!g_bSoundPresent)
  76.       g_DS_Finish();
  77.  
  78.   /* Read in the sounds, etc */
  79.   InitSound2();
  80.  
  81.   return 1;
  82. }
  83.  
  84. void FinishSound()
  85. {
  86.     g_DS_Finish();
  87.     FinishSound2();
  88. }
  89.  
  90. int g_DS_Init()
  91. {
  92.     HWND hwnd;
  93.  
  94.     hwnd = GetActiveWindow();
  95.  
  96.   g_DX_Result = DirectSoundCreate(NULL, &g_lpDS, NULL);
  97.   DS_CHECK_ERROR("Error - DS - Create - Audio cannot be used");
  98.  
  99.   g_DX_Result = IDirectSound_SetCooperativeLevel (g_lpDS, GetActiveWindow(), DSSCL_NORMAL);
  100.   DS_CHECK_ERROR("Error - DS - SetCooperativeLevel");
  101.  
  102.   return 1;
  103. }
  104.  
  105. void g_DS_Finish()
  106. {
  107.   if(g_lpDS != NULL)
  108.   {
  109. //  g_lpDS->Release();
  110.     IDirectSound_Release (g_lpDS);
  111.     g_lpDS = NULL;
  112.   }
  113. }
  114.  
  115. int InitSound2()
  116. {
  117.     if((m_bSoundPresent = g_bSoundPresent) == 1)
  118.       m_bSoundPresent = DS_Init();
  119.  
  120.   return 1;
  121. }
  122.  
  123. int FinishSound2() 
  124. {
  125.   if(m_bSoundPresent)
  126.     DS_Finish();
  127.   return 1;
  128. }
  129.  
  130. /*  Playing sounds
  131.  
  132.       #ifdef USE_DSOUND
  133.         DS_PlaySound(DS_SOUND_SIGNALIZING, NULL);
  134.       #endif
  135.       #ifdef USE_DSOUND
  136.         DS_PlaySound(DS_SOUND_FALLING, NULL);
  137.       #endif
  138.     #ifdef USE_DSOUND
  139.       DS_PlaySound(DS_SOUND_ROTATE, NULL);
  140.     #endif
  141.       #ifdef USE_DSOUND
  142.         DS_PlaySound(DS_SOUND_PLACE, NULL);
  143.       #endif
  144.               #ifdef USE_DSOUND
  145.                 DS_PlaySound(DS_SOUND_SPEEDUP, NULL);
  146.               #endif
  147. */
  148.  
  149. int DS_Init()
  150. {
  151.   enum sounds i;
  152.  
  153.   for(i = SOUND_FIRE; i < NSOUNDS; i ++)    // Null out all the sound pointers
  154.     m_lpDS_Sounds[i] = NULL;
  155.  
  156.   for(i = SOUND_FIRE; i < NSOUNDS; i++)
  157.     if(!DS_CreateBufferFromWaveFile(sample_names[i], i))
  158.       DS_CB_ERROR("Error - DS - Loading .WAV file");
  159.  
  160.   return 1;
  161. }
  162.  
  163. int DS_CreateBufferFromWaveFile(char* FileName, DWORD dwBuf)
  164. {
  165.   struct WaveHeader
  166.   {
  167.     BYTE        RIFF[4];          // "RIFF"
  168.     DWORD       dwSize;           // Size of data to follow
  169.     BYTE        WAVE[4];          // "WAVE"
  170.     BYTE        fmt_[4];          // "fmt "
  171.     DWORD       dw16;             // 16
  172.     WORD        wOne_0;           // 1
  173.     WORD        wChnls;           // Number of Channels
  174.     DWORD       dwSRate;          // Sample Rate
  175.     DWORD       BytesPerSec;      // Sample Rate
  176.     WORD        wBlkAlign;        // 1
  177.     WORD        BitsPerSample;    // Sample size
  178.     BYTE        DATA[4];          // "DATA"
  179.     DWORD       dwDSize;          // Number of Samples
  180.   };
  181.  
  182.   struct WaveHeader wavHdr;
  183.   FILE *pFile;
  184.   DWORD dwSize;
  185.   BOOL bStereo;
  186.  
  187.   // Open the wave file       
  188.   pFile = fopen(FileName, "rb");
  189.   if(!pFile)
  190.   {
  191.     Log ("DS_CreateBufferFromWaveFile: Can't open %s", FileName);
  192.     return 0;
  193.   }
  194.  
  195.   // Read in the wave header          
  196.   if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1) 
  197.   {
  198.     Log ("DS_CreateBufferFromWaveFile: Can't read wave header");
  199.     fclose(pFile);
  200.     return 0;
  201.   }
  202.  
  203. /**
  204.     Log ("Header for WAV file %s", FileName);
  205.     Log ("dwSize: %d", wavHdr.dwSize);
  206.     Log ("dw16: %d", wavHdr.dw16);
  207.     Log ("wOne_0: %d", wavHdr.wOne_0);
  208.     Log ("wChnls: %d", wavHdr.wChnls);
  209.     Log ("dwSRate: %d", wavHdr.dwSRate);
  210.     Log ("BytesPerSec: %d", wavHdr.BytesPerSec);
  211.     Log ("wBlkAlign: %d", wavHdr.wBlkAlign);
  212.     Log ("BitsPerSample: %d", wavHdr.BitsPerSample);
  213.     Log ("dwDSize: %d", wavHdr.dwDSize);
  214. **/
  215.  
  216.   // Figure out the size of the data region
  217.   dwSize = wavHdr.dwDSize;
  218.  
  219.   // Is this a stereo or mono file?
  220.   bStereo = wavHdr.wChnls > 1 ? 1 : 0;
  221.  
  222.   // Create the sound buffer for the wave file
  223.   if(DS_CreateSoundBuffer(dwBuf, dwSize, wavHdr.dwSRate, wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo) != TRUE)
  224.   {
  225.     Log ("DS_CreateBufferFromWaveFile: DS_CreateSoundBuffer returned FALSE");
  226.     // Close the file
  227.     fclose(pFile);
  228.     
  229.     return 0;
  230.   }
  231.  
  232.   // Read the data for the wave file into the sound buffer
  233.   if (!DS_ReadData(m_lpDS_Sounds[dwBuf], pFile, dwSize, sizeof(wavHdr))) 
  234.   {
  235.     Log ("DS_CreateBufferFromWaveFile: DS_ReadData returned FALSE");
  236.     fclose(pFile);
  237.     return 0;
  238.   }
  239.   fclose(pFile);
  240.   return 1;
  241. }
  242.  
  243. int DS_CreateSoundBuffer(DWORD dwBuf, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
  244. {
  245.   PCMWAVEFORMAT pcmwf;
  246.   DSBUFFERDESC dsbdesc;
  247.   
  248.   // Set up wave format structure.
  249.   memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
  250.   pcmwf.wf.wFormatTag         = WAVE_FORMAT_PCM;      
  251.   pcmwf.wf.nChannels          = bStereo ? 2 : 1;
  252.   pcmwf.wf.nSamplesPerSec     = dwFreq;
  253.   pcmwf.wf.nBlockAlign        = (WORD)dwBlkAlign;
  254.   pcmwf.wf.nAvgBytesPerSec    = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
  255.   pcmwf.wBitsPerSample        = (WORD)dwBitsPerSample;
  256.  
  257.   // Set up DSBUFFERDESC structure.
  258.   memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));  // Zero it out. 
  259.   dsbdesc.dwSize              = sizeof(DSBUFFERDESC);
  260.   dsbdesc.dwFlags             = DSBCAPS_CTRLDEFAULT;  // Need default controls (pan, volume, frequency).
  261.   dsbdesc.dwBufferBytes       = dwBufSize; 
  262.   dsbdesc.lpwfxFormat         = (LPWAVEFORMATEX)&pcmwf;
  263.  
  264. //g_DX_Result = g_lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDS_Sounds[dwBuf], NULL);
  265.   g_DX_Result = IDirectSound_CreateSoundBuffer(g_lpDS, &dsbdesc, &m_lpDS_Sounds[dwBuf], NULL);
  266.   DS_CHECK_ERROR("Error - DS - CreateSoundBuffer");
  267.  
  268.   return 1;
  269. }
  270.  
  271. int DS_ReadData(LPDIRECTSOUNDBUFFER lpDSB, FILE* pFile, DWORD dwSize, DWORD dwPos) 
  272. {
  273.   LPVOID pData1;
  274.   DWORD  dwData1Size;
  275.   LPVOID pData2;
  276.   DWORD  dwData2Size;
  277.   HRESULT rval;
  278.  
  279.   // Seek to correct position in file (if necessary)
  280.   if (dwPos != 0xffffffff) 
  281.   {
  282.     if (fseek(pFile, dwPos, SEEK_SET) != 0) 
  283.     {
  284.       Log ("DS_ReadData: fseek failed");
  285.       return 0;
  286.     }
  287.   }
  288.  
  289.   // Lock data in buffer for writing
  290. //rval = lpDSB->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
  291.   rval = IDirectSoundBuffer_Lock(lpDSB, 0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
  292. //Log ("dwSize = %d, dwData1Size = %d, dwData2Size= %d", dwSize, dwData1Size, dwData2Size);
  293.   if (rval != DS_OK)
  294.   {
  295.     Log ("DS_ReadData: IDirectSoundBuffer_Loc returned %d", rval);
  296.     return 0;
  297.   }
  298.  
  299.   // Read in first chunk of data
  300.   if (dwData1Size > 0) 
  301.   {
  302.     if (fread(pData1, dwData1Size, 1, pFile) != 1) 
  303.     {
  304.       Log ("DS_ReadData: fread() of first chunk failed");
  305.       return 0;
  306.     }
  307.   }
  308.  
  309.   // read in second chunk if necessary
  310.   if (dwData2Size > 0) 
  311.   {
  312.     if (fread(pData2, dwData2Size, 1, pFile) != 1) 
  313.     {
  314.       Log ("DS_ReadData: fread() of second chunk failed");
  315.       return 0;
  316.     }
  317.   }
  318.  
  319.   // Unlock data in buffer
  320. //rval = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
  321.   rval = IDirectSoundBuffer_Unlock(lpDSB, pData1, dwData1Size, pData2, dwData2Size);
  322.   if (rval != DS_OK)
  323.   {
  324.     Log ("DS_ReadData: IDirectSoundBuffer_Unlock returned %d", rval);
  325.     return 0;
  326.   }
  327.  
  328.   return 1;
  329. }
  330.  
  331. int StopAllSounds()
  332. {
  333.   int i;
  334.  
  335.   // Make sure we have a valid sound buffer
  336.   for (i = 0; i < NSOUNDS; i++)
  337.   {
  338.     if(m_lpDS_Sounds[i])
  339.     {
  340.       DWORD dwStatus;
  341. //    g_DX_Result = m_lpDS_Sounds[i]->GetStatus(&dwStatus);
  342.       g_DX_Result = IDirectSoundBuffer_GetStatus(m_lpDS_Sounds[i], &dwStatus);
  343.       DS_CHECK_ERROR("Error - DS - GetStatus");
  344.  
  345.       if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
  346.       {  
  347. //      g_DX_Result = m_lpDS_Sounds[i]->Stop();     // Play the sound
  348.         g_DX_Result = IDirectSoundBuffer_Stop(m_lpDS_Sounds[i]);     // Play the sound
  349.         DS_CHECK_ERROR("Error - DS - Stop");
  350.       }
  351.     }
  352.   }
  353.   return 1;
  354. }
  355.  
  356. int PlayAudio (enum sounds nSound)
  357. {
  358.   DS_PlaySound(nSound, 0);
  359. }
  360.  
  361. int DS_PlaySound(int nSound, DWORD dwFlags)
  362. {
  363.   if(!m_bSoundPresent)
  364.     return 1;
  365.  
  366.   if(m_lpDS_Sounds[nSound])  // Make sure we have a valid sound buffer
  367.   {
  368.     DWORD dwStatus;
  369. //  g_DX_Result = m_lpDS_Sounds[nSound]->GetStatus(&dwStatus);
  370.     g_DX_Result = IDirectSoundBuffer_GetStatus(m_lpDS_Sounds[nSound], &dwStatus);
  371.     DS_CHECK_ERROR("Error - DS - GetStatus");
  372.  
  373.     if((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
  374.     {
  375. //    g_DX_Result = m_lpDS_Sounds[nSound]->Play(0, 0, dwFlags);    // Play the sound
  376.       g_DX_Result = IDirectSoundBuffer_Play(m_lpDS_Sounds[nSound], 0, 0, dwFlags);    // Play the sound
  377.       DS_CHECK_ERROR("Error - DS - Play");
  378.     }
  379.   }
  380.  
  381.   return 1;
  382. }
  383.  
  384. void DS_Finish()
  385. {
  386.   int i;
  387.  
  388.   if(g_lpDS != NULL)
  389.   {
  390.     for(i = 0; i < NSOUNDS; i ++)
  391.     {
  392.       if(m_lpDS_Sounds[i])
  393.       {       
  394. //      m_lpDS_Sounds[i]->Release();
  395.         IDirectSound_Release (m_lpDS_Sounds[i]);
  396.         m_lpDS_Sounds[i] = NULL;
  397.       }
  398.     }
  399.   }
  400. }
  401.  
  402. #elif defined ESD /* ifdef WIN32 */
  403.  
  404. /*
  405.  *  Enlightened Sound Daemon
  406.  */
  407. #include "esd.h"
  408.  
  409. char *host = "localhost";
  410. char *name = "Orbit";
  411. int samples[NSOUNDS];
  412. int esd_fd = -1;
  413.  
  414. int InitSound (void)
  415. {
  416.     int error = 0;
  417.     int i;
  418.  
  419.     /* Open sound daemon */
  420.     esd_fd = esd_open_sound(host);
  421.     /* Check for success */
  422.     if(esd_fd < 0)
  423.         return 0;
  424.  
  425.     for(i=0; i<NSOUNDS; i++)
  426.     {
  427.         samples[i] = esd_file_cache(esd_fd, name, sample_names[i]);
  428.         if(samples[i] < 0)
  429.         {
  430.             error = 1;
  431.             break;
  432.         }
  433.     }
  434.     /* Check for errors */
  435.     if(error == 0)
  436.         return 1;
  437.  
  438.     /* Error, close daemon */
  439.     esd_close(esd_fd);
  440.     return 0;
  441. }
  442.  
  443. int PlayAudio(enum sounds nSound)
  444. {
  445.     if(esd_fd < 0)
  446.         return 0;
  447.     /* Play precached sample */
  448.     esd_sample_play(esd_fd, samples[nSound]);
  449.     return 1;
  450. }
  451.  
  452. void FinishSound (void)
  453. {
  454.     int i;
  455.  
  456.     if(esd_fd < 0)
  457.         return;
  458.     /* Uncache samples */
  459.     for(i = 0; i < NSOUNDS; i++)
  460.     {
  461.         /*esd_sample_kill(esd_fd, samples[i]);*/
  462.         esd_sample_free(esd_fd, samples[i]);
  463.     }
  464.     /* Close daemon */
  465.     esd_close(esd_fd);
  466.     esd_fd = -1;
  467.     return;
  468. }
  469. #else /* if defined ESD */
  470.  
  471. /* Dummy functions for non existing functions */
  472. int InitSound(void)
  473. { return 0; }
  474. int PlayAudio(enum sounds nSound)
  475. { return 0; }
  476. void FinishSound(void)
  477. {}
  478.  
  479. #endif
  480.