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 LURE_SOUND_H
24 #define LURE_SOUND_H
25 
26 #include "lure/luredefs.h"
27 #include "lure/disk.h"
28 #include "lure/memory.h"
29 
30 #include "common/mutex.h"
31 #include "common/singleton.h"
32 #include "common/ptr.h"
33 
34 #include "audio/adlib_ms.h"
35 #include "audio/mididrv.h"
36 #include "audio/mt32gm.h"
37 
38 class MidiParser;
39 class MidiChannel;
40 
41 namespace Lure {
42 
43 #define NUM_CHANNELS 16
44 #define LURE_MAX_SOURCES 10
45 
46 class MidiMusic: public MidiDriver_BASE {
47 private:
48 	uint8 _soundNumber;
49 	uint8 _numChannels;
50 	byte _volume;
51 	MemoryBlock *_decompressedSound;
52 	uint8 *_soundData;
53 	uint8 _soundSize;
54 	MidiDriver_Multisource *_driver;
55 	MidiDriver_MT32GM *_mt32Driver;
56 	int8 _source;
57 	MidiParser *_parser;
58 	bool _isMusic;
59 	bool _loop;
60 	bool _isPlaying;
61 
62 	void queueUpdatePos();
63 	uint8 randomQueuePos();
64 	uint32 songOffset(uint16 songNum) const;
65 	uint32 songLength(uint16 songNum) const;
66 
67 public:
68 	MidiMusic(MidiDriver_Multisource *driver, uint8 soundNum, bool isMus, bool loop,
69 		int8 source, uint8 numChannels, void *soundData, uint32 size, uint8 volume);
70 	~MidiMusic() override;
71 	void setVolume(int volume);
getVolume()72 	int getVolume() const { return _volume; }
73 
74 	void playSong(uint16 songNum);
stopSong()75 	void stopSong() { stopMusic(); }
76 	void playMusic();
77 	void stopMusic();
78 	void pauseMusic();
79 	void resumeMusic();
80 	void queueTuneList(int16 tuneList);
81 	bool queueSong(uint16 songNum);
82 	void toggleVChange();
83 
84 	// MidiDriver_BASE interface implementation
85 	void send(uint32 b) override;
86 	void send(int8 source, uint32 b) override;
87 	void metaEvent(byte type, byte *data, uint16 length) override;
88 	void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
89 
90 	void onTimer();
91 
soundNumber()92 	uint8 soundNumber() const { return _soundNumber; }
getSource()93 	int8 getSource() const { return _source; }
isPlaying()94 	bool isPlaying() const { return _isPlaying; }
isMusic()95 	bool isMusic() const { return _isMusic; }
96 };
97 
98 class SoundManager : public Common::Singleton<SoundManager> {
99 private:
100 	// Outer sound interface properties
101 	MemoryBlock *_descs;
102 	MemoryBlock *_soundData;
103 	uint8 _soundsTotal;
104 	int _numDescs;
soundDescs()105 	SoundDescResource *soundDescs() { return (SoundDescResource *) _descs->data(); }
106 	MidiDriver_Multisource *_driver;
107 	MidiDriver_MT32GM *_mt32Driver;
108 	typedef Common::List<Common::SharedPtr<SoundDescResource> > SoundList;
109 	typedef SoundList::iterator SoundListIterator;
110 	SoundList _activeSounds;
111 	typedef Common::List<Common::SharedPtr<MidiMusic> > MusicList;
112 	typedef MusicList::iterator MusicListIterator;
113 	MusicList _playingSounds;
114 	bool _sourcesInUse[LURE_MAX_SOURCES];
115 	bool _nativeMT32;
116 	bool _isRoland;
117 	Common::Mutex _soundMutex;
118 	bool _paused;
119 
120 	// Internal support methods
121 	void bellsBodge();
122 	void musicInterface_TidySounds();
123 	static void onTimer(void *data);
124 	void doTimer();
125 
126 public:
127 	SoundManager();
128 	~SoundManager() override;
129 
130 	void saveToStream(Common::WriteStream *stream);
131 	void loadFromStream(Common::ReadStream *stream);
132 
133 	void loadSection(uint16 sectionId);
134 	bool initCustomTimbres(bool canAbort = false);
135 	void killSounds();
136 	void addSound(uint8 soundIndex, bool tidyFlag = true);
137 	void addSound2(uint8 soundIndex);
138 	void stopSound(uint8 soundIndex);
139 	void killSound(uint8 soundNumber);
140 	void setVolume(uint8 soundNumber, uint8 volume);
141 	void syncSounds();
142 	void tidySounds();
143 	uint8 descIndexOf(uint8 soundNumber);
144 	SoundDescResource *findSound(uint8 soundNumber);
145 	void removeSounds();
146 	void restoreSounds();
147 	bool fadeOut();
148 	void pause();
149 	void resume();
getPaused()150 	bool getPaused() const { return _paused; }
hasNativeMT32()151 	bool hasNativeMT32() const { return _nativeMT32; }
isRoland()152 	bool isRoland() const { return _isRoland; }
153 
154 	// The following methods implement the external sound player module
155 	//void musicInterface_Initialize();
156 	void musicInterface_Play(uint8 soundNumber, bool isMusic = false, uint8 numChannels = 4, uint8 volume = 0x80);
157 	void musicInterface_Stop(uint8 soundNumber);
158 	bool musicInterface_CheckPlaying(uint8 soundNumber);
159 	void musicInterface_SetVolume(uint8 soundNumber, uint8 volume);
160 	void musicInterface_KillAll();
161 	void musicInterface_ContinuePlaying();
162 	void musicInterface_TrashReverb();
163 };
164 
165 // AdLib MidiDriver subclass implementing the behavior specific to Lure of the
166 // Temptress.
167 class MidiDriver_ADLIB_Lure : public MidiDriver_ADLIB_Multisource {
168 protected:
169 	// Lookup array for OPL frequency (F-num) values.
170 	static const uint16 OPL_FREQUENCY_LOOKUP[];
171 
172 public:
173 	MidiDriver_ADLIB_Lure();
174 
175 	// Channel aftertouch is used to adjust a note's volume. This is done by
176 	// overriding the velocity of the active note and recalculating the volume.
177 	void channelAftertouch(uint8 channel, uint8 pressure, uint8 source) override;
178 	// The MIDI data uses three custom sequencer meta events; the most important
179 	// one sets the instrument definition for a channel.
180 	void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
181 
182 protected:
183 	InstrumentInfo determineInstrument(uint8 channel, uint8 source, uint8 note)	override;
184 	uint16 calculateFrequency(uint8 channel, uint8 source, uint8 note) override;
185 	// Returns the number of semitones in bits 8+ and an 8 bit fraction of a
186 	// semitone.
187 	int32 calculatePitchBend(uint8 channel, uint8 source, uint16 oplFrequency) override;
188 	uint8 calculateUnscaledVolume(uint8 channel, uint8 source, uint8 velocity, OplInstrumentDefinition &instrumentDef, uint8 operatorNum) override;
189 
190 	// Stores the instrument definitions set by sequencer meta events.
191 	OplInstrumentDefinition _instrumentDefs[LURE_MAX_SOURCES][MIDI_CHANNEL_COUNT];
192 	// Pitch bend sensitivity in semi-tones. This is a global setting;
193 	// it cannot be specified for a specific MIDI channel.
194 	uint8 _pitchBendSensitivity;
195 };
196 
197 } // End of namespace Lure
198 
199 #define Sound (::Lure::SoundManager::instance())
200 
201 #endif
202