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  * Additional copyright for this file:
8  * Copyright (C) 1994-1998 Revolution Software Ltd.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24 
25 /*****************************************************************************
26  *		SOUND.H		Sound engine
27  *
28  *		SOUND.CPP Contains the sound engine, fx & music functions
29  *		Some very 'sound' code in here ;)
30  *
31  *		(16Dec96 JEL)
32  *
33  ****************************************************************************/
34 
35 #ifndef SWORD2_SOUND_H
36 #define SWORD2_SOUND_H
37 
38 #include "common/file.h"
39 #include "common/mutex.h"
40 #include "audio/audiostream.h"
41 #include "audio/mixer.h"
42 
43 // Max number of sound fx
44 #define MAXMUS 2
45 
46 // Max number of fx in queue at once
47 #define FXQ_LENGTH 32
48 
49 #define BUFFER_SIZE 4096
50 
51 namespace Sword2 {
52 
53 enum {
54 	kCLUMode = 1,
55 	kMP3Mode,
56 	kVorbisMode,
57 	kFLACMode
58 };
59 
60 enum {
61 	kLeadInSound,
62 	kLeadOutSound
63 };
64 
65 enum {
66 	// These three types correspond to types set by the scripts
67 	FX_SPOT		= 0,
68 	FX_LOOP		= 1,
69 	FX_RANDOM	= 2,
70 
71 	// These are used for FX queue bookkeeping
72 	FX_SPOT2	= 3,
73 	FX_LOOPING	= 4
74 };
75 
76 // Sound defines
77 
78 enum {
79 	RDSE_SAMPLEFINISHED		= 0,
80 	RDSE_SAMPLEPLAYING		= 1,
81 	RDSE_FXTOCLEAR			= 0,		// Unused
82 	RDSE_FXCACHED			= 1,		// Unused
83 	RDSE_FXSPOT			= 0,
84 	RDSE_FXLOOP			= 1,
85 	RDSE_FXLEADIN			= 2,
86 	RDSE_FXLEADOUT			= 3,
87 	RDSE_QUIET			= 1,
88 	RDSE_SPEAKING			= 0
89 };
90 
91 class CLUInputStream : public Audio::AudioStream {
92 private:
93 	Common::File *_file;
94 	bool _firstTime;
95 	uint32 _file_pos;
96 	uint32 _end_pos;
97 	int16 _outbuf[BUFFER_SIZE];
98 	byte _inbuf[BUFFER_SIZE];
99 	const int16 *_bufferEnd;
100 	const int16 *_pos;
101 
102 	uint16 _prev;
103 
104 	void refill();
105 
eosIntern()106 	inline bool eosIntern() const {
107 		return !_file->isOpen() || _pos >= _bufferEnd;
108 	}
109 
110 public:
111 	CLUInputStream(Common::File *file, int size);
112 	~CLUInputStream() override;
113 
114 	int readBuffer(int16 *buffer, const int numSamples) override;
115 
endOfData()116 	bool endOfData() const override	{ return eosIntern(); }
isStereo()117 	bool isStereo() const override	{ return false; }
getRate()118 	int getRate() const override	{ return 22050; }
119 };
120 
121 struct SoundFileHandle {
122 	Common::File file;
123 	uint32 *idxTab;
124 	uint32 idxLen;
125 	int32 fileSize;
126 	uint32 fileType;
127 	volatile bool inUse;
128 };
129 
130 class MusicInputStream : public Audio::AudioStream {
131 private:
132 	int _cd;
133 	SoundFileHandle *_fh;
134 	uint32 _musicId;
135 	Audio::AudioStream *_decoder;
136 	int16 _buffer[BUFFER_SIZE];
137 	const int16 *_bufferEnd;
138 	const int16 *_pos;
139 	bool _remove;
140 	uint32 _numSamples;
141 	uint32 _samplesLeft;
142 	bool _looping;
143 	int32 _fading;
144 	int32 _fadeSamples;
145 
146 	void refill();
147 
eosIntern()148 	inline bool eosIntern() const {
149 		if (_looping)
150 			return false;
151 		return _remove || _pos >= _bufferEnd;
152 	}
153 
154 public:
155 	MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping);
156 	~MusicInputStream() override;
157 
158 	int readBuffer(int16 *buffer, const int numSamples) override;
159 
endOfData()160 	bool endOfData() const override	{ return eosIntern(); }
isStereo()161 	bool isStereo() const override	{ return _decoder->isStereo(); }
getRate()162 	int getRate() const override	{ return _decoder->getRate(); }
163 
getCD()164 	int getCD()		{ return _cd; }
165 
166 	void fadeUp();
167 	void fadeDown();
168 
isReady()169 	bool isReady()		{ return _decoder != NULL; }
isFading()170 	int32 isFading()	{ return _fading; }
171 
172 	bool readyToRemove();
173 	int32 getTimeRemaining();
174 };
175 
176 class Sound : public Audio::AudioStream {
177 private:
178 	Sword2Engine *_vm;
179 
180 	Common::Mutex _mutex;
181 
182 	Audio::SoundHandle _mixerSoundHandle;
183 	Audio::SoundHandle _leadInHandle;
184 	Audio::SoundHandle _leadOutHandle;
185 
186 	struct FxQueueEntry {
187 		Audio::SoundHandle handle;	// sound handle
188 		uint32 resource;		// resource id of sample
189 		byte *data;			// pointer to WAV data
190 		uint32 len;			// WAV data length
191 		uint16 delay;			// cycles to wait before playing (or 'random chance' if FX_RANDOM)
192 		uint8 volume;			// sound volume
193 		int8 pan;			// sound panning
194 		uint8 type;			// FX_SPOT, FX_RANDOM, FX_LOOP
195 	};
196 
197 	FxQueueEntry _fxQueue[FXQ_LENGTH];
198 
199 	void triggerFx(uint8 i);
200 
201 	bool _reverseStereo;
202 
203 	bool _speechMuted;
204 	bool _fxMuted;
205 	bool _musicMuted;
206 
207 	bool _speechPaused;
208 	bool _fxPaused;
209 	bool _musicPaused;
210 
211 	int32 _loopingMusicId;
212 
213 	Audio::SoundHandle _soundHandleSpeech;
214 
215 	MusicInputStream *_music[MAXMUS];
216 	SoundFileHandle _musicFile[MAXMUS];
217 	SoundFileHandle _speechFile[MAXMUS];
218 
219 	int16 *_mixBuffer;
220 	int _mixBufferLen;
221 
222 public:
223 	Sound(Sword2Engine *vm);
224 	~Sound() override;
225 
226 	// AudioStream API
227 
228 	int readBuffer(int16 *buffer, const int numSamples) override;
isStereo()229 	bool isStereo() const override { return false; }
230 	bool endOfData() const override;
getRate()231 	int getRate() const override { return Sword2Engine::isPsx() ? 11025 : 22050; }
232 
233 	// End of AudioStream API
234 
235 	void clearFxQueue(bool killMovieSounds);
236 	void processFxQueue();
237 
238 	void setReverseStereo(bool reverse);
isReverseStereo()239 	bool isReverseStereo() const { return _reverseStereo; }
240 
241 	void muteSpeech(bool mute);
isSpeechMute()242 	bool isSpeechMute() const { return _speechMuted; }
243 
244 	void muteFx(bool mute);
isFxMute()245 	bool isFxMute() const { return _fxMuted; }
246 
muteMusic(bool mute)247 	void muteMusic(bool mute) { _musicMuted = mute; }
isMusicMute()248 	bool isMusicMute() const { return _musicMuted; }
249 
setLoopingMusicId(int32 id)250 	void setLoopingMusicId(int32 id) { _loopingMusicId = id; }
getLoopingMusicId()251 	int32 getLoopingMusicId() const { return _loopingMusicId; }
252 
253 	void pauseSpeech();
254 	void unpauseSpeech();
255 
256 	void pauseFx();
257 	void unpauseFx();
258 
259 	void pauseMusic();
260 	void unpauseMusic();
261 
262 	void playMovieSound(int32 res, int type);
263 	void stopMovieSounds();
264 
265 	void queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan);
266 	int32 playFx(FxQueueEntry *fx);
267 	int32 playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType);
268 	int32 stopFx(int32 i);
269 	int32 setFxIdVolumePan(int32 id, int vol, int pan = 255);
270 
271 	int32 getSpeechStatus();
272 	int32 amISpeaking();
273 	int32 playCompSpeech(uint32 speechId, uint8 vol, int8 pan);
274 	int32 stopSpeech();
275 
276 	int32 streamCompMusic(uint32 musicId, bool loop);
277 	void stopMusic(bool immediately);
278 	int32 musicTimeRemaining();
279 
280 	void printFxQueue();
281 };
282 
283 } // End of namespace Sword2
284 
285 #endif
286