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 SCI_MUSIC_H 24 #define SCI_MUSIC_H 25 26 #include "common/serializer.h" 27 #include "common/mutex.h" 28 29 #include "audio/mixer.h" 30 31 #include "sci/sci.h" 32 #include "sci/resource/resource.h" 33 #include "sci/sound/drivers/mididriver.h" 34 #ifdef ENABLE_SCI32 35 #include "sci/sound/audio32.h" 36 #endif 37 38 namespace Audio { 39 class LoopingAudioStream; 40 class RewindableAudioStream; 41 } 42 43 namespace Sci { 44 45 enum SoundStatus { 46 kSoundStopped = 0, 47 kSoundInitialized = 1, 48 kSoundPaused = 2, 49 kSoundPlaying = 3 50 }; 51 52 #define MUSIC_VOLUME_DEFAULT 127 53 #define MUSIC_VOLUME_MAX 127 54 #define MUSIC_MASTERVOLUME_DEFAULT 15 55 #define MUSIC_MASTERVOLUME_MAX 15 56 57 class MidiParser_SCI; 58 class SegManager; 59 60 typedef Common::Array<uint16> SignalQueue; 61 62 63 struct MusicEntryChannel { 64 // Channel info 65 int8 _prio; // 0 = essential; lower is higher priority 66 int8 _voices; 67 bool _dontRemap; 68 bool _dontMap; 69 bool _mute; 70 }; 71 72 73 class MusicEntry : public Common::Serializable { 74 public: 75 // Do not get these directly for the sound objects! 76 // It's a bad idea, as the sound code (i.e. the SciMusic 77 // class) should be as separate as possible from the rest 78 // of the engine 79 80 reg_t soundObj; 81 82 SoundResource *soundRes; 83 uint16 resourceId; 84 85 int time; // "tim"estamp to indicate in which order songs have been added 86 87 uint16 dataInc; 88 uint16 ticker; 89 uint16 signal; 90 int16 priority; // must be int16, at least in Laura Bow 1, main music (object conMusic) uses priority -1 91 uint16 loop; 92 int16 volume; 93 int16 hold; 94 int8 reverb; 95 bool playBed; 96 bool overridePriority; // Use soundObj's priority instead of resource's 97 98 int16 pauseCounter; 99 uint sampleLoopCounter; 100 101 byte fadeTo; 102 short fadeStep; 103 uint32 fadeTicker; 104 uint32 fadeTickerStep; 105 bool fadeSetVolume; 106 bool fadeCompleted; 107 bool stopAfterFading; 108 109 SoundStatus status; 110 111 Audio::Mixer::SoundType soundType; 112 113 int _usedChannels[16]; 114 MusicEntryChannel _chan[16]; 115 MidiParser_SCI *pMidiParser; 116 117 // this is used for storing signals, when the current signal is not yet 118 // sent to the scripts. We shouldn't need to save it, this normally only 119 // happens in rare situations like lb1, knocking on the door in the attic 120 SignalQueue signalQueue; 121 122 // TODO: We need to revise how we store the different 123 // audio stream objects we require. 124 Audio::RewindableAudioStream *pStreamAud; 125 Audio::LoopingAudioStream *pLoopStream; 126 Audio::SoundHandle hCurrentAud; 127 bool isSample; 128 129 public: 130 MusicEntry(); 131 ~MusicEntry() override; 132 133 void doFade(); 134 void onTimer(); 135 void setSignal(int signal); 136 137 void saveLoadWithSerializer(Common::Serializer &ser) override; 138 }; 139 140 struct DeviceChannelUsage { 141 MusicEntry *_song; 142 int _channel; 143 bool operator==(const DeviceChannelUsage& other) const { return _song == other._song && _channel == other._channel; } 144 bool operator!=(const DeviceChannelUsage& other) const { return !(*this == other); } 145 }; 146 147 struct ChannelRemapping { 148 DeviceChannelUsage _map[16]; 149 int _prio[16]; 150 int _voices[16]; 151 bool _dontRemap[16]; 152 int _freeVoices; 153 154 void clear(); 155 void swap(int i, int j); 156 void evict(int i); 157 ChannelRemapping& operator=(ChannelRemapping& other); 158 int lowestPrio() const; 159 }; 160 161 struct MidiCommand { 162 enum CmdType { 163 kTypeMidiMessage = 0, 164 kTypeTrackInit 165 }; 166 // Keeping this very simple, due to the very limited purpose of it. MidiCommandMidiCommand167 MidiCommand(CmdType type, uint32 val) : _type(type), _dataPtr(0), _dataVal(val) {} MidiCommandMidiCommand168 MidiCommand(CmdType type, void *ptr) : _type(type), _dataPtr(ptr), _dataVal(0) {} 169 CmdType _type; 170 void *_dataPtr; 171 uint32 _dataVal; 172 }; 173 174 typedef Common::Array<MusicEntry *> MusicList; 175 typedef Common::Array<MidiCommand> MidiCommandQueue; 176 177 class SciMusic : public Common::Serializable { 178 179 public: 180 SciMusic(SciVersion soundVersion, bool useDigitalSFX); 181 ~SciMusic() override; 182 183 void init(); 184 185 void onTimer(); 186 void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp); 187 void putMidiCommandInQueue(uint32 midi); 188 void putTrackInitCommandInQueue(MusicEntry *psnd); 189 void removeTrackInitCommandsFromQueue(MusicEntry *psnd); 190 private: 191 static void miditimerCallback(void *p); 192 void sendMidiCommandsFromQueue(); 193 194 public: 195 void clearPlayList(); 196 void pauseAll(bool pause); 197 void stopAll(); 198 void stopAllSamples(); 199 200 // sound and midi functions 201 void soundInitSnd(MusicEntry *pSnd); 202 void soundPlay(MusicEntry *pSnd, bool restoring = false); 203 void soundStop(MusicEntry *pSnd); 204 void soundKill(MusicEntry *pSnd); 205 void soundPause(MusicEntry *pSnd); 206 void soundResume(MusicEntry *pSnd); 207 void soundToggle(MusicEntry *pSnd, bool pause); 208 void soundSetVolume(MusicEntry *pSnd, byte volume); 209 void soundSetSampleVolume(MusicEntry *pSnd, byte volume); 210 void soundSetPriority(MusicEntry *pSnd, byte prio); 211 uint16 soundGetMasterVolume(); 212 void soundSetMasterVolume(uint16 vol); soundGetSoundOn()213 uint16 soundGetSoundOn() const { return _soundOn; } 214 void soundSetSoundOn(bool soundOnFlag); 215 uint16 soundGetVoices(); soundGetTempo()216 uint32 soundGetTempo() const { return _dwTempo; } soundGetMusicType()217 MusicType soundGetMusicType() const { return _musicType; } 218 soundIsActive(MusicEntry * pSnd)219 bool soundIsActive(MusicEntry *pSnd) { 220 assert(pSnd->pStreamAud != 0); 221 return _pMixer->isSoundHandleActive(pSnd->hCurrentAud); 222 } 223 updateAudioStreamTicker(MusicEntry * pSnd)224 void updateAudioStreamTicker(MusicEntry *pSnd) { 225 assert(pSnd->pStreamAud != 0); 226 pSnd->ticker = (uint16)(_pMixer->getSoundElapsedTime(pSnd->hCurrentAud) * 0.06); 227 } 228 229 MusicEntry *getSlot(reg_t obj); 230 MusicEntry *getFirstSlotWithStatus(SoundStatus status); 231 pushBackSlot(MusicEntry * slotEntry)232 void pushBackSlot(MusicEntry *slotEntry) { 233 Common::StackLock lock(_mutex); 234 _playList.push_back(slotEntry); 235 if (_soundVersion <= SCI_VERSION_0_LATE) // I limit this to SCI0, since it always inserts the nodes at the correct position, but no idea about >=SCI1 236 sortPlayList(); 237 } 238 239 void printPlayList(Console *con); 240 void printSongInfo(reg_t obj, Console *con); 241 242 // The following two methods are NOT thread safe - make sure that 243 // the mutex is always locked before calling them getPlayListStart()244 MusicList::iterator getPlayListStart() { return _playList.begin(); } getPlayListEnd()245 MusicList::iterator getPlayListEnd() { return _playList.end(); } 246 247 void sendMidiCommand(uint32 cmd); 248 void sendMidiCommand(MusicEntry *pSnd, uint32 cmd); 249 250 void setGlobalReverb(int8 reverb); getGlobalReverb()251 int8 getGlobalReverb() { return _globalReverb; } 252 253 byte getCurrentReverb(); 254 needsRemap()255 void needsRemap() { _needsRemap = true; } 256 257 void saveLoadWithSerializer(Common::Serializer &ser) override; 258 259 // Mutex for music code. Used to guard access to the song playlist, to the 260 // MIDI parser and to the MIDI driver/player. Note that guarded code must NOT 261 // include references to the mixer, otherwise there will probably be situations 262 // where a deadlock can occur 263 Common::Mutex _mutex; 264 265 protected: 266 void sortPlayList(); 267 268 SciVersion _soundVersion; 269 270 Audio::Mixer *_pMixer; 271 MidiPlayer *_pMidiDrv; 272 273 uint32 _dwTempo; 274 // If true and a sound has a digital track, the sound from the AdLib track is played 275 bool _useDigitalSFX; 276 277 // remapping: 278 void remapChannels(bool mainThread = true); 279 ChannelRemapping *determineChannelMap(); 280 void resetDeviceChannel(int devChannel, bool mainThread); 281 282 private: 283 MusicList _playList; 284 bool _soundOn; 285 byte _masterVolume; 286 MusicEntry *_usedChannel[16]; 287 int8 _channelRemap[16]; 288 int8 _globalReverb; 289 bool _needsRemap; 290 int _globalPause; 291 bool _needsResume; 292 293 DeviceChannelUsage _channelMap[16]; 294 295 MidiCommandQueue _queuedCommands; 296 MusicType _musicType; 297 298 int _driverFirstChannel; 299 int _driverLastChannel; 300 301 MusicEntry *_currentlyPlayingSample; 302 303 int _timeCounter; // Used to keep track of the order in which MusicEntries 304 // are added, for priority purposes. 305 }; 306 307 } // End of namespace Sci 308 309 #endif 310