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
31namespace 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
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
145class HEMixer;
146
147class SoundHE : public Sound {
148 friend class HEMixer;
149
150protected:
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
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
179public: // 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
211public:
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
266protected:
267 void processSoundQueues() override;
268
269private:
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: mixer.h:70
Definition: file.h:47
Definition: mutex.h:67
Definition: mixer_he.h:125
Definition: intern_he.h:53
Definition: sound_he.h:147
Definition: sound.h:59
Definition: actor.h:30
Definition: sound_he.h:109
Definition: sound_he.h:136
Definition: sound_he.h:157
Definition: sound_he.h:166