1 // Emacs style mode select	 -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // Copyright (C) 1993-1996 by id Software, Inc.
5 //
6 // This source is available for distribution and/or modification
7 // only under the terms of the DOOM Source Code License as
8 // published by id Software. All rights reserved.
9 //
10 // The source is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
13 // for more details.
14 //
15 // DESCRIPTION:
16 //		The not so system specific sound interface.
17 //
18 //-----------------------------------------------------------------------------
19 
20 
21 #ifndef __S_SOUND__
22 #define __S_SOUND__
23 
24 #include "doomtype.h"
25 #include "i_soundinternal.h"
26 #include "dobject.h"
27 
28 class AActor;
29 class FScanner;
30 
31 //
32 // SoundFX struct.
33 //
34 struct sfxinfo_t
35 {
36 	// Next field is for use by the system sound interface.
37 	// A non-null data means the sound has been loaded.
38 	SoundHandle	data;
39 
40 	FString		name;					// [RH] Sound name defined in SNDINFO
41 	int 		lumpnum;				// lump number of sfx
42 
43 	unsigned int next, index;			// [RH] For hashing
44 	float		Volume;
45 
46 	BYTE		PitchMask;
47 	SWORD		NearLimit;				// 0 means unlimited
48 	float		LimitRange;				// Range for sound limiting (squared for faster computations)
49 
50 	WORD		bRandomHeader:1;
51 	WORD		bPlayerReserve:1;
52 	WORD		bLoadRAW:1;
53 	WORD		bPlayerCompat:1;
54 	WORD		b16bit:1;
55 	WORD		bUsed:1;
56 	WORD		bSingular:1;
57 	WORD		bTentative:1;
58 	WORD		bPlayerSilent:1;		// This player sound is intentionally silent.
59 
60 	WORD		RawRate;				// Sample rate to use when bLoadRAW is true
61 
62 	int			LoopStart;				// -1 means no specific loop defined
63 
64 	unsigned int link;
65 	enum { NO_LINK = 0xffffffff };
66 
67 	FRolloffInfo	Rolloff;
68 	float		Attenuation;			// Multiplies the attenuation passed to S_Sound.
69 
70 	void		MarkUsed();				// Marks this sound as used.
71 };
72 
73 // Rolloff types
74 enum
75 {
76 	ROLLOFF_Doom,		// Linear rolloff with a logarithmic volume scale
77 	ROLLOFF_Linear,		// Linear rolloff with a linear volume scale
78 	ROLLOFF_Log,		// Logarithmic rolloff (standard hardware type)
79 	ROLLOFF_Custom		// Lookup volume from SNDCURVE
80 };
81 
82 int S_FindSound (const char *logicalname);
83 
84 // the complete set of sound effects
85 extern TArray<sfxinfo_t> S_sfx;
86 
87 // An index into the S_sfx[] array.
88 class FSoundID
89 {
90 public:
FSoundID()91 	FSoundID()
92 	{
93 		ID = 0;
94 	}
FSoundID(int id)95 	FSoundID(int id)
96 	{
97 		ID = id;
98 	}
FSoundID(const char * name)99 	FSoundID(const char *name)
100 	{
101 		ID = S_FindSound(name);
102 	}
FSoundID(const FString & name)103 	FSoundID(const FString &name)
104 	{
105 		ID = S_FindSound(name);
106 	}
FSoundID(const FSoundID & other)107 	FSoundID(const FSoundID &other)
108 	{
109 		ID = other.ID;
110 	}
111 	FSoundID &operator=(const FSoundID &other)
112 	{
113 		ID = other.ID;
114 		return *this;
115 	}
116 	FSoundID &operator=(const char *name)
117 	{
118 		ID = S_FindSound(name);
119 		return *this;
120 	}
121 	FSoundID &operator=(const FString &name)
122 	{
123 		ID = S_FindSound(name);
124 		return *this;
125 	}
126 	operator int() const
127 	{
128 		return ID;
129 	}
FString()130 	operator FString() const
131 	{
132 		return ID ? S_sfx[ID].name : "";
133 	}
134 	operator const char *() const
135 	{
136 		return ID ? S_sfx[ID].name.GetChars() : NULL;
137 	}
MarkUsed()138 	void MarkUsed() const
139 	{
140 		S_sfx[ID].MarkUsed();
141 	}
142 private:
143 	int ID;
144 protected:
145 	enum EDummy { NoInit };
FSoundID(EDummy)146 	FSoundID(EDummy) {}
147 };
148 
149 class FSoundIDNoInit : public FSoundID
150 {
151 public:
FSoundIDNoInit()152 	FSoundIDNoInit() : FSoundID(NoInit) {}
153 
154 	FSoundID &operator=(const FSoundID &other)
155 	{
156 		return FSoundID::operator=(other);
157 	}
158 	FSoundID &operator=(const char *name)
159 	{
160 		return FSoundID::operator=(name);
161 	}
162 	FSoundID &operator=(const FString &name)
163 	{
164 		return FSoundID::operator=(name);
165 	}
166 };
167 
168 FArchive &operator<<(FArchive &arc, FSoundID &sid);
169 
170 extern FRolloffInfo S_Rolloff;
171 extern BYTE *S_SoundCurve;
172 extern int S_SoundCurveSize;
173 
174 // Information about one playing sound.
175 struct sector_t;
176 struct FPolyObj;
177 struct FSoundChan : public FISoundChannel
178 {
179 	FSoundChan	*NextChan;	// Next channel in this list.
180 	FSoundChan **PrevChan;	// Previous channel in this list.
181 	FSoundID	SoundID;	// Sound ID of playing sound.
182 	FSoundID	OrgID;		// Sound ID of sound used to start this channel.
183 	float		Volume;
184 	int			ChanFlags;
185 	SWORD		Pitch;		// Pitch variation.
186 	BYTE		EntChannel;	// Actor's sound channel.
187 	SBYTE		Priority;
188 	SWORD		NearLimit;
189 	BYTE		SourceType;
190 	float		LimitRange;
191 	union
192 	{
193 		AActor			*Actor;		// Used for position and velocity.
194 		const sector_t	*Sector;	// Sector for area sounds.
195 		const FPolyObj	*Poly;		// Polyobject sound source.
196 		float			 Point[3];	// Sound is not attached to any source.
197 	};
198 };
199 extern FSoundChan *Channels;
200 
201 void S_ReturnChannel(FSoundChan *chan);
202 void S_EvictAllChannels();
203 
204 void S_StopChannel(FSoundChan *chan);
205 void S_LinkChannel(FSoundChan *chan, FSoundChan **head);
206 void S_UnlinkChannel(FSoundChan *chan);
207 
208 // Initializes sound stuff, including volume
209 // Sets channels, SFX and music volume,
210 //	allocates channel buffer, sets S_sfx lookup.
211 //
212 void S_Init ();
213 void S_InitData ();
214 void S_Shutdown ();
215 
216 // Per level startup code.
217 // Kills playing sounds at start of level and starts new music.
218 //
219 void S_Start ();
220 
221 // Called after a level is loaded. Ensures that most sounds are loaded.
222 void S_PrecacheLevel ();
223 
224 // Loads a sound, including any random sounds it might reference.
225 void S_CacheSound (sfxinfo_t *sfx);
226 
227 // Start sound for thing at <ent>
228 void S_Sound (int channel, FSoundID sfxid, float volume, float attenuation);
229 void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation);
230 void S_SoundMinMaxDist (AActor *ent, int channel, FSoundID sfxid, float volume, float mindist, float maxdist);
231 void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, float attenuation);
232 void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation);
233 void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, float volume, float attenuation);
234 
235 // sound channels
236 // channel 0 never willingly overrides
237 // other channels (1-7) always override a playing sound on that channel
238 //
239 // CHAN_AUTO searches down from channel 7 until it finds a channel not in use
240 // CHAN_WEAPON is for weapons
241 // CHAN_VOICE is for oof, sight, or other voice sounds
242 // CHAN_ITEM is for small things and item pickup
243 // CHAN_BODY is for generic body sounds
244 // CHAN_PICKUP can optionally be set as a local sound only for "compatibility"
245 
246 #define CHAN_AUTO				0
247 #define CHAN_WEAPON				1
248 #define CHAN_VOICE				2
249 #define CHAN_ITEM				3
250 #define CHAN_BODY				4
251 
252 // Channel alias for sector sounds. These define how listener height is
253 // used when calculating 3D sound volume.
254 #define CHAN_FLOOR				1	// Sound comes from the floor.
255 #define CHAN_CEILING			2	// Sound comes from the ceiling.
256 #define CHAN_FULLHEIGHT			3	// Sound comes entire height of the sector.
257 #define CHAN_INTERIOR			4	// Sound comes height between floor and ceiling.
258 
259 // modifier flags
260 #define CHAN_LISTENERZ			8
261 #define CHAN_MAYBE_LOCAL		16
262 #define CHAN_UI					32	// Do not record sound in savegames.
263 #define CHAN_NOPAUSE			64	// Do not pause this sound in menus.
264 #define CHAN_AREA				128	// Sound plays from all around. Only valid with sector sounds.
265 #define CHAN_LOOP				256
266 
267 #define CHAN_PICKUP				(CHAN_ITEM|CHAN_MAYBE_LOCAL)
268 
269 #define CHAN_IS3D				1	// internal: Sound is 3D.
270 #define CHAN_EVICTED			2	// internal: Sound was evicted.
271 #define CHAN_FORGETTABLE		4	// internal: Forget channel data when sound stops.
272 #define CHAN_JUSTSTARTED		512	// internal: Sound has not been updated yet.
273 #define CHAN_ABSTIME			1024// internal: Start time is absolute and does not depend on current time.
274 #define CHAN_VIRTUAL			2048// internal: Channel is currently virtual
275 
276 // sound attenuation values
277 #define ATTN_NONE				0.f	// full volume the entire level
278 #define ATTN_NORM				1.f
279 #define ATTN_IDLE				1.001f
280 #define ATTN_STATIC				3.f	// diminish very rapidly with distance
281 
282 int S_PickReplacement (int refid);
283 void S_CacheRandomSound (sfxinfo_t *sfx);
284 
285 // Checks if a copy of this sound is already playing.
286 bool S_CheckSingular (int sound_id);
287 
288 // Stops a sound emanating from one of an emitter's channels.
289 void S_StopSound (AActor *ent, int channel);
290 void S_StopSound (const sector_t *sec, int channel);
291 void S_StopSound (const FPolyObj *poly, int channel);
292 
293 // Stops an origin-less sound from playing from this channel.
294 void S_StopSound (int channel);
295 
296 // Stop sound for all channels
297 void S_StopAllChannels (void);
298 
299 // Is the sound playing on one of the emitter's channels?
300 bool S_GetSoundPlayingInfo (const AActor *actor, int sound_id);
301 bool S_GetSoundPlayingInfo (const sector_t *sector, int sound_id);
302 bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id);
303 
304 bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id);
305 
306 // Change a playing sound's volume
307 bool S_ChangeSoundVolume(AActor *actor, int channel, float volume);
308 
309 // Moves all sounds from one mobj to another
310 void S_RelinkSound (AActor *from, AActor *to);
311 
312 // Stores/retrieves playing channel information in an archive.
313 void S_SerializeSounds(FArchive &arc);
314 
315 // Start music using <music_name>
316 bool S_StartMusic (const char *music_name);
317 
318 // Start music using <music_name>, and set whether looping
319 bool S_ChangeMusic (const char *music_name, int order=0, bool looping=true, bool force=false);
320 
321 // Start playing a cd track as music
322 bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true);
323 
324 void S_RestartMusic ();
325 
326 void S_MIDIDeviceChanged();
327 
328 int S_GetMusic (char **name);
329 
330 // Stops the music for sure.
331 void S_StopMusic (bool force);
332 void S_UpdateMusic();
333 
334 // Stop and resume music, during game PAUSE.
335 void S_PauseSound (bool notmusic, bool notsfx);
336 void S_ResumeSound (bool notsfx);
337 void S_SetSoundPaused (int state);
338 
339 //
340 // Updates music & sounds
341 //
342 void S_UpdateSounds (AActor *listener);
343 
344 void S_RestoreEvictedChannels();
345 
346 // [RH] S_sfx "maintenance" routines
347 void S_ParseSndInfo (bool redefine);
348 void S_ParseReverbDef ();
349 void S_UnloadReverbDef ();
350 
351 void S_HashSounds ();
352 int S_FindSoundNoHash (const char *logicalname);
353 bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2);
354 bool S_AreSoundsEquivalent (AActor *actor, const char *name1, const char *name2);
355 int S_LookupPlayerSound (const char *playerclass, int gender, const char *logicalname);
356 int S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid);
357 int S_FindSkinnedSound (AActor *actor, FSoundID refid);
358 int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname);
359 int S_FindSoundByLump (int lump);
360 int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL);	// Add sound by lumpname
361 int S_AddSoundLump (const char *logicalname, int lump);	// Add sound by lump index
362 int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname);
363 int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false);
364 int S_AddPlayerSoundExisting (const char *playerclass, const int gender, int refid, int aliasto, bool fromskin=false);
365 void S_MarkPlayerSounds (const char *playerclass);
366 void S_ShrinkPlayerSoundLists ();
367 void S_UnloadSound (sfxinfo_t *sfx);
368 sfxinfo_t *S_LoadSound(sfxinfo_t *sfx);
369 unsigned int S_GetMSLength(FSoundID sound);
370 void S_ParseMusInfo();
371 bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time);
372 
373 // [RH] Prints sound debug info to the screen.
374 //		Modelled after Hexen's noise cheat.
375 void S_NoiseDebug ();
376 
377 extern ReverbContainer *Environments;
378 extern ReverbContainer *DefaultEnvironments[26];
379 
380 class FArchive;
381 FArchive &operator<< (FArchive &arc, ReverbContainer *&env);
382 
383 void S_SetEnvironment (const ReverbContainer *settings);
384 ReverbContainer *S_FindEnvironment (const char *name);
385 ReverbContainer *S_FindEnvironment (int id);
386 void S_AddEnvironment (ReverbContainer *settings);
387 
388 enum EMidiDevice
389 {
390 	MDEV_DEFAULT = -1,
391 	MDEV_MMAPI = 0,
392 	MDEV_OPL = 1,
393 	MDEV_SNDSYS = 2,
394 	MDEV_TIMIDITY = 3,
395 	MDEV_FLUIDSYNTH = 4,
396 	MDEV_GUS = 5,
397 	MDEV_WILDMIDI = 6,
398 };
399 
400 struct MidiDeviceSetting
401 {
402 	int device;
403 	FString args;
404 
MidiDeviceSettingMidiDeviceSetting405 	MidiDeviceSetting()
406 	{
407 		device = MDEV_DEFAULT;
408 	}
409 };
410 
411 typedef TMap<FName, FName> MusicAliasMap;
412 typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
413 
414 extern MusicAliasMap MusicAliases;
415 extern MidiDeviceMap MidiDevices;
416 
417 #endif
418