1 /* 2 Copyright (c) 2009 Peter "Corsix" Cawley 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy of 5 this software and associated documentation files (the "Software"), to deal in 6 the Software without restriction, including without limitation the rights to 7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 of the Software, and to permit persons to whom the Software is furnished to do 9 so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in all 12 copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 SOFTWARE. 21 */ 22 23 #ifndef CORSIX_TH_TH_SOUND_H_ 24 #define CORSIX_TH_TH_SOUND_H_ 25 #include "config.h" 26 27 #include <SDL.h> 28 #ifdef CORSIX_TH_USE_SDL_MIXER 29 #include <SDL_mixer.h> 30 #endif 31 32 //! Utility class for accessing Theme Hospital's SOUND-0.DAT 33 class sound_archive { 34 public: 35 sound_archive(); 36 ~sound_archive(); 37 38 bool load_from_th_file(const uint8_t* pData, size_t iDataLength); 39 40 //! Returns the number of sounds present in the archive 41 size_t get_number_of_sounds() const; 42 43 //! Gets the name of the sound at a given index 44 const char* get_sound_name(size_t iIndex) const; 45 46 //! Gets the duration (in milliseconds) of the sound at a given index 47 size_t get_sound_duration(size_t iIndex); 48 49 //! Opens the sound at a given index into an SDL_RWops structure 50 /*! 51 The caller is responsible for closing/freeing the result. 52 */ 53 SDL_RWops* load_sound(size_t iIndex); 54 55 private: 56 #if CORSIX_TH_USE_PACK_PRAGMAS 57 #pragma pack(push) 58 #pragma pack(1) 59 #endif 60 struct sound_dat_file_header { 61 uint8_t unknown1[50]; 62 uint32_t table_position; 63 uint32_t unknown2; 64 uint32_t table_length; 65 uint32_t table_position2; 66 uint8_t unknown3[112]; 67 uint32_t table_position3; 68 uint32_t table_length2; 69 uint8_t unknown4[48]; 70 } CORSIX_TH_PACKED_FLAGS; 71 72 struct sound_dat_sound_info { 73 char sound_name[18]; 74 uint32_t position; 75 uint32_t unknown1; 76 uint32_t length; 77 uint16_t unknown2; 78 } CORSIX_TH_PACKED_FLAGS; 79 #if CORSIX_TH_USE_PACK_PRAGMAS 80 #pragma pack(pop) 81 #endif 82 83 // TODO: header is only used in one function, should not be class variable. 84 sound_dat_file_header header; 85 sound_dat_sound_info* sound_files; 86 uint8_t* data; 87 size_t sound_file_count; 88 }; 89 90 class sound_player { 91 public: 92 sound_player(); 93 ~sound_player(); 94 95 static sound_player* get_singleton(); 96 97 void populate_from(sound_archive* pArchive); 98 99 void play(size_t iIndex, double dVolume); 100 void play_at(size_t iIndex, int iX, int iY); 101 void play_at(size_t iIndex, double dVolume, int iX, int iY); 102 void set_sound_effect_volume(double dVolume); 103 void set_sound_effects_enabled(bool bOn); 104 void set_camera(int iX, int iY, int iRadius); 105 int reserve_channel(); 106 void release_channel(int iChannel); 107 108 private: 109 #ifdef CORSIX_TH_USE_SDL_MIXER 110 static sound_player* singleton; 111 static void on_channel_finished(int iChannel); 112 113 inline void play_raw(size_t iIndex, int iVolume); 114 115 Mix_Chunk** sounds; 116 size_t sound_count; 117 uint32_t available_channels_bitmap; ///< The bit index corresponding to a 118 ///< channel is 1 if the channel is 119 ///< available and 0 if it is reserved 120 ///< or in use. 121 int camera_x; 122 int camera_y; 123 double camera_radius; 124 double master_volume; 125 double sound_effect_volume; 126 int positionless_volume; 127 bool sound_effects_enabled; 128 #endif // CORSIX_TH_USE_SDL_MIXER 129 }; 130 131 #endif // CORSIX_TH_TH_SOUND_H_ 132