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