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 "engines/scumm/imuse/drivers/amiga.h"
24 #include "audio/mixer.h"
25 #include "common/file.h"
26 #include "common/translation.h"
27 #include "gui/error.h"
28 
29 namespace Scumm {
30 
31 struct Instrument_Amiga {
32 	struct Samples {
33 		uint16 rate;
34 		uint16 baseNote;
35 		int16 noteRangeMin;
36 		int16 noteRangeMax;
37 		int16 sustainLevel;
38 		uint16 type;
39 		uint32 numSamples;
40 		uint32 dr_offset;
41 		uint32 dr_numSamples;
42 		int16 levelFadeDelayAT;
43 		int16 levelFadeDelayRL;
44 		int16 levelFadeTriggerRL;
45 		int16 levelFadeDelayDC;
46 		const int8 *data;
47 	};
48 	Samples samples[8];
49 	int numBlocks;
50 };
51 
52 class SoundChannel_Amiga {
53 public:
54 	SoundChannel_Amiga(IMuseDriver_Amiga *driver, int id, Instrument_Amiga *instruments);
55 	~SoundChannel_Amiga();
56 
57 	static SoundChannel_Amiga *allocate(int prio);
58 	void connect(IMusePart_Amiga *part);
59 	void disconnect();
60 
61 	void noteOn(byte note, byte velocity, byte program, int8 transpose, int16 pitchBend);
62 	void ctrl_volume(uint8 volume);
63 	void ctrl_sustain(bool sustainToggle);
64 	void transposePitchBend(int8 transpose, int16 pitchBend);
65 
66 	void updateLevel();
67 	void updateEnvelope();
68 
getNote() const69 	uint8 getNote() const { return _note; }
next() const70 	SoundChannel_Amiga *next() const { return _next; }
71 
72 private:
73 	void keyOn(const int8 *data1, uint16 data1Size, const int8 *data2, uint16 data2Size, uint16 period);
74 	void keyOff();
75 	void setRepeatData(const int8 *data, uint16 size);
76 	void setVelocity(uint8 velo, int delay);
77 	void setVolume(uint8 volume);
78 
79 	uint16 calculatePeriod(int16 tone, uint8 baseNote, uint16 rate);
80 
81 	void createVolumeTable();
82 
83 	SoundChannel_Amiga *_prev, *_next;
84 	IMusePart_Amiga *_assign;
85 
86 	uint8 _id;
87 	uint8 _note;
88 	bool _sustain;
89 
90 	IMuseDriver_Amiga *_driver;
91 
92 	static uint8 _allocCurPos;
93 	static SoundChannel_Amiga *_channels[4];
94 
95 	enum EnvelopeState {
96 		kReady = 0,
97 		kRelease = 1,
98 		kDecay = 2,
99 		kAttack = 3,
100 		kRestart = 4
101 	};
102 
103 	struct IOUnit {
IOUnitScumm::SoundChannel_Amiga::IOUnit104 		IOUnit() : program(0), block(0), volume(63), currentLevel(0), fadeTargetLevel(0), fadeLevelDelta(0), fadeLevelMod(0), levelFadeTriggerDC(0), fadeLevelTicks(0),
105 			fadeLevelTicker(0), fadeLevelDuration(0), releaseData(0), releaseDataSize(0), repeatData(0), repeatDataSize(0), envelopeState(kReady) {}
106 		uint8 program;
107 		uint8 block;
108 		uint8 volume;
109 		uint8 currentLevel;
110 		uint8 fadeTargetLevel;
111 		uint8 fadeLevelDelta;
112 		uint16 fadeLevelTicks;
113 		int8 fadeLevelMod;
114 		bool levelFadeTriggerDC;
115 		uint32 fadeLevelTicker;
116 		uint32 fadeLevelDuration;
117 		const int8 *releaseData;
118 		uint16 releaseDataSize;
119 		const int8 *repeatData;
120 		uint16 repeatDataSize;
121 		uint8 envelopeState;
122 	};
123 
124 	IOUnit _ioUnit;
125 
126 	const Instrument_Amiga *_instruments;
127 
128 	static const int8 _muteData[16];
129 	static const uint8 *_volTable;
130 };
131 
132 class IMusePart_Amiga : public MidiChannel {
133 public:
134 	IMusePart_Amiga(IMuseDriver_Amiga *driver, int id);
~IMusePart_Amiga()135 	~IMusePart_Amiga() override {}
136 
device()137 	MidiDriver *device() override { return _driver; }
getNumber()138 	byte getNumber() override { return _id; }
139 	bool allocate();
140 	void release() override;
141 
142 	void send(uint32 b) override;
143 
144 	void noteOff(byte note) override;
145 	void noteOn(byte note, byte velocity) override;
146 	void controlChange(byte control, byte value) override;
147 	void programChange(byte program) override;
148 	void pitchBend(int16 bend) override;
149 	void pitchBendFactor(byte value) override;
150 	void transpose(int8 value) override;
151 
152 	void priority(byte value) override;
sysEx_customInstrument(uint32 type,const byte * instr)153 	void sysEx_customInstrument(uint32 type, const byte *instr) override {}
154 
getPriority() const155 	int getPriority() const { return _priority; }
getChannel() const156 	SoundChannel_Amiga *getChannel() const { return _out; }
setChannel(SoundChannel_Amiga * chan)157 	void setChannel(SoundChannel_Amiga *chan) { _out = chan; }
158 
159 private:
160 	void controlModulationWheel(byte value);
161 	void controlVolume(byte value);
162 	void controlSustain(byte value);
163 
164 	uint8 _priority;
165 	uint8 _program;
166 	int8 _modulation;
167 	int8 _transpose;
168 	int16 _pitchBend;
169 	uint8 _pitchBendSensitivity;
170 	uint16 _volume;
171 	bool _sustain;
172 	bool _allocated;
173 	const uint8 _id;
174 	SoundChannel_Amiga *_out;
175 	IMuseDriver_Amiga *_driver;
176 };
177 
SoundChannel_Amiga(IMuseDriver_Amiga * driver,int id,Instrument_Amiga * instruments)178 SoundChannel_Amiga::SoundChannel_Amiga(IMuseDriver_Amiga *driver, int id, Instrument_Amiga *instruments) : _driver(driver), _id(id), _instruments(instruments),
179 	_assign(0), _next(0), _prev(0), _sustain(false), _note(0) {
180 	assert(id > -1 && id < 4);
181 	_channels[id] = this;
182 	createVolumeTable();
183 }
184 
~SoundChannel_Amiga()185 SoundChannel_Amiga::~SoundChannel_Amiga() {
186 	_channels[_id] = 0;
187 
188 	// delete volume table only if this is the last remaining SoundChannel_Amiga object
189 	for (int i = 0; i < 4; ++i) {
190 		if (_channels[i])
191 			return;
192 	}
193 
194 	delete[] _volTable;
195 	_volTable = 0;
196 }
197 
allocate(int prio)198 SoundChannel_Amiga *SoundChannel_Amiga::allocate(int prio) {
199 	SoundChannel_Amiga *res = 0;
200 
201 	for (int i = 0; i < 4; i++) {
202 		if (++_allocCurPos == 4)
203 			_allocCurPos = 0;
204 
205 		SoundChannel_Amiga *temp = _channels[_allocCurPos];
206 		if (!temp->_assign)
207 			return temp;
208 
209 		if (temp->_next)
210 			continue;
211 
212 		if (prio >= temp->_assign->getPriority()) {
213 			res = temp;
214 			prio = temp->_assign->getPriority();
215 		}
216 	}
217 
218 	if (res)
219 		res->disconnect();
220 
221 	return res;
222 }
223 
connect(IMusePart_Amiga * part)224 void SoundChannel_Amiga::connect(IMusePart_Amiga *part) {
225 	if (!part)
226 		return;
227 
228 	_assign = part;
229 	_next = part->getChannel();
230 	_prev = 0;
231 	part->setChannel(this);
232 	if (_next)
233 		_next->_prev = this;
234 }
235 
disconnect()236 void SoundChannel_Amiga::disconnect() {
237 	keyOff();
238 
239 	SoundChannel_Amiga *p = _prev;
240 	SoundChannel_Amiga *n = _next;
241 
242 	if (n)
243 		n->_prev = p;
244 	if (p)
245 		p->_next = n;
246 	else
247 		_assign->setChannel(n);
248 	_assign = 0;
249 }
250 
noteOn(byte note,byte volume,byte program,int8 transpose,int16 pitchBend)251 void SoundChannel_Amiga::noteOn(byte note, byte volume, byte program, int8 transpose, int16 pitchBend) {
252 	if (program > 128)
253 		program = 128;
254 
255 	if (program != 128 && !_instruments[program].samples[0].data)
256 		program = 128;
257 
258 	_note = note;
259 	_sustain = false;
260 
261 	_ioUnit.block = 0;
262 	_ioUnit.program = program;
263 	const Instrument_Amiga::Samples *s = &_instruments[program].samples[_ioUnit.block];
264 	int16 pnote = note + transpose + (pitchBend >> 7);
265 
266 	if (_instruments[program].numBlocks > 1) {
267 		for (int i = 0; i < _instruments[program].numBlocks; ++i) {
268 			if (pnote >= _instruments[program].samples[i].noteRangeMin && pnote <= _instruments[program].samples[i].noteRangeMax) {
269 				_ioUnit.block = i;
270 				s = &_instruments[program].samples[_ioUnit.block];
271 				break;
272 			}
273 		}
274 	}
275 
276 	_driver->disableChannel(_id);
277 	setVelocity(0, 0);
278 	setVolume(volume);
279 
280 	if (s->type > 1)
281 		return;
282 
283 	uint16 period = calculatePeriod(pitchBend + ((_note + transpose) << 7), s->baseNote, s->rate);
284 
285 	if (s->type == 1) {
286 		keyOn(s->data, s->numSamples, 0, 0, period);
287 		setRepeatData(0, 0);
288 	} else {
289 		if (s->dr_numSamples) {
290 			keyOn(s->data, s->dr_numSamples, s->data + s->dr_offset, s->dr_numSamples - s->dr_offset, period);
291 			setRepeatData(s->data + s->dr_numSamples, s->numSamples - s->dr_numSamples);
292 		} else {
293 			keyOn(s->data, s->numSamples, s->data + s->dr_offset, s->numSamples - s->dr_offset, period);
294 			setRepeatData(0, 0);
295 		}
296 	}
297 }
298 
ctrl_volume(uint8 volume)299 void SoundChannel_Amiga::ctrl_volume(uint8 volume) {
300 	setVolume(volume);
301 }
302 
ctrl_sustain(bool sustainToggle)303 void SoundChannel_Amiga::ctrl_sustain(bool sustainToggle) {
304 	if (_sustain && !sustainToggle)
305 		disconnect();
306 	else if (sustainToggle)
307 		_sustain = true;
308 }
309 
transposePitchBend(int8 transpose,int16 pitchBend)310 void SoundChannel_Amiga::transposePitchBend(int8 transpose, int16 pitchBend) {
311 	const Instrument_Amiga::Samples *s = &_instruments[_ioUnit.program].samples[_ioUnit.block];
312 	_driver->setChannelPeriod(_id, calculatePeriod(((_note + transpose) << 7) + pitchBend, s->baseNote, s->rate));
313 }
314 
updateLevel()315 void SoundChannel_Amiga::updateLevel() {
316 	if (!_ioUnit.fadeLevelMod)
317 		return;
318 
319 	_ioUnit.fadeLevelDuration += _ioUnit.fadeLevelDelta;
320 	if (_ioUnit.fadeLevelDuration <= _ioUnit.fadeLevelTicker)
321 		return;
322 
323 	while (_ioUnit.fadeLevelDuration > _ioUnit.fadeLevelTicker && _ioUnit.currentLevel != _ioUnit.fadeTargetLevel) {
324 		_ioUnit.fadeLevelTicker += _ioUnit.fadeLevelTicks;
325 		_ioUnit.currentLevel += _ioUnit.fadeLevelMod;
326 	}
327 
328 	_driver->setChannelVolume(_id, _volTable[(_ioUnit.volume << 5) + _ioUnit.currentLevel]);
329 
330 	if (_ioUnit.currentLevel != _ioUnit.fadeTargetLevel)
331 		return;
332 
333 	_ioUnit.fadeLevelMod = 0;
334 	if (!_ioUnit.levelFadeTriggerDC)
335 		return;
336 
337 	const Instrument_Amiga::Samples *s = &_instruments[_ioUnit.program].samples[_ioUnit.block];
338 	setVelocity(s->sustainLevel >> 1, s->levelFadeDelayDC);
339 }
340 
updateEnvelope()341 void SoundChannel_Amiga::updateEnvelope() {
342 	if (_ioUnit.envelopeState == kReady)
343 		return;
344 
345 	uint8 envCur = _ioUnit.envelopeState--;
346 	if (envCur == kAttack) {
347 		const Instrument_Amiga::Samples *s = &_instruments[_ioUnit.program].samples[_ioUnit.block];
348 		_driver->enableChannel(_id);
349 		if (s->levelFadeDelayDC) {
350 			setVelocity(31, s->levelFadeDelayAT);
351 			if (s->levelFadeDelayAT)
352 				_ioUnit.levelFadeTriggerDC = true;
353 			else
354 				setVelocity(s->sustainLevel >> 1, s->levelFadeDelayDC);
355 		} else {
356 			setVelocity(s->sustainLevel >> 1, s->levelFadeDelayAT);
357 		}
358 	}
359 
360 	if (envCur == kRelease) {
361 		_driver->setChannelSampleStart(_id, _ioUnit.releaseData);
362 		_driver->setChannelSampleLen(_id, _ioUnit.releaseDataSize);
363 	}
364 }
365 
keyOn(const int8 * attackData,uint16 attackDataSize,const int8 * releaseData,uint16 releaseDataSize,uint16 period)366 void SoundChannel_Amiga::keyOn(const int8 *attackData, uint16 attackDataSize, const int8 *releaseData, uint16 releaseDataSize, uint16 period) {
367 	_driver->setChannelSampleStart(_id, attackData);
368 	_driver->setChannelSampleLen(_id, attackDataSize >> 1);
369 	_driver->setChannelPeriod(_id, period);
370 
371 	if (releaseData) {
372 		_ioUnit.releaseData = releaseData;
373 		_ioUnit.releaseDataSize = releaseDataSize >> 1;
374 	} else {
375 		_ioUnit.releaseData = _muteData;
376 		_ioUnit.releaseDataSize = ARRAYSIZE(_muteData) >> 1;
377 	}
378 
379 	_ioUnit.envelopeState = kRestart;
380 }
381 
keyOff()382 void SoundChannel_Amiga::keyOff() {
383 	_ioUnit.levelFadeTriggerDC = 0;
384 	if (_ioUnit.repeatData) {
385 		_driver->setChannelSampleStart(_id, _ioUnit.repeatData);
386 		_driver->setChannelSampleLen(_id, _ioUnit.repeatDataSize);
387 		_ioUnit.releaseData = _muteData;
388 		_ioUnit.releaseDataSize = ARRAYSIZE(_muteData) >> 1;
389 		_ioUnit.envelopeState = kDecay;
390 	} else {
391 		_ioUnit.envelopeState = kReady;
392 	}
393 
394 	if (_instruments[_ioUnit.program].samples[_ioUnit.block].levelFadeTriggerRL)
395 		setVelocity(0, _instruments[_ioUnit.program].samples[_ioUnit.block].levelFadeDelayRL);
396 }
397 
setRepeatData(const int8 * data,uint16 size)398 void SoundChannel_Amiga::setRepeatData(const int8 *data, uint16 size) {
399 	_ioUnit.repeatData = data;
400 	_ioUnit.repeatDataSize = size >> 1;
401 }
402 
setVelocity(uint8 velo,int delay)403 void SoundChannel_Amiga::setVelocity(uint8 velo, int delay) {
404 	_ioUnit.levelFadeTriggerDC = 0;
405 
406 	if (delay) {
407 		_ioUnit.fadeTargetLevel = velo;
408 		_ioUnit.fadeLevelDelta = ABS(_ioUnit.currentLevel - velo);
409 		_ioUnit.fadeLevelTicks = (delay << 10) / 5500;
410 		_ioUnit.fadeLevelMod = (_ioUnit.currentLevel >= velo) ? -1 : 1;
411 		_ioUnit.fadeLevelTicker = _ioUnit.fadeLevelDuration = 0;
412 	} else {
413 		_driver->setChannelVolume(_id, _volTable[(_ioUnit.volume << 5) + velo]);
414 		_ioUnit.currentLevel = _ioUnit.fadeTargetLevel = velo;
415 		_ioUnit.fadeLevelMod = 0;
416 	}
417 }
418 
setVolume(uint8 volume)419 void SoundChannel_Amiga::setVolume(uint8 volume) {
420 	volume >>= 1;
421 	_ioUnit.volume = volume;
422 	_driver->setChannelVolume(_id, _volTable[(volume << 5) + _ioUnit.currentLevel]);
423 }
424 
calculatePeriod(int16 tone,uint8 baseNote,uint16 rate)425 uint16 SoundChannel_Amiga::calculatePeriod(int16 tone, uint8 baseNote, uint16 rate) {
426 	static const uint32 octavePeriods[13] = { 0x4000, 0x43CE, 0x47D7, 0x4C1B, 0x50A2, 0x556D, 0x5A82, 0x5FE4, 0x6598, 0x6BA2, 0x7209, 0x78D0, 0x8000 };
427 
428 	int16 frq_coarse = tone >> 7;
429 	uint8 frq_fine = tone & 0x7F;
430 	int16 octTrans = baseNote;
431 	rate <<= 3;
432 
433 	for (int16 octTransHi = baseNote + 12; octTransHi <= frq_coarse; octTransHi += 12) {
434 		rate >>= 1;
435 		octTrans = octTransHi;
436 	}
437 
438 	while (octTrans > frq_coarse) {
439 		rate += rate;
440 		octTrans -= 12;
441 	}
442 
443 	uint32 res = (((octavePeriods[11 - (frq_coarse - octTrans)] * rate) >> 18) * frq_fine + ((octavePeriods[12 - (frq_coarse - octTrans)] * rate) >> 18) * (0x80 - frq_fine)) >> 7;
444 
445 	if (!res)
446 		return 124;
447 
448 	while (res < 124)
449 		res += res;
450 
451 	if (res > 65535)
452 		res = 65535;
453 
454 	return res & 0xFFFF;
455 }
456 
createVolumeTable()457 void SoundChannel_Amiga::createVolumeTable() {
458 	if (_volTable)
459 		return;
460 
461 	uint8 *volTbl = new uint8[2048];
462 	for (int a = 0; a < 64; ++a) {
463 		volTbl[a << 5] = 0;
464 		for (int b = 1; b < 32; ++b)
465 			volTbl[(a << 5) + b] = (a * (b + 1)) >> 5;
466 	}
467 	_volTable = volTbl;
468 }
469 
470 uint8 SoundChannel_Amiga::_allocCurPos = 0;
471 
472 const uint8 *SoundChannel_Amiga::_volTable = 0;
473 
474 SoundChannel_Amiga *SoundChannel_Amiga::_channels[4] = { 0, 0, 0, 0 };
475 
476 const int8 SoundChannel_Amiga::_muteData[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
477 
IMusePart_Amiga(IMuseDriver_Amiga * driver,int id)478 IMusePart_Amiga::IMusePart_Amiga(IMuseDriver_Amiga *driver, int id) : _driver(driver), _id(id), _allocated(false), _out(0), _priority(0), _program(0),
479 	_pitchBend(0), _pitchBendSensitivity(2), _volume(0), _modulation(0), _transpose(0), _sustain(false) {
480 }
481 
allocate()482 bool IMusePart_Amiga::allocate() {
483 	if (_allocated)
484 		return false;
485 
486 	_allocated = true;
487 
488 	while (_out)
489 		_out->disconnect();
490 
491 	return true;
492 }
493 
release()494 void IMusePart_Amiga::release() {
495 	_allocated = false;
496 
497 	while (_out)
498 		_out->disconnect();
499 }
500 
send(uint32 b)501 void IMusePart_Amiga::send(uint32 b) {
502 	_driver->send(b | _id);
503 }
504 
noteOff(byte note)505 void IMusePart_Amiga::noteOff(byte note) {
506 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next()) {
507 		if (note == cur->getNote()) {
508 			if (_sustain)
509 				cur->ctrl_sustain(true);
510 			else
511 				cur->disconnect();
512 		}
513 	}
514 }
515 
noteOn(byte note,byte velocity)516 void IMusePart_Amiga::noteOn(byte note, byte velocity) {
517 	if (!velocity) {
518 		noteOff(note);
519 		return;
520 	}
521 
522 	SoundChannel_Amiga *chan = SoundChannel_Amiga::allocate(_priority);
523 	if (!chan)
524 		return;
525 
526 	chan->connect(this);
527 	// The velocity parameter is ignored here.
528 	chan->noteOn(note, _volume, _program, _transpose, (_pitchBend * _pitchBendSensitivity) >> 6);
529 }
530 
controlChange(byte control,byte value)531 void IMusePart_Amiga::controlChange(byte control, byte value) {
532 	switch (control) {
533 	case 1:
534 		controlModulationWheel(value);
535 		break;
536 	case 7:
537 		controlVolume(value);
538 		break;
539 	case 10:
540 		// The original driver has no support for this.
541 		break;
542 	case 64:
543 		controlSustain(value);
544 		break;
545 	case 123:
546 		while (_out)
547 			_out->disconnect();
548 		break;
549 	default:
550 		break;
551 	}
552 }
553 
programChange(byte program)554 void IMusePart_Amiga::programChange(byte program) {
555 	_program = program;
556 }
557 
pitchBend(int16 bend)558 void IMusePart_Amiga::pitchBend(int16 bend) {
559 	_pitchBend = bend;
560 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
561 		cur->transposePitchBend(_transpose, (_pitchBend * _pitchBendSensitivity) >> 6);
562 }
563 
pitchBendFactor(byte value)564 void IMusePart_Amiga::pitchBendFactor(byte value) {
565 	_pitchBendSensitivity = value;
566 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
567 		cur->transposePitchBend(_transpose, (_pitchBend * _pitchBendSensitivity) >> 6);
568 }
569 
transpose(int8 value)570 void IMusePart_Amiga::transpose(int8 value) {
571 	_transpose = value << 1;
572 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
573 		cur->transposePitchBend(_transpose, (_pitchBend * _pitchBendSensitivity) >> 6);
574 }
575 
priority(byte value)576 void IMusePart_Amiga::priority(byte value) {
577 	_priority = value;
578 }
579 
controlModulationWheel(byte value)580 void IMusePart_Amiga::controlModulationWheel(byte value) {
581 	_modulation = (int8)value;
582 }
583 
controlVolume(byte value)584 void IMusePart_Amiga::controlVolume(byte value) {
585 	_volume = value;
586 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
587 		cur->ctrl_volume(_volume);
588 }
589 
controlSustain(byte value)590 void IMusePart_Amiga::controlSustain(byte value) {
591 	_sustain = value;
592 	if (!value) {
593 		for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
594 			cur->ctrl_sustain(false);
595 	}
596 }
597 
IMuseDriver_Amiga(Audio::Mixer * mixer)598 IMuseDriver_Amiga::IMuseDriver_Amiga(Audio::Mixer *mixer) : Paula(true, mixer->getOutputRate(), (mixer->getOutputRate() * 1000) / 181818), _mixer(mixer), _isOpen(false), _soundHandle(),
599 	_numParts(24), _baseTempo(5500), _internalTempo(5500), _timerProc(0), _timerProcPara(0), _parts(0), _chan(0), _instruments(0), _missingFiles(0), _ticker(0) {
600 	setAudioFilter(true);
601 
602 	_instruments = new Instrument_Amiga[129];
603 	memset(_instruments, 0, sizeof(Instrument_Amiga) * 129);
604 	loadInstrument(128);
605 
606 	_parts = new IMusePart_Amiga*[_numParts];
607 	for (int i = 0; i < _numParts; i++)
608 		_parts[i] = new IMusePart_Amiga(this, i);
609 
610 	_chan = new SoundChannel_Amiga*[4];
611 	for (int i = 0; i < 4; i++)
612 		_chan[i] = new SoundChannel_Amiga(this, i, _instruments);
613 }
614 
~IMuseDriver_Amiga()615 IMuseDriver_Amiga::~IMuseDriver_Amiga() {
616 	close();
617 
618 	Common::StackLock lock(_mutex);
619 
620 	if (_chan) {
621 		for (int i = 0; i < 4; i++)
622 			delete _chan[i];
623 		delete[] _chan;
624 	}
625 	_chan = 0;
626 
627 	if (_parts) {
628 		for (int i = 0; i < _numParts; i++)
629 			delete _parts[i];
630 		delete[] _parts;
631 	}
632 	_parts = 0;
633 
634 	delete[] _instruments;
635 }
636 
open()637 int IMuseDriver_Amiga::open() {
638 	if (_isOpen)
639 		return MERR_ALREADY_OPEN;
640 
641 	// Load all instruments at once. The original will load the programs that are necessary for the currently playing
642 	// sounds into a fixed 100000 bytes buffer. The approach here needs more memory (approx. 480 KB for MI2), but we
643 	// can easily afford this and it saves me the trouble of implementing a loader into the imuse code. The original
644 	// loader is quite unpleasant, since it scans the whole imuse midi track for program change events and collects
645 	// the program numbers for each such event in a buffer. Afterwards these instruments will get loaded.
646 	for (int i = 0; i < 128; ++i)
647 		loadInstrument(i);
648 
649 	// Actually not all of the .IMS files are required to play. Many of these contain copies of the same instruments.
650 	// Each floppy disk contains one of the .IMS files. This would reduce the number of necessary floppy disk changes
651 	// when playing from the floppy disks. Obviously we don't need the redundancy files. The error dialog will display
652 	// only the required files. These are different for MI2 and INDY4.
653 	if (_missingFiles) {
654 		Common::U32String message = _("This AMIGA version is missing (at least) the following file(s):\n\n");
655 		for (int i = 0; i < 11; ++i) {
656 			if (_missingFiles & (1 << i))
657 				message += Common::String::format("AMIGA%d.IMS\n", i + 1);
658 		}
659 		message += _("\nPlease copy these file(s) into the game data directory.\n\n");
660 		::GUI::displayErrorDialog(message);
661 		return MERR_DEVICE_NOT_AVAILABLE;
662 	}
663 
664 	startPaula();
665 	_mixer->playStream(Audio::Mixer::kPlainSoundType,
666 		&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
667 
668 	_isOpen = true;
669 
670 	return 0;
671 }
672 
close()673 void IMuseDriver_Amiga::close() {
674 	if (!_isOpen)
675 		return;
676 
677 	_isOpen = false;
678 
679 	stopPaula();
680 	setTimerCallback(0, 0);
681 	_mixer->stopHandle(_soundHandle);
682 
683 	Common::StackLock lock(_mutex);
684 
685 	unloadInstruments();
686 
687 	g_system->delayMillis(20);
688 }
689 
send(uint32 b)690 void IMuseDriver_Amiga::send(uint32 b) {
691 	if (!_isOpen)
692 		return;
693 
694 	byte param2 = (b >> 16) & 0xFF;
695 	byte param1 = (b >> 8) & 0xFF;
696 	byte cmd = b & 0xF0;
697 
698 	IMusePart_Amiga *p = _parts[b & 0x0F];
699 
700 	switch (cmd) {
701 	case 0x80:
702 		p->noteOff(param1);
703 		break;
704 	case 0x90:
705 		p->noteOn(param1, param2);
706 		break;
707 	case 0xB0:
708 		p->controlChange(param1, param2);
709 		break;
710 	case 0xC0:
711 		p->programChange(param1);
712 		break;
713 	case 0xE0:
714 		p->pitchBend((param1 | (param2 << 7)) - 0x2000);
715 		break;
716 	case 0xF0:
717 		warning("IMuseDriver_Amiga: Receiving SysEx command on a send() call");
718 		break;
719 
720 	default:
721 		break;
722 	}
723 }
724 
setTimerCallback(void * timer_param,Common::TimerManager::TimerProc timer_proc)725 void IMuseDriver_Amiga::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
726 	_timerProc = timer_proc;
727 	_timerProcPara = timer_param;
728 }
729 
getBaseTempo()730 uint32 IMuseDriver_Amiga::getBaseTempo() {
731 	return _baseTempo;
732 }
733 
allocateChannel()734 MidiChannel *IMuseDriver_Amiga::allocateChannel() {
735 	if (!_isOpen)
736 		return 0;
737 
738 	for (int i = 0; i < _numParts; ++i) {
739 		if (_parts[i]->allocate())
740 			return _parts[i];
741 	}
742 
743 	return 0;
744 }
745 
getPercussionChannel()746 MidiChannel *IMuseDriver_Amiga::getPercussionChannel() {
747 	return 0;
748 }
749 
interrupt()750 void IMuseDriver_Amiga::interrupt() {
751 	if (!_isOpen)
752 		return;
753 
754 	for (_ticker += _internalTempo; _ticker >= _baseTempo; _ticker -= _baseTempo) {
755 		updateParser();
756 		updateSounds();
757 	}
758 }
759 
updateParser()760 void IMuseDriver_Amiga::updateParser() {
761 	if (_timerProc)
762 		_timerProc(_timerProcPara);
763 }
764 
updateSounds()765 void IMuseDriver_Amiga::updateSounds() {
766 	for (int i = 0; i < 4; i++)
767 		_chan[i]->updateLevel();
768 	for (int i = 0; i < 4; i++)
769 		_chan[i]->updateEnvelope();
770 }
771 
loadInstrument(int program)772 void IMuseDriver_Amiga::loadInstrument(int program) {
773 	Common::StackLock lock(_mutex);
774 
775 	if (program == 128) {
776 		// The hard-coded default instrument definitions and sample data are the same in MI2 and INDY4.
777 		static const int8 defaultData[16] = { 0, 49, 90, 117, 127, 117, 90, 49, 0, -49, -90, -117, -127, -117, -90, -49 };
778 		static Instrument_Amiga::Samples defaultSamples = { 428, 60, 0, 127, 33, 0, /*0, 0,*/16, 0, 0, 5, 300, 5, 100, defaultData };
779 		_instruments[128].numBlocks = 1;
780 		memcpy(&_instruments[128].samples[0], &defaultSamples, sizeof(Instrument_Amiga::Samples));
781 	}
782 
783 	if (program > 127)
784 		return;
785 
786 	Common::File ims;
787 	int32 header[10];
788 	uint32 offset = 0;
789 	memset(header, 0, sizeof(header));
790 
791 	for (int i = 0; i < 8; ++i) {
792 		if (_instruments[program].samples[i].data) {
793 			delete[] _instruments[program].samples[i].data;
794 			_instruments[program].samples[i].data = 0;
795 		}
796 	}
797 
798 	for (int fileNo = 1; fileNo != -1 && !ims.isOpen(); ) {
799 		if (!ims.open(Common::String::format("amiga%d.ims", fileNo))) {
800 			_missingFiles |= (1 << (fileNo - 1));
801 			return;
802 		}
803 
804 		ims.seek(16 + (program << 2), SEEK_SET);
805 		offset = ims.readUint32BE();
806 		if (offset & 0x40000000) {
807 			offset &= ~0x40000000;
808 			ims.seek(16 + (offset << 2), SEEK_SET);
809 			offset = ims.readUint32BE();
810 		}
811 
812 		if (offset & 0x80000000) {
813 			offset &= ~0x80000000;
814 			ims.close();
815 			fileNo = offset ? offset : -1;
816 		} else {
817 			ims.seek(552 + offset, SEEK_SET);
818 			for (int i = 0; i < 10; ++i)
819 				header[i] = ims.readSint32BE();
820 		}
821 	}
822 
823 	if (!ims.isOpen())
824 		return;
825 
826 	for (int block = 0; block < 8; ++block) {
827 		int size = 0;
828 
829 		if (header[block] != -1)
830 			size = (block != 7 && header[block + 1] != -1 ? header[block + 1] : header[9]) - header[block];
831 
832 		if (size <= 0)
833 			break;
834 
835 		size -= 38;
836 		Instrument_Amiga::Samples *s = &_instruments[program].samples[block];
837 		ims.seek(594 + offset + header[block], SEEK_SET);
838 		int8 *buf = new int8[size];
839 
840 		s->rate = ims.readUint16BE();
841 		s->baseNote = ims.readUint16BE();
842 		s->noteRangeMin = ims.readSint16BE();
843 		s->noteRangeMax = ims.readSint16BE();
844 		s->sustainLevel = ims.readSint16BE();
845 		s->type = ims.readUint16BE();
846 		ims.skip(8);
847 		s->numSamples = size;
848 		s->dr_offset = ims.readUint32BE();
849 		s->dr_numSamples = ims.readUint32BE();
850 		s->levelFadeDelayAT = ims.readSint16BE();
851 		s->levelFadeDelayRL = ims.readSint16BE();
852 		s->levelFadeTriggerRL = ims.readSint16BE();
853 		s->levelFadeDelayDC = ims.readSint16BE();
854 		ims.read(buf, size);
855 		s->data = buf;
856 		_instruments[program].numBlocks = block + 1;
857 	}
858 
859 	ims.close();
860 }
861 
unloadInstruments()862 void IMuseDriver_Amiga::unloadInstruments() {
863 	Common::StackLock lock(_mutex);
864 	for (int prg = 0; prg < 128; ++prg) {
865 		for (int block = 0; block < 8; ++block) {
866 			if (_instruments[prg].samples[block].data)
867 				delete[] _instruments[prg].samples[block].data;
868 		}
869 	}
870 	memset(_instruments, 0, sizeof(Instrument_Amiga) * 128);
871 }
872 
873 }
874