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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef KYRA_SOUND_INTERN_H
24 #define KYRA_SOUND_INTERN_H
25 
26 
27 #include "kyra/sound/sound.h"
28 #include "kyra/sound/sound_adlib.h"
29 
30 #include "audio/midiparser.h"
31 #include "audio/softsynth/emumidi.h"
32 #include "audio/softsynth/fmtowns_pc98/towns_audio.h"
33 
34 #include "common/mutex.h"
35 
36 class EuphonyPlayer;
37 class TownsPC98_AudioDriver;
38 
39 namespace Audio {
40 class PCSpeaker;
41 class MaxTrax;
42 } // End of namespace Audio
43 
44 namespace Kyra {
45 
46 class MidiOutput;
47 
48 /**
49  * MIDI output device.
50  *
51  * This device supports both MT-32 MIDI, as used in
52  * Kyrandia 1 and 2, and GM MIDI, as used in Kyrandia 2.
53  */
54 class SoundMidiPC : public Sound {
55 public:
56 	SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver, kType type);
57 	virtual ~SoundMidiPC();
58 
getMusicType()59 	virtual kType getMusicType() const { return _type; }
60 
61 	virtual bool init();
62 
63 	virtual void updateVolumeSettings();
64 
65 	virtual void initAudioResourceInfo(int set, void *info);
66 	virtual void selectAudioResourceSet(int set);
67 	virtual bool hasSoundFile(uint file) const;
68 	virtual void loadSoundFile(uint file);
69 	virtual void loadSoundFile(Common::String file);
70 	virtual void loadSfxFile(Common::String file);
71 
72 	virtual void playTrack(uint8 track);
73 	virtual void haltTrack();
74 	virtual bool isPlaying() const;
75 
76 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
77 	virtual void stopAllSoundEffects();
78 
79 	virtual void beginFadeOut();
80 
81 	virtual void pause(bool paused);
82 private:
83 	static void onTimer(void *data);
84 
85 	// Our channel handling
86 	int _musicVolume, _sfxVolume;
87 
88 	uint32 _fadeStartTime;
89 	bool _fadeMusicOut;
90 
91 	// Midi file related
92 	Common::String _mFileName, _sFileName;
93 	byte *_musicFile, *_sfxFile;
94 
95 	MidiParser *_music;
96 	MidiParser *_sfx[3];
97 
res()98 	const SoundResourceInfo_PC *res() const {return _resInfo[_currentResourceSet]; }
99 	SoundResourceInfo_PC *_resInfo[3];
100 	int _currentResourceSet;
101 
102 	// misc
103 	kType _type;
104 	Common::String getFileName(const Common::String &str);
105 
106 	bool _nativeMT32;
107 	MidiDriver *_driver;
108 	MidiOutput *_output;
109 
110 	Common::Mutex _mutex;
111 };
112 
113 class SoundTowns_LoK : public Sound {
114 public:
115 	SoundTowns_LoK(KyraEngine_v1 *vm, Audio::Mixer *mixer);
116 	virtual ~SoundTowns_LoK();
117 
getMusicType()118 	virtual kType getMusicType() const { return kTowns; }
119 
120 	virtual bool init();
121 	virtual void process();
122 
123 	virtual void initAudioResourceInfo(int set, void *info);
124 	virtual void selectAudioResourceSet(int set);
125 	virtual bool hasSoundFile(uint file) const;
126 	virtual void loadSoundFile(uint file);
loadSoundFile(Common::String)127 	virtual void loadSoundFile(Common::String) {}
128 
129 	virtual void playTrack(uint8 track);
130 	virtual void haltTrack();
131 
132 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
133 	virtual void stopAllSoundEffects();
134 
135 	virtual void beginFadeOut();
136 
137 	virtual void updateVolumeSettings();
138 
139 private:
140 	bool loadInstruments();
141 	void playEuphonyTrack(uint32 offset, int loop);
142 
143 	void fadeOutSoundEffects();
144 
145 	int _lastTrack;
146 	Audio::SoundHandle _sfxHandle;
147 
148 	uint8 *_musicTrackData;
149 
150 	uint _sfxFileIndex;
151 	uint8 *_sfxFileData;
152 	uint8 _sfxChannel;
153 
154 	EuphonyPlayer *_player;
155 
156 	bool _cdaPlaying;
157 
res()158 	const SoundResourceInfo_Towns *res() const {return _resInfo[_currentResourceSet]; }
159 	SoundResourceInfo_Towns *_resInfo[3];
160 	int _currentResourceSet;
161 
162 	const uint8 *_musicFadeTable;
163 	const uint8 *_sfxBTTable;
164 	const uint8 *_sfxWDTable;
165 };
166 
167 class SoundPC98_LoK : public Sound {
168 public:
169 	SoundPC98_LoK(KyraEngine_v1 *vm, Audio::Mixer *mixer);
170 	virtual ~SoundPC98_LoK();
171 
getMusicType()172 	virtual kType getMusicType() const override { return kPC98; }
173 
174 	virtual bool init() override;
175 
176 	virtual void initAudioResourceInfo(int set, void *info) override;
177 	virtual void selectAudioResourceSet(int set) override;
178 	virtual bool hasSoundFile(uint file) const override;
179 	virtual void loadSoundFile(uint file) override;
180 	virtual void loadSoundFile(Common::String file) override;
181 
182 	virtual void playTrack(uint8 track) override;
183 	virtual void haltTrack() override;
184 	virtual void beginFadeOut() override;
185 
voicePlay(const char * file,Audio::SoundHandle * handle,uint8 volume,uint8 priority,bool isSfx)186 	virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; }
187 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
188 
189 	virtual void updateVolumeSettings() override;
190 
191 private:
192 	int _lastTrack;
193 	uint8 *_musicTrackData;
194 	uint8 *_sfxTrackData;
195 	TownsPC98_AudioDriver *_driver;
196 
resPattern()197 	const char *resPattern() {return _resInfo[_currentResourceSet]->c_str(); }
198 	Common::String *_resInfo[3];
199 	int _currentResourceSet;
200 };
201 
202 class SoundTownsPC98_v2 : public Sound {
203 public:
204 	SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer);
205 	virtual ~SoundTownsPC98_v2();
206 
getMusicType()207 	virtual kType getMusicType() const override { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; }
208 
209 	virtual bool init() override;
210 	virtual void process() override;
211 
212 	virtual void initAudioResourceInfo(int set, void *info) override;
213 	virtual void selectAudioResourceSet(int set) override;
214 	virtual bool hasSoundFile(uint file) const override;
loadSoundFile(uint file)215 	virtual void loadSoundFile(uint file) override {}
216 	virtual void loadSoundFile(Common::String file) override;
217 
218 	virtual void playTrack(uint8 track) override;
219 	virtual void haltTrack() override;
220 	virtual void beginFadeOut() override;
221 
222 	virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume = 255, uint8 priority = 255, bool isSfx = true) override;
223 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
224 
225 	virtual void updateVolumeSettings() override;
226 
227 private:
228 	Audio::AudioStream *_currentSFX;
229 	int _lastTrack;
230 	bool _useFmSfx;
231 
232 	uint8 *_musicTrackData;
233 	uint8 *_sfxTrackData;
234 	TownsPC98_AudioDriver *_driver;
235 
res()236 	const SoundResourceInfo_TownsPC98V2 *res() const {return _resInfo[_currentResourceSet]; }
237 	SoundResourceInfo_TownsPC98V2 *_resInfo[3];
238 	int _currentResourceSet;
239 };
240 
241 // PC Speaker MIDI driver
242 class MidiDriver_PCSpeaker : public MidiDriver_Emulated {
243 public:
244 	MidiDriver_PCSpeaker(Audio::Mixer *mixer);
245 	~MidiDriver_PCSpeaker();
246 
247 	// MidiDriver interface
close()248 	virtual void close() {}
249 
250 	virtual void send(uint32 data);
251 
allocateChannel()252 	virtual MidiChannel *allocateChannel() { return 0; }
getPercussionChannel()253 	virtual MidiChannel *getPercussionChannel() { return 0; }
254 
255 	// MidiDriver_Emulated interface
256 	void generateSamples(int16 *buffer, int numSamples);
257 
258 	// AudioStream interface
isStereo()259 	bool isStereo() const { return false; }
getRate()260 	int getRate() const { return _rate; }
261 private:
262 	Common::Mutex _mutex;
263 	Audio::PCSpeaker *_speaker;
264 	int _rate;
265 
266 	struct Channel {
267 		uint8 pitchBendLow, pitchBendHigh;
268 		uint8 hold;
269 		uint8 modulation;
270 		uint8 voiceProtect;
271 		uint8 noteCount;
272 	} _channel[2];
273 
274 	void resetController(int channel);
275 
276 	struct Note {
277 		bool enabled;
278 		uint8 hardwareChannel;
279 		uint8 midiChannel;
280 		uint8 note;
281 		bool processHold;
282 		uint8 flags;
283 		uint8 hardwareFlags;
284 		uint16 priority;
285 		int16 modulation;
286 		uint16 precedence;
287 	} _note[2];
288 
289 	void noteOn(int channel, int note);
290 	void noteOff(int channel, int note);
291 
292 	void turnNoteOn(int note);
293 	void overwriteNote(int note);
294 	void turnNoteOff(int note);
295 
296 	void setupTone(int note);
297 
298 	uint16 _countdown;
299 	uint8 _hardwareChannel[1];
300 	bool _modulationFlag;
301 
302 	uint8 _timerValue;
303 	void onTimer();
304 
305 	static const uint8 _noteTable1[];
306 	static const uint8 _noteTable2[];
307 };
308 
309 // for StaticResource (maybe we can find a nicer way to handle it)
310 struct AmigaSfxTable {
311 	uint8 note;
312 	uint8 patch;
313 	uint16 duration;
314 	uint8 volume;
315 	uint8 pan;
316 };
317 
318 class SoundAmiga_LoK : public Sound {
319 public:
320 	SoundAmiga_LoK(KyraEngine_v1 *vm, Audio::Mixer *mixer);
321 	virtual ~SoundAmiga_LoK();
322 
getMusicType()323 	virtual kType getMusicType() const override { return kAmiga; } //FIXME
324 
325 	virtual bool init() override;
326 
327 	virtual void initAudioResourceInfo(int set, void *info) override;
328 	virtual void selectAudioResourceSet(int set) override;
329 	virtual bool hasSoundFile(uint file) const override;
330 	virtual void loadSoundFile(uint file) override;
loadSoundFile(Common::String)331 	virtual void loadSoundFile(Common::String) override {}
332 
333 	virtual void playTrack(uint8 track) override;
334 	virtual void haltTrack() override;
335 	virtual void beginFadeOut() override;
336 
voicePlay(const char * file,Audio::SoundHandle * handle,uint8 volume,uint8 priority,bool isSfx)337 	virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; }
338 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
339 
340 protected:
341 	Audio::MaxTrax *_driver;
342 	Audio::SoundHandle _musicHandle;
343 	enum FileType { kFileNone = -1, kFileIntro = 0, kFileGame = 1, kFileFinal = 2 } _fileLoaded;
344 
345 	const AmigaSfxTable *_tableSfxIntro;
346 	int _tableSfxIntro_Size;
347 
348 	const AmigaSfxTable *_tableSfxGame;
349 	int _tableSfxGame_Size;
350 };
351 
352 #ifdef ENABLE_EOB
353 
354 class SoundTowns_Darkmoon : public Sound, public TownsAudioInterfacePluginDriver {
355 public:
356 	SoundTowns_Darkmoon(KyraEngine_v1 *vm, Audio::Mixer *mixer);
357 	virtual ~SoundTowns_Darkmoon();
358 
getMusicType()359 	virtual kType getMusicType() const { return kTowns; }
360 
361 	virtual bool init();
362 
363 	void timerCallback(int timerId);
364 
365 	virtual void initAudioResourceInfo(int set, void *info);
366 	virtual void selectAudioResourceSet(int set);
367 	virtual bool hasSoundFile(uint file) const;
368 	virtual void loadSoundFile(uint file);
369 	virtual void loadSoundFile(Common::String name);
370 
371 	virtual void playTrack(uint8 track);
372 	virtual void haltTrack();
373 	virtual bool isPlaying() const;
374 
375 	virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
376 	virtual void stopAllSoundEffects();
377 
378 	virtual void beginFadeOut();
379 
380 	virtual void updateVolumeSettings();
381 
382 	virtual int checkTrigger();
383 
384 	virtual void resetTrigger();
385 
386 private:
387 	struct SoundTableEntry {
388 		int8 type;
389 		int32 para1;
390 		int16 para2;
391 	} _soundTable[120];
392 
393 	const char *const *_fileList;
394 	uint _fileListLen;
395 
396 	uint8 _lastSfxChan;
397 	uint8 _lastEnvChan;
398 	uint8 *_pcmData;
399 	uint32 _pcmDataSize;
400 	uint8 _pcmVol;
401 
402 	int _timer;
403 	int _timerSwitch;
404 
405 	SoundResourceInfo_TownsEoB *_resource[3];
406 
407 	TownsAudioInterface *_intf;
408 };
409 
410 class AudioMaster2;
411 class SoundAmiga_EoB: public Sound {
412 public:
413 	SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer);
414 	virtual ~SoundAmiga_EoB();
415 
416 	kType getMusicType() const;
417 
418 	bool init();
419 	void initAudioResourceInfo(int set, void *info);
420 	void selectAudioResourceSet(int set);
hasSoundFile(uint file)421 	bool hasSoundFile(uint file) const { return false; }
loadSoundFile(uint)422 	void loadSoundFile(uint) {}
423 	void loadSoundFile(Common::String file);
424 	void unloadSoundFile(Common::String file);
425 	void playTrack(uint8 track);
426 	void haltTrack();
427 	void playSoundEffect(uint8 track, uint8 volume = 0xFF);
beginFadeOut()428 	void beginFadeOut() { beginFadeOut(160); }
429 	void beginFadeOut(int delay);
430 	void updateVolumeSettings();
431 	int checkTrigger();
432 
433 private:
434 	uint8 *_fileBuffer;
435 
436 	KyraEngine_v1 *_vm;
437 	AudioMaster2 *_driver;
438 	SoundResourceInfo_AmigaEoB *_resInfo[3];
439 	Common::String _lastSound;
440 
441 	int _currentResourceSet;
442 
443 	bool _ready;
444 };
445 
446 #endif
447 
448 } // End of namespace Kyra
449 
450 #endif
451