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