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 * Additional copyright for this file: 8 * Copyright (C) 1994-1998 Revolution Software Ltd. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 */ 24 25 /***************************************************************************** 26 * SOUND.H Sound engine 27 * 28 * SOUND.CPP Contains the sound engine, fx & music functions 29 * Some very 'sound' code in here ;) 30 * 31 * (16Dec96 JEL) 32 * 33 ****************************************************************************/ 34 35 #ifndef SWORD2_SOUND_H 36 #define SWORD2_SOUND_H 37 38 #include "common/file.h" 39 #include "common/mutex.h" 40 #include "audio/audiostream.h" 41 #include "audio/mixer.h" 42 43 // Max number of sound fx 44 #define MAXMUS 2 45 46 // Max number of fx in queue at once 47 #define FXQ_LENGTH 32 48 49 #define BUFFER_SIZE 4096 50 51 namespace Sword2 { 52 53 enum { 54 kCLUMode = 1, 55 kMP3Mode, 56 kVorbisMode, 57 kFLACMode 58 }; 59 60 enum { 61 kLeadInSound, 62 kLeadOutSound 63 }; 64 65 enum { 66 // These three types correspond to types set by the scripts 67 FX_SPOT = 0, 68 FX_LOOP = 1, 69 FX_RANDOM = 2, 70 71 // These are used for FX queue bookkeeping 72 FX_SPOT2 = 3, 73 FX_LOOPING = 4 74 }; 75 76 // Sound defines 77 78 enum { 79 RDSE_SAMPLEFINISHED = 0, 80 RDSE_SAMPLEPLAYING = 1, 81 RDSE_FXTOCLEAR = 0, // Unused 82 RDSE_FXCACHED = 1, // Unused 83 RDSE_FXSPOT = 0, 84 RDSE_FXLOOP = 1, 85 RDSE_FXLEADIN = 2, 86 RDSE_FXLEADOUT = 3, 87 RDSE_QUIET = 1, 88 RDSE_SPEAKING = 0 89 }; 90 91 class CLUInputStream : public Audio::AudioStream { 92 private: 93 Common::File *_file; 94 bool _firstTime; 95 uint32 _file_pos; 96 uint32 _end_pos; 97 int16 _outbuf[BUFFER_SIZE]; 98 byte _inbuf[BUFFER_SIZE]; 99 const int16 *_bufferEnd; 100 const int16 *_pos; 101 102 uint16 _prev; 103 104 void refill(); 105 eosIntern()106 inline bool eosIntern() const { 107 return !_file->isOpen() || _pos >= _bufferEnd; 108 } 109 110 public: 111 CLUInputStream(Common::File *file, int size); 112 ~CLUInputStream(); 113 114 int readBuffer(int16 *buffer, const int numSamples); 115 endOfData()116 bool endOfData() const { return eosIntern(); } isStereo()117 bool isStereo() const { return false; } getRate()118 int getRate() const { return 22050; } 119 }; 120 121 struct SoundFileHandle { 122 Common::File file; 123 uint32 *idxTab; 124 uint32 idxLen; 125 int32 fileSize; 126 uint32 fileType; 127 volatile bool inUse; 128 }; 129 130 class MusicInputStream : public Audio::AudioStream { 131 private: 132 int _cd; 133 SoundFileHandle *_fh; 134 uint32 _musicId; 135 Audio::AudioStream *_decoder; 136 int16 _buffer[BUFFER_SIZE]; 137 const int16 *_bufferEnd; 138 const int16 *_pos; 139 bool _remove; 140 uint32 _numSamples; 141 uint32 _samplesLeft; 142 bool _looping; 143 int32 _fading; 144 int32 _fadeSamples; 145 146 void refill(); 147 eosIntern()148 inline bool eosIntern() const { 149 if (_looping) 150 return false; 151 return _remove || _pos >= _bufferEnd; 152 } 153 154 public: 155 MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping); 156 ~MusicInputStream(); 157 158 int readBuffer(int16 *buffer, const int numSamples); 159 endOfData()160 bool endOfData() const { return eosIntern(); } isStereo()161 bool isStereo() const { return _decoder->isStereo(); } getRate()162 int getRate() const { return _decoder->getRate(); } 163 getCD()164 int getCD() { return _cd; } 165 166 void fadeUp(); 167 void fadeDown(); 168 isReady()169 bool isReady() { return _decoder != NULL; } isFading()170 int32 isFading() { return _fading; } 171 172 bool readyToRemove(); 173 int32 getTimeRemaining(); 174 }; 175 176 class Sound : public Audio::AudioStream { 177 private: 178 Sword2Engine *_vm; 179 180 Common::Mutex _mutex; 181 182 Audio::SoundHandle _mixerSoundHandle; 183 Audio::SoundHandle _leadInHandle; 184 Audio::SoundHandle _leadOutHandle; 185 186 struct FxQueueEntry { 187 Audio::SoundHandle handle; // sound handle 188 uint32 resource; // resource id of sample 189 byte *data; // pointer to WAV data 190 uint32 len; // WAV data length 191 uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM) 192 uint8 volume; // sound volume 193 int8 pan; // sound panning 194 uint8 type; // FX_SPOT, FX_RANDOM, FX_LOOP 195 }; 196 197 FxQueueEntry _fxQueue[FXQ_LENGTH]; 198 199 void triggerFx(uint8 i); 200 201 bool _reverseStereo; 202 203 bool _speechMuted; 204 bool _fxMuted; 205 bool _musicMuted; 206 207 bool _speechPaused; 208 bool _fxPaused; 209 bool _musicPaused; 210 211 int32 _loopingMusicId; 212 213 Audio::SoundHandle _soundHandleSpeech; 214 215 MusicInputStream *_music[MAXMUS]; 216 SoundFileHandle _musicFile[MAXMUS]; 217 SoundFileHandle _speechFile[MAXMUS]; 218 219 int16 *_mixBuffer; 220 int _mixBufferLen; 221 222 public: 223 Sound(Sword2Engine *vm); 224 ~Sound(); 225 226 // AudioStream API 227 228 int readBuffer(int16 *buffer, const int numSamples); isStereo()229 bool isStereo() const { return false; } 230 bool endOfData() const; getRate()231 int getRate() const { return Sword2Engine::isPsx() ? 11025 : 22050; } 232 233 // End of AudioStream API 234 235 void clearFxQueue(bool killMovieSounds); 236 void processFxQueue(); 237 238 void setReverseStereo(bool reverse); isReverseStereo()239 bool isReverseStereo() const { return _reverseStereo; } 240 241 void muteSpeech(bool mute); isSpeechMute()242 bool isSpeechMute() const { return _speechMuted; } 243 244 void muteFx(bool mute); isFxMute()245 bool isFxMute() const { return _fxMuted; } 246 muteMusic(bool mute)247 void muteMusic(bool mute) { _musicMuted = mute; } isMusicMute()248 bool isMusicMute() const { return _musicMuted; } 249 setLoopingMusicId(int32 id)250 void setLoopingMusicId(int32 id) { _loopingMusicId = id; } getLoopingMusicId()251 int32 getLoopingMusicId() const { return _loopingMusicId; } 252 253 void pauseSpeech(); 254 void unpauseSpeech(); 255 256 void pauseFx(); 257 void unpauseFx(); 258 259 void pauseMusic(); 260 void unpauseMusic(); 261 262 void playMovieSound(int32 res, int type); 263 void stopMovieSounds(); 264 265 void queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan); 266 int32 playFx(FxQueueEntry *fx); 267 int32 playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType); 268 int32 stopFx(int32 i); 269 int32 setFxIdVolumePan(int32 id, int vol, int pan = 255); 270 271 int32 getSpeechStatus(); 272 int32 amISpeaking(); 273 int32 playCompSpeech(uint32 speechId, uint8 vol, int8 pan); 274 int32 stopSpeech(); 275 276 int32 streamCompMusic(uint32 musicId, bool loop); 277 void stopMusic(bool immediately); 278 int32 musicTimeRemaining(); 279 280 void printFxQueue(); 281 }; 282 283 } // End of namespace Sword2 284 285 #endif 286