aboutsummaryrefslogtreecommitdiff
path: root/engines/neverhood/sound.h
blob: 0733346daa067cde1fac81002e1abc91316f3523 (plain)
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
284
285
286
287
288
289
290
/* 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef NEVERHOOD_SOUND_H
#define NEVERHOOD_SOUND_H

#include "audio/audiostream.h"
#include "common/array.h"
#include "graphics/surface.h"
#include "neverhood/neverhood.h"
#include "neverhood/resource.h"

namespace Neverhood {

// Convert volume from percent to 0..255
#define VOLUME(volume) (Audio::Mixer::kMaxChannelVolume / 100 * (volume))

// Convert panning from percent (50% equals center) to -127..0..+127
#define PANNING(panning) (254 / 100 * (panning) - 127)

class AudioResourceManSoundItem;
class AudioResourceManMusicItem;
class AudioResourceMan;

class SoundResource {
public:
	SoundResource(NeverhoodEngine *vm);
	~SoundResource();
	bool isPlaying();
	void load(uint32 fileHash);
	void unload();
	void play(uint32 fileHash);
	void play();
	void stop();
	void setVolume(int16 volume);
	void setPan(int16 pan);
protected:
	NeverhoodEngine *_vm;
	int16 _soundIndex;
	AudioResourceManSoundItem *getSoundItem();
};

class MusicResource {
public:
	MusicResource(NeverhoodEngine *vm);
	bool isPlaying();
	void load(uint32 fileHash);
	void unload();
	void play(int16 fadeVolumeStep);
	void stop(int16 fadeVolumeStep);
	void setVolume(int16 volume);
protected:
	NeverhoodEngine *_vm;
	int16 _musicIndex;
	AudioResourceManMusicItem *getMusicItem();
};

class MusicItem {
public:
	MusicItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 musicFileHash);
	~MusicItem();
	void startMusic(int16 countdown, int16 fadeVolumeStep);
	void stopMusic(int16 countdown, int16 fadeVolumeStep);
	void update();
	uint32 getGroupNameHash() const { return _groupNameHash; }
	uint32 getFileHash() const { return _fileHash; }
protected:
	NeverhoodEngine *_vm;
	uint32 _groupNameHash;
	uint32 _fileHash;
	bool _play;
	bool _stop;
	int16 _fadeVolumeStep;
	int16 _countdown;
	MusicResource *_musicResource;
};

class SoundItem {
public:
	SoundItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 soundFileHash,
		bool playOnceAfterRandomCountdown, int16 minCountdown, int16 maxCountdown,
		bool playOnceAfterCountdown, int16 initialCountdown, bool playLooping, int16 currCountdown);
	~SoundItem();
	void setSoundParams(bool playOnceAfterRandomCountdown, int16 minCountdown, int16 maxCountdown,
		int16 firstMinCountdown, int16 firstMaxCountdown);
	void playSoundLooping();
	void stopSound();
	void setVolume(int volume);
	void update();
	void setPlayOnceAfterCountdown(bool playOnceAfterCountdown) { _playOnceAfterCountdown = playOnceAfterCountdown; }
	uint32 getGroupNameHash() const { return _groupNameHash; }
	uint32 getFileHash() const { return _fileHash; }
	int16 getCurrCountdown() const { return _currCountdown; }
protected:
	NeverhoodEngine *_vm;
	uint32 _groupNameHash;
	uint32 _fileHash;
	bool _playOnceAfterRandomCountdown;
	int16 _minCountdown;
	int16 _maxCountdown;
	bool _playOnceAfterCountdown;
	int16 _initialCountdown;
	bool _playLooping;
	int16 _currCountdown;
	SoundResource *_soundResource;
};

class SoundMan {
public:
	SoundMan(NeverhoodEngine *vm);
	~SoundMan();

	void stopAllSounds();

	// Music
	void addMusic(uint32 groupNameHash, uint32 musicFileHash);
	void deleteMusic(uint32 musicFileHash);
	void startMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep);
	void stopMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep);

	// Sound
	void addSound(uint32 groupNameHash, uint32 soundFileHash);
	void addSoundList(uint32 groupNameHash, const uint32 *soundFileHashList);
	void deleteSound(uint32 soundFileHash);
	void setSoundParams(uint32 soundFileHash, bool playOnceAfterRandomCountdown,
		int16 minCountdown, int16 maxCountdown, int16 firstMinCountdown, int16 firstMaxCountdown);
	void setSoundListParams(const uint32 *soundFileHashList, bool playOnceAfterRandomCountdown,
		int16 minCountdown, int16 maxCountdown, int16 firstMinCountdown, int16 firstMaxCountdown);
	void playSoundLooping(uint32 soundFileHash);
	void stopSound(uint32 soundFileHash);
	void setSoundVolume(uint32 soundFileHash, int volume);

	// Misc
	void update();
	void deleteGroup(uint32 groupNameHash);
	void deleteMusicGroup(uint32 groupNameHash);
	void deleteSoundGroup(uint32 groupNameHash);
	void playTwoSounds(uint32 groupNameHash, uint32 soundFileHash1, uint32 soundFileHash2, int16 initialCountdown);
	void playSoundThree(uint32 groupNameHash, uint32 soundFileHash);
	void setTwoSoundsPlayFlag(bool playOnceAfterCountdown);
	void setSoundThreePlayFlag(bool playOnceAfterCountdown);

protected:
	NeverhoodEngine *_vm;

	// TODO Find out what these special sounds are used for (door sounds?)
	int _soundIndex1, _soundIndex2;
	int16 _initialCountdown;
	bool _playOnceAfterCountdown;

	int _soundIndex3;
	int16 _initialCountdown3;
	bool _playOnceAfterCountdown3;

	Common::Array<MusicItem*> _musicItems;
	Common::Array<SoundItem*> _soundItems;

	MusicItem *getMusicItemByHash(uint32 musicFileHash);
	SoundItem *getSoundItemByHash(uint32 soundFileHash);
	int16 addMusicItem(MusicItem *musicItem);
	int16 addSoundItem(SoundItem *soundItem);
	void deleteSoundByIndex(int index);

};

class NeverhoodAudioStream : public Audio::AudioStream {
public:
	NeverhoodAudioStream(int rate, byte shiftValue, bool isLooping, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream);
	~NeverhoodAudioStream();
	int readBuffer(int16 *buffer, const int numSamples);
	bool isStereo() const  { return _isStereo; }
	bool endOfData() const { return _endOfData; }
	int getRate() const { return _rate; }
private:
	const int _rate;
	const bool _isLooping;
	const bool _isStereo;
	const byte _shiftValue;
	const bool _isCompressed;
	int16 _prevValue;
	Common::DisposablePtr<Common::SeekableReadStream> _stream;
	bool _endOfData;
	byte *_buffer;
	enum {
		kSampleBufferLength = 2048
	};
	int fillBuffer(int maxSamples);
};

// TODO Rename these

class AudioResourceManSoundItem {
public:
	AudioResourceManSoundItem(NeverhoodEngine *vm, uint32 fileHash);
	void loadSound();
	void unloadSound();
	void setVolume(int16 volume);
	void setPan(int16 pan);
	void playSound(bool looping);
	void stopSound();
	bool isPlaying();
protected:
	NeverhoodEngine *_vm;
	uint32 _fileHash;
	ResourceHandle _resourceHandle;
	const byte *_data;
	bool _isLoaded;
	bool _isPlaying;
	int16 _volume;
	int16 _panning;
	Audio::SoundHandle _soundHandle;
};

class AudioResourceManMusicItem {
public:
	AudioResourceManMusicItem(NeverhoodEngine *vm, uint32 fileHash);
	void playMusic(int16 fadeVolumeStep);
	void stopMusic(int16 fadeVolumeStep);
	void unloadMusic();
	void setVolume(int16 volume);
	void restart();
	void update();
	bool isPlaying() const { return _isPlaying; }
	bool canRestart() const { return _canRestart; }
	bool isTerminated() const { return _terminate; }
	uint32 getFileHash() const { return _fileHash; }
protected:
	NeverhoodEngine *_vm;
	uint32 _fileHash;
	bool _isPlaying;
	bool _canRestart;
	bool _terminate;
	int16 _volume;
	int16 _panning;
	bool _start;
	bool _isFadingIn;
	bool _isFadingOut;
	int16 _fadeVolume;
	int16 _fadeVolumeStep;
	Audio::SoundHandle _soundHandle;
};

class AudioResourceMan {
public:
	AudioResourceMan(NeverhoodEngine *vm);
	~AudioResourceMan();

	void stopAllSounds();

	int16 addSound(uint32 fileHash);
	void removeSound(int16 soundIndex);

	int16 loadMusic(uint32 fileHash);
	void updateMusic();

	AudioResourceManSoundItem *getSoundItem(int16 index);
	AudioResourceManMusicItem *getMusicItem(int16 index);

protected:
	NeverhoodEngine *_vm;

	Common::Array<AudioResourceManMusicItem*> _musicItems;
	Common::Array<AudioResourceManSoundItem*> _soundItems;

	int16 addSoundItem(AudioResourceManSoundItem *soundItem);

};

} // End of namespace Neverhood

#endif /* NEVERHOOD_SOUND_H */