ScummVM API documentation
sound.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 
22 #ifndef DIRECTOR_SOUND_H
23 #define DIRECTOR_SOUND_H
24 
25 #include "audio/mixer.h"
26 
27 namespace Audio {
28  class AudioStream;
29  class SoundHandle;
30  class PCSpeaker;
31  class RewindableAudioStream;
32  class LoopableAudioStream;
33 }
34 
35 namespace Common {
36  class MacResManager;
37 }
38 
39 namespace Director {
40 
41 class AudioDecoder;
42 
43 struct FadeParams {
44  int startVol;
45  int targetVol;
46  int totalTicks;
47  int startTicks;
48  int lapsedTicks;
49  bool fadeIn;
50  bool autoStop;
51 
52  FadeParams(int sv, int tv, int tt, int st, bool f, bool as) :
53  startVol(sv), targetVol(tv), totalTicks(tt), startTicks(st), lapsedTicks(0), fadeIn(f), autoStop(as) {}
54 };
55 
56 const uint16 kMinSampledMenu = 10;
57 const uint16 kMaxSampledMenu = 15;
58 const uint16 kNumSampledMenus = kMaxSampledMenu - kMinSampledMenu + 1;
59 
61  uint16 menu;
62  uint16 submenu;
63 
64  ExternalSoundID() : menu(0), submenu(0) {}
65  ExternalSoundID(uint16 menuID, uint16 submenuID)
66  : menu(menuID), submenu(submenuID) {}
67 
68  bool operator==(const ExternalSoundID &b) {
69  return menu == b.menu && submenu == b.submenu;
70  }
71  bool operator!=(const ExternalSoundID &b) {
72  return !(*this == b);
73  }
74 };
75 
76 enum SoundIDType {
77  kSoundCast,
78  kSoundExternal
79 };
80 
81 struct SoundID {
82  SoundIDType type;
83  union {
84  struct {
85  int member;
86  int castLib;
87  } cast;
88  struct {
89  uint16 menu;
90  uint16 submenu;
91  } external;
92  } u;
93 
94  SoundID() {
95  type = kSoundCast;
96  u.cast.member = 0;
97  u.cast.castLib = 0;
98  }
99  SoundID(SoundIDType type_, int a, int b) {
100  type = type_;
101  switch (type) {
102  case kSoundCast:
103  u.cast.member = a;
104  u.cast.castLib = b;
105  break;
106  case kSoundExternal:
107  u.external.menu = a;
108  u.external.submenu = b;
109  }
110  }
111  SoundID(CastMemberID memberID) {
112  type = kSoundCast;
113  u.cast.member = memberID.member;
114  u.cast.castLib = memberID.castLib;
115  }
116 
117  bool operator==(const SoundID &b) {
118  if (type != b.type)
119  return false;
120 
121  switch (type) {
122  case kSoundCast:
123  return u.cast.member == b.u.cast.member && u.cast.castLib == b.u.cast.castLib;
124  case kSoundExternal:
125  return u.external.menu == b.u.external.menu && u.external.submenu == b.u.external.submenu;
126  }
127 
128  return false;
129  }
130  bool operator!=(const SoundID &b) {
131  return !(*this == b);
132  }
133  bool isZero() {
134  if (type == kSoundCast)
135  return u.cast.member == 0;
136  return false;
137  }
138 };
139 
140 struct SoundChannel {
141  Audio::SoundHandle handle;
142  SoundID lastPlayedSound;
143  bool stopOnZero; // Should the sound be stopped when the channel contains cast member 0?
144  byte volume;
145  int pitchShiftPercent;
146  int originalRate;
147  FadeParams *fade;
148 
149  // a non-zero sound ID if the channel is a puppet. i.e. it's controlled by lingo
150  SoundID puppet;
151  bool newPuppet;
152 
153  // this indicate whether the sound is playing across the movie. Because the cast name may be the same while the actual sounds are changing.
154  // And we will override the sound when ever the sound is changing. thus we use a flag to indicate whether the movie is changed.
155  bool movieChanged;
156 
157  // Pointer for keeping track of a looping sound, used to signal
158  // a stop at the end of a loop.
160 
161  SoundChannel(): handle(), lastPlayedSound(SoundID()), stopOnZero(true), volume(255), originalRate(-1), pitchShiftPercent(100), fade(nullptr), puppet(SoundID()), newPuppet(false), movieChanged(false), loopPtr(nullptr) {}
162 };
163 
165 
166 private:
167  Window *_window;
169  Common::HashMap<int, int> _volumes;
170  Audio::SoundHandle _scriptSound;
171  Audio::Mixer *_mixer;
172  Audio::PCSpeaker *_speaker;
173 
174  // these two were used in fplay xobj
175  Common::Queue<Common::String> _fplayQueue;
176  Common::String _currentSoundName;
177 
178  bool _enable;
179 
180  Common::Array<AudioDecoder *> _sampleSounds[kNumSampledMenus];
181 
182 public:
183  DirectorSound(Window *window);
184  ~DirectorSound();
185 
186  SoundChannel *getChannel(int soundChannel);
187  void playFile(Common::String filename, int soundChannel);
188  void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
189  void playStream(Audio::AudioStream &stream, int soundChannel);
190  void playSound(SoundID soundId, int soundChannel, bool forPuppet = false);
191  void playCastMember(CastMemberID memberID, int soundChannel, bool forPuppet = false);
192  void playExternalSound(uint16 menu, uint16 submenu, int soundChannel);
193  void playFPlaySound(const Common::Array<Common::String> &fplayList);
194  void playFPlaySound();
195  void setSoundEnabled(bool enabled);
196  void systemBeep();
197  void changingMovie();
198 
199  void loadSampleSounds(uint type);
200  void unloadSampleSounds();
201 
202  bool isChannelPuppet(int soundChannel);
203  void setPuppetSound(SoundID soundId, int soundChannel);
204  void disablePuppetSound(int soundChannel);
205  void playPuppetSound(int soundChannel);
206 
207  bool getSoundEnabled() { return _enable; }
208 
209  Common::String getCurrentSound() { return _currentSoundName; }
210 
211  void registerFade(int soundChannel, int startVol, int targetVol, int ticks, bool autoStop = false);
212  void registerFade(int soundChannel, bool fadeIn, int ticks, bool autoStop = false);
213  bool fadeChannels();
214 
215  bool isChannelActive(int soundChannel);
216  uint8 getChannelVolume(int soundChannel);
217  void setChannelVolume(int channel, uint8 volume);
218  int8 getChannelBalance(int soundChannel);
219  void setChannelBalance(int soundChannel, int8 balance);
220  uint8 getChannelFaderL(int soundChannel);
221  void setChannelFaderL(int soundChannel, uint8 faderL);
222  uint8 getChannelFaderR(int soundChannel);
223  void setChannelFaderR(int soundChannel, uint8 faderR);
224  void stopSound(int soundChannel);
225  void stopSound();
226  void setChannelDefaultVolume(int soundChannel);
227  void setChannelPitchShift(int soundChannel, int pitchShiftPercent);
228 
229 private:
230  void setLastPlayedSound(int soundChannel, SoundID soundId, bool stopOnZero = true);
231  bool isLastPlayedSound(int soundChannel, const SoundID &soundId);
232  bool shouldStopOnZero(int soundChannel);
233 
234  void setChannelVolumeInternal(int soundChannel, uint8 volume);
235  bool assertChannel(int soundChannel);
236  void cancelFade(int soundChannel);
237 };
238 
240 public:
241  AudioDecoder() {};
242  virtual ~AudioDecoder() {};
243 public:
244  virtual Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) { return nullptr; }
245  virtual int getChannelCount() { return 0; }
246  virtual int getSampleRate() { return 0; }
247  virtual int getSampleSize() { return 0; }
248 };
249 
250 class SNDDecoder : public AudioDecoder {
251 public:
252  SNDDecoder();
253  ~SNDDecoder();
254 
255  bool loadStream(Common::SeekableReadStreamEndian &stream);
256  void loadExternalSoundStream(Common::SeekableReadStreamEndian &stream);
257  bool processCommands(Common::SeekableReadStreamEndian &stream);
258  bool processBufferCommand(Common::SeekableReadStreamEndian &stream);
259  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
260  bool hasLoopBounds();
261  void resetLoopBounds();
262  bool hasValidLoopBounds();
263  int getChannelCount() override { return _channels; }
264  int getSampleRate() override { return _rate; }
265  int getSampleSize() override { return _bits; }
266 
267 private:
268  byte *_data;
269  uint16 _channels;
270  uint32 _size;
271  uint16 _rate;
272  uint16 _bits;
273  byte _flags;
274  uint32 _loopStart;
275  uint32 _loopEnd;
276 };
277 
279 public:
281  ~AudioFileDecoder();
282 
283  void setPath(Common::String &path);
284 
285  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
286 
287 private:
288  Common::String _path;
289  Common::MacResManager *_macresman;
290 };
291 
292 } // End of namespace Director
293 
294 #endif
Definition: audiostream.h:123
Definition: sound.h:250
Definition: macresman.h:126
Definition: str.h:59
Definition: array.h:52
Definition: sound.h:81
Definition: sound.h:239
Definition: sound.h:278
Definition: window.h:103
Definition: archive.h:36
Definition: mixer.h:49
Definition: mixer.h:70
Definition: sound.h:164
Definition: hashmap.h:85
Definition: algorithm.h:29
Definition: audiostream.h:50
Definition: sound.h:60
Definition: stream.h:944
Definition: sound.h:140
Definition: sound.h:43
Definition: types.h:411
Definition: pcspk.h:34
Definition: system.h:38