1 // hardcoded sounds, defined in sounds.cfg
2 
3 
4 enum
5 {    // To avoid a lot of work, possible bugs and allow backward compatibility for players own custom
6     // cfg files, it's best not to change the listed sound order, instead, just add to it.
7     S_JUMP = 0,
8     S_SOFTLAND, S_HARDLAND,
9     S_BULLETAIR1, S_BULLETAIR2, S_BULLETHIT, S_BULLETWATERHIT,
10     S_KNIFE,
11     S_PISTOL, S_RPISTOL,
12     S_CARBINE, S_RCARBINE,
13     S_SHOTGUN, S_RSHOTGUN,
14     S_SUBGUN, S_RSUBGUN,
15     S_SNIPER, S_RSNIPER,
16     S_ASSAULT, S_RASSAULT,
17     S_ITEMAMMO, S_ITEMHEALTH,
18     S_ITEMARMOUR, S_ITEMAKIMBO,
19     S_NOAMMO, S_AKIMBOOUT,
20     S_PAIN1, S_PAIN2, S_PAIN3, S_PAIN4, S_PAIN5, S_PAIN6,
21     S_DIE1, S_DIE2,
22     S_FEXPLODE,
23     S_SPLASH1, S_SPLASH2,
24     S_FLAGDROP, S_FLAGPICKUP, S_FLAGRETURN, S_FLAGSCORE,
25     S_GRENADEPULL, S_GRENADETHROW, S_GRENADEBOUNCE1, S_GRENADEBOUNCE2, S_RAKIMBO,
26     S_GUNCHANGE,
27     S_HITSOUND,
28     S_GIB, S_HEADSHOT,
29     S_CALLVOTE, S_VOTEPASS, S_VOTEFAIL,
30     S_FOOTSTEPS, S_FOOTSTEPSCROUCH, S_WATERFOOTSTEPS, S_WATERFOOTSTEPSCROUCH,
31     S_CROUCH, S_UNCROUCH,
32     S_MENUSELECT, S_MENUENTER,
33     S_UNDERWATER,
34     S_TINNITUS,
35 // begin: voicecoms
36     S_AFFIRMATIVE,
37     S_ALLRIGHTSIR,
38     S_COMEONMOVE,
39     S_COMINGINWITHTHEFLAG,
40     S_COVERME,
41     S_DEFENDTHEFLAG,
42     S_ENEMYDOWN,
43     S_GOGETEMBOYS,
44     S_GOODJOBTEAM,
45     S_IGOTONE,
46     S_IMADECONTACT,
47     S_IMATTACKING,
48     S_IMONDEFENSE,
49     S_IMONYOURTEAMMAN,
50     S_NEGATIVE,
51     S_NOCANDO,
52     S_RECOVERTHEFLAG,
53     S_SORRY,
54     S_SPREADOUT,
55     S_STAYHERE,
56     S_STAYTOGETHER,
57     S_THERESNOWAYSIR,
58     S_WEDIDIT,
59     S_YES,
60     S_ONTHEMOVE1,
61     S_ONTHEMOVE2,
62     S_GOTURBACK,
63     S_GOTUCOVERED,
64     S_INPOSITION1,
65     S_INPOSITION2,
66     S_REPORTIN,
67     S_NICESHOT, // begin: public
68     S_THANKS1,
69     S_THANKS2,
70     S_AWESOME1,
71     S_AWESOME2,
72     S_ITEMHELMET, // begin: Sounds for AssaultCube v1.1.0.4 onwards
73     S_HEARTBEAT,
74     S_KTFSCORE,
75     S_NULL
76 };
77 
78 // hardcoded music
79 
80 enum
81 {
82     M_FLAGGRAB = 0,
83     M_LASTMINUTE1,
84     M_LASTMINUTE2
85 };
86 
87 // sound priorities
88 
89 enum
90 {
91     SP_LOW = 0,
92     SP_NORMAL,
93     SP_HIGH,
94     SP_HIGHEST
95 };
96 
97 #ifndef STANDALONE
98 
99 // owner of an OpenAL source, used as callback interface
100 
101 class sourceowner
102 {
103 public:
~sourceowner()104     virtual ~sourceowner() {}
105     virtual void onsourcereassign(class source *s) = 0;
106 };
107 
108 // represents an OpenAL source, an audio emitter in the 3D world
109 
110 class source
111 {
112 public:
113     ALuint id;
114 
115     sourceowner *owner;
116     bool locked, valid;
117     int priority;
118 
119     source();
120     ~source();
121 
122     void lock();
123     void unlock();
124     void reset();
125     void init(sourceowner *o);
126     void onreassign();
127 
128     bool generate();
129     bool delete_();
130     bool buffer(ALuint buf_id);
131     bool looping(bool enable);
132     bool queuebuffers(ALsizei n, const ALuint *buffer_ids);
133     bool unqueueallbuffers();
134     bool gain(float g);
135     bool pitch(float p);
136     bool position(const vec &pos);
137     bool position(float x, float y, float z);
138     bool velocity(float x, float y, float z);
139     vec position();
140     bool sourcerelative(bool enable);
141     int state();
142     bool secoffset(float secs);
143     float secoffset();
144     bool playing();
145     bool play();
146     bool stop();
147     bool rewind();
148 
149     void printposition();
150 };
151 
152 
153 // represents an OpenAL sound buffer
154 
155 class sbuffer
156 {
157 public:
158     ALuint id;
159     const char *name;
160 
161     sbuffer();
162     ~sbuffer();
163 
164     bool load(bool trydl = false);
165     void unload();
166 };
167 
168 // buffer storage
169 
170 class bufferhashtable : public hashtable<char *, sbuffer>
171 {
172 public:
173     virtual ~bufferhashtable();
174     virtual sbuffer *find(char *name);
175 };
176 
177 // manages available sources, abstracts audio channels
178 // is a singleton
179 
180 class sourcescheduler
181 {
182     int numsoundchannels;
183     static sourcescheduler *inst;
184     vector<source *> sources;
185 
186 public:
187     sourcescheduler();
188     static sourcescheduler &instance(); // singleton access
189 
190     void init(int numsoundchannels);
191     void reset();
192     source *newsource(int priority, const vec &o);
193     void releasesource(source *src);
194 };
195 
196 // audio streaming
197 
198 class oggstream : sourceowner
199 {
200 public:
201     string name;
202     bool valid;
203 
204     // file stream
205     OggVorbis_File oggfile;
206     bool isopen;
207     vorbis_info *info;
208     double totalseconds;
209     static const int BUFSIZE = 1024 * 512; // 512kb buffer
210 
211     // OpenAL resources
212     ALuint bufferids[2];
213     source *src;
214     ALenum format;
215 
216     // settings
217     float volume, gain;
218     int startmillis, endmillis, startfademillis, endfademillis;
219     bool looping;
220 
221     oggstream();
222     ~oggstream();
223 
224     void reset();
225     bool open(const char *f);
226     void onsourcereassign(source *s);
227     bool stream(ALuint bufid);
228     bool update();
229     bool playing();
230     void updategain();
231     void setgain(float g);
232     void setvolume(float v);
233     void fadein(int startmillis, int fademillis);
234     void fadeout(int endmillis, int fademillis);
235     bool playback(bool looping = false);
236     void seek(double offset);
237 };
238 
239 
240 struct soundconfig
241 {
242     sbuffer *buf; // sound data
243     int vol; // volume
244     int uses, maxuses; // track uses
245     bool loop;
246     bool muted;
247     int audibleradius;
248 
249     enum distancemodel
250     {
251         DM_DEFAULT = 0, // use openal distance model
252         DM_LINEAR // custom linear model (used in conjunction with audibleradius)
253     };
254 
255     distancemodel model;
256 
257     soundconfig(sbuffer *b, int vol, int maxuses, bool loop, int audibleradius);
258     void onattach();
259     void ondetach();
260 };
261 
262 
263 class worldobjreference
264 {
265 public:
266 
267     enum worldobjtype { WR_CAMERA, WR_PHYSENT, WR_ENTITY, WR_STATICPOS };
268     int type;
269 
worldobjreference(int t)270     worldobjreference(int t) : type(t) {}
~worldobjreference()271     virtual ~worldobjreference() {}
272     virtual worldobjreference *clone() const = 0;
273     virtual const vec &currentposition() const = 0;
274     virtual bool nodistance() = 0;
275     virtual bool operator==(const worldobjreference &other) = 0;
276     virtual bool operator!=(const worldobjreference &other) { return !(*this==other); }
attach()277     virtual void attach() {}
detach()278     virtual void detach() {}
279 };
280 
281 
282 class camerareference : public worldobjreference
283 {
284 public:
285     camerareference();
286 
287     worldobjreference *clone() const;
288     const vec &currentposition() const;
289     bool nodistance();
290     bool operator==(const worldobjreference &other);
291 };
292 
293 
294 class physentreference : public worldobjreference
295 {
296 public:
297     class physent *phys;
298 
299     physentreference(physent *ref);
300     worldobjreference *clone() const;
301     const vec &currentposition() const;
302     bool nodistance();
303     bool operator==(const worldobjreference &other);
304 };
305 
306 
307 struct entityreference : public worldobjreference
308 {
309 public:
310     struct entity *ent;
311 
312     entityreference(entity *ref);
313     worldobjreference *clone() const;
314     const vec &currentposition() const;
315     bool nodistance();
316     bool operator==(const worldobjreference &other);
317 };
318 
319 
320 struct staticreference : public worldobjreference
321 {
322 public:
323     vec pos;
324 
325     staticreference(const vec &ref);
326     worldobjreference *clone() const;
327     const vec &currentposition() const;
328     bool nodistance();
329     bool operator==(const worldobjreference &other);
330 };
331 
332 
333 class location : sourceowner
334 {
335 public:
336     soundconfig *cfg;
337     source *src;
338     worldobjreference *ref;
339 
340     bool stale;
341     int playmillis;
342 
343     location(int sound, const worldobjreference &r, int priority = SP_NORMAL);
344     ~location();
345     void attachworldobjreference(const worldobjreference &r);
346     void evaluateworldobjref();
347     void onsourcereassign(source *s);
348     void updatepos();
349     void update();
350     void play(bool loop = false);
351     void pitch(float p);
352     bool setvolume(float v);
353     void offset(float secs);
354     float offset();
355     void drop();
356 };
357 
358 
359 struct locvector : vector<location *>
360 {
~locvectorlocvector361     virtual ~locvector() {}
362 
363     location *find(int sound, worldobjreference *ref/* = NULL*/, const vector<soundconfig> &soundcollection /* = gamesounds*/);
364     void delete_(int i);
365     void replaceworldobjreference(const worldobjreference &oldr, const worldobjreference &newr);
366     void updatelocations();
367     void forcepitch(float pitch);
368     void deleteworldobjsounds();
369 };
370 
371 
372 // audio interface to the engine
373 
374 class audiomanager
375 {
376     bool nosound;
377     float currentpitch;
378     vector<char *> musics;
379     ALCdevice *device;
380     ALCcontext *context;
381 
382     bufferhashtable bufferpool;
383     oggstream *gamemusic;
384 
385 public:
386 
387     locvector locations;
388 
389     audiomanager();
390 
391     // init & setup
392     void initsound();
393     void preloadmapsound(entity &e, bool trydl = false);
394     void preloadmapsounds(bool trydl = false);
395     void applymapsoundchanges();
396 
397     // configuration
398     void setchannels(int num);
399     void setlistenervol(int vol);
400     int addsound(char *name, int vol, int maxuses, bool loop, vector<soundconfig> &sounds, bool load, int audibleradius);
401     void registermusic(char *name);
402     void mutesound(int n, int off);
403     void unmuteallsounds();
404     int soundmuted(int n);
405 
406     // cleanup
407     void soundcleanup();
408     void clearworldsounds(bool fullclean = true);
409     void mapsoundreset();
410     void stopsound();
411 
412     // music handling
413     void music(char *name, int millis, char *cmd);
414     void musicpreload(int id);
415     void musicsuggest(int id, int millis, bool rndofs);
416     void musicfadeout(int id);
417     void setmusicvol(int musicvol);
418 
419     // sound handling
420     location *_playsound(int n, const worldobjreference &r, int priority, float offset = 0.0f, bool loop = false);
421     void playsound(int n, int priority = SP_NORMAL);
422     void playsound(int n, class physent *p, int priority = SP_NORMAL);
423     void playsound(int n, struct entity *e, int priority = SP_NORMAL);
424     void playsound(int n, const vec *v, int priority = SP_NORMAL);
425     void playsoundname(char *s, const vec *loc, int vol);
426     void playsoundc(int n, physent *p = NULL, int priority = SP_NORMAL);
427     void sound(int n);
428     int findsound(char *name, int vol, vector<soundconfig> &sounds);
429     void detachsounds(class playerent *owner);
430 
431     // update
432     void updateplayerfootsteps(class playerent *p);
433     location *updateloopsound(int sound, bool active, float vol = 1.0f);
434     void updateaudio();
435 
436     // misc
437     void writesoundconfig(stream *f);
438 };
439 
440 void alclearerr();
441 bool alerr(bool msg = true, int line = 0);
442 #define ALERR alerr(true, __LINE__)
443 
444 extern vector<soundconfig> gamesounds, mapsounds;
445 extern ov_callbacks oggcallbacks;
446 extern int soundvol;
447 extern int audiodebug;
448 
449 extern audiomanager audiomgr;
450 
451 #endif //#ifndef STANDALONE
452