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 #include "common/config-manager.h"
24 #include "common/fs.h"
25 #include "common/archive.h"
26 #include "common/md5.h"
27 #include "common/memstream.h"
28 #include "common/str-array.h"
29 #include "common/textconsole.h"
30 #include "audio/mixer.h"
31 
32 #include "agi/agi.h"
33 #include "agi/sound_2gs.h"
34 
35 namespace Agi {
36 
SoundGen2GS(AgiBase * vm,Audio::Mixer * pMixer)37 SoundGen2GS::SoundGen2GS(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) {
38 	// Allocate memory for the wavetable
39 	_wavetable = new int8[SIERRASTANDARD_SIZE];
40 
41 	// Apple IIGS AGI MIDI player advances 60 ticks per second. Strategy
42 	// here is to first generate audio for a 1/60th of a second and then
43 	// advance the MIDI player by one tick. Thus, make the output buffer
44 	// to be a 1/60th of a second in length.
45 	_outSize = _sampleRate / 60;
46 	_out = new int16[2 * _outSize]; // stereo
47 
48 	// Initialize player variables
49 	_nextGen = 0;
50 	_ticks = 0;
51 
52 	// Not playing anything yet
53 	_playingSound = -1;
54 	_playing = false;
55 
56 	// Load instruments
57 	_disableMidi = !loadInstruments();
58 
59 	_mixer->playStream(Audio::Mixer::kMusicSoundType, _soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
60 }
61 
~SoundGen2GS()62 SoundGen2GS::~SoundGen2GS() {
63 	_mixer->stopHandle(*_soundHandle);
64 	delete[] _wavetable;
65 	delete[] _out;
66 }
67 
readBuffer(int16 * buffer,const int numSamples)68 int SoundGen2GS::readBuffer(int16 *buffer, const int numSamples) {
69 	static uint data_available = 0;
70 	static uint data_offset = 0;
71 	uint n = numSamples << 1;
72 	uint8 *p = (uint8 *)buffer;
73 
74 	while (n > data_available) {
75 		memcpy(p, (uint8 *)_out + data_offset, data_available);
76 		p += data_available;
77 		n -= data_available;
78 
79 		advancePlayer();
80 
81 		data_available = generateOutput() << 1;
82 		data_offset = 0;
83 	}
84 
85 	memcpy(p, (uint8 *)_out + data_offset, n);
86 	data_offset += n;
87 	data_available -= n;
88 
89 	return numSamples;
90 }
91 
92 /**
93  * Initiate the playing of a sound resource.
94  * @param resnum Resource number
95  */
play(int resnum)96 void SoundGen2GS::play(int resnum) {
97 	AgiSoundEmuType type;
98 
99 	type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type();
100 	assert(type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI);
101 
102 	if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
103 		warning("Trying to play sample or MIDI resource but not using Apple IIGS sound emulation mode");
104 		return;
105 	}
106 
107 	// FIXME: all sorts of things in here are not thread-safe
108 	haltGenerators();
109 
110 	switch (type) {
111 	case AGI_SOUND_SAMPLE: {
112 		IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[resnum];
113 		const IIgsSampleHeader &header = sampleRes->getHeader();
114 		_channels[kSfxMidiChannel].setInstrument(&header.instrument);
115 		_channels[kSfxMidiChannel].setVolume(header.volume);
116 		midiNoteOn(kSfxMidiChannel, header.pitch, 127);
117 		break;
118 	}
119 	case AGI_SOUND_MIDI:
120 		((IIgsMidi *) _vm->_game.sounds[resnum])->rewind();
121 		_ticks = 0;
122 		break;
123 	default:
124 		break;
125 	}
126 
127 	_playingSound = resnum;
128 }
129 
stop()130 void SoundGen2GS::stop() {
131 	haltGenerators();
132 	_playingSound = -1;
133 	_playing = false;
134 }
135 
136 /**
137  * Fill output buffer by advancing the generators for a 1/60th of a second.
138  * @return Number of generated samples
139  */
generateOutput()140 uint SoundGen2GS::generateOutput() {
141 	memset(_out, 0, _outSize * 2 * 2);
142 
143 	if (!_playing || _playingSound == -1)
144 		return _outSize * 2;
145 
146 	int16 *p = _out;
147 	int n = _outSize;
148 	while (n--) {
149 		int outLeft = 0;
150 		int outRight = 0;
151 		for (int k = 0; k < MAX_GENERATORS; k++) {
152 			IIgsGenerator *g = &_generators[k];
153 			if (!g->curInstrument)
154 				continue;
155 			const IIgsInstrumentHeader *curInstrument = g->curInstrument;
156 
157 			// Advance envelope
158 			int vol = fracToInt(g->a);
159 			if (g->a <= curInstrument->env[g->seg].bp) {
160 				g->a += curInstrument->env[g->seg].inc * ENVELOPE_COEF;
161 				if (g->a > curInstrument->env[g->seg].bp) {
162 					g->a = curInstrument->env[g->seg].bp;
163 					g->seg++;
164 				}
165 			} else {
166 				g->a -= curInstrument->env[g->seg].inc * ENVELOPE_COEF;
167 				if (g->a < curInstrument->env[g->seg].bp) {
168 					g->a = curInstrument->env[g->seg].bp;
169 					g->seg++;
170 				}
171 			}
172 
173 			// TODO: Advance vibrato here. The Apple IIGS uses a LFO with
174 			// triangle wave to modulate the frequency of both oscillators.
175 			// In Apple IIGS the vibrato and the envelope are updated at the
176 			// same time, so the vibrato speed depends on ENVELOPE_COEF.
177 
178 			// Advance oscillators
179 			int s0 = 0;
180 			int s1 = 0;
181 			if (!g->osc[0].halt) {
182 				s0 = g->osc[0].base[fracToInt(g->osc[0].p)];
183 				g->osc[0].p += g->osc[0].pd;
184 				if ((uint)fracToInt(g->osc[0].p) >= g->osc[0].size) {
185 					g->osc[0].p -= intToFrac(g->osc[0].size);
186 					if (!g->osc[0].loop)
187 						g->osc[0].halt = true;
188 					if (g->osc[0].swap) {
189 						g->osc[0].halt = true;
190 						g->osc[1].halt = false;
191 					}
192 				}
193 			}
194 			if (!g->osc[1].halt) {
195 				s1 = g->osc[1].base[fracToInt(g->osc[1].p)];
196 				g->osc[1].p += g->osc[1].pd;
197 				if ((uint)fracToInt(g->osc[1].p) >= g->osc[1].size) {
198 					g->osc[1].p -= intToFrac(g->osc[1].size);
199 					if (!g->osc[1].loop)
200 						g->osc[1].halt = true;
201 					if (g->osc[1].swap) {
202 						g->osc[0].halt = false;
203 						g->osc[1].halt = true;
204 					}
205 				}
206 			}
207 
208 			// Take envelope and MIDI volume information into account.
209 			// Also amplify.
210 			s0 *= vol * g->velocity / 127 * 80 / 256;
211 			s1 *= vol * g->velocity / 127 * 80 / 256;
212 
213 			// Select output channel.
214 			if (g->osc[0].rightChannel)
215 				outRight += s0;
216 			else
217 				outLeft += s0;
218 
219 			if (g->osc[1].rightChannel)
220 				outRight += s1;
221 			else
222 				outLeft += s1;
223 		}
224 
225 		if (outLeft > 32768)
226 			outLeft = 32768;
227 		if (outLeft < -32767)
228 			outLeft = -32767;
229 		if (outRight > 32768)
230 			outRight = 32768;
231 		if (outRight < -32767)
232 			outRight = -32767;
233 
234 		*p++ = outLeft;
235 		*p++ = outRight;
236 	}
237 
238 	return _outSize * 2;
239 }
240 
advancePlayer()241 void SoundGen2GS::advancePlayer() {
242 	if (_playingSound == -1)
243 		return;
244 
245 	if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) {
246 		advanceMidiPlayer();
247 	} else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) {
248 		_playing = activeGenerators() > 0;
249 	}
250 
251 	if (!_playing) {
252 		_vm->_sound->soundIsFinished();
253 		_playingSound = -1;
254 	}
255 }
256 
advanceMidiPlayer()257 void SoundGen2GS::advanceMidiPlayer() {
258 	if (_disableMidi)
259 		return;
260 
261 	const uint8 *p;
262 	uint8 parm1, parm2;
263 	static uint8 cmd, chn;
264 
265 	if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) {
266 		warning("Error playing Apple IIGS MIDI sound resource");
267 		_playing = false;
268 		return;
269 	}
270 
271 	IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound];
272 
273 	_ticks++;
274 	_playing = true;
275 	p = midiObj->getPtr();
276 
277 	while (true) {
278 		// Check for end of MIDI sequence marker (Can also be here before delta-time)
279 		if (*p == MIDI_STOP_SEQUENCE) {
280 			debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)");
281 			_playing = false;
282 			midiObj->rewind();
283 			return;
284 		}
285 		if (*p == MIDI_TIMER_SYNC) {
286 			debugC(3, kDebugLevelSound, "Timer sync");
287 			p++; // Jump over the timer sync byte as it's not needed
288 			continue;
289 		}
290 
291 		// Check for delta time
292 		uint8 delta = *p;
293 		if (midiObj->_ticks + delta > _ticks)
294 			break;
295 		midiObj->_ticks += delta;
296 		p++;
297 
298 		// Check for end of MIDI sequence marker (This time it after reading delta-time)
299 		if (*p == MIDI_STOP_SEQUENCE) {
300 			debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)");
301 			_playing = false;
302 			midiObj->rewind();
303 			return;
304 		}
305 
306 		// Separate byte into command and channel if it's a command byte.
307 		// Otherwise use running status (i.e. previously set command and channel).
308 		if (*p & 0x80) {
309 			cmd = *p++;
310 			chn = cmd & 0x0f;
311 			cmd >>= 4;
312 		}
313 
314 		switch (cmd) {
315 		case MIDI_NOTE_OFF:
316 			parm1 = *p++;
317 			parm2 = *p++;
318 			debugC(3, kDebugLevelSound, "channel %X: note off (key = %d, velocity = %d)", chn, parm1, parm2);
319 			midiNoteOff(chn, parm1, parm2);
320 			break;
321 		case MIDI_NOTE_ON:
322 			parm1 = *p++;
323 			parm2 = *p++;
324 			debugC(3, kDebugLevelSound, "channel %X: note on (key = %d, velocity = %d)", chn, parm1, parm2);
325 			midiNoteOn(chn, parm1, parm2);
326 			break;
327 		case MIDI_CONTROLLER:
328 			parm1 = *p++;
329 			parm2 = *p++;
330 			debugC(3, kDebugLevelSound, "channel %X: controller %02X = %02X", chn, parm1, parm2);
331 			// The tested Apple IIGS AGI MIDI resources only used
332 			// controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off).
333 			// Controller 0's parameter was in range 94-127,
334 			// controller 7's parameter was in range 0-127 and
335 			// controller 64's parameter was always 0 (i.e. sustain off).
336 			switch (parm1) {
337 			case 7:
338 				_channels[chn].setVolume(parm2);
339 				break;
340 			}
341 			break;
342 		case MIDI_PROGRAM_CHANGE:
343 			parm1 = *p++;
344 			debugC(3, kDebugLevelSound, "channel %X: program change %02X", chn, parm1);
345 			_channels[chn].setInstrument(getInstrument(parm1));
346 			break;
347 		case MIDI_PITCH_WHEEL:
348 			parm1 = *p++;
349 			parm2 = *p++;
350 			debugC(3, kDebugLevelSound, "channel %X: pitch wheel (unimplemented) %02X, %02X", chn, parm1, parm2);
351 			break;
352 
353 		default:
354 			debugC(3, kDebugLevelSound, "channel %X: unimplemented command %02X", chn, cmd);
355 			break;
356 		}
357 	}
358 
359 	midiObj->setPtr(p);
360 }
361 
midiNoteOff(int channel,int note,int velocity)362 void SoundGen2GS::midiNoteOff(int channel, int note, int velocity) {
363 	// Release keys within the given MIDI channel
364 	for (int i = 0; i < MAX_GENERATORS; i++) {
365 		if (_generators[i].channel == channel && _generators[i].key == note) {
366 			if (_generators[i].curInstrument) {
367 				_generators[i].seg = _generators[i].curInstrument->seg;
368 			}
369 		}
370 	}
371 }
372 
midiNoteOn(int channel,int note,int velocity)373 void SoundGen2GS::midiNoteOn(int channel, int note, int velocity) {
374 	if (!_channels[channel].getInstrument()) {
375 		debugC(3, kDebugLevelSound, "midiNoteOn(): no instrument specified for channel %d", channel);
376 		return;
377 	}
378 
379 	// Allocate a generator for the note.
380 	IIgsGenerator *generator = allocateGenerator();
381 	generator->curInstrument = _channels[channel].getInstrument();
382 	const IIgsInstrumentHeader *curInstrument = generator->curInstrument;
383 
384 	// Pass information from the MIDI channel to the generator. Take
385 	// velocity into account, although simplistically.
386 	velocity *= 5 / 3;
387 	if (velocity > 127)
388 		velocity = 127;
389 
390 	generator->key = note;
391 	generator->velocity = velocity * _channels[channel].getVolume() / 127;
392 	generator->channel = channel;
393 
394 	// Instruments can define different samples to be used based on
395 	// what the key is. Find the correct samples for our key.
396 	int wa = 0;
397 	int wb = 0;
398 	while (wa < curInstrument->waveCount[0] - 1 && note > curInstrument->wave[0][wa].key)
399 		wa++;
400 	while (wb < curInstrument->waveCount[1] - 1 && note > curInstrument->wave[1][wb].key)
401 		wb++;
402 
403 	// Prepare the generator.
404 	generator->osc[0].base  = curInstrument->wavetableBase + curInstrument->wave[0][wa].offset;
405 	generator->osc[0].size  = curInstrument->wave[0][wa].size;
406 	generator->osc[0].pd    = doubleToFrac(midiKeyToFreq(note, (double)curInstrument->wave[0][wa].tune / 256.0) / (double)_sampleRate);
407 	generator->osc[0].p     = 0;
408 	generator->osc[0].halt  = curInstrument->wave[0][wa].halt;
409 	generator->osc[0].loop  = curInstrument->wave[0][wa].loop;
410 	generator->osc[0].swap  = curInstrument->wave[0][wa].swap;
411 	generator->osc[0].rightChannel = curInstrument->wave[0][wa].rightChannel;
412 
413 	generator->osc[1].base  = curInstrument->wavetableBase + curInstrument->wave[1][wb].offset;
414 	generator->osc[1].size  = curInstrument->wave[1][wb].size;
415 	generator->osc[1].pd    = doubleToFrac(midiKeyToFreq(note, (double)curInstrument->wave[1][wb].tune / 256.0) / (double)_sampleRate);
416 	generator->osc[1].p     = 0;
417 	generator->osc[1].halt  = curInstrument->wave[1][wb].halt;
418 	generator->osc[1].loop  = curInstrument->wave[1][wb].loop;
419 	generator->osc[1].swap  = curInstrument->wave[1][wb].swap;
420 	generator->osc[1].rightChannel = curInstrument->wave[1][wb].rightChannel;
421 
422 	generator->seg  = 0;
423 	generator->a    = 0;
424 
425 	// Print debug messages for instruments with swap mode or vibrato enabled
426 	if (generator->osc[0].swap || generator->osc[1].swap)
427 		debugC(2, kDebugLevelSound, "Detected swap mode in a playing instrument. This is rare and is not tested well...");
428 	if (curInstrument->vibDepth > 0)
429 		debugC(2, kDebugLevelSound, "Detected vibrato in a playing instrument. Vibrato is not implemented, playing without...");
430 }
431 
midiKeyToFreq(int key,double finetune)432 double SoundGen2GS::midiKeyToFreq(int key, double finetune) {
433 	return 440.0 * pow(2.0, (15.0 + (double)key + finetune) / 12.0);
434 }
435 
haltGenerators()436 void SoundGen2GS::haltGenerators() {
437 	for (int i = 0; i < MAX_GENERATORS; i++) {
438 		// Reset instrument pointer especially for samples, because samples are deleted on unload/room changes
439 		// and not resetting them here would cause those invalidated samples get accessed during generateOutput()
440 		_generators[i].curInstrument = nullptr;
441 		_generators[i].osc[0].halt = true;
442 		_generators[i].osc[1].halt = true;
443 	}
444 }
445 
activeGenerators()446 uint SoundGen2GS::activeGenerators() {
447 	int n = 0;
448 	for (int i = 0; i < MAX_GENERATORS; i++)
449 		if (!_generators[i].osc[0].halt || !_generators[i].osc[1].halt)
450 			n++;
451 	return n;
452 }
453 
setProgramChangeMapping(const IIgsMidiProgramMapping * mapping)454 void SoundGen2GS::setProgramChangeMapping(const IIgsMidiProgramMapping *mapping) {
455 	_progToInst = mapping;
456 }
457 
IIgsMidi(uint8 * data,uint32 len,int resnum)458 IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum) : AgiSound() {
459 	_data = data; // Save the resource pointer
460 	_ptr = _data + 2; // Set current position to just after the header
461 	_len = len;  // Save the resource's length
462 	_type = READ_LE_UINT16(data); // Read sound resource's type
463 	_ticks = 0;
464 	_isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2);
465 
466 	if (!_isValid) // Check for errors
467 		warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len);
468 }
469 
470 /**
471  * Convert sample from 8-bit unsigned to 8-bit signed format.
472  * @param source  Source stream containing the 8-bit unsigned sample data.
473  * @param dest  Destination buffer for the 8-bit signed sample data.
474  * @param length  Length of the sample data to be converted.
475  */
convertWave(Common::SeekableReadStream & source,int8 * dest,uint length)476 static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) {
477 	// Convert the wave from 8-bit unsigned to 8-bit signed format
478 	for (uint i = 0; i < length; i++)
479 		dest[i] = (int8)((int)source.readByte() - ZERO_OFFSET);
480 	return !(source.eos() || source.err());
481 }
482 
IIgsSample(uint8 * data,uint32 len,int16 resourceNr)483 IIgsSample::IIgsSample(uint8 *data, uint32 len, int16 resourceNr) : AgiSound() {
484 	Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES);
485 
486 	_sample = nullptr;
487 
488 	// Check that the header was read ok and that it's of the correct type
489 	if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
490 		uint32 sampleStartPos = stream.pos();
491 		uint32 tailLen = stream.size() - sampleStartPos;
492 
493 		if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream
494 			// Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes
495 			// of sample data although header says it should have 16384 bytes.
496 			warning("Apple IIGS sample (%d) expected %d bytes, got %d bytes only",
497 			        resourceNr, _header.sampleSize, tailLen);
498 
499 			_header.sampleSize = (uint16) tailLen; // Use the part that's left
500 		}
501 
502 		if (_header.pitch > 0x7F) { // Check if the pitch is invalid
503 			warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resourceNr, _header.pitch);
504 
505 			_header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too
506 		}
507 
508 		// Convert sample data from 8-bit unsigned to 8-bit signed format
509 		stream.seek(sampleStartPos);
510 		_sample = new int8[_header.sampleSize];
511 
512 		if (_sample != NULL) {
513 			_isValid = convertWave(stream, _sample, _header.sampleSize);
514 
515 			if (_isValid) {
516 				// Finalize header info using sample data
517 				_header.finalize(_sample);
518 			}
519 		}
520 	}
521 
522 	if (!_isValid) // Check for errors
523 		warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resourceNr, _header.type, len);
524 }
525 
526 
read(Common::SeekableReadStream & stream,bool ignoreAddr)527 bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
528 	for (int i = 0; i < ENVELOPE_SEGMENT_COUNT; i++) {
529 		env[i].bp = intToFrac(stream.readByte());
530 		env[i].inc = intToFrac(stream.readUint16LE()) >> 8;
531 	}
532 	seg         = stream.readByte();
533 	/*priority  =*/ stream.readByte(); // Not needed. 32 in all tested data.
534 	bend        = stream.readByte();
535 	vibDepth    = stream.readByte();
536 	vibSpeed    = stream.readByte();
537 	stream.readByte(); // Not needed? 0 in all tested data.
538 
539 	waveCount[0] = stream.readByte();
540 	waveCount[1] = stream.readByte();
541 	for (int i = 0; i < 2; i++) {
542 		for (int k = 0; k < waveCount[i]; k++) {
543 			wave[i][k].key = stream.readByte();
544 			wave[i][k].offset = stream.readByte() << 8;
545 			wave[i][k].size = 0x100 << (stream.readByte() & 7);
546 			uint8 b = stream.readByte();
547 			wave[i][k].tune = stream.readUint16LE();
548 
549 			// For sample resources we ignore the address.
550 			if (ignoreAddr)
551 				wave[i][k].offset = 0;
552 
553 			// Parse the generator mode byte to separate fields.
554 			wave[i][k].halt = b & 0x1;          // Bit 0     = HALT
555 			wave[i][k].loop = !(b & 0x2);       // Bit 1     =!LOOP
556 			wave[i][k].swap = (b & 0x6) == 0x6; // Bit 1&2   = SWAP
557 			// channels seem to be reversed, verified with emulator + captured apple IIgs music
558 			if (b & 0x10) {
559 				wave[i][k].rightChannel = true; // Bit 4 set = right channel
560 			} else {
561 				wave[i][k].rightChannel = false; // Bit 4 not set = left channel
562 			}
563 		}
564 	}
565 
566 	return !(stream.eos() || stream.err());
567 }
568 
finalize(int8 * wavetable,uint32 wavetableSize)569 bool IIgsInstrumentHeader::finalize(int8 *wavetable, uint32 wavetableSize) {
570 	wavetableBase = wavetable;
571 
572 	// Go through all offsets and sizes and make sure, they point to within wavetable
573 	for (int i = 0; i < 2; i++) {
574 		for (int k = 0; k < waveCount[i]; k++) {
575 			uint32 waveOffset = wave[i][k].offset;
576 			uint32 waveSize   = wave[i][k].size;
577 
578 			if (waveOffset >= wavetableSize) {
579 				error("Apple IIgs sound: sample data points outside of wavetable");
580 			}
581 
582 			if ((waveOffset + waveSize) > wavetableSize) {
583 				// fix up size, it's actually saved in a way in the header, that it can't be correct
584 				// if we don't fix it here, we would do invalid memory access, which results in potential crashes
585 				wave[i][k].size = wavetableSize - waveOffset;
586 			}
587 
588 			// Detect true sample size
589 			int8 *sample = wavetableBase + wave[i][k].offset;
590 			uint32 trueSize;
591 			for (trueSize = 0; trueSize < wave[i][k].size; trueSize++) {
592 				if (sample[trueSize] == -ZERO_OFFSET)
593 					break;
594 			}
595 			wave[i][k].size = trueSize;
596 		}
597 	}
598 
599 	return true;
600 }
601 
read(Common::SeekableReadStream & stream)602 bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) {
603 	type                = stream.readUint16LE();
604 	pitch               = stream.readByte();
605 	unknownByte_Ofs3    = stream.readByte();
606 	volume              = stream.readByte();
607 	unknownByte_Ofs5    = stream.readByte();
608 	instrumentSize      = stream.readUint16LE();
609 	sampleSize          = stream.readUint16LE();
610 	// Read the instrument header *ignoring* its wave address info
611 	return instrument.read(stream, true);
612 }
613 
finalize(int8 * sampleData)614 bool IIgsSampleHeader::finalize(int8 *sampleData) {
615 	return instrument.finalize(sampleData, sampleSize);
616 }
617 
618 //###
619 //### LOADER METHODS
620 //###
621 
loadInstruments()622 bool SoundGen2GS::loadInstruments() {
623 	// Get info on the particular Apple IIGS AGI game's executable
624 	const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID)_vm->getGameID());
625 	if (exeInfo == NULL) {
626 		warning("Unsupported Apple IIGS game, not loading instruments");
627 		return false;
628 	}
629 
630 	// Find the executable file and the wavetable file
631 	Common::ArchiveMemberList exeNames, waveNames;
632 	SearchMan.listMatchingMembers(exeNames, "*.SYS16");
633 	SearchMan.listMatchingMembers(exeNames, "*.SYS");
634 	SearchMan.listMatchingMembers(waveNames, "SIERRASTANDARD");
635 	SearchMan.listMatchingMembers(waveNames, "SIERRAST");
636 
637 	if (exeNames.empty()) {
638 		warning("Couldn't find Apple IIGS game executable (*.SYS16 or *.SYS), not loading instruments");
639 		return false;
640 	}
641 	if (waveNames.empty()) {
642 		warning("Couldn't find Apple IIGS wave file (SIERRASTANDARD or SIERRAST), not loading instruments");
643 		return false;
644 	}
645 
646 	Common::String exeName  = exeNames.front()->getName();
647 	Common::String waveName = waveNames.front()->getName();
648 
649 	// Set the MIDI program change to instrument number mapping and
650 	// load the instrument headers and their sample data.
651 	setProgramChangeMapping(exeInfo->instSet->progToInst);
652 	return loadWaveFile(waveName, *exeInfo) && loadInstrumentHeaders(exeName, *exeInfo);
653 }
654 
655 /** Older Apple IIGS AGI MIDI program change to instrument number mapping. */
656 static const IIgsMidiProgramMapping progToInstMappingV1 = {
657 	{
658 		19, 20, 22, 23, 21, 24, 5, 5, 5, 5,
659 		6, 7, 10, 9, 11, 9, 15, 8, 5, 5,
660 		17, 16, 18, 12, 14, 5, 5, 5, 5, 5,
661 		0, 1, 2, 9, 3, 4, 15, 2, 2, 2,
662 		25, 13, 13, 25
663 	},
664 	5
665 };
666 
667 /** Newer Apple IIGS AGI MIDI program change to instrument number mapping.
668     FIXME: Some instrument choices sound wrong. */
669 static const IIgsMidiProgramMapping progToInstMappingV2 = {
670 	{
671 		21, 22, 24, 25, 23, 26, 6, 6, 6, 6,
672 		7, 9, 12, 8, 13, 11, 17, 10, 6, 6,
673 		19, 18, 20, 14, 16, 6, 6, 6, 6, 6,
674 		0, 1, 2, 4, 3, 5, 17, 2, 2, 2,
675 		27, 15, 15, 27
676 	},
677 	6
678 };
679 
680 // Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002).
681 //
682 // Instrument 0 uses vibrato.
683 // Instrument 1 uses vibrato.
684 // Instrument 3 uses vibrato.
685 // Instrument 5 has swap mode enabled for the first oscillator.
686 // Instruemnt 9 uses vibrato.
687 // Instrument 10 uses vibrato.
688 // Instrument 12 uses vibrato.
689 // Instrument 15 uses vibrato.
690 // Instrument 16 uses vibrato.
691 // Instrument 18 uses vibrato.
692 static const IIgsInstrumentSetInfo instSetV1 = {
693 	1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", &progToInstMappingV1
694 };
695 
696 // Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I.
697 //
698 // Instrument 0 uses vibrato.
699 // Instrument 1 uses vibrato.
700 // Instrument 3 uses vibrato.
701 // Instrument 6 has swap mode enabled for the first oscillator.
702 // Instrument 11 uses vibrato.
703 // Instrument 12 uses vibrato.
704 // Instrument 14 uses vibrato.
705 // Instrument 17 uses vibrato.
706 // Instrument 18 uses vibrato.
707 // Instrument 20 uses vibrato.
708 //
709 // In KQ1 intro and in LSL intro one (and the same, or at least similar)
710 // instrument is using vibrato. In PQ intro there is also one instrument
711 // using vibrato.
712 static const IIgsInstrumentSetInfo instSetV2 = {
713 	1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", &progToInstMappingV2
714 };
715 
716 /** Information about different Apple IIGS AGI executables. */
717 static const IIgsExeInfo IIgsExeInfos[] = {
718 	{GID_SQ1,      "SQ",   0x1002, 138496, 0x80AD, &instSetV1},
719 	{GID_LSL1,     "LL",   0x1003, 141003, 0x844E, &instSetV2},
720 	{GID_AGIDEMO,  "DEMO", 0x1005, 141884, 0x8469, &instSetV2},
721 	{GID_KQ1,      "KQ",   0x1006, 141894, 0x8469, &instSetV2},
722 	{GID_PQ1,      "PQ",   0x1007, 141882, 0x8469, &instSetV2},
723 	{GID_MIXEDUP,  "MG",   0x1013, 142552, 0x84B7, &instSetV2},
724 	{GID_KQ2,      "KQ2",  0x1013, 143775, 0x84B7, &instSetV2},
725 	{GID_KQ3,      "KQ3",  0x1014, 144312, 0x84B7, &instSetV2},
726 	{GID_SQ2,      "SQ2",  0x1014, 107882, 0x6563, &instSetV2},
727 	{GID_MH1,      "MH",   0x2004, 147678, 0x8979, &instSetV2},
728 	{GID_KQ4,      "KQ4",  0x2006, 147652, 0x8979, &instSetV2},
729 	{GID_BC,       "BC",   0x3001, 148192, 0x8979, &instSetV2},
730 	{GID_GOLDRUSH, "GR",   0x3003, 148268, 0x8979, &instSetV2}
731 };
732 
733 /**
734  * Finds information about an Apple IIGS AGI executable based on the game ID.
735  * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL.
736  */
getIIgsExeInfo(enum AgiGameID gameid) const737 const IIgsExeInfo *SoundGen2GS::getIIgsExeInfo(enum AgiGameID gameid) const {
738 	for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++)
739 		if (IIgsExeInfos[i].gameid == gameid)
740 			return &IIgsExeInfos[i];
741 	return NULL;
742 }
743 
loadInstrumentHeaders(Common::String & exePath,const IIgsExeInfo & exeInfo)744 bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeInfo &exeInfo) {
745 	Common::File file;
746 
747 	// Open the executable file and check that it has correct size
748 	file.open(exePath);
749 	if (file.size() != (int32)exeInfo.exeSize) {
750 		debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
751 		       exePath.c_str(), file.size(), exeInfo.exeSize);
752 	}
753 
754 	// Read the whole executable file into memory
755 	// CHECKME: Why do we read the file into memory first? It does not seem to be
756 	// kept outside of this function. Is the processing of the data too slow
757 	// otherwise?
758 	Common::ScopedPtr<Common::SeekableReadStream> data(file.readStream(file.size()));
759 	file.close();
760 
761 	// Check that we got enough data to be able to parse the instruments
762 	if (!data || data->size() < (int32)(exeInfo.instSetStart + exeInfo.instSet->byteCount)) {
763 		warning("Error loading instruments from Apple IIGS executable (%s)", exePath.c_str());
764 		return false;
765 	}
766 
767 	// Check instrument set's length (The info's saved in the executable)
768 	data->seek(exeInfo.instSetStart - 4);
769 	uint16 instSetByteCount = data->readUint16LE();
770 	if (instSetByteCount != exeInfo.instSet->byteCount) {
771 		debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
772 		       instSetByteCount, exeInfo.instSet->byteCount, exePath.c_str());
773 	}
774 
775 	// Check instrument set's md5sum
776 	data->seek(exeInfo.instSetStart);
777 	Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet->byteCount);
778 	if (md5str != exeInfo.instSet->md5) {
779 		warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
780 		        md5str.c_str(), exePath.c_str());
781 	}
782 
783 	// Read in the instrument set one instrument at a time
784 	data->seek(exeInfo.instSetStart);
785 
786 	_instruments.clear();
787 	_instruments.reserve(exeInfo.instSet->instCount);
788 
789 	IIgsInstrumentHeader instrument;
790 	for (uint i = 0; i < exeInfo.instSet->instCount; i++) {
791 		if (!instrument.read(*data)) {
792 			warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
793 			        i + 1, exeInfo.instSet->instCount, exePath.c_str());
794 			break;
795 		}
796 		instrument.finalize(_wavetable, SIERRASTANDARD_SIZE);
797 		_instruments.push_back(instrument);
798 	}
799 
800 	// Loading was successful only if all instruments were loaded successfully
801 	return (_instruments.size() == exeInfo.instSet->instCount);
802 }
803 
loadWaveFile(Common::String & wavePath,const IIgsExeInfo & exeInfo)804 bool SoundGen2GS::loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeInfo) {
805 	Common::File file;
806 
807 	// Open the wave file and read it into memory
808 	// CHECKME: Why do we read the file into memory first? It does not seem to be
809 	// kept outside of this function. Is the processing of the data too slow
810 	// otherwise?
811 	file.open(wavePath);
812 	Common::ScopedPtr<Common::SeekableReadStream> uint8Wave(file.readStream(file.size()));
813 	file.close();
814 
815 	// Check that we got the whole wave file
816 	if (!uint8Wave || (uint8Wave->size() != SIERRASTANDARD_SIZE)) {
817 		warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.c_str());
818 		return false;
819 	}
820 
821 	// Check wave file's md5sum
822 	Common::String md5str = Common::computeStreamMD5AsString(*uint8Wave, SIERRASTANDARD_SIZE);
823 	if (md5str != exeInfo.instSet->waveFileMd5) {
824 		warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
825 		        "Please report the information on the previous line to the ScummVM team.\n" \
826 		        "Using the wave file as it is - music may sound weird", md5str.c_str(), exeInfo.exePrefix);
827 	}
828 
829 	// Convert the wave file to 8-bit signed and save the result
830 	uint8Wave->seek(0);
831 	return convertWave(*uint8Wave, _wavetable, SIERRASTANDARD_SIZE);
832 }
833 
834 } // End of namespace Agi
835