1 #ifndef __SOUNDMANAGER_H
2 #define __SOUNDMANAGER_H
3 
4 /*
5 
6 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
7 	and the "Aleph One" developers.
8 
9 	This program is free software; you can redistribute it and/or modify
10 	it under the terms of the GNU General Public License as published by
11 	the Free Software Foundation; either version 3 of the License, or
12 	(at your option) any later version.
13 
14 	This program is distributed in the hope that it will be useful,
15 	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 	GNU General Public License for more details.
18 
19 	This license is contained in the file "COPYING",
20 	which is included with this source code; it is available online at
21 	http://www.gnu.org/licenses/gpl.html
22 
23 */
24 
25 #include "cseries.h"
26 #include "FileHandler.h"
27 #include "SoundFile.h"
28 #include "world.h"
29 
30 #include "SoundManagerEnums.h"
31 
32 #include <boost/function.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include <boost/scoped_ptr.hpp>
35 
36 struct ambient_sound_data;
37 
38 class SoundMemoryManager;
39 
40 class SoundManager
41 {
42 public:
instance()43 	static inline SoundManager* instance() {
44 		static SoundManager *m_instance = 0;
45 		if (!m_instance) m_instance = new SoundManager;
46 		return m_instance;
47 	}
48 
49 	struct Parameters;
50 	void Initialize(const Parameters&);
51 	void SetParameters(const Parameters&);
52 	void Shutdown();
53 
54 	bool OpenSoundFile(FileSpecifier& File);
55 	void CloseSoundFile();
56 
57 	bool AdjustVolumeUp(short sound_index = NONE);
58 	bool AdjustVolumeDown(short sound_index = NONE);
59 	void TestVolume(short volume, short sound_index);
60 
61 	bool LoadSound(short sound);
62 	void LoadSounds(short *sounds, short count);
63 
64 	void OrphanSound(short identifier);
65 
66 	void UnloadAllSounds();
67 
68 	void PlaySound(short sound_index, world_location3d *source, short identifier, _fixed pitch = _normal_frequency);
69 	void PlayLocalSound(short sound_index, _fixed pitch = _normal_frequency) { PlaySound(sound_index, 0, NONE, pitch); }
70 	void DirectPlaySound(short sound_index, angle direction, short volume, _fixed pitch);
71 	bool SoundIsPlaying(short sound_index);
72 
73 	void StopSound(short identifier, short sound_index);
StopAllSounds()74 	void StopAllSounds() { StopSound(NONE, NONE); }
75 
GetNetmicVolumeAdjustment()76 	inline int16 GetNetmicVolumeAdjustment() {
77 		return (parameters.volume_while_speaking);
78 	}
79 
80 	void Idle();
81 
82 	class Pause
83 	{
84 	public:
Pause()85 		Pause() { instance()->SetStatus(false); }
~Pause()86 		~Pause() { instance()->SetStatus(true); }
87 	};
88 
89 	// ambient sounds
90 	void CauseAmbientSoundSourceUpdate();
91 	void AddOneAmbientSoundSource(ambient_sound_data *ambient_sounds, world_location3d *source, world_location3d *listener, short ambient_sound_index, short absolute_volume);
92 
93 	// random sounds
94 	short RandomSoundIndexToSoundIndex(short random_sound_index);
95 
96 	struct Parameters
97 	{
98 		static const int DEFAULT_RATE = 44100;
99 		static const int DEFAULT_SAMPLES = 1024;
100 		int16 channel_count; // >= 0
101 		int16 volume; // [0, NUMBER_OF_SOUND_VOLUME_LEVELS)
102 		uint16 flags; // stereo, dynamic_tracking, etc.
103 
104 		uint16 rate; // in Hz
105 		uint16 samples; // size of buffer
106 
107 		int16 music; // Music volume: [0, NUMBER_OF_SOUND_VOLUME_LEVELS)
108 
109 		int16 volume_while_speaking; // [0, NUMBER_OF_SOUND_VOLUME_LEVELS)
110 		bool mute_while_transmitting;
111 
112 		Parameters();
113 		bool Verify();
114 	} parameters;
115 
116 	struct Channel
117 	{
118 		uint16 flags;
119 
120 		short sound_index; // sound_index being played in this channel
121 		short identifier; // unique sound identifier for the sound being played in this channel (object_index)
122 		struct Variables
123 		{
124 			short volume, left_volume, right_volume;
125 			_fixed original_pitch, pitch;
126 
127 			short priority;
128 		} variables; // variables of the sound being played
129 
130 		world_location3d *dynamic_source; // can be NULL for immobile sounds
131 		world_location3d source; // must be valid
132 
133 		uint32 start_tick;
134 
135 		int mixer_channel;
136 		short callback_count;
137 	};
138 
IncrementChannelCallbackCount(int channel)139 	void IncrementChannelCallbackCount(int channel) { channels[channel].callback_count++; } // fix this
140 
IsActive()141 	bool IsActive() { return active; }
IsInitialized()142 	bool IsInitialized() { return initialized; }
143 
144 private:
145 	SoundManager();
146 	void SetStatus(bool active);
147 
148 	SoundDefinition* GetSoundDefinition(short sound_index);
149 	void BufferSound(Channel &, short sound_index, _fixed pitch, bool ext_play_immed = true);
150 
151 	Channel *BestChannel(short sound_index, Channel::Variables& variables);
152 	void FreeChannel(Channel &);
153 
154 	void UnlockLockedSounds();
155 
156 	void CalculateSoundVariables(short sound_index, world_location3d *source, Channel::Variables& variables);
157 	void CalculateInitialSoundVariables(short sound_index, world_location3d *source, Channel::Variables& variables, _fixed pitch);
158 	void InstantiateSoundVariables(Channel::Variables& variables, Channel& channel, bool first_time);
159 
160 	_fixed CalculatePitchModifier(short sound_index, _fixed pitch_modifier);
161 	void AngleAndVolumeToStereoVolume(angle delta, short volume, short *right_volume, short *left_volume);
162 
163 	short GetRandomSoundPermutation(short sound_index);
164 
165 	void TrackStereoSounds();
166 	void UpdateAmbientSoundSources();
167 
168 	bool initialized;
169 	bool active;
170 
171 	short total_channel_count;
172 
173 	short sound_source; // 8-bit, 16-bit
174 
175 	std::vector<Channel> channels;
176 
177 	boost::scoped_ptr<SoundFile> sound_file;
178 	SoundMemoryManager* sounds;
179 
180 	// buffer sizes
181 	static const int MINIMUM_SOUND_BUFFER_SIZE = 300*KILO;
182 	static const int MORE_SOUND_BUFFER_SIZE = 600*KILO;
183 	static const int AMBIENT_SOUND_BUFFER_SIZE = 1*MEG;
184 	static const int MAXIMUM_SOUND_BUFFER_SIZE = 1*MEG;
185 
186 	// channels
187 	static const int MAXIMUM_SOUND_CHANNELS = 32;
188 	static const int MAXIMUM_AMBIENT_SOUND_CHANNELS = 4;
189 	static const int MAXIMUM_PROCESSED_AMBIENT_SOUNDS = 5;
190 
191 	// volumes
192 	// MAXIMUM_SOUND_VOLUME is 256, NUMBER_OF_SOUND_VOLUME_LEVELS is 8
193 	static const int MAXIMUM_OUTPUT_SOUND_VOLUME = 2 * MAXIMUM_SOUND_VOLUME;
194 	static const int SOUND_VOLUME_DELTA = MAXIMUM_OUTPUT_SOUND_VOLUME / NUMBER_OF_SOUND_VOLUME_LEVELS;
195 	static const int MAXIMUM_AMBIENT_SOUND_VOLUME = 3 * MAXIMUM_SOUND_VOLUME / 2;
196 	static const int DEFAULT_SOUND_LEVEL= NUMBER_OF_SOUND_VOLUME_LEVELS/3;
197 	static const int DEFAULT_MUSIC_LEVEL = NUMBER_OF_SOUND_VOLUME_LEVELS/2;
198 	static const int DEFAULT_VOLUME_WHILE_SPEAKING = MAXIMUM_SOUND_VOLUME / 8;
199 
200 	// pitch
201 	static const int MINIMUM_SOUND_PITCH= 1;
202 	static const int MAXIMUM_SOUND_PITCH= 256*FIXED_ONE;
203 
204 	// best channel
205 	static const int ABORT_AMPLITUDE_THRESHHOLD= (MAXIMUM_SOUND_VOLUME/6);
206 	static const int MINIMUM_RESTART_TICKS= MACHINE_TICKS_PER_SECOND/12;
207 
208 	// channel flags
209 	static const int _sound_is_local = 0x0001;
210 };
211 
212 /* ---------- types */
213 
214 typedef void (*add_ambient_sound_source_proc_ptr)(ambient_sound_data *ambient_sounds,
215 	world_location3d *source, world_location3d *listener, short sound_index,
216 	short absolute_volume);
217 
218 /* ---------- external prototypes */
219 
220 /* _sound_listener_proc() gives the location and facing of the listener at any point in time;
221 	what are the alternatives to providing this function? */
222 world_location3d *_sound_listener_proc(void);
223 
224 /* _sound_obstructed_proc() tells whether the given sound is obstructed or not */
225 uint16 _sound_obstructed_proc(world_location3d *source);
226 
227 void _sound_add_ambient_sources_proc(void *data, add_ambient_sound_source_proc_ptr add_one_ambient_sound_source);
228 
229 // Accessors for remaining formerly hardcoded sounds:
230 
231 short Sound_TerminalLogon();
232 short Sound_TerminalLogoff();
233 short Sound_TerminalPage();
234 
235 short Sound_TeleportIn();
236 short Sound_TeleportOut();
237 
238 short Sound_GotPowerup();
239 short Sound_GotItem();
240 
241 short Sound_Crunched();
242 short Sound_Exploding();
243 
244 short Sound_Breathing();
245 short Sound_OxygenWarning();
246 
247 short Sound_AdjustVolume();
248 
249 // LP: Ian-Rickard-style commands for interface buttons
250 
251 short Sound_ButtonSuccess();
252 short Sound_ButtonFailure();
253 short Sound_ButtonInoperative();
254 short Sound_OGL_Reset();
255 short Sound_Center_Button();
256 
257 class InfoTree;
258 void parse_mml_sounds(const InfoTree& root);
259 void reset_mml_sounds();
260 
261 #endif
262