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