ScummVM API documentation
sound_he.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 SCUMM_HE_SOUND_HE_H
23 #define SCUMM_HE_SOUND_HE_H
24 
25 #include "common/scummsys.h"
26 #include "common/mutex.h"
27 #include "scumm/sound.h"
28 #include "scumm/he/mixer_he.h"
29 #include "audio/audiostream.h"
30 
31 namespace Scumm {
32 
33 #define HSND_DYN_SOUND_CHAN -1
34 #define HSND_TALKIE_SLOT 1
35 #define HSND_SOUND_STOPPED 1
36 #define HSND_SOUND_ENDED 2
37 #define HSND_SOUND_TIMEOUT 3
38 #define HSND_TIMER_SLOT 4
39 #define HSND_MAX_CALLBACK_SCRIPTS 20
40 #define HSND_MAX_CHANNELS 8
41 #define HSND_CHANNEL_0 10000
42 #define HSND_CHANNEL_1 10001
43 #define HSND_CHANNEL_2 10002
44 #define HSND_CHANNEL_3 10003
45 #define HSND_CHANNEL_4 10004
46 #define HSND_CHANNEL_5 10005
47 #define HSND_CHANNEL_6 10006
48 #define HSND_CHANNEL_7 10007
49 #define HSND_MAX_SOUND_VARS 26
50 #define HSND_DEFAULT_FREQUENCY 11025
51 #define HSND_BASE_FREQ_FACTOR 1024
52 #define HSND_SOUND_FREQ_BASE 1024
53 #define HSND_MAX_VOLUME 255
54 #define HSND_SOUND_PAN_LEFT 0
55 #define HSND_SOUND_PAN_CENTER 64
56 #define HSND_SOUND_PAN_RIGHT 127
57 #define HSND_FIRST_SPOOLING_SOUND 4000
58 #define HSND_MAX_FREQ_RATIO 4
59 
60 #define HSND_MAX_SPOOLING_CODE_SIZE 16384
61 
62 #define HSND_SBNG_TYPE_ALL 0xF8
63 #define HSND_SBNG_DATA_ALL 0x07
64 
65 #define HSND_SBNG_MAGIC_NUMBER 0x2000
66 #define HSND_SBNG_MAGIC_MASK 0xF000
67 
68 #define HSND_SBNG_END 0x00
69 #define HSND_SBNG_FACE 0x10
70 #define HSND_SBNG_SET_SET 0x20
71 #define HSND_SBNG_SET_ADD 0x30
72 #define HSND_SBNG_SET_SUB 0x38
73 #define HSND_SBNG_SET_MUL 0x40
74 #define HSND_SBNG_SET_DIV 0x50
75 #define HSND_SBNG_SET_INC 0x60
76 #define HSND_SBNG_SET_DEC 0x68
77 #define HSND_SBNG_VARORVAL 0x03
78 #define HSND_SBNG_VARVAL 0x02
79 
80 #define HSND_SNDVAR_TOKENS 26
81 
82 #define XSH2_FLAG_HAS_PRIORITY 0x01
83 
84 #define WAVE_FORMAT_PCM 1
85 #define WAVE_FORMAT_IMA_ADPCM 17
86 #define WAVE_RIFF_HEADER_LEN 44
87 
88 #define HSND_RES_OFFSET_ID1 0 // uint32, DIGI or MIDI header
89 #define HSND_RES_OFFSET_LEN1 4 // uint32
90 #define HSND_RES_OFFSET_ID 8 // uint32, HSHD header
91 #define HSND_RES_OFFSET_LEN2 12 // uint32
92 #define HSND_RES_OFFSET_COMPRESSED 16 // uint8, header data
93 #define HSND_RES_OFFSET_FORMATTED 17 // uint8
94 #define HSND_RES_OFFSET_KILL_PRIO 18 // uint8
95 #define HSND_RES_OFFSET_DEAD_PRIO 19 // uint8
96 #define HSND_RES_OFFSET_LEFT_VOLUME 20 // uint8
97 #define HSND_RES_OFFSET_RIGHT_VOLUME 21 // uint8
98 #define HSND_RES_OFFSET_FREQUENCY 22 // uint16
99 #define HSND_RES_OFFSET_MONDO_OFFSET 24 // uint32
100 #define HSND_RES_OFFSET_BITS_PER_SAMPLE 28 // uint8
101 #define HSND_RES_OFFSET_SAMPLE_CHANNELS 29 // uint8
102 #define HSND_RES_OFFSET_UNUSED3 30 // uint8
103 #define HSND_RES_OFFSET_UNUSED4 31 // uint8
104 #define HSND_RES_OFFSET_ID3 32 // uint32, SDAT header
105 #define HSND_RES_OFFSET_LEN3 36 // uint32
106 #define HSND_RES_OFFSET_SOUND_DATA 40
107 
108 // Used both in SoundHE and HEMixer
110  HESoundModifiers(int mFrequencyShift, int mPan, int mVolume) {
111  // Hey, turns out Moonbase Commander just LOVES sending out invalid modifiers :-)
112  /*
113  assert(mFrequencyShift >= HSND_SOUND_FREQ_BASE / HSND_MAX_FREQ_RATIO);
114  assert(mFrequencyShift <= HSND_SOUND_FREQ_BASE * HSND_MAX_FREQ_RATIO);
115  assert(mPan >= HSND_SOUND_PAN_LEFT && mPan <= HSND_SOUND_PAN_RIGHT);
116  assert(mVolume >= 0 && mVolume <= HSND_MAX_VOLUME);
117  */
118 
119  frequencyShift = mFrequencyShift;
120  pan = mPan;
121  volume = mVolume;
122  }
123 
124  HESoundModifiers() {
125  frequencyShift = HSND_SOUND_FREQ_BASE;
126  pan = HSND_SOUND_PAN_CENTER;
127  volume = HSND_MAX_VOLUME;
128  }
129 
130  int frequencyShift;
131  int pan;
132  int volume;
133 };
134 
135 
137  int32 song;
138  int32 offset;
139  int32 size;
140 
141  char filename[128];
142 };
143 
144 class ScummEngine_v60he;
145 class HEMixer;
146 
147 class SoundHE : public Sound {
148  friend class HEMixer;
149 
150 protected:
151  ScummEngine_v60he *_vm;
152 
153  int _overrideFreq;
154  Common::Mutex *_mutex;
155  HEMixer *_heMixer;
156 
158  int32 sound;
159  int32 channel;
160  int32 whatFrame;
161  };
162  HESoundCallbackItem _soundCallbackScripts[HSND_MAX_CALLBACK_SCRIPTS];
163 
164  HESpoolingMusicItem *_heSpoolingMusicTable;
165 
166  struct PCMWaveFormat {
167  uint16 wFormatTag;
168  uint16 wChannels;
169  uint32 dwSamplesPerSec;
170  uint32 dwAvgBytesPerSec;
171  uint16 wBlockAlign;
172  uint16 wBitsPerSample;
173  };
174 
175  int32 _heSpoolingMusicCount;
176  Common::File _heSpoolingMusicFile;
177  byte _heSpoolingCodeBuffer[HSND_MAX_SPOOLING_CODE_SIZE];
178 
179 public: // Used by createSound()
180  struct {
181  int sound;
182  int codeOffset;
183  byte *codeBuffer;
184  int priority;
185  int frequency;
186  int timeout;
187  bool hasSoundTokens;
188  int soundVars[HSND_MAX_SOUND_VARS];
189  int age;
190 
191  void clearChannel() {
192  sound = 0;
193  codeOffset = 0;
194  codeBuffer = nullptr;
195  priority = 0;
196  frequency = 0;
197  timeout = 0;
198  hasSoundTokens = false;
199  memset(soundVars, 0, sizeof(soundVars));
200  age = 0;
201  }
202 
203  } _heChannel[HSND_MAX_CHANNELS];
204 
205  // Used throughout script functions
206  int32 _createSndId;
207  int32 _createSndLastAppend;
208  int32 _createSndLastPos;
209  int32 _baseSndSize;
210 
211 public:
212  SoundHE(ScummEngine *parent, Audio::Mixer *mixer, Common::Mutex *mutex);
213  ~SoundHE() override;
214 
215  void startSound(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
216  void addSoundToQueue(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
217  void modifySound(int sound, int offset, int frequencyShift, int pan, int volume, int flags) override;
218 
219  int isSoundRunning(int sound) const override;
220  bool isSoundInUse(int sound) const override;
221  void stopSound(int sound) override;
222  void stopAllSounds() override;
223  int hsFindSoundChannel(int sound) const;
224  void setupSound() override;
225  void pauseSounds(bool pause) override;
226 
227  bool getHEMusicDetails(int id, int &musicOffs, int &musicSize);
228  int getNextDynamicChannel();
229  bool isSoundCodeUsed(int sound);
230  int getSoundPosition(int sound);
231  int getSoundVar(int sound, int var);
232  void setSoundVar(int sound, int var, int val);
233  void setSoundVolume(int sound, int volume);
234  void triggerSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
235  void triggerSpoolingSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
236  void triggerDigitalSound(int soundId, int heOffset, int heChannel, int heFlags);
237  void triggerMidiSound(int soundId, int heOffset);
238  void triggerRIFFSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
239  void triggerXSOUSound(int soundId, int heOffset, int heChannel, int heFlags);
240 
241  void hsStartDigitalSound(int sound, int offset, byte *addr, int sound_data, int globType, int globNum,
242  int sampleCount, int frequency, int channel, int priority, int soundCode,
243  int flags, int bitsPerSample, int soundChannelCount, HESoundModifiers modifiers);
244  void hsStopDigitalSound(int sound);
245 
246  void handleSoundFrame();
247  void feedMixer();
248  void unqueueSoundCallbackScripts();
249  void checkSoundTimeouts();
250  void digitalSoundCallback(int message, int channel, bool earlyCallback = false);
251  void queueSoundCallbackScript(int sound, int channel, int message);
252  void runSoundCode();
253  void processSoundOpcodes(int sound, byte *codePtr, int *soundVars);
254  void setOverrideFreq(int freq);
255  void setupHEMusicFile();
256  void playVoice(uint32 offset, uint32 length);
257  void playVoiceFile(char *filename);
258  void stopDigitalSound(int sound);
259  void createSound(int snd1id, int snd2id);
260  int getChannelPosition(int channel);
261 
262  const byte *findWavBlock(uint32 tag, const byte *block);
263  int getCurrentSpeechOffset();
264  bool is3DOSound(int sound) const;
265 
266 protected:
267  void processSoundQueues() override;
268 
269 private:
270  int _heTalkOffset = 0;
271  bool _stopActorTalkingFlag = false;
272  bool _inSoundCallbackFlag = false;
273  int _soundCallbacksQueueSize = 0;
274  int _soundAlreadyInQueueCount = 0;
275  int _inUnqueueCallbackScripts = 0;
276  int _soundsDebugFrameCounter = 0;
277  int _dynamicSoundAgeCounter = 0;
278 };
279 
280 
281 } // End of namespace Scumm
282 
283 #endif
Definition: sound_he.h:147
Definition: sound.h:59
Definition: scumm.h:518
Definition: intern_he.h:49
Definition: mixer.h:59
Definition: file.h:47
Definition: mixer_he.h:120
Definition: mutex.h:67
Definition: sound_he.h:109
Definition: sound_he.h:166
Definition: sound_he.h:157
Definition: actor.h:30
Definition: sound_he.h:136