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  bool fromLastMovie; // Was this sound carried over from a movie switch?
145  byte volume;
146  int pitchShiftPercent;
147  int originalRate;
148  FadeParams *fade;
149  int lastCuePointIndex;
150 
151  // a non-zero sound ID if the channel is a puppet. i.e. it's controlled by lingo
152  SoundID puppet;
153  bool newPuppet;
154 
155  // this indicate whether the sound is playing across the movie. Because the cast name may be the same while the actual sounds are changing.
156  // And we will override the sound when ever the sound is changing. thus we use a flag to indicate whether the movie is changed.
157  bool movieChanged;
158 
159  // Pointer for keeping track of a looping sound, used to signal
160  // a stop at the end of a loop.
162 
163  SoundChannel(): handle(), lastPlayedSound(SoundID()), stopOnZero(true), fromLastMovie(false), volume(255), originalRate(-1),
164  pitchShiftPercent(100), fade(nullptr), puppet(SoundID()), newPuppet(false), movieChanged(false), loopPtr(nullptr),
165  lastCuePointIndex(-1) {}
166 };
167 
169 
170 private:
171  Window *_window;
173  Common::HashMap<int, int> _volumes;
174  Audio::SoundHandle _scriptSound;
175  Audio::Mixer *_mixer;
176  Audio::PCSpeaker *_speaker;
177 
178  // these two were used in fplay xobj
179  Common::Queue<Common::String> _fplayQueue;
180  Common::String _currentSoundName;
181 
182  bool _enable;
183 
184  Common::Array<AudioDecoder *> _sampleSounds[kNumSampledMenus];
185 
186 public:
187  DirectorSound(Window *window);
188  ~DirectorSound();
189 
190  SoundChannel *getChannel(int soundChannel);
191  void playFile(Common::String filename, int soundChannel);
192  void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
193  void playStream(Audio::AudioStream &stream, int soundChannel);
194  void playSound(SoundID soundId, int soundChannel, bool forPuppet = false);
195  void playCastMember(CastMemberID memberID, int soundChannel, bool forPuppet = false);
196  void playExternalSound(uint16 menu, uint16 submenu, int soundChannel);
197  void playFPlaySound(const Common::Array<Common::String> &fplayList);
198  void playFPlaySound();
199  void setSoundEnabled(bool enabled);
200  void systemBeep();
201  void changingMovie();
202 
203  void loadSampleSounds(uint type);
204  void unloadSampleSounds();
205 
206  bool isChannelPuppet(int soundChannel);
207  void setPuppetSound(SoundID soundId, int soundChannel);
208  void disablePuppetSound(int soundChannel);
209  void playPuppetSound(int soundChannel);
210 
211  bool getSoundEnabled() { return _enable; }
212 
213  Common::String getCurrentSound() { return _currentSoundName; }
214 
215  void registerFade(int soundChannel, int startVol, int targetVol, int ticks, bool autoStop = false);
216  void registerFade(int soundChannel, bool fadeIn, int ticks, bool autoStop = false);
217  bool fadeChannels();
218 
219  bool isChannelActive(int soundChannel);
220  uint8 getChannelVolume(int soundChannel);
221  void setChannelVolume(int channel, uint8 volume);
222  int8 getChannelBalance(int soundChannel);
223  void setChannelBalance(int soundChannel, int8 balance);
224  uint8 getChannelFaderL(int soundChannel);
225  void setChannelFaderL(int soundChannel, uint8 faderL);
226  uint8 getChannelFaderR(int soundChannel);
227  void setChannelFaderR(int soundChannel, uint8 faderR);
228  void stopSound(int soundChannel);
229  void stopSound();
230  void setChannelDefaultVolume(int soundChannel);
231  void setChannelPitchShift(int soundChannel, int pitchShiftPercent);
232 
233  void processCuePoints();
234 
235 private:
236  void setLastPlayedSound(int soundChannel, SoundID soundId, bool stopOnZero = true);
237  bool isLastPlayedSound(int soundChannel, const SoundID &soundId);
238  bool shouldStopOnZero(int soundChannel);
239 
240  void setChannelVolumeInternal(int soundChannel, uint8 volume);
241  bool assertChannel(int soundChannel);
242  void cancelFade(int soundChannel);
243 };
244 
246 public:
247  AudioDecoder() {};
248  virtual ~AudioDecoder() {};
249 public:
250  virtual Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) { return nullptr; }
251  virtual int getChannelCount() { return 0; }
252  virtual int getSampleRate() { return 0; }
253  virtual int getSampleSize() { return 0; }
254 };
255 
256 class SNDDecoder : public AudioDecoder {
257 public:
258  SNDDecoder();
259  ~SNDDecoder();
260 
261  bool loadStream(Common::SeekableReadStreamEndian &stream);
262  void loadExternalSoundStream(Common::SeekableReadStreamEndian &stream);
263  bool processCommands(Common::SeekableReadStreamEndian &stream);
264  bool processBufferCommand(Common::SeekableReadStreamEndian &stream);
265  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
266  bool hasLoopBounds();
267  void resetLoopBounds();
268  bool hasValidLoopBounds();
269  int getChannelCount() override { return _channels; }
270  int getSampleRate() override { return _rate; }
271  int getSampleSize() override { return _bits; }
272 
273 private:
274  byte *_data;
275  uint16 _channels;
276  uint32 _size;
277  uint16 _rate;
278  uint16 _bits;
279  byte _flags;
280  uint32 _loopStart;
281  uint32 _loopEnd;
282 };
283 
285 public:
287  ~AudioFileDecoder();
288 
289  void setPath(Common::String &path);
290 
291  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
292 
293 private:
294  Common::String _path;
295  Common::MacResManager *_macresman;
296 };
297 
299 public:
301  ~MoaStreamDecoder();
302 
303  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
304 
305 private:
306  Common::String _format;
308 };
309 
310 // Source: mixsnd.h in the Director 7 XDK
312  int32 offset;
313  int32 size;
314  int32 playbackStart;
315  int32 playbackStartFrame;
316  int32 loopStart;
317  int32 loopStartFrame;
318  int32 loopEnd;
319  int32 loopEndFrame;
320  int32 playbackEnd;
321  int32 playbackEndFrame;
322  int32 numFrames;
323  int32 frameRate;
324  int32 byteRate;
325  byte compressionType[16];
326  int32 bitsPerSample;
327  int32 bytesPerSample;
328  int32 numChannels;
329  int32 bytesPerFrame;
330  byte soundHeaderType[16];
331  uint32 platformData[63];
332  int32 bytesPerBlock;
333 };
334 
336 public:
339 
340  bool loadHeaderStream(Common::SeekableReadStreamEndian &stream);
341  bool loadSampleStream(Common::SeekableReadStreamEndian &stream);
342 
343  MoaSoundFormat _format;
344  byte *_data = nullptr;
345  uint32 _size = 0;
346 
347  Audio::AudioStream *getAudioStream(bool looping = false, bool forPuppet = false, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) override;
348 };
349 
350 } // End of namespace Director
351 
352 #endif
Definition: audiostream.h:123
Definition: sound.h:311
Definition: sound.h:256
Definition: macresman.h:126
Definition: str.h:59
Definition: array.h:52
Definition: sound.h:81
Definition: sound.h:298
Definition: sound.h:245
Definition: sound.h:284
Definition: window.h:106
Definition: archive.h:36
Definition: sound.h:335
Definition: mixer.h:49
Definition: mixer.h:70
Definition: sound.h:168
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:419
Definition: pcspk.h:34
Definition: system.h:38