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 AGI_SOUND_2GS_H
24 #define AGI_SOUND_2GS_H
25 
26 #include "common/frac.h"
27 #include "audio/audiostream.h"
28 
29 namespace Agi {
30 
31 // Sample data in SIERRASTANDARD files is in unsigned 8-bit format. A zero
32 // occurring in the sample data causes the ES5503 wavetable sound chip in
33 // Apple IIGS to halt the corresponding oscillator immediately. We preprocess
34 // the sample data by converting it to signed values and the instruments by
35 // detecting prematurely stopping samples beforehand.
36 //
37 // Note: None of the tested SIERRASTANDARD files have zeroes in them. So in
38 // practice there is no need to check for them. However, they still do exist
39 // in the sample resources.
40 #define ZERO_OFFSET 0x80
41 
42 // Apple IIGS envelope update frequency defaults to 100Hz. It can be changed,
43 // so there might be differences per game, for example.
44 #define ENVELOPE_COEF 100 / _sampleRate
45 
46 // MIDI player commands
47 #define MIDI_NOTE_OFF       0x8
48 #define MIDI_NOTE_ON        0x9
49 #define MIDI_CONTROLLER     0xB
50 #define MIDI_PROGRAM_CHANGE 0xC
51 #define MIDI_PITCH_WHEEL    0xE
52 
53 #define MIDI_STOP_SEQUENCE  0xFC
54 #define MIDI_TIMER_SYNC     0xF8
55 
56 // Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments).
57 #define SIERRASTANDARD_SIZE 65536
58 
59 // Maximum number of instruments in an Apple IIGS instrument set.
60 // Chosen empirically based on Apple IIGS AGI game data, increase if needed.
61 #define MAX_INSTRUMENTS 28
62 
63 // The MIDI player allocates one generator for each note it starts to play.
64 // Here the maximum number of generators is defined. Feel free to increase
65 // this if it does not seem to be enough.
66 #define MAX_GENERATORS 16
67 
68 #define ENVELOPE_SEGMENT_COUNT 8
69 #define MAX_OSCILLATOR_WAVES 127  // Maximum is one for every MIDI key
70 
71 struct IIgsInstrumentHeader {
72 	struct {
73 		frac_t bp;      ///< Envelope segment breakpoint
74 		frac_t inc;     ///< Envelope segment velocity
75 	} env[ENVELOPE_SEGMENT_COUNT];
76 	uint8 seg;          ///< Envelope release segment
77 	uint8 bend;         ///< Maximum range for pitch bend
78 	uint8 vibDepth;     ///< Vibrato depth
79 	uint8 vibSpeed;     ///< Vibrato speed
80 	uint8 waveCount[2]; ///< Wave count for both generators
81 	struct {
82 		uint8 key;      ///< Highest MIDI key to use this wave
83 		uint32 offset;  ///< Offset of wave data, relative to base
84 		uint32 size;    ///< Wave size
85 		bool halt;      ///< Oscillator halted?
86 		bool loop;      ///< Loop mode?
87 		bool swap;      ///< Swap mode?
88 		bool rightChannel;  ///< Output channel (left / right)
89 		int16 tune;     ///< Fine tune in semitones (8.8 fixed point)
90 	} wave[2][MAX_OSCILLATOR_WAVES];
91 
92 	int8 *wavetableBase; ///< Base of wave data
93 
94 	/**
95 	 * Read an Apple IIGS instrument header from the given stream.
96 	 * @param stream The source stream from which to read the data.
97 	 * @param ignoreAddr Should we ignore wave infos' wave address variable's value?
98 	 * @return True if successful, false otherwise.
99 	 */
100 	bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
101 	bool finalize(int8 *wavetable, uint32 wavetableSize);
102 };
103 
104 struct IIgsSampleHeader {
105 	uint16 type;
106 	uint8  pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
107 	uint8  unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
108 	uint8  volume; ///< Current guess: Logarithmic in 6 dB steps
109 	uint8  unknownByte_Ofs5; ///< 0 in all tested samples.
110 	uint16 instrumentSize; ///< 44 in all tested samples. A guess.
111 	uint16 sampleSize; ///< Accurate in all tested samples excluding Manhunter I's sound resource 16.
112 	IIgsInstrumentHeader instrument;
113 
114 	/**
115 	 * Read an Apple IIGS AGI sample header from the given stream.
116 	 * @param stream The source stream from which to read the data.
117 	 * @return True if successful, false otherwise.
118 	 */
119 	bool read(Common::SeekableReadStream &stream);
120 	bool finalize(int8 *sampleData);
121 };
122 
123 class IIgsGenerator {
124 public:
IIgsGenerator()125 	IIgsGenerator() : curInstrument(nullptr), key(-1), channel(-1) {
126 		memset(&osc, 0, sizeof(osc));
127 		seg = 0;
128 		a = 0;
129 		velocity = 0;
130 	}
131 
132 	const IIgsInstrumentHeader *curInstrument; ///< Currently used instrument
133 	int key;        ///< MIDI key
134 	int velocity;   ///< MIDI velocity (& channel volume)
135 	int channel;    ///< MIDI channel
136 	struct {
137 		int8 *base; ///< Sample base pointer
138 		uint size;  ///< Sample size
139 		frac_t p;   ///< Sample pointer
140 		frac_t pd;  ///< Sample pointer delta
141 		bool halt;  ///< Is oscillator halted?
142 		bool loop;  ///< Is looping enabled?
143 		bool swap;  ///< Is swapping enabled?
144 		bool rightChannel;  ///< Output channel (left / right)
145 	} osc[2];
146 	int seg;        ///< Current envelope segment
147 	frac_t a;       ///< Current envelope amplitude
148 };
149 
150 class IIgsMidi : public AgiSound {
151 public:
152 	IIgsMidi(uint8 *data, uint32 len, int resnum);
~IIgsMidi()153 	~IIgsMidi() override { if (_data != NULL) free(_data); }
type()154 	uint16 type() override { return _type; }
getPtr()155 	virtual const uint8 *getPtr() { return _ptr; }
setPtr(const uint8 * ptr)156 	virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
rewind()157 	virtual void rewind() { _ptr = _data + 2; _ticks = 0; }
158 protected:
159 	uint8 *_data; ///< Raw sound resource data
160 	const uint8 *_ptr; ///< Pointer to the current position in the MIDI data
161 	uint32 _len; ///< Length of the raw sound resource
162 	uint16 _type; ///< Sound resource type
163 public:
164 	uint _ticks; ///< MIDI song position in ticks (1/60ths of a second)
165 };
166 
167 class IIgsSample : public AgiSound {
168 public:
169 	IIgsSample(uint8 *data, uint32 len, int16 resourceNr);
~IIgsSample()170 	~IIgsSample() override { delete[] _sample; }
type()171 	uint16 type() override { return _header.type; }
getHeader()172 	const IIgsSampleHeader &getHeader() const { return _header; }
173 protected:
174 	IIgsSampleHeader _header;   ///< Apple IIGS AGI sample header
175 	int8 *_sample;              ///< Sample data (8-bit signed format)
176 };
177 
178 /** Apple IIGS MIDI program change to instrument number mapping. */
179 struct IIgsMidiProgramMapping {
180 	byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping
181 	byte undefinedInst; ///< The undefined instrument number
182 
183 	// Maps the MIDI program number to an instrument number
mapIIgsMidiProgramMapping184 	byte map(uint midiProg) const {
185 		return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst;
186 	}
187 };
188 
189 /** Apple IIGS AGI instrument set information. */
190 struct IIgsInstrumentSetInfo {
191 	uint byteCount; ///< Length of the whole instrument set in bytes
192 	uint instCount; ///< Amount of instrument in the set
193 	const char *md5; ///< MD5 hex digest of the whole instrument set
194 	const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
195 	const IIgsMidiProgramMapping *progToInst; ///< Program change to instrument number mapping
196 };
197 
198 /** Apple IIGS AGI executable file information. */
199 struct IIgsExeInfo {
200 	enum AgiGameID gameid;  ///< Game ID
201 	const char *exePrefix;  ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc)
202 	uint agiVer;            ///< Apple IIGS AGI version number, not strictly needed
203 	uint exeSize;           ///< Size of the Apple IIGS AGI executable file in bytes
204 	uint instSetStart;      ///< Starting offset of the instrument set inside the executable file
205 	const IIgsInstrumentSetInfo *instSet; ///< Information about the used instrument set
206 };
207 
208 class IIgsMidiChannel {
209 public:
IIgsMidiChannel()210 	IIgsMidiChannel() : _instrument(NULL), _volume(127) {}
setInstrument(const IIgsInstrumentHeader * instrument)211 	void setInstrument(const IIgsInstrumentHeader *instrument) { _instrument = instrument; }
getInstrument()212 	const IIgsInstrumentHeader *getInstrument() { return _instrument; }
setVolume(int volume)213 	void setVolume(int volume) { _volume = volume; }
getVolume()214 	int getVolume() { return _volume; }
215 private:
216 	const IIgsInstrumentHeader *_instrument;    ///< Instrument used on this MIDI channel
217 	int _volume;                                ///< MIDI controller number 7 (Volume)
218 };
219 
220 class SoundGen2GS : public SoundGen, public Audio::AudioStream {
221 public:
222 	SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer);
223 	~SoundGen2GS() override;
224 
225 	void play(int resnum) override;
226 	void stop(void) override;
227 
228 	int readBuffer(int16 *buffer, const int numSamples) override;
229 
isStereo()230 	bool isStereo() const override { return true; }
endOfData()231 	bool endOfData() const override { return false; }
getRate()232 	int getRate() const override { return _sampleRate; }
233 
234 private:
235 	// Loader methods
236 	bool loadInstruments();
237 	bool loadInstrumentHeaders(Common::String &exePath, const IIgsExeInfo &exeInfo);
238 	bool loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeInfo);
239 
240 	const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
241 	void setProgramChangeMapping(const IIgsMidiProgramMapping *mapping);
242 
243 	// Player methods
244 	void advancePlayer();       ///< Advance the player
245 	void advanceMidiPlayer();   ///< Advance MIDI player
246 	uint generateOutput();      ///< Fill the output buffer
247 
248 	void haltGenerators();      ///< Halt all generators
249 	uint activeGenerators();    ///< How many generators are active?
250 
251 	void midiNoteOff(int channel, int note, int velocity);
252 	void midiNoteOn(int channel, int note, int velocity);
253 	double midiKeyToFreq(int key, double finetune);
getInstrument(uint8 program)254 	IIgsInstrumentHeader *getInstrument(uint8 program) { return &_instruments[_progToInst->map(program)]; }
allocateGenerator()255 	IIgsGenerator *allocateGenerator() { IIgsGenerator *g = &_generators[_nextGen++]; _nextGen %= 16; return g; }
256 
257 	bool _disableMidi;  ///< Disable MIDI if loading instruments fail
258 	int _playingSound;  ///< Resource number for the currently playing sound
259 	bool _playing;      ///< True when the resource is still playing
260 
261 	IIgsGenerator _generators[MAX_GENERATORS];          ///< IIGS sound generators that are used to play single notes
262 	uint _nextGen;                                      ///< Next generator available for allocation
263 	IIgsMidiChannel _channels[16];                      ///< MIDI channels
264 	Common::Array<IIgsInstrumentHeader> _instruments;   ///< Instrument data
265 	const IIgsMidiProgramMapping *_progToInst;          ///< MIDI program number to instrument mapping
266 	int8 *_wavetable;                                   ///< Sample data used by the instruments
267 	uint _ticks;                                        ///< MIDI ticks (60Hz)
268 	int16 *_out;                                        ///< Output buffer
269 	uint _outSize;                                      ///< Output buffer size
270 
271 	static const int kSfxMidiChannel = 15; ///< MIDI channel used for playing sample resources
272 };
273 
274 } // End of namespace Agi
275 
276 #endif /* AGI_SOUND_2GS_H */
277