no message
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1340 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
@@ -10,7 +10,7 @@ char *entnames[] =
|
||||
"clips", "ammobox","grenades",
|
||||
"health", "armour", "akimbo",
|
||||
"mapmodel", "trigger",
|
||||
"ladder", "ctf-flag", "?", "?", "?",
|
||||
"ladder", "ctf-flag", "sound", "?", "?",
|
||||
};
|
||||
char *entmdlnames[] =
|
||||
{
|
||||
|
||||
+3
-1
@@ -9,6 +9,7 @@ enum // static entity types
|
||||
CARROT, // attr1 = tag, attr2 = type
|
||||
LADDER,
|
||||
CTF_FLAG, // attr1 = angle, attr2 = red/blue
|
||||
SOUND,
|
||||
MAXENTTYPES
|
||||
};
|
||||
|
||||
@@ -24,7 +25,8 @@ struct persistent_entity // map entity
|
||||
|
||||
struct entity : public persistent_entity
|
||||
{
|
||||
bool spawned; // the only dynamic state of a map entity
|
||||
bool spawned; // fixme,ah//the only dynamic state of a map entity
|
||||
bool visible;
|
||||
};
|
||||
|
||||
struct itemstat { int add, start, max, sound; };
|
||||
|
||||
@@ -455,6 +455,8 @@ int main(int argc, char **argv)
|
||||
fps = (1000.0f/elapsed+fps*10)/11;
|
||||
frames++;
|
||||
|
||||
checkmapsounds();
|
||||
|
||||
computeraytable(camera1->o.x, camera1->o.y);
|
||||
if(frames>4) SDL_GL_SwapBuffers();
|
||||
extern void updatevol(); updatevol();
|
||||
|
||||
+3
-2
@@ -294,11 +294,12 @@ extern void fixcamerarange(physent *cam = camera1);
|
||||
extern float floor(short x, short y);
|
||||
|
||||
// sound
|
||||
extern void playsound(int n, vec *loc = 0);
|
||||
extern void playsound(int n, const vec *loc = NULL, entity *ent = NULL);
|
||||
extern void playsoundc(int n);
|
||||
extern void initsound();
|
||||
extern void cleansound();
|
||||
extern void music(char *name);
|
||||
extern void checkmapsounds();
|
||||
extern void music(char *name, char *cmd);
|
||||
|
||||
// rendermodel
|
||||
extern void rendermodel(char *mdl, int anim, int tex, float rad, const vec &o, float yaw, float pitch, float speed = 0, int basetime = 0, playerent *d = NULL, char *vwepmdl = NULL, float scale = 1.0f);
|
||||
|
||||
+201
-57
@@ -1,7 +1,6 @@
|
||||
// sound.cpp: uses fmod on windows and sdl_mixer on unix (both had problems on the other platform)
|
||||
|
||||
#include "cube.h"
|
||||
#include "bot/bot.h"
|
||||
|
||||
//#ifndef WIN32 // NOTE: fmod not being supported for the moment as it does not allow stereo pan/vol updating during playback
|
||||
#define USE_MIXER
|
||||
@@ -13,12 +12,13 @@ bool nosound = true;
|
||||
#include "SDL_mixer.h"
|
||||
#define MAXVOL MIX_MAX_VOLUME
|
||||
Mix_Music *mod = NULL;
|
||||
void *stream = NULL;
|
||||
void *stream = NULL; // TODO
|
||||
#else
|
||||
#include "fmod.h"
|
||||
#define MAXVOL 255
|
||||
FMUSIC_MODULE *mod = NULL;
|
||||
FSOUND_STREAM *stream = NULL;
|
||||
|
||||
#define MAXVOL 255
|
||||
int musicchan;
|
||||
#endif
|
||||
|
||||
@@ -31,11 +31,25 @@ struct sample
|
||||
FSOUND_SAMPLE *sound;
|
||||
#endif
|
||||
|
||||
sample(const char *name) : name(newstring(name)), sound(NULL) {}
|
||||
sample() : name(NULL) {}
|
||||
~sample() { DELETEA(name); }
|
||||
};
|
||||
|
||||
struct soundloc { vec loc; bool inuse; };
|
||||
struct soundslot
|
||||
{
|
||||
sample *s;
|
||||
int vol;
|
||||
int uses, maxuses;
|
||||
};
|
||||
|
||||
struct soundloc
|
||||
{
|
||||
vec loc;
|
||||
bool inuse;
|
||||
soundslot *slot;
|
||||
entity *ent;
|
||||
};
|
||||
|
||||
vector<soundloc> soundlocs;
|
||||
|
||||
void setmusicvol(int musicvol)
|
||||
@@ -49,12 +63,15 @@ void setmusicvol(int musicvol)
|
||||
#endif
|
||||
}
|
||||
|
||||
VARP(soundvol, 0, 150, 255);
|
||||
VARP(soundvol, 0, 255, 255);
|
||||
VARFP(musicvol, 0, 128, 255, setmusicvol(musicvol));
|
||||
|
||||
char *musicdonecmd = NULL;
|
||||
|
||||
void stopsound()
|
||||
{
|
||||
if(nosound) return;
|
||||
DELETEA(musicdonecmd);
|
||||
if(mod)
|
||||
{
|
||||
#ifdef USE_MIXER
|
||||
@@ -86,7 +103,7 @@ void initsound()
|
||||
conoutf("sound init failed (SDL_mixer): %s", (size_t)Mix_GetError());
|
||||
return;
|
||||
}
|
||||
Mix_AllocateChannels(soundchans);
|
||||
Mix_AllocateChannels(soundchans);
|
||||
#else
|
||||
if(FSOUND_GetVersion()<FMOD_VERSION) fatal("old FMOD dll");
|
||||
if(!FSOUND_Init(soundfreq, soundchans, FSOUND_INIT_GLOBALFOCUS))
|
||||
@@ -98,18 +115,36 @@ void initsound()
|
||||
nosound = false;
|
||||
}
|
||||
|
||||
void music(char *name)
|
||||
void musicdone()
|
||||
{
|
||||
if(!musicdonecmd) return;
|
||||
#ifdef USE_MIXER
|
||||
if(mod) Mix_FreeMusic(mod);
|
||||
#else
|
||||
if(mod) FMUSIC_FreeSong(mod);
|
||||
if(stream) FSOUND_Stream_Close(stream);
|
||||
#endif
|
||||
mod = NULL;
|
||||
stream = NULL;
|
||||
char *cmd = musicdonecmd;
|
||||
musicdonecmd = NULL;
|
||||
execute(cmd);
|
||||
delete[] cmd;
|
||||
}
|
||||
|
||||
void music(char *name, char *cmd)
|
||||
{
|
||||
if(nosound) return;
|
||||
stopsound();
|
||||
if(soundvol && musicvol)
|
||||
if(soundvol && musicvol && *name)
|
||||
{
|
||||
if(cmd[0]) musicdonecmd = newstring(cmd);
|
||||
s_sprintfd(sn)("packages/audio/songs/%s", name);
|
||||
const char *file = findfile(path(sn), "rb");
|
||||
#ifdef USE_MIXER
|
||||
if((mod = Mix_LoadMUS(file)))
|
||||
{
|
||||
Mix_PlayMusic(mod, -1);
|
||||
Mix_PlayMusic(mod, cmd[0] ? 0 : -1);
|
||||
Mix_VolumeMusic((musicvol*MAXVOL)/255);
|
||||
}
|
||||
#else
|
||||
@@ -117,38 +152,66 @@ void music(char *name)
|
||||
{
|
||||
FMUSIC_PlaySong(mod);
|
||||
FMUSIC_SetMasterVolume(mod, musicvol);
|
||||
FMUSIC_SetLooping(mod, cmd[0] ? FALSE : TRUE);
|
||||
}
|
||||
else if((stream = FSOUND_Stream_Open(file, FSOUND_LOOP_NORMAL, 0, 0)))
|
||||
else if((stream = FSOUND_Stream_Open(file, cmd[0] ? FSOUND_LOOP_OFF : FSOUND_LOOP_NORMAL, 0, 0)))
|
||||
{
|
||||
musicchan = FSOUND_Stream_Play(FSOUND_FREE, stream);
|
||||
if(musicchan>=0) { FSOUND_SetVolume(musicchan, (musicvol*MAXVOL)/255); FSOUND_SetPaused(musicchan, false); }
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
else
|
||||
{
|
||||
conoutf("could not play music: %s", sn);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND(music, ARG_1STR);
|
||||
COMMAND(music, ARG_2STR);
|
||||
|
||||
vector<sample *> samples;
|
||||
hashtable<char *, sample> samples;
|
||||
vector<soundslot> gamesounds, mapsounds;
|
||||
|
||||
int registersound(char *name)
|
||||
int findsound(char *name, int vol, vector<soundslot> &sounds)
|
||||
{
|
||||
loopv(samples) if(!strcmp(samples[i]->name, name)) return i;
|
||||
samples.add(new sample(name));
|
||||
return samples.length()-1;
|
||||
loopv(sounds)
|
||||
{
|
||||
if(!strcmp(sounds[i].s->name, name) && (!vol || sounds[i].vol==vol)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
COMMAND(registersound, ARG_1EST);
|
||||
int addsound(char *name, int vol, int maxuses, vector<soundslot> &sounds)
|
||||
{
|
||||
sample *s = samples.access(name);
|
||||
if(!s)
|
||||
{
|
||||
char *n = newstring(name);
|
||||
s = &samples[n];
|
||||
s->name = n;
|
||||
s->sound = NULL;
|
||||
}
|
||||
soundslot &slot = sounds.add();
|
||||
slot.s = s;
|
||||
slot.vol = vol ? vol : 100;
|
||||
slot.uses = 0;
|
||||
slot.maxuses = maxuses;
|
||||
return sounds.length()-1;
|
||||
}
|
||||
|
||||
void registersound(char *name, char *vol) { addsound(name, atoi(vol), 0, gamesounds); }
|
||||
COMMAND(registersound, ARG_2STR);
|
||||
|
||||
void mapsound(char *name, char *vol, char *maxuses) { addsound(name, atoi(vol), atoi(maxuses) < 0 ? 0 : max(1, *maxuses), mapsounds); }
|
||||
COMMAND(mapsound, ARG_3STR);
|
||||
|
||||
void cleansound()
|
||||
{
|
||||
if(nosound) return;
|
||||
stopsound();
|
||||
gamesounds.setsizenodelete(0);
|
||||
mapsounds.setsizenodelete(0);
|
||||
samples.clear();
|
||||
#ifdef USE_MIXER
|
||||
Mix_CloseAudio();
|
||||
#else
|
||||
@@ -156,24 +219,66 @@ void cleansound()
|
||||
#endif
|
||||
}
|
||||
|
||||
void clearmapsounds()
|
||||
{
|
||||
loopv(soundlocs) if(soundlocs[i].inuse && soundlocs[i].ent)
|
||||
{
|
||||
#ifdef USE_MIXER
|
||||
if(Mix_Playing(i)) Mix_HaltChannel(i);
|
||||
#else
|
||||
if(FSOUND_IsPlaying(i)) FSOUND_StopSound();
|
||||
#endif
|
||||
soundlocs[i].inuse = false;
|
||||
soundlocs[i].ent->visible = false;
|
||||
soundlocs[i].slot->uses--;
|
||||
}
|
||||
mapsounds.setsizenodelete(0);
|
||||
}
|
||||
|
||||
void checkmapsounds()
|
||||
{
|
||||
//const vector<entity *> &ents = et->getents();
|
||||
loopv(ents)
|
||||
{
|
||||
entity &e = ents[i];
|
||||
vec o(e.x, e.y, e.z);
|
||||
if(e.type!=SOUND || e.visible || camera1->o.dist(o)>=e.attr2) continue;
|
||||
playsound(e.attr1, NULL, &e);
|
||||
}
|
||||
}
|
||||
|
||||
VAR(stereo, 0, 1, 1);
|
||||
|
||||
void updatechanvol(int chan, vec *loc)
|
||||
void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL)
|
||||
{
|
||||
int vol = soundvol, pan = 255/2;
|
||||
if(loc)
|
||||
{
|
||||
vec v;
|
||||
float dist = camera1->o.dist(*loc, v);
|
||||
vol -= (int)(dist*3*soundvol/255); // simple mono distance attenuation
|
||||
if(vol<0) vol = 0;
|
||||
if(stereo && (v.x != 0 || v.y != 0))
|
||||
if(ent)
|
||||
{
|
||||
int rad = ent->attr2;
|
||||
if(ent->attr3)
|
||||
{
|
||||
rad -= ent->attr3;
|
||||
dist -= ent->attr3;
|
||||
}
|
||||
vol -= (int)(min(max(dist/rad, 0), 1)*soundvol);
|
||||
}
|
||||
else
|
||||
{
|
||||
vol -= (int)(dist*3/4*soundvol/255); // simple mono distance attenuation
|
||||
if(vol<0) vol = 0;
|
||||
}
|
||||
if(stereo && (v.x != 0 || v.y != 0) && dist>0)
|
||||
{
|
||||
float yaw = -atan2f(v.x, v.y) - camera1->yaw*RAD; // relative angle of sound along X-Y axis
|
||||
pan = int(255.9f*(0.5f*sinf(yaw)+0.5f)); // range is from 0 (left) to 255 (right)
|
||||
}
|
||||
}
|
||||
vol = (vol*MAXVOL)/255;
|
||||
vol = (vol*MAXVOL*svol)/255/255;
|
||||
vol = min(vol, MAXVOL);
|
||||
#ifdef USE_MIXER
|
||||
Mix_Volume(chan, vol);
|
||||
Mix_SetPanning(chan, 255-pan, pan);
|
||||
@@ -183,11 +288,13 @@ void updatechanvol(int chan, vec *loc)
|
||||
#endif
|
||||
}
|
||||
|
||||
void newsoundloc(int chan, vec *loc)
|
||||
void newsoundloc(int chan, const vec *loc, soundslot *slot, entity *ent = NULL)
|
||||
{
|
||||
while(chan >= soundlocs.length()) soundlocs.add().inuse = false;
|
||||
soundlocs[chan].loc = *loc;
|
||||
soundlocs[chan].inuse = true;
|
||||
soundlocs[chan].slot = slot;
|
||||
soundlocs[chan].ent = ent;
|
||||
}
|
||||
|
||||
void updatevol()
|
||||
@@ -200,63 +307,100 @@ void updatevol()
|
||||
#else
|
||||
if(FSOUND_IsPlaying(i))
|
||||
#endif
|
||||
updatechanvol(i, &soundlocs[i].loc);
|
||||
else soundlocs[i].inuse = false;
|
||||
updatechanvol(i, soundlocs[i].slot->vol, &soundlocs[i].loc, soundlocs[i].ent);
|
||||
else
|
||||
{
|
||||
soundlocs[i].inuse = false;
|
||||
if(soundlocs[i].ent)
|
||||
{
|
||||
soundlocs[i].ent->visible = false;
|
||||
soundlocs[i].slot->uses--;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef USE_MIXER
|
||||
if(mod && FMUSIC_IsFinished(mod)) musicdone();
|
||||
else if(stream && !FSOUND_IsPlaying(musicchan)) musicdone();
|
||||
#else
|
||||
if(mod && !Mix_PlayingMusic()) musicdone();
|
||||
#endif
|
||||
}
|
||||
|
||||
void playsoundc(int n)
|
||||
{
|
||||
addmsg(SV_SOUND, "i", n);
|
||||
playsound(n);
|
||||
}
|
||||
|
||||
void playsound(int n, vec *loc)
|
||||
void playsound(int n, const vec *loc, entity *ent)
|
||||
{
|
||||
if(nosound) return;
|
||||
if(!soundvol) return;
|
||||
if(n==S_NULL) return;
|
||||
if(m_botmode) BotManager.LetBotsHear(n, loc);
|
||||
|
||||
static int soundsatonce = 0, lastsoundmillis = 0;
|
||||
if(lastmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
|
||||
lastsoundmillis = lastmillis;
|
||||
if(soundsatonce>5) return; // avoid bursts of sounds with heavy packetloss and in sp
|
||||
|
||||
if(!samples.inrange(n)) { conoutf("unregistered sound: %d", n); return; }
|
||||
|
||||
sample &s = *samples[n];
|
||||
if(!s.sound)
|
||||
if(!ent)
|
||||
{
|
||||
s_sprintfd(buf)("packages/audio/sounds/%s", s.name);
|
||||
static int soundsatonce = 0, lastsoundmillis = 0;
|
||||
if(totalmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
|
||||
lastsoundmillis = totalmillis;
|
||||
if(soundsatonce>5) return; // avoid bursts of sounds with heavy packetloss and in sp
|
||||
}
|
||||
|
||||
vector<soundslot> &sounds = ent ? mapsounds : gamesounds;
|
||||
if(!sounds.inrange(n)) { conoutf("unregistered sound: %d", n); return; }
|
||||
soundslot &slot = sounds[n];
|
||||
if(ent && slot.maxuses && slot.uses>=slot.maxuses) return;
|
||||
|
||||
if(!slot.s->sound)
|
||||
{
|
||||
s_sprintfd(buf)("packages/audio/sounds/%s", slot.s->name);
|
||||
|
||||
loopi(2)
|
||||
{
|
||||
if(i) s_strcat(buf, ".wav");
|
||||
const char *file = findfile(path(buf), "rb");
|
||||
#ifdef USE_MIXER
|
||||
s.sound = Mix_LoadWAV(file);
|
||||
slot.s->sound = Mix_LoadWAV(file);
|
||||
#else
|
||||
s.sound = FSOUND_Sample_Load(n, file, FSOUND_LOOP_OFF, 0, 0);
|
||||
slot.s->sound = FSOUND_Sample_Load(ent ? n+gamesounds.length() : n, file, FSOUND_LOOP_OFF, 0, 0);
|
||||
#endif
|
||||
if(s.sound) break;
|
||||
if(slot.s->sound) break;
|
||||
}
|
||||
|
||||
if(!s.sound) { conoutf("failed to load sample: %s", buf); return; }
|
||||
if(!slot.s->sound) { conoutf("failed to load sample: %s", buf); return; }
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_MIXER
|
||||
int chan = Mix_PlayChannel(-1, s.sound, 0);
|
||||
int chan = Mix_PlayChannel(-1, slot.s->sound, 0);
|
||||
#else
|
||||
int chan = FSOUND_PlaySoundEx(FSOUND_FREE, s.sound, NULL, true);
|
||||
int chan = FSOUND_PlaySoundEx(FSOUND_FREE, slot.s->sound, NULL, true);
|
||||
#endif
|
||||
if(chan<0) return;
|
||||
if(loc) newsoundloc(chan, loc);
|
||||
updatechanvol(chan, loc);
|
||||
|
||||
vec eloc; //fixme,ah
|
||||
if(ent)
|
||||
{
|
||||
eloc.x = ent->x;
|
||||
eloc.y = ent->y;
|
||||
eloc.z = ent->z;
|
||||
loc = &eloc;
|
||||
//loc = &ent->o;
|
||||
ent->visible = true;
|
||||
slot.uses++;
|
||||
}
|
||||
if(loc) newsoundloc(chan, loc, &slot, ent);
|
||||
updatechanvol(chan, slot.vol, loc, ent);
|
||||
#ifndef USE_MIXER
|
||||
FSOUND_SetPaused(chan, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sound(int n) { playsound(n, NULL); }
|
||||
void playsoundname(char *s, const vec *loc, int vol)
|
||||
{
|
||||
if(!vol) vol = 100;
|
||||
int id = findsound(s, vol, gamesounds);
|
||||
if(id < 0) id = addsound(s, vol, 0, gamesounds);
|
||||
playsound(id, loc);
|
||||
}
|
||||
|
||||
void sound(int *n) { playsound(*n); }
|
||||
COMMAND(sound, ARG_1INT);
|
||||
|
||||
void playsoundc(int n)
|
||||
{
|
||||
addmsg(SV_SOUND, "i", n);
|
||||
playsound(n);
|
||||
}
|
||||
@@ -20,6 +20,7 @@ enum
|
||||
S_GRENADEPULL, S_GRENADETHROW,
|
||||
S_RAKIMBO, S_GUNCHANGE, S_GIB, S_HEADSHOT,
|
||||
S_CALLVOTE, S_VOTEPASS, S_VOTEFAIL,
|
||||
S_FOOTSTEPS,
|
||||
S_NULL
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user