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