File: sound_he.h

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (283 lines) | stat: -rw-r--r-- 8,992 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef SCUMM_HE_SOUND_HE_H
#define SCUMM_HE_SOUND_HE_H

#include "common/scummsys.h"
#include "common/mutex.h"
#include "scumm/sound.h"
#include "scumm/he/mixer_he.h"
#include "audio/audiostream.h"

namespace Scumm {

#define HSND_DYN_SOUND_CHAN      -1
#define HSND_TALKIE_SLOT          1
#define HSND_SOUND_STOPPED        1
#define HSND_SOUND_ENDED          2
#define HSND_SOUND_TIMEOUT        3
#define HSND_TIMER_SLOT           4
#define HSND_MAX_CALLBACK_SCRIPTS 20
#define HSND_MAX_CHANNELS         8
#define HSND_CHANNEL_0            10000
#define HSND_CHANNEL_1            10001
#define HSND_CHANNEL_2            10002
#define HSND_CHANNEL_3            10003
#define HSND_CHANNEL_4            10004
#define HSND_CHANNEL_5            10005
#define HSND_CHANNEL_6            10006
#define HSND_CHANNEL_7            10007
#define HSND_MAX_SOUND_VARS       26
#define HSND_DEFAULT_FREQUENCY    11025
#define HSND_BASE_FREQ_FACTOR     1024
#define HSND_SOUND_FREQ_BASE      1024
#define HSND_MAX_VOLUME           255
#define HSND_SOUND_PAN_LEFT       0
#define HSND_SOUND_PAN_CENTER     64
#define HSND_SOUND_PAN_RIGHT      127
#define HSND_FIRST_SPOOLING_SOUND 4000
#define HSND_MAX_FREQ_RATIO       4

#define HSND_MAX_SPOOLING_CODE_SIZE 16384

#define HSND_SBNG_TYPE_ALL 0xF8
#define HSND_SBNG_DATA_ALL 0x07

#define HSND_SBNG_MAGIC_NUMBER 0x2000
#define HSND_SBNG_MAGIC_MASK   0xF000

#define HSND_SBNG_END      0x00
#define HSND_SBNG_FACE     0x10
#define HSND_SBNG_SET_SET  0x20
#define HSND_SBNG_SET_ADD  0x30
#define HSND_SBNG_SET_SUB  0x38
#define HSND_SBNG_SET_MUL  0x40
#define HSND_SBNG_SET_DIV  0x50
#define HSND_SBNG_SET_INC  0x60
#define HSND_SBNG_SET_DEC  0x68
#define HSND_SBNG_VARORVAL 0x03
#define HSND_SBNG_VARVAL   0x02

#define HSND_SNDVAR_TOKENS 26

#define XSH2_FLAG_HAS_PRIORITY 0x01

#define WAVE_FORMAT_PCM       1
#define WAVE_FORMAT_IMA_ADPCM 17
#define WAVE_RIFF_HEADER_LEN  44

#define HSND_RES_OFFSET_ID1              0 // uint32, DIGI or MIDI header
#define HSND_RES_OFFSET_LEN1             4 // uint32
#define HSND_RES_OFFSET_ID               8 // uint32, HSHD header
#define HSND_RES_OFFSET_LEN2            12 // uint32
#define HSND_RES_OFFSET_COMPRESSED      16 // uint8, header data
#define HSND_RES_OFFSET_FORMATTED       17 // uint8
#define HSND_RES_OFFSET_KILL_PRIO       18 // uint8
#define HSND_RES_OFFSET_DEAD_PRIO       19 // uint8
#define HSND_RES_OFFSET_LEFT_VOLUME     20 // uint8
#define HSND_RES_OFFSET_RIGHT_VOLUME    21 // uint8
#define HSND_RES_OFFSET_FREQUENCY       22 // uint16
#define HSND_RES_OFFSET_MONDO_OFFSET    24 // uint32
#define HSND_RES_OFFSET_BITS_PER_SAMPLE 28 // uint8
#define HSND_RES_OFFSET_SAMPLE_CHANNELS 29 // uint8
#define HSND_RES_OFFSET_UNUSED3         30 // uint8
#define HSND_RES_OFFSET_UNUSED4         31 // uint8
#define HSND_RES_OFFSET_ID3             32 // uint32, SDAT header
#define HSND_RES_OFFSET_LEN3            36 // uint32
#define HSND_RES_OFFSET_SOUND_DATA      40

// Used both in SoundHE and HEMixer
struct HESoundModifiers {
	HESoundModifiers(int mFrequencyShift, int mPan, int mVolume) {
		// Hey, turns out Moonbase Commander just LOVES sending out invalid modifiers :-)
		/*
		assert(mFrequencyShift >= HSND_SOUND_FREQ_BASE / HSND_MAX_FREQ_RATIO);
		assert(mFrequencyShift <= HSND_SOUND_FREQ_BASE * HSND_MAX_FREQ_RATIO);
		assert(mPan >= HSND_SOUND_PAN_LEFT && mPan <= HSND_SOUND_PAN_RIGHT);
		assert(mVolume >= 0 && mVolume <= HSND_MAX_VOLUME);
		*/

		frequencyShift = mFrequencyShift;
		pan = mPan;
		volume = mVolume;
	}

