1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef TITANIC_SOUND_MANAGER_H 24 #define TITANIC_SOUND_MANAGER_H 25 26 #include "titanic/core/list.h" 27 #include "titanic/support/simple_file.h" 28 #include "titanic/sound/audio_buffer.h" 29 #include "titanic/sound/proximity.h" 30 #include "titanic/sound/qmixer.h" 31 #include "titanic/sound/wave_file.h" 32 #include "titanic/true_talk/dialogue_file.h" 33 34 namespace Titanic { 35 36 enum VolumeMode { 37 VOL_NORMAL = -1, VOL_QUIET = -2, VOL_VERY_QUIET = -3, VOL_MUTE = -4 38 }; 39 40 /** 41 * Abstract interface class for a sound manager 42 */ 43 class CSoundManager { 44 protected: 45 uint _handleCtr; 46 // Old volume levels, deprecated in favor of setting the volumes 47 // directly in the ScummVM mixer 48 double _musicPercent; 49 double _speechPercent; 50 double _masterPercent; 51 double _parrotPercent; 52 public: 53 CSoundManager(); ~CSoundManager()54 virtual ~CSoundManager() {} 55 56 /** 57 * Loads a sound 58 * @param name Name of sound resource 59 * @returns Loaded wave file 60 */ loadSound(const CString & name)61 virtual CWaveFile *loadSound(const CString &name) { return nullptr; } 62 63 /** 64 * Loads a speech resource from a dialogue file 65 * @param name Name of sound resource 66 * @returns Loaded wave file 67 */ loadSpeech(CDialogueFile * dialogueFile,int speechId)68 virtual CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId) { return 0; } 69 70 /** 71 * Loads a music file 72 * @param name Name of music resource 73 * @returns Loaded wave file 74 * @remarks The original only classified music as what's produced in the 75 * music room puzzle. For ScummVM, we've reclassified some wave files that 76 * contain background music as music as well. 77 */ loadMusic(const CString & name)78 virtual CWaveFile *loadMusic(const CString &name) { return nullptr; } 79 80 /** 81 * Loads a music file from a streaming audio buffer 82 * @param buffer Audio buffer 83 * @returns Loaded wave file 84 */ loadMusic(CAudioBuffer * buffer,DisposeAfterUse::Flag disposeAfterUse)85 virtual CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) { return nullptr; } 86 87 /** 88 * Start playing a previously loaded wave file 89 */ 90 virtual int playSound(CWaveFile &waveFile, CProximity &prox) = 0; 91 92 /** 93 * Stop playing the specified sound 94 */ 95 virtual void stopSound(int handle) = 0; 96 97 /** 98 * Stops a designated range of channels 99 */ 100 virtual void stopChannel(int channel) = 0; 101 proc9(int handle)102 virtual void proc9(int handle) {} 103 104 /** 105 * Stops sounds on all playing channels 106 */ 107 virtual void stopAllChannels() = 0; 108 109 /** 110 * Sets the volume for a sound 111 * @param handle Handle for sound 112 * @param volume New volume 113 * @param seconds Number of seconds to transition to the new volume 114 */ 115 virtual void setVolume(int handle, uint volume, uint seconds) = 0; 116 117 /** 118 * Set the position for a sound 119 * @param handle Handle for sound 120 * @param x x position in metres 121 * @param y y position in metres 122 * @param z z position in metres 123 * @param panRate Rate in milliseconds to transition 124 */ setVectorPosition(int handle,double x,double y,double z,uint panRate)125 virtual void setVectorPosition(int handle, double x, double y, double z, uint panRate) {} 126 127 /** 128 * Set the position for a sound 129 * @param handle Handle for sound 130 * @param range Range value in metres 131 * @param azimuth Azimuth value in degrees 132 * @param elevation Elevation value in degrees 133 * @param panRate Rate in milliseconds to transition 134 */ setPolarPosition(int handle,double range,double azimuth,double elevation,uint panRate)135 virtual void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) {} 136 137 /** 138 * Returns true if the given sound is currently active 139 */ 140 virtual bool isActive(int handle) = 0; 141 142 /** 143 * Returns true if the given sound is currently active 144 */ isActive(const CWaveFile * waveFile)145 virtual bool isActive(const CWaveFile *waveFile) { return false; } 146 147 /** 148 * Handles regularly updating the mixer 149 */ 150 virtual void waveMixPump() = 0; 151 152 /** 153 * Returns the movie latency 154 */ getLatency()155 virtual uint getLatency() const { return 0; } 156 157 /** 158 * Sets the music volume percent 159 */ 160 virtual void setMusicPercent(double percent) = 0; 161 162 /** 163 * Sets the speech volume percent 164 */ 165 virtual void setSpeechPercent(double percent) = 0; 166 167 /** 168 * Sets the master volume percent 169 */ 170 virtual void setMasterPercent(double percent) = 0; 171 172 /** 173 * Sets the Parrot NPC volume percent 174 */ 175 virtual void setParrotPercent(double percent) = 0; 176 177 /** 178 * Called when a game is about to be loaded 179 */ preLoad()180 virtual void preLoad() { stopAllChannels(); } 181 182 /** 183 * Load the data for the class from file 184 */ load(SimpleFile * file)185 void load(SimpleFile *file) {} 186 187 /** 188 * Called after loading of a game is completed 189 */ postLoad()190 virtual void postLoad() {} 191 192 /** 193 * Called when a game is about to be saved 194 */ preSave()195 virtual void preSave() {} 196 197 /** 198 * Save the data for the class to file 199 */ save(SimpleFile * file)200 void save(SimpleFile *file) const {} 201 202 /** 203 * Called after saving is complete 204 */ postSave()205 virtual void postSave() {} 206 207 /** 208 * Sets the position and orientation for the listener (player) 209 */ setListenerPosition(double posX,double posY,double posZ,double directionX,double directionY,double directionZ,bool stopSounds)210 virtual void setListenerPosition(double posX, double posY, double posZ, 211 double directionX, double directionY, double directionZ, bool stopSounds) {} 212 213 /** 214 * Returns the music volume percent 215 */ getMusicVolume()216 double getMusicVolume() const { return _musicPercent; } 217 218 /** 219 * Returns the speech volume percent 220 */ getSpeechVolume()221 double getSpeechVolume() const { return _speechPercent; } 222 223 /** 224 * Returns the parrot volume percent 225 */ getParrotVolume()226 double getParrotVolume() const { return _parrotPercent; } 227 228 /** 229 * Gets the volume for a given mode? value 230 */ 231 uint getModeVolume(VolumeMode mode); 232 }; 233 234 class QSoundManagerSound : public ListItem { 235 public: 236 CWaveFile *_waveFile; 237 int _iChannel; 238 CEndTalkerFn _endFn; 239 TTtalker *_talker; 240 public: QSoundManagerSound()241 QSoundManagerSound() : ListItem(), _waveFile(nullptr), 242 _iChannel(0), _endFn(nullptr), _talker(nullptr) {} QSoundManagerSound(CWaveFile * waveFile,int iChannel,CEndTalkerFn endFn,TTtalker * talker)243 QSoundManagerSound(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) : 244 ListItem(), _waveFile(waveFile), _iChannel(iChannel), _endFn(endFn), _talker(talker) {} 245 }; 246 247 class QSoundManagerSounds : public List<QSoundManagerSound> { 248 public: 249 /** 250 * Adds a new sound entry to the list 251 */ 252 void add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker); 253 254 /** 255 * Flushes a wave file attached to the specified channel 256 */ 257 void flushChannel(int iChannel); 258 259 /** 260 * Flushes a wave file attached to the specified channel 261 */ 262 void flushChannel(CWaveFile *waveFile, int iChannel); 263 264 /** 265 * Returns true if the list contains the specified wave file 266 */ 267 bool contains(const CWaveFile *waveFile) const; 268 }; 269 270 /** 271 * Concrete sound manager class that handles interfacing with 272 * the QMixer sound mixer class 273 */ 274 class QSoundManager : public CSoundManager, public QMixer { 275 struct Slot { 276 CWaveFile *_waveFile; 277 bool _isTimed; 278 uint _ticks; 279 int _channel; 280 int _handle; 281 PositioningMode _positioningMode; 282 SlotSlot283 Slot() : _waveFile(0), _isTimed(0), _ticks(0), _channel(-1), 284 _handle(0), _positioningMode(POSMODE_NONE) {} 285 void clear(); 286 }; 287 private: 288 QSoundManagerSounds _sounds; 289 Common::Array<Slot> _slots; 290 uint _channelsVolume[16]; 291 int _channelsMode[16]; 292 private: 293 /** 294 * Updates the volume for a channel 295 * @param channel Channel to be update 296 * @param panRate Time in milliseconds for change to occur 297 */ 298 void updateVolume(int channel, uint panRate); 299 300 /** 301 * Updates all the volumes 302 */ 303 void updateVolumes(); 304 305 /** 306 * Called by the QMixer when a sound finishes playing 307 */ 308 static void soundFinished(int iChannel, CWaveFile *waveFile, void *soundManager); 309 310 /** 311 * Finds the first free slot 312 */ 313 int findFreeSlot(); 314 315 /** 316 * Sets a channel volume 317 */ 318 void setChannelVolume(int iChannel, uint volume, uint mode); 319 320 /** 321 * Resets the specified channel and returns a new free one 322 */ 323 int resetChannel(int iChannel); 324 public: 325 int _field18; 326 int _field1C; 327 328 public: 329 QSoundManager(Audio::Mixer *mixer); 330 ~QSoundManager() override; 331 332 /** 333 * Loads a sound 334 * @param name Name of sound resource 335 * @returns Loaded wave file 336 */ 337 CWaveFile *loadSound(const CString &name) override; 338 339 /** 340 * Loads a speech resource from a dialogue file 341 * @param name Name of sound resource 342 * @returns Loaded wave file 343 */ 344 CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId) override; 345 346 /** 347 * Loads a music file 348 * @param name Name of music resource 349 * @returns Loaded wave file 350 * @remarks The original only classified music as what's produced in the 351 * music room puzzle. For ScummVM, we've reclassified some wave files that 352 * contain background music as music as well. 353 */ 354 CWaveFile *loadMusic(const CString &name) override; 355 356 /** 357 * Loads a music file from a streaming audio buffer 358 * @param buffer Audio buffer 359 * @returns Loaded wave file 360 */ 361 CWaveFile *loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAfterUse) override; 362 363 /** 364 * Start playing a previously loaded sound resource 365 */ 366 int playSound(CWaveFile &waveFile, CProximity &prox) override; 367 368 /** 369 * Stop playing the specified sound 370 */ 371 void stopSound(int handle) override; 372 373 /** 374 * Stops a designated range of channels 375 */ 376 void stopChannel(int channel) override; 377 378 /** 379 * Flags that a sound can be freed if a timeout is set 380 */ 381 virtual void setCanFree(int handle); 382 383 /** 384 * Stops sounds on all playing channels 385 */ 386 void stopAllChannels() override; 387 388 /** 389 * Sets the volume for a sound 390 * @param handle Handle for sound 391 * @param volume New volume 392 * @param seconds Number of seconds to transition to the new volume 393 */ 394 void setVolume(int handle, uint volume, uint seconds) override; 395 396 /** 397 * Set the position for a sound 398 * @param handle Handle for sound 399 * @param x x position in metres 400 * @param y y position in metres 401 * @param z z position in metres 402 * @param panRate Rate in milliseconds to transition 403 */ 404 void setVectorPosition(int handle, double x, double y, double z, uint panRate) override; 405 406 /** 407 * Set the position for a sound 408 * @param handle Handle for sound 409 * @param range Range value in metres 410 * @param azimuth Azimuth value in degrees 411 * @param elevation Elevation value in degrees 412 * @param panRate Rate in milliseconds to transition 413 */ 414 void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) override; 415 416 /** 417 * Returns true if the given sound is currently active 418 */ 419 bool isActive(int handle) override; 420 421 /** 422 * Returns true if the given sound is currently active 423 */ 424 bool isActive(const CWaveFile *waveFile) override; 425 426 /** 427 * Handles regularly updating the mixer 428 */ 429 void waveMixPump() override; 430 431 /** 432 * Returns the movie latency 433 */ 434 uint getLatency() const override; 435 436 /** 437 * Sets the music volume percent 438 */ 439 void setMusicPercent(double percent) override; 440 441 /** 442 * Sets the speech volume percent 443 */ 444 void setSpeechPercent(double percent) override; 445 446 /** 447 * Sets the master volume percent 448 */ 449 void setMasterPercent(double percent) override; 450 451 /** 452 * Sets the Parrot NPC volume percent 453 */ 454 void setParrotPercent(double percent) override; 455 456 /** 457 * Sets the position and orientation for the listener (player) 458 */ 459 void setListenerPosition(double posX, double posY, double posZ, 460 double directionX, double directionY, double directionZ, bool stopSounds) override; 461 462 /** 463 * Starts a wave file playing 464 */ 465 virtual int playWave(CWaveFile *waveFile, int iChannel, uint flags, CProximity &prox); 466 467 /** 468 * Called when a wave file is freed 469 */ 470 void soundFreed(Audio::SoundHandle &handle); 471 }; 472 473 } // End of namespace Titanic 474 475 #endif /* TITANIC_QSOUND_MANAGER_H */ 476