home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / sound.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-05-14  |  6.3 KB  |  254 lines

  1. // sound.cpp: uses fmod on windows and sdl_mixer on unix (both had problems on the other platform)
  2.  
  3. #include "cube.h"
  4. #include "bot/bot.h"
  5.  
  6. //#ifndef WIN32    // NOTE: fmod not being supported for the moment as it does not allow stereo pan/vol updating during playback
  7. #define USE_MIXER
  8. //#endif
  9.  
  10. VARP(soundvol, 0, 150, 255);
  11. bool nosound = true;
  12.  
  13. #define MAXCHAN 32
  14. #define SOUNDFREQ 22050
  15.  
  16. struct soundloc { vec loc; bool inuse; } soundlocs[MAXCHAN];
  17.  
  18. #ifdef USE_MIXER
  19.     #include "SDL_mixer.h"
  20.     #define MAXVOL MIX_MAX_VOLUME
  21.     Mix_Music *mod = NULL;
  22.     void *stream = NULL;
  23. #else
  24.     #include "fmod.h"
  25.     #define MAXVOL 255
  26.     FMUSIC_MODULE *mod = NULL;
  27.     FSOUND_STREAM *stream = NULL;
  28. #endif
  29.  
  30. int musicvol = 125;
  31.  
  32. void setmusicvol(int vol)
  33. {
  34.     if(musicvol > 255 || musicvol < 0) return;
  35.     musicvol = vol;
  36.     if(nosound) return;
  37.     #ifdef USE_MIXER
  38.         if(mod) Mix_VolumeMusic((musicvol*MAXVOL)/255);
  39.     #else
  40.         if(mod) FMUSIC_SetMasterVolume(mod, musicvol);
  41.         else if(stream && musicchan>=0) FSOUND_SetVolume(musicchan, (musicvol*MAXVOL)/255);
  42.     #endif
  43. }
  44.  
  45. COMMANDN(musicvol, setmusicvol, ARG_1INT);
  46.  
  47. void stopsound()
  48. {
  49.     if(nosound) return;
  50.     if(mod)
  51.     {
  52.         #ifdef USE_MIXER
  53.             Mix_HaltMusic();
  54.             Mix_FreeMusic(mod);
  55.         #else
  56.             FMUSIC_FreeSong(mod);
  57.         #endif
  58.         mod = NULL;
  59.     }
  60.     if(stream)
  61.     {
  62.         #ifndef USE_MIXER
  63.             FSOUND_Stream_Close(stream);
  64.         #endif
  65.         stream = NULL;
  66.     }
  67. }
  68.  
  69. VAR(soundbufferlen, 128, 1024, 4096);
  70.  
  71. void initsound()
  72. {
  73.     memset(soundlocs, 0, sizeof(soundloc)*MAXCHAN);
  74.     #ifdef USE_MIXER
  75.         if(Mix_OpenAudio(SOUNDFREQ, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0)
  76.         {
  77.             conoutf("sound init failed (SDL_mixer): %s", (size_t)Mix_GetError());
  78.             return;
  79.         }
  80.         Mix_AllocateChannels(MAXCHAN);    
  81.     #else
  82.         if(FSOUND_GetVersion()<FMOD_VERSION) fatal("old FMOD dll");
  83.         if(!FSOUND_Init(SOUNDFREQ, MAXCHAN, FSOUND_INIT_GLOBALFOCUS))
  84.         {
  85.             conoutf("sound init failed (FMOD): %d", FSOUND_GetError());
  86.             return;
  87.         }
  88.     #endif
  89.     nosound = false;
  90. }
  91.  
  92. void music(char *name)
  93. {
  94.     if(nosound) return;
  95.     stopsound();
  96.     if(soundvol && musicvol)
  97.     {
  98.         s_sprintfd(sn)("packages/audio/songs/%s", name);
  99.         #ifdef USE_MIXER
  100.             if((mod = Mix_LoadMUS(path(sn))))
  101.             {
  102.                 Mix_PlayMusic(mod, -1);
  103.                 Mix_VolumeMusic((musicvol*MAXVOL)/255);
  104.             }
  105.         #else
  106.             if((mod = FMUSIC_LoadSong(path(sn))))
  107.             {
  108.                 FMUSIC_PlaySong(mod);
  109.                 FMUSIC_SetMasterVolume(mod, musicvol);
  110.             }
  111.             else if((stream = FSOUND_Stream_Open(path(sn), FSOUND_LOOP_NORMAL, 0, 0)))
  112.             {
  113.                 int chan = FSOUND_Stream_Play(FSOUND_FREE, stream);
  114.                 if(chan>=0) { FSOUND_SetVolume(chan, (musicvol*MAXVOL)/255); FSOUND_SetPaused(chan, false); }
  115.             }
  116.         #endif
  117.             else
  118.             {
  119.                 conoutf("could not play music: %s", sn);
  120.             }
  121.         
  122.     }
  123. }
  124.  
  125. COMMAND(music, ARG_1STR);
  126.  
  127.  
  128. #ifdef USE_MIXER
  129. vector<Mix_Chunk *> samples;
  130. #else
  131. vector<FSOUND_SAMPLE *> samples;
  132. #endif
  133.  
  134. cvector snames;
  135.  
  136. int registersound(char *name)
  137. {
  138.     loopv(snames) if(strcmp(snames[i], name)==0) return i;
  139.     snames.add(newstring(name));
  140.     samples.add(NULL);
  141.     return samples.length()-1;
  142. }
  143.  
  144. COMMAND(registersound, ARG_1EST);
  145.  
  146. void cleansound()
  147. {
  148.     if(nosound) return;
  149.     stopsound();
  150.     #ifdef USE_MIXER
  151.         Mix_CloseAudio();
  152.     #else
  153.         FSOUND_Close();
  154.     #endif
  155. }
  156.  
  157. VAR(stereo, 0, 1, 1);
  158.  
  159. void updatechanvol(int chan, vec *loc)
  160. {
  161.     int vol = soundvol, pan = 255/2;
  162.     if(loc)
  163.     {
  164.         vec v;
  165.         float dist = camera1->o.dist(*loc, v);
  166.         vol -= (int)(dist*3*soundvol/255); // simple mono distance attenuation
  167.         if(vol<0) vol = 0;
  168.         if(stereo && (v.x != 0 || v.y != 0))
  169.         {
  170.             float yaw = -atan2f(v.x, v.y) - camera1->yaw*RAD; // relative angle of sound along X-Y axis
  171.             pan = int(255.9f*(0.5f*sinf(yaw)+0.5f)); // range is from 0 (left) to 255 (right)
  172.         }
  173.     }
  174.     vol = (vol*MAXVOL)/255;
  175.     #ifdef USE_MIXER
  176.         Mix_Volume(chan, vol);
  177.         Mix_SetPanning(chan, 255-pan, pan);
  178.     #else
  179.         FSOUND_SetVolume(chan, vol);
  180.         FSOUND_SetPan(chan, pan);
  181.     #endif
  182. }  
  183.  
  184. void newsoundloc(int chan, vec *loc)
  185. {
  186.     ASSERT(chan>=0 && chan<MAXCHAN);
  187.     soundlocs[chan].loc = *loc;
  188.     soundlocs[chan].inuse = true;
  189. }
  190.  
  191. void updatevol()
  192. {
  193.     if(nosound) return;
  194.     loopi(MAXCHAN) if(soundlocs[i].inuse)
  195.     {
  196.         #ifdef USE_MIXER
  197.             if(Mix_Playing(i))
  198.         #else
  199.             if(FSOUND_IsPlaying(i))
  200.         #endif
  201.                 updatechanvol(i, &soundlocs[i].loc);
  202.             else soundlocs[i].inuse = false;
  203.     }
  204. }
  205.  
  206. void playsoundc(int n)
  207.     if(demoplayback) return;
  208.     addmsg(SV_SOUND, "i", n);
  209.     playsound(n);
  210. }
  211.  
  212. int soundsatonce = 0, lastsoundmillis = 0;
  213.  
  214. void playsound(int n, vec *loc)
  215. {
  216.     if(nosound) return;
  217.     if(!soundvol) return;
  218.     if(n==S_NULL) return;
  219.     if(m_botmode) BotManager.LetBotsHear(n, loc);
  220.     if(lastmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
  221.     lastsoundmillis = lastmillis;
  222.     if(soundsatonce>5) return;  // avoid bursts of sounds with heavy packetloss and in sp
  223.     if(n<0 || n>=samples.length())     { conoutf("unregistered sound: %d", n); return; }
  224.  
  225.     if(!samples[n])
  226.     {
  227.         s_sprintfd(buf)("packages/audio/sounds/%s.wav", snames[n]);
  228.  
  229.         #ifdef USE_MIXER
  230.             samples[n] = Mix_LoadWAV(path(buf));
  231.         #else
  232.             samples[n] = FSOUND_Sample_Load(n, path(buf), FSOUND_LOOP_OFF, 0, 0);
  233.         #endif
  234.  
  235.         if(!samples[n]) { conoutf("failed to load sample: %s", buf); return; }
  236.     }
  237.     
  238.     #ifdef USE_MIXER
  239.         int chan = Mix_PlayChannel(-1, samples[n], 0);
  240.     #else
  241.         int chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[n], NULL, true);
  242.     #endif
  243.     if(chan<0) return;
  244.     if(loc) newsoundloc(chan, loc);
  245.     updatechanvol(chan, loc);
  246.     #ifndef USE_MIXER
  247.         FSOUND_SetPaused(chan, false);
  248.     #endif
  249. }
  250.  
  251. void sound(int n) { playsound(n, NULL); }
  252. COMMAND(sound, ARG_1INT);
  253.