	HESoundModifiers() {
		frequencyShift = HSND_SOUND_FREQ_BASE;
		pan = HSND_SOUND_PAN_CENTER;
		volume = HSND_MAX_VOLUME;
	}

	int frequencyShift;
	int pan;
	int volume;
};


struct HESpoolingMusicItem {
	int32 song;
	int32 offset;
	int32 size;

	char filename[128];
};

class ScummEngine_v60he;
class HEMixer;

class SoundHE : public Sound {
	friend class HEMixer;

protected:
	ScummEngine_v60he *_vm;

	int _overrideFreq;
	Common::Mutex *_mutex;
	HEMixer *_heMixer;

	struct HESoundCallbackItem {
		int32 sound;
		int32 channel;
		int32 whatFrame;
	};
	HESoundCallbackItem _soundCallbackScripts[HSND_MAX_CALLBACK_SCRIPTS];

	HESpoolingMusicItem *_heSpoolingMusicTable;

	struct PCMWaveFormat {
		uint16 wFormatTag;
		uint16 wChannels;
		uint32 dwSamplesPerSec;
		uint32 dwAvgBytesPerSec;
		uint16 wBlockAlign;
		uint16 wBitsPerSample;
	};

	int32 _heSpoolingMusicCount;
	Common::File _heSpoolingMusicFile;
	byte _heSpoolingCodeBuffer[HSND_MAX_SPOOLING_CODE_SIZE];

public: // Used by createSound()
	struct {
		int sound;
		int codeOffset;
		byte *codeBuffer;
		int priority;
		int frequency;
		int timeout;
		bool hasSoundTokens;
		int soundVars[HSND_MAX_SOUND_VARS];
		int age;

		void clearChannel() {
			sound = 0;
			codeOffset = 0;
			codeBuffer = nullptr;
			priority = 0;
			frequency = 0;
			timeout = 0;
			hasSoundTokens = false;
			memset(soundVars, 0, sizeof(soundVars));
			age = 0;
		}

	} _heChannel[HSND_MAX_CHANNELS];

	// Used throughout script functions
	int32 _createSndId;
	int32 _createSndLastAppend;
	int32 _createSndLastPos;
	int32 _baseSndSize;

public:
	SoundHE(ScummEngine *parent, Audio::Mixer *mixer, Common::Mutex *mutex);
	~SoundHE() override;

	void startSound(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
	void addSoundToQueue(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
	void modifySound(int sound, int offset, int frequencyShift, int pan, int volume, int flags) override;

	int isSoundRunning(int sound) const override;
	bool isSoundInUse(int sound) const override;
	void stopSound(int sound) override;
	void stopAllSounds() override;
	int hsFindSoundChannel(int sound) const;
	void setupSound() override;
	void pauseSounds(bool pause) override;

	bool getHEMusicDetails(int id, int &musicOffs, int &musicSize);
	int getNextDynamicChannel();
	bool isSoundCodeUsed(int sound);
	int getSoundPosition(int sound);
	int getSoundVar(int sound, int var);
	void setSoundVar(int sound, int var, int val);
	void setSoundVolume(int sound, int volume);
	void triggerSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
	void triggerSpoolingSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
	void triggerDigitalSound(int soundId, int heOffset, int heChannel, int heFlags);
	void triggerMidiSound(int soundId, int heOffset);
	void triggerRIFFSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
	void triggerXSOUSound(int soundId, int heOffset, int heChannel, int heFlags);

	void hsStartDigitalSound(int sound, int offset, byte *addr, int sound_data, int globType, int globNum,
							 int sampleCount, int frequency, int channel, int priority, int soundCode,
							 int flags, int bitsPerSample, int soundChannelCount, HESoundModifiers modifiers);
	void hsStopDigitalSound(int sound);

	void handleSoundFrame();
	void feedMixer();
	void unqueueSoundCallbackScripts();
	void checkSoundTimeouts();
	void digitalSoundCallback(int message, int channel, bool earlyCallback = false);
	void queueSoundCallbackScript(int sound, int channel, int message);
	void runSoundCode();
	void processSoundOpcodes(int sound, byte *codePtr, int *soundVars);
	void setOverrideFreq(int freq);
	void setupHEMusicFile();
	void playVoice(uint32 offset, uint32 length);
	void playVoiceFile(char *filename);
	void stopDigitalSound(int sound);
	void createSound(int snd1id, int snd2id);
	int getChannelPosition(int channel);

	const byte *findWavBlock(uint32 tag, const byte *block);
	int getCurrentSpeechOffset();
	bool is3DOSound(int sound) const;

protected:
	void processSoundQueues() override;

private:
	int _heTalkOffset = 0;
	bool _stopActorTalkingFlag = false;
	bool _inSoundCallbackFlag = false;
	int _soundCallbacksQueueSize = 0;
	int _soundAlreadyInQueueCount = 0;
	int _inUnqueueCallbackScripts = 0;
	int _soundsDebugFrameCounter = 0;
	int _dynamicSoundAgeCounter = 0;
};


} // End of namespace Scumm

#endif